Merge remote-tracking branch 'citadel/master' into projectiles_2

This commit is contained in:
kevinz000
2020-05-08 23:32:01 -07:00
152 changed files with 1550 additions and 1110 deletions
@@ -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))
+282
View File
@@ -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()
+374
View File
@@ -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"
+137
View File
@@ -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
+109
View File
@@ -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)
+67
View File
@@ -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)
+74
View File
@@ -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)
+10
View File
@@ -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
+159
View File
@@ -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)
+1 -1
View File
@@ -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)
+1 -2
View File
@@ -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)
+11 -5
View File
@@ -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)
. = ..()
+1 -1
View File
@@ -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)
+2
View File
@@ -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
+2
View File
@@ -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
+1 -2
View File
@@ -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>")
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+8 -12
View File
@@ -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>")
+1 -2
View File
@@ -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
//////////////////////////////////////////////
+1 -2
View File
@@ -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."
+12 -11
View File
@@ -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
+1 -4
View File
@@ -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
@@ -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")
@@ -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"
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+4 -5
View File
@@ -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