mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-10 09:54:52 +00:00
let's fix arousal huh
This commit is contained in:
@@ -72,9 +72,6 @@
|
|||||||
#define MILK_RATE_MULT 1
|
#define MILK_RATE_MULT 1
|
||||||
#define MILK_EFFICIENCY 1
|
#define MILK_EFFICIENCY 1
|
||||||
|
|
||||||
#define AROUSAL_MINIMUM_DEFAULT 0
|
|
||||||
#define AROUSAL_MAXIMUM_DEFAULT 100
|
|
||||||
#define AROUSAL_START_VALUE 1
|
|
||||||
//Individual logging define
|
//Individual logging define
|
||||||
#define INDIVIDUAL_LOOC_LOG "LOOC log"
|
#define INDIVIDUAL_LOOC_LOG "LOOC log"
|
||||||
|
|
||||||
@@ -82,9 +79,6 @@
|
|||||||
#define ADMIN_IC(client) "(<a href='?_src_=holder;icissue=\ref[client]'>IC</a>)"//marks and adminhelp as an IC issue
|
#define ADMIN_IC(client) "(<a href='?_src_=holder;icissue=\ref[client]'>IC</a>)"//marks and adminhelp as an IC issue
|
||||||
#define ADMIN_REJECT(client) "(<a href='?_src_=holder;rejectadminhelp=\ref[client]'>REJT</a>)"//Rejects an adminhelp for being unclear or otherwise unhelpful. resets their adminhelp timer
|
#define ADMIN_REJECT(client) "(<a href='?_src_=holder;rejectadminhelp=\ref[client]'>REJT</a>)"//Rejects an adminhelp for being unclear or otherwise unhelpful. resets their adminhelp timer
|
||||||
|
|
||||||
//Damage stuffs
|
|
||||||
#define AROUSAL "arousal"
|
|
||||||
|
|
||||||
//Citadel istypes
|
//Citadel istypes
|
||||||
#define isgenital(A) (istype(A, /obj/item/organ/genital))
|
#define isgenital(A) (istype(A, /obj/item/organ/genital))
|
||||||
|
|
||||||
|
|||||||
@@ -161,9 +161,8 @@
|
|||||||
#define TRAIT_TAGGER "tagger"
|
#define TRAIT_TAGGER "tagger"
|
||||||
#define TRAIT_PHOTOGRAPHER "photographer"
|
#define TRAIT_PHOTOGRAPHER "photographer"
|
||||||
#define TRAIT_MUSICIAN "musician"
|
#define TRAIT_MUSICIAN "musician"
|
||||||
#define TRAIT_NYMPHO "nymphomania"
|
#define TRAIT_PERMABONER "permanent_arousal"
|
||||||
#define TRAIT_MASO "masochism"
|
#define TRAIT_NEVERBONER "never_aroused"
|
||||||
#define TRAIT_EXHIBITIONIST "exhibitionist"
|
|
||||||
#define TRAIT_HIGH_BLOOD "high_blood"
|
#define TRAIT_HIGH_BLOOD "high_blood"
|
||||||
#define TRAIT_PARA "paraplegic"
|
#define TRAIT_PARA "paraplegic"
|
||||||
#define TRAIT_EMPATH "empath"
|
#define TRAIT_EMPATH "empath"
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ GLOBAL_LIST_INIT(meat_types, list(
|
|||||||
"Mammalian" = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/mammal,
|
"Mammalian" = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/mammal,
|
||||||
"Aquatic" = /obj/item/reagent_containers/food/snacks/carpmeat/aquatic,
|
"Aquatic" = /obj/item/reagent_containers/food/snacks/carpmeat/aquatic,
|
||||||
"Avian" = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/avian,
|
"Avian" = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/avian,
|
||||||
"Inesct" = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/insect))
|
"Insect" = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/insect))
|
||||||
|
|
||||||
//Crew objective and miscreants stuff
|
//Crew objective and miscreants stuff
|
||||||
GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
|
GLOBAL_VAR_INIT(miscreants_allowed, FALSE)
|
||||||
|
|||||||
@@ -61,9 +61,6 @@ GLOBAL_LIST_INIT(available_ui_styles, list(
|
|||||||
// subtypes can override this to force a specific UI style
|
// subtypes can override this to force a specific UI style
|
||||||
var/ui_style
|
var/ui_style
|
||||||
|
|
||||||
//Citadel stuff
|
|
||||||
var/obj/screen/arousal
|
|
||||||
|
|
||||||
/datum/hud/New(mob/owner)
|
/datum/hud/New(mob/owner)
|
||||||
mymob = owner
|
mymob = owner
|
||||||
|
|
||||||
|
|||||||
@@ -336,11 +336,6 @@
|
|||||||
healths = new /obj/screen/healths()
|
healths = new /obj/screen/healths()
|
||||||
healths.hud = src
|
healths.hud = src
|
||||||
infodisplay += healths
|
infodisplay += healths
|
||||||
//CIT CHANGE - adds arousal and stamina to hud
|
|
||||||
arousal = new /obj/screen/arousal()
|
|
||||||
arousal.icon_state = (owner.canbearoused == 1 ? "arousal0" : "")
|
|
||||||
arousal.hud = src
|
|
||||||
infodisplay += arousal
|
|
||||||
|
|
||||||
staminas = new /obj/screen/staminas()
|
staminas = new /obj/screen/staminas()
|
||||||
staminas.hud = src
|
staminas.hud = src
|
||||||
|
|||||||
@@ -96,7 +96,6 @@
|
|||||||
CLONE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=clone' id='clone'>[M.getCloneLoss()]</a>
|
CLONE:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=clone' id='clone'>[M.getCloneLoss()]</a>
|
||||||
BRAIN:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=brain' id='brain'>[M.getOrganLoss(ORGAN_SLOT_BRAIN)]</a>
|
BRAIN:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=brain' id='brain'>[M.getOrganLoss(ORGAN_SLOT_BRAIN)]</a>
|
||||||
STAMINA:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=stamina' id='stamina'>[M.getStaminaLoss()]</a>
|
STAMINA:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=stamina' id='stamina'>[M.getStaminaLoss()]</a>
|
||||||
AROUSAL:<font size='1'><a href='?_src_=vars;[HrefToken()];mobToDamage=[refid];adjustDamage=arousal' id='arousal'>[M.getArousalLoss()]</a>
|
|
||||||
"}
|
"}
|
||||||
if(GLOB.Debug2)
|
if(GLOB.Debug2)
|
||||||
atomsnowflake += {"
|
atomsnowflake += {"
|
||||||
@@ -1355,9 +1354,6 @@
|
|||||||
if("stamina")
|
if("stamina")
|
||||||
L.adjustStaminaLoss(amount)
|
L.adjustStaminaLoss(amount)
|
||||||
newamt = L.getStaminaLoss()
|
newamt = L.getStaminaLoss()
|
||||||
if("arousal")
|
|
||||||
L.adjustArousalLoss(amount)
|
|
||||||
newamt = L.getArousalLoss()
|
|
||||||
if("heart")
|
if("heart")
|
||||||
L.adjustOrganLoss(ORGAN_SLOT_HEART, amount)
|
L.adjustOrganLoss(ORGAN_SLOT_HEART, amount)
|
||||||
newamt = L.getOrganLoss(ORGAN_SLOT_HEART)
|
newamt = L.getOrganLoss(ORGAN_SLOT_HEART)
|
||||||
|
|||||||
@@ -132,12 +132,8 @@
|
|||||||
//CIT CHANGE - makes arousal update when transfering bodies
|
//CIT CHANGE - makes arousal update when transfering bodies
|
||||||
if(isliving(new_character)) //New humans and such are by default enabled arousal. Let's always use the new mind's prefs.
|
if(isliving(new_character)) //New humans and such are by default enabled arousal. Let's always use the new mind's prefs.
|
||||||
var/mob/living/L = new_character
|
var/mob/living/L = new_character
|
||||||
if(L.client && L.client.prefs)
|
if(L.client && L.client.prefs & L.client.prefs.auto_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...
|
DISABLE_BITFIELD(L.client.prefs.chat_toggles,CHAT_OOC)
|
||||||
L.update_arousal_hud() //Removes the old icon
|
|
||||||
if (L.client.prefs.auto_ooc)
|
|
||||||
if (L.client.prefs.chat_toggles & CHAT_OOC)
|
|
||||||
L.client.prefs.chat_toggles ^= CHAT_OOC
|
|
||||||
|
|
||||||
SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character, old_character)
|
SEND_SIGNAL(src, COMSIG_MIND_TRANSFER, new_character, old_character)
|
||||||
|
|
||||||
|
|||||||
@@ -87,37 +87,3 @@
|
|||||||
/datum/quirk/monochromatic/remove()
|
/datum/quirk/monochromatic/remove()
|
||||||
if(quirk_holder)
|
if(quirk_holder)
|
||||||
quirk_holder.remove_client_colour(/datum/client_colour/monochrome)
|
quirk_holder.remove_client_colour(/datum/client_colour/monochrome)
|
||||||
|
|
||||||
/datum/quirk/libido
|
|
||||||
name = "Nymphomania"
|
|
||||||
desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual."
|
|
||||||
value = 0
|
|
||||||
mob_trait = TRAIT_NYMPHO
|
|
||||||
gain_text = "<span class='notice'>You are feeling extra wild.</span>"
|
|
||||||
lose_text = "<span class='notice'>You don't feel that burning sensation anymore.</span>"
|
|
||||||
|
|
||||||
/datum/quirk/libido/add()
|
|
||||||
quirk_holder.min_arousal = 16
|
|
||||||
quirk_holder.arousal_rate = 3
|
|
||||||
|
|
||||||
/datum/quirk/libido/remove()
|
|
||||||
if(quirk_holder)
|
|
||||||
quirk_holder.min_arousal = initial(quirk_holder.min_arousal)
|
|
||||||
quirk_holder.arousal_rate = initial(quirk_holder.arousal_rate)
|
|
||||||
|
|
||||||
/datum/quirk/maso
|
|
||||||
name = "Masochism"
|
|
||||||
desc = "You are aroused by pain."
|
|
||||||
value = 0
|
|
||||||
mob_trait = TRAIT_MASO
|
|
||||||
gain_text = "<span class='notice'>You desire to be hurt.</span>"
|
|
||||||
lose_text = "<span class='notice'>Pain has become less exciting for you.</span>"
|
|
||||||
|
|
||||||
/datum/quirk/exhibitionism
|
|
||||||
name = "Exhibitionism"
|
|
||||||
desc = "You don't mind showing off your bare body to strangers, in fact you find it quite satistying."
|
|
||||||
value = 0
|
|
||||||
medical_record_text = "Patient has been diagnosed with exhibitionistic disorder."
|
|
||||||
mob_trait = TRAIT_EXHIBITIONIST
|
|
||||||
gain_text = "<span class='notice'>You feel like exposing yourself to the world.</span>"
|
|
||||||
lose_text = "<span class='notice'>Indecent exposure doesn't sound as charming to you anymore.</span>"
|
|
||||||
|
|||||||
@@ -109,11 +109,6 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
|||||||
else if(current_version < 23) // we are fixing a gamebreaking bug.
|
else if(current_version < 23) // we are fixing a gamebreaking bug.
|
||||||
job_preferences = list() //It loaded null from nonexistant savefile field.
|
job_preferences = list() //It loaded null from nonexistant savefile field.
|
||||||
|
|
||||||
if(current_version < 24 && S["feature_exhibitionist"])
|
|
||||||
var/datum/quirk/exhibitionism/E
|
|
||||||
var/quirk_name = initial(E.name)
|
|
||||||
all_quirks += quirk_name
|
|
||||||
|
|
||||||
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
|
/datum/preferences/proc/load_path(ckey,filename="preferences.sav")
|
||||||
if(!ckey)
|
if(!ckey)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1310,34 +1310,3 @@
|
|||||||
set_pin_data(IC_OUTPUT, 2, regurgitated_contents)
|
set_pin_data(IC_OUTPUT, 2, regurgitated_contents)
|
||||||
push_data()
|
push_data()
|
||||||
activate_pin(2)
|
activate_pin(2)
|
||||||
|
|
||||||
//Degens
|
|
||||||
/obj/item/integrated_circuit/input/bonermeter
|
|
||||||
name = "bonermeter"
|
|
||||||
desc = "Detects the target's arousal and various statistics about the target's arousal levels. Invasive!"
|
|
||||||
icon_state = "medscan"
|
|
||||||
complexity = 4
|
|
||||||
inputs = list("target" = IC_PINTYPE_REF)
|
|
||||||
outputs = list(
|
|
||||||
"current arousal" = IC_PINTYPE_NUMBER,
|
|
||||||
"minimum arousal" = IC_PINTYPE_NUMBER,
|
|
||||||
"maximum arousal" = IC_PINTYPE_NUMBER,
|
|
||||||
"can be aroused" = IC_PINTYPE_BOOLEAN
|
|
||||||
)
|
|
||||||
activators = list("scan" = IC_PINTYPE_PULSE_IN, "on scanned" = IC_PINTYPE_PULSE_OUT)
|
|
||||||
spawn_flags = IC_SPAWN_RESEARCH
|
|
||||||
power_draw_per_use = 40
|
|
||||||
|
|
||||||
/obj/item/integrated_circuit/input/bonermeter/do_work()
|
|
||||||
|
|
||||||
var/mob/living/L = get_pin_data_as_type(IC_INPUT, 1, /mob/living)
|
|
||||||
|
|
||||||
if(!istype(L) || !L.Adjacent(get_turf(src)) ) //Invalid input
|
|
||||||
return
|
|
||||||
|
|
||||||
set_pin_data(IC_OUTPUT, 1, L.getArousalLoss())
|
|
||||||
set_pin_data(IC_OUTPUT, 2, L.min_arousal)
|
|
||||||
set_pin_data(IC_OUTPUT, 3, L.max_arousal)
|
|
||||||
set_pin_data(IC_OUTPUT, 4, L.canbearoused)
|
|
||||||
push_data()
|
|
||||||
activate_pin(2)
|
|
||||||
@@ -41,9 +41,6 @@
|
|||||||
update_damage_overlays()
|
update_damage_overlays()
|
||||||
else
|
else
|
||||||
adjustStaminaLoss(damage_amount, forced = forced)
|
adjustStaminaLoss(damage_amount, forced = forced)
|
||||||
//citadel code
|
|
||||||
if(AROUSAL)
|
|
||||||
adjustArousalLoss(damage_amount)
|
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -39,10 +39,6 @@
|
|||||||
//Stuff jammed in your limbs hurts
|
//Stuff jammed in your limbs hurts
|
||||||
handle_embedded_objects()
|
handle_embedded_objects()
|
||||||
|
|
||||||
if(stat != DEAD)
|
|
||||||
//process your dick energy
|
|
||||||
handle_arousal(times_fired)
|
|
||||||
|
|
||||||
//Update our name based on whether our face is obscured/disfigured
|
//Update our name based on whether our face is obscured/disfigured
|
||||||
name = get_visible_name()
|
name = get_visible_name()
|
||||||
|
|
||||||
|
|||||||
@@ -323,12 +323,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
|||||||
for(var/datum/disease/A in C.diseases)
|
for(var/datum/disease/A in C.diseases)
|
||||||
A.cure(FALSE)
|
A.cure(FALSE)
|
||||||
|
|
||||||
//CITADEL EDIT
|
|
||||||
if(NOAROUSAL in species_traits)
|
|
||||||
C.canbearoused = FALSE
|
|
||||||
else
|
|
||||||
if(C.client)
|
|
||||||
C.canbearoused = C.client.prefs.arousable
|
|
||||||
if(ishuman(C))
|
if(ishuman(C))
|
||||||
var/mob/living/carbon/human/H = C
|
var/mob/living/carbon/human/H = C
|
||||||
if(NOGENITALS in H.dna.species.species_traits)
|
if(NOGENITALS in H.dna.species.species_traits)
|
||||||
@@ -1586,8 +1580,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
|||||||
"<span class='notice'>You slap [user == target ? "yourself" : "\the [target]"] in the face! </span>",\
|
"<span class='notice'>You slap [user == target ? "yourself" : "\the [target]"] in the face! </span>",\
|
||||||
"You hear a slap."
|
"You hear a slap."
|
||||||
)
|
)
|
||||||
if (!HAS_TRAIT(target, TRAIT_NYMPHO))
|
|
||||||
stop_wagging_tail(target)
|
|
||||||
user.do_attack_animation(target, ATTACK_EFFECT_FACE_SLAP)
|
user.do_attack_animation(target, ATTACK_EFFECT_FACE_SLAP)
|
||||||
user.adjustStaminaLossBuffered(3)
|
user.adjustStaminaLossBuffered(3)
|
||||||
return FALSE
|
return FALSE
|
||||||
@@ -1602,14 +1594,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
|||||||
"<span class='danger'>\The [user] slaps \the [target]'s ass!</span>",\
|
"<span class='danger'>\The [user] slaps \the [target]'s ass!</span>",\
|
||||||
"<span class='notice'>You slap [user == target ? "your" : "\the [target]'s"] ass!</span>",\
|
"<span class='notice'>You slap [user == target ? "your" : "\the [target]'s"] ass!</span>",\
|
||||||
"You hear a slap."
|
"You hear a slap."
|
||||||
)
|
)
|
||||||
if (target.canbearoused)
|
|
||||||
target.adjustArousalLoss(5)
|
|
||||||
if (target.getArousalLoss() >= 100 && ishuman(target) && HAS_TRAIT(target, TRAIT_MASO) && target.has_dna())
|
|
||||||
target.mob_climax(forced_climax=TRUE)
|
|
||||||
if (!HAS_TRAIT(target, TRAIT_NYMPHO))
|
|
||||||
stop_wagging_tail(target)
|
|
||||||
|
|
||||||
return FALSE
|
return FALSE
|
||||||
else if(attacker_style && attacker_style.disarm_act(user,target))
|
else if(attacker_style && attacker_style.disarm_act(user,target))
|
||||||
return 1
|
return 1
|
||||||
@@ -1962,10 +1947,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
|||||||
if(BP)
|
if(BP)
|
||||||
if(damage > 0 ? BP.receive_damage(damage_amount, 0) : BP.heal_damage(abs(damage_amount), 0))
|
if(damage > 0 ? BP.receive_damage(damage_amount, 0) : BP.heal_damage(abs(damage_amount), 0))
|
||||||
H.update_damage_overlays()
|
H.update_damage_overlays()
|
||||||
if(HAS_TRAIT(H, TRAIT_MASO))
|
|
||||||
H.adjustArousalLoss(damage_amount, 0)
|
|
||||||
if (H.getArousalLoss() >= 100 && ishuman(H) && H.has_dna())
|
|
||||||
H.mob_climax(forced_climax=TRUE)
|
|
||||||
|
|
||||||
else//no bodypart, we deal damage with a more general method.
|
else//no bodypart, we deal damage with a more general method.
|
||||||
H.adjustBruteLoss(damage_amount)
|
H.adjustBruteLoss(damage_amount)
|
||||||
@@ -1996,8 +1977,6 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
|||||||
if(BRAIN)
|
if(BRAIN)
|
||||||
var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.brain_mod
|
var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.brain_mod
|
||||||
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, damage_amount)
|
H.adjustOrganLoss(ORGAN_SLOT_BRAIN, damage_amount)
|
||||||
if(AROUSAL) //Citadel edit - arousal
|
|
||||||
H.adjustArousalLoss(damage * hit_percent)
|
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
/datum/species/proc/on_hit(obj/item/projectile/P, mob/living/carbon/human/H)
|
/datum/species/proc/on_hit(obj/item/projectile/P, mob/living/carbon/human/H)
|
||||||
|
|||||||
@@ -966,7 +966,12 @@
|
|||||||
M.emote("nya")
|
M.emote("nya")
|
||||||
if(prob(20))
|
if(prob(20))
|
||||||
to_chat(M, "<span class = 'notice'>[pick("Headpats feel nice.", "Backrubs would be nice.", "Mew")]</span>")
|
to_chat(M, "<span class = 'notice'>[pick("Headpats feel nice.", "Backrubs would be nice.", "Mew")]</span>")
|
||||||
M.adjustArousalLoss(5)
|
if(M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(5))
|
||||||
|
for(var/obj/item/organ/genital/G in M.internal_organs)
|
||||||
|
if(!G.aroused_state && prob(5))
|
||||||
|
G.aroused_state = TRUE
|
||||||
|
to_chat(M, "<span class='userlove'>You feel like playing with your [G.name]!")
|
||||||
|
|
||||||
..()
|
..()
|
||||||
|
|
||||||
/datum/reagent/consumable/monkey_energy
|
/datum/reagent/consumable/monkey_energy
|
||||||
|
|||||||
@@ -2280,5 +2280,10 @@
|
|||||||
M.emote("nya")
|
M.emote("nya")
|
||||||
if(prob(20))
|
if(prob(20))
|
||||||
to_chat(M, "<span class = 'notice'>[pick("Headpats feel nice.", "The feeling of a hairball...", "Backrubs would be nice.", "Whats behind those doors?")]</span>")
|
to_chat(M, "<span class = 'notice'>[pick("Headpats feel nice.", "The feeling of a hairball...", "Backrubs would be nice.", "Whats behind those doors?")]</span>")
|
||||||
M.adjustArousalLoss(2)
|
if(M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO && ishuman(M)))
|
||||||
|
var/mob/living/carbon/human/H = M
|
||||||
|
for(var/obj/item/organ/genital/G in H.internal_organs)
|
||||||
|
if(!G.aroused_state && prob(2))
|
||||||
|
G.aroused_state = TRUE
|
||||||
|
to_chat(M, "<span class='userlove'>You feel like playing with your [G.name]!")
|
||||||
..()
|
..()
|
||||||
|
|||||||
@@ -578,7 +578,8 @@
|
|||||||
cooldown = COOLDOWN_MEME
|
cooldown = COOLDOWN_MEME
|
||||||
for(var/V in listeners)
|
for(var/V in listeners)
|
||||||
var/mob/living/carbon/human/H = V
|
var/mob/living/carbon/human/H = V
|
||||||
if(H.canbearoused && H.has_dna() && HAS_TRAIT(H, TRAIT_NYMPHO)) // probably a redundant check but for good measure
|
|
||||||
|
if(H.client && H.client.prefs && H.client.prefs.cit_toggles & HYPNO) // probably a redundant check but for good measure
|
||||||
H.mob_climax(forced_climax=TRUE)
|
H.mob_climax(forced_climax=TRUE)
|
||||||
|
|
||||||
//DAB
|
//DAB
|
||||||
@@ -807,7 +808,7 @@
|
|||||||
E.enthrallTally += (power_multiplier*(((length(message))/200) + 1)) //encourage players to say more than one word.
|
E.enthrallTally += (power_multiplier*(((length(message))/200) + 1)) //encourage players to say more than one word.
|
||||||
else
|
else
|
||||||
E.enthrallTally += power_multiplier*1.25 //thinking about it, I don't know how this can proc
|
E.enthrallTally += power_multiplier*1.25 //thinking about it, I don't know how this can proc
|
||||||
if(L.canbearoused && E.lewd)
|
if(E.lewd)
|
||||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='nicegreen'><i><b>[E.enthrallGender] is so nice to listen to.</b></i></span>"), 5)
|
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='nicegreen'><i><b>[E.enthrallGender] is so nice to listen to.</b></i></span>"), 5)
|
||||||
E.cooldown += 1
|
E.cooldown += 1
|
||||||
|
|
||||||
@@ -821,12 +822,6 @@
|
|||||||
continue
|
continue
|
||||||
if (E.lewd)
|
if (E.lewd)
|
||||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='love'>[E.enthrallGender] has praised me!!</span>"), 5)
|
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='love'>[E.enthrallGender] has praised me!!</span>"), 5)
|
||||||
if(HAS_TRAIT(L, TRAIT_NYMPHO))
|
|
||||||
L.adjustArousalLoss(2*power_multiplier)
|
|
||||||
if(HAS_TRAIT(L, TRAIT_MASO))
|
|
||||||
E.enthrallTally -= power_multiplier
|
|
||||||
E.resistanceTally += power_multiplier
|
|
||||||
E.cooldown += 1
|
|
||||||
else
|
else
|
||||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='nicegreen'><b><i>I've been praised for doing a good job!</b></i></span>"), 5)
|
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='nicegreen'><b><i>I've been praised for doing a good job!</b></i></span>"), 5)
|
||||||
E.resistanceTally -= power_multiplier
|
E.resistanceTally -= power_multiplier
|
||||||
@@ -844,14 +839,7 @@
|
|||||||
if(L == user)
|
if(L == user)
|
||||||
continue
|
continue
|
||||||
if (E.lewd)
|
if (E.lewd)
|
||||||
if(HAS_TRAIT(L, TRAIT_MASO))
|
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='warning'>I've let [E.enthrallGender] down...</b></span>"), 5)
|
||||||
L.adjustArousalLoss(3*power_multiplier)
|
|
||||||
descmessage += "And yet, it feels so good..!</span>" //I don't really understand masco, is this the right sort of thing they like?
|
|
||||||
E.enthrallTally += power_multiplier
|
|
||||||
E.resistanceTally -= power_multiplier
|
|
||||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='love'>I've let [E.enthrallGender] down...!</b></span>"), 5)
|
|
||||||
else
|
|
||||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='warning'>I've let [E.enthrallGender] down...</b></span>"), 5)
|
|
||||||
else
|
else
|
||||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='warning'>I've failed [E.master]...</b></span>"), 5)
|
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, L, "<span class='warning'>I've failed [E.master]...</b></span>"), 5)
|
||||||
E.resistanceTally += power_multiplier
|
E.resistanceTally += power_multiplier
|
||||||
@@ -1001,16 +989,6 @@
|
|||||||
if(160 to INFINITY)
|
if(160 to INFINITY)
|
||||||
speaktrigger += "I feel like I'm on the brink of losing my mind, "
|
speaktrigger += "I feel like I'm on the brink of losing my mind, "
|
||||||
|
|
||||||
//horny
|
|
||||||
if(HAS_TRAIT(H, TRAIT_NYMPHO) && H.canbearoused && E.lewd)
|
|
||||||
switch(H.getArousalLoss())
|
|
||||||
if(40 to 60)
|
|
||||||
speaktrigger += "I'm feeling a little horny, "
|
|
||||||
if(60 to 80)
|
|
||||||
speaktrigger += "I'm feeling horny, "
|
|
||||||
if(80 to INFINITY)
|
|
||||||
speaktrigger += "I'm really, really horny, "
|
|
||||||
|
|
||||||
//collar
|
//collar
|
||||||
if(istype(H.wear_neck, /obj/item/clothing/neck/petcollar) && E.lewd)
|
if(istype(H.wear_neck, /obj/item/clothing/neck/petcollar) && E.lewd)
|
||||||
speaktrigger += "I love the collar you gave me, "
|
speaktrigger += "I love the collar you gave me, "
|
||||||
@@ -1111,11 +1089,10 @@
|
|||||||
var/mob/living/carbon/human/H = V
|
var/mob/living/carbon/human/H = V
|
||||||
var/datum/status_effect/chem/enthrall/E = H.has_status_effect(/datum/status_effect/chem/enthrall)
|
var/datum/status_effect/chem/enthrall/E = H.has_status_effect(/datum/status_effect/chem/enthrall)
|
||||||
if(E.phase > 1)
|
if(E.phase > 1)
|
||||||
if(HAS_TRAIT(H, TRAIT_NYMPHO) && H.canbearoused && E.lewd) // probably a redundant check but for good measure
|
if(E.lewd) // probably a redundant check but for good measure
|
||||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "<span class='love'>Your [E.enthrallGender] pushes you over the limit, overwhelming your body with pleasure.</b></span>"), 5)
|
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, H, "<span class='love'>Your [E.enthrallGender] pushes you over the limit, overwhelming your body with pleasure.</b></span>"), 5)
|
||||||
H.mob_climax(forced_climax=TRUE)
|
H.mob_climax(forced_climax=TRUE)
|
||||||
H.SetStun(20)
|
H.SetStun(20)
|
||||||
H.setArousalLoss(H.min_arousal)
|
|
||||||
E.resistanceTally = 0 //makes resistance 0, but resets arousal, resistance buildup is faster unaroused (massively so).
|
E.resistanceTally = 0 //makes resistance 0, but resets arousal, resistance buildup is faster unaroused (massively so).
|
||||||
E.enthrallTally += power_multiplier
|
E.enthrallTally += power_multiplier
|
||||||
E.cooldown += 6
|
E.cooldown += 6
|
||||||
|
|||||||
@@ -268,10 +268,6 @@
|
|||||||
RegisterSignal(owner, COMSIG_LIVING_RESIST, .proc/owner_resist) //Do resistance calc if resist is pressed#
|
RegisterSignal(owner, COMSIG_LIVING_RESIST, .proc/owner_resist) //Do resistance calc if resist is pressed#
|
||||||
RegisterSignal(owner, COMSIG_MOVABLE_HEAR, .proc/owner_hear)
|
RegisterSignal(owner, COMSIG_MOVABLE_HEAR, .proc/owner_hear)
|
||||||
mental_capacity = 500 - M.getOrganLoss(ORGAN_SLOT_BRAIN)//It's their brain!
|
mental_capacity = 500 - M.getOrganLoss(ORGAN_SLOT_BRAIN)//It's their brain!
|
||||||
var/mob/living/carbon/human/H = owner
|
|
||||||
if(H)//Prefs
|
|
||||||
if(!H.canbearoused)
|
|
||||||
H.client?.prefs.cit_toggles &= ~HYPNO
|
|
||||||
lewd = (owner.client?.prefs.cit_toggles & HYPNO) && (master.client?.prefs.cit_toggles & HYPNO)
|
lewd = (owner.client?.prefs.cit_toggles & HYPNO) && (master.client?.prefs.cit_toggles & HYPNO)
|
||||||
var/message = "[(lewd ? "I am a good pet for [enthrallGender]." : "[master] is a really inspirational person!")]"
|
var/message = "[(lewd ? "I am a good pet for [enthrallGender]." : "[master] is a really inspirational person!")]"
|
||||||
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "enthrall", /datum/mood_event/enthrall, message)
|
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "enthrall", /datum/mood_event/enthrall, message)
|
||||||
@@ -625,8 +621,6 @@
|
|||||||
//Speak (Forces player to talk)
|
//Speak (Forces player to talk)
|
||||||
if (lowertext(customTriggers[trigger][1]) == "speak")//trigger2
|
if (lowertext(customTriggers[trigger][1]) == "speak")//trigger2
|
||||||
var/saytext = "Your mouth moves on it's own before you can even catch it."
|
var/saytext = "Your mouth moves on it's own before you can even catch it."
|
||||||
if(HAS_TRAIT(C, TRAIT_NYMPHO))
|
|
||||||
saytext += " You find yourself fully believing in the validity of what you just said and don't think to question it."
|
|
||||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "<span class='notice'><i>[saytext]</i></span>"), 5)
|
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat, C, "<span class='notice'><i>[saytext]</i></span>"), 5)
|
||||||
addtimer(CALLBACK(C, /atom/movable/proc/say, "[customTriggers[trigger][2]]"), 5)
|
addtimer(CALLBACK(C, /atom/movable/proc/say, "[customTriggers[trigger][2]]"), 5)
|
||||||
log_game("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been forced to say: \"[customTriggers[trigger][2]]\" from previous trigger.")
|
log_game("FERMICHEM: MKULTRA: [owner] ckey: [owner.key] has been forced to say: \"[customTriggers[trigger][2]]\" from previous trigger.")
|
||||||
@@ -639,8 +633,6 @@
|
|||||||
|
|
||||||
//Shocking truth!
|
//Shocking truth!
|
||||||
else if (lowertext(customTriggers[trigger]) == "shock")
|
else if (lowertext(customTriggers[trigger]) == "shock")
|
||||||
if (C.canbearoused && lewd)
|
|
||||||
C.adjustArousalLoss(5)
|
|
||||||
C.jitteriness += 100
|
C.jitteriness += 100
|
||||||
C.stuttering += 25
|
C.stuttering += 25
|
||||||
C.Knockdown(60)
|
C.Knockdown(60)
|
||||||
@@ -649,13 +641,11 @@
|
|||||||
|
|
||||||
//wah intensifies wah-rks
|
//wah intensifies wah-rks
|
||||||
else if (lowertext(customTriggers[trigger]) == "cum")//aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
else if (lowertext(customTriggers[trigger]) == "cum")//aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
|
||||||
if (HAS_TRAIT(C, TRAIT_NYMPHO) && lewd)
|
if (lewd)
|
||||||
if (C.getArousalLoss() > 80)
|
if(ishuman(C))
|
||||||
C.mob_climax(forced_climax=TRUE)
|
var/mob/living/carbon/human/H = C
|
||||||
C.SetStun(10)//We got your stun effects in somewhere, Kev.
|
H.mob_climax(forced_climax=TRUE)
|
||||||
else
|
C.SetStun(10)//We got your stun effects in somewhere, Kev.
|
||||||
C.adjustArousalLoss(10)
|
|
||||||
to_chat(C, "<span class='love'><i>You feel a surge of arousal!</i></span>")
|
|
||||||
else
|
else
|
||||||
C.throw_at(get_step_towards(hearing_args[HEARING_SPEAKER],C), 3, 1) //cut this if it's too hard to get working
|
C.throw_at(get_step_towards(hearing_args[HEARING_SPEAKER],C), 3, 1) //cut this if it's too hard to get working
|
||||||
|
|
||||||
@@ -734,16 +724,13 @@
|
|||||||
if(prob(5))
|
if(prob(5))
|
||||||
M.emote("me",1,"squints, shaking their head for a moment.")//shows that you're trying to resist sometimes
|
M.emote("me",1,"squints, shaking their head for a moment.")//shows that you're trying to resist sometimes
|
||||||
deltaResist *= 1.5
|
deltaResist *= 1.5
|
||||||
//nymphomania
|
|
||||||
if (M.canbearoused && HAS_TRAIT(M, TRAIT_NYMPHO))//I'm okay with this being removed.
|
|
||||||
deltaResist*= 0.5-(((2/200)*M.arousalloss)/1)//more aroused you are, the weaker resistance you can give, the less you are, the more you gain. (+/- 0.5)
|
|
||||||
|
|
||||||
//chemical resistance, brain and annaphros are the key to undoing, but the subject has to to be willing to resist.
|
//chemical resistance, brain and annaphros are the key to undoing, but the subject has to to be willing to resist.
|
||||||
if (owner.reagents.has_reagent("mannitol"))
|
if (owner.reagents.has_reagent("mannitol"))
|
||||||
deltaResist *= 1.25
|
deltaResist *= 1.25
|
||||||
if (owner.reagents.has_reagent("neurine"))
|
if (owner.reagents.has_reagent("neurine"))
|
||||||
deltaResist *= 1.5
|
deltaResist *= 1.5
|
||||||
if (!(owner.client?.prefs.cit_toggles & NO_APHRO) && M.canbearoused && lewd)
|
if (!(owner.client?.prefs.cit_toggles & NO_APHRO) && lewd)
|
||||||
if (owner.reagents.has_reagent("anaphro"))
|
if (owner.reagents.has_reagent("anaphro"))
|
||||||
deltaResist *= 1.5
|
deltaResist *= 1.5
|
||||||
if (owner.reagents.has_reagent("anaphro+"))
|
if (owner.reagents.has_reagent("anaphro+"))
|
||||||
|
|||||||
@@ -1,17 +1,8 @@
|
|||||||
//Mob vars
|
|
||||||
/mob/living
|
/mob/living
|
||||||
var/arousalloss = 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_length = 5 SECONDS //5 second cooldown for masturbating because fuck spam.
|
||||||
var/mb_cd_timer = 0 //The timer itself
|
var/mb_cd_timer = 0 //The timer itself
|
||||||
|
|
||||||
/mob/living/carbon/human
|
/mob/living/carbon/human
|
||||||
canbearoused = TRUE
|
|
||||||
|
|
||||||
var/saved_underwear = ""//saves their underwear so it can be toggled later
|
var/saved_underwear = ""//saves their underwear so it can be toggled later
|
||||||
var/saved_undershirt = ""
|
var/saved_undershirt = ""
|
||||||
var/saved_socks = ""
|
var/saved_socks = ""
|
||||||
@@ -21,8 +12,6 @@
|
|||||||
|
|
||||||
//Species vars
|
//Species vars
|
||||||
/datum/species
|
/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("semen")
|
var/list/cum_fluids = list("semen")
|
||||||
var/list/milk_fluids = list("milk")
|
var/list/milk_fluids = list("milk")
|
||||||
var/list/femcum_fluids = list("femcum")
|
var/list/femcum_fluids = list("femcum")
|
||||||
@@ -30,7 +19,7 @@
|
|||||||
//Mob procs
|
//Mob procs
|
||||||
/mob/living/carbon/human/proc/underwear_toggle()
|
/mob/living/carbon/human/proc/underwear_toggle()
|
||||||
set name = "Toggle undergarments"
|
set name = "Toggle undergarments"
|
||||||
set category = "IC"
|
set category = "Arousal"
|
||||||
|
|
||||||
var/confirm = input(src, "Select what part of your form to alter", "Undergarment Toggling") as null|anything in list("Top", "Bottom", "Socks", "All")
|
var/confirm = input(src, "Select what part of your form to alter", "Undergarment Toggling") as null|anything in list("Top", "Bottom", "Socks", "All")
|
||||||
if(!confirm)
|
if(!confirm)
|
||||||
@@ -52,131 +41,6 @@
|
|||||||
|
|
||||||
update_body()
|
update_body()
|
||||||
|
|
||||||
/mob/living/proc/handle_arousal(times_fired)
|
|
||||||
return
|
|
||||||
|
|
||||||
/mob/living/carbon/handle_arousal(times_fired)
|
|
||||||
if(!canbearoused || !dna)
|
|
||||||
return
|
|
||||||
var/datum/species/S = dna.species
|
|
||||||
if(!S || (times_fired % 36) || !getArousalLoss() >= max_arousal)//Totally stolen from breathing code. Do this every 36 ticks.
|
|
||||||
return
|
|
||||||
var/our_loss = arousal_rate * S.arousal_gain_rate
|
|
||||||
if(HAS_TRAIT(src, TRAIT_EXHIBITIONIST) && client)
|
|
||||||
var/amt_nude = 0
|
|
||||||
for(var/obj/item/organ/genital/G in internal_organs)
|
|
||||||
if(G.is_exposed())
|
|
||||||
amt_nude++
|
|
||||||
if(amt_nude)
|
|
||||||
var/watchers = 0
|
|
||||||
for(var/mob/living/L in view(src))
|
|
||||||
if(L.client && !L.stat && !L.eye_blind && (src in view(L)))
|
|
||||||
watchers++
|
|
||||||
if(watchers)
|
|
||||||
our_loss += (amt_nude * watchers) + S.arousal_gain_rate
|
|
||||||
adjustArousalLoss(our_loss)
|
|
||||||
|
|
||||||
/mob/living/proc/getArousalLoss()
|
|
||||||
return arousalloss
|
|
||||||
|
|
||||||
/mob/living/proc/adjustArousalLoss(amount, updating_arousal=1)
|
|
||||||
if(status_flags & GODMODE || !canbearoused)
|
|
||||||
return FALSE
|
|
||||||
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 FALSE
|
|
||||||
arousalloss = CLAMP(amount, min_arousal, max_arousal)
|
|
||||||
if(updating_arousal)
|
|
||||||
updatearousal()
|
|
||||||
|
|
||||||
/mob/living/proc/getPercentAroused()
|
|
||||||
var/percentage = ((100 / max_arousal) * arousalloss)
|
|
||||||
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)
|
|
||||||
else
|
|
||||||
G.aroused_state = FALSE
|
|
||||||
G.update_appearance()
|
|
||||||
|
|
||||||
/mob/living/proc/update_arousal_hud()
|
|
||||||
return FALSE
|
|
||||||
|
|
||||||
/mob/living/carbon/human/update_arousal_hud()
|
|
||||||
if(!client || !(hud_used?.arousal))
|
|
||||||
return FALSE
|
|
||||||
if(!canbearoused)
|
|
||||||
hud_used.arousal.icon_state = ""
|
|
||||||
return FALSE
|
|
||||||
else
|
|
||||||
var/value = FLOOR(getPercentAroused(), 10)
|
|
||||||
hud_used.arousal.icon_state = "arousal[value]"
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
/obj/screen/arousal
|
|
||||||
name = "arousal"
|
|
||||||
icon_state = "arousal0"
|
|
||||||
icon = 'modular_citadel/icons/obj/genitals/hud.dmi'
|
|
||||||
screen_loc = ui_arousal
|
|
||||||
|
|
||||||
/obj/screen/arousal/Click()
|
|
||||||
if(!isliving(usr))
|
|
||||||
return FALSE
|
|
||||||
var/mob/living/M = usr
|
|
||||||
if(M.canbearoused)
|
|
||||||
M.mob_climax()
|
|
||||||
return TRUE
|
|
||||||
else
|
|
||||||
to_chat(M, "<span class='warning'>Arousal is disabled. Feature is unavailable.</span>")
|
|
||||||
|
|
||||||
|
|
||||||
/mob/living/proc/mob_climax(forced_climax = FALSE)//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() >= 33)//one third of average max_arousal or greater required
|
|
||||||
visible_message("<span class='danger'>[src] starts masturbating!</span>", \
|
|
||||||
"<span class='userdanger'>You start masturbating.</span>")
|
|
||||||
if(do_after(src, 30, target = src))
|
|
||||||
visible_message("<span class='danger'>[src] relieves [p_them()]self!</span>", \
|
|
||||||
"<span class='userdanger'>You have relieved yourself.</span>")
|
|
||||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
|
|
||||||
setArousalLoss(min_arousal)
|
|
||||||
else
|
|
||||||
to_chat(src, "<span class='notice'>You aren't aroused enough for that.</span>")
|
|
||||||
|
|
||||||
/obj/item/organ/genital/proc/climaxable(mob/living/carbon/human/H, silent = FALSE) //returns the fluid source (ergo reagents holder) if found.
|
/obj/item/organ/genital/proc/climaxable(mob/living/carbon/human/H, silent = FALSE) //returns the fluid source (ergo reagents holder) if found.
|
||||||
if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION))
|
if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION))
|
||||||
. = reagents
|
. = reagents
|
||||||
@@ -189,97 +53,38 @@
|
|||||||
/mob/living/carbon/human/proc/do_climax(datum/reagents/R, atom/target, obj/item/organ/genital/G, spill = TRUE)
|
/mob/living/carbon/human/proc/do_climax(datum/reagents/R, atom/target, obj/item/organ/genital/G, spill = TRUE)
|
||||||
if(!G)
|
if(!G)
|
||||||
return
|
return
|
||||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
|
|
||||||
setArousalLoss(min_arousal)
|
|
||||||
if(!target || !R)
|
if(!target || !R)
|
||||||
return
|
return
|
||||||
var/turfing = isturf(target)
|
var/turfing = isturf(target)
|
||||||
if(spill & R.total_volume >= 5)
|
if(spill && R.total_volume >= 5)
|
||||||
R.reaction(turfing ? target : target.loc, TOUCH, 1, 0)
|
R.reaction(turfing ? target : target.loc, TOUCH, 1, 0)
|
||||||
if(!turfing)
|
if(!turfing)
|
||||||
R.trans_to(target, R.total_volume * (spill ? G.fluid_transfer_factor : 1))
|
R.trans_to(target, R.total_volume * (spill ? G.fluid_transfer_factor : 1))
|
||||||
R.clear_reagents()
|
R.clear_reagents()
|
||||||
|
|
||||||
//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/datum/reagents/fluid_source = G.climaxable(src)
|
|
||||||
if(!fluid_source)
|
|
||||||
return
|
|
||||||
var/obj/item/organ/genital/PP = CHECK_BITFIELD(G.genital_flags, MASTURBATE_LINKED_ORGAN) ? G.linked_organ : G
|
|
||||||
if(!PP)
|
|
||||||
to_chat(src, "<span class='warning'>You shudder, unable to cum with your [name].</span>")
|
|
||||||
if(mb_time)
|
|
||||||
visible_message("<span class='love'>[src] starts to [G.masturbation_verb] [p_their()] [G.name].</span>", \
|
|
||||||
"<span class='userlove'>You start to [G.masturbation_verb] your [G.name].</span>")
|
|
||||||
if(!do_after(src, mb_time, target = src) || !G.climaxable(src, TRUE))
|
|
||||||
return
|
|
||||||
visible_message("<span class='love'>[src] orgasms, [PP.orgasm_verb][isturf(loc) ? " onto [loc]" : ""] with [p_their()] [PP.name]!</span>", \
|
|
||||||
"<span class='userlove'>You orgasm, [PP.orgasm_verb][isturf(loc) ? " onto [loc]" : ""] with your [PP.name].</span>")
|
|
||||||
do_climax(fluid_source, loc, G)
|
|
||||||
|
|
||||||
/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
|
/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)
|
var/datum/reagents/fluid_source = G.climaxable(src, TRUE)
|
||||||
if(!fluid_source)
|
if(!fluid_source)
|
||||||
visible_message("<span class='danger'>[src] shudders, their [G.name] unable to cum.</span>", \
|
to_chat(src,"<span class='userdanger'>Your [G.name] cannot cum.</span>")
|
||||||
"<span class='userdanger'>Your [G.name] cannot cum, giving no relief.</span>")
|
|
||||||
return
|
return
|
||||||
if(mb_time) //as long as it's not instant, give a warning
|
if(mb_time) //as long as it's not instant, give a warning
|
||||||
visible_message("<span class='love'>[src] looks like they're about to cum.</span>", \
|
to_chat(src,"<span class='userlove'>You feel yourself about to orgasm.</span>")
|
||||||
"<span class='userlove'>You feel yourself about to orgasm.</span>")
|
|
||||||
if(!do_after(src, mb_time, target = src) || !G.climaxable(src, TRUE))
|
if(!do_after(src, mb_time, target = src) || !G.climaxable(src, TRUE))
|
||||||
return
|
return
|
||||||
visible_message("<span class='love'>[src] orgasms[isturf(loc) ? " onto [loc]" : ""], using [p_their()] [G.name]!</span>", \
|
to_chat(src,"<span class='userlove'>You climax[isturf(loc) ? " onto [loc]" : ""] with your [G.name].</span>")
|
||||||
"<span class='userlove'>You climax[isturf(loc) ? " onto [loc]" : ""] with your [G.name].</span>")
|
|
||||||
do_climax(fluid_source, loc, G)
|
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.
|
|
||||||
visible_message("<span class='love'>[src] is about to climax with [L]!</span>", \
|
|
||||||
"<span class='userlove'>You're about to climax with [L]!</span>")
|
|
||||||
if(!do_after(src, mb_time, target = src) || !in_range(src, L) || !G.climaxable(src, TRUE))
|
|
||||||
return
|
|
||||||
if(spillage)
|
|
||||||
visible_message("<span class='love'>[src] climaxes with [L], overflowing and spilling, using [p_their()] [G.name]!</span>", \
|
|
||||||
"<span class='userlove'>You orgasm with [L], spilling out of them, using your [G.name].</span>")
|
|
||||||
else //knots and other non-spilling orgasms
|
|
||||||
visible_message("<span class='love'>[src] climaxes with [L], [p_their()] [G.name] spilling nothing!</span>", \
|
|
||||||
"<span class='userlove'>You ejaculate with [L], your [G.name] spilling nothing.</span>")
|
|
||||||
SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
|
|
||||||
do_climax(fluid_source, spillage ? loc : L, G, spillage)
|
|
||||||
|
|
||||||
|
|
||||||
/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
|
/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)
|
var/datum/reagents/fluid_source = G.climaxable(src)
|
||||||
if(!fluid_source)
|
if(!fluid_source)
|
||||||
return
|
return
|
||||||
if(mb_time)
|
if(mb_time)
|
||||||
visible_message("<span class='love'>[src] starts to [G.masturbation_verb] their [G.name] over [container].</span>", \
|
to_chat(src,"<span class='userlove'>You start to [G.masturbation_verb] your [G.name] over [container].</span>")
|
||||||
"<span class='userlove'>You start to [G.masturbation_verb] your [G.name] over [container].</span>")
|
|
||||||
if(!do_after(src, mb_time, target = src) || !in_range(src, container) || !G.climaxable(src, TRUE))
|
if(!do_after(src, mb_time, target = src) || !in_range(src, container) || !G.climaxable(src, TRUE))
|
||||||
return
|
return
|
||||||
visible_message("<span class='love'>[src] uses [p_their()] [G.name] to fill [container]!</span>", \
|
to_chat(src,"<span class='userlove'>You used your [G.name] to fill [container].</span>")
|
||||||
"<span class='userlove'>You used your [G.name] to fill [container].</span>")
|
|
||||||
do_climax(fluid_source, container, G, FALSE)
|
do_climax(fluid_source, container, G, FALSE)
|
||||||
|
|
||||||
/mob/living/carbon/human/proc/pick_masturbate_genitals(silent = FALSE)
|
|
||||||
var/list/genitals_list
|
|
||||||
var/list/worn_stuff = get_equipped_items()
|
|
||||||
|
|
||||||
for(var/obj/item/organ/genital/G in internal_organs)
|
|
||||||
if(CHECK_BITFIELD(G.genital_flags, CAN_MASTURBATE_WITH) && G.is_exposed(worn_stuff)) //filter out what you can't masturbate with
|
|
||||||
if(CHECK_BITFIELD(G.genital_flags, MASTURBATE_LINKED_ORGAN) && !G.linked_organ)
|
|
||||||
continue
|
|
||||||
LAZYADD(genitals_list, G)
|
|
||||||
if(LAZYLEN(genitals_list))
|
|
||||||
var/obj/item/organ/genital/ret_organ = input(src, "with what?", "Masturbate", null) as null|obj in genitals_list
|
|
||||||
return ret_organ
|
|
||||||
else if(!silent)
|
|
||||||
to_chat(src, "<span class='warning'>You cannot masturbate without available genitals.</span>")
|
|
||||||
|
|
||||||
/mob/living/carbon/human/proc/pick_climax_genitals(silent = FALSE)
|
/mob/living/carbon/human/proc/pick_climax_genitals(silent = FALSE)
|
||||||
var/list/genitals_list
|
var/list/genitals_list
|
||||||
var/list/worn_stuff = get_equipped_items()
|
var/list/worn_stuff = get_equipped_items()
|
||||||
@@ -293,27 +98,6 @@
|
|||||||
else if(!silent)
|
else if(!silent)
|
||||||
to_chat(src, "<span class='warning'>You cannot climax without available genitals.</span>")
|
to_chat(src, "<span class='warning'>You cannot climax without available genitals.</span>")
|
||||||
|
|
||||||
/mob/living/carbon/human/proc/pick_partner(silent = FALSE)
|
|
||||||
var/list/partners = list()
|
|
||||||
if(pulling)
|
|
||||||
partners += pulling
|
|
||||||
if(pulledby)
|
|
||||||
partners += pulledby
|
|
||||||
//Now we got both of them, let's check if they're proper
|
|
||||||
for(var/mob/living/L in partners)
|
|
||||||
if(iscarbon(L))
|
|
||||||
var/mob/living/carbon/C = L
|
|
||||||
if(!C.exposed_genitals.len && !C.is_groin_exposed() && !C.is_chest_exposed()) //Nothing through_clothing, no proper partner.
|
|
||||||
partners -= C
|
|
||||||
//NOW the list should only contain correct partners
|
|
||||||
if(!partners.len)
|
|
||||||
if(!silent)
|
|
||||||
to_chat(src, "<span class='warning'>You cannot do this alone.</span>")
|
|
||||||
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))
|
|
||||||
return target
|
|
||||||
|
|
||||||
/mob/living/carbon/human/proc/pick_climax_container(silent = FALSE)
|
/mob/living/carbon/human/proc/pick_climax_container(silent = FALSE)
|
||||||
var/list/containers_list = list()
|
var/list/containers_list = list()
|
||||||
|
|
||||||
@@ -349,13 +133,13 @@
|
|||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
//Here's the main proc itself
|
//Here's the main proc itself
|
||||||
/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
|
/mob/living/carbon/human/proc/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(mb_cd_timer > world.time)
|
||||||
if(!forced_climax) //Don't spam the message to the victim if forced to come too fast
|
if(!forced_climax) //Don't spam the message to the victim if forced to come too fast
|
||||||
to_chat(src, "<span class='warning'>You need to wait [DisplayTimeText((mb_cd_timer - world.time), TRUE)] before you can do that again!</span>")
|
to_chat(src, "<span class='warning'>You need to wait [DisplayTimeText((mb_cd_timer - world.time), TRUE)] before you can do that again!</span>")
|
||||||
return
|
return
|
||||||
|
|
||||||
if(!canbearoused || !has_dna())
|
if(!client?.prefs.arousable || !has_dna())
|
||||||
return
|
return
|
||||||
if(stat == DEAD)
|
if(stat == DEAD)
|
||||||
if(!forced_climax)
|
if(!forced_climax)
|
||||||
@@ -363,31 +147,6 @@
|
|||||||
return
|
return
|
||||||
if(forced_climax) //Something forced us to cum, this is not a masturbation thing and does not progress to the other checks
|
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)
|
for(var/obj/item/organ/genital/G in internal_organs)
|
||||||
if(!CHECK_BITFIELD(G.genital_flags, CAN_CLIMAX_WITH)) //Skip things like wombs and testicles
|
|
||||||
continue
|
|
||||||
var/mob/living/partner
|
|
||||||
var/check_target
|
|
||||||
var/list/worn_stuff = get_equipped_items()
|
|
||||||
|
|
||||||
if(G.is_exposed(worn_stuff))
|
|
||||||
if(pulling) //Are we pulling someone? Priority target, we can't be making option menus for this, has to be quick
|
|
||||||
if(isliving(pulling)) //Don't fuck objects
|
|
||||||
check_target = pulling
|
|
||||||
if(pulledby && !check_target) //prioritise pulled over pulledby
|
|
||||||
if(isliving(pulledby))
|
|
||||||
check_target = 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
|
mob_climax_outside(G, mb_time = 0) //removed climax timer for sudden, forced orgasms
|
||||||
//Now all genitals that could climax, have.
|
//Now all genitals that could climax, have.
|
||||||
//Since this was a forced climax, we do not need to continue with the other stuff
|
//Since this was a forced climax, we do not need to continue with the other stuff
|
||||||
@@ -398,42 +157,20 @@
|
|||||||
if(stat == UNCONSCIOUS) //No sleep-masturbation, you're unconscious.
|
if(stat == UNCONSCIOUS) //No sleep-masturbation, you're unconscious.
|
||||||
to_chat(src, "<span class='warning'>You must be conscious to do that!</span>")
|
to_chat(src, "<span class='warning'>You must be conscious to do that!</span>")
|
||||||
return
|
return
|
||||||
if(getArousalLoss() < 33) //flat number instead of percentage
|
|
||||||
to_chat(src, "<span class='warning'>You aren't aroused enough for that!</span>")
|
|
||||||
return
|
|
||||||
|
|
||||||
//Ok, now we check what they want to do.
|
//Ok, now we check what they want to do.
|
||||||
var/choice = input(src, "Select sexual activity", "Sexual activity:") as null|anything in list("Masturbate", "Climax alone", "Climax with partner", "Fill container")
|
var/choice = input(src, "Select sexual activity", "Sexual activity:") as null|anything in list("Climax", "Fill container")
|
||||||
if(!choice)
|
if(!choice)
|
||||||
return
|
return
|
||||||
|
|
||||||
switch(choice)
|
switch(choice)
|
||||||
if("Masturbate")
|
if("Climax")
|
||||||
if(!available_rosie_palms())
|
|
||||||
return
|
|
||||||
//We got hands, let's pick an organ
|
|
||||||
var/obj/item/organ/genital/picked_organ = pick_masturbate_genitals()
|
|
||||||
if(picked_organ && available_rosie_palms(TRUE))
|
|
||||||
mob_masturbate(picked_organ)
|
|
||||||
return
|
|
||||||
|
|
||||||
if("Climax alone")
|
|
||||||
if(!available_rosie_palms())
|
if(!available_rosie_palms())
|
||||||
return
|
return
|
||||||
var/obj/item/organ/genital/picked_organ = pick_climax_genitals()
|
var/obj/item/organ/genital/picked_organ = pick_climax_genitals()
|
||||||
if(picked_organ && available_rosie_palms(TRUE))
|
if(picked_organ && available_rosie_palms(TRUE))
|
||||||
mob_climax_outside(picked_organ)
|
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")
|
if("Fill container")
|
||||||
//We'll need hands and no restraints.
|
//We'll need hands and no restraints.
|
||||||
if(!available_rosie_palms(FALSE, /obj/item/reagent_containers))
|
if(!available_rosie_palms(FALSE, /obj/item/reagent_containers))
|
||||||
@@ -447,4 +184,10 @@
|
|||||||
if(fluid_container && available_rosie_palms(TRUE, /obj/item/reagent_containers))
|
if(fluid_container && available_rosie_palms(TRUE, /obj/item/reagent_containers))
|
||||||
mob_fill_container(picked_organ, fluid_container)
|
mob_fill_container(picked_organ, fluid_container)
|
||||||
|
|
||||||
mb_cd_timer = world.time + mb_cd_length
|
mb_cd_timer = world.time + mb_cd_length
|
||||||
|
|
||||||
|
/mob/living/carbon/human/verb/climax_verb()
|
||||||
|
set category = "Arousal"
|
||||||
|
set name = "Climax"
|
||||||
|
set desc = "Lets you choose a couple ways to ejaculate."
|
||||||
|
mob_climax()
|
||||||
|
|||||||
@@ -2,10 +2,11 @@
|
|||||||
color = "#fcccb3"
|
color = "#fcccb3"
|
||||||
w_class = WEIGHT_CLASS_NORMAL
|
w_class = WEIGHT_CLASS_NORMAL
|
||||||
var/shape = "human"
|
var/shape = "human"
|
||||||
var/sensitivity = AROUSAL_START_VALUE
|
var/sensitivity = 1 // wow if this were ever used that'd be cool but it's not but i'm keeping it for my unshit code
|
||||||
var/genital_flags //see citadel_defines.dm
|
var/genital_flags //see citadel_defines.dm
|
||||||
var/masturbation_verb = "masturbate"
|
var/masturbation_verb = "masturbate"
|
||||||
var/orgasm_verb = "cumming" //present continous
|
var/orgasm_verb = "cumming" //present continous
|
||||||
|
var/arousal_verb = "feel aroused"
|
||||||
var/fluid_transfer_factor = 0 //How much would a partner get in them if they climax using this?
|
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/size = 2 //can vary between num or text, just used in icon_state strings
|
||||||
var/fluid_id = null
|
var/fluid_id = null
|
||||||
@@ -14,7 +15,6 @@
|
|||||||
var/fluid_rate = CUM_RATE
|
var/fluid_rate = CUM_RATE
|
||||||
var/fluid_mult = 1
|
var/fluid_mult = 1
|
||||||
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/obj/item/organ/genital/linked_organ
|
||||||
var/linked_organ_slot //used for linking an apparatus' organ to its other half on update_link().
|
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/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.
|
||||||
@@ -85,16 +85,14 @@
|
|||||||
H.update_genitals()
|
H.update_genitals()
|
||||||
|
|
||||||
/mob/living/carbon/verb/toggle_genitals()
|
/mob/living/carbon/verb/toggle_genitals()
|
||||||
set category = "IC"
|
set category = "Arousal"
|
||||||
set name = "Expose/Hide genitals"
|
set name = "Expose/Hide genitals"
|
||||||
set desc = "Allows you to toggle which genitals should show through clothes or not."
|
set desc = "Allows you to toggle which genitals should show through clothes or not."
|
||||||
|
|
||||||
var/list/genital_list = list()
|
var/list/genital_list = list()
|
||||||
for(var/obj/item/organ/O in internal_organs)
|
for(var/obj/item/organ/genital/G in internal_organs)
|
||||||
if(isgenital(O))
|
if(!CHECK_BITFIELD(G.genital_flags, GENITAL_INTERNAL))
|
||||||
var/obj/item/organ/genital/G = O
|
genital_list += G
|
||||||
if(!CHECK_BITFIELD(G.genital_flags, GENITAL_INTERNAL))
|
|
||||||
genital_list += G
|
|
||||||
if(!genital_list.len) //There is nothing to expose
|
if(!genital_list.len) //There is nothing to expose
|
||||||
return
|
return
|
||||||
//Full list of exposable genitals created
|
//Full list of exposable genitals created
|
||||||
@@ -105,6 +103,35 @@
|
|||||||
picked_organ.toggle_visibility(picked_visibility)
|
picked_organ.toggle_visibility(picked_visibility)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
/mob/living/carbon/verb/toggle_arousal_state()
|
||||||
|
set category = "Arousal"
|
||||||
|
set name = "Toggle genital arousal"
|
||||||
|
set desc = "Allows you to toggle which genitals are showing signs of arousal."
|
||||||
|
var/list/genital_list = list()
|
||||||
|
for(var/obj/item/organ/genital/G in internal_organs)
|
||||||
|
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)
|
||||||
|
genital_list += G
|
||||||
|
if(!genital_list.len) //There's nothing that can show arousal
|
||||||
|
return
|
||||||
|
var/obj/item/organ/genital/picked_organ
|
||||||
|
picked_organ = input(src, "Choose which genitalia to toggle arousal on", "Set genital arousal", null) in genital_list
|
||||||
|
if(picked_organ)
|
||||||
|
picked_organ.aroused_state = !picked_organ.aroused_state
|
||||||
|
to_chat(src,"<span class='userlove'>You [picked_organ.arousal_verb].")
|
||||||
|
picked_organ.update_appearance()
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
/obj/item/organ/genital/proc/modify_size(modifier, min = -INFINITY, max = INFINITY)
|
/obj/item/organ/genital/proc/modify_size(modifier, min = -INFINITY, max = INFINITY)
|
||||||
fluid_max_volume += modifier*2.5
|
fluid_max_volume += modifier*2.5
|
||||||
fluid_rate += modifier/10
|
fluid_rate += modifier/10
|
||||||
@@ -233,7 +260,7 @@
|
|||||||
|
|
||||||
//Checks to see if organs are new on the mob, and changes their colours so that they don't get crazy colours.
|
//Checks to see if organs are new on the mob, and changes their colours so that they don't get crazy colours.
|
||||||
/mob/living/carbon/human/proc/emergent_genital_call()
|
/mob/living/carbon/human/proc/emergent_genital_call()
|
||||||
if(!canbearoused)
|
if(!client.prefs.arousable)
|
||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
var/organCheck = locate(/obj/item/organ/genital) in internal_organs
|
var/organCheck = locate(/obj/item/organ/genital) in internal_organs
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
shape = "pair"
|
shape = "pair"
|
||||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_FUID_PRODUCTION
|
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_FUID_PRODUCTION
|
||||||
masturbation_verb = "massage"
|
masturbation_verb = "massage"
|
||||||
|
arousal_verb = "feel very sensitive in your breasts"
|
||||||
orgasm_verb = "leaking"
|
orgasm_verb = "leaking"
|
||||||
fluid_transfer_factor = 0.5
|
fluid_transfer_factor = 0.5
|
||||||
var/static/list/breast_values = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5, "f" = 6, "g" = 7, "h" = 8, "i" = 9, "j" = 10, "k" = 11, "l" = 12, "m" = 13, "n" = 14, "o" = 15, "huge" = 16, "flat" = 0)
|
var/static/list/breast_values = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5, "f" = 6, "g" = 7, "h" = 8, "i" = 9, "j" = 10, "k" = 11, "l" = 12, "m" = 13, "n" = 14, "o" = 15, "huge" = 16, "flat" = 0)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
zone = BODY_ZONE_PRECISE_GROIN
|
zone = BODY_ZONE_PRECISE_GROIN
|
||||||
slot = ORGAN_SLOT_PENIS
|
slot = ORGAN_SLOT_PENIS
|
||||||
masturbation_verb = "stroke"
|
masturbation_verb = "stroke"
|
||||||
|
arousal_verb = "pop a boner"
|
||||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH
|
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH
|
||||||
linked_organ_slot = ORGAN_SLOT_TESTICLES
|
linked_organ_slot = ORGAN_SLOT_TESTICLES
|
||||||
fluid_transfer_factor = 0.5
|
fluid_transfer_factor = 0.5
|
||||||
@@ -26,7 +27,7 @@
|
|||||||
..()
|
..()
|
||||||
|
|
||||||
/obj/item/organ/genital/penis/update_size(modified = FALSE)
|
/obj/item/organ/genital/penis/update_size(modified = FALSE)
|
||||||
if(length < 0)//I don't actually know what round() does to negative numbers, so to be safe!!
|
if(length <= 0)//I don't actually know what round() does to negative numbers, so to be safe!!
|
||||||
if(owner)
|
if(owner)
|
||||||
to_chat(owner, "<span class='warning'>You feel your tallywacker shrinking away from your body as your groin flattens out!</b></span>")
|
to_chat(owner, "<span class='warning'>You feel your tallywacker shrinking away from your body as your groin flattens out!</b></span>")
|
||||||
QDEL_IN(src, 1)
|
QDEL_IN(src, 1)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
size = 1 //There is only 1 size right now
|
size = 1 //There is only 1 size right now
|
||||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH
|
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH
|
||||||
masturbation_verb = "finger"
|
masturbation_verb = "finger"
|
||||||
|
arousal_verb = "feel wet"
|
||||||
fluid_transfer_factor = 0.1 //Yes, some amount is exposed to you, go get your AIDS
|
fluid_transfer_factor = 0.1 //Yes, some amount is exposed to you, go get your AIDS
|
||||||
layer_index = VAGINA_LAYER_INDEX
|
layer_index = VAGINA_LAYER_INDEX
|
||||||
var/cap_length = 8//D E P T H (cap = capacity)
|
var/cap_length = 8//D E P T H (cap = capacity)
|
||||||
|
|||||||
@@ -5,8 +5,7 @@
|
|||||||
name = "dildo"
|
name = "dildo"
|
||||||
desc = "Floppy!"
|
desc = "Floppy!"
|
||||||
icon = 'modular_citadel/icons/obj/genitals/dildo.dmi'
|
icon = 'modular_citadel/icons/obj/genitals/dildo.dmi'
|
||||||
damtype = AROUSAL
|
force = 0
|
||||||
force = 5
|
|
||||||
hitsound = 'sound/weapons/tap.ogg'
|
hitsound = 'sound/weapons/tap.ogg'
|
||||||
throwforce = 0
|
throwforce = 0
|
||||||
icon_state = "dildo_knotted_2"
|
icon_state = "dildo_knotted_2"
|
||||||
|
|||||||
@@ -49,10 +49,9 @@
|
|||||||
if(L[slot_to_string(slot)] < DEFAULT_SLOT_AMT)
|
if(L[slot_to_string(slot)] < DEFAULT_SLOT_AMT)
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
datum/preferences/copy_to(mob/living/carbon/human/character, icon_updates = 1)
|
/datum/preferences/copy_to(mob/living/carbon/human/character, icon_updates = 1)
|
||||||
..()
|
..()
|
||||||
character.give_genitals(TRUE)
|
character.give_genitals(TRUE)
|
||||||
character.flavor_text = features["flavor_text"] //Let's update their flavor_text at least initially
|
character.flavor_text = features["flavor_text"] //Let's update their flavor_text at least initially
|
||||||
character.canbearoused = arousable
|
|
||||||
if(icon_updates)
|
if(icon_updates)
|
||||||
character.update_genitals()
|
character.update_genitals()
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
/obj/item/integrated_circuit/manipulation/electric_stimulator
|
|
||||||
name = "electronic stimulation module"
|
|
||||||
desc = "Used to induce sexual stimulation in a target via electricity."
|
|
||||||
icon_state = "power_relay"
|
|
||||||
extended_desc = "The circuit accepts a reference to a person, as well as a number representing the strength of the shock, and upon activation, attempts to stimulate them to orgasm. The number ranges from -35 to 35, with negative numbers reducing arousal and positive numbers increasing it by that amount."
|
|
||||||
complexity = 15
|
|
||||||
size = 2
|
|
||||||
inputs = list("target" = IC_PINTYPE_REF, "strength" = IC_PINTYPE_NUMBER)
|
|
||||||
outputs = list("arousal gain"=IC_PINTYPE_NUMBER)
|
|
||||||
activators = list("fire" = IC_PINTYPE_PULSE_IN, "on success" = IC_PINTYPE_PULSE_OUT, "on fail" = IC_PINTYPE_PULSE_OUT, "on orgasm" = IC_PINTYPE_PULSE_OUT)
|
|
||||||
spawn_flags = IC_SPAWN_RESEARCH
|
|
||||||
power_draw_per_use = 500
|
|
||||||
cooldown_per_use = 50
|
|
||||||
ext_cooldown = 25
|
|
||||||
|
|
||||||
/obj/item/integrated_circuit/manipulation/electric_stimulator/do_work()
|
|
||||||
set_pin_data(IC_OUTPUT, 1, 0)
|
|
||||||
var/mob/living/M = get_pin_data_as_type(IC_INPUT, 1, /mob/living)
|
|
||||||
if(!check_target(M))
|
|
||||||
return
|
|
||||||
|
|
||||||
var/arousal_gain = CLAMP(get_pin_data(IC_INPUT, 2),-35,35)
|
|
||||||
set_pin_data(IC_OUTPUT, 1, arousal_gain)
|
|
||||||
|
|
||||||
if(ismob(M) && M.canbearoused && arousal_gain != 0)
|
|
||||||
var/orgasm = FALSE
|
|
||||||
if(arousal_gain > 0)
|
|
||||||
if(M.getArousalLoss() >= 100 && ishuman(M) && M.has_dna())
|
|
||||||
var/mob/living/carbon/human/H = M
|
|
||||||
var/orgasm_message = pick("A sharp pulse of electricity pushes you to orgasm!", "You feel a jolt of electricity force you into orgasm!")
|
|
||||||
H.visible_message("<span class='warning'>\The [assembly] electrodes shock [H]!</span>", "<span class='warning'>[orgasm_message]</span>")
|
|
||||||
playsound(src, "sound/effects/light_flicker.ogg", 30, 1)
|
|
||||||
H.mob_climax(forced_climax=TRUE)
|
|
||||||
orgasm = TRUE
|
|
||||||
else
|
|
||||||
M.adjustArousalLoss(arousal_gain)
|
|
||||||
var/stimulate_message = pick("You feel a sharp warming tingle of electricity through your body!", "A burst of arousing electricity flows through your body!")
|
|
||||||
M.visible_message("<span class='warning'>\The [assembly] electrodes shock [M]!</span>", "<span class='warning'>[stimulate_message]</span>")
|
|
||||||
|
|
||||||
else
|
|
||||||
var/stimulate_message = pick("You feel a dull prickle of electricity through your body!", "A burst of dull electricity flows through your body!")
|
|
||||||
M.visible_message("<span class='warning'>\The [assembly] electrodes shock [M]!</span>", "<span class='warning'>[stimulate_message]</span>")
|
|
||||||
M.adjustArousalLoss(arousal_gain)
|
|
||||||
|
|
||||||
playsound(src, "sound/effects/light_flicker.ogg", 30, 1)
|
|
||||||
push_data()
|
|
||||||
activate_pin(2)
|
|
||||||
if(orgasm) activate_pin(4)
|
|
||||||
|
|
||||||
else
|
|
||||||
visible_message("<span class='warning'>\The [assembly] electrodes fail to shock [M]!</span>")
|
|
||||||
push_data()
|
|
||||||
activate_pin(3)
|
|
||||||
@@ -312,8 +312,6 @@ Creating a chem with a low purity will make you permanently fall in love with so
|
|||||||
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times people have bonded")
|
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times people have bonded")
|
||||||
else
|
else
|
||||||
if(get_dist(M, love) < 8)
|
if(get_dist(M, love) < 8)
|
||||||
if(HAS_TRAIT(M, TRAIT_NYMPHO)) //Add this back when merged/updated.
|
|
||||||
M.adjustArousalLoss(5)
|
|
||||||
var/message = "[(lewd?"I'm next to my crush..! Eee!":"I'm making friends with [love]!")]"
|
var/message = "[(lewd?"I'm next to my crush..! Eee!":"I'm making friends with [love]!")]"
|
||||||
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "InLove", /datum/mood_event/InLove, message)
|
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "InLove", /datum/mood_event/InLove, message)
|
||||||
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "MissingLove")
|
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "MissingLove")
|
||||||
|
|||||||
@@ -100,14 +100,18 @@
|
|||||||
color = "#FFADFF"//PINK, rgb(255, 173, 255)
|
color = "#FFADFF"//PINK, rgb(255, 173, 255)
|
||||||
|
|
||||||
/datum/reagent/drug/aphrodisiac/on_mob_life(mob/living/M)
|
/datum/reagent/drug/aphrodisiac/on_mob_life(mob/living/M)
|
||||||
if(M && M.canbearoused && !(M.client?.prefs.cit_toggles & NO_APHRO))
|
if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO))
|
||||||
if(prob(33))
|
if((prob(min(current_cycle/2,5))))
|
||||||
M.adjustArousalLoss(2)
|
|
||||||
if(prob(5))
|
|
||||||
M.emote(pick("moan","blush"))
|
M.emote(pick("moan","blush"))
|
||||||
if(prob(5))
|
if(prob(min(current_cycle/4,10)))
|
||||||
var/aroused_message = pick("You feel frisky.", "You're having trouble suppressing your urges.", "You feel in the mood.")
|
var/aroused_message = pick("You feel frisky.", "You're having trouble suppressing your urges.", "You feel in the mood.")
|
||||||
to_chat(M, "<span class='userlove'>[aroused_message]</span>")
|
to_chat(M, "<span class='userlove'>[aroused_message]</span>")
|
||||||
|
if(ishuman(M))
|
||||||
|
var/mob/living/carbon/human/H = M
|
||||||
|
for(var/obj/item/organ/genital/G in H.internal_organs)
|
||||||
|
if(!G.aroused_state && prob(current_cycle))
|
||||||
|
G.aroused_state = TRUE
|
||||||
|
to_chat(M, "<span class='userlove'>You suddenly [G.arousal_verb]!")
|
||||||
..()
|
..()
|
||||||
|
|
||||||
/datum/reagent/drug/aphrodisiacplus
|
/datum/reagent/drug/aphrodisiacplus
|
||||||
@@ -122,21 +126,26 @@
|
|||||||
overdose_threshold = 20
|
overdose_threshold = 20
|
||||||
|
|
||||||
/datum/reagent/drug/aphrodisiacplus/on_mob_life(mob/living/M)
|
/datum/reagent/drug/aphrodisiacplus/on_mob_life(mob/living/M)
|
||||||
if(M && M.canbearoused && !(M.client?.prefs.cit_toggles & NO_APHRO))
|
if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO))
|
||||||
if(prob(33))
|
|
||||||
M.adjustArousalLoss(6)//not quite six times as powerful, but still considerably more powerful.
|
|
||||||
if(prob(5))
|
if(prob(5))
|
||||||
if(M.getArousalLoss() > 75)
|
if(prob(current_cycle))
|
||||||
M.say(pick("Hnnnnngghh...", "Ohh...", "Mmnnn..."))
|
M.say(pick("Hnnnnngghh...", "Ohh...", "Mmnnn..."))
|
||||||
else
|
else
|
||||||
M.emote(pick("moan","blush"))
|
M.emote(pick("moan","blush"))
|
||||||
if(prob(5))
|
if(prob(5))
|
||||||
var/aroused_message
|
var/aroused_message
|
||||||
if(M.getArousalLoss() > 90)
|
if(current_cycle>25)
|
||||||
aroused_message = pick("You need to fuck someone!", "You're bursting with sexual tension!", "You can't get sex off your mind!")
|
aroused_message = pick("You need to fuck someone!", "You're bursting with sexual tension!", "You can't get sex off your mind!")
|
||||||
else
|
else
|
||||||
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.")
|
aroused_message = pick("You feel a bit hot.", "You feel strong sexual urges.", "You feel in the mood.", "You're ready to go down on someone.")
|
||||||
to_chat(M, "<span class='userlove'>[aroused_message]</span>")
|
to_chat(M, "<span class='userlove'>[aroused_message]</span>")
|
||||||
|
REMOVE_TRAIT(M,TRAIT_NEVERBONER,"aphro")
|
||||||
|
if(ishuman(M))
|
||||||
|
var/mob/living/carbon/human/H = M
|
||||||
|
for(var/obj/item/organ/genital/G in H.internal_organs)
|
||||||
|
if(!G.aroused_state)
|
||||||
|
G.aroused_state = TRUE
|
||||||
|
to_chat(M, "<span class='userlove'>You suddenly [G.arousal_verb]!")
|
||||||
..()
|
..()
|
||||||
|
|
||||||
/datum/reagent/drug/aphrodisiacplus/addiction_act_stage2(mob/living/M)
|
/datum/reagent/drug/aphrodisiacplus/addiction_act_stage2(mob/living/M)
|
||||||
@@ -154,15 +163,11 @@
|
|||||||
..()
|
..()
|
||||||
|
|
||||||
/datum/reagent/drug/aphrodisiacplus/overdose_process(mob/living/M)
|
/datum/reagent/drug/aphrodisiacplus/overdose_process(mob/living/M)
|
||||||
if(M && M.canbearoused && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(33))
|
if(M && M.client?.prefs.arousable && !(M.client?.prefs.cit_toggles & NO_APHRO) && prob(33))
|
||||||
if(prob(5) && M.getArousalLoss() >= 100 && ishuman(M) && M.has_dna())
|
if(prob(5) && ishuman(M) && M.has_dna())
|
||||||
if(prob(5)) //Less spam
|
if(prob(5)) //Less spam
|
||||||
to_chat(M, "<span class='love'>Your libido is going haywire!</span>")
|
to_chat(M, "<span class='love'>Your libido is going haywire!</span>")
|
||||||
if(M.min_arousal < 50)
|
ADD_TRAIT(M,TRAIT_PERMABONER,"aphro")
|
||||||
M.min_arousal += 1
|
|
||||||
if(M.min_arousal < M.max_arousal)
|
|
||||||
M.min_arousal += 1
|
|
||||||
M.adjustArousalLoss(2)
|
|
||||||
..()
|
..()
|
||||||
|
|
||||||
/datum/reagent/drug/anaphrodisiac
|
/datum/reagent/drug/anaphrodisiac
|
||||||
@@ -176,8 +181,16 @@
|
|||||||
reagent_state = SOLID
|
reagent_state = SOLID
|
||||||
|
|
||||||
/datum/reagent/drug/anaphrodisiac/on_mob_life(mob/living/M)
|
/datum/reagent/drug/anaphrodisiac/on_mob_life(mob/living/M)
|
||||||
if(M && M.canbearoused && prob(33))
|
if(M && M.client?.prefs.arousable && prob(16))
|
||||||
M.adjustArousalLoss(-2)
|
if(ishuman(M))
|
||||||
|
var/unboner = FALSE
|
||||||
|
var/mob/living/carbon/human/H = M
|
||||||
|
for(var/obj/item/organ/genital/G in H.internal_organs)
|
||||||
|
if(G.aroused_state)
|
||||||
|
G.aroused_state = FALSE
|
||||||
|
unboner = TRUE
|
||||||
|
if(unboner)
|
||||||
|
to_chat(M, "<span class='notice'>You no longer feel aroused.")
|
||||||
..()
|
..()
|
||||||
|
|
||||||
/datum/reagent/drug/anaphrodisiacplus
|
/datum/reagent/drug/anaphrodisiacplus
|
||||||
@@ -190,17 +203,22 @@
|
|||||||
overdose_threshold = 20
|
overdose_threshold = 20
|
||||||
|
|
||||||
/datum/reagent/drug/anaphrodisiacplus/on_mob_life(mob/living/M)
|
/datum/reagent/drug/anaphrodisiacplus/on_mob_life(mob/living/M)
|
||||||
if(M && M.canbearoused && prob(33))
|
if(M && M.client?.prefs.arousable)
|
||||||
M.adjustArousalLoss(-4)
|
REMOVE_TRAIT(M,TRAIT_PERMABONER,"aphro")
|
||||||
|
if(ishuman(M))
|
||||||
|
var/unboner = FALSE
|
||||||
|
var/mob/living/carbon/human/H = M
|
||||||
|
for(var/obj/item/organ/genital/G in H.internal_organs)
|
||||||
|
if(G.aroused_state)
|
||||||
|
G.aroused_state = FALSE
|
||||||
|
unboner = TRUE
|
||||||
|
if(unboner)
|
||||||
|
to_chat(M, "<span class='notice'>You no longer feel aroused.")
|
||||||
..()
|
..()
|
||||||
|
|
||||||
/datum/reagent/drug/anaphrodisiacplus/overdose_process(mob/living/M)
|
/datum/reagent/drug/anaphrodisiacplus/overdose_process(mob/living/M)
|
||||||
if(M && M.canbearoused && prob(33))
|
if(M && M.client?.prefs.arousable && prob(5))
|
||||||
if(M.min_arousal > 0)
|
ADD_TRAIT(M,TRAIT_NEVERBONER,"aphro")
|
||||||
M.min_arousal -= 1
|
|
||||||
if(M.min_arousal > 50)
|
|
||||||
M.min_arousal -= 1
|
|
||||||
M.adjustArousalLoss(-2)
|
|
||||||
..()
|
..()
|
||||||
|
|
||||||
//recipes
|
//recipes
|
||||||
|
|||||||
@@ -3126,7 +3126,6 @@
|
|||||||
#include "modular_citadel\code\modules\custom_loadout\custom_items.dm"
|
#include "modular_citadel\code\modules\custom_loadout\custom_items.dm"
|
||||||
#include "modular_citadel\code\modules\custom_loadout\load_to_mob.dm"
|
#include "modular_citadel\code\modules\custom_loadout\load_to_mob.dm"
|
||||||
#include "modular_citadel\code\modules\custom_loadout\read_from_file.dm"
|
#include "modular_citadel\code\modules\custom_loadout\read_from_file.dm"
|
||||||
#include "modular_citadel\code\modules\integrated_electronics\subtypes\manipulation.dm"
|
|
||||||
#include "modular_citadel\code\modules\mentor\follow.dm"
|
#include "modular_citadel\code\modules\mentor\follow.dm"
|
||||||
#include "modular_citadel\code\modules\mentor\mentor.dm"
|
#include "modular_citadel\code\modules\mentor\mentor.dm"
|
||||||
#include "modular_citadel\code\modules\mentor\mentor_memo.dm"
|
#include "modular_citadel\code\modules\mentor\mentor_memo.dm"
|
||||||
|
|||||||
Reference in New Issue
Block a user