Merge branch 'master' into Yote
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
/datum/controller/subsystem/shuttle/proc/autoEnd() //CIT CHANGE - allows shift to end after 2 hours have passed.
|
||||
if((world.realtime - SSshuttle.realtimeofstart) > auto_call && EMERGENCY_IDLE_OR_RECALLED) //2 hours
|
||||
SSshuttle.emergency.request(silent = TRUE)
|
||||
priority_announce("The shift has come to an end and the shuttle called. [seclevel2num(get_security_level()) == SEC_LEVEL_RED ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [emergency.timeLeft(600)] minutes.", null, 'sound/ai/shuttlecalled.ogg', "Priority")
|
||||
priority_announce("The shift has come to an end and the shuttle called. [seclevel2num(get_security_level()) == SEC_LEVEL_RED ? "Red Alert state confirmed: Dispatching priority shuttle. " : "" ]It will arrive in [emergency.timeLeft(600)] minutes.", null, "shuttlecalled", "Priority")
|
||||
log_game("Round time limit reached. Shuttle has been auto-called.")
|
||||
message_admins("Round time limit reached. Shuttle called.")
|
||||
emergencyNoRecall = TRUE
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
if(!wearer)
|
||||
return //idfk
|
||||
new/obj/effect/temp_visual/souldeath(wearer.loc, wearer)
|
||||
playsound(wearer, 'modular_citadel/sound/misc/souldeath.ogg', 100, FALSE)
|
||||
playsound(wearer, 'sound/misc/souldeath.ogg', 100, FALSE)
|
||||
|
||||
/datum/component/souldeath/neck
|
||||
equip_slot = SLOT_NECK
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
// Jack the Ripper starring plush
|
||||
/obj/item/toy/plush/attackby(obj/item/I, mob/living/user, params)
|
||||
. = ..()
|
||||
if(I.is_sharp())
|
||||
if(I.get_sharpness())
|
||||
if(!grenade)
|
||||
SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT,"plushjack", /datum/mood_event/plushjack)
|
||||
|
||||
|
||||
@@ -37,64 +37,62 @@
|
||||
alert_type = null
|
||||
var/moveCalc = 1
|
||||
var/cachedmoveCalc = 1
|
||||
var/last_checked_size //used to prevent potential cpu waste from happening every tick.
|
||||
|
||||
/datum/status_effect/chem/breast_enlarger/on_apply(mob/living/carbon/human/H)//Removes clothes, they're too small to contain you. You belong to space now.
|
||||
/datum/status_effect/chem/breast_enlarger/on_apply()//Removes clothes, they're too small to contain you. You belong to space now.
|
||||
log_game("FERMICHEM: [owner]'s breasts has reached comical sizes. ID: [owner.key]")
|
||||
var/mob/living/carbon/human/o = owner
|
||||
var/items = o.get_contents()
|
||||
for(var/obj/item/W in items)
|
||||
if(W == o.w_uniform || W == o.wear_suit)
|
||||
o.dropItemToGround(W, TRUE)
|
||||
playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
|
||||
to_chat(o, "<span class='warning'>Your clothes give, ripping into peices under the strain of your swelling breasts! Unless you manage to reduce the size of your breasts, there's no way you're going to be able to put anything on over these melons..!</b></span>")
|
||||
o.visible_message("<span class='boldnotice'>[o]'s chest suddenly bursts forth, ripping their clothes off!'</span>")
|
||||
else
|
||||
to_chat(o, "<span class='notice'>Your bountiful bosom is so rich with mass, you seriously doubt you'll be able to fit any clothes over it.</b></span>")
|
||||
return ..()
|
||||
var/mob/living/carbon/human/H = owner
|
||||
var/message = FALSE
|
||||
if(H.w_uniform)
|
||||
H.dropItemToGround(H.w_uniform, TRUE)
|
||||
message = TRUE
|
||||
if(H.wear_suit)
|
||||
H.dropItemToGround(H.wear_suit, TRUE)
|
||||
message = TRUE
|
||||
if(message)
|
||||
playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1)
|
||||
H.visible_message("<span class='boldnotice'>[H]'s chest suddenly bursts forth, ripping their clothes off!'</span>", \
|
||||
"<span class='warning'>Your clothes give, ripping into peices under the strain of your swelling breasts! Unless you manage to reduce the size of your breasts, there's no way you're going to be able to put anything on over these melons..!</b></span>")
|
||||
else
|
||||
to_chat(H, "<span class='notice'>Your bountiful bosom is so rich with mass, you seriously doubt you'll be able to fit any clothes over it.</b></span>")
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/chem/breast_enlarger/tick(mob/living/carbon/human/H)//If you try to wear clothes, you fail. Slows you down if you're comically huge
|
||||
var/mob/living/carbon/human/o = owner
|
||||
var/obj/item/organ/genital/breasts/B = o.getorganslot("breasts")
|
||||
moveCalc = 1+((round(B.cached_size) - 9)/3) //Afffects how fast you move, and how often you can click.
|
||||
/datum/status_effect/chem/breast_enlarger/tick()//If you try to wear clothes, you fail. Slows you down if you're comically huge
|
||||
var/mob/living/carbon/human/H = owner
|
||||
var/obj/item/organ/genital/breasts/B = H.getorganslot(ORGAN_SLOT_BREASTS)
|
||||
if(!B)
|
||||
o.remove_movespeed_modifier(BREAST_MOVEMENT_SPEED)
|
||||
sizeMoveMod(1)
|
||||
owner.remove_status_effect(src)
|
||||
var/items = o.get_contents()
|
||||
for(var/obj/item/W in items)
|
||||
if(W == o.w_uniform || W == o.wear_suit)
|
||||
o.dropItemToGround(W, TRUE)
|
||||
playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
|
||||
to_chat(owner, "<span class='warning'>Your enormous breasts are way too large to fit anything over them!</b></span>")
|
||||
H.remove_status_effect(src)
|
||||
return
|
||||
moveCalc = 1+((round(B.cached_size) - 9)/3) //Afffects how fast you move, and how often you can click.
|
||||
var/message = FALSE
|
||||
if(H.w_uniform)
|
||||
H.dropItemToGround(H.w_uniform, TRUE)
|
||||
message = TRUE
|
||||
if(H.wear_suit)
|
||||
H.dropItemToGround(H.wear_suit, TRUE)
|
||||
message = TRUE
|
||||
if(message)
|
||||
playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1)
|
||||
to_chat(H, "<span class='warning'>Your enormous breasts are way too large to fit anything over them!</b></span>")
|
||||
|
||||
if(last_checked_size != B.cached_size)
|
||||
H.add_movespeed_modifier(BREAST_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc)
|
||||
sizeMoveMod(moveCalc)
|
||||
|
||||
if (B.size == "huge")
|
||||
if(prob(1))
|
||||
to_chat(owner, "<span class='notice'>Your back is feeling sore.</span>")
|
||||
var/target = o.get_bodypart(BODY_ZONE_CHEST)
|
||||
o.apply_damage(0.1, BRUTE, target)
|
||||
if(!B.cached_size == B.breast_values[B.prev_size])
|
||||
o.add_movespeed_modifier(BREAST_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc)
|
||||
sizeMoveMod(moveCalc)
|
||||
return ..()
|
||||
else if (B.breast_values[B.size] > B.breast_values[B.prev_size])
|
||||
o.add_movespeed_modifier(BREAST_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc)
|
||||
sizeMoveMod(moveCalc)
|
||||
else if (B.breast_values[B.size] < B.breast_values[B.prev_size])
|
||||
o.add_movespeed_modifier(BREAST_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc)
|
||||
sizeMoveMod(moveCalc)
|
||||
if((B.cached_size) < 16)
|
||||
switch(round(B.cached_size))
|
||||
if(9)
|
||||
if (B.breast_values[B.prev_size] != B.breast_values[B.size])
|
||||
to_chat(o, "<span class='notice'>Your expansive chest has become a more managable size, liberating your movements.</b></span>")
|
||||
if(10 to INFINITY)
|
||||
if (B.breast_values[B.prev_size] != B.breast_values[B.size])
|
||||
to_chat(H, "<span class='warning'>Your indulgent busom is so substantial, it's affecting your movements!</b></span>")
|
||||
var/target = H.get_bodypart(BODY_ZONE_CHEST)
|
||||
H.apply_damage(0.1, BRUTE, target)
|
||||
else
|
||||
if(prob(1))
|
||||
to_chat(owner, "<span class='notice'>Your back is feeling a little sore.</span>")
|
||||
..()
|
||||
to_chat(H, "<span class='notice'>Your back is feeling a little sore.</span>")
|
||||
last_checked_size = B.cached_size
|
||||
..()
|
||||
|
||||
/datum/status_effect/chem/breast_enlarger/on_remove(mob/living/carbon/M)
|
||||
/datum/status_effect/chem/breast_enlarger/on_remove()
|
||||
log_game("FERMICHEM: [owner]'s breasts has reduced to an acceptable size. ID: [owner.key]")
|
||||
to_chat(owner, "<span class='notice'>Your expansive chest has become a more managable size, liberating your movements.</b></span>")
|
||||
owner.remove_movespeed_modifier(BREAST_MOVEMENT_SPEED)
|
||||
sizeMoveMod(1)
|
||||
|
||||
@@ -112,51 +110,57 @@
|
||||
alert_type = null
|
||||
var/bloodCalc
|
||||
var/moveCalc
|
||||
var/last_checked_size //used to prevent potential cpu waste, just like the above.
|
||||
|
||||
/datum/status_effect/chem/penis_enlarger/on_apply(mob/living/carbon/human/H)//Removes clothes, they're too small to contain you. You belong to space now.
|
||||
/datum/status_effect/chem/penis_enlarger/on_apply()//Removes clothes, they're too small to contain you. You belong to space now.
|
||||
log_game("FERMICHEM: [owner]'s dick has reached comical sizes. ID: [owner.key]")
|
||||
var/mob/living/carbon/human/o = owner
|
||||
var/items = o.get_contents()
|
||||
if(o.w_uniform || o.wear_suit)
|
||||
to_chat(o, "<span class='warning'>Your clothes give, ripping into peices under the strain of your swelling pecker! Unless you manage to reduce the size of your emancipated trouser snake, there's no way you're going to be able to put anything on over this girth..!</b></span>")
|
||||
owner.visible_message("<span class='boldnotice'>[o]'s schlong suddenly bursts forth, ripping their clothes off!'</span>")
|
||||
var/mob/living/carbon/human/H = owner
|
||||
var/message = FALSE
|
||||
if(H.w_uniform)
|
||||
H.dropItemToGround(H.w_uniform, TRUE)
|
||||
message = TRUE
|
||||
if(H.wear_suit)
|
||||
H.dropItemToGround(H.wear_suit, TRUE)
|
||||
message = TRUE
|
||||
if(message)
|
||||
playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1)
|
||||
H.visible_message("<span class='boldnotice'>[H]'s schlong suddenly bursts forth, ripping their clothes off!'</span>", \
|
||||
"<span class='warning'>Your clothes give, ripping into peices under the strain of your swelling pecker! Unless you manage to reduce the size of your emancipated trouser snake, there's no way you're going to be able to put anything on over this girth..!</b></span>")
|
||||
else
|
||||
to_chat(o, "<span class='notice'>Your emancipated trouser snake is so ripe with girth, you seriously doubt you'll be able to fit any clothes over it.</b></span>")
|
||||
for(var/obj/item/W in items)
|
||||
if(W == o.w_uniform || W == o.wear_suit)
|
||||
o.dropItemToGround(W, TRUE)
|
||||
playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
|
||||
to_chat(H, "<span class='notice'>Your emancipated trouser snake is so ripe with girth, you seriously doubt you'll be able to fit any clothes over it.</b></span>")
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/status_effect/chem/penis_enlarger/tick(mob/living/carbon/M)
|
||||
var/mob/living/carbon/human/o = owner
|
||||
var/obj/item/organ/genital/penis/P = o.getorganslot("penis")
|
||||
/datum/status_effect/chem/penis_enlarger/tick()
|
||||
var/mob/living/carbon/human/H = owner
|
||||
var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS)
|
||||
if(!P)
|
||||
owner.remove_status_effect(src)
|
||||
return
|
||||
moveCalc = 1+((round(P.length) - 21)/3) //effects how fast you can move
|
||||
bloodCalc = 1+((round(P.length) - 21)/15) //effects how much blood you need (I didn' bother adding an arousal check because I'm spending too much time on this organ already.)
|
||||
if(!P)
|
||||
o.remove_movespeed_modifier(DICK_MOVEMENT_SPEED)
|
||||
o.ResetBloodVol()
|
||||
owner.remove_status_effect(src)
|
||||
var/items = o.get_contents()
|
||||
for(var/obj/item/W in items)
|
||||
if(W == o.w_uniform || W == o.wear_suit)
|
||||
o.dropItemToGround(W, TRUE)
|
||||
playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1)
|
||||
to_chat(owner, "<span class='warning'>Your enormous package is way to large to fit anything over!</b></span>")
|
||||
switch(round(P.cached_length))
|
||||
if(21)
|
||||
to_chat(o, "<span class='notice'>Your rascally willy has become a more managable size, liberating your movements.</b></span>")
|
||||
o.remove_movespeed_modifier(DICK_MOVEMENT_SPEED)
|
||||
o.AdjustBloodVol(bloodCalc)
|
||||
if(22 to INFINITY)
|
||||
if(prob(2))
|
||||
to_chat(o, "<span class='warning'>Your indulgent johnson is so substantial, it's taking all your blood and affecting your movements!</b></span>")
|
||||
o.add_movespeed_modifier(DICK_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc)
|
||||
o.AdjustBloodVol(bloodCalc)
|
||||
|
||||
var/message = FALSE
|
||||
if(H.w_uniform)
|
||||
H.dropItemToGround(H.w_uniform, TRUE)
|
||||
message = TRUE
|
||||
if(H.wear_suit)
|
||||
H.dropItemToGround(H.wear_suit, TRUE)
|
||||
message = TRUE
|
||||
if(message)
|
||||
playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1)
|
||||
to_chat(H, "<span class='warning'>Your enormous package is way to large to fit anything over!</b></span>")
|
||||
|
||||
if(P.length < 22 && H.has_movespeed_modifier(DICK_MOVEMENT_SPEED))
|
||||
to_chat(owner, "<span class='notice'>Your rascally willy has become a more managable size, liberating your movements.</b></span>")
|
||||
H.remove_movespeed_modifier(DICK_MOVEMENT_SPEED)
|
||||
else if(P.length >= 22 && !H.has_movespeed_modifier(DICK_MOVEMENT_SPEED))
|
||||
to_chat(H, "<span class='warning'>Your indulgent johnson is so substantial, it's taking all your blood and affecting your movements!</b></span>")
|
||||
H.add_movespeed_modifier(DICK_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc)
|
||||
H.AdjustBloodVol(bloodCalc)
|
||||
..()
|
||||
|
||||
/datum/status_effect/chem/penis_enlarger/on_remove(mob/living/carbon/human/o)
|
||||
/datum/status_effect/chem/penis_enlarger/on_remove()
|
||||
log_game("FERMICHEM: [owner]'s dick has reduced to an acceptable size. ID: [owner.key]")
|
||||
owner.remove_movespeed_modifier(DICK_MOVEMENT_SPEED)
|
||||
owner.ResetBloodVol()
|
||||
@@ -499,7 +503,7 @@
|
||||
cooldown += 1 //Cooldown doesn't process till status is done
|
||||
|
||||
else if(status == "charge")
|
||||
ADD_TRAIT(owner, TRAIT_GOTTAGOFAST, "MKUltra")
|
||||
owner.add_movespeed_modifier(MOVESPEED_ID_MKULTRA, update=TRUE, priority=100, multiplicative_slowdown=-2, blacklisted_movetypes=(FLYING|FLOATING))
|
||||
status = "charged"
|
||||
if(master.client?.prefs.lewdchem)
|
||||
to_chat(owner, "<span class='notice'><i>Your [enthrallGender]'s order fills you with a burst of speed!</i></span>")
|
||||
@@ -509,7 +513,7 @@
|
||||
else if (status == "charged")
|
||||
if (statusStrength < 0)
|
||||
status = null
|
||||
REMOVE_TRAIT(owner, TRAIT_GOTTAGOFAST, "MKUltra")
|
||||
owner.remove_movespeed_modifier(MOVESPEED_ID_MKULTRA)
|
||||
owner.Knockdown(50)
|
||||
to_chat(owner, "<span class='notice'><i>Your body gives out as the adrenaline in your system runs out.</i></span>")
|
||||
else
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
// Citadel-specific Neutral Traits
|
||||
|
||||
/datum/quirk/libido
|
||||
name = "Nymphomania"
|
||||
desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual."
|
||||
value = 0
|
||||
mob_trait = TRAIT_NYMPHO
|
||||
gain_text = "<span class='notice'>You are feeling extra wild.</span>"
|
||||
lose_text = "<span class='notice'>You don't feel that burning sensation anymore.</span>"
|
||||
|
||||
/datum/quirk/libido/add()
|
||||
var/mob/living/M = quirk_holder
|
||||
M.min_arousal = 16
|
||||
M.arousal_rate = 3
|
||||
|
||||
/datum/quirk/libido/remove()
|
||||
var/mob/living/M = quirk_holder
|
||||
M.min_arousal = initial(M.min_arousal)
|
||||
M.arousal_rate = initial(M.arousal_rate)
|
||||
|
||||
/datum/quirk/libido/on_process()
|
||||
var/mob/living/M = quirk_holder
|
||||
if(M.canbearoused == FALSE)
|
||||
to_chat(quirk_holder, "<span class='notice'>Having high libido is useless when you can't feel arousal at all!</span>")
|
||||
qdel(src)
|
||||
|
||||
/datum/quirk/maso
|
||||
name = "Masochism"
|
||||
desc = "You are aroused by pain."
|
||||
value = 0
|
||||
mob_trait = TRAIT_MASO
|
||||
gain_text = "<span class='notice'>You desire to be hurt.</span>"
|
||||
lose_text = "<span class='notice'>Pain has become less exciting for you.</span>"
|
||||
|
||||
/datum/quirk/pharmacokinesis //Prevents unwanted organ additions.
|
||||
name = "Acute hepatic pharmacokinesis"
|
||||
desc = "You've a rare genetic disorder that causes Incubus draft and Sucubus milk to be absorbed by your liver instead."
|
||||
value = 0
|
||||
mob_trait = TRAIT_PHARMA
|
||||
lose_text = "<span class='notice'>Your liver feels different.</span>"
|
||||
var/active = FALSE
|
||||
var/power = 0
|
||||
var/cachedmoveCalc = 1
|
||||
@@ -53,19 +53,17 @@
|
||||
|
||||
/obj/machinery/dominator/update_icon()
|
||||
cut_overlays()
|
||||
if(!(stat & BROKEN))
|
||||
icon_state = "dominator-active"
|
||||
if(operating)
|
||||
var/mutable_appearance/dominator_overlay = mutable_appearance('icons/obj/machines/dominator.dmi', "dominator-overlay")
|
||||
if(gang)
|
||||
dominator_overlay.color = gang.color
|
||||
add_overlay(dominator_overlay)
|
||||
else
|
||||
icon_state = "dominator"
|
||||
if(obj_integrity/max_integrity < 0.66)
|
||||
add_overlay("damage")
|
||||
else
|
||||
if(stat & BROKEN)
|
||||
icon_state = "dominator-broken"
|
||||
return
|
||||
icon_state = "dominator"
|
||||
if(operating)
|
||||
var/mutable_appearance/dominator_overlay = mutable_appearance('icons/obj/machines/dominator.dmi', "dominator-overlay")
|
||||
if(gang)
|
||||
dominator_overlay.color = gang.color
|
||||
add_overlay(dominator_overlay)
|
||||
if(obj_integrity/max_integrity < 0.66)
|
||||
add_overlay("damage")
|
||||
|
||||
/obj/machinery/dominator/examine(mob/user)
|
||||
..()
|
||||
@@ -168,7 +166,7 @@
|
||||
examine(user)
|
||||
return
|
||||
|
||||
if(tempgang.domination_time != NOT_DOMINATING)
|
||||
if(tempgang.domination_time != NOT_DOMINATING)
|
||||
to_chat(user, "<span class='warning'>Error: Hostile Takeover is already in progress.</span>")
|
||||
return
|
||||
|
||||
|
||||
@@ -72,32 +72,7 @@
|
||||
/obj/item/reagent_containers/glass/bottle/hexacrocin = 10
|
||||
)
|
||||
refill_canister = /obj/item/vending_refill/kink
|
||||
/*
|
||||
/obj/machinery/vending/nazivend
|
||||
name = "Nazivend"
|
||||
desc = "A vending machine containing Nazi German supplies. A label reads: \"Remember the gorrilions lost.\""
|
||||
icon = 'icons/obj/citvending.dmi'
|
||||
icon_state = "nazi"
|
||||
vend_reply = "SIEG HEIL!"
|
||||
product_slogans = "Das Vierte Reich wird zuruckkehren!;ENTFERNEN JUDEN!;Billiger als die Juden jemals geben!;Rader auf dem adminbus geht rund und rund.;Warten Sie, warum wir wieder hassen Juden?- *BZZT*"
|
||||
products = list(
|
||||
/obj/item/clothing/head/stalhelm = 20,
|
||||
/obj/item/clothing/head/panzer = 20,
|
||||
/obj/item/clothing/suit/soldiercoat = 20,
|
||||
// /obj/item/clothing/under/soldieruniform = 20,
|
||||
/obj/item/clothing/shoes/jackboots = 20
|
||||
)
|
||||
contraband = list(
|
||||
/obj/item/clothing/head/naziofficer = 10,
|
||||
// /obj/item/clothing/suit/officercoat = 10,
|
||||
// /obj/item/clothing/under/officeruniform = 10,
|
||||
/obj/item/clothing/suit/space/hardsuit/nazi = 3,
|
||||
/obj/item/gun/energy/plasma/MP40k = 4
|
||||
)
|
||||
premium = list()
|
||||
|
||||
refill_canister = /obj/item/vending_refill/nazi
|
||||
*/
|
||||
/obj/machinery/vending/sovietvend
|
||||
name = "KomradeVendtink"
|
||||
desc = "Rodina-mat' zovyot!"
|
||||
@@ -137,10 +112,6 @@
|
||||
icon = 'modular_citadel/icons/vending_restock.dmi'
|
||||
icon_state = "refill_kink"
|
||||
|
||||
/obj/item/vending_refill/nazi
|
||||
machine_name = "nazivend"
|
||||
icon_state = "refill_nazi"
|
||||
|
||||
/obj/item/vending_refill/soviet
|
||||
machine_name = "sovietvend"
|
||||
icon_state = "refill_soviet"
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
alternate_screams = list('modular_citadel/sound/voice/scream_silicon.ogg')
|
||||
|
||||
/obj/item/clothing/head/ushanka
|
||||
alternate_screams = list('modular_citadel/sound/misc/cyka1.ogg', 'modular_citadel/sound/misc/cheekibreeki.ogg')
|
||||
alternate_screams = list('sound/voice/human/cyka1.ogg', 'sound/voice/human/cheekibreeki.ogg')
|
||||
|
||||
/obj/item/proc/grenade_prime_react(obj/item/grenade/nade)
|
||||
return
|
||||
@@ -1,4 +0,0 @@
|
||||
/obj/item/aicard/potato
|
||||
name = "Potat-OS"
|
||||
desc = "A storage device for possibly malfunctioning AIs. Go on. Get a big fat eyeful. With your big fat eyes."
|
||||
icon = 'modular_citadel/icons/aicards.dmi'
|
||||
@@ -1,24 +0,0 @@
|
||||
//Yes, hi. This is the file that handles Citadel's turf modifications.
|
||||
|
||||
/*
|
||||
/turf/open/floor/Entered(atom/obj, atom/oldloc)
|
||||
. = ..()
|
||||
CitDirtify(obj, oldloc)*/
|
||||
|
||||
//Baystation-styled tile dirtification.
|
||||
/turf/open/floor/proc/CitDirtify(atom/obj, atom/oldloc)
|
||||
if(prob(50))
|
||||
if(has_gravity(src) && !isobserver(obj))
|
||||
var/dirtamount
|
||||
var/obj/effect/decal/cleanable/dirt/dirt = locate(/obj/effect/decal/cleanable/dirt, src)
|
||||
if(!dirt)
|
||||
dirt = new/obj/effect/decal/cleanable/dirt(src)
|
||||
dirt.alpha = 0
|
||||
dirtamount = 0
|
||||
dirtamount = dirt.alpha + 1
|
||||
if(oldloc && istype(oldloc, /turf/open/floor))
|
||||
var/obj/effect/decal/cleanable/dirt/spreadindirt = locate(/obj/effect/decal/cleanable/dirt, oldloc)
|
||||
if(spreadindirt && spreadindirt.alpha)
|
||||
dirtamount += round(spreadindirt.alpha * 0.05)
|
||||
dirt.alpha = min(dirtamount,255)
|
||||
return TRUE
|
||||
@@ -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