Merge remote-tracking branch 'citadel/master' into projectiles_2
This commit is contained in:
@@ -10,9 +10,9 @@
|
||||
/obj/item/organ/heart/gland/trauma/activate()
|
||||
to_chat(owner, "<span class='warning'>You feel a spike of pain in your head.</span>")
|
||||
if(prob(33))
|
||||
owner.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
|
||||
owner.gain_trauma_type(BRAIN_TRAUMA_SPECIAL, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_SURGERY))
|
||||
else
|
||||
if(prob(20))
|
||||
owner.gain_trauma_type(BRAIN_TRAUMA_SEVERE, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
|
||||
owner.gain_trauma_type(BRAIN_TRAUMA_SEVERE, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_SURGERY))
|
||||
else
|
||||
owner.gain_trauma_type(BRAIN_TRAUMA_MILD, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_LOBOTOMY))
|
||||
owner.gain_trauma_type(BRAIN_TRAUMA_MILD, rand(TRAUMA_RESILIENCE_BASIC, TRAUMA_RESILIENCE_SURGERY))
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
/mob/living
|
||||
var/mb_cd_length = 5 SECONDS //5 second cooldown for masturbating because fuck spam.
|
||||
var/mb_cd_timer = 0 //The timer itself
|
||||
|
||||
/mob/living/carbon/human
|
||||
var/saved_underwear = ""//saves their underwear so it can be toggled later
|
||||
var/saved_undershirt = ""
|
||||
var/saved_socks = ""
|
||||
var/hidden_underwear = FALSE
|
||||
var/hidden_undershirt = FALSE
|
||||
var/hidden_socks = FALSE
|
||||
|
||||
//Mob procs
|
||||
/mob/living/carbon/human/proc/underwear_toggle()
|
||||
set name = "Toggle undergarments"
|
||||
set category = "IC"
|
||||
|
||||
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 == "Bottom")
|
||||
hidden_underwear = !hidden_underwear
|
||||
|
||||
if(confirm == "Socks")
|
||||
hidden_socks = !hidden_socks
|
||||
|
||||
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
|
||||
|
||||
update_body(TRUE)
|
||||
|
||||
|
||||
/mob/living/carbon/human/proc/adjust_arousal(strength,aphro = FALSE,maso = FALSE) // returns all genitals that were adjust
|
||||
var/list/obj/item/organ/genital/genit_list = list()
|
||||
if(!client?.prefs.arousable || (aphro && (client?.prefs.cit_toggles & NO_APHRO)) || (maso && !HAS_TRAIT(src, TRAIT_MASO)))
|
||||
return // no adjusting made here
|
||||
for(var/obj/item/organ/genital/G in internal_organs)
|
||||
if(G.genital_flags & GENITAL_CAN_AROUSE && !G.aroused_state && prob(strength*G.sensitivity))
|
||||
G.set_aroused_state(strength > 0)
|
||||
G.update_appearance()
|
||||
if(G.aroused_state)
|
||||
genit_list += G
|
||||
return genit_list
|
||||
|
||||
/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
|
||||
if(!target || !R)
|
||||
return
|
||||
var/turfing = isturf(target)
|
||||
G.generate_fluid()
|
||||
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))
|
||||
G.time_since_last_orgasm = 0
|
||||
R.clear_reagents()
|
||||
|
||||
/mob/living/carbon/human/proc/mob_climax_outside(obj/item/organ/genital/G, mb_time = 30) //This is used for forced orgasms and other hands-free climaxes
|
||||
var/datum/reagents/fluid_source = G.climaxable(src, TRUE)
|
||||
if(!fluid_source)
|
||||
to_chat(src,"<span class='userdanger'>Your [G.name] cannot cum.</span>")
|
||||
return
|
||||
if(mb_time) //as long as it's not instant, give a warning
|
||||
to_chat(src,"<span class='userlove'>You feel yourself about to orgasm.</span>")
|
||||
if(!do_after(src, mb_time, target = src) || !G.climaxable(src, TRUE))
|
||||
return
|
||||
to_chat(src,"<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/datum/reagents/fluid_source = G.climaxable(src)
|
||||
if(!fluid_source)
|
||||
return
|
||||
if(mb_time) //Skip warning if this is an instant climax.
|
||||
to_chat(src,"<span class='userlove'>You're about to climax with [L]!</span>")
|
||||
to_chat(L,"<span class='userlove'>[src] is about to climax with you!</span>")
|
||||
if(!do_after(src, mb_time, target = src) || !in_range(src, L) || !G.climaxable(src, TRUE))
|
||||
return
|
||||
if(spillage)
|
||||
to_chat(src,"<span class='userlove'>You orgasm with [L], spilling out of them, using your [G.name].</span>")
|
||||
to_chat(L,"<span class='userlove'>[src] climaxes with you, overflowing and spilling, using [p_their()] [G.name]!</span>")
|
||||
else //knots and other non-spilling orgasms
|
||||
to_chat(src,"<span class='userlove'>You climax with [L], your [G.name] spilling nothing.</span>")
|
||||
to_chat(L,"<span class='userlove'>[src] climaxes with you, [p_their()] [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/datum/reagents/fluid_source = G.climaxable(src)
|
||||
if(!fluid_source)
|
||||
return
|
||||
if(mb_time)
|
||||
to_chat(src,"<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
|
||||
to_chat(src,"<span class='userlove'>You used your [G.name] to fill [container].</span>")
|
||||
do_climax(fluid_source, container, G, FALSE)
|
||||
|
||||
/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(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
|
||||
else if(!silent)
|
||||
to_chat(src, "<span class='warning'>You cannot climax without available genitals.</span>")
|
||||
|
||||
/mob/living/carbon/human/proc/pick_partner(silent = FALSE)
|
||||
var/list/partners = list()
|
||||
if(pulling)
|
||||
partners += pulling
|
||||
if(pulledby)
|
||||
partners += pulledby
|
||||
//Now we got both of them, let's check if they're proper
|
||||
for(var/mob/living/L in partners)
|
||||
if(!L.client || !L.mind) // can't consent, not a partner
|
||||
partners -= L
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/C = L
|
||||
if(!C.exposed_genitals.len && !C.is_groin_exposed() && !C.is_chest_exposed()) //Nothing through_clothing, no proper partner.
|
||||
partners -= C
|
||||
//NOW the list should only contain correct partners
|
||||
if(!partners.len)
|
||||
if(!silent)
|
||||
to_chat(src, "<span class='warning'>You cannot do this alone.</span>")
|
||||
return //No one left.
|
||||
var/mob/living/target = input(src, "With whom?", "Sexual partner", null) as null|anything in partners //pick one, default to null
|
||||
if(target && in_range(src, target))
|
||||
to_chat(src,"<span class='notice'>Waiting for consent...</span>")
|
||||
var/consenting = input(target, "Do you want [src] to climax with you?","Climax mechanics","No") in list("Yes","No")
|
||||
if(consenting == "Yes")
|
||||
return target
|
||||
else
|
||||
message_admins("[src] tried to climax with [target], but [target] did not consent.")
|
||||
log_consent("[src] tried to climax with [target], but [target] did not consent.")
|
||||
|
||||
/mob/living/carbon/human/proc/pick_climax_container(silent = FALSE)
|
||||
var/list/containers_list = list()
|
||||
|
||||
for(var/obj/item/reagent_containers/C in held_items)
|
||||
if(C.is_open_container() || istype(C, /obj/item/reagent_containers/food/snacks))
|
||||
containers_list += C
|
||||
for(var/obj/item/reagent_containers/C in range(1, src))
|
||||
if((C.is_open_container() || istype(C, /obj/item/reagent_containers/food/snacks)) && CanReach(C))
|
||||
containers_list += C
|
||||
|
||||
if(containers_list.len)
|
||||
var/obj/item/reagent_containers/SC = input(src, "Into or onto what?(Cancel for nowhere)", null) as null|obj in containers_list
|
||||
if(SC && CanReach(SC))
|
||||
return SC
|
||||
else if(!silent)
|
||||
to_chat(src, "<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/proc/mob_climax(forced_climax=FALSE) //Forced is instead of the other proc, makes you cum if you have the tools for it, ignoring restraints
|
||||
if(mb_cd_timer > world.time)
|
||||
if(!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
|
||||
|
||||
if(!client?.prefs.arousable || !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/genital/G in internal_organs)
|
||||
if(!CHECK_BITFIELD(G.genital_flags, CAN_CLIMAX_WITH)) //Skip things like wombs and testicles
|
||||
continue
|
||||
var/mob/living/partner
|
||||
var/check_target
|
||||
var/list/worn_stuff = get_equipped_items()
|
||||
|
||||
if(G.is_exposed(worn_stuff))
|
||||
if(pulling) //Are we pulling someone? Priority target, we can't be making option menus for this, has to be quick
|
||||
if(isliving(pulling)) //Don't fuck objects
|
||||
check_target = pulling
|
||||
if(pulledby && !check_target) //prioritise pulled over pulledby
|
||||
if(isliving(pulledby))
|
||||
check_target = pulledby
|
||||
//Now we should have a partner, or else we have to come alone
|
||||
if(check_target)
|
||||
if(iscarbon(check_target)) //carbons can have clothes
|
||||
var/mob/living/carbon/C = check_target
|
||||
if(C.exposed_genitals.len || C.is_groin_exposed() || C.is_chest_exposed()) //Are they naked enough?
|
||||
partner = C
|
||||
else //A cat is fine too
|
||||
partner = check_target
|
||||
if(partner) //Did they pass the clothing checks?
|
||||
mob_climax_partner(G, partner, mb_time = 0) //Instant climax due to forced
|
||||
continue //You've climaxed once with this organ, continue on
|
||||
//not exposed OR if no partner was found while exposed, climax alone
|
||||
mob_climax_outside(G, mb_time = 0) //removed climax timer for sudden, forced orgasms
|
||||
//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 == UNCONSCIOUS) //No sleep-masturbation, you're unconscious.
|
||||
to_chat(src, "<span class='warning'>You must be conscious to do that!</span>")
|
||||
return
|
||||
|
||||
//Ok, now we check what they want to do.
|
||||
var/choice = input(src, "Select sexual activity", "Sexual activity:") as null|anything in list("Climax alone","Climax with partner", "Fill container")
|
||||
if(!choice)
|
||||
return
|
||||
|
||||
switch(choice)
|
||||
if("Climax alone")
|
||||
if(!available_rosie_palms())
|
||||
return
|
||||
var/obj/item/organ/genital/picked_organ = pick_climax_genitals()
|
||||
if(picked_organ && available_rosie_palms(TRUE))
|
||||
mob_climax_outside(picked_organ)
|
||||
if("Climax with partner")
|
||||
//We need no hands, we can be restrained and so on, so let's pick an organ
|
||||
var/obj/item/organ/genital/picked_organ = pick_climax_genitals()
|
||||
if(picked_organ)
|
||||
var/mob/living/partner = pick_partner() //Get someone
|
||||
if(partner)
|
||||
var/spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as null|anything in list("Yes", "No")
|
||||
if(spillage && in_range(src, partner))
|
||||
mob_climax_partner(picked_organ, partner, spillage == "Yes" ? TRUE : FALSE)
|
||||
if("Fill container")
|
||||
//We'll need hands and no restraints.
|
||||
if(!available_rosie_palms(FALSE, /obj/item/reagent_containers))
|
||||
return
|
||||
//We got hands, let's pick an organ
|
||||
var/obj/item/organ/genital/picked_organ
|
||||
picked_organ = pick_climax_genitals() //Gotta be climaxable, not just masturbation, to fill with fluids.
|
||||
if(picked_organ)
|
||||
//Good, got an organ, time to pick a container
|
||||
var/obj/item/reagent_containers/fluid_container = pick_climax_container()
|
||||
if(fluid_container && available_rosie_palms(TRUE, /obj/item/reagent_containers))
|
||||
mob_fill_container(picked_organ, fluid_container)
|
||||
|
||||
mb_cd_timer = world.time + mb_cd_length
|
||||
|
||||
/mob/living/carbon/human/verb/climax_verb()
|
||||
set category = "IC"
|
||||
set name = "Climax"
|
||||
set desc = "Lets you choose a couple ways to ejaculate."
|
||||
mob_climax()
|
||||
@@ -0,0 +1,374 @@
|
||||
/obj/item/organ/genital
|
||||
color = "#fcccb3"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
organ_flags = ORGAN_NO_DISMEMBERMENT
|
||||
var/shape
|
||||
var/sensitivity = 1 // wow if this were ever used that'd be cool but it's not but i'm keeping it for my unshit code
|
||||
var/genital_flags //see citadel_defines.dm
|
||||
var/masturbation_verb = "masturbate"
|
||||
var/orgasm_verb = "cumming" //present continous
|
||||
var/arousal_verb = "You feel aroused"
|
||||
var/unarousal_verb = "You no longer feel aroused"
|
||||
var/fluid_transfer_factor = 0 //How much would a partner get in them if they climax using this?
|
||||
var/size = 2 //can vary between num or text, just used in icon_state strings
|
||||
var/datum/reagent/fluid_id = null
|
||||
var/fluid_max_volume = 50
|
||||
var/fluid_efficiency = 1
|
||||
var/fluid_rate = CUM_RATE
|
||||
var/fluid_mult = 1
|
||||
var/time_since_last_orgasm = 500
|
||||
var/aroused_state = FALSE //Boolean used in icon_state strings
|
||||
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, do_update = TRUE)
|
||||
. = ..()
|
||||
if(fluid_id)
|
||||
create_reagents(fluid_max_volume, NONE, NO_REAGENTS_VALUE)
|
||||
if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION))
|
||||
reagents.add_reagent(fluid_id, fluid_max_volume)
|
||||
if(do_update)
|
||||
update()
|
||||
|
||||
/obj/item/organ/genital/proc/set_aroused_state(new_state)
|
||||
if(!(genital_flags & GENITAL_CAN_AROUSE))
|
||||
return FALSE
|
||||
if(!((HAS_TRAIT(owner,TRAIT_PERMABONER) && !new_state) || HAS_TRAIT(owner,TRAIT_NEVERBONER) && new_state))
|
||||
aroused_state = new_state
|
||||
return aroused_state
|
||||
|
||||
/obj/item/organ/genital/proc/update()
|
||||
if(QDELETED(src))
|
||||
return
|
||||
update_size()
|
||||
update_appearance()
|
||||
if(genital_flags & UPDATE_OWNER_APPEARANCE && owner && ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.update_genitals()
|
||||
if(linked_organ_slot || (linked_organ && !owner))
|
||||
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 || genital_flags & (GENITAL_INTERNAL|GENITAL_HIDDEN))
|
||||
return FALSE
|
||||
if(genital_flags & GENITAL_UNDIES_HIDDEN && ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(!(NO_UNDERWEAR in H.dna.species.species_traits))
|
||||
var/datum/sprite_accessory/underwear/top/T = H.hidden_undershirt ? null : GLOB.undershirt_list[H.undershirt]
|
||||
var/datum/sprite_accessory/underwear/bottom/B = H.hidden_underwear ? null : GLOB.underwear_list[H.underwear]
|
||||
if(zone == BODY_ZONE_CHEST ? (T?.covers_chest || B?.covers_chest) : (T?.covers_groin || B?.covers_groin))
|
||||
return FALSE
|
||||
if(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, update = TRUE)
|
||||
genital_flags &= ~(GENITAL_THROUGH_CLOTHES|GENITAL_HIDDEN|GENITAL_UNDIES_HIDDEN)
|
||||
if(owner)
|
||||
owner.exposed_genitals -= src
|
||||
switch(visibility)
|
||||
if(GEN_VISIBLE_ALWAYS)
|
||||
genital_flags |= GENITAL_THROUGH_CLOTHES
|
||||
if(owner)
|
||||
owner.exposed_genitals += src
|
||||
if(GEN_VISIBLE_NO_UNDIES)
|
||||
genital_flags |= GENITAL_UNDIES_HIDDEN
|
||||
if(GEN_VISIBLE_NEVER)
|
||||
genital_flags |= GENITAL_HIDDEN
|
||||
|
||||
if(update && owner && 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."
|
||||
|
||||
if(stat != CONSCIOUS)
|
||||
to_chat(usr, "<span class='warning'>You can toggle genitals visibility right now...</span>")
|
||||
return
|
||||
|
||||
var/list/genital_list = list()
|
||||
for(var/obj/item/organ/genital/G in internal_organs)
|
||||
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") as null|anything in genital_list
|
||||
if(picked_organ && (picked_organ in internal_organs))
|
||||
var/picked_visibility = input(src, "Choose visibility setting", "Expose/Hide genitals") as null|anything in GLOB.genitals_visibility_toggles
|
||||
if(picked_visibility && picked_organ && (picked_organ in internal_organs))
|
||||
picked_organ.toggle_visibility(picked_visibility)
|
||||
return
|
||||
|
||||
/mob/living/carbon/verb/toggle_arousal_state()
|
||||
set category = "IC"
|
||||
set name = "Toggle genital arousal"
|
||||
set desc = "Allows you to toggle which genitals are showing signs of arousal."
|
||||
var/list/genital_list = list()
|
||||
for(var/obj/item/organ/genital/G in internal_organs)
|
||||
if(G.genital_flags & GENITAL_CAN_AROUSE)
|
||||
genital_list += G
|
||||
if(!genital_list.len) //There's nothing that can show arousal
|
||||
return
|
||||
var/obj/item/organ/genital/picked_organ
|
||||
picked_organ = input(src, "Choose which genitalia to toggle arousal on", "Set genital arousal", null) in genital_list
|
||||
if(picked_organ)
|
||||
var/original_state = picked_organ.aroused_state
|
||||
picked_organ.set_aroused_state(!picked_organ.aroused_state)
|
||||
if(original_state != picked_organ.aroused_state)
|
||||
to_chat(src,"<span class='userlove'>[picked_organ.aroused_state ? picked_organ.arousal_verb : picked_organ.unarousal_verb].</span>")
|
||||
else
|
||||
to_chat(src,"<span class='userlove'>You can't make that genital [picked_organ.aroused_state ? "unaroused" : "aroused"]!</span>")
|
||||
picked_organ.update_appearance()
|
||||
return
|
||||
|
||||
|
||||
/obj/item/organ/genital/proc/modify_size(modifier, min = -INFINITY, max = INFINITY)
|
||||
fluid_max_volume += modifier*2.5
|
||||
fluid_rate += modifier/10
|
||||
if(reagents)
|
||||
reagents.maximum_volume = fluid_max_volume
|
||||
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 || !.)
|
||||
return
|
||||
reagents.maximum_volume = fluid_max_volume
|
||||
if(fluid_id && CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION))
|
||||
time_since_last_orgasm++
|
||||
|
||||
/obj/item/organ/genital/proc/generate_fluid()
|
||||
var/amount = clamp(fluid_rate * time_since_last_orgasm * fluid_mult,0,fluid_max_volume)
|
||||
reagents.clear_reagents()
|
||||
reagents.add_reagent(fluid_id,amount)
|
||||
return TRUE
|
||||
|
||||
/obj/item/organ/genital/proc/update_link()
|
||||
if(owner)
|
||||
if(linked_organ)
|
||||
return FALSE
|
||||
linked_organ = owner.getorganslot(linked_organ_slot)
|
||||
if(linked_organ)
|
||||
linked_organ.linked_organ = src
|
||||
linked_organ.upon_link()
|
||||
upon_link()
|
||||
return TRUE
|
||||
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)
|
||||
if(genital_flags & GENITAL_THROUGH_CLOTHES)
|
||||
owner.exposed_genitals += src
|
||||
|
||||
/obj/item/organ/genital/Remove(special = FALSE)
|
||||
. = ..()
|
||||
var/mob/living/carbon/C = .
|
||||
update()
|
||||
if(!QDELETED(C))
|
||||
if(genital_flags & UPDATE_OWNER_APPEARANCE && ishuman(C))
|
||||
var/mob/living/carbon/human/H = .
|
||||
H.update_genitals()
|
||||
C.exposed_genitals -= src
|
||||
UnregisterSignal(C, 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)
|
||||
|
||||
/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, FALSE)
|
||||
G.get_features(src)
|
||||
G.Insert(src)
|
||||
return G
|
||||
|
||||
/obj/item/organ/genital/proc/get_features(mob/living/carbon/human/H)
|
||||
return
|
||||
|
||||
|
||||
//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))
|
||||
return
|
||||
var/static/list/relevant_layers = list("[GENITALS_BEHIND_LAYER]" = "BEHIND", "[GENITALS_FRONT_LAYER]" = "FRONT")
|
||||
var/static/list/layers_num
|
||||
if(!layers_num)
|
||||
for(var/L in relevant_layers)
|
||||
LAZYSET(layers_num, L, text2num(L))
|
||||
for(var/L in relevant_layers) //Less hardcode
|
||||
remove_overlay(layers_num[L])
|
||||
remove_overlay(GENITALS_EXPOSED_LAYER)
|
||||
if(!LAZYLEN(internal_organs) || ((NOGENITALS in dna.species.species_traits) && !genital_override) || HAS_TRAIT(src, TRAIT_HUSK))
|
||||
return
|
||||
|
||||
//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 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 = relevant_layers[layer]
|
||||
for(var/A in genitals_to_add)
|
||||
var/obj/item/organ/genital/G = A
|
||||
var/datum/sprite_accessory/S
|
||||
var/size = G.size
|
||||
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/aroused_state = G.aroused_state && S.alt_aroused
|
||||
var/accessory_icon = S.icon
|
||||
var/do_center = S.center
|
||||
var/dim_x = S.dimension_x
|
||||
var/dim_y = S.dimension_y
|
||||
if(G.genital_flags & GENITAL_CAN_TAUR && S.taur_icon && (!S.feat_taur || dna.features[S.feat_taur]) && dna.species.mutant_bodyparts["taur"])
|
||||
var/datum/sprite_accessory/taur/T = GLOB.taur_list[dna.features["taur"]]
|
||||
if(T?.taur_mode & S.accepted_taurs)
|
||||
accessory_icon = S.taur_icon
|
||||
do_center = TRUE
|
||||
dim_x = S.taur_dimension_x
|
||||
dim_y = S.taur_dimension_y
|
||||
|
||||
var/mutable_appearance/genital_overlay = mutable_appearance(accessory_icon, layer = -layer)
|
||||
if(do_center)
|
||||
genital_overlay = center_image(genital_overlay, dim_x, dim_y)
|
||||
|
||||
if(dna.species.use_skintones && dna.features["genitals_use_skintone"])
|
||||
genital_overlay.color = SKINTONE2HEX(skin_tone)
|
||||
else
|
||||
switch(S.color_src)
|
||||
if("cock_color")
|
||||
genital_overlay.color = "#[dna.features["cock_color"]]"
|
||||
if("balls_color")
|
||||
genital_overlay.color = "#[dna.features["balls_color"]]"
|
||||
if("breasts_color")
|
||||
genital_overlay.color = "#[dna.features["breasts_color"]]"
|
||||
if("vag_color")
|
||||
genital_overlay.color = "#[dna.features["vag_color"]]"
|
||||
|
||||
genital_overlay.icon_state = "[G.slot]_[S.icon_state]_[size][(dna.species.use_skintones && !dna.skin_tone_override) ? "_s" : ""]_[aroused_state]_[layertext]"
|
||||
|
||||
if(layers_num[layer] == GENITALS_FRONT_LAYER && G.genital_flags & GENITAL_THROUGH_CLOTHES)
|
||||
genital_overlay.layer = -GENITALS_EXPOSED_LAYER
|
||||
LAZYADD(fully_exposed, genital_overlay)
|
||||
else
|
||||
genital_overlay.layer = -layers_num[layer]
|
||||
standing += genital_overlay
|
||||
|
||||
if(LAZYLEN(standing))
|
||||
overlays_standing[layers_num[layer]] = standing
|
||||
|
||||
if(LAZYLEN(fully_exposed))
|
||||
overlays_standing[GENITALS_EXPOSED_LAYER] = fully_exposed
|
||||
apply_overlay(GENITALS_EXPOSED_LAYER)
|
||||
|
||||
for(var/L in relevant_layers)
|
||||
apply_overlay(layers_num[L])
|
||||
|
||||
|
||||
//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(!client.prefs.arousable)
|
||||
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.use_skintones)
|
||||
dna.features["genitals_use_skintone"] = TRUE
|
||||
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
|
||||
@@ -0,0 +1,121 @@
|
||||
/datum/sprite_accessory
|
||||
var/alt_aroused = FALSE //CIT CODE if this is TRUE, then the genitals will use an alternate icon_state when aroused.
|
||||
var/taur_icon //leave null if the genital doesn't have a taur counterpart.
|
||||
var/accepted_taurs = STYLE_HOOF_TAURIC|STYLE_PAW_TAURIC //Types that match with the accessory.
|
||||
var/feat_taur //the text string of the dna feature to check for those who want to opt out.
|
||||
var/taur_dimension_y = 32
|
||||
var/taur_dimension_x = 32
|
||||
|
||||
|
||||
//DICKS,COCKS,PENISES,WHATEVER YOU WANT TO CALL THEM
|
||||
/datum/sprite_accessory/penis
|
||||
icon = 'icons/obj/genitals/penis_onmob.dmi'
|
||||
name = "penis" //the preview name of the accessory
|
||||
color_src = "cock_color"
|
||||
alt_aroused = TRUE
|
||||
feat_taur = "cock_taur"
|
||||
|
||||
/datum/sprite_accessory/penis/human
|
||||
icon_state = "human"
|
||||
name = "Human"
|
||||
|
||||
/datum/sprite_accessory/penis/knotted
|
||||
icon_state = "knotted"
|
||||
name = "Knotted"
|
||||
taur_icon = 'icons/obj/genitals/taur_penis_onmob.dmi'
|
||||
taur_dimension_x = 64
|
||||
|
||||
/datum/sprite_accessory/penis/flared
|
||||
icon_state = "flared"
|
||||
name = "Flared"
|
||||
taur_icon = 'icons/obj/genitals/taur_penis_onmob.dmi'
|
||||
taur_dimension_x = 64
|
||||
|
||||
/datum/sprite_accessory/penis/barbknot
|
||||
icon_state = "barbknot"
|
||||
name = "Barbed, Knotted"
|
||||
|
||||
/datum/sprite_accessory/penis/tapered
|
||||
icon_state = "tapered"
|
||||
name = "Tapered"
|
||||
taur_icon = 'icons/obj/genitals/taur_penis_onmob.dmi'
|
||||
taur_dimension_x = 64
|
||||
|
||||
/datum/sprite_accessory/penis/tentacle
|
||||
icon_state = "tentacle"
|
||||
name = "Tentacled"
|
||||
|
||||
/datum/sprite_accessory/penis/hemi
|
||||
icon_state = "hemi"
|
||||
name = "Hemi"
|
||||
|
||||
/datum/sprite_accessory/penis/hemiknot
|
||||
icon_state = "hemiknot"
|
||||
name = "Knotted Hemi"
|
||||
|
||||
//Testicles
|
||||
/datum/sprite_accessory/testicles
|
||||
icon = 'icons/obj/genitals/testicles_onmob.dmi'
|
||||
icon_state = "testicle"
|
||||
name = "testicle" //the preview name of the accessory
|
||||
color_src = "balls_color"
|
||||
|
||||
/datum/sprite_accessory/testicles/single
|
||||
icon_state = "single"
|
||||
name = "Single" //Single as "single pair", for clarity.
|
||||
|
||||
//Vaginas
|
||||
/datum/sprite_accessory/vagina
|
||||
icon = 'icons/obj/genitals/vagina_onmob.dmi'
|
||||
name = "vagina"
|
||||
color_src = "vag_color"
|
||||
alt_aroused = TRUE
|
||||
|
||||
/datum/sprite_accessory/vagina/human
|
||||
icon_state = "human"
|
||||
name = "Human"
|
||||
|
||||
/datum/sprite_accessory/vagina/tentacles
|
||||
icon_state = "tentacle"
|
||||
name = "Tentacle"
|
||||
|
||||
/datum/sprite_accessory/vagina/dentata
|
||||
icon_state = "dentata"
|
||||
name = "Dentata"
|
||||
|
||||
/datum/sprite_accessory/vagina/hairy
|
||||
icon_state = "hairy"
|
||||
name = "Hairy"
|
||||
alt_aroused = FALSE
|
||||
|
||||
/datum/sprite_accessory/vagina/spade
|
||||
icon_state = "spade"
|
||||
name = "Spade"
|
||||
alt_aroused = FALSE
|
||||
|
||||
/datum/sprite_accessory/vagina/furred
|
||||
icon_state = "furred"
|
||||
name = "Furred"
|
||||
alt_aroused = FALSE
|
||||
|
||||
/datum/sprite_accessory/vagina/gaping
|
||||
icon_state = "gaping"
|
||||
name = "Gaping"
|
||||
|
||||
//BREASTS BE HERE
|
||||
/datum/sprite_accessory/breasts
|
||||
icon = 'icons/obj/genitals/breasts_onmob.dmi'
|
||||
name = "breasts"
|
||||
color_src = "breasts_color"
|
||||
|
||||
/datum/sprite_accessory/breasts/pair
|
||||
icon_state = "pair"
|
||||
name = "Pair"
|
||||
|
||||
/datum/sprite_accessory/breasts/quad
|
||||
icon_state = "quad"
|
||||
name = "Quad"
|
||||
|
||||
/datum/sprite_accessory/breasts/sextuple
|
||||
icon_state = "sextuple"
|
||||
name = "Sextuple"
|
||||
@@ -0,0 +1,137 @@
|
||||
#define BREASTS_ICON_MIN_SIZE 1
|
||||
#define BREASTS_ICON_MAX_SIZE 6
|
||||
|
||||
/obj/item/organ/genital/breasts
|
||||
name = "breasts"
|
||||
desc = "Female milk producing organs."
|
||||
icon_state = "breasts"
|
||||
icon = 'icons/obj/genitals/breasts.dmi'
|
||||
zone = BODY_ZONE_CHEST
|
||||
slot = ORGAN_SLOT_BREASTS
|
||||
size = BREASTS_SIZE_DEF // "c". Refer to the breast_values static list below for the cups associated number values
|
||||
fluid_id = /datum/reagent/consumable/milk
|
||||
fluid_rate = MILK_RATE
|
||||
shape = DEF_BREASTS_SHAPE
|
||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_FUID_PRODUCTION|GENITAL_CAN_AROUSE|UPDATE_OWNER_APPEARANCE|GENITAL_UNDIES_HIDDEN
|
||||
masturbation_verb = "massage"
|
||||
arousal_verb = "Your breasts start feeling sensitive"
|
||||
unarousal_verb = "Your breasts no longer feel sensitive"
|
||||
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/Initialize(mapload, do_update = TRUE)
|
||||
if(do_update)
|
||||
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")
|
||||
desc = "You see a pair of breasts."
|
||||
if("quad")
|
||||
desc = "You see two pairs of breast, one just under the other."
|
||||
if("sextuple")
|
||||
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(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 (size == "flat")
|
||||
desc += " They're very small and flatchested, however."
|
||||
else
|
||||
desc += " You estimate that they're [uppertext(size)]-cups."
|
||||
|
||||
if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION) && aroused_state)
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[fluid_id]
|
||||
if(R)
|
||||
desc += " They're leaking [lowertext(R.name)]."
|
||||
var/datum/sprite_accessory/S = GLOB.breasts_shapes_list[shape]
|
||||
var/icon_shape = S ? S.icon_state : "pair"
|
||||
var/icon_size = clamp(breast_values[size], BREASTS_ICON_MIN_SIZE, BREASTS_ICON_MAX_SIZE)
|
||||
icon_state = "breasts_[icon_shape]_[icon_size]"
|
||||
if(owner)
|
||||
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
|
||||
if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow...
|
||||
var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need.
|
||||
color = SKINTONE2HEX(H.skin_tone)
|
||||
if(!H.dna.skin_tone_override)
|
||||
icon_state += "_s"
|
||||
else
|
||||
color = "#[owner.dna.features["breasts_color"]]"
|
||||
|
||||
//Allows breasts to grow and change size, with sprite changes too.
|
||||
//maximum wah
|
||||
//Comical sizes slow you down in movement and actions.
|
||||
//Ridiculous sizes makes you more cumbersome.
|
||||
//this is far too lewd wah
|
||||
|
||||
/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
|
||||
prev_size = cached_size
|
||||
cached_size = new_value
|
||||
update()
|
||||
..()
|
||||
|
||||
/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(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"]
|
||||
if(!D.features["breasts_producing"])
|
||||
DISABLE_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION|CAN_CLIMAX_WITH|CAN_MASTURBATE_WITH)
|
||||
if(!isnum(size))
|
||||
cached_size = breast_values[size]
|
||||
else
|
||||
cached_size = size
|
||||
size = breast_values[size]
|
||||
prev_size = cached_size
|
||||
toggle_visibility(D.features["breasts_visibility"], FALSE)
|
||||
|
||||
#undef BREASTS_ICON_MIN_SIZE
|
||||
#undef BREASTS_ICON_MAX_SIZE
|
||||
@@ -0,0 +1,109 @@
|
||||
/obj/item/organ/genital/penis
|
||||
name = "penis"
|
||||
desc = "A male reproductive organ."
|
||||
icon_state = "penis"
|
||||
icon = 'icons/obj/genitals/penis.dmi'
|
||||
zone = BODY_ZONE_PRECISE_GROIN
|
||||
slot = ORGAN_SLOT_PENIS
|
||||
masturbation_verb = "stroke"
|
||||
arousal_verb = "You pop a boner"
|
||||
unarousal_verb = "Your boner goes down"
|
||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_CAN_AROUSE|UPDATE_OWNER_APPEARANCE|GENITAL_UNDIES_HIDDEN|GENITAL_CAN_TAUR
|
||||
linked_organ_slot = ORGAN_SLOT_TESTICLES
|
||||
fluid_transfer_factor = 0.5
|
||||
shape = DEF_COCK_SHAPE
|
||||
size = 2 //arbitrary value derived from length and diameter for sprites.
|
||||
layer_index = PENIS_LAYER_INDEX
|
||||
var/length = 6 //inches
|
||||
|
||||
var/prev_length = 6 //really should be renamed to prev_length
|
||||
var/diameter = 4.38
|
||||
var/diameter_ratio = COCK_DIAMETER_RATIO_DEF //0.25; check citadel_defines.dm
|
||||
|
||||
/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
|
||||
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.dick_nouns)] [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.dick_nouns)] [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]")
|
||||
diameter = (length * diameter_ratio)//Is it just me or is this ludicous, why not make it exponentially decay?
|
||||
|
||||
|
||||
/obj/item/organ/genital/penis/update_appearance()
|
||||
. = ..()
|
||||
var/datum/sprite_accessory/S = GLOB.cock_shapes_list[shape]
|
||||
var/icon_shape = S ? S.icon_state : "human"
|
||||
icon_state = "penis_[icon_shape]_[size]"
|
||||
var/lowershape = lowertext(shape)
|
||||
|
||||
if(owner)
|
||||
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
|
||||
if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow...
|
||||
var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need.
|
||||
color = SKINTONE2HEX(H.skin_tone)
|
||||
if(!H.dna.skin_tone_override)
|
||||
icon_state += "_s"
|
||||
else
|
||||
color = "#[owner.dna.features["cock_color"]]"
|
||||
if(genital_flags & GENITAL_CAN_TAUR && S?.taur_icon && (!S.feat_taur || owner.dna.features[S.feat_taur]) && owner.dna.species.mutant_bodyparts["taur"])
|
||||
var/datum/sprite_accessory/taur/T = GLOB.taur_list[owner.dna.features["taur"]]
|
||||
if(T.taur_mode & S.accepted_taurs) //looks out of place on those.
|
||||
lowershape = "taur, [lowershape]"
|
||||
|
||||
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(diameter, 0.25)] inch[round(diameter, 0.25) != 1 ? "es" : ""] in diameter."
|
||||
|
||||
/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
|
||||
color = "#[D.features["cock_color"]]"
|
||||
length = D.features["cock_length"]
|
||||
diameter_ratio = D.features["cock_diameter_ratio"]
|
||||
shape = D.features["cock_shape"]
|
||||
prev_length = length
|
||||
toggle_visibility(D.features["cock_visibility"], FALSE)
|
||||
@@ -0,0 +1,67 @@
|
||||
/obj/item/organ/genital/testicles
|
||||
name = "testicles"
|
||||
desc = "A male reproductive organ."
|
||||
icon_state = "testicles"
|
||||
icon = 'icons/obj/genitals/testicles.dmi'
|
||||
zone = BODY_ZONE_PRECISE_GROIN
|
||||
slot = ORGAN_SLOT_TESTICLES
|
||||
size = BALLS_SIZE_MIN
|
||||
arousal_verb = "Your balls ache a little"
|
||||
unarousal_verb = "Your balls finally stop aching, again"
|
||||
linked_organ_slot = ORGAN_SLOT_PENIS
|
||||
genital_flags = CAN_MASTURBATE_WITH|MASTURBATE_LINKED_ORGAN|GENITAL_FUID_PRODUCTION|UPDATE_OWNER_APPEARANCE|GENITAL_UNDIES_HIDDEN
|
||||
var/size_name = "average"
|
||||
shape = DEF_BALLS_SHAPE
|
||||
fluid_id = /datum/reagent/consumable/semen
|
||||
masturbation_verb = "massage"
|
||||
layer_index = TESTICLES_LAYER_INDEX
|
||||
|
||||
/obj/item/organ/genital/testicles/generate_fluid()
|
||||
if(!linked_organ && !update_link())
|
||||
return FALSE
|
||||
return ..()
|
||||
// in memoriam "Your balls finally feel full, again." ??-2020
|
||||
|
||||
/obj/item/organ/genital/testicles/upon_link()
|
||||
size = linked_organ.size
|
||||
update_size()
|
||||
update_appearance()
|
||||
|
||||
/obj/item/organ/genital/testicles/update_size(modified = FALSE)
|
||||
switch(size)
|
||||
if(BALLS_SIZE_MIN)
|
||||
size_name = "average"
|
||||
if(BALLS_SIZE_DEF)
|
||||
size_name = "enlarged"
|
||||
if(BALLS_SIZE_MAX)
|
||||
size_name = "engorged"
|
||||
else
|
||||
size_name = "nonexistant"
|
||||
|
||||
/obj/item/organ/genital/testicles/update_appearance()
|
||||
. = ..()
|
||||
desc = "You see an [size_name] pair of testicles."
|
||||
var/datum/sprite_accessory/S = GLOB.balls_shapes_list[shape]
|
||||
var/icon_shape = S ? S.icon_state : "single"
|
||||
icon_state = "testicles_[icon_shape]_[size]"
|
||||
if(owner)
|
||||
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
|
||||
if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow...
|
||||
var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need.
|
||||
color = SKINTONE2HEX(H.skin_tone)
|
||||
if(!H.dna.skin_tone_override)
|
||||
icon_state += "_s"
|
||||
else
|
||||
color = "#[owner.dna.features["balls_color"]]"
|
||||
|
||||
/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"]]"
|
||||
shape = D.features["balls_shape"]
|
||||
fluid_rate = D.features["balls_cum_rate"]
|
||||
fluid_mult = D.features["balls_cum_mult"]
|
||||
fluid_efficiency = D.features["balls_efficiency"]
|
||||
toggle_visibility(D.features["balls_visibility"], FALSE)
|
||||
@@ -0,0 +1,74 @@
|
||||
/obj/item/organ/genital/vagina
|
||||
name = "vagina"
|
||||
desc = "A female reproductive organ."
|
||||
icon = '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
|
||||
shape = DEF_VAGINA_SHAPE
|
||||
genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_CAN_AROUSE|GENITAL_UNDIES_HIDDEN
|
||||
masturbation_verb = "finger"
|
||||
arousal_verb = "You feel wetness on your crotch"
|
||||
unarousal_verb = "You no longer feel wet"
|
||||
fluid_transfer_factor = 0.1 //Yes, some amount is exposed to you, go get your AIDS
|
||||
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/list/vag_types = list("tentacle", "dentata", "hairy", "spade", "furred")
|
||||
|
||||
/obj/item/organ/genital/vagina/update_appearance()
|
||||
. = ..()
|
||||
icon_state = "vagina"
|
||||
var/lowershape = lowertext(shape)
|
||||
var/details
|
||||
|
||||
switch(lowershape)
|
||||
if("tentacle")
|
||||
details = "Its opening is lined with several tentacles and "
|
||||
if("dentata")
|
||||
details = "There's teeth inside it and it "
|
||||
if("hairy")
|
||||
details = "It has quite a bit of hair growing on it and "
|
||||
if("human")
|
||||
details = "It is taut with smooth skin, though without much hair and "
|
||||
if("gaping")
|
||||
details = "It is gaping slightly open, though without much hair and "
|
||||
if("spade")
|
||||
details = "It is a plush canine spade, it "
|
||||
if("furred")
|
||||
details = "It has neatly groomed fur around the outer folds, it "
|
||||
else
|
||||
details = "It has an exotic shape and "
|
||||
if(aroused_state)
|
||||
details += "is slick with female arousal."
|
||||
else
|
||||
details += "seems to be dry."
|
||||
|
||||
desc = "You see a vagina. [details]"
|
||||
|
||||
if(owner)
|
||||
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
|
||||
if(ishuman(owner)) // Check before recasting type, although someone fucked up if you're not human AND have use_skintones somehow...
|
||||
var/mob/living/carbon/human/H = owner // only human mobs have skin_tone, which we need.
|
||||
color = SKINTONE2HEX(H.skin_tone)
|
||||
if(!H.dna.skin_tone_override)
|
||||
icon_state += "_s"
|
||||
else
|
||||
color = "#[owner.dna.features["vag_color"]]"
|
||||
if(ishuman(owner))
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.update_genitals()
|
||||
|
||||
/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
|
||||
color = "[D.features["vag_color"]]"
|
||||
shape = "[D.features["vag_shape"]]"
|
||||
toggle_visibility(D.features["vag_visibility"], FALSE)
|
||||
@@ -0,0 +1,10 @@
|
||||
/obj/item/organ/genital/womb
|
||||
name = "womb"
|
||||
desc = "A female reproductive organ."
|
||||
icon = '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 = /datum/reagent/consumable/femcum
|
||||
linked_organ_slot = ORGAN_SLOT_VAGINA
|
||||
@@ -0,0 +1,159 @@
|
||||
//////////
|
||||
//DILDOS//
|
||||
//////////
|
||||
/obj/item/dildo
|
||||
name = "dildo"
|
||||
desc = "Floppy!"
|
||||
icon = 'icons/obj/genitals/dildo.dmi'
|
||||
force = 0
|
||||
hitsound = 'sound/weapons/tap.ogg'
|
||||
throwforce = 0
|
||||
icon_state = "dildo_knotted_2"
|
||||
alpha = 192//transparent
|
||||
var/can_customize = FALSE
|
||||
var/dildo_shape = "human"
|
||||
var/dildo_size = 2
|
||||
var/dildo_type = "dildo"//pretty much just used for the icon state
|
||||
var/random_color = TRUE
|
||||
var/random_size = FALSE
|
||||
var/random_shape = FALSE
|
||||
var/is_knotted = FALSE
|
||||
//Lists moved to _cit_helpers.dm as globals so they're not instanced individually
|
||||
|
||||
/obj/item/dildo/proc/update_appearance()
|
||||
icon_state = "[dildo_type]_[dildo_shape]_[dildo_size]"
|
||||
var/sizeword = ""
|
||||
switch(dildo_size)
|
||||
if(1)
|
||||
sizeword = "small "
|
||||
if(3)
|
||||
sizeword = "big "
|
||||
if(4)
|
||||
sizeword = "huge "
|
||||
if(5)
|
||||
sizeword = "gigantic "
|
||||
|
||||
name = "[sizeword][dildo_shape] [can_customize ? "custom " : ""][dildo_type]"
|
||||
|
||||
/obj/item/dildo/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
customize(user)
|
||||
return TRUE
|
||||
|
||||
/obj/item/dildo/proc/customize(mob/living/user)
|
||||
if(!can_customize)
|
||||
return FALSE
|
||||
if(src && !user.incapacitated() && in_range(user,src))
|
||||
var/color_choice = input(user,"Choose a color for your dildo.","Dildo Color") as null|anything in GLOB.dildo_colors
|
||||
if(src && color_choice && !user.incapacitated() && in_range(user,src))
|
||||
sanitize_inlist(color_choice, GLOB.dildo_colors, "Red")
|
||||
color = GLOB.dildo_colors[color_choice]
|
||||
update_appearance()
|
||||
if(src && !user.incapacitated() && in_range(user,src))
|
||||
var/shape_choice = input(user,"Choose a shape for your dildo.","Dildo Shape") as null|anything in GLOB.dildo_shapes
|
||||
if(src && shape_choice && !user.incapacitated() && in_range(user,src))
|
||||
sanitize_inlist(shape_choice, GLOB.dildo_colors, "Knotted")
|
||||
dildo_shape = GLOB.dildo_shapes[shape_choice]
|
||||
update_appearance()
|
||||
if(src && !user.incapacitated() && in_range(user,src))
|
||||
var/size_choice = input(user,"Choose the size for your dildo.","Dildo Size") as null|anything in GLOB.dildo_sizes
|
||||
if(src && size_choice && !user.incapacitated() && in_range(user,src))
|
||||
sanitize_inlist(size_choice, GLOB.dildo_colors, "Medium")
|
||||
dildo_size = GLOB.dildo_sizes[size_choice]
|
||||
update_appearance()
|
||||
if(src && !user.incapacitated() && in_range(user,src))
|
||||
var/transparency_choice = input(user,"Choose the transparency of your dildo. Lower is more transparent!(192-255)","Dildo Transparency") as null|num
|
||||
if(src && transparency_choice && !user.incapacitated() && in_range(user,src))
|
||||
sanitize_integer(transparency_choice, 192, 255, 192)
|
||||
alpha = transparency_choice
|
||||
update_appearance()
|
||||
return TRUE
|
||||
|
||||
/obj/item/dildo/Initialize()
|
||||
. = ..()
|
||||
if(random_color == TRUE)
|
||||
var/randcolor = pick(GLOB.dildo_colors)
|
||||
color = GLOB.dildo_colors[randcolor]
|
||||
if(random_shape == TRUE)
|
||||
var/randshape = pick(GLOB.dildo_shapes)
|
||||
dildo_shape = GLOB.dildo_shapes[randshape]
|
||||
if(random_size == TRUE)
|
||||
var/randsize = pick(GLOB.dildo_sizes)
|
||||
dildo_size = GLOB.dildo_sizes[randsize]
|
||||
update_appearance()
|
||||
alpha = rand(192, 255)
|
||||
pixel_y = rand(-7,7)
|
||||
pixel_x = rand(-7,7)
|
||||
|
||||
/obj/item/dildo/examine(mob/user)
|
||||
. = ..()
|
||||
if(can_customize)
|
||||
. += "<span class='notice'>Alt-Click \the [src.name] to customize it.</span>"
|
||||
|
||||
/obj/item/dildo/random//totally random
|
||||
name = "random dildo"//this name will show up in vendors and shit so you know what you're vending(or don't, i guess :^))
|
||||
random_color = TRUE
|
||||
random_shape = TRUE
|
||||
random_size = TRUE
|
||||
|
||||
/obj/item/dildo/knotted
|
||||
dildo_shape = "knotted"
|
||||
name = "knotted dildo"
|
||||
attack_verb = list("penetrated", "knotted", "slapped", "inseminated")
|
||||
|
||||
obj/item/dildo/human
|
||||
dildo_shape = "human"
|
||||
name = "human dildo"
|
||||
attack_verb = list("penetrated", "slapped", "inseminated")
|
||||
|
||||
obj/item/dildo/plain
|
||||
dildo_shape = "plain"
|
||||
name = "plain dildo"
|
||||
attack_verb = list("penetrated", "slapped", "inseminated")
|
||||
|
||||
obj/item/dildo/flared
|
||||
dildo_shape = "flared"
|
||||
name = "flared dildo"
|
||||
attack_verb = list("penetrated", "slapped", "neighed", "gaped", "prolapsed", "inseminated")
|
||||
|
||||
obj/item/dildo/flared/huge
|
||||
name = "literal horse cock"
|
||||
desc = "THIS THING IS HUGE!"
|
||||
dildo_size = 4
|
||||
|
||||
obj/item/dildo/custom
|
||||
name = "customizable dildo"
|
||||
desc = "Thanks to significant advances in synthetic nanomaterials, this dildo is capable of taking on many different forms to fit the user's preferences! Pricy!"
|
||||
can_customize = TRUE
|
||||
random_color = TRUE
|
||||
random_shape = TRUE
|
||||
random_size = TRUE
|
||||
|
||||
// Suicide acts, by request
|
||||
|
||||
/obj/item/dildo/proc/manual_suicide(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] finally finishes deepthroating the [src], and their life.</span>")
|
||||
user.adjustOxyLoss(200)
|
||||
user.death(0)
|
||||
|
||||
/obj/item/dildo/suicide_act(mob/living/user)
|
||||
// is_knotted = ((src.dildo_shape == "knotted")?"They swallowed the knot":"Their face is turning blue")
|
||||
if(do_after(user,17,target=src))
|
||||
user.visible_message("<span class='suicide'>[user] tears-up and gags as they shove [src] down their throat! It looks like [user.p_theyre()] trying to commit suicide!</span>")
|
||||
playsound(loc, 'sound/weapons/gagging.ogg', 50, 1, -1)
|
||||
user.Stun(150)
|
||||
user.adjust_blurriness(8)
|
||||
var/obj/item/organ/eyes/eyes = user.getorganslot(ORGAN_SLOT_EYES)
|
||||
eyes?.applyOrganDamage(10)
|
||||
return MANUAL_SUICIDE
|
||||
|
||||
/obj/item/dildo/flared/huge/suicide_act(mob/living/user)
|
||||
if(do_after(user,35,target=src))
|
||||
user.visible_message("<span class='suicide'>[user] tears-up and gags as they try to deepthroat the [src]! WHY WOULD THEY DO THAT? It looks like [user.p_theyre()] trying to commit suicide!!</span>")
|
||||
playsound(loc, 'sound/weapons/gagging.ogg', 50, 2, -1)
|
||||
user.Stun(300)
|
||||
user.adjust_blurriness(8)
|
||||
return MANUAL_SUICIDE
|
||||
|
||||
@@ -786,9 +786,8 @@
|
||||
return
|
||||
user.visible_message("[user.name] wires the air alarm.", \
|
||||
"<span class='notice'>You start wiring the air alarm...</span>")
|
||||
if (do_after(user, 20, target = src))
|
||||
if (cable.get_amount() >= 5 && buildstage == 1)
|
||||
cable.use(5)
|
||||
if (W.use_tool(src, user, 20, 5))
|
||||
if (buildstage == 1)
|
||||
to_chat(user, "<span class='notice'>You wire the air alarm.</span>")
|
||||
wires.repair()
|
||||
aidisabled = 0
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
desc = "You put the cake on your head. Brilliant."
|
||||
icon_state = "hardhat0_cakehat"
|
||||
item_state = "hardhat0_cakehat"
|
||||
hat_type = "cakehat"
|
||||
hitsound = 'sound/weapons/tap.ogg'
|
||||
flags_inv = HIDEEARS|HIDEHAIR
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0)
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
/obj/item/clothing/under/attackby(obj/item/I, mob/user, params)
|
||||
if((has_sensor == BROKEN_SENSORS) && istype(I, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/C = I
|
||||
C.use(1)
|
||||
I.use_tool(src, user, 0, 1)
|
||||
has_sensor = HAS_SENSORS
|
||||
to_chat(user,"<span class='notice'>You repair the suit sensors on [src] with [C].</span>")
|
||||
return 1
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/sushi_basic
|
||||
name = "funa hosomaki"
|
||||
desc = "A small cylindrical kudzu skin, filled with rice and fish."
|
||||
icon = 'modular_citadel/icons/obj/food/food.dmi'
|
||||
icon_state = "sushie_basic"
|
||||
bonus_reagents = list(/datum/reagent/consumable/nutriment/vitamin = 2)
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 4)
|
||||
@@ -69,7 +68,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/sushi_adv
|
||||
name = "funa nigiri"
|
||||
desc = "A peace of carp lightly placed on some rice."
|
||||
icon = 'modular_citadel/icons/obj/food/food.dmi'
|
||||
icon_state = "sushie_adv"
|
||||
bonus_reagents = list(/datum/reagent/consumable/nutriment/vitamin = 2)
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 6)
|
||||
@@ -81,7 +79,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/sushi_pro
|
||||
name = "funa nigiri"
|
||||
desc = "A well prepared peace of the best of the carp fillet placed on rice. Looks fancy and fresh!"
|
||||
icon = 'modular_citadel/icons/obj/food/food.dmi'
|
||||
icon_state = "sushie_pro"
|
||||
bonus_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/nutriment/vitamin = 2)
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/nutriment/vitamin = 2)
|
||||
|
||||
@@ -215,7 +215,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/tobiko
|
||||
name = "tobiko"
|
||||
desc = "Spider eggs wrapped in a thin salted Kudzu pod"
|
||||
icon = 'modular_citadel/icons/obj/food/food.dmi'
|
||||
icon_state = "sushie_egg"
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/nutriment/vitamin = 2)
|
||||
filling_color = "#FF3333" // R225 G051 B051
|
||||
@@ -558,7 +557,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/riceball
|
||||
name = "onigiri"
|
||||
desc = "A ball of rice with some light salt and a wrap of Kudzu skin."
|
||||
icon = 'modular_citadel/icons/obj/food/food.dmi'
|
||||
icon_state = "riceball"
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/sodiumchloride = 2)
|
||||
tastes = list("rice" = 3, "salt" = 1)
|
||||
|
||||
@@ -136,7 +136,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/tuna_sandwich
|
||||
name = "tuna sandwich"
|
||||
desc = "Both a salad and a sandwich in one."
|
||||
icon = 'modular_citadel/icons/obj/food/food.dmi'
|
||||
icon_state = "tunasandwich"
|
||||
trash = /obj/item/trash/plate
|
||||
bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 3)
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/sushi_rice
|
||||
name = "Sushi Rice"
|
||||
desc = "A bowl of sticky rice for making sushi."
|
||||
icon = 'modular_citadel/icons/obj/food/food.dmi'
|
||||
icon_state = "sushi_rice"
|
||||
list_reagents = list(/datum/reagent/consumable/sodiumchloride = 5)
|
||||
tastes = list("rice" = 5, "salt" = 1)
|
||||
@@ -12,7 +11,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/sea_weed
|
||||
name = "Sea Weed Sheet"
|
||||
desc = "A thin, light salt sheet of plant mater. This is commenly used in sushi recipes,"
|
||||
icon = 'modular_citadel/icons/obj/food/food.dmi'
|
||||
icon_state = "sea_weed"
|
||||
list_reagents = list(/datum/reagent/consumable/sodiumchloride = 2)
|
||||
tastes = list("plants" = 2, "salt" = 1)
|
||||
@@ -21,7 +19,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/tuna
|
||||
name = "Canned Tuna"
|
||||
desc = "A small can of tuna fish beloved by felines."
|
||||
icon = 'modular_citadel/icons/obj/food/food.dmi'
|
||||
icon_state = "tuna_can"
|
||||
//trash = /obj/item/trash/tuna_used //I dont know if I like this idea - A Masked Cat
|
||||
list_reagents = list(/datum/reagent/consumable/sodiumchloride = 5, /datum/reagent/mercury = 2)
|
||||
@@ -32,7 +29,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/sushie_basic
|
||||
name = "Funa Hosomaki"
|
||||
desc = "A small cylindrical filled with rice and fish."
|
||||
icon = 'modular_citadel/icons/obj/food/food.dmi'
|
||||
icon_state = "sushie_basic"
|
||||
bonus_reagents = list(/datum/reagent/consumable/nutriment/vitamin = 2)
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 1)
|
||||
@@ -44,7 +40,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/sushie_adv
|
||||
name = "Funa Nigiri"
|
||||
desc = "A pice of carp lightly placed on some rice."
|
||||
icon = 'modular_citadel/icons/obj/food/food.dmi'
|
||||
icon_state = "sushie_adv"
|
||||
bonus_reagents = list(/datum/reagent/consumable/nutriment/vitamin = 2)
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 2)
|
||||
@@ -56,7 +51,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/sushie_pro
|
||||
name = "Funa Nigiri"
|
||||
desc = "A well prepared pice of the best of the carp fillet placed on rice. Looks fancy and fresh!"
|
||||
icon = 'modular_citadel/icons/obj/food/food.dmi'
|
||||
icon_state = "sushie_pro"
|
||||
bonus_reagents = list(/datum/reagent/consumable/nutriment = 1, /datum/reagent/consumable/nutriment/vitamin = 2)
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 8, /datum/reagent/consumable/nutriment/vitamin = 1)
|
||||
@@ -68,7 +62,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/tobiko
|
||||
name = "Tobiko"
|
||||
desc = "Spider eggs wrapped in a thin salted Kudzu pod"
|
||||
icon = 'modular_citadel/icons/obj/food/food.dmi'
|
||||
icon_state = "sushie_egg"
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/vitamin = 2)
|
||||
filling_color = "#FF3333" // R225 G051 B051
|
||||
@@ -78,7 +71,6 @@
|
||||
/obj/item/reagent_containers/food/snacks/riceball
|
||||
name = "Onigiri"
|
||||
desc = "A ball of rice with some light salt and a wrap of Kudzu skin."
|
||||
icon = 'modular_citadel/icons/obj/food/food.dmi'
|
||||
icon_state = "riceball"
|
||||
list_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/sodiumchloride = 2)
|
||||
tastes = list("rice" = 4, "salt" = 1)
|
||||
|
||||
@@ -392,8 +392,7 @@
|
||||
|
||||
/datum/plant_gene/trait/battery/on_attackby(obj/item/reagent_containers/food/snacks/grown/G, obj/item/I, mob/user)
|
||||
if(istype(I, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/C = I
|
||||
if(C.use(5))
|
||||
if(I.use_tool(src, user, 0, 5, max_level = JOB_SKILL_EXPERT))
|
||||
to_chat(user, "<span class='notice'>You add some cable to [G] and slide it inside the battery encasing.</span>")
|
||||
var/obj/item/stock_parts/cell/potato/pocell = new /obj/item/stock_parts/cell/potato(user.loc)
|
||||
pocell.icon_state = G.icon_state
|
||||
|
||||
@@ -66,6 +66,11 @@
|
||||
/obj/item/instrument/proc/is_tuned()
|
||||
return tune_time_left > 0
|
||||
|
||||
/obj/item/instrument/dropped(mob/user)
|
||||
. = ..()
|
||||
if((loc != user) && (user.machine == src))
|
||||
user.set_machine(null)
|
||||
|
||||
/obj/item/instrument/interact(mob/user)
|
||||
ui_interact(user)
|
||||
|
||||
|
||||
@@ -222,7 +222,9 @@
|
||||
tempo = sanitize_tempo(600 / bpm)
|
||||
|
||||
/// Updates the window for our user. Override in subtypes.
|
||||
/datum/song/proc/updateDialog(mob/user)
|
||||
/datum/song/proc/updateDialog(mob/user = usr)
|
||||
if(user.machine != src)
|
||||
return
|
||||
ui_interact(user)
|
||||
|
||||
/datum/song/process(wait)
|
||||
@@ -277,8 +279,10 @@
|
||||
// subtype for handheld instruments, like violin
|
||||
/datum/song/handheld
|
||||
|
||||
/datum/song/handheld/updateDialog(mob/user)
|
||||
parent.ui_interact(user || usr)
|
||||
/datum/song/handheld/updateDialog(mob/user = usr)
|
||||
if(user.machine != src)
|
||||
return
|
||||
parent.ui_interact(user)
|
||||
|
||||
/datum/song/handheld/should_stop_playing(mob/user)
|
||||
. = ..()
|
||||
@@ -290,8 +294,10 @@
|
||||
// subtype for stationary structures, like pianos
|
||||
/datum/song/stationary
|
||||
|
||||
/datum/song/stationary/updateDialog(mob/user)
|
||||
parent.ui_interact(user || usr)
|
||||
/datum/song/stationary/updateDialog(mob/user = usr)
|
||||
if(user.machine != src)
|
||||
return
|
||||
parent.ui_interact(user)
|
||||
|
||||
/datum/song/stationary/should_stop_playing(mob/user)
|
||||
. = ..()
|
||||
|
||||
@@ -174,7 +174,7 @@
|
||||
if(!starting_skills)
|
||||
return
|
||||
for(var/skill in starting_skills)
|
||||
M.skill_holder.boost_skill_value_to(skill, starting_skills[skill])
|
||||
M.skill_holder.boost_skill_value_to(skill, starting_skills[skill], TRUE) //silent
|
||||
// do wipe affinities though
|
||||
M.skill_holder.skill_affinities = list()
|
||||
for(var/skill in skill_affinities)
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
var/do_special_check = TRUE
|
||||
threat = 5
|
||||
|
||||
starting_skills = list(/datum/skill/level/job/wiring = GET_STANDARD_LVL(JOB_SKILL_BASIC))
|
||||
|
||||
/datum/job/ai/equip(mob/living/carbon/human/H, visualsOnly, announce, latejoin, datum/outfit/outfit_override, client/preference_source = null)
|
||||
if(visualsOnly)
|
||||
CRASH("dynamic preview is unsupported")
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_ATMOSPHERICS, ACCESS_MINERAL_STOREROOM)
|
||||
minimal_access = list(ACCESS_ATMOSPHERICS, ACCESS_MAINT_TUNNELS, ACCESS_EXTERNAL_AIRLOCKS, ACCESS_ENGINE,
|
||||
ACCESS_ENGINE_EQUIP, ACCESS_EMERGENCY_STORAGE, ACCESS_CONSTRUCTION, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
starting_skills = list(/datum/skill/level/job/wiring = GET_STANDARD_LVL(JOB_SKILL_BASIC))
|
||||
skill_affinities = list(/datum/skill/level/job/wiring = STARTING_SKILL_AFFINITY_WIRING_ENGI_ROBO)
|
||||
|
||||
display_order = JOB_DISPLAY_ORDER_ATMOSPHERIC_TECHNICIAN
|
||||
threat = 0.5
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
ACCESS_HEADS, ACCESS_CONSTRUCTION, ACCESS_SEC_DOORS, ACCESS_MINISAT,
|
||||
ACCESS_CE, ACCESS_RC_ANNOUNCE, ACCESS_KEYCARD_AUTH, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
starting_skills = list(/datum/skill/level/job/wiring = GET_STANDARD_LVL(JOB_SKILL_TRAINED))
|
||||
skill_affinities = list(/datum/skill/level/job/wiring = STARTING_SKILL_AFFINITY_WIRING_ENGI_ROBO)
|
||||
|
||||
display_order = JOB_DISPLAY_ORDER_CHIEF_ENGINEER
|
||||
blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/paraplegic, /datum/quirk/insanity)
|
||||
threat = 2
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
exp_requirements = 120
|
||||
exp_type = EXP_TYPE_CREW
|
||||
|
||||
starting_skills = list(/datum/skill/level/job/wiring = GET_STANDARD_LVL(JOB_SKILL_BASIC))
|
||||
|
||||
display_order = JOB_DISPLAY_ORDER_CYBORG
|
||||
|
||||
/datum/job/cyborg/equip(mob/living/carbon/human/H, visualsOnly = FALSE, announce = TRUE, latejoin = FALSE, datum/outfit/outfit_override = null, client/preference_source = null)
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
access = list(ACCESS_ROBOTICS, ACCESS_TOX, ACCESS_TOX_STORAGE, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM, ACCESS_XENOBIOLOGY, ACCESS_GENETICS)
|
||||
minimal_access = list(ACCESS_ROBOTICS, ACCESS_TECH_STORAGE, ACCESS_MORGUE, ACCESS_RESEARCH, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
starting_skills = list(/datum/skill/level/job/wiring = GET_STANDARD_LVL(JOB_SKILL_TRAINED))
|
||||
skill_affinities = list(/datum/skill/level/job/wiring = STARTING_SKILL_AFFINITY_WIRING_ENGI_ROBO)
|
||||
|
||||
|
||||
display_order = JOB_DISPLAY_ORDER_ROBOTICIST
|
||||
threat = 1
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
minimal_access = list(ACCESS_ENGINE, ACCESS_ENGINE_EQUIP, ACCESS_TECH_STORAGE, ACCESS_MAINT_TUNNELS,
|
||||
ACCESS_EXTERNAL_AIRLOCKS, ACCESS_CONSTRUCTION, ACCESS_TCOMSAT, ACCESS_MINERAL_STOREROOM)
|
||||
|
||||
starting_skills = list(/datum/skill/level/job/wiring = GET_STANDARD_LVL(JOB_SKILL_TRAINED))
|
||||
skill_affinities = list(/datum/skill/level/job/wiring = STARTING_SKILL_AFFINITY_WIRING_ENGI_ROBO)
|
||||
|
||||
display_order = JOB_DISPLAY_ORDER_STATION_ENGINEER
|
||||
|
||||
threat = 1
|
||||
|
||||
@@ -363,12 +363,11 @@ GLOBAL_LIST_INIT(sand_recipes, list(\
|
||||
|
||||
/obj/item/coin/attackby(obj/item/W, mob/user, params)
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/CC = W
|
||||
if(string_attached)
|
||||
to_chat(user, "<span class='warning'>There already is a string attached to this coin!</span>")
|
||||
return
|
||||
|
||||
if (CC.use(1))
|
||||
if (W.use_tool(src, user, 0, 1, max_level = JOB_SKILL_BASIC))
|
||||
add_overlay("coin_string_overlay")
|
||||
string_attached = 1
|
||||
to_chat(user, "<span class='notice'>You attach a string to the coin.</span>")
|
||||
|
||||
@@ -199,7 +199,7 @@
|
||||
to_chat(src, "<span class='notice'>You set [I] down gently on the ground.</span>")
|
||||
return
|
||||
|
||||
adjustStaminaLossBuffered(I.getweight()*2)//CIT CHANGE - throwing items shall be more tiring than swinging em. Doubly so.
|
||||
adjustStaminaLossBuffered(I.getweight(src, STAM_COST_THROW_MULT, SKILL_THROW_STAM_COST))
|
||||
|
||||
if(thrown_thing)
|
||||
visible_message("<span class='danger'>[src] has thrown [thrown_thing].</span>")
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
if(istype(src.glasses, /obj/item/clothing/glasses)) //glasses
|
||||
var/obj/item/clothing/glasses/GFP = src.glasses
|
||||
number += GFP.flash_protect
|
||||
|
||||
|
||||
if(istype(src.wear_mask, /obj/item/clothing/mask)) //mask
|
||||
var/obj/item/clothing/mask/MFP = src.wear_mask
|
||||
number += MFP.flash_protect
|
||||
@@ -77,15 +77,13 @@
|
||||
SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
|
||||
|
||||
/mob/living/carbon/attacked_by(obj/item/I, mob/living/user)
|
||||
//CIT CHANGES START HERE - combatmode and resting checks
|
||||
var/totitemdamage = I.force
|
||||
var/totitemdamage = pre_attacked_by(I, user)
|
||||
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
|
||||
totitemdamage *= 0.5
|
||||
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
|
||||
totitemdamage *= 0.5
|
||||
if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
|
||||
totitemdamage *= 1.5
|
||||
//CIT CHANGES END HERE
|
||||
var/impacting_zone = (user == src)? check_zone(user.zone_selected) : ran_zone(user.zone_selected)
|
||||
if((user != src) && (run_block(I, totitemdamage, "the [I]", ATTACK_TYPE_MELEE, I.armour_penetration, user, impacting_zone) & BLOCK_SUCCESS))
|
||||
return FALSE
|
||||
@@ -94,7 +92,7 @@
|
||||
affecting = bodyparts[1]
|
||||
SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting)
|
||||
send_item_attack_message(I, user, affecting.name)
|
||||
I.do_stagger_action(src, user)
|
||||
I.do_stagger_action(src, user, totitemdamage)
|
||||
if(I.force)
|
||||
apply_damage(totitemdamage, I.damtype, affecting) //CIT CHANGE - replaces I.force with totitemdamage
|
||||
if(I.damtype == BRUTE && affecting.status == BODYPART_ORGANIC)
|
||||
|
||||
@@ -43,5 +43,6 @@ GLOBAL_LIST_EMPTY(dummy_mob_list)
|
||||
return
|
||||
var/mob/living/carbon/human/dummy/D = GLOB.human_dummy_list[slotnumber]
|
||||
if(istype(D))
|
||||
D.set_species(/datum/species/human,icon_update = TRUE, pref_load = TRUE) //for some fucking reason, if you don't change the species every time, some species will dafault certain things when it's their own species on the mannequin two times in a row, like lizards losing spines and tails setting to smooth. If you can find a fix for this that isn't this, good on you
|
||||
D.wipe_state()
|
||||
D.in_use = FALSE
|
||||
|
||||
@@ -1668,9 +1668,10 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
disarm(M, H, attacker_style)
|
||||
|
||||
/datum/species/proc/spec_attacked_by(obj/item/I, mob/living/user, obj/item/bodypart/affecting, intent, mob/living/carbon/human/H)
|
||||
var/totitemdamage = H.pre_attacked_by(I, user)
|
||||
// Allows you to put in item-specific reactions based on species
|
||||
if(user != H)
|
||||
if(H.run_block(I, I.force, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone) & BLOCK_SUCCESS)
|
||||
if(H.run_block(I, totitemdamage, "the [I.name]", ATTACK_TYPE_MELEE, I.armour_penetration, user, affecting.body_zone) & BLOCK_SUCCESS)
|
||||
return 0
|
||||
if(H.check_martial_melee_block())
|
||||
H.visible_message("<span class='warning'>[H] blocks [I]!</span>")
|
||||
@@ -1686,24 +1687,14 @@ GLOBAL_LIST_EMPTY(roundstart_race_names)
|
||||
var/armor_block = H.run_armor_check(affecting, "melee", "<span class='notice'>Your armor has protected your [hit_area].</span>", "<span class='notice'>Your armor has softened a hit to your [hit_area].</span>",I.armour_penetration)
|
||||
armor_block = min(90,armor_block) //cap damage reduction at 90%
|
||||
var/Iforce = I.force //to avoid runtimes on the forcesay checks at the bottom. Some items might delete themselves if you drop them. (stunning yourself, ninja swords)
|
||||
//CIT CHANGES START HERE - combatmode and resting checks
|
||||
var/totitemdamage = I.force
|
||||
if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
|
||||
totitemdamage *= 0.5
|
||||
if(!CHECK_MOBILITY(user, MOBILITY_STAND))
|
||||
totitemdamage *= 0.5
|
||||
if(istype(H))
|
||||
if(!(H.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE))
|
||||
totitemdamage *= 1.5
|
||||
//CIT CHANGES END HERE
|
||||
var/weakness = H.check_weakness(I, user)
|
||||
apply_damage(totitemdamage * weakness, I.damtype, def_zone, armor_block, H) //CIT CHANGE - replaces I.force with totitemdamage
|
||||
|
||||
H.send_item_attack_message(I, user, hit_area)
|
||||
|
||||
I.do_stagger_action(H, user)
|
||||
I.do_stagger_action(H, user, totitemdamage)
|
||||
|
||||
if(!I.force)
|
||||
if(!totitemdamage)
|
||||
return 0 //item force is zero
|
||||
|
||||
//dismemberment
|
||||
|
||||
@@ -427,24 +427,23 @@
|
||||
|
||||
else if(istype(W, /obj/item/stack/cable_coil) && wiresexposed)
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
var/obj/item/stack/cable_coil/coil = W
|
||||
if (getFireLoss() > 0 || getToxLoss() > 0)
|
||||
if(src == user && coil.use(1))
|
||||
if(src == user)
|
||||
to_chat(user, "<span class='notice'>You start fixing yourself...</span>")
|
||||
if(!do_after(user, 50, target = src))
|
||||
if(!W.use_tool(src, user, 50, 1, max_level = JOB_SKILL_TRAINED))
|
||||
to_chat(user, "<span class='warning'>You need more cable to repair [src]!</span>")
|
||||
return
|
||||
adjustFireLoss(-10)
|
||||
adjustToxLoss(-10)
|
||||
if (coil.use(1))
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You start fixing [src]...</span>")
|
||||
if(!do_after(user, 30, target = src))
|
||||
if(!W.use_tool(src, user, 30, 1))
|
||||
to_chat(user, "<span class='warning'>You need more cable to repair [src]!</span>")
|
||||
return
|
||||
adjustFireLoss(-30)
|
||||
adjustToxLoss(-30)
|
||||
updatehealth()
|
||||
user.visible_message("[user] has fixed some of the burnt wires on [src].", "<span class='notice'>You fix some of the burnt wires on [src].</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>You need more cable to repair [src]!</span>")
|
||||
else
|
||||
to_chat(user, "The wires seem fine, there's no need to fix them.")
|
||||
|
||||
|
||||
@@ -147,9 +147,8 @@
|
||||
to_chat(user, "<span class='warning'>You need one length of cable to wire the ED-209!</span>")
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You start to wire [src]...</span>")
|
||||
if(do_after(user, 40, target = src))
|
||||
if(coil.get_amount() >= 1 && build_step == 6)
|
||||
coil.use(1)
|
||||
if(coil.use_tool(src, user, 40, 1))
|
||||
if(build_step == 6)
|
||||
to_chat(user, "<span class='notice'>You wire [src].</span>")
|
||||
name = "wired ED-209 assembly"
|
||||
build_step++
|
||||
|
||||
@@ -87,7 +87,6 @@
|
||||
pass_flags = PASSMOB
|
||||
mob_size = MOB_SIZE_SMALL
|
||||
collar_type = "kitten"
|
||||
held_icon = "cat"
|
||||
|
||||
//RUNTIME IS ALIVE! SQUEEEEEEEE~
|
||||
/mob/living/simple_animal/pet/cat/Runtime
|
||||
@@ -99,6 +98,7 @@
|
||||
gender = FEMALE
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
unique_pet = TRUE
|
||||
held_icon = "cat"
|
||||
var/list/family = list()//var restored from savefile, has count of each child type
|
||||
var/list/children = list()//Actual mob instances of children
|
||||
var/cats_deployed = 0
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
mob_biotypes = MOB_ORGANIC|MOB_BEAST
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
speak_emote = list("telepathically cries")
|
||||
speed = 2
|
||||
speed = 1
|
||||
move_to_delay = 2
|
||||
projectiletype = /obj/item/projectile/temp/basilisk/ice
|
||||
projectilesound = 'sound/weapons/pierce.ogg'
|
||||
@@ -25,8 +25,8 @@
|
||||
melee_damage_upper = 15
|
||||
attacktext = "slices"
|
||||
attack_sound = 'sound/weapons/bladeslice.ogg'
|
||||
vision_range = 9
|
||||
aggro_vision_range = 9
|
||||
vision_range = 7
|
||||
aggro_vision_range = 7
|
||||
move_force = MOVE_FORCE_VERY_STRONG
|
||||
move_resist = MOVE_FORCE_VERY_STRONG
|
||||
pull_force = MOVE_FORCE_VERY_STRONG
|
||||
|
||||
@@ -593,7 +593,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
|
||||
stat("Failsafe Controller:", "ERROR")
|
||||
if(Master)
|
||||
stat(null)
|
||||
for(var/datum/controller/subsystem/SS in Master.subsystems)
|
||||
for(var/datum/controller/subsystem/SS in Master.statworthy_subsystems)
|
||||
SS.stat_entry()
|
||||
GLOB.cameranet.stat_entry()
|
||||
if(statpanel("Tickets"))
|
||||
|
||||
@@ -41,11 +41,10 @@
|
||||
|
||||
// Cable coil. Works as repair method, but will probably require multiple applications and more cable.
|
||||
if(istype(I, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/S = I
|
||||
if(obj_integrity == max_integrity)
|
||||
to_chat(user, "<span class='warning'>\The [src] doesn't seem to require repairs.</span>")
|
||||
return 1
|
||||
if(S.use(1))
|
||||
if(I.use_tool(src, user, 0, 1))
|
||||
to_chat(user, "<span class='notice'>You patch up \the [src] with a bit of \the [I].</span>")
|
||||
obj_integrity = min(obj_integrity + 10, max_integrity)
|
||||
return 1
|
||||
|
||||
@@ -597,19 +597,15 @@
|
||||
user.visible_message("[user.name] adds cables to the APC frame.", \
|
||||
"<span class='notice'>You start adding cables to the APC frame...</span>")
|
||||
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
if(do_after(user, 20, target = src))
|
||||
if (C.get_amount() < 10 || !C)
|
||||
if(C.use_tool(src, user, 20, 10) && !terminal && opened && has_electronics)
|
||||
var/turf/T = get_turf(src)
|
||||
var/obj/structure/cable/N = T.get_cable_node()
|
||||
if (prob(50) && electrocute_mob(usr, N, N, 1, TRUE))
|
||||
do_sparks(5, TRUE, src)
|
||||
return
|
||||
if (C.get_amount() >= 10 && !terminal && opened && has_electronics)
|
||||
var/turf/T = get_turf(src)
|
||||
var/obj/structure/cable/N = T.get_cable_node()
|
||||
if (prob(50) && electrocute_mob(usr, N, N, 1, TRUE))
|
||||
do_sparks(5, TRUE, src)
|
||||
return
|
||||
C.use(10)
|
||||
to_chat(user, "<span class='notice'>You add cables to the APC frame.</span>")
|
||||
make_terminal()
|
||||
terminal.connect_to_network()
|
||||
to_chat(user, "<span class='notice'>You add cables to the APC frame.</span>")
|
||||
make_terminal()
|
||||
terminal.connect_to_network()
|
||||
else if (istype(W, /obj/item/electronics/apc) && opened)
|
||||
if (has_electronics)
|
||||
to_chat(user, "<span class='warning'>There is already a board inside the [src]!</span>")
|
||||
|
||||
@@ -510,6 +510,7 @@ By design, d1 is the smallest direction and d2 is the highest
|
||||
full_w_class = WEIGHT_CLASS_SMALL
|
||||
grind_results = list(/datum/reagent/copper = 2) //2 copper per cable in the coil
|
||||
usesound = 'sound/items/deconstruct.ogg'
|
||||
used_skills = list(/datum/skill/level/job/wiring)
|
||||
|
||||
/obj/item/stack/cable_coil/cyborg
|
||||
is_cyborg = 1
|
||||
@@ -591,8 +592,6 @@ By design, d1 is the smallest direction and d2 is the highest
|
||||
amount += extra
|
||||
update_icon()
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// Cable laying procedures
|
||||
//////////////////////////////////////////////
|
||||
|
||||
@@ -15,8 +15,7 @@
|
||||
state = FLOODLIGHT_NEEDS_WIRES
|
||||
desc = "A bare metal frame looking vaguely like a floodlight. Requires wiring."
|
||||
else if(istype(O, /obj/item/stack/cable_coil) && (state == FLOODLIGHT_NEEDS_WIRES))
|
||||
var/obj/item/stack/S = O
|
||||
if(S.use(5))
|
||||
if(O.use_tool(src, user, 0, 5))
|
||||
to_chat(user, "<span class='notice'>You wire [src].</span>")
|
||||
name = "wired [name]"
|
||||
desc = "A bare metal frame looking vaguely like a floodlight. Requires securing with a screwdriver."
|
||||
|
||||
@@ -118,8 +118,7 @@
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/coil = W
|
||||
if(coil.use(1))
|
||||
if(W.use_tool(src, user, 0, 1, max_level = JOB_SKILL_TRAINED))
|
||||
icon_state = "[fixture_type]-construct-stage2"
|
||||
stage = 2
|
||||
user.visible_message("[user.name] adds wires to [src].", \
|
||||
@@ -193,7 +192,7 @@
|
||||
var/on = FALSE // 1 if on, 0 if off
|
||||
var/on_gs = FALSE
|
||||
var/static_power_used = 0
|
||||
var/brightness = 11 // luminosity when on, also used in power calculation
|
||||
var/brightness = 9 // luminosity when on, also used in power calculation
|
||||
var/bulb_power = 0.75 // basically the alpha of the emitted light source
|
||||
var/bulb_colour = "#FFF6ED" // befault colour of the light.
|
||||
var/status = LIGHT_OK // LIGHT_OK, _EMPTY, _BURNED or _BROKEN
|
||||
@@ -232,7 +231,8 @@
|
||||
icon_state = "bulb"
|
||||
base_state = "bulb"
|
||||
fitting = "bulb"
|
||||
brightness = 6
|
||||
brightness = 5
|
||||
nightshift_brightness = 4
|
||||
bulb_colour = "#FFDDBB"
|
||||
desc = "A small lighting fixture."
|
||||
light_type = /obj/item/light/bulb
|
||||
@@ -274,11 +274,11 @@
|
||||
spawn(2)
|
||||
switch(fitting)
|
||||
if("tube")
|
||||
brightness = 11
|
||||
brightness = 9
|
||||
if(prob(2))
|
||||
break_light_tube(1)
|
||||
if("bulb")
|
||||
brightness = 6
|
||||
brightness = 5
|
||||
if(prob(5))
|
||||
break_light_tube(1)
|
||||
spawn(1)
|
||||
@@ -361,11 +361,11 @@
|
||||
set_light(0)
|
||||
update_icon()
|
||||
|
||||
active_power_usage = (brightness * 7.2)
|
||||
active_power_usage = (brightness * 10)
|
||||
if(on != on_gs)
|
||||
on_gs = on
|
||||
if(on)
|
||||
static_power_used = brightness * 14.4 * (hijacked ? 2 : 1) //20W per unit luminosity
|
||||
static_power_used = brightness * 20 * (hijacked ? 2 : 1) //20W per unit luminosity
|
||||
addStaticPower(static_power_used, STATIC_LIGHT)
|
||||
else
|
||||
removeStaticPower(static_power_used, STATIC_LIGHT)
|
||||
@@ -748,7 +748,7 @@
|
||||
icon_state = "ltube"
|
||||
base_state = "ltube"
|
||||
item_state = "c_tube"
|
||||
brightness = 11
|
||||
brightness = 9
|
||||
|
||||
/obj/item/light/tube/broken
|
||||
status = LIGHT_BROKEN
|
||||
@@ -761,7 +761,7 @@
|
||||
item_state = "contvapour"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
||||
brightness = 6
|
||||
brightness = 5
|
||||
|
||||
/obj/item/light/bulb/broken
|
||||
status = LIGHT_BROKEN
|
||||
@@ -830,7 +830,8 @@
|
||||
icon = 'icons/obj/lighting.dmi'
|
||||
base_state = "floor" // base description and icon_state
|
||||
icon_state = "floor"
|
||||
brightness = 6
|
||||
brightness = 5
|
||||
nightshift_brightness = 4
|
||||
layer = 2.5
|
||||
light_type = /obj/item/light/bulb
|
||||
fitting = "bulb"
|
||||
|
||||
@@ -79,8 +79,7 @@
|
||||
construction_state = PA_CONSTRUCTION_UNSECURED
|
||||
did_something = TRUE
|
||||
else if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/CC = W
|
||||
if(CC.use(1))
|
||||
if(W.use_tool(src, user, 0, 1))
|
||||
user.visible_message("[user.name] adds wires to the [name].", \
|
||||
"You add some wires.")
|
||||
construction_state = PA_CONSTRUCTION_PANEL_OPEN
|
||||
|
||||
@@ -288,8 +288,7 @@
|
||||
construction_state = PA_CONSTRUCTION_UNSECURED
|
||||
did_something = TRUE
|
||||
else if(istype(W, /obj/item/stack/cable_coil))
|
||||
var/obj/item/stack/cable_coil/CC = W
|
||||
if(CC.use(1))
|
||||
if(W.use_tool(src, user, 0, 1))
|
||||
user.visible_message("[user.name] adds wires to the [name].", \
|
||||
"You add some wires.")
|
||||
construction_state = PA_CONSTRUCTION_PANEL_OPEN
|
||||
|
||||
@@ -125,15 +125,12 @@
|
||||
to_chat(user, "<span class='notice'>You start building the power terminal...</span>")
|
||||
playsound(src.loc, 'sound/items/deconstruct.ogg', 50, 1)
|
||||
|
||||
if(do_after(user, 20, target = src) && C.get_amount() >= 10)
|
||||
if(C.get_amount() < 10 || !C)
|
||||
return
|
||||
if(C.use_tool(src, user, 20, 10))
|
||||
var/obj/structure/cable/N = T.get_cable_node() //get the connecting node cable, if there's one
|
||||
if (prob(50) && electrocute_mob(usr, N, N, 1, TRUE)) //animate the electrocution if uncautious and unlucky
|
||||
do_sparks(5, TRUE, src)
|
||||
return
|
||||
|
||||
C.use(10)
|
||||
user.visible_message(\
|
||||
"[user.name] has built a power terminal.",\
|
||||
"<span class='notice'>You build the power terminal.</span>")
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
|
||||
/obj/item/ammo_box/update_icon()
|
||||
. = ..()
|
||||
desc = "[initial(desc)] There are [stored_ammo.len] shell\s left!"
|
||||
desc = "[initial(desc)] There [stored_ammo.len == 1 ? "is" : "are"] [stored_ammo.len] shell\s left!"
|
||||
for (var/material in bullet_cost)
|
||||
var/material_amount = bullet_cost[material]
|
||||
material_amount = (material_amount*stored_ammo.len) + base_cost[material]
|
||||
|
||||
@@ -121,3 +121,51 @@
|
||||
icon_state = "foambox_riot"
|
||||
ammo_type = /obj/item/ammo_casing/caseless/foam_dart/riot
|
||||
custom_materials = list(/datum/material/iron = 50000)
|
||||
|
||||
//Shotgun clips
|
||||
/obj/item/ammo_box/shotgun
|
||||
name = "stripper clip (shotgun shells)"
|
||||
desc = "A stripper clip, designed to help with loading a shotgun slightly faster."
|
||||
icon = 'icons/obj/ammo.dmi'
|
||||
icon_state = "shotgunclip"
|
||||
caliber = "shotgun" // slapped in to allow shell mix n match
|
||||
ammo_type = /obj/item/ammo_casing/shotgun
|
||||
max_ammo = 4
|
||||
var/pixeloffsetx = 4
|
||||
start_empty = TRUE
|
||||
|
||||
/obj/item/ammo_box/shotgun/update_overlays()
|
||||
. = ..()
|
||||
if(stored_ammo.len)
|
||||
var/offset = -4
|
||||
for(var/A in stored_ammo)
|
||||
var/obj/item/ammo_casing/shotgun/C = A
|
||||
offset += pixeloffsetx
|
||||
var/mutable_appearance/shell_overlay = mutable_appearance(icon, "[initial(C.icon_state)]-clip")
|
||||
shell_overlay.pixel_x += offset
|
||||
shell_overlay.appearance_flags = RESET_COLOR
|
||||
. += shell_overlay
|
||||
|
||||
/obj/item/ammo_box/shotgun/loaded
|
||||
start_empty = FALSE
|
||||
|
||||
/obj/item/ammo_box/shotgun/loaded/rubbershot
|
||||
ammo_type = /obj/item/ammo_casing/shotgun/rubbershot
|
||||
|
||||
/obj/item/ammo_box/shotgun/loaded/buckshot
|
||||
ammo_type = /obj/item/ammo_casing/shotgun/buckshot
|
||||
|
||||
/obj/item/ammo_box/shotgun/loaded/beanbag
|
||||
ammo_type = /obj/item/ammo_casing/shotgun/beanbag
|
||||
|
||||
/obj/item/ammo_box/shotgun/loaded/stunslug
|
||||
ammo_type = /obj/item/ammo_casing/shotgun/stunslug
|
||||
|
||||
/obj/item/ammo_box/shotgun/loaded/techshell
|
||||
ammo_type = /obj/item/ammo_casing/shotgun/techshell
|
||||
|
||||
/obj/item/ammo_box/shotgun/loaded/incendiary
|
||||
ammo_type = /obj/item/ammo_casing/shotgun/incendiary
|
||||
|
||||
/obj/item/ammo_box/shotgun/loaded/dart
|
||||
ammo_type = /obj/item/ammo_casing/shotgun/dart
|
||||
|
||||
@@ -331,8 +331,7 @@
|
||||
/obj/item/gun/ballistic/revolver/doublebarrel/improvised/attackby(obj/item/A, mob/user, params)
|
||||
..()
|
||||
if(istype(A, /obj/item/stack/cable_coil) && !sawn_off)
|
||||
var/obj/item/stack/cable_coil/C = A
|
||||
if(C.use(10))
|
||||
if(A.use_tool(src, user, 0, 10, max_level = JOB_SKILL_BASIC))
|
||||
slot_flags = ITEM_SLOT_BACK
|
||||
to_chat(user, "<span class='notice'>You tie the lengths of cable to the shotgun, making a sling.</span>")
|
||||
slung = TRUE
|
||||
|
||||
@@ -211,7 +211,6 @@
|
||||
/obj/structure/reagent_dispensers/keg
|
||||
name = "keg"
|
||||
desc = "A keg."
|
||||
icon = 'modular_citadel/icons/obj/objects.dmi'
|
||||
icon_state = "keg"
|
||||
|
||||
/obj/structure/reagent_dispensers/keg/mead
|
||||
|
||||
@@ -112,8 +112,8 @@
|
||||
/datum/design/rcd_ammo_large
|
||||
name = "Large Compressed Matter Cartridge"
|
||||
id = "rcd_ammo_large"
|
||||
build_type = AUTOLATHE | PROTOLATHE
|
||||
build_type = AUTOLATHE | PROTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 48000, /datum/material/glass = 32000)
|
||||
build_path = /obj/item/rcd_ammo/large
|
||||
category = list("Tool Designs")
|
||||
category = list("hacked", "Construction", "Tool Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@
|
||||
/datum/design/kitchen_knife
|
||||
name = "Kitchen Knife"
|
||||
id = "kitchen_knife"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 12000)
|
||||
build_path = /obj/item/kitchen/knife
|
||||
category = list("initial","Dinnerware")
|
||||
@@ -140,7 +140,7 @@
|
||||
/datum/design/healthanalyzer
|
||||
name = "Health Analyzer"
|
||||
id = "healthanalyzer"
|
||||
build_type = AUTOLATHE | PROTOLATHE
|
||||
build_type = AUTOLATHE | PROTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 500, /datum/material/glass = 50)
|
||||
build_path = /obj/item/healthanalyzer
|
||||
category = list("initial", "Medical")
|
||||
|
||||
+19
-19
@@ -36,7 +36,7 @@
|
||||
/datum/design/large_welding_tool
|
||||
name = "Industrial Welding Tool"
|
||||
id = "large_welding_tool"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 70, /datum/material/glass = 60)
|
||||
build_path = /obj/item/weldingtool/largetank
|
||||
category = list("hacked", "Tools")
|
||||
@@ -44,7 +44,7 @@
|
||||
/datum/design/flamethrower
|
||||
name = "Flamethrower"
|
||||
id = "flamethrower"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 500)
|
||||
build_path = /obj/item/flamethrower/full
|
||||
category = list("hacked", "Security")
|
||||
@@ -52,7 +52,7 @@
|
||||
/datum/design/rcd
|
||||
name = "Rapid Construction Device (RCD)"
|
||||
id = "rcd"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 30000)
|
||||
build_path = /obj/item/construction/rcd
|
||||
category = list("hacked", "Construction")
|
||||
@@ -60,7 +60,7 @@
|
||||
/datum/design/rpd
|
||||
name = "Rapid Pipe Dispenser (RPD)"
|
||||
id = "rpd"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 75000, /datum/material/glass = 37500)
|
||||
build_path = /obj/item/pipe_dispenser
|
||||
category = list("hacked", "Construction")
|
||||
@@ -68,7 +68,7 @@
|
||||
/datum/design/handcuffs
|
||||
name = "Handcuffs"
|
||||
id = "handcuffs"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 500)
|
||||
build_path = /obj/item/restraints/handcuffs
|
||||
category = list("hacked", "Security")
|
||||
@@ -76,7 +76,7 @@
|
||||
/datum/design/receiver
|
||||
name = "Modular Receiver"
|
||||
id = "receiver"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 15000)
|
||||
build_path = /obj/item/weaponcrafting/receiver
|
||||
category = list("hacked", "Security")
|
||||
@@ -84,7 +84,7 @@
|
||||
/datum/design/shotgun_slug
|
||||
name = "Shotgun Slug"
|
||||
id = "shotgun_slug"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 4000)
|
||||
build_path = /obj/item/ammo_casing/shotgun
|
||||
category = list("hacked", "Security")
|
||||
@@ -92,7 +92,7 @@
|
||||
/datum/design/buckshot_shell
|
||||
name = "Buckshot Shell"
|
||||
id = "buckshot_shell"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 4000)
|
||||
build_path = /obj/item/ammo_casing/shotgun/buckshot
|
||||
category = list("hacked", "Security")
|
||||
@@ -100,7 +100,7 @@
|
||||
/datum/design/shotgun_dart
|
||||
name = "Shotgun Dart"
|
||||
id = "shotgun_dart"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 4000)
|
||||
build_path = /obj/item/ammo_casing/shotgun/dart
|
||||
category = list("hacked", "Security")
|
||||
@@ -108,7 +108,7 @@
|
||||
/datum/design/incendiary_slug
|
||||
name = "Incendiary Slug"
|
||||
id = "incendiary_slug"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 4000)
|
||||
build_path = /obj/item/ammo_casing/shotgun/incendiary
|
||||
category = list("hacked", "Security")
|
||||
@@ -116,7 +116,7 @@
|
||||
/datum/design/riot_dart
|
||||
name = "Foam Riot Dart"
|
||||
id = "riot_dart"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 1125) //Discount for making individually - no box = less metal!
|
||||
build_path = /obj/item/ammo_casing/caseless/foam_dart/riot
|
||||
category = list("hacked", "Security")
|
||||
@@ -124,7 +124,7 @@
|
||||
/datum/design/riot_darts
|
||||
name = "Foam Riot Dart Box"
|
||||
id = "riot_darts"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 50000) //Comes with 40 darts
|
||||
build_path = /obj/item/ammo_box/foambox/riot
|
||||
category = list("hacked", "Security")
|
||||
@@ -132,7 +132,7 @@
|
||||
/datum/design/a357
|
||||
name = "Revolver Bullet (.357)"
|
||||
id = "a357"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 4000)
|
||||
build_path = /obj/item/ammo_casing/a357
|
||||
category = list("hacked", "Security")
|
||||
@@ -140,7 +140,7 @@
|
||||
/datum/design/a762
|
||||
name = "Rifle Bullet (7.62mm)"
|
||||
id = "a762"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 5000) //need seclathe for clips
|
||||
build_path = /obj/item/ammo_casing/a762
|
||||
category = list("hacked", "Security")
|
||||
@@ -148,7 +148,7 @@
|
||||
/datum/design/c10mm
|
||||
name = "Ammo Box (10mm)"
|
||||
id = "c10mm"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 30000)
|
||||
build_path = /obj/item/ammo_box/c10mm
|
||||
category = list("hacked", "Security")
|
||||
@@ -156,7 +156,7 @@
|
||||
/datum/design/c45
|
||||
name = "Ammo Box (.45)"
|
||||
id = "c45"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 30000)
|
||||
build_path = /obj/item/ammo_box/c45
|
||||
category = list("hacked", "Security")
|
||||
@@ -164,7 +164,7 @@
|
||||
/datum/design/c9mm
|
||||
name = "Ammo Box (9mm)"
|
||||
id = "c9mm"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 30000)
|
||||
build_path = /obj/item/ammo_box/c9mm
|
||||
category = list("hacked", "Security")
|
||||
@@ -172,7 +172,7 @@
|
||||
/datum/design/electropack
|
||||
name = "Electropack"
|
||||
id = "electropack"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 10000, /datum/material/glass = 2500)
|
||||
build_path = /obj/item/electropack
|
||||
category = list("hacked", "Security")
|
||||
@@ -180,7 +180,7 @@
|
||||
/datum/design/cleaver
|
||||
name = "Butcher's Cleaver"
|
||||
id = "cleaver"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 18000)
|
||||
build_path = /obj/item/kitchen/knife/butcher
|
||||
category = list("hacked", "Dinnerware")
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
/datum/design/multitool
|
||||
name = "Multitool"
|
||||
id = "multitool"
|
||||
build_type = AUTOLATHE | PROTOLATHE
|
||||
build_type = AUTOLATHE | PROTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 50, /datum/material/glass = 20)
|
||||
build_path = /obj/item/multitool
|
||||
category = list("initial","Tools","Tool Designs")
|
||||
@@ -75,7 +75,7 @@
|
||||
/datum/design/weldingtool
|
||||
name = "Welding Tool"
|
||||
id = "welding_tool"
|
||||
build_type = AUTOLATHE
|
||||
build_type = AUTOLATHE | NO_PUBLIC_LATHE
|
||||
materials = list(/datum/material/iron = 70, /datum/material/glass = 20)
|
||||
build_path = /obj/item/weldingtool
|
||||
category = list("initial","Tools","Tool Designs")
|
||||
@@ -97,6 +97,7 @@
|
||||
build_path = /obj/item/screwdriver
|
||||
category = list("initial","Tools","Tool Designs")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SCIENCE
|
||||
|
||||
/datum/design/wirecutters
|
||||
name = "Wirecutters"
|
||||
id = "wirecutters"
|
||||
|
||||
@@ -562,6 +562,7 @@
|
||||
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
|
||||
build_path = /obj/item/gun/ballistic/automatic/x9/toy
|
||||
category = list("initial", "Rifles")
|
||||
build_type = TOYLATHE | NO_PUBLIC_LATHE
|
||||
|
||||
/datum/design/foam_dart
|
||||
name = "Box of Foam Darts"
|
||||
@@ -586,6 +587,7 @@
|
||||
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
|
||||
build_path = /obj/item/gun/ballistic/automatic/toy/magrifle
|
||||
category = list("initial", "Rifles")
|
||||
build_type = TOYLATHE | NO_PUBLIC_LATHE
|
||||
|
||||
/datum/design/foam_hyperburst
|
||||
name = "MagTag Hyper Rifle"
|
||||
@@ -618,6 +620,7 @@
|
||||
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
|
||||
build_path = /obj/item/gun/ballistic/automatic/AM4C
|
||||
category = list("initial", "Rifles")
|
||||
build_type = TOYLATHE | NO_PUBLIC_LATHE
|
||||
|
||||
/datum/design/foam_f3
|
||||
name = "Replica F3 Justicar"
|
||||
@@ -650,6 +653,7 @@
|
||||
materials = list(/datum/material/plastic = 2000, /datum/material/iron = 250)
|
||||
build_path = /obj/item/gun/ballistic/automatic/toy/unrestricted
|
||||
category = list("initial", "Pistols")
|
||||
build_type = TOYLATHE | NO_PUBLIC_LATHE
|
||||
|
||||
/datum/design/foam_pistol
|
||||
name = "Foam Force Pistol"
|
||||
@@ -698,6 +702,7 @@
|
||||
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
|
||||
build_path = /obj/item/gun/ballistic/automatic/c20r/toy/unrestricted
|
||||
category = list("hacked", "Rifles")
|
||||
build_type = TOYLATHE | NO_PUBLIC_LATHE
|
||||
|
||||
/datum/design/foam_l6
|
||||
name = "Donksoft LMG"
|
||||
@@ -706,3 +711,4 @@
|
||||
materials = list(/datum/material/plastic = 4000, /datum/material/iron = 500)
|
||||
build_path = /obj/item/gun/ballistic/automatic/l6_saw/toy/unrestricted
|
||||
category = list("hacked", "Rifles")
|
||||
build_type = TOYLATHE | NO_PUBLIC_LATHE
|
||||
|
||||
@@ -135,6 +135,15 @@
|
||||
//Ammo Shells/
|
||||
//////////////
|
||||
|
||||
/datum/design/shell_clip
|
||||
name = "stripper clip (shotgun shells)"
|
||||
id = "sec_shellclip"
|
||||
build_type = PROTOLATHE
|
||||
materials = list(/datum/material/iron = 5000)
|
||||
build_path = /obj/item/ammo_box/shotgun
|
||||
category = list("Ammo")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
|
||||
|
||||
/datum/design/beanbag_slug/sec
|
||||
id = "sec_beanbag"
|
||||
build_type = PROTOLATHE
|
||||
@@ -166,7 +175,7 @@
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
|
||||
|
||||
/datum/design/incendiary_slug/sec
|
||||
id = "sec_Islug"
|
||||
id = "sec_islug"
|
||||
build_type = PROTOLATHE
|
||||
category = list("Ammo")
|
||||
departmental_flags = DEPARTMENTAL_FLAG_SECURITY
|
||||
|
||||
@@ -76,7 +76,8 @@
|
||||
var/problems = FALSE
|
||||
if(iscarbon(host_mob))
|
||||
var/mob/living/carbon/C = host_mob
|
||||
if(length(C.get_traumas()))
|
||||
var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN)
|
||||
if(length(B?.get_traumas_type(TRAUMA_RESILIENCE_BASIC)))
|
||||
problems = TRUE
|
||||
if(host_mob.getOrganLoss(ORGAN_SLOT_BRAIN) > 0)
|
||||
problems = TRUE
|
||||
@@ -198,7 +199,8 @@
|
||||
var/problems = FALSE
|
||||
if(iscarbon(host_mob))
|
||||
var/mob/living/carbon/C = host_mob
|
||||
if(length(C.get_traumas()))
|
||||
var/obj/item/organ/brain/B = C.getorganslot(ORGAN_SLOT_BRAIN)
|
||||
if(length(B?.get_traumas_type(TRAUMA_RESILIENCE_SURGERY)))
|
||||
problems = TRUE
|
||||
if(host_mob.getOrganLoss(ORGAN_SLOT_BRAIN) > 0)
|
||||
problems = TRUE
|
||||
@@ -208,7 +210,7 @@
|
||||
host_mob.adjustOrganLoss(ORGAN_SLOT_BRAIN, -2)
|
||||
if(iscarbon(host_mob) && prob(10))
|
||||
var/mob/living/carbon/C = host_mob
|
||||
C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_LOBOTOMY)
|
||||
C.cure_trauma_type(resilience = TRAUMA_RESILIENCE_SURGERY)
|
||||
|
||||
/datum/nanite_program/defib
|
||||
name = "Defibrillation"
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
// Default research tech, prevents bricking
|
||||
design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani", "desttagger", "handlabel", "packagewrap",
|
||||
"destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab",
|
||||
"space_heater", "beaker", "large_beaker", "bucket", "xlarge_beaker", "sec_beanbag", "sec_rshot", "sec_bshot", "sec_slug", "sec_Islug", "sec_dart", "sec_38", "sec_38lethal",
|
||||
"space_heater", "beaker", "large_beaker", "bucket", "xlarge_beaker", "sec_shellclip", "sec_beanbag", "sec_rshot", "sec_bshot", "sec_slug", "sec_islug", "sec_dart", "sec_38", "sec_38lethal",
|
||||
"rglass","plasteel","plastitanium","plasmaglass","plasmareinforcedglass","titaniumglass","plastitaniumglass")
|
||||
|
||||
/datum/techweb_node/mmi
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
target.cure_all_traumas(TRAUMA_RESILIENCE_LOBOTOMY)
|
||||
if(target.mind && target.mind.has_antag_datum(/datum/antagonist/brainwashed))
|
||||
target.mind.remove_antag_datum(/datum/antagonist/brainwashed)
|
||||
switch(rand(1,4))//Now let's see what hopefully-not-important part of the brain we cut off
|
||||
switch(rand(1,6))//Now let's see what hopefully-not-important part of the brain we cut off
|
||||
if(1)
|
||||
target.gain_trauma_type(BRAIN_TRAUMA_MILD, TRAUMA_RESILIENCE_MAGIC)
|
||||
if(2)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
flags_1 = CONDUCT_1
|
||||
icon_state = "borg_l_arm"
|
||||
status = BODYPART_ROBOTIC
|
||||
|
||||
|
||||
brute_reduction = 2
|
||||
burn_reduction = 1
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
flags_1 = CONDUCT_1
|
||||
icon_state = "borg_r_arm"
|
||||
status = BODYPART_ROBOTIC
|
||||
|
||||
|
||||
brute_reduction = 2
|
||||
burn_reduction = 1
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
flags_1 = CONDUCT_1
|
||||
icon_state = "borg_l_leg"
|
||||
status = BODYPART_ROBOTIC
|
||||
|
||||
|
||||
brute_reduction = 2
|
||||
burn_reduction = 1
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
flags_1 = CONDUCT_1
|
||||
icon_state = "borg_r_leg"
|
||||
status = BODYPART_ROBOTIC
|
||||
|
||||
|
||||
brute_reduction = 2
|
||||
burn_reduction = 1
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
flags_1 = CONDUCT_1
|
||||
icon_state = "borg_chest"
|
||||
status = BODYPART_ROBOTIC
|
||||
|
||||
|
||||
brute_reduction = 2
|
||||
burn_reduction = 1
|
||||
|
||||
@@ -131,8 +131,7 @@
|
||||
if(src.wired)
|
||||
to_chat(user, "<span class='warning'>You have already inserted wire!</span>")
|
||||
return
|
||||
var/obj/item/stack/cable_coil/coil = W
|
||||
if (coil.use(1))
|
||||
if (W.use_tool(src, user, 0, 1))
|
||||
src.wired = 1
|
||||
to_chat(user, "<span class='notice'>You insert the wire.</span>")
|
||||
else
|
||||
@@ -164,7 +163,7 @@
|
||||
flags_1 = CONDUCT_1
|
||||
icon_state = "borg_head"
|
||||
status = BODYPART_ROBOTIC
|
||||
|
||||
|
||||
brute_reduction = 5
|
||||
burn_reduction = 4
|
||||
|
||||
|
||||
@@ -58,10 +58,9 @@
|
||||
return FALSE
|
||||
if(tool)
|
||||
speed_mod = tool.toolspeed
|
||||
var/skill_mod = 1
|
||||
if(user?.mind?.skill_holder)
|
||||
skill_mod = SURGERY_SKILL_SPEEDUP_NUMERICAL_SCALE(user.mind.skill_holder.get_skill_value(/datum/skill/numerical/surgery))
|
||||
if(do_after(user, time * speed_mod * skill_mod, target = target))
|
||||
if(user.mind)
|
||||
speed_mod = user.mind.skill_holder.action_skills_mod(/datum/skill/numerical/surgery, speed_mod, THRESHOLD_COMPETENT, FALSE)
|
||||
if(do_after(user, time * speed_mod, target = target))
|
||||
var/prob_chance = 100
|
||||
if(implement_type) //this means it isn't a require hand or any item step.
|
||||
prob_chance = implements[implement_type]
|
||||
@@ -69,7 +68,7 @@
|
||||
|
||||
if((prob(prob_chance) || (iscyborg(user) && !silicons_obey_prob)) && chem_check(target) && !try_to_fail)
|
||||
if(success(user, target, target_zone, tool, surgery))
|
||||
user?.mind?.skill_holder?.auto_gain_experience(/datum/skill/numerical/surgery, SKILL_GAIN_SURGERY_PER_STEP)
|
||||
user.mind?.skill_holder.auto_gain_experience(/datum/skill/numerical/surgery, SKILL_GAIN_SURGERY_PER_STEP)
|
||||
advance = TRUE
|
||||
else
|
||||
if(failure(user, target, target_zone, tool, surgery))
|
||||
|
||||
@@ -201,10 +201,9 @@
|
||||
/datum/uplink_item/device_tools/stimpack
|
||||
name = "Stimpack"
|
||||
desc = "Stimpacks, the tool of many great heroes, make you nearly immune to stuns and knockdowns for about \
|
||||
5 minutes after fully injecting yourself. Can inject yourself, or others, 5 times and through hardsuits. \
|
||||
Each injection will gives around a minute of stimulants."
|
||||
item = /obj/item/reagent_containers/hypospray/medipen/stimulants
|
||||
cost = 5
|
||||
5 minutes after injection."
|
||||
item = /obj/item/reagent_containers/syringe/stimulants
|
||||
cost = 3
|
||||
surplus = 90
|
||||
|
||||
/datum/uplink_item/device_tools/medkit
|
||||
|
||||
Reference in New Issue
Block a user