//Mob vars /mob/living var/arousalloss = 0 //How aroused the mob is. var/min_arousal = 0 //The lowest this mobs arousal will get. default = 0 var/max_arousal = 100 //The highest this mobs arousal will get. default = 100 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_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 = "" /mob/living/carbon/human/New() ..() saved_underwear = underwear saved_undershirt = undershirt //Species vars /datum/species var/arousal_gain_rate = 1 //Rate at which this species becomes aroused var/arousal_lose_rate = 1 //Multiplier for how easily arousal can be relieved var/list/cum_fluids = list("semen") var/list/milk_fluids = list("milk") var/list/femcum_fluids = list("femcum") //Mob procs /mob/living/proc/handle_arousal() /mob/living/carbon/handle_arousal() if(canbearoused && dna) var/datum/species/S S = dna.species if(S && SSmobs.times_fired%36==2 && getArousalLoss() < max_arousal)//Totally stolen from breathing code. Do this every 36 ticks. adjustArousalLoss(arousal_rate * S.arousal_gain_rate) if(dna.features["exhibitionist"]) var/amt_nude = 0 if(is_chest_exposed() && (gender == FEMALE || getorganslot("breasts"))) amt_nude++ if(is_groin_exposed()) if(getorganslot("penis")) amt_nude++ if(getorganslot("vagina")) amt_nude++ var/mob/living/M var/watchers = 0 for(M in view(world.view, src)) if(M.client && !M.stat && !M.eye_blind && (locate(src) in viewers(world.view,M))) watchers++ if(watchers && amt_nude) adjustArousalLoss((amt_nude * watchers) + S.arousal_gain_rate) /mob/living/proc/getArousalLoss() return arousalloss /mob/living/proc/adjustArousalLoss(amount, updating_arousal=1) if(status_flags & GODMODE || !canbearoused) return 0 arousalloss = Clamp(arousalloss + amount, min_arousal, max_arousal) if(updating_arousal) updatearousal() /mob/living/proc/setArousalLoss(amount, updating_arousal=1) if(status_flags & GODMODE || !canbearoused) return 0 arousalloss = Clamp(amount, min_arousal, max_arousal) if(updating_arousal) updatearousal() /mob/living/proc/getPercentAroused() return ((100 / max_arousal) * arousalloss) /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/proc/update_arousal_hud() return 0 /datum/species/proc/update_arousal_hud(mob/living/carbon/human/H) return 0 /mob/living/carbon/human/update_arousal_hud() if(!client || !hud_used) return 0 if(dna.species.update_arousal_hud()) return 0 if(!canbearoused) hud_used.arousal.icon_state = "arousal0" return 0 else if(hud_used.arousal) if(stat == DEAD) hud_used.arousal.icon_state = "arousal0" return 1 if(getArousalLoss() == max_arousal) hud_used.arousal.icon_state = "arousal100" return 1 if(getArousalLoss() >= (max_arousal / 100) * 90)//M O D U L A R , W O W hud_used.arousal.icon_state = "arousal90" return 1 if(getArousalLoss() >= (max_arousal / 100) * 80)//M O D U L A R , W O W hud_used.arousal.icon_state = "arousal80" return 1 if(getArousalLoss() >= (max_arousal / 100) * 70)//M O D U L A R , W O W hud_used.arousal.icon_state = "arousal70" return 1 if(getArousalLoss() >= (max_arousal / 100) * 60)//M O D U L A R , W O W hud_used.arousal.icon_state = "arousal60" return 1 if(getArousalLoss() >= (max_arousal / 100) * 50)//M O D U L A R , W O W hud_used.arousal.icon_state = "arousal50" return 1 if(getArousalLoss() >= (max_arousal / 100) * 40)//M O D U L A R , W O W hud_used.arousal.icon_state = "arousal40" return 1 if(getArousalLoss() >= (max_arousal / 100) * 30)//M O D U L A R , W O W hud_used.arousal.icon_state = "arousal30" return 1 if(getArousalLoss() >= (max_arousal / 100) * 20)//M O D U L A R , W O W hud_used.arousal.icon_state = "arousal10" return 1 if(getArousalLoss() >= (max_arousal / 100) * 10)//M O D U L A R , W O W hud_used.arousal.icon_state = "arousal10" return 1 else hud_used.arousal.icon_state = "arousal0" /obj/screen/arousal name = "arousal" icon_state = "arousal0" icon = 'code/citadel/icons/hud.dmi' screen_loc = ui_arousal /obj/screen/arousal/Click() if(!isliving(usr)) return 0 var/mob/living/M = usr if(M.canbearoused) M.mob_masturbate() return 1 else 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. 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(getArousalLoss() >= ((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 themself!", \ "You have relieved yourself.") setArousalLoss(min_arousal) /* switch(gender) if(MALE) PoolOrNew(/obj/effect/decal/cleanable/semen, loc) if(FEMALE) PoolOrNew(/obj/effect/decal/cleanable/femcum, loc) */ else src << "You aren't aroused enough for that." /mob/living/carbon/human/mob_masturbate() 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!" return 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/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!" return if(stat) src << "You must be conscious to do that!" return if(getArousalLoss() < 33)//flat number instead of percentage src << "You aren't aroused enough for that!" return if(!is_groin_exposed()) src << "You need to undress, first!" return if(!arms) src << "You need at least one 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." return for(var/obj/item/organ/genital/G in internal_organs) if(G.can_masturbate_with)//filter out what you can't masturbate with genitals_list += G if(genitals_list.len) SG = input(src, "with what?", "Masturbate") as null|obj in genitals_list if(SG) for(var/obj/item/weapon/reagent_containers/container in held_items) if(container.is_open_container() || istype(container, /obj/item/weapon/reagent_containers/food/snacks/pie)) containers_list += container if(containers_list.len) SC = input(src, "Into or onto what?(Cancel for nowhere)", "Masturbate") as null|obj in containers_list if(SC) if(in_range(src, SC)) into_container = 1 SG.update() switch(SG.type) //Penis if(/obj/item/organ/genital/penis) var/obj/item/organ/genital/penis/P = SG if(!P.linked_balls) src << "Grow a pair!" 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].", \ "You start jerking off over [SC.name].", \ "You start masturbating.") if(do_after(src, mb_time, target = src) && in_range(src, SC)) fluid_source.trans_to(SC, total_cum) src.visible_message("[src] orgasms, [pick("cumming into", "emptying themself into")] [SC]!", \ "You cum into [SC].", \ "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!" 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].", \ "You start fingering over [SC.name].", \ "You start masturbating.") if(do_after(src, mb_time, target = src) && in_range(src, SC)) fluid_source.trans_to(SC, total_cum) src.visible_message("[src] orgasms, [pick("cumming into", "emptying themself into")] [SC]!", \ "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.", \ "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 else//backup message, just in case src.visible_message("[src] starts masturbating!", \ "You start masturbating.") if(do_after(src, mb_time, target = src)) src.visible_message("[src] [pick("relieves themself!", "shudders and moans in orgasm!")]", \ "You have relieved yourself.") finished = 1 if(finished) setArousalLoss(min_arousal) else 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