Merge branch 'master' into Yote
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
return
|
||||
|
||||
to_chat(M, "<span class='warning bold reallybig'>Man up, and deal with it.</span><br><span class='warning big'>Move on.</span>")
|
||||
M.playsound_local(M, 'modular_citadel/sound/misc/manup.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
M.playsound_local(M, 'sound/voice/manup.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
|
||||
log_admin("Man up: [key_name(usr)] told [key_name(M)] to man up")
|
||||
var/message = "<span class='adminnotice'>[key_name_admin(usr)] told [key_name_admin(M)] to man up.</span>"
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
to_chat(world, "<span class='warning bold reallybig'>Man up, and deal with it.</span><br><span class='warning big'>Move on.</span>")
|
||||
for(var/mob/M in GLOB.player_list)
|
||||
M.playsound_local(M, 'modular_citadel/sound/misc/manup.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
M.playsound_local(M, 'sound/voice/manup.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
|
||||
log_admin("Man up global: [key_name(usr)] told everybody to man up")
|
||||
message_admins("<span class='adminnotice'>[key_name_admin(usr)] told everybody to man up.</span>")
|
||||
|
||||
@@ -19,11 +19,6 @@
|
||||
var/hidden_undershirt = FALSE
|
||||
var/hidden_socks = FALSE
|
||||
|
||||
/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
|
||||
@@ -35,60 +30,51 @@
|
||||
//Mob procs
|
||||
/mob/living/carbon/human/proc/underwear_toggle()
|
||||
set name = "Toggle undergarments"
|
||||
set category = "Object"
|
||||
if(ishuman(src))
|
||||
var/mob/living/carbon/human/humz = src
|
||||
var/confirm = input(src, "Select what part of your form to alter", "Undergarment Toggling", "Cancel") in list("Top", "Bottom", "Socks", "All", "Cancel")
|
||||
if(confirm == "Top")
|
||||
humz.hidden_undershirt = !humz.hidden_undershirt
|
||||
set category = "IC"
|
||||
|
||||
if(confirm == "Bottom")
|
||||
humz.hidden_underwear = !humz.hidden_underwear
|
||||
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)
|
||||
return
|
||||
if(confirm == "Top")
|
||||
hidden_undershirt = !hidden_undershirt
|
||||
|
||||
if(confirm == "Socks")
|
||||
humz.hidden_socks = !humz.hidden_socks
|
||||
if(confirm == "Bottom")
|
||||
hidden_underwear = !hidden_underwear
|
||||
|
||||
if(confirm == "All")
|
||||
humz.hidden_undershirt = !humz.hidden_undershirt
|
||||
humz.hidden_underwear = !humz.hidden_underwear
|
||||
humz.hidden_socks = !humz.hidden_socks
|
||||
if(confirm == "Socks")
|
||||
hidden_socks = !hidden_socks
|
||||
|
||||
if(confirm == "Cancel")
|
||||
return
|
||||
src.update_body()
|
||||
if(confirm == "All")
|
||||
var/on_off = (hidden_undershirt || hidden_underwear || hidden_socks) ? FALSE : TRUE
|
||||
hidden_undershirt = on_off
|
||||
hidden_underwear = on_off
|
||||
hidden_socks = on_off
|
||||
|
||||
else
|
||||
to_chat(src, "Humans only. How the fuck did you get this verb anyway.")
|
||||
update_body()
|
||||
|
||||
/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) && getArousalLoss() < max_arousal)//Totally stolen from breathing code. Do this every 36 ticks.
|
||||
adjustArousalLoss(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(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)
|
||||
adjustArousalLoss((amt_nude * watchers) + S.arousal_gain_rate)
|
||||
/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
|
||||
@@ -138,8 +124,6 @@
|
||||
S = GLOB.breasts_shapes_list[G.shape]
|
||||
if(S?.alt_aroused)
|
||||
G.aroused_state = isPercentAroused(G.aroused_amount)
|
||||
if(getArousalLoss() >= ((max_arousal / 100) * 33))
|
||||
G.aroused_state = TRUE
|
||||
else
|
||||
G.aroused_state = FALSE
|
||||
G.update_appearance()
|
||||
@@ -147,54 +131,16 @@
|
||||
/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())
|
||||
if(!client || !(hud_used?.arousal))
|
||||
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(getArousalLoss() == max_arousal)
|
||||
hud_used.arousal.icon_state = "arousal100"
|
||||
return TRUE
|
||||
if(getArousalLoss() >= (max_arousal / 100) * 90)//M O D U L A R , W O W
|
||||
hud_used.arousal.icon_state = "arousal90"
|
||||
return TRUE
|
||||
if(getArousalLoss() >= (max_arousal / 100) * 80)//M O D U L A R , W O W
|
||||
hud_used.arousal.icon_state = "arousal80"
|
||||
return TRUE
|
||||
if(getArousalLoss() >= (max_arousal / 100) * 70)//M O D U L A R , W O W
|
||||
hud_used.arousal.icon_state = "arousal70"
|
||||
return TRUE
|
||||
if(getArousalLoss() >= (max_arousal / 100) * 60)//M O D U L A R , W O W
|
||||
hud_used.arousal.icon_state = "arousal60"
|
||||
return TRUE
|
||||
if(getArousalLoss() >= (max_arousal / 100) * 50)//M O D U L A R , W O W
|
||||
hud_used.arousal.icon_state = "arousal50"
|
||||
return TRUE
|
||||
if(getArousalLoss() >= (max_arousal / 100) * 40)//M O D U L A R , W O W
|
||||
hud_used.arousal.icon_state = "arousal40"
|
||||
return TRUE
|
||||
if(getArousalLoss() >= (max_arousal / 100) * 30)//M O D U L A R , W O W
|
||||
hud_used.arousal.icon_state = "arousal30"
|
||||
return TRUE
|
||||
if(getArousalLoss() >= (max_arousal / 100) * 20)//M O D U L A R , W O W
|
||||
hud_used.arousal.icon_state = "arousal10"
|
||||
return TRUE
|
||||
if(getArousalLoss() >= (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"
|
||||
var/value = FLOOR(getPercentAroused(), 10)
|
||||
hud_used.arousal.icon_state = "arousal[value]"
|
||||
return TRUE
|
||||
|
||||
/obj/screen/arousal
|
||||
name = "arousal"
|
||||
@@ -213,7 +159,6 @@
|
||||
to_chat(M, "<span class='warning'>Arousal is disabled. Feature is unavailable.</span>")
|
||||
|
||||
|
||||
|
||||
/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"
|
||||
@@ -221,225 +166,187 @@
|
||||
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("<span class='danger'>[src] starts masturbating!</span>", \
|
||||
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))
|
||||
src.visible_message("<span class='danger'>[src] relieves [p_them()]self!</span>", \
|
||||
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.
|
||||
if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION))
|
||||
. = reagents
|
||||
else
|
||||
if(linked_organ)
|
||||
. = linked_organ.reagents
|
||||
if(!. && !silent)
|
||||
to_chat(H, "<span class='warning'>Your [name] is unable to produce it's own fluids, it's missing the organs for it.</span>")
|
||||
|
||||
/mob/living/carbon/human/proc/do_climax(datum/reagents/R, atom/target, obj/item/organ/genital/G, spill = TRUE)
|
||||
if(!G)
|
||||
return
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
|
||||
setArousalLoss(min_arousal)
|
||||
if(!target || !R)
|
||||
return
|
||||
var/turfing = isturf(target)
|
||||
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))
|
||||
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/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, "<span class='warning'>Your [G.name] is unable to produce it's own fluids, it's missing the organs for it.</span>")
|
||||
return
|
||||
fluid_source = G.linked_organ.reagents
|
||||
total_fluids = fluid_source.total_volume
|
||||
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)
|
||||
src.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>", \
|
||||
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))
|
||||
if(total_fluids > 5)
|
||||
fluid_source.reaction(src.loc, TOUCH, 1, 0)
|
||||
fluid_source.clear_reagents()
|
||||
src.visible_message("<span class='love'>[src] orgasms, cumming[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""]!</span>", \
|
||||
"<span class='userlove'>You cum[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""].</span>", \
|
||||
"<span class='userlove'>You have relieved yourself.</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
|
||||
if(G.can_climax)
|
||||
setArousalLoss(min_arousal)
|
||||
|
||||
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
|
||||
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("<span class='danger'>[src] shudders, their [G.name] unable to cum.</span>", \
|
||||
"<span class='userdanger'>Your [G.name] cannot cum, giving no relief.</span>", \
|
||||
var/datum/reagents/fluid_source = G.climaxable(src, TRUE)
|
||||
if(!fluid_source)
|
||||
visible_message("<span class='danger'>[src] shudders, their [G.name] unable to cum.</span>", \
|
||||
"<span class='userdanger'>Your [G.name] cannot cum, giving no relief.</span>")
|
||||
else
|
||||
total_fluids = fluid_source.total_volume
|
||||
if(mb_time) //as long as it's not instant, give a warning
|
||||
src.visible_message("<span class='love'>[src] looks like they're about to cum.</span>", \
|
||||
"<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))
|
||||
if(total_fluids > 5)
|
||||
fluid_source.reaction(src.loc, TOUCH, 1, 0)
|
||||
fluid_source.clear_reagents()
|
||||
src.visible_message("<span class='love'>[src] orgasms[istype(src.loc, /turf/open/floor) ? ", spilling onto [src.loc]" : ""], using [p_their()] [G.name]!</span>", \
|
||||
"<span class='userlove'>You climax[istype(src.loc, /turf/open/floor) ? ", spilling onto [src.loc]" : ""] with your [G.name].</span>", \
|
||||
"<span class='userlove'>You climax using your [G.name].</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
|
||||
if(G.can_climax)
|
||||
setArousalLoss(min_arousal)
|
||||
|
||||
return
|
||||
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>", \
|
||||
"<span class='userlove'>You feel yourself about to orgasm.</span>")
|
||||
if(!do_after(src, mb_time, target = src) || !G.climaxable(src, TRUE))
|
||||
return
|
||||
visible_message("<span class='love'>[src] orgasms[isturf(loc) ? " onto [loc]" : ""], using [p_their()] [G.name]!</span>", \
|
||||
"<span class='userlove'>You climax[isturf(loc) ? " onto [loc]" : ""] with your [G.name].</span>")
|
||||
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/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, "<span class='warning'>Your [G.name] is unable to produce it's own fluids, it's missing the organs for it.</span>")
|
||||
return
|
||||
fluid_source = G.linked_organ.reagents
|
||||
total_fluids = fluid_source.total_volume
|
||||
var/datum/reagents/fluid_source = G.climaxable(src)
|
||||
if(!fluid_source)
|
||||
return
|
||||
if(mb_time) //Skip warning if this is an instant climax.
|
||||
src.visible_message("<span class='love'>[src] is about to climax with [L]!</span>", \
|
||||
"<span class='userlove'>You're about to climax with [L]!</span>", \
|
||||
"<span class='userlove'>You're preparing to climax with someone!</span>")
|
||||
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)
|
||||
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 > 5)
|
||||
fluid_source.reaction(L.loc, TOUCH, 1, 0)
|
||||
fluid_source.clear_reagents()
|
||||
src.visible_message("<span class='love'>[src] climaxes with [L][spillage ? ", overflowing and spilling":""], using [p_their()] [G.name]!</span>", \
|
||||
"<span class='userlove'>You orgasm with [L][spillage ? ", spilling out of them":""], using your [G.name].</span>", \
|
||||
"<span class='userlove'>You have climaxed with someone[spillage ? ", spilling out of them":""], using your [G.name].</span>")
|
||||
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)
|
||||
setArousalLoss(min_arousal)
|
||||
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
|
||||
if(do_after(src, mb_time, target = src) && in_range(src, L))
|
||||
fluid_source.trans_to(L, total_fluids)
|
||||
total_fluids = 0
|
||||
src.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>", \
|
||||
"<span class='userlove'>You have climaxed inside someone, your [G.name] spilling nothing.</span>")
|
||||
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)
|
||||
setArousalLoss(min_arousal)
|
||||
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
|
||||
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, "<span class='warning'>Your [G.name] is unable to produce it's own fluids, it's missing the organs for it.</span>")
|
||||
var/datum/reagents/fluid_source = G.climaxable(src)
|
||||
if(!fluid_source)
|
||||
return
|
||||
if(mb_time)
|
||||
visible_message("<span class='love'>[src] starts to [G.masturbation_verb] their [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))
|
||||
return
|
||||
fluid_source = G.linked_organ.reagents
|
||||
total_fluids = fluid_source.total_volume
|
||||
visible_message("<span class='love'>[src] uses [p_their()] [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)
|
||||
|
||||
//if(!container) //Something weird happened
|
||||
// to_chat(src, "<span class='warning'>You need a container to do this!</span>")
|
||||
// return
|
||||
|
||||
src.visible_message("<span class='love'>[src] starts to [G.masturbation_verb] their [G.name] over [container].</span>", \
|
||||
"<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 something.</span>")
|
||||
if(do_after(src, mb_time, target = src) && in_range(src, container))
|
||||
fluid_source.trans_to(container, total_fluids)
|
||||
src.visible_message("<span class='love'>[src] uses [p_their()] [G.name] to fill [container]!</span>", \
|
||||
"<span class='userlove'>You used your [G.name] to fill [container].</span>", \
|
||||
"<span class='userlove'>You have relieved some pressure.</span>")
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm)
|
||||
if(G.can_climax)
|
||||
setArousalLoss(min_arousal)
|
||||
|
||||
/mob/living/carbon/human/proc/pick_masturbate_genitals()
|
||||
var/obj/item/organ/genital/ret_organ
|
||||
var/list/genitals_list = list()
|
||||
/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(G.can_masturbate_with) //filter out what you can't masturbate with
|
||||
if(G.is_exposed(worn_stuff)) //Nude or through_clothing
|
||||
genitals_list += G
|
||||
if(genitals_list.len)
|
||||
ret_organ = input(src, "with what?", "Masturbate", null) as null|obj in genitals_list
|
||||
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
|
||||
return null //error stuff
|
||||
else if(!silent)
|
||||
to_chat(src, "<span class='warning'>You cannot masturbate without available genitals.</span>")
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/pick_climax_genitals()
|
||||
var/obj/item/organ/genital/ret_organ
|
||||
var/list/genitals_list = list()
|
||||
/mob/living/carbon/human/proc/pick_climax_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(G.can_climax) //filter out what you can't masturbate with
|
||||
if(G.is_exposed(worn_stuff)) //Nude or through_clothing
|
||||
genitals_list += G
|
||||
if(genitals_list.len)
|
||||
ret_organ = input(src, "with what?", "Climax", null) as null|obj in genitals_list
|
||||
if(CHECK_BITFIELD(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
|
||||
return ret_organ
|
||||
return null //error stuff
|
||||
else if(!silent)
|
||||
to_chat(src, "<span class='warning'>You cannot climax without available genitals.</span>")
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/pick_partner()
|
||||
/mob/living/carbon/human/proc/pick_partner(silent = FALSE)
|
||||
var/list/partners = list()
|
||||
if(src.pulling)
|
||||
partners += src.pulling //Yes, even objects for now
|
||||
if(src.pulledby)
|
||||
partners += src.pulledby
|
||||
if(pulling)
|
||||
partners += pulling
|
||||
if(pulledby)
|
||||
partners += 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
|
||||
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)
|
||||
return null //No one left.
|
||||
return input(src, "With whom?", "Sexual partner", null) in partners //pick one, default to null
|
||||
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()
|
||||
var/obj/item/reagent_containers/SC = null
|
||||
/mob/living/carbon/human/proc/pick_climax_container(silent = FALSE)
|
||||
var/list/containers_list = list()
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
if(containers_list.len)
|
||||
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.
|
||||
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, "<span class='warning'>You cannot do this without an appropriate container.</span>")
|
||||
|
||||
/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, "<span class='warning'>You can't do that while restrained!</span>")
|
||||
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, "<span class='warning'>You need at least one free arm.</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
//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
|
||||
@@ -447,156 +354,97 @@
|
||||
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>")
|
||||
return
|
||||
mb_cd_timer = (world.time + mb_cd_length)
|
||||
|
||||
|
||||
if(canbearoused && has_dna())
|
||||
if(stat==2)
|
||||
if(!canbearoused || !has_dna())
|
||||
return
|
||||
if(stat == DEAD)
|
||||
if(!forced_climax)
|
||||
to_chat(src, "<span class='warning'>You can't do that while dead!</span>")
|
||||
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()
|
||||
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/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(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.
|
||||
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
|
||||
//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.
|
||||
|
||||
if(stat==1) //No sleep-masturbation, you're unconscious.
|
||||
to_chat(src, "<span class='warning'>You must be conscious to do that!</span>")
|
||||
return
|
||||
if(getArousalLoss() < 33) //flat number instead of percentage
|
||||
to_chat(src, "<span class='warning'>You aren't aroused enough for that!</span>")
|
||||
return
|
||||
if(stat == UNCONSCIOUS) //No sleep-masturbation, you're unconscious.
|
||||
to_chat(src, "<span class='warning'>You must be conscious to do that!</span>")
|
||||
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.
|
||||
var/choice = input(src, "Select sexual activity", "Sexual activity:") in list("Masturbate", "Climax alone", "Climax with partner", "Fill container")
|
||||
//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")
|
||||
if(!choice)
|
||||
return
|
||||
|
||||
switch(choice)
|
||||
if("Masturbate")
|
||||
if(restrained(TRUE)) //TRUE ignores grabs
|
||||
to_chat(src, "<span class='warning'>You can't do that while restrained!</span>")
|
||||
return
|
||||
var/free_hands = get_num_arms()
|
||||
if(!free_hands)
|
||||
to_chat(src, "<span class='warning'>You need at least one free arm.</span>")
|
||||
return
|
||||
for(var/helditem in held_items)//how many hands are free
|
||||
if(isobj(helditem))
|
||||
free_hands--
|
||||
if(free_hands <= 0)
|
||||
to_chat(src, "<span class='warning'>You're holding too many things.</span>")
|
||||
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, "<span class='warning'>You cannot masturbate without choosing genitals.</span>")
|
||||
return
|
||||
switch(choice)
|
||||
if("Masturbate")
|
||||
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(restrained(TRUE)) //TRUE ignores grabs
|
||||
to_chat(src, "<span class='warning'>You can't do that while restrained!</span>")
|
||||
return
|
||||
var/free_hands = get_num_arms()
|
||||
if(!free_hands)
|
||||
to_chat(src, "<span class='warning'>You need at least one free arm.</span>")
|
||||
return
|
||||
for(var/helditem in held_items)//how many hands are free
|
||||
if(isobj(helditem))
|
||||
free_hands--
|
||||
if(free_hands <= 0)
|
||||
to_chat(src, "<span class='warning'>You're holding too many things.</span>")
|
||||
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, "<span class='warning'>You cannot climax without choosing genitals.</span>")
|
||||
return
|
||||
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
|
||||
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 anything in list("Yes", "No")
|
||||
if(spillage == "Yes")
|
||||
mob_climax_partner(picked_organ, partner, TRUE)
|
||||
else
|
||||
mob_climax_partner(picked_organ, partner, FALSE)
|
||||
return
|
||||
else
|
||||
to_chat(src, "<span class='warning'>You cannot do this alone.</span>")
|
||||
return
|
||||
else //They either lack organs that can masturbate, or they didn't pick one.
|
||||
to_chat(src, "<span class='warning'>You cannot climax without choosing genitals.</span>")
|
||||
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 = 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(restrained(TRUE)) //TRUE ignores grabs
|
||||
to_chat(src, "<span class='warning'>You can't do that while restrained!</span>")
|
||||
return
|
||||
var/free_hands = get_num_arms()
|
||||
if(!free_hands)
|
||||
to_chat(src, "<span class='warning'>You need at least one free arm.</span>")
|
||||
return
|
||||
for(var/helditem in held_items)//how many hands are free
|
||||
if(isobj(helditem))
|
||||
free_hands--
|
||||
if(free_hands <= 0)
|
||||
to_chat(src, "<span class='warning'>You're holding too many things.</span>")
|
||||
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, "<span class='warning'>You cannot do this without anything to fill.</span>")
|
||||
return
|
||||
else //They either lack organs that can climax, or they didn't pick one.
|
||||
to_chat(src, "<span class='warning'>You cannot fill anything without choosing genitals.</span>")
|
||||
return
|
||||
else //Somehow another option was taken, maybe something interrupted the selection or it was cancelled
|
||||
return //Just end it in that case.
|
||||
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
|
||||
@@ -0,0 +1,339 @@
|
||||
/obj/item/organ/genital
|
||||
color = "#fcccb3"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
var/shape = "human"
|
||||
var/sensitivity = AROUSAL_START_VALUE
|
||||
var/genital_flags //see citadel_defines.dm
|
||||
var/masturbation_verb = "masturbate"
|
||||
var/orgasm_verb = "cumming" //present continous
|
||||
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/fluid_id = null
|
||||
var/fluid_max_volume = 50
|
||||
var/fluid_efficiency = 1
|
||||
var/fluid_rate = CUM_RATE
|
||||
var/fluid_mult = 1
|
||||
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.
|
||||
|
||||
/obj/item/organ/genital/Initialize(mapload, mob/living/carbon/human/H)
|
||||
. = ..()
|
||||
if(fluid_id)
|
||||
create_reagents(fluid_max_volume)
|
||||
if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION))
|
||||
reagents.add_reagent(fluid_id, fluid_max_volume)
|
||||
if(H)
|
||||
get_features(H)
|
||||
Insert(H)
|
||||
else
|
||||
update()
|
||||
|
||||
/obj/item/organ/genital/Destroy()
|
||||
if(linked_organ)
|
||||
update_link(TRUE)//this should remove any other links it has
|
||||
if(owner)
|
||||
Remove(owner, TRUE)//this should remove references to it, so it can be GCd correctly
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/genital/proc/update(removing = FALSE)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
update_size()
|
||||
update_appearance()
|
||||
if(linked_organ_slot || (linked_organ && removing))
|
||||
update_link(removing)
|
||||
|
||||
//exposure and through-clothing code
|
||||
/mob/living/carbon
|
||||
var/list/exposed_genitals = list() //Keeping track of them so we don't have to iterate through every genitalia and see if exposed
|
||||
|
||||
/obj/item/organ/genital/proc/is_exposed()
|
||||
if(!owner || CHECK_BITFIELD(genital_flags, GENITAL_INTERNAL) || CHECK_BITFIELD(genital_flags, GENITAL_HIDDEN))
|
||||
return FALSE
|
||||
if(CHECK_BITFIELD(genital_flags, GENITAL_THROUGH_CLOTHES))
|
||||
return TRUE
|
||||
|
||||
switch(zone) //update as more genitals are added
|
||||
if(BODY_ZONE_CHEST)
|
||||
return owner.is_chest_exposed()
|
||||
if(BODY_ZONE_PRECISE_GROIN)
|
||||
return owner.is_groin_exposed()
|
||||
|
||||
/obj/item/organ/genital/proc/toggle_visibility(visibility)
|
||||
switch(visibility)
|
||||
if("Always visible")
|
||||
ENABLE_BITFIELD(genital_flags, GENITAL_THROUGH_CLOTHES)
|
||||
DISABLE_BITFIELD(genital_flags, GENITAL_HIDDEN)
|
||||
if(!(src in owner.exposed_genitals))
|
||||
owner.exposed_genitals += src
|
||||
if("Hidden by clothes")
|
||||
DISABLE_BITFIELD(genital_flags, GENITAL_THROUGH_CLOTHES)
|
||||
DISABLE_BITFIELD(genital_flags, GENITAL_HIDDEN)
|
||||
if(src in owner.exposed_genitals)
|
||||
owner.exposed_genitals -= src
|
||||
if("Always hidden")
|
||||
DISABLE_BITFIELD(genital_flags, GENITAL_THROUGH_CLOTHES)
|
||||
ENABLE_BITFIELD(genital_flags, GENITAL_HIDDEN)
|
||||
if(src in owner.exposed_genitals)
|
||||
owner.exposed_genitals -= src
|
||||
|
||||
if(ishuman(owner)) //recast to use update genitals proc
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.update_genitals()
|
||||
|
||||
/mob/living/carbon/verb/toggle_genitals()
|
||||
set category = "IC"
|
||||
set name = "Expose/Hide genitals"
|
||||
set desc = "Allows you to toggle which genitals should show through clothes or not."
|
||||
|
||||
var/list/genital_list = list()
|
||||
for(var/obj/item/organ/O in internal_organs)
|
||||
if(isgenital(O))
|
||||
var/obj/item/organ/genital/G = O
|
||||
if(!CHECK_BITFIELD(G.genital_flags, GENITAL_INTERNAL))
|
||||
genital_list += G
|
||||
if(!genital_list.len) //There is nothing to expose
|
||||
return
|
||||
//Full list of exposable genitals created
|
||||
var/obj/item/organ/genital/picked_organ
|
||||
picked_organ = input(src, "Choose which genitalia to expose/hide", "Expose/Hide genitals", null) in genital_list
|
||||
if(picked_organ)
|
||||
var/picked_visibility = input(src, "Choose visibility setting", "Expose/Hide genitals", "Hidden by clothes") in list("Always visible", "Hidden by clothes", "Always hidden")
|
||||
picked_organ.toggle_visibility(picked_visibility)
|
||||
return
|
||||
|
||||
/obj/item/organ/genital/proc/modify_size(modifier, min = -INFINITY, max = INFINITY)
|
||||
return
|
||||
|
||||
/obj/item/organ/genital/proc/update_size()
|
||||
return
|
||||
|
||||
/obj/item/organ/genital/proc/update_appearance()
|
||||
if(!owner || owner.stat == DEAD)
|
||||
aroused_state = FALSE
|
||||
|
||||
/obj/item/organ/genital/on_life()
|
||||
if(!reagents || !owner)
|
||||
return
|
||||
reagents.maximum_volume = fluid_max_volume
|
||||
if(fluid_id && CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION))
|
||||
generate_fluid()
|
||||
|
||||
/obj/item/organ/genital/proc/generate_fluid()
|
||||
var/amount = fluid_rate
|
||||
if(!reagents.total_volume && amount < 0.1) // Apparently, 0.015 gets rounded down to zero and no reagents are created if we don't start it with 0.1 in the tank.
|
||||
amount += 0.1
|
||||
var/multiplier = fluid_mult
|
||||
if(reagents.total_volume >= 5)
|
||||
multiplier *= 0.5
|
||||
if(reagents.total_volume < reagents.maximum_volume)
|
||||
reagents.isolate_reagent(fluid_id)//remove old reagents if it changed and just clean up generally
|
||||
reagents.add_reagent(fluid_id, (amount * multiplier))//generate the cum
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/item/organ/genital/proc/update_link(removing = FALSE)
|
||||
if(!removing && owner)
|
||||
if(linked_organ)
|
||||
return
|
||||
linked_organ = owner.getorganslot(linked_organ_slot)
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = src
|
||||
linked_organ.upon_link()
|
||||
upon_link()
|
||||
return TRUE
|
||||
else
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = null
|
||||
linked_organ = null
|
||||
return FALSE
|
||||
|
||||
//post organ duo making arrangements.
|
||||
/obj/item/organ/genital/proc/upon_link()
|
||||
return
|
||||
|
||||
/obj/item/organ/genital/Insert(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE)
|
||||
. = ..()
|
||||
if(.)
|
||||
update()
|
||||
RegisterSignal(owner, COMSIG_MOB_DEATH, .proc/update_appearance)
|
||||
|
||||
/obj/item/organ/genital/Remove(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE)
|
||||
. = ..()
|
||||
if(.)
|
||||
update(TRUE)
|
||||
UnregisterSignal(M, COMSIG_MOB_DEATH)
|
||||
|
||||
//proc to give a player their genitals and stuff when they log in
|
||||
/mob/living/carbon/human/proc/give_genitals(clean = FALSE)//clean will remove all pre-existing genitals. proc will then give them any genitals that are enabled in their DNA
|
||||
if(clean)
|
||||
for(var/obj/item/organ/genital/G in internal_organs)
|
||||
qdel(G)
|
||||
if (NOGENITALS in dna.species.species_traits)
|
||||
return
|
||||
if(dna.features["has_vag"])
|
||||
give_genital(/obj/item/organ/genital/vagina)
|
||||
if(dna.features["has_womb"])
|
||||
give_genital(/obj/item/organ/genital/womb)
|
||||
if(dna.features["has_balls"])
|
||||
give_genital(/obj/item/organ/genital/testicles)
|
||||
if(dna.features["has_breasts"])
|
||||
give_genital(/obj/item/organ/genital/breasts)
|
||||
if(dna.features["has_cock"])
|
||||
give_genital(/obj/item/organ/genital/penis)
|
||||
/*
|
||||
if(dna.features["has_ovi"])
|
||||
give_genital(/obj/item/organ/genital/ovipositor)
|
||||
if(dna.features["has_eggsack"])
|
||||
give_genital(/obj/item/organ/genital/eggsack)
|
||||
*/
|
||||
|
||||
/mob/living/carbon/human/proc/give_genital(obj/item/organ/genital/G)
|
||||
if(!dna || (NOGENITALS in dna.species.species_traits) || getorganslot(initial(G.slot)))
|
||||
return FALSE
|
||||
G = new G(null, src)
|
||||
return G
|
||||
|
||||
/obj/item/organ/genital/proc/get_features(mob/living/carbon/human/H)
|
||||
return
|
||||
|
||||
/datum/species/proc/genitals_layertext(layer)
|
||||
switch(layer)
|
||||
if(GENITALS_BEHIND_LAYER)
|
||||
return "BEHIND"
|
||||
if(GENITALS_FRONT_LAYER)
|
||||
return "FRONT"
|
||||
|
||||
//procs to handle sprite overlays being applied to humans
|
||||
|
||||
/mob/living/carbon/human/equip_to_slot(obj/item/I, slot)
|
||||
. = ..()
|
||||
if(!. && I && slot && !(slot in GLOB.no_genitals_update_slots)) //the item was successfully equipped, and the chosen slot wasn't merely storage, hands or cuffs.
|
||||
update_genitals()
|
||||
|
||||
/mob/living/carbon/human/doUnEquip(obj/item/I, force, newloc, no_move, invdrop = TRUE)
|
||||
var/no_update = FALSE
|
||||
if(!I || I == l_store || I == r_store || I == s_store || I == handcuffed || I == legcuffed || get_held_index_of_item(I)) //stops storages, cuffs and held items from triggering it.
|
||||
no_update = TRUE
|
||||
. = ..()
|
||||
if(!. || no_update)
|
||||
return
|
||||
update_genitals()
|
||||
|
||||
/mob/living/carbon/human/proc/update_genitals()
|
||||
if(!QDELETED(src))
|
||||
dna.species.handle_genitals(src)
|
||||
|
||||
//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()
|
||||
if(!canbearoused)
|
||||
return FALSE
|
||||
|
||||
var/organCheck = locate(/obj/item/organ/genital) in internal_organs
|
||||
var/breastCheck = getorganslot(ORGAN_SLOT_BREASTS)
|
||||
var/willyCheck = getorganslot(ORGAN_SLOT_PENIS)
|
||||
|
||||
if(organCheck == FALSE)
|
||||
if(ishuman(src) && dna.species.id == "human")
|
||||
dna.features["genitals_use_skintone"] = TRUE
|
||||
dna.species.use_skintones = TRUE
|
||||
if(MUTCOLORS)
|
||||
if(src.dna.species.fixed_mut_color)
|
||||
dna.features["cock_color"] = "[dna.species.fixed_mut_color]"
|
||||
dna.features["breasts_color"] = "[dna.species.fixed_mut_color]"
|
||||
return
|
||||
//So people who haven't set stuff up don't get rainbow surprises.
|
||||
dna.features["cock_color"] = "[dna.features["mcolor"]]"
|
||||
dna.features["breasts_color"] = "[dna.features["mcolor"]]"
|
||||
else //If there's a new organ, make it the same colour.
|
||||
if(breastCheck == FALSE)
|
||||
dna.features["breasts_color"] = dna.features["cock_color"]
|
||||
else if (willyCheck == FALSE)
|
||||
dna.features["cock_color"] = dna.features["breasts_color"]
|
||||
return TRUE
|
||||
|
||||
/datum/species/proc/handle_genitals(mob/living/carbon/human/H)//more like handle sadness
|
||||
if(!H)//no args
|
||||
CRASH("H = null")
|
||||
if(!LAZYLEN(H.internal_organs) || ((NOGENITALS in species_traits) && !H.genital_override) || HAS_TRAIT(H, TRAIT_HUSK))
|
||||
return
|
||||
var/list/relevant_layers = list(GENITALS_BEHIND_LAYER, GENITALS_FRONT_LAYER)
|
||||
|
||||
for(var/L in relevant_layers) //Less hardcode
|
||||
H.remove_overlay(L)
|
||||
H.remove_overlay(GENITALS_EXPOSED_LAYER)
|
||||
//start scanning for genitals
|
||||
|
||||
var/list/gen_index[GENITAL_LAYER_INDEX_LENGTH]
|
||||
var/list/genitals_to_add
|
||||
var/list/fully_exposed
|
||||
for(var/obj/item/organ/genital/G in H.internal_organs)
|
||||
if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes
|
||||
LAZYADD(gen_index[G.layer_index], G)
|
||||
for(var/L in gen_index)
|
||||
if(L) //skip nulls
|
||||
LAZYADD(genitals_to_add, L)
|
||||
if(!genitals_to_add)
|
||||
return
|
||||
//Now we added all genitals that aren't internal and should be rendered
|
||||
//start applying overlays
|
||||
for(var/layer in relevant_layers)
|
||||
var/list/standing = list()
|
||||
var/layertext = genitals_layertext(layer)
|
||||
for(var/A in genitals_to_add)
|
||||
var/obj/item/organ/genital/G = A
|
||||
var/datum/sprite_accessory/S
|
||||
var/size = G.size
|
||||
var/aroused_state = G.aroused_state
|
||||
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 || S.icon_state == "none")
|
||||
continue
|
||||
|
||||
var/mutable_appearance/genital_overlay = mutable_appearance(S.icon, layer = -layer)
|
||||
genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size]_[aroused_state]_[layertext]"
|
||||
|
||||
if(S.center)
|
||||
genital_overlay = center_image(genital_overlay, S.dimension_x, S.dimension_y)
|
||||
|
||||
if(use_skintones && H.dna.features["genitals_use_skintone"])
|
||||
genital_overlay.color = "#[skintone2hex(H.skin_tone)]"
|
||||
genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size]-s_[aroused_state]_[layertext]"
|
||||
else
|
||||
switch(S.color_src)
|
||||
if("cock_color")
|
||||
genital_overlay.color = "#[H.dna.features["cock_color"]]"
|
||||
if("balls_color")
|
||||
genital_overlay.color = "#[H.dna.features["balls_color"]]"
|
||||
if("breasts_color")
|
||||
genital_overlay.color = "#[H.dna.features["breasts_color"]]"
|
||||
if("vag_color")
|
||||
genital_overlay.color = "#[H.dna.features["vag_color"]]"
|
||||
|
||||
if(layer == GENITALS_FRONT_LAYER && CHECK_BITFIELD(G.genital_flags, GENITAL_THROUGH_CLOTHES))
|
||||
genital_overlay.layer = -GENITALS_EXPOSED_LAYER
|
||||
LAZYADD(fully_exposed, genital_overlay) // to be added to a layer with higher priority than clothes, hence the name of the bitflag.
|
||||
else
|
||||
standing += genital_overlay
|
||||
|
||||
if(LAZYLEN(standing))
|
||||
H.overlays_standing[layer] = standing
|
||||
|
||||
if(LAZYLEN(fully_exposed))
|
||||
H.overlays_standing[GENITALS_EXPOSED_LAYER] = fully_exposed
|
||||
H.apply_overlay(GENITALS_EXPOSED_LAYER)
|
||||
|
||||
for(var/L in relevant_layers)
|
||||
H.apply_overlay(L)
|
||||
|
||||
+3
-18
@@ -5,11 +5,9 @@
|
||||
//DICKS,COCKS,PENISES,WHATEVER YOU WANT TO CALL THEM
|
||||
/datum/sprite_accessory/penis
|
||||
icon = 'modular_citadel/icons/obj/genitals/penis_onmob.dmi'
|
||||
icon_state = null
|
||||
name = "penis" //the preview name of the accessory
|
||||
gender_specific = 0 //Might be needed somewhere down the list.
|
||||
color_src = "cock_color"
|
||||
locked = 0
|
||||
alt_aroused = TRUE
|
||||
|
||||
/datum/sprite_accessory/penis/human
|
||||
icon_state = "human"
|
||||
@@ -75,27 +73,21 @@
|
||||
icon_state = "testicle"
|
||||
name = "testicle" //the preview name of the accessory
|
||||
color_src = "balls_color"
|
||||
locked = 0
|
||||
|
||||
/datum/sprite_accessory/testicles/hidden
|
||||
icon_state = "hidden"
|
||||
icon_state = "none"
|
||||
name = "Hidden"
|
||||
alt_aroused = TRUE
|
||||
|
||||
/datum/sprite_accessory/testicles/single
|
||||
icon_state = "single"
|
||||
name = "Single"
|
||||
alt_aroused = TRUE
|
||||
|
||||
//Vaginas
|
||||
/datum/sprite_accessory/vagina
|
||||
icon = 'modular_citadel/icons/obj/genitals/vagina_onmob.dmi'
|
||||
icon_state = null
|
||||
name = "vagina"
|
||||
gender_specific = 0
|
||||
color_src = "vag_color"
|
||||
locked = 0
|
||||
alt_aroused = FALSE //if this is TRUE, then the genitals will use an alternate sprite for aroused states
|
||||
|
||||
/datum/sprite_accessory/vagina/human
|
||||
icon_state = "human"
|
||||
@@ -131,35 +123,28 @@
|
||||
//BREASTS BE HERE
|
||||
/datum/sprite_accessory/breasts
|
||||
icon = 'modular_citadel/icons/obj/genitals/breasts_onmob.dmi'
|
||||
icon_state = null
|
||||
name = "breasts"
|
||||
gender_specific = 0
|
||||
color_src = "breasts_color"
|
||||
locked = 0
|
||||
alt_aroused = TRUE
|
||||
|
||||
/datum/sprite_accessory/breasts/pair
|
||||
icon_state = "pair"
|
||||
name = "Pair"
|
||||
alt_aroused = TRUE
|
||||
|
||||
/datum/sprite_accessory/breasts/quad
|
||||
icon_state = "quad"
|
||||
name = "Quad"
|
||||
alt_aroused = TRUE
|
||||
|
||||
/datum/sprite_accessory/breasts/sextuple
|
||||
icon_state = "sextuple"
|
||||
name = "Sextuple"
|
||||
alt_aroused = TRUE
|
||||
|
||||
//OVIPOSITORS BE HERE
|
||||
/datum/sprite_accessory/ovipositor
|
||||
icon = 'modular_citadel/icons/obj/genitals/penis_onmob.dmi'
|
||||
icon_state = null
|
||||
name = "Ovipositor" //the preview name of the accessory
|
||||
gender_specific = 0 //Might be needed somewhere down the list.
|
||||
color_src = "cock_color"
|
||||
locked = 0
|
||||
|
||||
/datum/sprite_accessory/ovipositor/knotted
|
||||
icon_state = "knotted"
|
||||
@@ -1,50 +1,29 @@
|
||||
/obj/item/organ/genital/breasts
|
||||
name = "breasts"
|
||||
desc = "Female milk producing organs."
|
||||
icon_state = "breasts"
|
||||
icon = 'modular_citadel/icons/obj/genitals/breasts.dmi'
|
||||
zone = "chest"
|
||||
slot = "breasts"
|
||||
w_class = 3
|
||||
size = BREASTS_SIZE_DEF //SHOULD BE A LETTER, starts as a number...???
|
||||
var/cached_size = null //for enlargement SHOULD BE A NUMBER
|
||||
var/prev_size //For flavour texts SHOULD BE A LETTER
|
||||
//var/breast_sizes = list ("a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "huge", "flat")
|
||||
var/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/statuscheck = FALSE
|
||||
fluid_id = "milk"
|
||||
var/amount = 2
|
||||
producing = TRUE
|
||||
shape = "Pair"
|
||||
can_masturbate_with = TRUE
|
||||
masturbation_verb = "massage"
|
||||
can_climax = TRUE
|
||||
fluid_transfer_factor = 0.5
|
||||
name = "breasts"
|
||||
desc = "Female milk producing organs."
|
||||
icon_state = "breasts"
|
||||
icon = 'modular_citadel/icons/obj/genitals/breasts.dmi'
|
||||
zone = BODY_ZONE_CHEST
|
||||
slot = ORGAN_SLOT_BREASTS
|
||||
size = "c" //refer to the breast_values static list below for the cups associated number values
|
||||
fluid_id = "milk"
|
||||
shape = "pair"
|
||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_FUID_PRODUCTION
|
||||
masturbation_verb = "massage"
|
||||
orgasm_verb = "leaking"
|
||||
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/cached_size //these two vars pertain size modifications and so should be expressed in NUMBERS.
|
||||
var/prev_size //former cached_size value, to allow update_size() to early return should be there no significant changes.
|
||||
|
||||
/obj/item/organ/genital/breasts/on_life()
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(!reagents || !owner)
|
||||
return
|
||||
reagents.maximum_volume = fluid_max_volume
|
||||
if(fluid_id && producing)
|
||||
if(reagents.total_volume == 0) // Apparently, 0.015 gets rounded down to zero and no reagents are created if we don't start it with 0.1 in the tank.
|
||||
fluid_rate = 0.1
|
||||
else
|
||||
fluid_rate = CUM_RATE
|
||||
if(reagents.total_volume >= 5)
|
||||
fluid_mult = 0.5
|
||||
else
|
||||
fluid_mult = 1
|
||||
generate_milk()
|
||||
|
||||
/obj/item/organ/genital/breasts/proc/generate_milk()
|
||||
if(owner.stat == DEAD)
|
||||
return FALSE
|
||||
reagents.isolate_reagent(fluid_id)
|
||||
reagents.add_reagent(fluid_id, (fluid_mult * fluid_rate))
|
||||
/obj/item/organ/genital/breasts/Initialize(mapload, mob/living/carbon/human/H)
|
||||
if(!H)
|
||||
cached_size = breast_values[size]
|
||||
prev_size = cached_size
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/genital/breasts/update_appearance()
|
||||
. = ..()
|
||||
var/lowershape = lowertext(shape)
|
||||
switch(lowershape)
|
||||
if("pair")
|
||||
@@ -55,16 +34,15 @@
|
||||
desc = "You see three sets of breasts, running from their chest to their belly."
|
||||
else
|
||||
desc = "You see some breasts, they seem to be quite exotic."
|
||||
if(cached_size > 16)
|
||||
if(size == "huge")
|
||||
desc = "You see [pick("some serious honkers", "a real set of badonkers", "some dobonhonkeros", "massive dohoonkabhankoloos", "two big old tonhongerekoogers", "a couple of giant bonkhonagahoogs", "a pair of humongous hungolomghnonoloughongous")]. Their volume is way beyond cupsize now, measuring in about [round(cached_size)]cm in diameter."
|
||||
else if (!isnum(size))
|
||||
else
|
||||
if (size == "flat")
|
||||
desc += " They're very small and flatchested, however."
|
||||
else
|
||||
desc += " You estimate that they're [uppertext(size)]-cups."
|
||||
//string = "breasts_[lowertext(shape)]_[size]-s"
|
||||
|
||||
if(producing && aroused_state)
|
||||
if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION) && aroused_state)
|
||||
desc += " They're leaking [fluid_id]."
|
||||
var/string
|
||||
if(owner)
|
||||
@@ -80,57 +58,70 @@
|
||||
var/mob/living/carbon/human/H = owner
|
||||
icon_state = sanitize_text(string)
|
||||
H.update_genitals()
|
||||
|
||||
icon_state = sanitize_text(string)
|
||||
|
||||
|
||||
//Allows breasts to grow and change size, with sprite changes too.
|
||||
//maximum wah
|
||||
//Comical sizes slow you down in movement and actions.
|
||||
//Rediculous sizes makes you more cumbersome.
|
||||
//this is far too lewd wah
|
||||
|
||||
/obj/item/organ/genital/breasts/update_size()//wah
|
||||
|
||||
if(!ishuman(owner) || !owner)
|
||||
/obj/item/organ/genital/breasts/modify_size(modifier, min = -INFINITY, max = INFINITY)
|
||||
var/new_value = CLAMP(cached_size + modifier, min, max)
|
||||
if(new_value == cached_size)
|
||||
return
|
||||
if(cached_size < 0)//I don't actually know what round() does to negative numbers, so to be safe!!fixed
|
||||
to_chat(owner, "<span class='warning'>You feel your breasts shrinking away from your body as your chest flattens out.</b></span>")
|
||||
src.Remove(owner)
|
||||
switch(round(cached_size))
|
||||
if(0) //If flatchested
|
||||
size = "flat"
|
||||
if(owner.has_status_effect(/datum/status_effect/chem/breast_enlarger))
|
||||
owner.remove_status_effect(/datum/status_effect/chem/breast_enlarger)
|
||||
statuscheck = FALSE
|
||||
if(1 to 8) //If modest size
|
||||
size = breast_values[round(cached_size)]
|
||||
if(owner.has_status_effect(/datum/status_effect/chem/breast_enlarger))
|
||||
owner.remove_status_effect(/datum/status_effect/chem/breast_enlarger)
|
||||
statuscheck = FALSE
|
||||
if(9 to 15) //If massive
|
||||
size = breast_values[round(cached_size)]
|
||||
if(!owner.has_status_effect(/datum/status_effect/chem/breast_enlarger))
|
||||
owner.apply_status_effect(/datum/status_effect/chem/breast_enlarger)
|
||||
statuscheck = TRUE
|
||||
if(16 to INFINITY) //if Rediculous
|
||||
size = cached_size
|
||||
prev_size = cached_size
|
||||
cached_size = new_value
|
||||
update()
|
||||
|
||||
if(round(cached_size) < 16)//Because byond doesn't count from 0, I have to do this.
|
||||
if (prev_size == 0)
|
||||
prev_size = "flat"
|
||||
if(size == 0)//Bloody byond with it's counting from 1
|
||||
/obj/item/organ/genital/breasts/update_size()//wah
|
||||
var/rounded_cached = round(cached_size)
|
||||
if(cached_size < 0)//I don't actually know what round() does to negative numbers, so to be safe!!fixed
|
||||
if(owner)
|
||||
to_chat(owner, "<span class='warning'>You feel your breasts shrinking away from your body as your chest flattens out.</span>")
|
||||
QDEL_IN(src, 1)
|
||||
return
|
||||
var/enlargement = FALSE
|
||||
switch(rounded_cached)
|
||||
if(0) //flatchested
|
||||
size = "flat"
|
||||
if(isnum(prev_size))
|
||||
prev_size = breast_values[prev_size]
|
||||
if (breast_values[size] > breast_values[prev_size])
|
||||
to_chat(owner, "<span class='warning'>Your breasts [pick("swell up to", "flourish into", "expand into", "burst forth into", "grow eagerly into", "amplify into")] a [uppertext(size)]-cup.</b></span>")
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.Force_update_genitals()
|
||||
else if ((breast_values[size] < breast_values[prev_size]) && (breast_values[size] > 0.5))
|
||||
to_chat(owner, "<span class='warning'>Your breasts [pick("shrink down to", "decrease into", "diminish into", "deflate into", "shrivel regretfully into", "contracts into")] a [uppertext(size)]-cup.</b></span>")
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.Force_update_genitals()
|
||||
prev_size = size
|
||||
else if (cached_size >= 16)
|
||||
size = "huge"
|
||||
if(1 to 8) //modest
|
||||
size = breast_values[rounded_cached]
|
||||
if(9 to 15) //massive
|
||||
size = breast_values[rounded_cached]
|
||||
enlargement = TRUE
|
||||
if(16 to INFINITY) //rediculous
|
||||
size = "huge"
|
||||
enlargement = TRUE
|
||||
if(owner)
|
||||
var/status_effect = owner.has_status_effect(STATUS_EFFECT_BREASTS_ENLARGEMENT)
|
||||
if(enlargement && !status_effect)
|
||||
owner.apply_status_effect(STATUS_EFFECT_BREASTS_ENLARGEMENT)
|
||||
else if(!enlargement && status_effect)
|
||||
owner.remove_status_effect(STATUS_EFFECT_BREASTS_ENLARGEMENT)
|
||||
|
||||
if(rounded_cached < 16 && owner)//Because byond doesn't count from 0, I have to do this.
|
||||
var/mob/living/carbon/human/H = owner
|
||||
var/r_prev_size = round(prev_size)
|
||||
if (rounded_cached > r_prev_size)
|
||||
to_chat(H, "<span class='warning'>Your breasts [pick("swell up to", "flourish into", "expand into", "burst forth into", "grow eagerly into", "amplify into")] a [uppertext(size)]-cup.</span>")
|
||||
else if (rounded_cached < r_prev_size)
|
||||
to_chat(H, "<span class='warning'>Your breasts [pick("shrink down to", "decrease into", "diminish into", "deflate into", "shrivel regretfully into", "contracts into")] a [uppertext(size)]-cup.</span>")
|
||||
|
||||
/obj/item/organ/genital/breasts/get_features(mob/living/carbon/human/H)
|
||||
var/datum/dna/D = H.dna
|
||||
if(D.species.use_skintones && D.features["genitals_use_skintone"])
|
||||
color = "#[skintone2hex(H.skin_tone)]"
|
||||
else
|
||||
color = "#[D.features["breasts_color"]]"
|
||||
size = D.features["breasts_size"]
|
||||
shape = D.features["breasts_shape"]
|
||||
fluid_id = D.features["breasts_fluid"]
|
||||
if(!D.features["breasts_producing"])
|
||||
DISABLE_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION)
|
||||
if(!isnum(size))
|
||||
cached_size = breast_values[size]
|
||||
else
|
||||
cached_size = size
|
||||
size = breast_values[size]
|
||||
prev_size = cached_size
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/obj/item/organ/genital/eggsack
|
||||
name = "Egg sack"
|
||||
desc = "An egg producing reproductive organ."
|
||||
icon_state = "egg_sack"
|
||||
icon = 'modular_citadel/icons/obj/genitals/ovipositor.dmi'
|
||||
zone = "groin"
|
||||
slot = "testicles"
|
||||
color = null //don't use the /genital color since it already is colored
|
||||
internal = TRUE
|
||||
name = "Egg sack"
|
||||
desc = "An egg producing reproductive organ."
|
||||
icon_state = "egg_sack"
|
||||
icon = 'modular_citadel/icons/obj/genitals/ovipositor.dmi'
|
||||
zone = BODY_ZONE_PRECISE_GROIN
|
||||
slot = ORGAN_SLOT_TESTICLES
|
||||
genital_flags = GENITAL_INTERNAL|GENITAL_BLACKLISTED //unimplemented
|
||||
linked_organ_slot = ORGAN_SLOT_PENIS
|
||||
color = null //don't use the /genital color since it already is colored
|
||||
var/egg_girth = EGG_GIRTH_DEF
|
||||
var/cum_mult = CUM_RATE_MULT
|
||||
var/cum_rate = CUM_RATE
|
||||
var/cum_efficiency = CUM_EFFICIENCY
|
||||
var/obj/item/organ/ovipositor/linked_ovi
|
||||
|
||||
@@ -1,414 +0,0 @@
|
||||
/obj/item/organ/genital
|
||||
color = "#fcccb3"
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
var/shape = "Human" //Changed to be uppercase, let me know if this breaks everything..!!
|
||||
var/sensitivity = AROUSAL_START_VALUE
|
||||
var/list/genital_flags = list()
|
||||
var/can_masturbate_with = FALSE
|
||||
var/masturbation_verb = "masturbate"
|
||||
var/can_climax = FALSE
|
||||
var/fluid_transfer_factor = 0.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/fluid_id = null
|
||||
var/fluid_max_volume = 15
|
||||
var/fluid_efficiency = 1
|
||||
var/fluid_rate = 1
|
||||
var/fluid_mult = 1
|
||||
var/producing = FALSE
|
||||
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/through_clothes = FALSE
|
||||
var/internal = FALSE
|
||||
var/hidden = FALSE
|
||||
|
||||
/obj/item/organ/genital/Initialize()
|
||||
. = ..()
|
||||
if(!reagents)
|
||||
create_reagents(fluid_max_volume)
|
||||
update()
|
||||
|
||||
/obj/item/organ/genital/Destroy()
|
||||
remove_ref()
|
||||
if(owner)
|
||||
Remove(owner, 1)//this should remove references to it, so it can be GCd correctly
|
||||
update_link()//this should remove any other links it has
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/genital/proc/update()
|
||||
if(QDELETED(src))
|
||||
return
|
||||
update_size()
|
||||
update_appearance()
|
||||
update_link()
|
||||
|
||||
//exposure and through-clothing code
|
||||
/mob/living/carbon
|
||||
var/list/exposed_genitals = list() //Keeping track of them so we don't have to iterate through every genitalia and see if exposed
|
||||
|
||||
/obj/item/organ/genital/proc/is_exposed()
|
||||
if(!owner)
|
||||
return FALSE
|
||||
if(hidden)
|
||||
return FALSE
|
||||
if(internal)
|
||||
return FALSE
|
||||
if(through_clothes)
|
||||
return TRUE
|
||||
|
||||
switch(zone) //update as more genitals are added
|
||||
if("chest")
|
||||
return owner.is_chest_exposed()
|
||||
if("groin")
|
||||
return owner.is_groin_exposed()
|
||||
|
||||
return FALSE
|
||||
|
||||
/obj/item/organ/genital/proc/toggle_visibility(visibility)
|
||||
switch(visibility)
|
||||
if("Always visible")
|
||||
through_clothes = TRUE
|
||||
hidden = FALSE
|
||||
if(!(src in owner.exposed_genitals))
|
||||
owner.exposed_genitals += src
|
||||
if("Hidden by clothes")
|
||||
through_clothes = FALSE
|
||||
hidden = TRUE
|
||||
if(src in owner.exposed_genitals)
|
||||
owner.exposed_genitals -= src
|
||||
if("Always hidden")
|
||||
through_clothes = FALSE
|
||||
hidden = TRUE
|
||||
if(src in owner.exposed_genitals)
|
||||
owner.exposed_genitals -= src
|
||||
|
||||
if(ishuman(owner)) //recast to use update genitals proc
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.update_genitals()
|
||||
|
||||
/mob/living/carbon/verb/toggle_genitals()
|
||||
set category = "IC"
|
||||
set name = "Expose/Hide genitals"
|
||||
set desc = "Allows you to toggle which genitals should show through clothes or not."
|
||||
|
||||
var/list/genital_list = list()
|
||||
for(var/obj/item/organ/O in internal_organs)
|
||||
if(isgenital(O))
|
||||
var/obj/item/organ/genital/G = O
|
||||
if(!G.internal)
|
||||
genital_list += G
|
||||
if(!genital_list.len) //There is nothing to expose
|
||||
return
|
||||
//Full list of exposable genitals created
|
||||
var/obj/item/organ/genital/picked_organ
|
||||
picked_organ = input(src, "Choose which genitalia to expose/hide", "Expose/Hide genitals", null) in genital_list
|
||||
if(picked_organ)
|
||||
var/picked_visibility = input(src, "Choose visibility setting", "Expose/Hide genitals", "Hidden by clothes") in list("Always visible", "Hidden by clothes", "Always hidden")
|
||||
picked_organ.toggle_visibility(picked_visibility)
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/item/organ/genital/proc/update_size()
|
||||
return
|
||||
|
||||
/obj/item/organ/genital/proc/update_appearance()
|
||||
return
|
||||
|
||||
/obj/item/organ/genital/proc/update_link()
|
||||
return
|
||||
|
||||
/obj/item/organ/genital/proc/remove_ref()
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = null
|
||||
linked_organ = null
|
||||
|
||||
/obj/item/organ/genital/Insert(mob/living/carbon/M, special = 0)
|
||||
..()
|
||||
update()
|
||||
|
||||
/obj/item/organ/genital/Remove(mob/living/carbon/M, special = 0)
|
||||
..()
|
||||
update()
|
||||
|
||||
//proc to give a player their genitals and stuff when they log in
|
||||
/mob/living/carbon/human/proc/give_genitals(clean=0)//clean will remove all pre-existing genitals. proc will then give them any genitals that are enabled in their DNA
|
||||
if(clean)
|
||||
var/obj/item/organ/genital/GtoClean
|
||||
for(GtoClean in internal_organs)
|
||||
qdel(GtoClean)
|
||||
if (NOGENITALS in dna.species.species_traits)
|
||||
return
|
||||
//Order should be very important. FIRST vagina, THEN testicles, THEN penis, as this affects the order they are rendered in.
|
||||
if(dna.features["has_vag"])
|
||||
give_vagina()
|
||||
if(dna.features["has_womb"])
|
||||
give_womb()
|
||||
if(dna.features["has_balls"])
|
||||
give_balls()
|
||||
if(dna.features["has_breasts"]) // since we have multi-boobs as a thing, we'll want to at least draw over these. but not over the pingas.
|
||||
give_breasts()
|
||||
if(dna.features["has_cock"])
|
||||
give_penis()
|
||||
if(dna.features["has_ovi"])
|
||||
give_ovipositor()
|
||||
if(dna.features["has_eggsack"])
|
||||
give_eggsack()
|
||||
|
||||
/mob/living/carbon/human/proc/give_penis()
|
||||
if(!dna)
|
||||
return FALSE
|
||||
if(NOGENITALS in dna.species.species_traits)
|
||||
return FALSE
|
||||
if(!getorganslot("penis"))
|
||||
var/obj/item/organ/genital/penis/P = new
|
||||
P.Insert(src)
|
||||
if(P)
|
||||
if(dna.species.use_skintones && dna.features["genitals_use_skintone"])
|
||||
P.color = "#[skintone2hex(skin_tone)]"
|
||||
else
|
||||
P.color = "#[dna.features["cock_color"]]"
|
||||
P.length = dna.features["cock_length"]
|
||||
P.girth_ratio = dna.features["cock_girth_ratio"]
|
||||
P.shape = dna.features["cock_shape"]
|
||||
P.prev_length = P.length
|
||||
P.cached_length = P.length
|
||||
P.update()
|
||||
|
||||
/mob/living/carbon/human/proc/give_balls()
|
||||
if(!dna)
|
||||
return FALSE
|
||||
if(NOGENITALS in dna.species.species_traits)
|
||||
return FALSE
|
||||
if(!getorganslot("testicles"))
|
||||
var/obj/item/organ/genital/testicles/T = new
|
||||
T.Insert(src)
|
||||
if(T)
|
||||
if(dna.species.use_skintones && dna.features["genitals_use_skintone"])
|
||||
T.color = "#[skintone2hex(skin_tone)]"
|
||||
else
|
||||
T.color = "#[dna.features["balls_color"]]"
|
||||
T.size = dna.features["balls_size"]
|
||||
T.sack_size = dna.features["balls_sack_size"]
|
||||
T.shape = dna.features["balls_shape"]
|
||||
if(dna.features["balls_shape"] == "Hidden")
|
||||
T.internal = TRUE
|
||||
else
|
||||
T.internal = FALSE
|
||||
T.fluid_id = dna.features["balls_fluid"]
|
||||
T.fluid_rate = dna.features["balls_cum_rate"]
|
||||
T.fluid_mult = dna.features["balls_cum_mult"]
|
||||
T.fluid_efficiency = dna.features["balls_efficiency"]
|
||||
T.update()
|
||||
|
||||
/mob/living/carbon/human/proc/give_breasts()
|
||||
if(!dna)
|
||||
return FALSE
|
||||
if(NOGENITALS in dna.species.species_traits)
|
||||
return FALSE
|
||||
if(!getorganslot("breasts"))
|
||||
var/obj/item/organ/genital/breasts/B = new
|
||||
B.Insert(src)
|
||||
if(B)
|
||||
if(dna.species.use_skintones && dna.features["genitals_use_skintone"])
|
||||
B.color = "#[skintone2hex(skin_tone)]"
|
||||
else
|
||||
B.color = "#[dna.features["breasts_color"]]"
|
||||
B.size = dna.features["breasts_size"]
|
||||
if(!isnum(B.size))
|
||||
if(B.size == "flat")
|
||||
B.cached_size = 0
|
||||
B.prev_size = 0
|
||||
else if (B.cached_size == "huge")
|
||||
B.prev_size = "huge"
|
||||
else
|
||||
B.cached_size = B.breast_values[B.size]
|
||||
B.prev_size = B.size
|
||||
else
|
||||
B.cached_size = B.size
|
||||
B.prev_size = B.size
|
||||
B.shape = dna.features["breasts_shape"]
|
||||
B.fluid_id = dna.features["breasts_fluid"]
|
||||
B.producing = dna.features["breasts_producing"]
|
||||
B.update()
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/give_ovipositor()
|
||||
return
|
||||
/mob/living/carbon/human/proc/give_eggsack()
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/give_vagina()
|
||||
if(!dna)
|
||||
return FALSE
|
||||
if(NOGENITALS in dna.species.species_traits)
|
||||
return FALSE
|
||||
if(!getorganslot("vagina"))
|
||||
var/obj/item/organ/genital/vagina/V = new
|
||||
V.Insert(src)
|
||||
if(V)
|
||||
if(dna.species.use_skintones && dna.features["genitals_use_skintone"])
|
||||
V.color = "#[skintone2hex(skin_tone)]"
|
||||
else
|
||||
V.color = "[dna.features["vag_color"]]"
|
||||
V.shape = "[dna.features["vag_shape"]]"
|
||||
V.update()
|
||||
|
||||
/mob/living/carbon/human/proc/give_womb()
|
||||
if(!dna)
|
||||
return FALSE
|
||||
if(NOGENITALS in dna.species.species_traits)
|
||||
return FALSE
|
||||
if(!getorganslot("womb"))
|
||||
var/obj/item/organ/genital/womb/W = new
|
||||
W.Insert(src)
|
||||
if(W)
|
||||
W.update()
|
||||
|
||||
|
||||
/datum/species/proc/genitals_layertext(layer)
|
||||
switch(layer)
|
||||
if(GENITALS_BEHIND_LAYER)
|
||||
return "BEHIND"
|
||||
/*if(GENITALS_ADJ_LAYER)
|
||||
return "ADJ"*/
|
||||
if(GENITALS_FRONT_LAYER)
|
||||
return "FRONT"
|
||||
|
||||
//procs to handle sprite overlays being applied to humans
|
||||
|
||||
/obj/item/equipped(mob/user, slot)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.update_genitals()
|
||||
..()
|
||||
|
||||
/mob/living/carbon/human/doUnEquip(obj/item/I, force)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
update_genitals()
|
||||
|
||||
/mob/living/carbon/human/proc/update_genitals()
|
||||
if(src && !QDELETED(src))
|
||||
dna.species.handle_genitals(src)
|
||||
|
||||
//fermichem procs
|
||||
/mob/living/carbon/human/proc/Force_update_genitals(mob/living/carbon/human/H) //called in fermiChem
|
||||
dna.species.handle_genitals(src)//should work.
|
||||
//dna.species.handle_breasts(src)
|
||||
|
||||
//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()
|
||||
var/organCheck = FALSE
|
||||
var/breastCheck = FALSE
|
||||
var/willyCheck = FALSE
|
||||
if(!canbearoused)
|
||||
ADD_TRAIT(src, TRAIT_PHARMA, "pharma")//Prefs prevent unwanted organs.
|
||||
return
|
||||
for(var/obj/item/organ/O in internal_organs)
|
||||
if(istype(O, /obj/item/organ/genital))
|
||||
organCheck = TRUE
|
||||
if(/obj/item/organ/genital/penis)
|
||||
//dna.features["has_cock"] = TRUE
|
||||
willyCheck = TRUE
|
||||
if(/obj/item/organ/genital/breasts)
|
||||
//dna.features["has_breasts"] = TRUE//Goddamnit get in there.
|
||||
breastCheck = TRUE
|
||||
if(organCheck == FALSE)
|
||||
if(ishuman(src) && dna.species.id == "human")
|
||||
dna.features["genitals_use_skintone"] = TRUE
|
||||
dna.species.use_skintones = TRUE
|
||||
if(MUTCOLORS)
|
||||
if(src.dna.species.fixed_mut_color)
|
||||
dna.features["cock_color"] = "[src.dna.species.fixed_mut_color]"
|
||||
dna.features["breasts_color"] = "[src.dna.species.fixed_mut_color]"
|
||||
return
|
||||
//So people who haven't set stuff up don't get rainbow surprises.
|
||||
dna.features["cock_color"] = "[dna.features["mcolor"]]"
|
||||
dna.features["breasts_color"] = "[dna.features["mcolor"]]"
|
||||
else //If there's a new organ, make it the same colour.
|
||||
if(breastCheck == FALSE)
|
||||
dna.features["breasts_color"] = dna.features["cock_color"]
|
||||
else if (willyCheck == FALSE)
|
||||
dna.features["cock_color"] = dna.features["breasts_color"]
|
||||
return
|
||||
|
||||
/datum/species/proc/handle_genitals(mob/living/carbon/human/H)//more like handle sadness
|
||||
if(!H)//no args
|
||||
CRASH("H = null")
|
||||
if(!LAZYLEN(H.internal_organs))//if they have no organs, we're done
|
||||
return
|
||||
if((NOGENITALS in species_traits) && (H.genital_override = FALSE))//golems and such - things that shouldn't
|
||||
return
|
||||
if(HAS_TRAIT(H, TRAIT_HUSK))
|
||||
return
|
||||
var/list/genitals_to_add = list()
|
||||
var/list/relevant_layers = list(GENITALS_BEHIND_LAYER, GENITALS_FRONT_LAYER) //GENITALS_ADJ_LAYER removed
|
||||
var/list/standing = list()
|
||||
var/size
|
||||
var/aroused_state
|
||||
|
||||
for(var/L in relevant_layers) //Less hardcode
|
||||
H.remove_overlay(L)
|
||||
//start scanning for genitals
|
||||
for(var/obj/item/organ/O in H.internal_organs)
|
||||
if(isgenital(O))
|
||||
var/obj/item/organ/genital/G = O
|
||||
if(G.hidden)
|
||||
return //we're gunna just hijack this for updates.
|
||||
if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes
|
||||
genitals_to_add += H.getorganslot(G.slot)
|
||||
//Now we added all genitals that aren't internal and should be rendered
|
||||
//start applying overlays
|
||||
for(var/layer in relevant_layers)
|
||||
var/layertext = genitals_layertext(layer)
|
||||
for(var/obj/item/organ/genital/G in genitals_to_add)
|
||||
var/datum/sprite_accessory/S
|
||||
size = G.size
|
||||
aroused_state = G.aroused_state
|
||||
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 || S.icon_state == "none")
|
||||
continue
|
||||
|
||||
var/mutable_appearance/genital_overlay = mutable_appearance(S.icon, layer = -layer)
|
||||
genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size]_[aroused_state]_[layertext]"
|
||||
|
||||
if(S.center)
|
||||
genital_overlay = center_image(genital_overlay, S.dimension_x, S.dimension_y)
|
||||
|
||||
if(use_skintones && H.dna.features["genitals_use_skintone"])
|
||||
genital_overlay.color = "#[skintone2hex(H.skin_tone)]"
|
||||
genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size]-s_[aroused_state]_[layertext]"
|
||||
else
|
||||
switch(S.color_src)
|
||||
if("cock_color")
|
||||
genital_overlay.color = "#[H.dna.features["cock_color"]]"
|
||||
if("balls_color")
|
||||
genital_overlay.color = "#[H.dna.features["balls_color"]]"
|
||||
if("breasts_color")
|
||||
genital_overlay.color = "#[H.dna.features["breasts_color"]]"
|
||||
if("vag_color")
|
||||
genital_overlay.color = "#[H.dna.features["vag_color"]]"
|
||||
|
||||
standing += genital_overlay
|
||||
|
||||
if(LAZYLEN(standing))
|
||||
H.overlays_standing[layer] = standing.Copy()
|
||||
standing = list()
|
||||
|
||||
for(var/L in relevant_layers)
|
||||
H.apply_overlay(L)
|
||||
@@ -3,14 +3,14 @@
|
||||
desc = "An egg laying reproductive organ."
|
||||
icon_state = "ovi_knotted_2"
|
||||
icon = 'modular_citadel/icons/obj/genitals/ovipositor.dmi'
|
||||
zone = "groin"
|
||||
slot = "penis"
|
||||
w_class = 3
|
||||
zone = BODY_ZONE_PRECISE_GROIN
|
||||
slot = ORGAN_SLOT_PENIS
|
||||
genital_flags = GENITAL_BLACKLISTED //unimplemented
|
||||
shape = "knotted"
|
||||
size = 3
|
||||
layer_index = PENIS_LAYER_INDEX
|
||||
var/length = 6 //inches
|
||||
var/girth = 0
|
||||
var/girth_ratio = COCK_GIRTH_RATIO_DEF //citadel_defines.dm for these defines
|
||||
var/knot_girth_ratio = KNOT_GIRTH_RATIO_DEF
|
||||
var/list/oviflags = list()
|
||||
var/obj/item/organ/eggsack/linked_eggsack
|
||||
|
||||
@@ -1,77 +1,78 @@
|
||||
/obj/item/organ/genital/penis
|
||||
name = "penis"
|
||||
desc = "A male reproductive organ."
|
||||
icon_state = "penis"
|
||||
icon = 'modular_citadel/icons/obj/genitals/penis.dmi'
|
||||
zone = "groin"
|
||||
slot = ORGAN_SLOT_PENIS
|
||||
can_masturbate_with = TRUE
|
||||
masturbation_verb = "stroke"
|
||||
can_climax = TRUE
|
||||
fluid_transfer_factor = 0.5
|
||||
size = 2 //arbitrary value derived from length and girth for sprites.
|
||||
var/length = 6 //inches
|
||||
var/cached_length //used to detect a change in length
|
||||
var/girth = 4.38
|
||||
var/girth_ratio = COCK_GIRTH_RATIO_DEF //0.73; check citadel_defines.dm
|
||||
var/knot_girth_ratio = KNOT_GIRTH_RATIO_DEF
|
||||
var/list/dickflags = list()
|
||||
var/list/knotted_types = list("knotted", "barbed, knotted")
|
||||
var/prev_length = 6 //really should be renamed to prev_length
|
||||
name = "penis"
|
||||
desc = "A male reproductive organ."
|
||||
icon_state = "penis"
|
||||
icon = 'modular_citadel/icons/obj/genitals/penis.dmi'
|
||||
zone = BODY_ZONE_PRECISE_GROIN
|
||||
slot = ORGAN_SLOT_PENIS
|
||||
masturbation_verb = "stroke"
|
||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH
|
||||
linked_organ_slot = ORGAN_SLOT_TESTICLES
|
||||
fluid_transfer_factor = 0.5
|
||||
size = 2 //arbitrary value derived from length and girth for sprites.
|
||||
layer_index = PENIS_LAYER_INDEX
|
||||
var/length = 6 //inches
|
||||
var/prev_length = 6 //really should be renamed to prev_length
|
||||
var/girth = 4.38
|
||||
var/girth_ratio = COCK_GIRTH_RATIO_DEF //0.73; check citadel_defines.dm
|
||||
|
||||
/obj/item/organ/genital/penis/Initialize()
|
||||
. = ..()
|
||||
/* I hate genitals.*/
|
||||
|
||||
/obj/item/organ/genital/penis/update_size()
|
||||
var/mob/living/carbon/human/o = owner
|
||||
if(!ishuman(o) || !o)
|
||||
/obj/item/organ/genital/penis/modify_size(modifier, min = -INFINITY, max = INFINITY)
|
||||
var/new_value = CLAMP(length + modifier, min, max)
|
||||
if(new_value == length)
|
||||
return
|
||||
if(cached_length < 0)//I don't actually know what round() does to negative numbers, so to be safe!!
|
||||
var/obj/item/organ/genital/penis/P = o.getorganslot("penis")
|
||||
to_chat(o, "<span class='warning'>You feel your tallywacker shrinking away from your body as your groin flattens out!</b></span>")
|
||||
P.Remove(o)
|
||||
switch(round(cached_length))
|
||||
if(0 to 4) //If modest size
|
||||
length = cached_length
|
||||
size = 1
|
||||
if(owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
|
||||
o.remove_status_effect(/datum/status_effect/chem/penis_enlarger)
|
||||
if(5 to 10) //If modest size
|
||||
length = cached_length
|
||||
size = 2
|
||||
if(owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
|
||||
o.remove_status_effect(/datum/status_effect/chem/penis_enlarger)
|
||||
if(11 to 20) //If massive
|
||||
length = cached_length
|
||||
size = 3
|
||||
if(owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
|
||||
o.remove_status_effect(/datum/status_effect/chem/penis_enlarger)
|
||||
if(21 to 35) //If massive and due for large effects
|
||||
length = cached_length
|
||||
size = 3
|
||||
if(!owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
|
||||
o.apply_status_effect(/datum/status_effect/chem/penis_enlarger)
|
||||
if(36 to INFINITY) //If comical
|
||||
length = cached_length
|
||||
size = 4 //no new sprites for anything larger yet
|
||||
if(!owner.has_status_effect(/datum/status_effect/chem/penis_enlarger))
|
||||
o.apply_status_effect(/datum/status_effect/chem/penis_enlarger)
|
||||
|
||||
if (round(length) > round(prev_length))
|
||||
to_chat(o, "<span class='warning'>Your [pick(GLOB.gentlemans_organ_names)] [pick("swells up to", "flourishes into", "expands into", "bursts forth into", "grows eagerly into", "amplifys into")] a [uppertext(round(length))] inch penis.</b></span>")
|
||||
else if ((round(length) < round(prev_length)) && (length > 0.5))
|
||||
to_chat(o, "<span class='warning'>Your [pick(GLOB.gentlemans_organ_names)] [pick("shrinks down to", "decreases into", "diminishes into", "deflates into", "shrivels regretfully into", "contracts into")] a [uppertext(round(length))] inch penis.</b></span>")
|
||||
prev_length = length
|
||||
length = CLAMP(length + modifier, min, max)
|
||||
update()
|
||||
|
||||
/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(owner)
|
||||
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)
|
||||
if(linked_organ)
|
||||
QDEL_IN(linked_organ, 1)
|
||||
return
|
||||
var/rounded_length = round(length)
|
||||
var/new_size
|
||||
var/enlargement = FALSE
|
||||
switch(rounded_length)
|
||||
if(0 to 6) //If modest size
|
||||
new_size = 1
|
||||
if(7 to 11) //If large
|
||||
new_size = 2
|
||||
if(12 to 20) //If massive
|
||||
new_size = 3
|
||||
if(21 to 34) //If massive and due for large effects
|
||||
new_size = 3
|
||||
enlargement = TRUE
|
||||
if(35 to INFINITY) //If comical
|
||||
new_size = 4 //no new sprites for anything larger yet
|
||||
enlargement = TRUE
|
||||
if(owner)
|
||||
var/status_effect = owner.has_status_effect(STATUS_EFFECT_PENIS_ENLARGEMENT)
|
||||
if(enlargement && !status_effect)
|
||||
owner.apply_status_effect(STATUS_EFFECT_PENIS_ENLARGEMENT)
|
||||
else if(!enlargement && status_effect)
|
||||
owner.remove_status_effect(STATUS_EFFECT_PENIS_ENLARGEMENT)
|
||||
if(linked_organ)
|
||||
linked_organ.size = CLAMP(size + new_size, BALLS_SIZE_MIN, BALLS_SIZE_MAX)
|
||||
linked_organ.update()
|
||||
size = new_size
|
||||
|
||||
if(owner)
|
||||
if (round(length) > round(prev_length))
|
||||
to_chat(owner, "<span class='warning'>Your [pick(GLOB.gentlemans_organ_names)] [pick("swells up to", "flourishes into", "expands into", "bursts forth into", "grows eagerly into", "amplifys into")] a [uppertext(round(length))] inch penis.</b></span>")
|
||||
else if ((round(length) < round(prev_length)) && (length > 0.5))
|
||||
to_chat(owner, "<span class='warning'>Your [pick(GLOB.gentlemans_organ_names)] [pick("shrinks down to", "decreases into", "diminishes into", "deflates into", "shrivels regretfully into", "contracts into")] a [uppertext(round(length))] inch penis.</b></span>")
|
||||
icon_state = sanitize_text("penis_[shape]_[size]")
|
||||
girth = (length * girth_ratio)//Is it just me or is this ludicous, why not make it exponentially decay?
|
||||
|
||||
//I have no idea on how to update sprites and I hate it
|
||||
|
||||
/obj/item/organ/genital/penis/update_appearance()
|
||||
. = ..()
|
||||
var/string
|
||||
var/lowershape = lowertext(shape)
|
||||
desc = "You see [aroused_state ? "an erect" : "a flaccid"] [lowershape] penis. You estimate it's about [round(length, 0.25)] inch[round(length, 0.25) != 1 ? "es" : ""] long and [round(girth, 0.25)] inch[round(girth, 0.25) != 1 ? "es" : ""] in girth."
|
||||
desc = "You see [aroused_state ? "an erect" : "a flaccid"] [lowershape] [name]. You estimate it's about [round(length, 0.25)] inch[round(length, 0.25) != 1 ? "es" : ""] long and [round(girth, 0.25)] inch[round(girth, 0.25) != 1 ? "es" : ""] in girth."
|
||||
|
||||
if(owner)
|
||||
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
|
||||
@@ -87,13 +88,13 @@
|
||||
icon_state = sanitize_text(string)
|
||||
H.update_genitals()
|
||||
|
||||
/obj/item/organ/genital/penis/update_link()
|
||||
if(owner)
|
||||
linked_organ = (owner.getorganslot("testicles"))
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = src
|
||||
linked_organ.size = size
|
||||
/obj/item/organ/genital/penis/get_features(mob/living/carbon/human/H)
|
||||
var/datum/dna/D = H.dna
|
||||
if(D.species.use_skintones && D.features["genitals_use_skintone"])
|
||||
color = "#[skintone2hex(H.skin_tone)]"
|
||||
else
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = null
|
||||
linked_organ = null
|
||||
color = "#[D.features["cock_color"]]"
|
||||
length = D.features["cock_length"]
|
||||
girth_ratio = D.features["cock_girth_ratio"]
|
||||
shape = D.features["cock_shape"]
|
||||
prev_length = length
|
||||
|
||||
@@ -1,82 +1,46 @@
|
||||
/obj/item/organ/genital/testicles
|
||||
name = "testicles"
|
||||
desc = "A male reproductive organ."
|
||||
icon_state = "testicles"
|
||||
icon = 'modular_citadel/icons/obj/genitals/testicles.dmi'
|
||||
zone = "groin"
|
||||
slot = "testicles"
|
||||
size = BALLS_SIZE_MIN
|
||||
var/size_name = "average"
|
||||
shape = "single"
|
||||
var/sack_size = BALLS_SACK_SIZE_DEF
|
||||
fluid_id = "semen"
|
||||
producing = TRUE
|
||||
can_masturbate_with = FALSE
|
||||
masturbation_verb = "massage"
|
||||
can_climax = TRUE
|
||||
var/sent_full_message = TRUE //defaults to 1 since they're full to start
|
||||
name = "testicles"
|
||||
desc = "A male reproductive organ."
|
||||
icon_state = "testicles"
|
||||
icon = 'modular_citadel/icons/obj/genitals/testicles.dmi'
|
||||
zone = BODY_ZONE_PRECISE_GROIN
|
||||
slot = ORGAN_SLOT_TESTICLES
|
||||
size = BALLS_SIZE_MIN
|
||||
linked_organ_slot = ORGAN_SLOT_PENIS
|
||||
genital_flags = CAN_MASTURBATE_WITH|MASTURBATE_LINKED_ORGAN|GENITAL_FUID_PRODUCTION
|
||||
var/size_name = "average"
|
||||
shape = "Single"
|
||||
var/sack_size = BALLS_SACK_SIZE_DEF
|
||||
fluid_id = "semen"
|
||||
masturbation_verb = "massage"
|
||||
layer_index = TESTICLES_LAYER_INDEX
|
||||
|
||||
/obj/item/organ/genital/testicles/on_life()
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(reagents && producing)
|
||||
if(reagents.total_volume == 0) // Apparently, 0.015 gets rounded down to zero and no reagents are created if we don't start it with 0.1 in the tank.
|
||||
fluid_rate = 0.1
|
||||
else
|
||||
fluid_rate = CUM_RATE
|
||||
if(reagents.total_volume >= 5)
|
||||
fluid_mult = 0.5
|
||||
else
|
||||
fluid_mult = 1
|
||||
generate_cum()
|
||||
|
||||
/obj/item/organ/genital/testicles/proc/generate_cum()
|
||||
reagents.maximum_volume = fluid_max_volume
|
||||
if(reagents.total_volume >= reagents.maximum_volume)
|
||||
if(!sent_full_message)
|
||||
send_full_message()
|
||||
sent_full_message = TRUE
|
||||
/obj/item/organ/genital/testicles/generate_fluid()
|
||||
if(!linked_organ && !update_link())
|
||||
return FALSE
|
||||
sent_full_message = FALSE
|
||||
update_link()
|
||||
if(!linked_organ)
|
||||
return FALSE
|
||||
reagents.isolate_reagent(fluid_id)//remove old reagents if it changed and just clean up generally
|
||||
reagents.add_reagent(fluid_id, (fluid_mult * fluid_rate))//generate the cum
|
||||
. = ..()
|
||||
if(. && reagents.holder_full())
|
||||
to_chat(owner, "Your balls finally feel full, again.")
|
||||
|
||||
/obj/item/organ/genital/testicles/update_link()
|
||||
if(owner && !QDELETED(src))
|
||||
linked_organ = (owner.getorganslot("penis"))
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = src
|
||||
size = linked_organ.size
|
||||
/obj/item/organ/genital/testicles/upon_link()
|
||||
size = linked_organ.size
|
||||
update_size()
|
||||
update_appearance()
|
||||
|
||||
else
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = null
|
||||
linked_organ = null
|
||||
|
||||
/obj/item/organ/genital/testicles/proc/send_full_message(msg = "Your balls finally feel full, again.")
|
||||
if(owner && istext(msg))
|
||||
to_chat(owner, msg)
|
||||
return TRUE
|
||||
|
||||
/obj/item/organ/genital/testicles/update_appearance()
|
||||
/obj/item/organ/genital/testicles/update_size(modified = FALSE)
|
||||
switch(size)
|
||||
if(0.1 to 1)
|
||||
if(BALLS_SIZE_MIN)
|
||||
size_name = "average"
|
||||
if(1.1 to 2)
|
||||
if(BALLS_SIZE_DEF)
|
||||
size_name = "enlarged"
|
||||
if(2.1 to INFINITY)
|
||||
if(BALLS_SIZE_MAX)
|
||||
size_name = "engorged"
|
||||
else
|
||||
size_name = "nonexistant"
|
||||
|
||||
if(!internal)
|
||||
desc = "You see an [size_name] pair of testicles."
|
||||
else
|
||||
desc = "They don't have any testicles you can see."
|
||||
|
||||
/obj/item/organ/genital/testicles/update_appearance()
|
||||
. = ..()
|
||||
desc = "You see an [size_name] pair of testicles."
|
||||
if(owner)
|
||||
var/string
|
||||
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
|
||||
@@ -91,3 +55,18 @@
|
||||
var/mob/living/carbon/human/H = owner
|
||||
icon_state = sanitize_text(string)
|
||||
H.update_genitals()
|
||||
|
||||
/obj/item/organ/genital/testicles/get_features(mob/living/carbon/human/H)
|
||||
var/datum/dna/D = H.dna
|
||||
if(D.species.use_skintones && D.features["genitals_use_skintone"])
|
||||
color = "#[skintone2hex(H.skin_tone)]"
|
||||
else
|
||||
color = "#[D.features["balls_color"]]"
|
||||
sack_size = D.features["balls_sack_size"]
|
||||
shape = D.features["balls_shape"]
|
||||
if(D.features["balls_shape"] == "Hidden")
|
||||
ENABLE_BITFIELD(genital_flags, GENITAL_INTERNAL)
|
||||
fluid_id = D.features["balls_fluid"]
|
||||
fluid_rate = D.features["balls_cum_rate"]
|
||||
fluid_mult = D.features["balls_cum_mult"]
|
||||
fluid_efficiency = D.features["balls_efficiency"]
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
/obj/item/organ/genital/vagina
|
||||
name = "vagina"
|
||||
desc = "A female reproductive organ."
|
||||
icon = 'modular_citadel/icons/obj/genitals/vagina.dmi'
|
||||
icon_state = "vagina"
|
||||
zone = "groin"
|
||||
slot = "vagina"
|
||||
size = 1 //There is only 1 size right now
|
||||
can_masturbate_with = TRUE
|
||||
masturbation_verb = "finger"
|
||||
can_climax = TRUE
|
||||
name = "vagina"
|
||||
desc = "A female reproductive organ."
|
||||
icon = 'modular_citadel/icons/obj/genitals/vagina.dmi'
|
||||
icon_state = ORGAN_SLOT_VAGINA
|
||||
zone = BODY_ZONE_PRECISE_GROIN
|
||||
slot = "vagina"
|
||||
size = 1 //There is only 1 size right now
|
||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH
|
||||
masturbation_verb = "finger"
|
||||
fluid_transfer_factor = 0.1 //Yes, some amount is exposed to you, go get your AIDS
|
||||
w_class = 3
|
||||
var/cap_length = 8//D E P T H (cap = capacity)
|
||||
var/cap_girth = 12
|
||||
layer_index = VAGINA_LAYER_INDEX
|
||||
var/cap_length = 8//D E P T H (cap = capacity)
|
||||
var/cap_girth = 12
|
||||
var/cap_girth_ratio = 1.5
|
||||
var/clits = 1
|
||||
var/clit_diam = 0.25
|
||||
var/clit_len = 0.25
|
||||
var/clits = 1
|
||||
var/clit_diam = 0.25
|
||||
var/clit_len = 0.25
|
||||
var/list/vag_types = list("tentacle", "dentata", "hairy", "spade", "furred")
|
||||
|
||||
|
||||
/obj/item/organ/genital/vagina/update_appearance()
|
||||
. = ..()
|
||||
var/string //Keeping this code here, so making multiple sprites for the different kinds is easier.
|
||||
var/lowershape = lowertext(shape)
|
||||
var/details
|
||||
@@ -63,12 +62,10 @@
|
||||
icon_state = sanitize_text(string)
|
||||
H.update_genitals()
|
||||
|
||||
/obj/item/organ/genital/vagina/update_link()
|
||||
if(owner)
|
||||
linked_organ = (owner.getorganslot("womb"))
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = src
|
||||
/obj/item/organ/genital/vagina/get_features(mob/living/carbon/human/H)
|
||||
var/datum/dna/D = H.dna
|
||||
if(D.species.use_skintones && D.features["genitals_use_skintone"])
|
||||
color = "#[skintone2hex(H.skin_tone)]"
|
||||
else
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = null
|
||||
linked_organ = null
|
||||
color = "[D.features["vag_color"]]"
|
||||
shape = "[D.features["vag_shape"]]"
|
||||
|
||||
@@ -1,45 +1,10 @@
|
||||
/obj/item/organ/genital/womb
|
||||
name = "womb"
|
||||
desc = "A female reproductive organ."
|
||||
icon = 'modular_citadel/icons/obj/genitals/vagina.dmi'
|
||||
icon_state = "womb"
|
||||
zone = "groin"
|
||||
slot = "womb"
|
||||
internal = TRUE
|
||||
fluid_id = "femcum"
|
||||
producing = TRUE
|
||||
|
||||
/obj/item/organ/genital/womb/on_life()
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(reagents && producing)
|
||||
if(reagents.total_volume == 0) // Apparently, 0.015 gets rounded down to zero and no reagents are created if we don't start it with 0.1 in the tank.
|
||||
fluid_rate = 0.1
|
||||
else
|
||||
fluid_rate = CUM_RATE
|
||||
if(reagents.total_volume >= 5)
|
||||
fluid_mult = 0.5
|
||||
else
|
||||
fluid_mult = 1
|
||||
generate_femcum()
|
||||
|
||||
/obj/item/organ/genital/womb/proc/generate_femcum()
|
||||
reagents.maximum_volume = fluid_max_volume
|
||||
update_link()
|
||||
if(!linked_organ)
|
||||
return FALSE
|
||||
reagents.isolate_reagent(fluid_id)//remove old reagents if it changed and just clean up generally
|
||||
reagents.add_reagent(fluid_id, (fluid_mult * fluid_rate))//generate the cum
|
||||
|
||||
/obj/item/organ/genital/womb/update_link()
|
||||
if(owner)
|
||||
linked_organ = (owner.getorganslot("vagina"))
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = src
|
||||
else
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = null
|
||||
linked_organ = null
|
||||
|
||||
/obj/item/organ/genital/womb/Destroy()
|
||||
return ..()
|
||||
name = "womb"
|
||||
desc = "A female reproductive organ."
|
||||
icon = 'modular_citadel/icons/obj/genitals/vagina.dmi'
|
||||
icon_state = "womb"
|
||||
zone = BODY_ZONE_PRECISE_GROIN
|
||||
slot = ORGAN_SLOT_WOMB
|
||||
genital_flags = GENITAL_INTERNAL|GENITAL_FUID_PRODUCTION
|
||||
fluid_id = "femcum"
|
||||
linked_organ_slot = ORGAN_SLOT_VAGINA
|
||||
|
||||
@@ -64,6 +64,64 @@
|
||||
category = SLOT_WEAR_SUIT
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat
|
||||
|
||||
/* Commented out until it is "balanced"
|
||||
/datum/gear/coat/sec
|
||||
name = "Security winter coat"
|
||||
category = SLOT_WEAR_SUIT
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/security
|
||||
restricted_roles = list("Head of Security", "Warden", "Detective", "Security Officer") // Reserve it to the Security Departement
|
||||
*/
|
||||
|
||||
/datum/gear/coat/med
|
||||
name = "Medical winter coat"
|
||||
category = SLOT_WEAR_SUIT
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/medical
|
||||
restricted_roles = list("Chief Medical Officer", "Medical Doctor") // Reserve it to Medical Doctors and their boss, the Chief Medical Officer
|
||||
|
||||
/* Commented out until there is a Chemistry Winter Coat
|
||||
/datum/gear/coat/med/chem
|
||||
name = "Chemistry winter coat"
|
||||
category = SLOT_WEAR_SUIT
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/medical/chemistry
|
||||
restricted_roles = list("Chief Medical Officer", "Chemist") // Reserve it to Chemists and their boss, the Chief Medical Officer
|
||||
*/
|
||||
|
||||
/datum/gear/coat/sci
|
||||
name = "Science winter coat"
|
||||
category = SLOT_WEAR_SUIT
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/science
|
||||
restricted_roles = list("Research Director", "Scientist", "Roboticist") // Reserve it to the Science Departement
|
||||
|
||||
/datum/gear/coat/eng
|
||||
name = "Engineering winter coat"
|
||||
category = SLOT_WEAR_SUIT
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/engineering
|
||||
restricted_roles = list("Chief Engineer", "Station Engineer") // Reserve it to Station Engineers and their boss, the Chief Engineer
|
||||
|
||||
/datum/gear/coat/eng/atmos
|
||||
name = "Atmospherics winter coat"
|
||||
category = SLOT_WEAR_SUIT
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/engineering/atmos
|
||||
restricted_roles = list("Chief Engineer", "Atmospheric Technician") // Reserve it to Atmos Techs and their boss, the Chief Engineer
|
||||
|
||||
/datum/gear/coat/hydro
|
||||
name = "Hydroponics winter coat"
|
||||
category = SLOT_WEAR_SUIT
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/hydro
|
||||
restricted_roles = list("Head of Personnel", "Botanist") // Reserve it to Botanists and their boss, the Head of Personnel
|
||||
|
||||
/datum/gear/coat/cargo
|
||||
name = "Cargo winter coat"
|
||||
category = SLOT_WEAR_SUIT
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/cargo
|
||||
restricted_roles = list("Quartermaster", "Cargo Technician") // Reserve it to Cargo Techs and their boss, the Quartermaster
|
||||
|
||||
/datum/gear/coat/miner
|
||||
name = "Mining winter coat"
|
||||
category = SLOT_WEAR_SUIT
|
||||
path = /obj/item/clothing/suit/hooded/wintercoat/miner
|
||||
restricted_roles = list("Quartermaster", "Shaft Miner") // Reserve it to Miners and their boss, the Quartermaster
|
||||
|
||||
/datum/gear/militaryjacket
|
||||
name = "Military Jacket"
|
||||
category = SLOT_WEAR_SUIT
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
WRITE_FILE(S["feature_ipc_antenna"], features["ipc_antenna"])
|
||||
//Citadel
|
||||
WRITE_FILE(S["feature_genitals_use_skintone"], features["genitals_use_skintone"])
|
||||
WRITE_FILE(S["feature_exhibitionist"], features["exhibitionist"])
|
||||
WRITE_FILE(S["feature_mcolor2"], features["mcolor2"])
|
||||
WRITE_FILE(S["feature_mcolor3"], features["mcolor3"])
|
||||
WRITE_FILE(S["feature_mam_body_markings"], features["mam_body_markings"])
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
if(istype(user) && combatmodestate && world.time >= nextadrenalinepop)
|
||||
nextadrenalinepop = world.time + 5 MINUTES
|
||||
user.reagents.add_reagent("syndicateadrenals", 5)
|
||||
user.playsound_local(user, 'modular_citadel/sound/misc/adrenalinject.ogg', 100, 0, pressure_affected = FALSE)
|
||||
user.playsound_local(user, 'sound/misc/adrenalinject.ogg', 100, 0, pressure_affected = FALSE)
|
||||
|
||||
/obj/item/clothing/glasses/phantomthief/syndicate/equipped(mob/user, slot)
|
||||
. = ..()
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
/datum/action/item_action/zanderlocket/Trigger()
|
||||
new/obj/effect/temp_visual/souldeath(owner.loc, owner)
|
||||
playsound(owner, 'modular_citadel/sound/misc/souldeath.ogg', 100, FALSE)
|
||||
playsound(owner, 'sound/misc/souldeath.ogg', 100, FALSE)
|
||||
|
||||
|
||||
/obj/item/clothing/neck/undertale/Initialize()
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
if(voremode)
|
||||
toggle_vore_mode()
|
||||
if(combatmode)
|
||||
playsound_local(src, 'modular_citadel/sound/misc/ui_toggle.ogg', 50, FALSE, pressure_affected = FALSE) //Sound from interbay!
|
||||
playsound_local(src, 'sound/misc/ui_toggle.ogg', 50, FALSE, pressure_affected = FALSE) //Sound from interbay!
|
||||
else
|
||||
playsound_local(src, 'modular_citadel/sound/misc/ui_toggleoff.ogg', 50, FALSE, pressure_affected = FALSE) //Slightly modified version of the above!
|
||||
playsound_local(src, 'sound/misc/ui_toggleoff.ogg', 50, FALSE, pressure_affected = FALSE) //Slightly modified version of the above!
|
||||
if(client)
|
||||
client.show_popup_menus = !combatmode // So we can right-click for alternate actions and all that other good shit. Also moves examine to shift+rightclick to make it possible to attack while sprinting
|
||||
if(hud_used && hud_used.static_inventory)
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
sprinting = !sprinting
|
||||
if(!resting && m_intent == MOVE_INTENT_RUN && canmove)
|
||||
if(sprinting)
|
||||
playsound_local(src, 'modular_citadel/sound/misc/sprintactivate.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
playsound_local(src, 'sound/misc/sprintactivate.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
else
|
||||
playsound_local(src, 'modular_citadel/sound/misc/sprintdeactivate.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
playsound_local(src, 'sound/misc/sprintdeactivate.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
if(hud_used && hud_used.static_inventory)
|
||||
for(var/obj/screen/sprintbutton/selector in hud_used.static_inventory)
|
||||
selector.insert_witty_toggle_joke_here(src)
|
||||
|
||||
@@ -13,13 +13,23 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
|
||||
w_class = 3
|
||||
hitsound = 'sound/weapons/bite.ogg'
|
||||
sharpness = IS_SHARP
|
||||
var/stamtostunconversion = 0.1 //Total stamloss gets multiplied by this value for the help intent hard stun. Resting adds an additional 2x multiplier on top. Keep this low or so help me god.
|
||||
var/stuncooldown = 4 SECONDS //How long it takes before you're able to attempt to stun a target again
|
||||
var/nextstuntime
|
||||
|
||||
/obj/item/dogborg/jaws/examine(mob/user)
|
||||
. = ..()
|
||||
if(!CONFIG_GET(flag/weaken_secborg))
|
||||
to_chat(user, "<span class='notice'>Use help intent to attempt to non-lethally incapacitate the target by latching on with your maw. This is more effective against exhausted and resting targets.</span>")
|
||||
|
||||
/obj/item/dogborg/jaws/big
|
||||
name = "combat jaws"
|
||||
desc = "The jaws of the law. Very sharp."
|
||||
icon_state = "jaws"
|
||||
force = 10 //Lowered to match secborg. No reason it should be more than a secborg's baton.
|
||||
force = 15 //Chomp chomp. Crew harm.
|
||||
attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced")
|
||||
stamtostunconversion = 0.2 // 100*0.2*2=40. Stun's just long enough to slap on cuffs with click delay if the target is near hard stamcrit.
|
||||
stuncooldown = 6 SECONDS
|
||||
|
||||
|
||||
/obj/item/dogborg/jaws/small
|
||||
@@ -31,11 +41,36 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
|
||||
var/status = 0
|
||||
|
||||
/obj/item/dogborg/jaws/attack(atom/A, mob/living/silicon/robot/user)
|
||||
..()
|
||||
user.do_attack_animation(A, ATTACK_EFFECT_BITE)
|
||||
if(!istype(user))
|
||||
return
|
||||
if(!CONFIG_GET(flag/weaken_secborg) && user.a_intent != INTENT_HARM && istype(A, /mob/living))
|
||||
if(A == user.pulling)
|
||||
to_chat(user, "<span class='warning'>You already have [A] in your jaws.</span>")
|
||||
return
|
||||
if(nextstuntime >= world.time)
|
||||
to_chat(user, "<span class='warning'>Your jaw servos are still recharging.</span>")
|
||||
return
|
||||
nextstuntime = world.time + stuncooldown
|
||||
var/mob/living/M = A
|
||||
var/cachedstam = M.getStaminaLoss()
|
||||
var/totalstuntime = cachedstam * stamtostunconversion * (M.lying ? 2 : 1)
|
||||
if(!M.resting)
|
||||
M.Knockdown(cachedstam*2) //BORK BORK. GET DOWN.
|
||||
M.Stun(totalstuntime)
|
||||
user.do_attack_animation(A, ATTACK_EFFECT_BITE)
|
||||
user.start_pulling(M, TRUE) //Yip yip. Come with.
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
M.visible_message("<span class='danger'>[user] clamps [user.p_their()] [src] onto [M] and latches on!</span>", "<span class='userdanger'>[user] clamps [user.p_their()] [src] onto you and latches on!</span>")
|
||||
if(totalstuntime >= 4 SECONDS)
|
||||
playsound(usr, 'sound/effects/k9_jaw_strong.ogg', 75, FALSE, 2) //Wuff wuff. Big stun.
|
||||
else
|
||||
playsound(usr, 'sound/effects/k9_jaw_weak.ogg', 50, TRUE, -1) //Arf arf. Pls buff.
|
||||
else
|
||||
. = ..()
|
||||
user.do_attack_animation(A, ATTACK_EFFECT_BITE)
|
||||
|
||||
/obj/item/dogborg/jaws/small/attack_self(mob/user)
|
||||
var/mob/living/silicon/robot.R = user
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(R.cell && R.cell.charge > 100)
|
||||
if(R.emagged && status == 0)
|
||||
name = "combat jaws"
|
||||
@@ -43,14 +78,18 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
|
||||
desc = "The jaws of the law."
|
||||
force = 12
|
||||
attack_verb = list("chomped", "bit", "ripped", "mauled", "enforced")
|
||||
stamtostunconversion = 0.15
|
||||
stuncooldown = 5 SECONDS
|
||||
status = 1
|
||||
to_chat(user, "<span class='notice'>Your jaws are now [status ? "Combat" : "Pup'd"].</span>")
|
||||
else
|
||||
name = "puppy jaws"
|
||||
icon_state = "smalljaws"
|
||||
desc = "The jaws of a small dog."
|
||||
force = 5
|
||||
force = initial(force)
|
||||
attack_verb = list("nibbled", "bit", "gnawed", "chomped", "nommed")
|
||||
stamtostunconversion = initial(stamtostunconversion)
|
||||
stuncooldown = initial(stuncooldown)
|
||||
status = 0
|
||||
if(R.emagged)
|
||||
to_chat(user, "<span class='notice'>Your jaws are now [status ? "Combat" : "Pup'd"].</span>")
|
||||
@@ -167,7 +206,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
|
||||
item_flags |= NOBLUDGEON //No more attack messages
|
||||
|
||||
/obj/item/soap/tongue/attack_self(mob/user)
|
||||
var/mob/living/silicon/robot.R = user
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(R.cell && R.cell.charge > 100)
|
||||
if(R.emagged && status == 0)
|
||||
status = !status
|
||||
@@ -187,7 +226,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
|
||||
update_icon()
|
||||
|
||||
/obj/item/soap/tongue/afterattack(atom/target, mob/user, proximity)
|
||||
var/mob/living/silicon/robot.R = user
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(!proximity || !check_allowed_items(target))
|
||||
return
|
||||
if(R.client && (target in R.client.screen))
|
||||
@@ -343,8 +382,10 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
|
||||
/mob/living/silicon/robot
|
||||
var/leaping = 0
|
||||
var/pounce_cooldown = 0
|
||||
var/pounce_cooldown_time = 20 //Buffed to counter balance changes
|
||||
var/pounce_spoolup = 1
|
||||
var/pounce_cooldown_time = 30 //Time in deciseconds between pounces
|
||||
var/pounce_spoolup = 5 //Time in deciseconds for the pounce to happen after clicking
|
||||
var/pounce_stamloss_cap = 120 //How much staminaloss pounces alone are capable of bringing a spaceman to
|
||||
var/pounce_stamloss = 80 //Base staminaloss value of the pounce
|
||||
var/leap_at
|
||||
var/disabler
|
||||
var/laser
|
||||
@@ -356,13 +397,12 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
|
||||
|
||||
/obj/item/dogborg/pounce/afterattack(atom/A, mob/user)
|
||||
var/mob/living/silicon/robot/R = user
|
||||
if(R && !R.pounce_cooldown)
|
||||
R.pounce_cooldown = !R.pounce_cooldown
|
||||
if(R && (world.time >= R.pounce_cooldown))
|
||||
R.pounce_cooldown = world.time + R.pounce_cooldown_time
|
||||
to_chat(R, "<span class ='warning'>Your targeting systems lock on to [A]...</span>")
|
||||
playsound(R, 'sound/effects/servostep.ogg', 100, TRUE)
|
||||
addtimer(CALLBACK(R, /mob/living/silicon/robot.proc/leap_at, A), R.pounce_spoolup)
|
||||
spawn(R.pounce_cooldown_time)
|
||||
R.pounce_cooldown = !R.pounce_cooldown
|
||||
else if(R && R.pounce_cooldown)
|
||||
else if(R && (world.time < R.pounce_cooldown))
|
||||
to_chat(R, "<span class='danger'>Your leg actuators are still recharging!</span>")
|
||||
|
||||
/mob/living/silicon/robot/proc/leap_at(atom/A)
|
||||
@@ -385,6 +425,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
|
||||
update_icons()
|
||||
throw_at(A, MAX_K9_LEAP_DIST, 1, spin=0, diagonals_first = 1)
|
||||
cell.use(750) //Less than a stunbaton since stunbatons hit everytime.
|
||||
playsound(src, 'sound/effects/stealthoff.ogg', 25, TRUE, -1)
|
||||
weather_immunities -= "lava"
|
||||
|
||||
/mob/living/silicon/robot/throw_impact(atom/A)
|
||||
@@ -402,7 +443,7 @@ SLEEPER CODE IS IN game/objects/items/devices/dogborg_sleeper.dm !
|
||||
blocked = 1
|
||||
if(!blocked)
|
||||
L.visible_message("<span class ='danger'>[src] pounces on [L]!</span>", "<span class ='userdanger'>[src] pounces on you!</span>")
|
||||
L.Knockdown(iscarbon(L) ? 225 : 45) // Temporary. If someone could rework how dogborg pounces work to accomodate for combat changes, that'd be nice.
|
||||
L.Knockdown(iscarbon(L) ? 60 : 45, override_stamdmg = CLAMP(pounce_stamloss, 0, pounce_stamloss_cap-L.getStaminaLoss())) // Temporary. If someone could rework how dogborg pounces work to accomodate for combat changes, that'd be nice.
|
||||
playsound(src, 'sound/weapons/Egloves.ogg', 50, 1)
|
||||
sleep(2)//Runtime prevention (infinite bump() calls on hulks)
|
||||
step_towards(src,L)
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
sprinting = shutdown ? FALSE : !sprinting
|
||||
if(!resting && canmove)
|
||||
if(sprinting)
|
||||
playsound_local(src, 'modular_citadel/sound/misc/sprintactivate.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
playsound_local(src, 'sound/misc/sprintactivate.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
else
|
||||
if(shutdown)
|
||||
playsound_local(src, 'sound/effects/light_flicker.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
playsound_local(src, 'modular_citadel/sound/misc/sprintdeactivate.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
playsound_local(src, 'sound/misc/sprintdeactivate.ogg', 50, FALSE, pressure_affected = FALSE)
|
||||
if(hud_used && hud_used.static_inventory)
|
||||
for(var/obj/screen/sprintbutton/selector in hud_used.static_inventory)
|
||||
selector.insert_witty_toggle_joke_here(src)
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
/obj/item/seeds/banana/Initialize()
|
||||
. = ..()
|
||||
mutatelist += /obj/item/seeds/banana/exotic_banana
|
||||
|
||||
|
||||
/obj/item/seeds/banana/exotic_banana
|
||||
name = "pack of exotic banana seeds"
|
||||
desc = "They're seeds that grow into banana trees. However, those bananas might be alive."
|
||||
icon = 'modular_citadel/icons/mob/BananaSpider.dmi'
|
||||
icon_state = "seed_ExoticBanana"
|
||||
species = "banana"
|
||||
plantname = "Exotic Banana Tree"
|
||||
product = /obj/item/reagent_containers/food/snacks/grown/banana/banana_spider_spawnable
|
||||
growing_icon = 'modular_citadel/icons/mob/BananaSpider.dmi'
|
||||
icon_dead = "banana-dead"
|
||||
mutatelist = list()
|
||||
genes = list(/datum/plant_gene/trait/slip)
|
||||
reagents_add = list("banana" = 0.1, "potassium" = 0.1, "vitamin" = 0.04, "nutriment" = 0.02)
|
||||
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/banana/banana_spider_spawnable
|
||||
seed = /obj/item/seeds/banana/exotic_banana
|
||||
name = "banana spider"
|
||||
desc = "You do not know what it is, but you can bet the clown would love it."
|
||||
icon = 'modular_citadel/icons/mob/BananaSpider.dmi'
|
||||
icon_state = "banana"
|
||||
item_state = "banana"
|
||||
filling_color = "#FFFF00"
|
||||
list_reagents = list("nutriment" = 3, "vitamin" = 2)
|
||||
foodtype = GROSS | MEAT | RAW | FRUIT
|
||||
grind_results = list("blood" = 20, "liquidgibs" = 5)
|
||||
juice_results = list("banana" = 0)
|
||||
var/awakening = 0
|
||||
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/banana/banana_spider_spawnable/attack_self(mob/user)
|
||||
if(awakening || isspaceturf(user.loc))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You decide to wake up the banana spider...</span>")
|
||||
awakening = 1
|
||||
|
||||
spawn(30)
|
||||
if(!QDELETED(src))
|
||||
var/mob/living/simple_animal/banana_spider/S = new /mob/living/simple_animal/banana_spider(get_turf(src.loc))
|
||||
S.speed += round(10 / seed.potency)
|
||||
S.visible_message("<span class='notice'>The banana spider chitters as it stretches its legs.</span>")
|
||||
qdel(src)
|
||||
|
||||
|
||||
/mob/living/simple_animal/banana_spider
|
||||
icon = 'modular_citadel/icons/mob/BananaSpider.dmi'
|
||||
name = "banana spider"
|
||||
desc = "What the fuck is this abomination?"
|
||||
icon_state = "banana"
|
||||
icon_dead = "banana_peel"
|
||||
health = 1
|
||||
maxHealth = 1
|
||||
turns_per_move = 5 //this isn't player speed =|
|
||||
speed = 2 //this is player speed
|
||||
loot = list(/obj/item/reagent_containers/food/snacks/deadbanana_spider)
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
minbodytemp = 270
|
||||
maxbodytemp = INFINITY
|
||||
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
|
||||
mob_size = MOB_SIZE_TINY
|
||||
response_help = "pokes"
|
||||
response_disarm = "shoos"
|
||||
response_harm = "splats"
|
||||
speak_emote = list("chitters")
|
||||
mouse_opacity = 2
|
||||
density = TRUE
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
verb_say = "chitters"
|
||||
verb_ask = "chitters inquisitively"
|
||||
verb_exclaim = "chitters loudly"
|
||||
verb_yell = "chitters loudly"
|
||||
var/squish_chance = 50
|
||||
var/projectile_density = TRUE //griffons get shot
|
||||
del_on_death = TRUE
|
||||
|
||||
/mob/living/simple_animal/banana_spider/Initialize()
|
||||
. = ..()
|
||||
var/area/A = get_area(src)
|
||||
if(A)
|
||||
notify_ghosts("A banana spider has been created in \the [A.name].", source = src, action=NOTIFY_ATTACK, flashwindow = FALSE)
|
||||
|
||||
/mob/living/simple_animal/banana_spider/attack_ghost(mob/user)
|
||||
if(key) //please stop using src. without a good reason.
|
||||
return
|
||||
if(CONFIG_GET(flag/use_age_restriction_for_jobs))
|
||||
if(!isnum(user.client.player_age))
|
||||
return
|
||||
if(!SSticker.mode)
|
||||
to_chat(user, "Can't become a banana spider before the game has started.")
|
||||
return
|
||||
var/be_spider = alert("Become a banana spider? (Warning, You can no longer be cloned!)",,"Yes","No")
|
||||
if(be_spider == "No" || QDELETED(src) || !isobserver(user))
|
||||
return
|
||||
sentience_act()
|
||||
user.transfer_ckey(src, FALSE)
|
||||
density = TRUE
|
||||
|
||||
/mob/living/simple_animal/banana_spider/ComponentInitialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/slippery, 40)
|
||||
|
||||
/mob/living/simple_animal/banana_spider/Crossed(atom/movable/AM) //no /var in proc headers
|
||||
. = ..()
|
||||
if(istype(AM, /obj/item/projectile) && projectile_density) //forced projectile density
|
||||
var/obj/item/projectile/P = AM
|
||||
P.Bump(src)
|
||||
if(ismob(AM))
|
||||
if(isliving(AM))
|
||||
var/mob/living/A = AM
|
||||
if(A.mob_size > MOB_SIZE_SMALL && !(A.movement_type & FLYING))
|
||||
if(prob(squish_chance))
|
||||
A.visible_message("<span class='notice'>[A] squashed [src].</span>", "<span class='notice'>You squashed [src] under your weight as you fell.</span>")
|
||||
adjustBruteLoss(1)
|
||||
else
|
||||
visible_message("<span class='notice'>[src] avoids getting crushed.</span>")
|
||||
else
|
||||
if(isstructure(AM))
|
||||
if(prob(squish_chance))
|
||||
AM.visible_message("<span class='notice'>[src] was crushed under [AM]'s weight as they fell.</span>")
|
||||
adjustBruteLoss(1)
|
||||
else
|
||||
visible_message("<span class='notice'>[src] avoids getting crushed.</span>")
|
||||
|
||||
/mob/living/simple_animal/banana_spider/ex_act()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/banana_spider/start_pulling()
|
||||
return FALSE //No.
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/deadbanana_spider
|
||||
name = "dead banana spider"
|
||||
desc = "Thank god it's gone...but it does look slippery."
|
||||
icon = 'modular_citadel/icons/mob/BananaSpider.dmi'
|
||||
icon_state = "banana_peel"
|
||||
bitesize = 3
|
||||
eatverb = "devours"
|
||||
list_reagents = list("nutriment" = 3, "vitamin" = 2)
|
||||
foodtype = GROSS | MEAT | RAW
|
||||
grind_results = list("blood" = 20, "liquidgibs" = 5)
|
||||
juice_results = list("banana" = 0)
|
||||
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/deadbanana_spider/Initialize()
|
||||
. = ..()
|
||||
AddComponent(/datum/component/slippery, 20)
|
||||
@@ -1,134 +0,0 @@
|
||||
/mob/living/simple_animal/kiwi
|
||||
name = "space kiwi"
|
||||
desc = "Exposure to low gravity made them grow larger."
|
||||
gender = FEMALE
|
||||
icon = 'modular_citadel/icons/mob/kiwi.dmi'
|
||||
icon_state = "kiwi"
|
||||
icon_living = "kiwi"
|
||||
icon_dead = "dead"
|
||||
speak = list("Chirp!","Cheep cheep chirp!!","Cheep.")
|
||||
speak_emote = list("chirps","trills")
|
||||
emote_hear = list("chirps.")
|
||||
emote_see = list("pecks at the ground.","jumps in place.")
|
||||
density = FALSE
|
||||
speak_chance = 2
|
||||
turns_per_move = 3
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 3)
|
||||
var/egg_type = /obj/item/reagent_containers/food/snacks/egg/kiwiEgg
|
||||
var/food_type = /obj/item/reagent_containers/food/snacks/grown/wheat
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "kicks"
|
||||
attacktext = "kicks"
|
||||
health = 25
|
||||
maxHealth = 25
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
var/eggsleft = 0
|
||||
var/eggsFertile = TRUE
|
||||
pass_flags = PASSTABLE | PASSMOB
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
var/list/feedMessages = list("It chirps happily.","It chirps happily.")
|
||||
var/list/layMessage = list("lays an egg.","squats down and croons.","begins making a huge racket.","begins chirping raucously.")
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
var/static/kiwi_count = 0
|
||||
|
||||
/mob/living/simple_animal/kiwi/Destroy()
|
||||
--kiwi_count
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/kiwi/Initialize()
|
||||
. = ..()
|
||||
++kiwi_count
|
||||
|
||||
|
||||
/mob/living/simple_animal/kiwi/Life()
|
||||
. =..()
|
||||
if(!.)
|
||||
return
|
||||
if((!stat && prob(3) && eggsleft > 0) && egg_type)
|
||||
visible_message("[src] [pick(layMessage)]")
|
||||
eggsleft--
|
||||
var/obj/item/E = new egg_type(get_turf(src))
|
||||
E.pixel_x = rand(-6,6)
|
||||
E.pixel_y = rand(-6,6)
|
||||
if(eggsFertile)
|
||||
if(kiwi_count < MAX_CHICKENS && prob(25))
|
||||
START_PROCESSING(SSobj, E)
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/egg/kiwiEgg/process()
|
||||
if(isturf(loc))
|
||||
amount_grown += rand(1,2)
|
||||
if(amount_grown >= 100)
|
||||
visible_message("[src] hatches with a quiet cracking sound.")
|
||||
new /mob/living/simple_animal/babyKiwi(get_turf(src))
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
qdel(src)
|
||||
else
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
|
||||
|
||||
/mob/living/simple_animal/kiwi/attackby(obj/item/O, mob/user, params)
|
||||
if(istype(O, food_type)) //feedin' dem kiwis
|
||||
if(!stat && eggsleft < 8)
|
||||
var/feedmsg = "[user] feeds [O] to [name]! [pick(feedMessages)]"
|
||||
user.visible_message(feedmsg)
|
||||
qdel(O)
|
||||
eggsleft += rand(1, 4)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[name] doesn't seem hungry!</span>")
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
/mob/living/simple_animal/babyKiwi
|
||||
name = "baby space kiwi"
|
||||
desc = "So huggable."
|
||||
icon = 'modular_citadel/icons/mob/kiwi.dmi'
|
||||
icon_state = "babyKiwi"
|
||||
icon_living = "babyKiwi"
|
||||
icon_dead = "deadBaby"
|
||||
icon_gib = "chick_gib"
|
||||
gender = FEMALE
|
||||
speak = list("Cherp.","Cherp?","Chirrup.","Cheep!")
|
||||
speak_emote = list("chirps")
|
||||
emote_hear = list("chirps.")
|
||||
emote_see = list("pecks at the ground.","Happily bounces in place.")
|
||||
density = FALSE
|
||||
speak_chance = 2
|
||||
turns_per_move = 2
|
||||
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab = 2)
|
||||
response_help = "pets"
|
||||
response_disarm = "gently pushes aside"
|
||||
response_harm = "kicks"
|
||||
attacktext = "kicks"
|
||||
health = 10
|
||||
maxHealth = 10
|
||||
ventcrawler = VENTCRAWLER_ALWAYS
|
||||
var/amount_grown = 0
|
||||
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
|
||||
mob_size = MOB_SIZE_TINY
|
||||
gold_core_spawnable = FRIENDLY_SPAWN
|
||||
|
||||
/mob/living/simple_animal/babyKiwi/Initialize()
|
||||
. = ..()
|
||||
pixel_x = rand(-6, 6)
|
||||
pixel_y = rand(0, 10)
|
||||
|
||||
/mob/living/simple_animal/babyKiwi/Life()
|
||||
. =..()
|
||||
if(!.)
|
||||
return
|
||||
if(!stat && !ckey)
|
||||
amount_grown += rand(1,2)
|
||||
if(amount_grown >= 100)
|
||||
new /mob/living/simple_animal/kiwi(src.loc)
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/egg/kiwiEgg
|
||||
name = "kiwi egg"
|
||||
icon = 'modular_citadel/icons/mob/kiwi.dmi'
|
||||
desc = "A slightly bigger egg!"
|
||||
icon_state = "egg"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/obj/item/projectile/bullet/c46x30mm_tx
|
||||
name = "toxin tipped 4.6x30mm bullet"
|
||||
damage = 15
|
||||
damage = 10
|
||||
damage_type = TOX
|
||||
@@ -57,10 +57,9 @@
|
||||
icon_state = "magjectile-nl"
|
||||
damage = 2
|
||||
knockdown = 0
|
||||
stamina = 25
|
||||
armour_penetration = -10
|
||||
stamina = 20
|
||||
light_range = 2
|
||||
speed = 0.7
|
||||
speed = 0.6
|
||||
range = 25
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
@@ -109,9 +108,10 @@
|
||||
fire_sound = 'sound/weapons/magpistol.ogg'
|
||||
mag_type = /obj/item/ammo_box/magazine/mmag/small
|
||||
can_suppress = 0
|
||||
casing_ejector = 0
|
||||
casing_ejector = FALSE
|
||||
fire_delay = 2
|
||||
recoil = 0.2
|
||||
recoil = 0.1
|
||||
inaccuracy_modifier = 0.25
|
||||
|
||||
/obj/item/gun/ballistic/automatic/pistol/mag/update_icon()
|
||||
..()
|
||||
@@ -123,7 +123,6 @@
|
||||
icon_state = "[initial(icon_state)][chambered ? "" : "-e"]"
|
||||
|
||||
///research memes///
|
||||
/*
|
||||
/obj/item/gun/ballistic/automatic/pistol/mag/nopin
|
||||
pin = null
|
||||
spawnwithmagazine = FALSE
|
||||
@@ -155,7 +154,7 @@
|
||||
materials = list(MAT_METAL = 3000, MAT_SILVER = 250, MAT_TITANIUM = 250)
|
||||
build_path = /obj/item/ammo_box/magazine/mmag/small
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
|
||||
*/
|
||||
|
||||
//////toy memes/////
|
||||
|
||||
/obj/item/projectile/bullet/reusable/foam_dart/mag
|
||||
@@ -201,9 +200,9 @@
|
||||
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "magjectile-large"
|
||||
damage = 20
|
||||
armour_penetration = 25
|
||||
armour_penetration = 20
|
||||
light_range = 3
|
||||
speed = 0.7
|
||||
speed = 0.6
|
||||
range = 35
|
||||
light_color = LIGHT_COLOR_RED
|
||||
|
||||
@@ -212,10 +211,10 @@
|
||||
icon_state = "magjectile-large-nl"
|
||||
damage = 2
|
||||
knockdown = 0
|
||||
stamina = 25
|
||||
armour_penetration = -10
|
||||
stamina = 20
|
||||
armour_penetration = 10
|
||||
light_range = 3
|
||||
speed = 0.65
|
||||
speed = 0.6
|
||||
range = 35
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
|
||||
@@ -227,6 +226,8 @@
|
||||
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "mag-casing-live"
|
||||
projectile_type = /obj/item/projectile/bullet/magrifle
|
||||
click_cooldown_override = 2.5
|
||||
delay = 3
|
||||
|
||||
/obj/item/ammo_casing/caseless/anlmagm
|
||||
desc = "A large, specialized ferromagnetic slug designed with a less-than-lethal payload."
|
||||
@@ -234,10 +235,12 @@
|
||||
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "mag-casing-live"
|
||||
projectile_type = /obj/item/projectile/bullet/nlmagrifle
|
||||
click_cooldown_override = 2.5
|
||||
delay = 3
|
||||
|
||||
///magazines///
|
||||
|
||||
/obj/item/ammo_box/magazine/mmag/
|
||||
/obj/item/ammo_box/magazine/mmag
|
||||
name = "magrifle magazine (non-lethal disabler)"
|
||||
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "mediummagmag"
|
||||
@@ -261,17 +264,20 @@
|
||||
icon = 'modular_citadel/icons/obj/guns/cit_guns.dmi'
|
||||
icon_state = "magrifle"
|
||||
item_state = "arg"
|
||||
slot_flags = 0
|
||||
slot_flags = NONE
|
||||
mag_type = /obj/item/ammo_box/magazine/mmag
|
||||
fire_sound = 'sound/weapons/magrifle.ogg'
|
||||
can_suppress = 0
|
||||
burst_size = 3
|
||||
fire_delay = 2
|
||||
spread = 5
|
||||
recoil = 0.15
|
||||
casing_ejector = 0
|
||||
burst_size = 1
|
||||
actions_types = null
|
||||
fire_delay = 3
|
||||
spread = 0
|
||||
recoil = 0.1
|
||||
casing_ejector = FALSE
|
||||
inaccuracy_modifier = 0.5
|
||||
weapon_weight = WEAPON_MEDIUM
|
||||
dualwield_spread_mult = 1.4
|
||||
|
||||
/*
|
||||
//research///
|
||||
|
||||
/obj/item/gun/ballistic/automatic/magrifle/nopin
|
||||
@@ -305,7 +311,7 @@
|
||||
materials = list(MAT_METAL = 6000, MAT_SILVER = 500, MAT_TITANIUM = 500)
|
||||
build_path = /obj/item/ammo_box/magazine/mmag
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
|
||||
*/
|
||||
|
||||
///foamagrifle///
|
||||
|
||||
/obj/item/ammo_box/magazine/toy/foamag
|
||||
@@ -327,7 +333,6 @@
|
||||
spread = 60
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
weapon_weight = WEAPON_HEAVY
|
||||
/*
|
||||
// TECHWEBS IMPLEMENTATION
|
||||
//
|
||||
|
||||
@@ -339,7 +344,6 @@
|
||||
design_ids = list("magrifle", "magpisol", "mag_magrifle", "mag_magrifle_nl", "mag_magpistol", "mag_magpistol_nl")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
export_price = 5000
|
||||
*/
|
||||
|
||||
//////Hyper-Burst Rifle//////
|
||||
|
||||
|
||||
@@ -143,6 +143,7 @@
|
||||
// TECHWEBS IMPLEMENTATION
|
||||
*/
|
||||
|
||||
/*
|
||||
/datum/techweb_node/magnetic_weapons
|
||||
id = "magnetic_weapons"
|
||||
display_name = "Magnetic Weapons"
|
||||
@@ -151,6 +152,7 @@
|
||||
design_ids = list("magrifle_e", "magpistol_e", "mag_magrifle_e", "mag_magrifle_e_nl", "mag_magpistol_e", "mag_magpistol_e_nl")
|
||||
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500)
|
||||
export_price = 5000
|
||||
*/
|
||||
|
||||
///magrifle///
|
||||
|
||||
|
||||
@@ -1,13 +1,6 @@
|
||||
/obj/item/gun/energy/e_gun
|
||||
name = "blaster carbine"
|
||||
desc = "A high powered particle blaster carbine with varitable setting for stunning or lethal applications."
|
||||
icon = 'modular_citadel/icons/obj/guns/OVERRIDE_energy.dmi'
|
||||
lefthand_file = 'modular_citadel/icons/mob/inhands/OVERRIDE_guns_lefthand.dmi'
|
||||
righthand_file = 'modular_citadel/icons/mob/inhands/OVERRIDE_guns_righthand.dmi'
|
||||
ammo_x_offset = 2
|
||||
flight_x_offset = 17
|
||||
flight_y_offset = 11
|
||||
|
||||
|
||||
/*/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
The Recolourable Energy Gun
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
/obj/item/gun/energy/laser
|
||||
name = "blaster rifle"
|
||||
desc = "a high energy particle blaster, efficient and deadly."
|
||||
icon = 'modular_citadel/icons/obj/guns/OVERRIDE_energy.dmi'
|
||||
ammo_x_offset = 1
|
||||
shaded_charge = 1
|
||||
lefthand_file = 'modular_citadel/icons/mob/inhands/OVERRIDE_guns_lefthand.dmi'
|
||||
righthand_file = 'modular_citadel/icons/mob/inhands/OVERRIDE_guns_righthand.dmi'
|
||||
|
||||
/obj/item/gun/energy/laser/practice
|
||||
icon = 'modular_citadel/icons/obj/guns/energy.dmi'
|
||||
icon_state = "laser-p"
|
||||
|
||||
/obj/item/gun/energy/laser/bluetag
|
||||
lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi'
|
||||
|
||||
/obj/item/gun/energy/laser/redtag
|
||||
lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi'
|
||||
lefthand_file = 'modular_citadel/icons/mob/inhands/OVERRIDE_guns_lefthand.dmi'
|
||||
righthand_file = 'modular_citadel/icons/mob/inhands/OVERRIDE_guns_righthand.dmi'
|
||||
ammo_x_offset = 1
|
||||
shaded_charge = 1
|
||||
|
||||
@@ -75,9 +75,9 @@
|
||||
/obj/item/gun/energy/pumpaction/proc/pump(mob/M) //pumping proc. Checks if the gun is empty and plays a different sound if it is.
|
||||
var/obj/item/ammo_casing/energy/shot = ammo_type[select]
|
||||
if(cell.charge < shot.e_cost)
|
||||
playsound(M, 'modular_citadel/sound/weapons/laserPumpEmpty.ogg', 100, 1) //Ends with three beeps made from highly processed knife honing noises
|
||||
playsound(M, 'sound/weapons/laserPumpEmpty.ogg', 100, 1) //Ends with three beeps made from highly processed knife honing noises
|
||||
else
|
||||
playsound(M, 'modular_citadel/sound/weapons/laserPump.ogg', 100, 1) //Ends with high pitched charging noise
|
||||
playsound(M, 'sound/weapons/laserPump.ogg', 100, 1) //Ends with high pitched charging noise
|
||||
recharge_newshot() //try to charge a new shot
|
||||
update_icon()
|
||||
return 1
|
||||
@@ -152,14 +152,14 @@
|
||||
e_cost = 150
|
||||
pellets = 4
|
||||
variance = 30
|
||||
fire_sound = 'modular_citadel/sound/weapons/ParticleBlaster.ogg'
|
||||
fire_sound = 'sound/weapons/ParticleBlaster.ogg'
|
||||
select_name = "disable"
|
||||
|
||||
/obj/item/ammo_casing/energy/disabler/slug
|
||||
projectile_type = /obj/item/projectile/beam/disabler/slug
|
||||
select_name = "overdrive"
|
||||
e_cost = 200
|
||||
fire_sound = 'modular_citadel/sound/weapons/LaserSlugv3.ogg'
|
||||
fire_sound = 'sound/weapons/LaserSlugv3.ogg'
|
||||
|
||||
/obj/item/ammo_casing/energy/laser/pump
|
||||
projectile_type = /obj/item/projectile/beam/weak
|
||||
@@ -167,12 +167,12 @@
|
||||
select_name = "kill"
|
||||
pellets = 3
|
||||
variance = 15
|
||||
fire_sound = 'modular_citadel/sound/weapons/ParticleBlaster.ogg'
|
||||
fire_sound = 'sound/weapons/ParticleBlaster.ogg'
|
||||
|
||||
/obj/item/ammo_casing/energy/electrode/pump
|
||||
projectile_type = /obj/item/projectile/energy/electrode/pump
|
||||
select_name = "stun"
|
||||
fire_sound = 'modular_citadel/sound/weapons/LaserSlugv3.ogg'
|
||||
fire_sound = 'sound/weapons/LaserSlugv3.ogg'
|
||||
e_cost = 300
|
||||
pellets = 3
|
||||
variance = 20
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
projectile_type = /obj/item/projectile/beam/lasertag/wavemotion
|
||||
select_name = "overdrive"
|
||||
e_cost = 300
|
||||
fire_sound = 'modular_citadel/sound/weapons/LaserSlugv3.ogg'
|
||||
fire_sound = 'sound/weapons/LaserSlugv3.ogg'
|
||||
|
||||
/obj/item/ammo_casing/energy/laser/dispersal
|
||||
projectile_type = /obj/item/projectile/beam/lasertag/dispersal
|
||||
@@ -47,7 +47,7 @@
|
||||
pellets = 5
|
||||
variance = 25
|
||||
e_cost = 200
|
||||
fire_sound = 'modular_citadel/sound/weapons/ParticleBlaster.ogg'
|
||||
fire_sound = 'sound/weapons/ParticleBlaster.ogg'
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//TOY REVOLVER
|
||||
|
||||
@@ -94,6 +94,7 @@ IMPORTANT FACTORS TO CONSIDER WHILE BALANCING
|
||||
if(!SM.mind) //Something went wrong, use alt mechanics
|
||||
return ..()
|
||||
SM.mind.enslave_mind_to_creator(M)
|
||||
SM.mind.store_memory(M.mind.memory)
|
||||
|
||||
//If they're a zombie, they can try to negate it with this.
|
||||
//I seriously wonder if anyone will ever use this function.
|
||||
|
||||
@@ -30,17 +30,15 @@
|
||||
inverse_chem_val = 0.35
|
||||
inverse_chem = "BEsmaller" //At really impure vols, it just becomes 100% inverse
|
||||
can_synth = FALSE
|
||||
var/message_spam = FALSE
|
||||
|
||||
/datum/reagent/fermi/breast_enlarger/on_mob_add(mob/living/carbon/M)
|
||||
/datum/reagent/fermi/breast_enlarger/on_mob_metabolize(mob/living/M)
|
||||
. = ..()
|
||||
if(!ishuman(M)) //The monkey clause
|
||||
if(volume >= 15) //To prevent monkey breast farms
|
||||
var/turf/T = get_turf(M)
|
||||
var/obj/item/organ/genital/breasts/B = new /obj/item/organ/genital/breasts(T)
|
||||
var/list/seen = viewers(8, T)
|
||||
for(var/mob/S in seen)
|
||||
to_chat(S, "<span class='warning'>A pair of breasts suddenly fly out of the [M]!</b></span>")
|
||||
//var/turf/T2 = pick(turf in view(5, M))
|
||||
M.visible_message("<span class='warning'>A pair of breasts suddenly fly out of the [M]!</b></span>")
|
||||
var/T2 = get_random_station_turf()
|
||||
M.adjustBruteLoss(25)
|
||||
M.Knockdown(50)
|
||||
@@ -48,94 +46,82 @@
|
||||
B.throw_at(T2, 8, 1)
|
||||
M.reagents.remove_reagent(id, volume)
|
||||
return
|
||||
log_game("FERMICHEM: [M] ckey: [M.key] has ingested Sucubus milk")
|
||||
var/mob/living/carbon/human/H = M
|
||||
H.genital_override = TRUE
|
||||
var/obj/item/organ/genital/breasts/B = H.getorganslot("breasts")
|
||||
if(!B)
|
||||
H.emergent_genital_call()
|
||||
return
|
||||
if(!B.size == "huge")
|
||||
var/sizeConv = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5)
|
||||
B.prev_size = B.size
|
||||
B.cached_size = sizeConv[B.size]
|
||||
if(!H.getorganslot(ORGAN_SLOT_BREASTS) && H.emergent_genital_call())
|
||||
H.genital_override = TRUE
|
||||
|
||||
/datum/reagent/fermi/breast_enlarger/on_mob_life(mob/living/carbon/M) //Increases breast size
|
||||
if(!ishuman(M))//Just in case
|
||||
return..()
|
||||
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/genital/breasts/B = M.getorganslot("breasts")
|
||||
var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS)
|
||||
if(!B) //If they don't have breasts, give them breasts.
|
||||
|
||||
//If they have Acute hepatic pharmacokinesis, then route processing though liver.
|
||||
if(HAS_TRAIT(M, TRAIT_PHARMA))
|
||||
var/obj/item/organ/liver/L = M.getorganslot("liver")
|
||||
if(HAS_TRAIT(H, TRAIT_PHARMA) || !H.canbearoused)
|
||||
var/obj/item/organ/liver/L = H.getorganslot(ORGAN_SLOT_LIVER)
|
||||
if(L)
|
||||
L.swelling+= 0.05
|
||||
return..()
|
||||
L.swelling += 0.05
|
||||
else
|
||||
M.adjustToxLoss(1)
|
||||
return..()
|
||||
H.adjustToxLoss(1)
|
||||
return..()
|
||||
|
||||
//otherwise proceed as normal
|
||||
var/obj/item/organ/genital/breasts/nB = new
|
||||
nB.Insert(M)
|
||||
if(nB)
|
||||
if(M.dna.species.use_skintones && M.dna.features["genitals_use_skintone"])
|
||||
nB.color = skintone2hex(H.skin_tone)
|
||||
else if(M.dna.features["breasts_color"])
|
||||
nB.color = "#[M.dna.features["breasts_color"]]"
|
||||
else
|
||||
nB.color = skintone2hex(H.skin_tone)
|
||||
nB.size = "flat"
|
||||
nB.cached_size = 0
|
||||
nB.prev_size = 0
|
||||
to_chat(M, "<span class='warning'>Your chest feels warm, tingling with newfound sensitivity.</b></span>")
|
||||
M.reagents.remove_reagent(id, 5)
|
||||
B = nB
|
||||
B = new
|
||||
if(H.dna.species.use_skintones && H.dna.features["genitals_use_skintone"])
|
||||
B.color = skintone2hex(H.skin_tone)
|
||||
else if(M.dna.features["breasts_color"])
|
||||
B.color = "#[M.dna.features["breasts_color"]]"
|
||||
else
|
||||
B.color = skintone2hex(H.skin_tone)
|
||||
B.size = "flat"
|
||||
B.cached_size = 0
|
||||
B.prev_size = 0
|
||||
to_chat(H, "<span class='warning'>Your chest feels warm, tingling with newfound sensitivity.</b></span>")
|
||||
H.reagents.remove_reagent(id, 5)
|
||||
B.Insert(H)
|
||||
|
||||
//If they have them, increase size. If size is comically big, limit movement and rip clothes.
|
||||
B.cached_size = B.cached_size + 0.05
|
||||
if (B.cached_size >= 8.5 && B.cached_size < 9)
|
||||
if(H.w_uniform || H.wear_suit)
|
||||
var/target = M.get_bodypart(BODY_ZONE_CHEST)
|
||||
to_chat(M, "<span class='warning'>Your breasts begin to strain against your clothes tightly!</b></span>")
|
||||
M.adjustOxyLoss(5, 0)
|
||||
M.apply_damage(1, BRUTE, target)
|
||||
B.update()
|
||||
..()
|
||||
B.modify_size(0.05)
|
||||
|
||||
if (ISINRANGE_EX(B.cached_size, 8.5, 9) && (H.w_uniform || H.wear_suit))
|
||||
var/target = H.get_bodypart(BODY_ZONE_CHEST)
|
||||
if(!message_spam)
|
||||
to_chat(H, "<span class='danger'>Your breasts begin to strain against your clothes tightly!</b></span>")
|
||||
message_spam = TRUE
|
||||
H.adjustOxyLoss(5, 0)
|
||||
H.apply_damage(1, BRUTE, target)
|
||||
return ..()
|
||||
|
||||
/datum/reagent/fermi/breast_enlarger/overdose_process(mob/living/carbon/M) //Turns you into a female if male and ODing, doesn't touch nonbinary and object genders.
|
||||
|
||||
//Acute hepatic pharmacokinesis.
|
||||
if(HAS_TRAIT(M, TRAIT_PHARMA))
|
||||
var/obj/item/organ/liver/L = M.getorganslot("liver")
|
||||
if(HAS_TRAIT(M, TRAIT_PHARMA) || !M.canbearoused)
|
||||
var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER)
|
||||
L.swelling+= 0.05
|
||||
return ..()
|
||||
|
||||
var/obj/item/organ/genital/penis/P = M.getorganslot("penis")
|
||||
var/obj/item/organ/genital/testicles/T = M.getorganslot("testicles")
|
||||
var/obj/item/organ/genital/vagina/V = M.getorganslot("vagina")
|
||||
var/obj/item/organ/genital/womb/W = M.getorganslot("womb")
|
||||
var/obj/item/organ/genital/penis/P = M.getorganslot(ORGAN_SLOT_PENIS)
|
||||
var/obj/item/organ/genital/testicles/T = M.getorganslot(ORGAN_SLOT_TESTICLES)
|
||||
var/obj/item/organ/genital/vagina/V = M.getorganslot(ORGAN_SLOT_VAGINA)
|
||||
var/obj/item/organ/genital/womb/W = M.getorganslot(ORGAN_SLOT_WOMB)
|
||||
|
||||
if(M.gender == MALE)
|
||||
M.gender = FEMALE
|
||||
M.visible_message("<span class='boldnotice'>[M] suddenly looks more feminine!</span>", "<span class='boldwarning'>You suddenly feel more feminine!</span>")
|
||||
|
||||
if(P)
|
||||
P.cached_length = P.cached_length - 0.05
|
||||
P.update()
|
||||
P.modify_size(-0.05)
|
||||
if(T)
|
||||
T.Remove(M)
|
||||
qdel(T)
|
||||
if(!V)
|
||||
var/obj/item/organ/genital/vagina/nV = new
|
||||
nV.Insert(M)
|
||||
V = nV
|
||||
V = new
|
||||
V.Insert(M)
|
||||
if(!W)
|
||||
var/obj/item/organ/genital/womb/nW = new
|
||||
nW.Insert(M)
|
||||
W = nW
|
||||
..()
|
||||
W = new
|
||||
W.Insert(M)
|
||||
return ..()
|
||||
|
||||
/datum/reagent/fermi/BEsmaller
|
||||
name = "Modesty milk"
|
||||
@@ -147,19 +133,18 @@
|
||||
can_synth = FALSE
|
||||
|
||||
/datum/reagent/fermi/BEsmaller/on_mob_life(mob/living/carbon/M)
|
||||
var/obj/item/organ/genital/breasts/B = M.getorganslot("breasts")
|
||||
var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS)
|
||||
if(!B)
|
||||
//Acute hepatic pharmacokinesis.
|
||||
if(HAS_TRAIT(M, TRAIT_PHARMA))
|
||||
var/obj/item/organ/liver/L = M.getorganslot("liver")
|
||||
if(HAS_TRAIT(M, TRAIT_PHARMA) || !M.canbearoused)
|
||||
var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER)
|
||||
L.swelling-= 0.05
|
||||
return ..()
|
||||
|
||||
//otherwise proceed as normal
|
||||
return..()
|
||||
B.cached_size = B.cached_size - 0.05
|
||||
B.update()
|
||||
..()
|
||||
B.modify_size(-0.05)
|
||||
return ..()
|
||||
|
||||
/datum/reagent/fermi/BEsmaller_hypo
|
||||
name = "Rectify milk" //Rectify
|
||||
@@ -171,31 +156,28 @@
|
||||
var/sizeConv = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5)
|
||||
can_synth = TRUE
|
||||
|
||||
/datum/reagent/fermi/BEsmaller_hypo/on_mob_add(mob/living/carbon/M)
|
||||
/datum/reagent/fermi/BEsmaller_hypo/on_mob_metabolize(mob/living/M)
|
||||
. = ..()
|
||||
if(!M.getorganslot("vagina"))
|
||||
if(M.dna.features["has_vag"])
|
||||
var/obj/item/organ/genital/vagina/nV = new
|
||||
nV.Insert(M)
|
||||
if(!M.getorganslot("womb"))
|
||||
if(M.dna.features["has_womb"])
|
||||
var/obj/item/organ/genital/womb/nW = new
|
||||
nW.Insert(M)
|
||||
if(!ishuman(M))
|
||||
return
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(!H.getorganslot(ORGAN_SLOT_VAGINA) && H.dna.features["has_vag"])
|
||||
H.give_genital(/obj/item/organ/genital/vagina)
|
||||
if(!H.getorganslot(ORGAN_SLOT_WOMB) && H.dna.features["has_womb"])
|
||||
H.give_genital(/obj/item/organ/genital/womb)
|
||||
|
||||
/datum/reagent/fermi/BEsmaller_hypo/on_mob_life(mob/living/carbon/M)
|
||||
var/obj/item/organ/genital/breasts/B = M.getorganslot("breasts")
|
||||
var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS)
|
||||
if(!B)
|
||||
return..()
|
||||
if(!M.dna.features["has_breasts"])//Fast fix for those who don't want it.
|
||||
B.cached_size = B.cached_size - 0.1
|
||||
B.update()
|
||||
else if(B.cached_size > (sizeConv[M.dna.features["breasts_size"]]+0.1))
|
||||
B.cached_size = B.cached_size - 0.05
|
||||
B.update()
|
||||
else if(B.cached_size < (sizeConv[M.dna.features["breasts_size"]])+0.1)
|
||||
B.cached_size = B.cached_size + 0.05
|
||||
B.update()
|
||||
..()
|
||||
var/optimal_size = B.breast_values[M.dna.features["breasts_size"]]
|
||||
if(!optimal_size)//Fast fix for those who don't want it.
|
||||
B.modify_size(-0.1)
|
||||
else if(B.cached_size > optimal_size)
|
||||
B.modify_size(-0.05, optimal_size)
|
||||
else if(B.cached_size < optimal_size)
|
||||
B.modify_size(0.05, 0, optimal_size)
|
||||
return ..()
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PENIS ENLARGE
|
||||
@@ -215,16 +197,15 @@
|
||||
inverse_chem_val = 0.35
|
||||
inverse_chem = "PEsmaller" //At really impure vols, it just becomes 100% inverse and shrinks instead.
|
||||
can_synth = FALSE
|
||||
var/message_spam = FALSE
|
||||
|
||||
/datum/reagent/fermi/penis_enlarger/on_mob_add(mob/living/carbon/M)
|
||||
/datum/reagent/fermi/penis_enlarger/on_mob_metabolize(mob/living/M)
|
||||
. = ..()
|
||||
if(!ishuman(M)) //Just monkeying around.
|
||||
if(volume >= 15) //to prevent monkey penis farms
|
||||
var/turf/T = get_turf(M)
|
||||
var/obj/item/organ/genital/penis/P = new /obj/item/organ/genital/penis(T)
|
||||
var/list/seen = viewers(8, T)
|
||||
for(var/mob/S in seen)
|
||||
to_chat(S, "<span class='warning'>A penis suddenly flies out of the [M]!</b></span>")
|
||||
M.visible_message("<span class='warning'>A penis suddenly flies out of the [M]!</b></span>")
|
||||
var/T2 = get_random_station_turf()
|
||||
M.adjustBruteLoss(25)
|
||||
M.Knockdown(50)
|
||||
@@ -233,80 +214,71 @@
|
||||
M.reagents.remove_reagent(id, volume)
|
||||
return
|
||||
var/mob/living/carbon/human/H = M
|
||||
H.genital_override = TRUE
|
||||
var/obj/item/organ/genital/penis/P = M.getorganslot("penis")
|
||||
if(!P)
|
||||
H.emergent_genital_call()
|
||||
return
|
||||
P.prev_length = P.length
|
||||
P.cached_length = P.length
|
||||
if(!H.getorganslot(ORGAN_SLOT_PENIS) && H.emergent_genital_call())
|
||||
H.genital_override = TRUE
|
||||
|
||||
/datum/reagent/fermi/penis_enlarger/on_mob_life(mob/living/carbon/M) //Increases penis size, 5u = +1 inch.
|
||||
if(!ishuman(M))
|
||||
return
|
||||
return ..()
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/genital/penis/P = M.getorganslot("penis")
|
||||
var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS)
|
||||
if(!P)//They do have a preponderance for escapism, or so I've heard.
|
||||
|
||||
//If they have Acute hepatic pharmacokinesis, then route processing though liver.
|
||||
if(HAS_TRAIT(M, TRAIT_PHARMA))
|
||||
var/obj/item/organ/liver/L = M.getorganslot("liver")
|
||||
if(HAS_TRAIT(H, TRAIT_PHARMA) || !H.canbearoused)
|
||||
var/obj/item/organ/liver/L = H.getorganslot(ORGAN_SLOT_LIVER)
|
||||
if(L)
|
||||
L.swelling+= 0.05
|
||||
return..()
|
||||
L.swelling += 0.05
|
||||
else
|
||||
M.adjustToxLoss(1)
|
||||
return..()
|
||||
H.adjustToxLoss(1)
|
||||
return ..()
|
||||
|
||||
//otherwise proceed as normal
|
||||
var/obj/item/organ/genital/penis/nP = new
|
||||
nP.Insert(M)
|
||||
if(nP)
|
||||
nP.length = 1
|
||||
to_chat(M, "<span class='warning'>Your groin feels warm, as you feel a newly forming bulge down below.</b></span>")
|
||||
nP.cached_length = 1
|
||||
nP.prev_length = 1
|
||||
M.reagents.remove_reagent(id, 5)
|
||||
P = nP
|
||||
P = new
|
||||
P.length = 1
|
||||
to_chat(H, "<span class='warning'>Your groin feels warm, as you feel a newly forming bulge down below.</b></span>")
|
||||
P.prev_length = 1
|
||||
H.reagents.remove_reagent(id, 5)
|
||||
P.Insert(H)
|
||||
|
||||
P.cached_length = P.cached_length + 0.1
|
||||
if (P.cached_length >= 20.5 && P.cached_length < 21)
|
||||
if(H.w_uniform || H.wear_suit)
|
||||
var/target = M.get_bodypart(BODY_ZONE_CHEST)
|
||||
to_chat(M, "<span class='warning'>Your cock begin to strain against your clothes tightly!</b></span>")
|
||||
M.apply_damage(2.5, BRUTE, target)
|
||||
P.modify_size(0.1)
|
||||
if (ISINRANGE_EX(P.length, 20.5, 21) && (H.w_uniform || H.wear_suit))
|
||||
var/target = H.get_bodypart(BODY_ZONE_CHEST)
|
||||
if(!message_spam)
|
||||
to_chat(H, "<span class='danger'>Your cock begin to strain against your clothes tightly!</b></span>")
|
||||
message_spam = TRUE
|
||||
H.apply_damage(2.5, BRUTE, target)
|
||||
|
||||
P.update()
|
||||
..()
|
||||
return ..()
|
||||
|
||||
/datum/reagent/fermi/penis_enlarger/overdose_process(mob/living/carbon/M) //Turns you into a male if female and ODing, doesn't touch nonbinary and object genders.
|
||||
/datum/reagent/fermi/penis_enlarger/overdose_process(mob/living/carbon/human/M) //Turns you into a male if female and ODing, doesn't touch nonbinary and object genders.
|
||||
if(!istype(M))
|
||||
return ..()
|
||||
//Acute hepatic pharmacokinesis.
|
||||
if(HAS_TRAIT(M, TRAIT_PHARMA))
|
||||
var/obj/item/organ/liver/L = M.getorganslot("liver")
|
||||
if(HAS_TRAIT(M, TRAIT_PHARMA) || !M.canbearoused)
|
||||
var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER)
|
||||
L.swelling+= 0.05
|
||||
return..()
|
||||
|
||||
var/obj/item/organ/genital/breasts/B = M.getorganslot("breasts")
|
||||
var/obj/item/organ/genital/testicles/T = M.getorganslot("testicles")
|
||||
var/obj/item/organ/genital/vagina/V = M.getorganslot("vagina")
|
||||
var/obj/item/organ/genital/womb/W = M.getorganslot("womb")
|
||||
var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS)
|
||||
var/obj/item/organ/genital/testicles/T = M.getorganslot(ORGAN_SLOT_TESTICLES)
|
||||
var/obj/item/organ/genital/vagina/V = M.getorganslot(ORGAN_SLOT_VAGINA)
|
||||
var/obj/item/organ/genital/womb/W = M.getorganslot(ORGAN_SLOT_WOMB)
|
||||
|
||||
if(M.gender == FEMALE)
|
||||
M.gender = MALE
|
||||
M.visible_message("<span class='boldnotice'>[M] suddenly looks more masculine!</span>", "<span class='boldwarning'>You suddenly feel more masculine!</span>")
|
||||
|
||||
if(B)
|
||||
B.cached_size = B.cached_size - 0.05
|
||||
B.update()
|
||||
if(V)
|
||||
V.Remove(M)
|
||||
B.modify_size(-0.05)
|
||||
if(M.getorganslot(ORGAN_SLOT_VAGINA))
|
||||
qdel(V)
|
||||
if(W)
|
||||
W.Remove(M)
|
||||
qdel(W)
|
||||
if(!T)
|
||||
var/obj/item/organ/genital/testicles/nT = new
|
||||
nT.Insert(M)
|
||||
T = nT
|
||||
..()
|
||||
T = new
|
||||
T.Insert(M)
|
||||
return ..()
|
||||
|
||||
/datum/reagent/fermi/PEsmaller // Due to cozmo's request...!
|
||||
name = "Chastity draft"
|
||||
@@ -318,19 +290,18 @@
|
||||
can_synth = FALSE
|
||||
|
||||
/datum/reagent/fermi/PEsmaller/on_mob_life(mob/living/carbon/M)
|
||||
if(!ishuman(M))
|
||||
return ..()
|
||||
var/mob/living/carbon/human/H = M
|
||||
var/obj/item/organ/genital/penis/P = H.getorganslot("penis")
|
||||
var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS)
|
||||
if(!P)
|
||||
//Acute hepatic pharmacokinesis.
|
||||
if(HAS_TRAIT(M, TRAIT_PHARMA))
|
||||
var/obj/item/organ/liver/L = M.getorganslot("liver")
|
||||
var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER)
|
||||
L.swelling-= 0.05
|
||||
return..()
|
||||
|
||||
//otherwise proceed as normal
|
||||
return..()
|
||||
P.cached_length = P.cached_length - 0.1
|
||||
P.update()
|
||||
|
||||
P.modify_size(-0.1)
|
||||
..()
|
||||
|
||||
/datum/reagent/fermi/PEsmaller_hypo
|
||||
@@ -342,24 +313,25 @@
|
||||
metabolization_rate = 0.5
|
||||
can_synth = TRUE
|
||||
|
||||
/datum/reagent/fermi/PEsmaller_hypo/on_mob_add(mob/living/carbon/M)
|
||||
/datum/reagent/fermi/PEsmaller_hypo/on_mob_metabolize(mob/living/M)
|
||||
. = ..()
|
||||
if(!M.getorganslot("testicles"))
|
||||
if(M.dna.features["has_balls"])
|
||||
var/obj/item/organ/genital/testicles/nT = new
|
||||
nT.Insert(M)
|
||||
if(!ishuman(M))
|
||||
return
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(!H.getorganslot(ORGAN_SLOT_PENIS) && H.dna.features["has_cock"])
|
||||
H.give_genital(/obj/item/organ/genital/penis)
|
||||
if(!H.getorganslot(ORGAN_SLOT_TESTICLES) && H.dna.features["has_balls"])
|
||||
H.give_genital(/obj/item/organ/genital/testicles)
|
||||
|
||||
/datum/reagent/fermi/PEsmaller_hypo/on_mob_life(mob/living/carbon/M)
|
||||
var/obj/item/organ/genital/penis/P = M.getorganslot("penis")
|
||||
var/obj/item/organ/genital/penis/P = M.getorganslot(ORGAN_SLOT_PENIS)
|
||||
if(!P)
|
||||
return ..()
|
||||
if(!M.dna.features["has_cock"])//Fast fix for those who don't want it.
|
||||
P.cached_length = P.cached_length - 0.2
|
||||
P.update()
|
||||
else if(P.cached_length > (M.dna.features["cock_length"]+0.1))
|
||||
P.cached_length = P.cached_length - 0.1
|
||||
P.update()
|
||||
else if(P.cached_length < (M.dna.features["cock_length"]+0.1))
|
||||
P.cached_length = P.cached_length + 0.1
|
||||
P.update()
|
||||
..()
|
||||
var/optimal_size = M.dna.features["cock_length"]
|
||||
if(!optimal_size)//Fast fix for those who don't want it.
|
||||
P.modify_size(-0.2)
|
||||
else if(P.length > optimal_size)
|
||||
P.modify_size(-0.1, optimal_size)
|
||||
else if(P.length < optimal_size)
|
||||
P.modify_size(0.1, 0, optimal_size)
|
||||
return ..()
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/obj/vehicle/ridden/secway
|
||||
var/chargemax = 150
|
||||
var/chargerate = 0.35
|
||||
var/charge = 150
|
||||
var/chargespeed = 1
|
||||
var/normalspeed = 2
|
||||
var/last_tick = 0
|
||||
var/list/progressbars_by_rider = list()
|
||||
|
||||
/obj/vehicle/ridden/secway/Initialize()
|
||||
. = ..()
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
|
||||
/obj/vehicle/ridden/secway/process()
|
||||
var/diff = world.time - last_tick
|
||||
var/regen = chargerate * diff
|
||||
charge = CLAMP(charge + regen, 0, chargemax)
|
||||
last_tick = world.time
|
||||
|
||||
/obj/vehicle/ridden/secway/relaymove(mob/user, direction)
|
||||
var/new_speed = normalspeed
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.sprinting && charge)
|
||||
charge--
|
||||
new_speed = chargespeed
|
||||
var/datum/component/riding/D = GetComponent(/datum/component/riding)
|
||||
D.vehicle_move_delay = new_speed
|
||||
for(var/i in progressbars_by_rider)
|
||||
var/datum/progressbar/B = progressbars_by_rider[i]
|
||||
B.update(charge)
|
||||
return ..()
|
||||
|
||||
/obj/vehicle/ridden/secway/buckle_mob(mob/living/M, force, check_loc)
|
||||
. = ..(M, force, check_loc)
|
||||
if(.)
|
||||
if(progressbars_by_rider[M])
|
||||
qdel(progressbars_by_rider[M])
|
||||
var/datum/progressbar/D = new(M, chargemax, src)
|
||||
D.update(charge)
|
||||
progressbars_by_rider[M] = D
|
||||
|
||||
/obj/vehicle/ridden/secway/unbuckle_mob(mob/living/M, force)
|
||||
. = ..(M, force)
|
||||
if(.)
|
||||
qdel(progressbars_by_rider[M])
|
||||
progressbars_by_rider -= M
|
||||
|
||||
/obj/vehicle/ridden/secway/Destroy()
|
||||
for(var/i in progressbars_by_rider)
|
||||
qdel(progressbars_by_rider[i])
|
||||
progressbars_by_rider.Cut()
|
||||
STOP_PROCESSING(SSfastprocess, src)
|
||||
return ..()
|
||||
Reference in New Issue
Block a user