diff --git a/GainStation13/code/mechanics/fatrousal.dm b/GainStation13/code/mechanics/fatrousal.dm index c31b6054af..b2523ace24 100644 --- a/GainStation13/code/mechanics/fatrousal.dm +++ b/GainStation13/code/mechanics/fatrousal.dm @@ -20,7 +20,7 @@ /datum/quirk/fatrousal/proc/fat_hide(var/mob/living/carbon/user) if(iscarbon(quirk_holder)) var/mob/living/carbon/C = quirk_holder - return C.getArousalLoss()*35 + return C.getArousal()*35 return FALSE */ diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index b3b5ece36d..bd9cb34827 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -70,6 +70,11 @@ #define BELLY_SIZE_DEF 0 #define BELLY_SIZE_MAX 10 +//GS13 Port - Add back Arousal +#define AROUSAL_MINIMUM_DEFAULT 0 +#define AROUSAL_MAXIMUM_DEFAULT 100 +#define AROUSAL_START_VALUE 1 + //visibility toggles defines to avoid errors typos code errors. #define GEN_VISIBLE_ALWAYS "Always visible" #define GEN_VISIBLE_NO_CLOTHES "Hidden by clothes" diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm index 14a3b7dc49..4842a38716 100644 --- a/code/__DEFINES/hud.dm +++ b/code/__DEFINES/hud.dm @@ -98,6 +98,7 @@ #define ui_health "EAST-1:28,CENTER-1:15" #define ui_internal "EAST-1:28,CENTER+1:19"//CIT CHANGE - moves internal icon up a little bit to accommodate for the stamina meter #define ui_mood "EAST-1:28,CENTER-3:10" +#define ui_arousal "EAST-1:28,CENTER-4:8" // #define ui_spacesuit "EAST-1:28,CENTER-4:10" //Pop-up inventory diff --git a/code/__HELPERS/_cit_helpers.dm b/code/__HELPERS/_cit_helpers.dm index de006de90e..c885a5b996 100644 --- a/code/__HELPERS/_cit_helpers.dm +++ b/code/__HELPERS/_cit_helpers.dm @@ -144,6 +144,17 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE) if(I.body_parts_covered & GROIN) return FALSE return TRUE +//GS13 Port - Arousal +/mob/living/carbon/proc/is_butt_exposed(var/list/L) + if(!L) + L = get_equipped_items() + for(var/obj/item/I in L) + if(I.body_parts_covered & GROIN) + if(!I.do_not_cover_butt) + return FALSE + else + return TRUE + return TRUE /mob/living/carbon/proc/is_chest_exposed(list/L) if(!L) diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 53d69fe01e..61d99e29f3 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -88,6 +88,9 @@ GLOBAL_LIST_INIT(available_ui_styles, list( var/atom/movable/screen/healthdoll var/atom/movable/screen/internals + //GS13 Port - Add back Arousal + var/atom/movable/screen/arousal + var/atom/movable/screen/wanted/wanted_lvl // subtypes can override this to force a specific UI style var/ui_style @@ -144,6 +147,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( healthdoll = null wanted_lvl = null internals = null + arousal = null lingchemdisplay = null devilsouldisplay = null lingstingdisplay = null diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index 27989f3bb1..bea9e564f2 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -430,6 +430,12 @@ infodisplay += staminabuffer //END OF CIT CHANGES + //GS13 Port - adds arousal and stamina to hud + arousal = new /atom/movable/screen/arousal() + arousal.icon_state = (owner.canbearoused == 1 ? "arousal0" : "") + arousal.hud = src + infodisplay += arousal + healthdoll = new /atom/movable/screen/healthdoll() healthdoll.hud = src infodisplay += healthdoll diff --git a/code/datums/mind.dm b/code/datums/mind.dm index c05d04ede8..5c810bed2a 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -169,6 +169,8 @@ var/mob/living/L = new_character if(L.client?.prefs && L.client.prefs.auto_ooc && L.client.prefs.chat_toggles & CHAT_OOC) L.client.prefs.chat_toggles &= ~(CHAT_OOC) + L.canbearoused = L.client?.prefs?.arousable //Technically this should make taking over a character mean the body gain the new minds setting... + L.update_arousal_hud() //Removes the old icon hide_ckey = current.client?.prefs?.hide_ckey diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 0eaba60ba8..ae025b355a 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -94,6 +94,7 @@ var/datum/wires/wires = null var/icon/blood_splatter_icon + var/icon/cum_splatter_icon var/list/fingerprints var/list/fingerprintshidden var/list/blood_DNA diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index e437ac5c8b..9db3090d66 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -181,6 +181,9 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb /// Used if we want to have a custom verb text for throwing. "John Spaceman flicks the ciggerate" for example. var/throw_verb + //GS13 Port - Hyper, for clothes that reveal your behind! butt stuff, you know how it is. + var/do_not_cover_butt = FALSE + /obj/item/Initialize(mapload) if(attack_verb) diff --git a/code/modules/arousal/arousal.dm b/code/modules/arousal/arousal.dm index 4e0f37d529..298d9168c1 100644 --- a/code/modules/arousal/arousal.dm +++ b/code/modules/arousal/arousal.dm @@ -1,15 +1,36 @@ +//GS13 Port - Oh boy this has changed /mob/living + var/arousal = 0 //How aroused the mob is. + var/min_arousal = AROUSAL_MINIMUM_DEFAULT //The lowest this mobs arousal will get. default = 0 + var/max_arousal = AROUSAL_MAXIMUM_DEFAULT //The highest this mobs arousal will get. default = 100 + var/arousal_rate = AROUSAL_START_VALUE //The base rate that arousal will increase in this mob. + var/arousal_loss_rate = AROUSAL_START_VALUE //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 = 5 SECONDS //5 second cooldown for masturbating because fuck spam. var/mb_cd_timer = 0 //The timer itself /mob/living/carbon/human + canbearoused = TRUE + var/saved_underwear = ""//saves their underwear so it can be toggled later var/saved_undershirt = "" var/saved_socks = "" var/hidden_underwear = FALSE var/hidden_undershirt = FALSE var/hidden_socks = FALSE - var/arousal_rate = 1 + +/mob/living/carbon/human/New() + ..() + saved_underwear = underwear + saved_undershirt = undershirt + +//Species vars +/datum/species + var/arousal_gain_rate = AROUSAL_START_VALUE //Rate at which this species becomes aroused + var/arousal_lose_rate = AROUSAL_START_VALUE //Multiplier for how easily arousal can be relieved + var/list/cum_fluids = list(/datum/reagent/consumable/semen) + var/list/milk_fluids = list(/datum/reagent/consumable/milk) + var/list/femcum_fluids = list(/datum/reagent/consumable/semen/femcum) //Mob procs /mob/living/carbon/human/verb/underwear_toggle() @@ -40,6 +61,162 @@ update_body(TRUE) +/mob/living/proc/handle_arousal() + + +/mob/living/carbon/handle_arousal() + if(canbearoused && dna) + var/datum/species/S + S = dna.species + if(S) + if(!(SSmobs.times_fired % 36)) + if(getArousal() < max_arousal) + //if(S && !(SSmobs.times_fired % 36) && getArousal() < max_arousal)//Totally stolen from breathing code. Do this every 36 ticks. + adjustArousal(arousal_rate * S.arousal_gain_rate) + if(dna.features["exhibitionist"] && client) + var/amt_nude = 0 + if(is_chest_exposed() && (getorganslot("breasts"))) + amt_nude++ + if(is_groin_exposed()) + if(getorganslot("penis")) + amt_nude++ + if(getorganslot("vagina")) + amt_nude++ + if(is_butt_exposed()) + if(getorganslot("anus")) + amt_nude++ + if(amt_nude) + var/watchers = 0 + for(var/mob/_M in view(world.view, src)) + var/mob/living/M = _M + if(!istype(M)) + continue + if(M.client && !M.stat && !M.eye_blind && (locate(src) in viewers(world.view,M))) + watchers++ + if(watchers) + adjustArousal((amt_nude * watchers) + S.arousal_gain_rate) + +/mob/living/proc/getArousal() + return arousal + +/mob/living/proc/adjustArousal(amount, updating_arousal=1) + if(status_flags & GODMODE || !canbearoused) + return FALSE + arousal = clamp(arousal + amount, min_arousal, max_arousal) + if(updating_arousal) + updatearousal() + +/mob/living/proc/setArousal(amount, updating_arousal=1) + if(status_flags & GODMODE || !canbearoused) + return FALSE + arousal = clamp(amount, min_arousal, max_arousal) + if(updating_arousal) + updatearousal() + +/mob/living/proc/getPercentAroused() + var/percentage = ((100 / max_arousal) * arousal) + return percentage + +/mob/living/proc/isPercentAroused(percentage)//returns true if the mob's arousal (measured in a percent of 100) is greater than the arg percentage. + if(!isnum(percentage) || percentage > 100 || percentage < 0) + CRASH("Provided percentage is invalid") + if(getPercentAroused() >= percentage) + return TRUE + return FALSE + +//H U D// +/mob/living/proc/updatearousal() + update_arousal_hud() + +/mob/living/carbon/updatearousal() + . = ..() + + for(var/obj/item/organ/genital/G in internal_organs) + if(istype(G)) + var/datum/sprite_accessory/S + switch(G.type) + if(/obj/item/organ/genital/penis) + S = GLOB.cock_shapes_list[G.shape] + if(/obj/item/organ/genital/testicles) + S = GLOB.balls_shapes_list[G.shape] + if(/obj/item/organ/genital/vagina) + S = GLOB.vagina_shapes_list[G.shape] + if(/obj/item/organ/genital/breasts) + S = GLOB.breasts_shapes_list[G.shape] + if(S?.alt_aroused) + G.aroused_state = isPercentAroused(G.aroused_amount) + if(getArousal() >= ((max_arousal / 100) * 33)) + G.aroused_state = TRUE + else + G.aroused_state = FALSE + G.update_appearance() +/mob/living/proc/update_arousal_hud() + return FALSE + +/datum/species/proc/update_arousal_hud(mob/living/carbon/human/H) + return FALSE + +/mob/living/carbon/human/update_arousal_hud() + if(!client || !hud_used) + return FALSE + if(dna.species.update_arousal_hud()) + return FALSE + if(!canbearoused) + hud_used.arousal.icon_state = "" + return FALSE + else + if(hud_used.arousal) + if(stat == DEAD) + hud_used.arousal.icon_state = "arousal0" + return TRUE + if(getArousal() == max_arousal) + hud_used.arousal.icon_state = "arousal100" + return TRUE + if(getArousal() >= (max_arousal / 100) * 90)//M O D U L A R , W O W + hud_used.arousal.icon_state = "arousal90" + return TRUE + if(getArousal() >= (max_arousal / 100) * 80)//M O D U L A R , W O W + hud_used.arousal.icon_state = "arousal80" + return TRUE + if(getArousal() >= (max_arousal / 100) * 70)//M O D U L A R , W O W + hud_used.arousal.icon_state = "arousal70" + return TRUE + if(getArousal() >= (max_arousal / 100) * 60)//M O D U L A R , W O W + hud_used.arousal.icon_state = "arousal60" + return TRUE + if(getArousal() >= (max_arousal / 100) * 50)//M O D U L A R , W O W + hud_used.arousal.icon_state = "arousal50" + return TRUE + if(getArousal() >= (max_arousal / 100) * 40)//M O D U L A R , W O W + hud_used.arousal.icon_state = "arousal40" + return TRUE + if(getArousal() >= (max_arousal / 100) * 30)//M O D U L A R , W O W + hud_used.arousal.icon_state = "arousal30" + return TRUE + if(getArousal() >= (max_arousal / 100) * 20)//M O D U L A R , W O W + hud_used.arousal.icon_state = "arousal10" + return TRUE + if(getArousal() >= (max_arousal / 100) * 10)//M O D U L A R , W O W + hud_used.arousal.icon_state = "arousal10" + return TRUE + else + hud_used.arousal.icon_state = "arousal0" + +//GS13 Port - Arousal menu +/atom/movable/screen/arousal + name = "arousal" + icon_state = "arousal0" + icon = 'icons/obj/genitals/hud.dmi' + screen_loc = ui_arousal + +/atom/movable/screen/arousal/Click() + if(!isliving(usr)) + return FALSE + if(isobserver(usr)) + return + var/mob/living/M = usr + if(M.canbearoused) + ui_interact(usr) /mob/living/carbon/human/proc/adjust_arousal(strength, cause = "manual toggle", aphro = FALSE,maso = FALSE) // returns all genitals that were adjust var/list/obj/item/organ/genital/genit_list = list() @@ -63,207 +240,564 @@ if(!. && !silent) to_chat(H, "Your [name] is unable to produce it's own fluids, it's missing the organs for it.") -/mob/living/carbon/human/proc/do_climax(datum/reagents/R, atom/target, obj/item/organ/genital/G, spill = TRUE) - if(!G) - return - if(!target || !R) - return - var/turfing = isturf(target) - G.generate_fluid(R) - log_message("Climaxed using [G] with [target]", LOG_EMOTE) - if(spill && R.total_volume >= 5) - R.reaction(turfing ? target : target.loc, TOUCH, 1, 0) - if(!turfing) - R.trans_to(target, R.total_volume * (spill ? G.fluid_transfer_factor : 1), log = TRUE) - G.last_orgasmed = world.time - R.clear_reagents() +//GS13 Port +/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) + if(mb_cd_timer <= world.time) + //start the cooldown even if it fails + mb_cd_timer = world.time + mb_cd_length + if(getArousal() >= ((max_arousal / 100) * 33))//33% arousal or greater required + src.visible_message("[src] starts masturbating!", \ + "You start masturbating.") + if(do_after(src, 30, target = src)) + src.visible_message("[src] relieves [p_them()]self!", \ + "You have relieved yourself.") + SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + setArousal(min_arousal) + else + to_chat(src, "You aren't aroused enough for that.") -/mob/living/carbon/human/proc/mob_climax_outside(obj/item/organ/genital/G, mb_time = 30) //This is used for forced orgasms and other hands-free climaxes - var/datum/reagents/fluid_source = G.climaxable(src, TRUE) - if(!fluid_source) - to_chat(src,"Your [G.name] cannot cum.") - return - if(mb_time) //as long as it's not instant, give a warning - to_chat(src,"You feel yourself about to orgasm.") - if(!do_after(src, mb_time, target = src) || !G.climaxable(src, TRUE)) - return - to_chat(src,"You climax[isturf(loc) ? " onto [loc]" : ""] with your [G.name].") - do_climax(fluid_source, loc, G) -/mob/living/carbon/human/proc/mob_climax_partner(obj/item/organ/genital/G, mob/living/L, spillage = TRUE, mb_time = 30) //Used for climaxing with any living thing - var/datum/reagents/fluid_source = G.climaxable(src) - if(!fluid_source) - return - if(mb_time) //Skip warning if this is an instant climax. - to_chat(src,"You're about to climax with [L]!") - to_chat(L,"[src] is about to climax with you!") - if(!do_after(src, mb_time, target = src) || !in_range(src, L) || !G.climaxable(src, TRUE)) +//These are various procs that we'll use later, split up for readability instead of having one, huge proc. +//For all of these, we assume the arguments given are proper and have been checked beforehand. +/mob/living/carbon/human/proc/mob_masturbate(obj/item/organ/genital/G, mb_time = 30) //Masturbation, keep it gender-neutral + var/total_fluids = 0 + var/datum/reagents/fluid_source = null + + if(G.producing) //Can it produce its own fluids, such as breasts? + fluid_source = G.reagents + else + if(!G.linked_organ) + to_chat(src, "Your [G.name] is unable to produce it's own fluids, it's missing the organs for it.") return - if(spillage) - to_chat(src,"You orgasm with [L], spilling out of them, using your [G.name].") - to_chat(L,"[src] climaxes with you, overflowing and spilling, using [p_their()] [G.name]!") - else //knots and other non-spilling orgasms - to_chat(src,"You climax with [L], your [G.name] spilling nothing.") - to_chat(L,"[src] climaxes with you, [p_their()] [G.name] spilling nothing!") - SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) - do_climax(fluid_source, spillage ? loc : L, G, spillage) + fluid_source = G.linked_organ.reagents + total_fluids = fluid_source.total_volume + if(mb_time) + src.visible_message("[src] starts to [G.masturbation_verb] [p_their()] [G.name].", \ + "You start to [G.masturbation_verb] your [G.name].", \ + "You start to [G.masturbation_verb] your [G.name].") + + if(do_after(src, mb_time, target = src)) + if(total_fluids > 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.") + + + SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + if(G.can_climax) + setArousal(min_arousal) + + +/mob/living/carbon/human/proc/mob_climax_outside(obj/item/organ/genital/G, mb_time = 30, spillage = TRUE) //This is used for forced orgasms and other hands-free climaxes + var/total_fluids = 0 + var/datum/reagents/fluid_source = null + var/unable_to_come = FALSE + + if(G.producing) //Can it produce its own fluids, such as breasts? + fluid_source = G.reagents + total_fluids = fluid_source.total_volume + else + if(!G.linked_organ) + unable_to_come = TRUE + else + fluid_source = G.linked_organ.reagents + total_fluids = fluid_source.total_volume + + 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 + total_fluids = fluid_source.total_volume + if(mb_time) //as long as it's not instant, give a warning + 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(spillage) + if(total_fluids > 5) + fluid_source.reaction(src.loc, TOUCH, 1, 0) + + fluid_source.clear_reagents() + src.visible_message("[src] orgasms[istype(src.loc, /turf/open/floor) ? ", spilling onto [src.loc]" : ""], with [p_their()] [G.name]!", \ + "You climax[istype(src.loc, /turf/open/floor) ? ", spilling onto [src.loc]" : ""] with your [G.name].", \ + "You climax using your [G.name].") + else //Else from spillage check, also note subtle text change + src.visible_message("[src] orgasms with [p_their()] [G.name]!", \ + "You climax with your [G.name].", \ + "You climax using your [G.name].") + + SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + if(G.can_climax) + setArousal(min_arousal) + + +/mob/living/carbon/human/proc/mob_climax_partner(obj/item/organ/genital/G, mob/living/L, spillage = TRUE, impreg = FALSE,cover = FALSE,remote = FALSE, mb_time = 30) //Used for climaxing with any living thing + var/total_fluids = 0 + var/datum/reagents/fluid_source = null + + if(G.producing) //Can it produce its own fluids, such as breasts? + fluid_source = G.reagents + else + if(!G.linked_organ) + to_chat(src, "Your [G.name] is unable to produce it's own fluids, it's missing the organs for it.") + return + fluid_source = G.linked_organ.reagents + total_fluids = fluid_source.total_volume + + if(mb_time && !remote) //Skip warning if this is an instant climax. + src.visible_message("[src] is about to climax with [L]!", \ + "You're about to climax with [L]!", \ + "You're preparing to climax with something!") + if(remote) + src.visible_message("[src] is about to climax with someone!", \ + "You're about to climax with someone!", \ + "You're preparing to climax with something!") + + if(cover)//covering the partner in cum, this overrides other options. + if(do_after(src, mb_time, target = src) && in_range(src, L)) + fluid_source.trans_to(L, total_fluids*G.fluid_transfer_factor) + total_fluids -= total_fluids*G.fluid_transfer_factor + if(total_fluids > 80) // now thats a big cum! + if(isliving(L)) + var/mutable_appearance/cumoverlaylarge = mutable_appearance('hyperstation/icons/effects/cumoverlay.dmi') + cumoverlaylarge.icon_state = "cum_large" + L.add_overlay(cumoverlaylarge) + + if(total_fluids > 5) + fluid_source.reaction(L.loc, TOUCH, 1, 0) + var/mob/living/carbon/human/H = L + if(H) + H.cumdrip_rate += rand(5,10) + fluid_source.clear_reagents() + src.visible_message("[src] climaxes over [L], using [p_their()] [G.name]!", \ + "You orgasm over [L], using your [G.name].", \ + "You have climaxed over something, using your [G.name].") + SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + + if(isliving(L)) + var/mutable_appearance/cumoverlay = mutable_appearance('hyperstation/icons/effects/cumoverlay.dmi') + cumoverlay.icon_state = "cum_normal" + L.add_overlay(cumoverlay) + else + L.add_cum_overlay() + + setArousal(min_arousal) + if(G.can_climax) + setArousal(min_arousal) + + if(spillage && !cover) + if(do_after(src, mb_time, target = src)) + if(!in_range(src, L) && !remote) + return + fluid_source.trans_to(L, total_fluids*G.fluid_transfer_factor) + total_fluids -= total_fluids*G.fluid_transfer_factor + if(total_fluids > 5) + fluid_source.reaction(L.loc, TOUCH, 1, 0) + var/mob/living/carbon/human/H = L + if(H) + H.cumdrip_rate += rand(5,10) + fluid_source.clear_reagents() + src.visible_message("[src] climaxes with [L][spillage ? ", overflowing and spilling":""], using [p_their()] [G.name]!", \ + "You orgasm with [L][spillage ? ", spilling out of them":""], using your [G.name].", \ + "You have climaxed with someone[spillage ? ", spilling out of them":""], using your [G.name].") + SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + + if(G.can_climax) + setArousal(min_arousal) + + else //knots, portal fleshlights, and other non-spilling orgasms + if(!cover) + if(!remote && !in_range(src, L)) + return + if(do_after(src, mb_time, target = src)) + + if(!spillage) //hyper inflation + var/obj/item/organ/genital/belly/B = L.getorganslot("belly") + if(B) + if(B.inflatable && total_fluids > 80) //requires a big cumshot to expand. + if(B.size < 3) + B.size += 1 + to_chat(L, "You feel your belly expand.") + else + to_chat(L, "You feel your belly strain.") + + var/obj/item/organ/genital/penis/P = G + fluid_source.trans_to(L, total_fluids) + total_fluids = 0 + if(!remote) + src.visible_message("[src] climaxes with [L], [p_their()] [G.name] spilling nothing!", \ + "You ejaculate with [L], your [G.name] spilling nothing.", \ + "You have climaxed inside someone, your [G.name] spilling nothing.") + else + src.visible_message("[src] climaxes with someone, using [p_their()] [G.name]!", \ + "You ejaculate with someone, using your [G.name].", \ + "You have climaxed inside someone, using your [G.name].") + to_chat(L, "You feel someone ejaculate inside you.") + + SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + + if(G.can_climax) + setArousal(min_arousal) + + //Hyper - antag code + /*if(src.mind.special_role == ROLE_LEWD_TRAITOR) + for(var/datum/objective/obj in src.mind.objectives) + if (L.mind == obj.target) + L.mind.sexed = TRUE //sexed + to_chat(src, "You feel deep satisfaction with yourself.") + */ + //Hyper - impreg + // if(impreg) + // //Role them odds, only people with the dicks can send the chance to the person with the settings enabled at the momment. + // if(prob(L.impregchance)) + // var/obj/item/organ/genital/womb/W = L.getorganslot("womb") + // if(W) //check if they have a womb. + // if (L.breedable == 1 && W.pregnant == 0) //Dont get pregnant again, if you are pregnant. + // log_game("Debug: [L] has been impregnated by [src]") + // to_chat(L, "You feel your hormones change, and a motherly instinct take over.") //leting them know magic has happened. + // W.pregnant = 1 + // if (HAS_TRAIT(L, TRAIT_HEAT)) + // SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "heat", /datum/mood_event/heat) //well done you perv. + // REMOVE_TRAIT(L, TRAIT_HEAT, ROUNDSTART_TRAIT) //take the heat away, you satisfied it! + + // //Make breasts produce quicker. + // var/obj/item/organ/genital/breasts/B = L.getorganslot("breasts") + // if (B.fluid_mult < 0.5 && B) + // B.fluid_mult = 0.5 + /mob/living/carbon/human/proc/mob_fill_container(obj/item/organ/genital/G, obj/item/reagent_containers/container, mb_time = 30) //For beaker-filling, beware the bartender - var/datum/reagents/fluid_source = G.climaxable(src) - if(!fluid_source) - return - if(mb_time) - to_chat(src,"You start to [G.masturbation_verb] your [G.name] over [container].") - if(!do_after(src, mb_time, target = src) || !in_range(src, container) || !G.climaxable(src, TRUE)) - return - to_chat(src,"You used your [G.name] to fill [container].") - message_admins("[ADMIN_LOOKUPFLW(src)] used their [G.name] to fill [container].") - log_consent("[key_name(src)] used their [G.name] to fill [container].") - do_climax(fluid_source, container, G, FALSE) + var/total_fluids = 0 + var/datum/reagents/fluid_source = null -/mob/living/carbon/human/proc/pick_climax_genitals(silent = FALSE) - var/list/genitals_list + if(G.producing) //Can it produce its own fluids, such as breasts? + fluid_source = G.reagents + else + if(!G.linked_organ) + to_chat(src, "Your [G.name] is unable to produce it's own fluids, it's missing the organs for it.") + return + fluid_source = G.linked_organ.reagents + total_fluids = fluid_source.total_volume + + if(!container) //Something weird happened + to_chat(src, "You need a container to do this!") + return + + src.visible_message("[src] starts to [G.masturbation_verb] their [G.name] over [container].", \ + "You start to [G.masturbation_verb] your [G.name] over [container].", \ + "You start to [G.masturbation_verb] your [G.name] over something.") + if(do_after(src, mb_time, target = src) && in_range(src, container)) + fluid_source.trans_to(container, total_fluids) + src.visible_message("[src] uses [p_their()] [G.name] to fill [container]!", \ + "You used your [G.name] and fill [container] with a total of [total_fluids]u's.", \ + "You have relieved some pressure.") + SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + container.add_cum_overlay() //your aim is bad... + if(G.can_climax) + setArousal(min_arousal) + + +/mob/living/carbon/human/proc/pick_masturbate_genitals() + var/obj/item/organ/genital/ret_organ + var/list/genitals_list = list() var/list/worn_stuff = get_equipped_items() for(var/obj/item/organ/genital/G in internal_organs) - if((G.genital_flags & CAN_CLIMAX_WITH) && G.is_exposed(worn_stuff)) //filter out what you can't masturbate with - LAZYADD(genitals_list, G) - if(LAZYLEN(genitals_list)) - var/obj/item/organ/genital/ret_organ = input(src, "with what?", "Climax", null) as null|obj in genitals_list + if(G.genital_flags & CAN_MASTURBATE_WITH) //filter out what you can't masturbate with + if(G.is_exposed(worn_stuff)) //Nude or through_clothing + if(!G.dontlist) + genitals_list += G + if(genitals_list.len) + ret_organ = input(src, "with what?", "Masturbate", null) as null|obj in genitals_list return ret_organ - else if(!silent) - to_chat(src, "You cannot climax without available genitals.") + return null //error stuff -/mob/living/carbon/human/proc/pick_partner(silent = FALSE) +/mob/living/carbon/human/proc/target_genitals(mob/living/carbon/human/T) //used for targeting others + var/obj/item/organ/genital/ret_organ + var/list/genitals_list = list() + var/list/worn_stuff = get_equipped_items() + + for(var/obj/item/organ/genital/G in T.internal_organs) + if(G.is_exposed(worn_stuff)) //Nude or through_clothing + if(!G.dontlist) + genitals_list += G + if(genitals_list.len) + ret_organ = input(src, "", "Genitals", null) as null|obj in genitals_list + return ret_organ + return null //error stuff + +/mob/living/carbon/human/proc/pick_climax_genitals() + var/obj/item/organ/genital/ret_organ + var/list/genitals_list = list() + var/list/worn_stuff = get_equipped_items() + + for(var/obj/item/organ/genital/G in internal_organs) + if(G.can_climax) //filter out what you can't masturbate with + if(G.is_exposed(worn_stuff)) //Nude or through_clothing + if(!G.dontlist) + genitals_list += G + if(genitals_list.len) + ret_organ = input(src, "with what?", "Climax", null) as null|obj in genitals_list + return ret_organ + return null //error stuff + +/mob/living/carbon/human/proc/pick_partner_overide() //used for cumming on people without genitals exposed var/list/partners = list() - if(pulling) - partners += pulling - if(pulledby) - partners += pulledby + if(src.pulling) + partners += src.pulling //Yes, even objects for now + if(src.pulledby) + partners += src.pulledby //Now we got both of them, let's check if they're proper - for(var/mob/living/L in partners) - if(!L.client || !L.mind) // can't consent, not a partner - partners -= L - if(iscarbon(L)) - var/mob/living/carbon/C = L - if(!C.exposed_genitals.len && !C.is_groin_exposed() && !C.is_chest_exposed() && C.is_mouth_covered()) //Nothing through_clothing, no proper partner. - partners -= C + for(var/I in partners) + if(isliving(I)) + else + partners -= I //No fucking objects //NOW the list should only contain correct partners if(!partners.len) - if(!silent) - to_chat(src, "You cannot do this alone.") - return //No one left. - var/mob/living/target = input(src, "With whom?", "Sexual partner", null) as null|anything in partners //pick one, default to null - if(target && in_range(src, target)) - to_chat(src,"Waiting for consent...") - var/consenting = input(target, "Do you want [src] to climax with you?","Climax mechanics","No") in list("Yes","No") - if(consenting == "Yes") - return target - else - message_admins("[ADMIN_LOOKUPFLW(src)] tried to climax with [target], but [target] did not consent.") - log_consent("[key_name(src)] tried to climax with [target], but [target] did not consent.") + return null //No one left. + return input(src, "With whom?", "Sexual partner", null) in partners //pick one, default to null -/mob/living/carbon/human/proc/pick_climax_container(silent = FALSE) +/mob/living/carbon/human/proc/pick_partner() + var/list/partners = list() + if(src.pulling) + partners += src.pulling //Yes, even objects for now + if(src.pulledby) + partners += src.pulledby + //Now we got both of them, let's check if they're proper + for(var/I in partners) + if(isliving(I)) + if(iscarbon(I)) + var/mob/living/carbon/C = I + if(!C.exposed_genitals.len) //Nothing through_clothing + if(!C.is_groin_exposed()) //No pants undone + if(!C.is_chest_exposed()) //No chest exposed + partners -= I //Then not proper, remove them + else + partners -= I //No fucking objects + //NOW the list should only contain correct partners + if(!partners.len) + return null //No one left. + return input(src, "With whom?", "Sexual partner", null) in partners //pick one, default to null + +/mob/living/carbon/human/proc/pick_climax_container() + var/obj/item/reagent_containers/SC = null var/list/containers_list = list() - for(var/obj/item/reagent_containers/C in held_items) - if(C.is_open_container() || istype(C, /obj/item/reagent_containers/food/snacks)) - containers_list += C - for(var/obj/item/reagent_containers/C in range(1, src)) - if((C.is_open_container() || istype(C, /obj/item/reagent_containers/food/snacks)) && CanReach(C)) - containers_list += C + for(var/obj/item/reagent_containers/container in held_items) + if(container.is_open_container() || istype(container, /obj/item/reagent_containers/food/snacks)) + containers_list += container if(containers_list.len) - var/obj/item/reagent_containers/SC = input(src, "Into or onto what?(Cancel for nowhere)", null) as null|obj in containers_list - if(SC && CanReach(SC)) - return SC - else if(!silent) - to_chat(src, "You cannot do this without an appropriate container.") + SC = input(src, "Into or onto what?(Cancel for nowhere)", null) as null|obj in containers_list + if(SC) + if(in_range(src, SC)) + return SC + return null //If nothing correct, give null. -/mob/living/carbon/human/proc/available_rosie_palms(silent = FALSE, list/whitelist_typepaths = list(/obj/item/dildo)) - if(restrained(TRUE)) //TRUE ignores grabs - if(!silent) - to_chat(src, "You can't do that while restrained!") - return FALSE - if(!get_num_arms() || !get_empty_held_indexes()) - if(whitelist_typepaths) - if(!islist(whitelist_typepaths)) - whitelist_typepaths = list(whitelist_typepaths) - for(var/path in whitelist_typepaths) - if(is_holding_item_of_type(path)) - return TRUE - if(!silent) - to_chat(src, "You need at least one free arm.") - return FALSE - return TRUE //Here's the main proc itself -/mob/living/carbon/human/proc/mob_climax(forced_climax=FALSE,cause = "") //Forced is instead of the other proc, makes you cum if you have the tools for it, ignoring restraints - set waitfor = FALSE +/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) if(!forced_climax) //Don't spam the message to the victim if forced to come too fast to_chat(src, "You need to wait [DisplayTimeText((mb_cd_timer - world.time), TRUE)] before you can do that again!") return + mb_cd_timer = (world.time + mb_cd_length) - if(!client?.prefs.arousable || !has_dna()) - return - if(stat == DEAD) - if(!forced_climax) + + if(canbearoused && has_dna()) + if(stat==2) to_chat(src, "You can't do that while dead!") - return - if(forced_climax) //Something forced us to cum, this is not a masturbation thing and does not progress to the other checks - log_message("was forced to climax by [cause]",LOG_EMOTE) - for(var/obj/item/organ/genital/G in internal_organs) - if(!(G.genital_flags & CAN_CLIMAX_WITH)) //Skip things like wombs and testicles - continue - mob_climax_outside(G, mb_time = 0) //removed climax timer for sudden, forced orgasms - //Now all genitals that could climax, have. - //Since this was a forced climax, we do not need to continue with the other stuff - mb_cd_timer = world.time + mb_cd_length - return - //If we get here, then this is not a forced climax and we gotta check a few things. + return + 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/O in internal_organs) + if(istype(O, /obj/item/organ/genital)) + var/obj/item/organ/genital/G = O + if(!G.can_climax) //Skip things like wombs and testicles + continue + var/mob/living/partner + var/check_target + var/list/worn_stuff = get_equipped_items() - if(stat == UNCONSCIOUS) //No sleep-masturbation, you're unconscious. - to_chat(src, "You must be conscious to do that!") - return + if(G.is_exposed(worn_stuff)) + if(src.pulling) //Are we pulling someone? Priority target, we can't be making option menus for this, has to be quick + if(isliving(src.pulling)) //Don't fuck objects + check_target = src.pulling + if(src.pulledby && !check_target) //prioritise pulled over pulledby + if(isliving(src.pulledby)) + check_target = src.pulledby + //Now we should have a partner, or else we have to come alone + if(check_target) + if(iscarbon(check_target)) //carbons can have clothes + var/mob/living/carbon/C = check_target + if(C.exposed_genitals.len || C.is_groin_exposed() || C.is_chest_exposed()) //Are they naked enough? + partner = C + else //A cat is fine too + partner = check_target + if(partner) //Did they pass the clothing checks? + mob_climax_partner(G, partner, mb_time = 0) //Instant climax due to forced + continue //You've climaxed once with this organ, continue on + //not exposed OR if no partner was found while exposed, climax alone + mob_climax_outside(G, mb_time = 0) //removed climax timer for sudden, forced orgasms + //Now all genitals that could climax, have. + //Since this was a forced climax, we do not need to continue with the other stuff + return + //If we get here, then this is not a forced climax and we gotta check a few things. - //Ok, now we check what they want to do. - var/choice = input(src, "Select sexual activity", "Sexual activity:") as null|anything in list("Climax alone","Climax with partner", "Fill container") - if(!choice) - return + if(stat==1) //No sleep-masturbation, you're unconscious. + to_chat(src, "You must be conscious to do that!") + return + if(getArousal() < 33) //flat number instead of percentage + to_chat(src, "You aren't aroused enough for that!") + return - switch(choice) - if("Climax alone") - if(!available_rosie_palms()) - return - var/obj/item/organ/genital/picked_organ = pick_climax_genitals() - if(picked_organ && available_rosie_palms(TRUE)) - mob_climax_outside(picked_organ) - if("Climax with partner") - //We need no hands, we can be restrained and so on, so let's pick an organ - var/obj/item/organ/genital/picked_organ = pick_climax_genitals() - if(picked_organ) - var/mob/living/partner = pick_partner() //Get someone - if(partner) - var/spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as null|anything in list("Yes", "No") - if(spillage && in_range(src, partner)) - mob_climax_partner(picked_organ, partner, spillage == "Yes" ? TRUE : FALSE) - if("Fill container") - //We'll need hands and no restraints. - if(!available_rosie_palms(FALSE, /obj/item/reagent_containers)) - return - //We got hands, let's pick an organ - var/obj/item/organ/genital/picked_organ - picked_organ = pick_climax_genitals() //Gotta be climaxable, not just masturbation, to fill with fluids. - if(picked_organ) - //Good, got an organ, time to pick a container - var/obj/item/reagent_containers/fluid_container = pick_climax_container() - if(fluid_container && available_rosie_palms(TRUE, /obj/item/reagent_containers)) - mob_fill_container(picked_organ, fluid_container) - mb_cd_timer = world.time + mb_cd_length + //Ok, now we check what they want to do. + var/choice = input(src, "Select sexual activity", "Sexual activity:") in list("Masturbate", "Climax alone", "Climax with partner","Climax over partner", "Fill container") + + switch(choice) + + if("Masturbate") + if(restrained(TRUE)) //TRUE ignores grabs + to_chat(src, "You can't do that while restrained!") + return + var/free_hands = get_num_arms() + 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) + to_chat(src, "You're holding too many things.") + return + //We got hands, let's pick an organ + var/obj/item/organ/genital/picked_organ + picked_organ = pick_masturbate_genitals() + if(picked_organ) + mob_masturbate(picked_organ) + return + else //They either lack organs that can masturbate, or they didn't pick one. + to_chat(src, "You cannot masturbate without choosing genitals.") + return + + if("Climax alone") + if(restrained(TRUE)) //TRUE ignores grabs + to_chat(src, "You can't do that while restrained!") + return + var/free_hands = get_num_arms() + 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) + to_chat(src, "You're holding too many things.") + return + //We got hands, let's pick an organ + var/obj/item/organ/genital/picked_organ + picked_organ = pick_climax_genitals() + if(picked_organ) + mob_climax_outside(picked_organ) + return + else //They either lack organs that can masturbate, or they didn't pick one. + to_chat(src, "You cannot climax without choosing genitals.") + return + + if("Climax with partner") + //We need no hands, we can be restrained and so on, so let's pick an organ + var/obj/item/organ/genital/picked_organ + picked_organ = pick_climax_genitals() + if(picked_organ) + var/mob/living/partner = pick_partner() //Get someone + if(partner) + var/obj/item/organ/genital/penis/P = picked_organ + /*GS13 Port - De we need breeding? + if(partner.breedable == 1 && picked_organ.name == "penis") + var/impreg = input(src, "Would this action carry the risk of pregnancy?", "Choose a option", "Yes") as anything in list("Yes", "No") + if(impreg == "Yes") //If we are impregging + var/spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as anything in list("Yes", "No") + if(spillage == "Yes") + mob_climax_partner(picked_organ, partner, TRUE, TRUE, FALSE) + else + mob_climax_partner(picked_organ, partner, FALSE, TRUE, FALSE) + else + var/spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as anything in list("Yes", "No") + if(spillage == "Yes") + mob_climax_partner(picked_organ, partner, TRUE, FALSE, FALSE) + else + mob_climax_partner(picked_organ, partner, FALSE, FALSE, FALSE) //Wow, im trash at coding, I need to find a better way of coding this, ill rewrite it later.-quote + return + + else //If we arent impregging + var/spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as anything in list("Yes", "No") + if(spillage == "Yes") + mob_climax_partner(picked_organ, partner, TRUE, FALSE, FALSE) + else + mob_climax_partner(picked_organ, partner, FALSE, FALSE, FALSE) + return + */ + var/spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as anything in list("Yes", "No") + if(spillage == "Yes") + mob_climax_partner(picked_organ, partner, TRUE, FALSE, FALSE) + else + mob_climax_partner(picked_organ, partner, FALSE, FALSE, FALSE) + return + + else + to_chat(src, "You cannot do this alone.") + return + else //They either lack organs that can masturbate, or they didn't pick one. + to_chat(src, "You cannot climax without choosing genitals.") + return + if("Climax over partner") + var/obj/item/organ/genital/picked_organ + picked_organ = pick_climax_genitals() + if(picked_organ) + var/mob/living/partner = pick_partner_overide() //Get your partner, clothed or not. + if(partner) + mob_climax_partner(picked_organ, partner, FALSE, FALSE, TRUE) + else + to_chat(src, "You cannot do this alone.") + + if("Fill container") + //We'll need hands and no restraints. + if(restrained(TRUE)) //TRUE ignores grabs + to_chat(src, "You can't do that while restrained!") + return + var/free_hands = get_num_arms() + 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) + to_chat(src, "You're holding too many things.") + return + //We got hands, let's pick an organ + var/obj/item/organ/genital/picked_organ + picked_organ = pick_climax_genitals() //Gotta be climaxable, not just masturbation, to fill with fluids. + if(picked_organ) + //Good, got an organ, time to pick a container + var/obj/item/reagent_containers/fluid_container = pick_climax_container() + if(fluid_container) + mob_fill_container(picked_organ, fluid_container) + return + else + to_chat(src, "You cannot do this without anything to fill.") + return + else //They either lack organs that can climax, or they didn't pick one. + to_chat(src, "You cannot fill anything without choosing genitals.") + return + else //Somehow another option was taken, maybe something interrupted the selection or it was cancelled + return //Just end it in that case. -/mob/living/carbon/human/verb/climax_verb() - set category = "IC" - set name = "Climax" - set desc = "Lets you choose a couple ways to ejaculate." - mob_climax() diff --git a/code/modules/arousal/genitals.dm b/code/modules/arousal/genitals.dm index e4b9f4107c..bfd807d3b6 100644 --- a/code/modules/arousal/genitals.dm +++ b/code/modules/arousal/genitals.dm @@ -9,6 +9,7 @@ var/orgasm_verb = "cumming" //present continous var/arousal_verb = "You feel aroused" var/unarousal_verb = "You no longer feel aroused" + var/can_climax = FALSE var/fluid_transfer_factor = 0 //How much would a partner get in them if they climax using this? var/size = 2 //can vary between num or text, just used in icon_state strings var/datum/reagent/fluid_id = null @@ -16,11 +17,22 @@ var/fluid_efficiency = 1 var/fluid_rate = CUM_RATE var/fluid_mult = 1 + var/producing = FALSE var/last_orgasmed = 0 - var/aroused_state = FALSE //Boolean used in icon_state strings + var/aroused_state = FALSE //Boolean used in icon_state strings + var/aroused_amount = 50 //This is a num from 0 to 100 for arousal percentage for when to use arousal state icons. var/obj/item/organ/genital/linked_organ var/linked_organ_slot //used for linking an apparatus' organ to its other half on update_link(). var/layer_index = GENITAL_LAYER_INDEX //Order should be very important. FIRST vagina, THEN testicles, THEN penis, as this affects the order they are rendered in. + var/through_clothes = FALSE + var/internal = FALSE + var/hidden = FALSE + var/colourtint = "" + var/mode = "clothes" + var/obj/item/equipment //for fun stuff that goes on the gentials/maybe rings down the line + var/dontlist = FALSE + var/nochange = FALSE //stops people changing visablity. + /obj/item/organ/genital/Initialize(mapload, do_update = TRUE) . = ..() diff --git a/code/modules/arousal/organs/breasts.dm b/code/modules/arousal/organs/breasts.dm index d7a8c67adb..69020da4f3 100644 --- a/code/modules/arousal/organs/breasts.dm +++ b/code/modules/arousal/organs/breasts.dm @@ -11,9 +11,11 @@ size = BREASTS_SIZE_DEF // "c". Refer to the breast_values static list below for the cups associated number values fluid_id = /datum/reagent/consumable/milk fluid_rate = MILK_RATE + producing = TRUE shape = DEF_BREASTS_SHAPE genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_FUID_PRODUCTION|GENITAL_CAN_AROUSE|UPDATE_OWNER_APPEARANCE|GENITAL_UNDIES_HIDDEN masturbation_verb = "massage" + can_climax = TRUE arousal_verb = "Your breasts start feeling sensitive" unarousal_verb = "Your breasts no longer feel sensitive" orgasm_verb = "leaking" diff --git a/code/modules/arousal/organs/penis.dm b/code/modules/arousal/organs/penis.dm index e1025094c3..6aee84de3c 100644 --- a/code/modules/arousal/organs/penis.dm +++ b/code/modules/arousal/organs/penis.dm @@ -6,11 +6,13 @@ zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_PENIS masturbation_verb = "stroke" + can_climax = TRUE arousal_verb = "You pop a boner" unarousal_verb = "Your boner goes down" genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_CAN_AROUSE|UPDATE_OWNER_APPEARANCE|GENITAL_UNDIES_HIDDEN|GENITAL_CAN_TAUR linked_organ_slot = ORGAN_SLOT_TESTICLES fluid_transfer_factor = 0.5 + producing = TRUE shape = DEF_COCK_SHAPE size = 2 //arbitrary value derived from length and diameter for sprites. layer_index = PENIS_LAYER_INDEX diff --git a/code/modules/arousal/organs/testicles.dm b/code/modules/arousal/organs/testicles.dm index bfb5c99a55..57f16be9b8 100644 --- a/code/modules/arousal/organs/testicles.dm +++ b/code/modules/arousal/organs/testicles.dm @@ -14,6 +14,7 @@ shape = DEF_BALLS_SHAPE fluid_id = /datum/reagent/consumable/semen masturbation_verb = "massage" + can_climax = TRUE layer_index = TESTICLES_LAYER_INDEX /obj/item/organ/genital/testicles/generate_fluid() diff --git a/code/modules/arousal/organs/vagina.dm b/code/modules/arousal/organs/vagina.dm index 5c8bbeea98..aaeb0fdf99 100644 --- a/code/modules/arousal/organs/vagina.dm +++ b/code/modules/arousal/organs/vagina.dm @@ -9,6 +9,7 @@ shape = DEF_VAGINA_SHAPE genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_CAN_AROUSE|GENITAL_UNDIES_HIDDEN masturbation_verb = "finger" + can_climax = TRUE arousal_verb = "You feel wetness on your crotch" unarousal_verb = "You no longer feel wet" fluid_transfer_factor = 0.1 //Yes, some amount is exposed to you, go get your AIDS diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index 6723d2d4a6..5a9d3971cb 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -66,6 +66,9 @@ var/blood_state = BLOOD_STATE_NOT_BLOODY var/list/blood_smear = list(BLOOD_STATE_BLOOD = 0, BLOOD_STATE_OIL = 0, BLOOD_STATE_NOT_BLOODY = 0) + //GS13 Port - Arousal + var/cumdrip_rate = 0 //how long are we dripping jizz for? + var/name_override //For temporary visible name changes var/genital_override = FALSE //Force genitals on things incase of chems diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 9b8daf0384..a209aca017 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -546,6 +546,13 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) SEND_SIGNAL(C, COMSIG_SPECIES_GAIN, src, old_species) + //GS13 Port - Add back arousal + if(NOAROUSAL in species_traits) + C.canbearoused = FALSE + else + if(C.client) + C.canbearoused = C.client?.prefs?.arousable + /datum/species/proc/update_species_slowdown(mob/living/carbon/human/H) H.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/species, TRUE, multiplicative_slowdown = speedmod) diff --git a/hyperstation/code/modules/arousal/arousalhud.dm b/hyperstation/code/modules/arousal/arousalhud.dm index c881d29cba..5f079e9213 100644 --- a/hyperstation/code/modules/arousal/arousalhud.dm +++ b/hyperstation/code/modules/arousal/arousalhud.dm @@ -3,7 +3,7 @@ //if you wanna use this on your own server go ahead, but alittle credit would always be nice! -quotefox //This still uses alot of cits arousal system! -/obj/screen/arousal/ui_interact(mob/user) +/atom/movable/screen/arousal/ui_interact(mob/user) . = ..() var/dat = {"Genitals

"} @@ -65,22 +65,13 @@ dat += "Climax with [user.pulling]" dat += {"(Orgasm with another person.)
"} - var/mob/living/carbon/human/H = user.pulling - if(H.breedable && P && H) - dat += "Impregnate [U.pulling] ([clamp(U.impregchance,0,100)]%)" - dat += "(Climax inside another person, and attempt to knock them up.)
" else dat += "Climax over" dat += "(Requires a partner)
" dat += "Climax with" dat += "(Requires a partner)
" - //old code needs to be cleaned - if(P) - if(P.condom == 1) - dat += "Remove condom (penis)
" - if(P.sounding == 1) - dat += "Remove sounding rod (penis)
" + for(var/obj/item/organ/genital/G in U.internal_organs) if(G.equipment) //they have equipment dat += "Remove [G.equipment.name] ([G.name])
" @@ -94,7 +85,6 @@ var/datum/browser/popup = new(user, "arousal", "Arousal Panel") popup.set_content(dat) - popup.set_title_image(user.browse_rsc_icon(icon, icon_state), 500,600) popup.open() @@ -102,7 +92,7 @@ -/obj/screen/arousal/Topic(href, href_list) +/atom/movable/screen/arousal/Topic(href, href_list) . = ..() //Sanity checks. if(..()) return @@ -150,7 +140,7 @@ T.toggle_visibility(picked_visibility) if(href_list["masturbate"]) - if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal. + if (H.arousal >= (H.max_arousal / 100) * 33) //requires 33% arousal. H.solomasturbate() return else @@ -158,7 +148,7 @@ return if(href_list["container"]) - if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal. + if (H.arousal >= (H.max_arousal / 100) * 33) //requires 33% arousal. H.cumcontainer() return else @@ -166,7 +156,7 @@ return if(href_list["clothesplosion"]) - if (H.arousalloss >= (H.max_arousal / 100) * 33) //Requires 33% arousal. + if (H.arousal >= (H.max_arousal / 100) * 33) //Requires 33% arousal. H.clothesplosion() return else @@ -174,7 +164,7 @@ return if(href_list["climax"]) - if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal. + if (H.arousal >= (H.max_arousal / 100) * 33) //requires 33% arousal. H.climaxalone(FALSE) return else @@ -182,7 +172,7 @@ return if(href_list["climaxover"]) - if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal. + if (H.arousal >= (H.max_arousal / 100) * 33) //requires 33% arousal. H.climaxover(usr.pulling) return else @@ -190,7 +180,7 @@ return if(href_list["climaxwith"]) - if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal. + if (H.arousal >= (H.max_arousal / 100) * 33) //requires 33% arousal. H.climaxwith(usr.pulling) return else @@ -198,7 +188,7 @@ return if(href_list["impreg"]) - if (H.arousalloss >= (H.max_arousal / 100) * 33) //requires 33% arousal. + if (H.arousal >= (H.max_arousal / 100) * 33) //requires 33% arousal. H.impregwith(usr.pulling) return else @@ -248,13 +238,6 @@ else to_chat(usr, "Your belly is already at the maximum size! ") - - if(href_list["removecondom"]) - H.menuremovecondom() - - if(href_list["removesound"]) - H.menuremovesounding() - if(href_list["removeequipmentpenis"]) var/obj/item/organ/genital/penis/O = usr.getorganslot("penis") var/obj/item/I = O.equipment @@ -302,7 +285,7 @@ src.ui_interact(usr) -obj/screen/arousal/proc/kiss() +/atom/movable/screen/arousal/proc/kiss() if(usr.restrained(TRUE)) to_chat(usr, "You can't do that while restrained!") return @@ -310,7 +293,7 @@ obj/screen/arousal/proc/kiss() if (H) H.kisstarget(H.pulling) -obj/screen/arousal/proc/feed() +/atom/movable/screen/arousal/proc/feed() if(usr.restrained(TRUE)) to_chat(usr, "You can't do that while restrained!") return @@ -318,7 +301,7 @@ obj/screen/arousal/proc/feed() if (H) H.genitalfeed(H.pulling) -obj/screen/arousal/proc/feedfrom() +/atom/movable/screen/arousal/proc/feedfrom() if(usr.restrained(TRUE)) to_chat(usr, "You can't do that while restrained!") return @@ -326,7 +309,7 @@ obj/screen/arousal/proc/feedfrom() if (H) H.genitalfeedfrom(H.pulling) -obj/screen/arousal/proc/feedyourself() +/atom/movable/screen/arousal/proc/feedyourself() if(usr.restrained(TRUE)) to_chat(usr, "You can't do that while restrained!") return @@ -334,47 +317,6 @@ obj/screen/arousal/proc/feedyourself() if (H) H.genitalfeedyourself() - -/mob/living/carbon/human/proc/menuremovecondom() - - if(restrained(TRUE)) - to_chat(src, "You can't do that while restrained!") - return - var/free_hands = get_num_arms() - if(!free_hands) - to_chat(src, "You need at least one free arm.") - return - var/obj/item/organ/genital/penis/P = getorganslot("penis") - if(!P.condom) - to_chat(src, "You don't have a condom on!") - return - if(P.condom) - to_chat(src, "You tug the condom off the end of your penis!") - removecondom() - src.ui_interact(usr) //reopen dialog - return - return - -/mob/living/carbon/human/proc/menuremovesounding() - - if(restrained(TRUE)) - to_chat(src, "You can't do that while restrained!") - return - var/free_hands = get_num_arms() - if(!free_hands) - to_chat(src, "You need at least one free arm.") - return - var/obj/item/organ/genital/penis/P = getorganslot("penis") - if(!P.sounding) - to_chat(src, "You don't have a rod inside!") - return - if(P.sounding) - to_chat(src, "You pull the rod off from the tip of your penis!") - removesounding() - src.ui_interact(usr) //reopen dialog - return - return - /mob/living/carbon/human/proc/solomasturbate() if(restrained(TRUE)) to_chat(src, "You can't do that while restrained!") @@ -439,8 +381,7 @@ obj/screen/arousal/proc/feedyourself() src << browse(null, "window=arousal") //alls fine, we can close the window now. var/obj/item/organ/genital/penis/P = picked_organ var/spillage = "No" //default to no, just incase player has items on to prevent climax - if(!P.condom == 1&&!P.sounding == 1) //you cant climax with a condom on or sounding in. - spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as anything in list("Yes", "No") + spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as anything in list("Yes", "No") if(spillage == "Yes") mob_climax_partner(picked_organ, partner, TRUE, FALSE, FALSE) else @@ -464,12 +405,6 @@ obj/screen/arousal/proc/feedyourself() var/mob/living/partner = L if(partner) var/obj/item/organ/genital/penis/P = picked_organ - if(P.condom == 1) - to_chat(src, "You cannot do this action with a condom on.") - return - if(P.sounding == 1) - to_chat(src, "You cannot do this action with a sounding in.") - return mob_climax_partner(picked_organ, partner, FALSE, FALSE, TRUE) else to_chat(src, "You cannot do this alone.") @@ -494,6 +429,7 @@ obj/screen/arousal/proc/feedyourself() /mob/living/carbon/human/proc/impregwith(mob/living/T) + /*GS13 Port - Do we even do breeding in legacy? var/mob/living/carbon/human/L = pick_partner() var/obj/item/organ/genital/picked_organ picked_organ = src.getorganslot("penis") //Impregnation must be done with a penis. @@ -504,13 +440,6 @@ obj/screen/arousal/proc/feedyourself() to_chat(src, "Your partner cannot be impregnated.")//some fuckary happening, you shouldnt even get to this point tbh. return var/obj/item/organ/genital/penis/P = picked_organ - //you cant impreg with a condom on or sounding in. - if(P.condom == 1) - to_chat(src, "You cannot do this action with a condom on.") - return - if(P.sounding == 1) - to_chat(src, "You cannot do this action with a sounding in.") - return src << browse(null, "window=arousal") //alls fine, we can close the window now. //Keeping this for messy fun var/spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as anything in list("Yes", "No") @@ -524,6 +453,8 @@ obj/screen/arousal/proc/feedyourself() else //no penis :( to_chat(src, "You cannot impregnate without a penis.") return + */ + return /mob/living/carbon/human/proc/cumcontainer(mob/living/T) //We'll need hands and no restraints. @@ -580,14 +511,6 @@ obj/screen/arousal/proc/feedyourself() picked_organ = pick_climax_genitals() //Gotta be climaxable, not just masturbation, to fill with fluids. if(picked_organ) //Good, got an organ, time to pick a container - if(picked_organ.name == "penis")//if the select organ is a penis - var/obj/item/organ/genital/penis/P = src.getorganslot("penis") - if(P.condom) //if the penis is condomed - to_chat(src, "You cannot feed someone when there is a condom over your [picked_organ.name].") - return - if(P.sounding) //if the penis is sounded - to_chat(src, "You cannot feed someone when there is a rod inside your [picked_organ.name].") - return if(picked_organ.producing) //Can it produce its own fluids, such as breasts? fluid_source = picked_organ.reagents else @@ -605,7 +528,7 @@ obj/screen/arousal/proc/feedyourself() "You used your [picked_organ.name] to feed [L.name] a total of [total_fluids]u's.") SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) if(picked_organ.can_climax) - setArousalLoss(min_arousal) + setArousal(min_arousal) else //They either lack organs that can climax, or they didn't pick one. to_chat(src, "You cannot fill anything without choosing exposed genitals.") @@ -633,14 +556,6 @@ obj/screen/arousal/proc/feedyourself() if(picked_organ) //Good, got an organ, time to pick a container - if(picked_organ.name == "penis")//if the select organ is a penis - var/obj/item/organ/genital/penis/P = L.getorganslot("penis") - if(P.condom) //if the penis is condomed - to_chat(src, "You cannot feed from [picked_organ.name] when there is a condom over it.") - return - if(P.sounding) //if the penis is sounded - to_chat(src, "You cannot feed from [picked_organ.name] when there is a rod inside it.") - return if(picked_organ.producing) //Can it produce its own fluids, such as breasts? fluid_source = picked_organ.reagents else @@ -658,7 +573,7 @@ obj/screen/arousal/proc/feedyourself() "You used [L.name]'s [picked_organ.name] to feed with a total of [total_fluids]u's.") SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) if(picked_organ.can_climax) - L.setArousalLoss(min_arousal) + L.setArousal(min_arousal) else //They either lack organs that can climax, or they didn't pick one. to_chat(src, "You cannot fill anything without choosing exposed genitals.") @@ -672,14 +587,6 @@ obj/screen/arousal/proc/feedyourself() picked_organ = pick_climax_genitals() //Gotta be climaxable, not just masturbation, to fill with fluids. if(picked_organ) //Good, got an organ, time to pick a container - if(picked_organ.name == "penis")//if the select organ is a penis - var/obj/item/organ/genital/penis/P = src.getorganslot("penis") - if(P.condom) //if the penis is condomed - to_chat(src, "You cannot feed yourself when there is a condom over your [picked_organ.name].") - return - if(P.sounding) //if the penis is sounded - to_chat(src, "You cannot feed yourself when there is a rod inside your [picked_organ.name].") - return if(picked_organ.producing) //Can it produce its own fluids, such as breasts? fluid_source = picked_organ.reagents else @@ -697,7 +604,7 @@ obj/screen/arousal/proc/feedyourself() "You used your [picked_organ.name] to feed yourself a total of [total_fluids]u's.") SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) if(picked_organ.can_climax) - setArousalLoss(min_arousal) + setArousal(min_arousal) else //They either lack organs that can climax, or they didn't pick one. to_chat(src, "You cannot fill anything without choosing exposed genitals.") diff --git a/hyperstation/code/modules/resize/resizing.dm b/hyperstation/code/modules/resize/resizing.dm index 3d6a7859aa..20c2d834d6 100644 --- a/hyperstation/code/modules/resize/resizing.dm +++ b/hyperstation/code/modules/resize/resizing.dm @@ -214,12 +214,12 @@ /* if(HAS_TRAIT(src, TRAIT_MICROPHILE)) src.adjust_arousal(8) - if (src.getArousalLoss() >= 100 && ishuman(tmob) && tmob.has_dna()) + if (src.getArousal() >= 100 && ishuman(tmob) && tmob.has_dna()) src.mob_climax(forced_climax=TRUE) if(HAS_TRAIT(tmob, TRAIT_MACROPHILE)) tmob.adjust_arousal(10) - if (tmob.getArousalLoss() >= 100 && ishuman(tmob) && tmob.has_dna()) + if (tmob.getArousal() >= 100 && ishuman(tmob) && tmob.has_dna()) tmob.mob_climax(forced_climax=TRUE) return TRUE @@ -244,12 +244,12 @@ /* if(HAS_TRAIT(src, TRAIT_MICROPHILE)) src.adjust_arousal((get_effective_size()/tmob.get_effective_size()*3)) - if (src.getArousalLoss() >= 100 && ishuman(tmob) && tmob.has_dna()) + if (src.getArousal() >= 100 && ishuman(tmob) && tmob.has_dna()) src.mob_climax(forced_climax=TRUE) if(HAS_TRAIT(tmob, TRAIT_MACROPHILE)) tmob.adjust_arousal((get_effective_size()/tmob.get_effective_size()*3)) - if (tmob.getArousalLoss() >= 100 && ishuman(tmob) && tmob.has_dna()) + if (tmob.getArousal() >= 100 && ishuman(tmob) && tmob.has_dna()) tmob.mob_climax(forced_climax=TRUE) commenting out for now */ diff --git a/hyperstation/code/obj/condom.dm b/hyperstation/code/obj/condom.dm index 663f5beac5..cf30e23be2 100644 --- a/hyperstation/code/obj/condom.dm +++ b/hyperstation/code/obj/condom.dm @@ -125,4 +125,4 @@ obj/item/condom/update_icon() C.update_icon() to_chat(src, "The condom bubbles outwards and fills with your cum.") SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) - setArousalLoss(0) + setArousal(0) diff --git a/hyperstation/code/obj/fleshlight.dm b/hyperstation/code/obj/fleshlight.dm index 413267713e..37e4574d58 100644 --- a/hyperstation/code/obj/fleshlight.dm +++ b/hyperstation/code/obj/fleshlight.dm @@ -11,7 +11,7 @@ item_state = "fleshlight" w_class = WEIGHT_CLASS_SMALL var/sleevecolor = "#ffcbd4" //pink - price = 8 + custom_price = PRICE_CHEAP var/mutable_appearance/sleeve var/inuse = 0 @@ -62,8 +62,8 @@ C.emote("moan") C.do_jitter_animation() - C.adjust_arousal(20) //make the target more aroused. - if (C.getArousalLoss() >= 100 && ishuman(C) && C.has_dna()) + C.adjustArousal(20) //make the target more aroused. + if (C.getArousal() >= 100 && ishuman(C) && C.has_dna()) C.mob_climax(forced_climax=TRUE) //make them cum if they are over the edge. return @@ -88,7 +88,7 @@ var/partnercolor = "#ffcbd4" var/partnerbase = "normal" var/partnerorgan = "portal_vag" - price = 20 + custom_price = PRICE_EXPENSIVE var/mutable_appearance/sleeve var/mutable_appearance/organ var/inuse = 0 @@ -161,26 +161,24 @@ C.emote("moan") if(prob(30)) //30% chance to make your partner moan. M.emote("moan") - C.adjust_arousal(20) - M.adjust_arousal(20) + C.adjustArousal(20) + M.adjustArousal(20) M.do_jitter_animation() //make your partner shake too! - if (M.getArousalLoss() >= 100 && ishuman(M) && prob(5))//Why not have a probability to cum when someone's getting nailed with max arousal?~ + if (M.getArousal() >= 100 && ishuman(M) && prob(5))//Why not have a probability to cum when someone's getting nailed with max arousal?~ if(G.is_exposed()) //Oh yea, if vagina is not exposed, the climax will not cause a spill M.mob_climax_outside(G, spillage = TRUE) else M.mob_climax_outside(G, spillage = FALSE) - if (C.getArousalLoss() >= 100 && ishuman(C) && C.has_dna()) + if (C.getArousal() >= 100 && ishuman(C) && C.has_dna()) var/mob/living/carbon/human/O = C - if( (P.condom == 1) || (P.sounding == 1)) //If coundomed and/or sounded, do not fire impreg chance + //Else, fire impreg chance + if(G.name == "vagina") //no more spontaneous impregnations through the butt! + O.mob_climax_partner(P, M, FALSE, TRUE, FALSE, TRUE) + else O.mob_climax_partner(P, M, FALSE, FALSE, FALSE, TRUE) - else //Else, fire impreg chance - if(G.name == "vagina") //no more spontaneous impregnations through the butt! - O.mob_climax_partner(P, M, FALSE, TRUE, FALSE, TRUE) - else - O.mob_climax_partner(P, M, FALSE, FALSE, FALSE, TRUE) if(option == "Lick") to_chat(M, "You feel a tongue lick you through the portal against your [G.name].") @@ -317,7 +315,7 @@ icon = 'hyperstation/icons/obj/fleshlight.dmi' desc = "A small silver box with Silver Love Co embossed." icon_state = "box" - price = 15 + custom_price = PRICE_NORMAL // portal fleshlight box /obj/item/storage/box/portallight/PopulateContents() @@ -372,7 +370,7 @@ // C.do_jitter_animation() // C.adjust_arousal(20) //make the target more aroused. -// if (C.getArousalLoss() >= 100 && ishuman(C) && C.has_dna()) +// if (C.getArousal() >= 100 && ishuman(C) && C.has_dna()) // C.mob_climax(forced_climax=TRUE) //make them cum if they are over the edge. // return diff --git a/hyperstation/code/obj/vibrator.dm b/hyperstation/code/obj/vibrator.dm index 91aeeb47e4..5f6b7d5fd5 100644 --- a/hyperstation/code/obj/vibrator.dm +++ b/hyperstation/code/obj/vibrator.dm @@ -132,13 +132,13 @@ Code: if(2) //med, can make you cum to_chat(U, "You feel intense pleasure surge through your [G.name]") U.do_jitter_animation() - if (U.getArousalLoss() >= 100 && ishuman(U) && U.has_dna()) + if (U.getArousal() >= 100 && ishuman(U) && U.has_dna()) U.mob_climax(forced_climax=TRUE) if(3) //high, makes you stun to_chat(U, "You feel overpowering pleasure surge through your [G.name]") U.Jitter(3) U.Stun(30) - if (U.getArousalLoss() >= 100 && ishuman(U) && U.has_dna()) + if (U.getArousal() >= 100 && ishuman(U) && U.has_dna()) U.mob_climax(forced_climax=TRUE) if(prob(50)) U.emote("moan") diff --git a/modular_citadel/code/modules/mob/living/carbon/human/life.dm b/modular_citadel/code/modules/mob/living/carbon/human/life.dm new file mode 100644 index 0000000000..ff7cc569a7 --- /dev/null +++ b/modular_citadel/code/modules/mob/living/carbon/human/life.dm @@ -0,0 +1,6 @@ +//GS13 Port - arousal +/mob/living/carbon/human/Life() + //citadel code + if(stat != DEAD) + handle_arousal() + . = ..() diff --git a/sound/lewd/champ_fingering.ogg b/sound/lewd/champ_fingering.ogg new file mode 100644 index 0000000000..7e540c9703 Binary files /dev/null and b/sound/lewd/champ_fingering.ogg differ diff --git a/sound/lewd/latex.ogg b/sound/lewd/latex.ogg new file mode 100644 index 0000000000..d9a602244e Binary files /dev/null and b/sound/lewd/latex.ogg differ diff --git a/sound/lewd/slaps.ogg b/sound/lewd/slaps.ogg new file mode 100644 index 0000000000..78cf4ecaae Binary files /dev/null and b/sound/lewd/slaps.ogg differ diff --git a/sound/lewd/vibrate.ogg b/sound/lewd/vibrate.ogg new file mode 100644 index 0000000000..87eb1a4a1d Binary files /dev/null and b/sound/lewd/vibrate.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 217a2b2daa..6b7e5de851 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4053,6 +4053,7 @@ #include "GainStation13\icons\obj\vairous_weapons.dm" #include "GainStation13\icons\obj\structure\beds.dm" #include "GainStation13\icons\obj\structure\flora.dm" +#include "hyperstation\code\datums\mood_events\events.dm" #include "hyperstation\code\game\objects\railings.dm" #include "hyperstation\code\game\objects\structures\bench.dm" #include "hyperstation\code\game\objects\structures\sauna_oven.dm" @@ -4066,9 +4067,11 @@ #include "hyperstation\code\modules\resize\sizechems.dm" #include "hyperstation\code\modules\resize\sizegun.dm" #include "hyperstation\code\modules\surgery\organs\augments_arms.dm" +#include "hyperstation\code\modules\arousal\arousalhud.dm" #include "hyperstation\code\obj\ashtray.dm" #include "hyperstation\code\obj\decal.dm" #include "hyperstation\code\obj\kinkyclothes.dm" +#include "hyperstation\code\obj\fleshlight.dm" #include "hyperstation\code\obj\sizeitems.dm" #include "hyperstation\code\obj\stargate_clothing.dm" #include "hyperstation\code\obj\ZaoCorp\hat.dm" @@ -4148,6 +4151,7 @@ #include "modular_citadel\code\modules\mob\living\carbon\reindex_screams.dm" #include "modular_citadel\code\modules\mob\living\carbon\human\human.dm" #include "modular_citadel\code\modules\mob\living\carbon\human\human_defense.dm" +#include "modular_citadel\code\modules\mob\living\carbon\human\life.dm" #include "modular_citadel\code\modules\projectiles\ammunition\caseless.dm" #include "modular_citadel\code\modules\projectiles\ammunition\ballistic\smg\smg.dm" #include "modular_citadel\code\modules\projectiles\boxes_magazines\ammo_boxes.dm"