From 3bd0ba02754753b4b93fbcc403bd198cca4bb44a Mon Sep 17 00:00:00 2001 From: Ghommie Date: Tue, 23 Jul 2019 06:39:53 +0200 Subject: [PATCH 01/58] Cleaning up Arousal code & co. --- code/__DEFINES/DNA.dm | 5 + code/__DEFINES/citadel_defines.dm | 9 + code/__DEFINES/traits.dm | 11 +- code/__HELPERS/_cit_helpers.dm | 41 +- code/__HELPERS/global_lists.dm | 4 + code/__HELPERS/mobs.dm | 1 - code/datums/traits/neutral.dm | 35 ++ code/modules/admin/create_mob.dm | 3 + code/modules/client/preferences.dm | 4 - code/modules/client/preferences_savefile.dm | 7 +- modular_citadel/code/datums/traits/neutral.dm | 33 -- .../code/modules/arousal/arousal.dm | 559 ++++++------------ .../organs/{genitals.dm => _genitals.dm} | 213 +++---- .../code/modules/arousal/organs/breasts.dm | 60 +- .../code/modules/arousal/organs/eggsack.dm | 16 +- .../organs/genitals_sprite_accessories.dm | 21 +- .../code/modules/arousal/organs/ovipositor.dm | 7 +- .../code/modules/arousal/organs/penis.dm | 56 +- .../code/modules/arousal/organs/testicles.dm | 105 ++-- .../code/modules/arousal/organs/vagina.dm | 47 +- .../code/modules/arousal/organs/womb.dm | 50 +- .../modules/client/preferences_savefile.dm | 1 - .../modules/mob/living/carbon/human/life.dm | 4 +- .../carbon/human/species_types/jellypeople.dm | 50 +- .../icons/obj/genitals/testicles_onmob.dmi | Bin 759 -> 562 bytes tgstation.dme | 3 +- 26 files changed, 525 insertions(+), 820 deletions(-) delete mode 100644 modular_citadel/code/datums/traits/neutral.dm rename modular_citadel/code/modules/arousal/organs/{genitals.dm => _genitals.dm} (60%) diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 4ed099d9e2..95c2c70801 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -122,3 +122,8 @@ #define ORGAN_SLOT_BRAIN_ANTISTUN "brain_antistun" #define ORGAN_SLOT_TAIL "tail" #define ORGAN_SLOT_PENIS "penis" +#define ORGAN_SLOT_WOMB "womb" +#define ORGAN_SLOT_VAGINA "vagina" +#define ORGAN_SLOT_TESTICLES "testicles" +#define ORGAN_SLOT_BREASTS "breasts" + diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 2abe0db04e..8b75784ab2 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -18,6 +18,15 @@ #define CIT_FILTER_STAMINACRIT filter(type="drop_shadow", x=0, y=0, size=-3, border=0, color="#04080F") //organ defines +#define VAGINA_LAYER_INDEX 1 +#define TESTICLES_LAYER_INDEX 2 +#define GENITAL_LAYER_INDEX 3 +#define PENIS_LAYER_INDEX 4 + +#define GENITAL_LAYER_INDEX_LENGTH 4 //keep it updated with each new index added, thanks. + +#define MASTURBATE_LINKED_ORGAN 2 //special value used to pass our mission to the linked organ + #define COCK_SIZE_MIN 1 #define COCK_SIZE_MAX 20 diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 7bcb4881f0..1546717c7a 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -136,13 +136,14 @@ #define TRAIT_SKITTISH "skittish" #define TRAIT_POOR_AIM "poor_aim" #define TRAIT_PROSOPAGNOSIA "prosopagnosia" -#define TRAIT_DRUNK_HEALING "drunk_healing" -#define TRAIT_TAGGER "tagger" -#define TRAIT_PHOTOGRAPHER "photographer" -#define TRAIT_MUSICIAN "musician" -#define TRAIT_CROCRIN_IMMUNE "crocin_immune" +#define TRAIT_DRUNK_HEALING "drunk_healing" +#define TRAIT_TAGGER "tagger" +#define TRAIT_PHOTOGRAPHER "photographer" +#define TRAIT_MUSICIAN "musician" +#define TRAIT_CROCRIN_IMMUNE "crocin_immune" #define TRAIT_NYMPHO "nymphomania" #define TRAIT_MASO "masochism" +#define TRAIT_EXHIBITIONIST "exhibitionist" #define TRAIT_PARA "paraplegic" #define TRAIT_EMPATH "empath" #define TRAIT_FRIENDLY "friendly" diff --git a/code/__HELPERS/_cit_helpers.dm b/code/__HELPERS/_cit_helpers.dm index 668b151b6e..d75dd31b46 100644 --- a/code/__HELPERS/_cit_helpers.dm +++ b/code/__HELPERS/_cit_helpers.dm @@ -56,6 +56,7 @@ GLOBAL_LIST_EMPTY(ipc_screens_list) GLOBAL_LIST_EMPTY(ipc_antennas_list) //Genitals and Arousal Lists +GLOBAL_LIST_EMPTY(genitals_list) GLOBAL_LIST_EMPTY(cock_shapes_list)//global_lists.dm for the list initializations //Now also _DATASTRUCTURES globals.dm GLOBAL_LIST_EMPTY(cock_shapes_icons) //Associated list for names->icon_states for cockshapes. GLOBAL_LIST_EMPTY(balls_shapes_list) @@ -124,41 +125,39 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE) SSblackbox.record_feedback("tally", "admin_verb", 1, "TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /mob/living/carbon/proc/has_penis() - if(getorganslot("penis"))//slot shared with ovipositor - if(istype(getorganslot("penis"), /obj/item/organ/genital/penis)) - return TRUE + var/obj/item/organ/genital/G = getorganslot(ORGAN_SLOT_PENIS) + if(G && istype(G, /obj/item/organ/genital/penis)) + return TRUE return FALSE /mob/living/carbon/proc/has_balls() - if(getorganslot("balls")) - if(istype(getorganslot("balls"), /obj/item/organ/genital/testicles)) - return TRUE + var/obj/item/organ/genital/G = getorganslot(ORGAN_SLOT_TESTICLES) + if(G && istype(G, /obj/item/organ/genital/testicles)) + return TRUE return FALSE /mob/living/carbon/proc/has_vagina() - if(getorganslot("vagina")) + if(getorganslot(ORGAN_SLOT_VAGINA)) return TRUE return FALSE /mob/living/carbon/proc/has_breasts() - if(getorganslot("breasts")) + if(getorganslot(ORGAN_SLOT_BREASTS)) return TRUE return FALSE /mob/living/carbon/proc/has_ovipositor() - if(getorganslot("penis"))//shared slot - if(istype(getorganslot("penis"), /obj/item/organ/genital/ovipositor)) - return TRUE + var/obj/item/organ/genital/G = getorganslot(ORGAN_SLOT_PENIS) + if(G && istype(G, /obj/item/organ/genital/ovipositor)) + return TRUE return FALSE /mob/living/carbon/human/proc/has_eggsack() - if(getorganslot("balls")) - if(istype(getorganslot("balls"), /obj/item/organ/genital/eggsack)) - return TRUE + var/obj/item/organ/genital/G = getorganslot(ORGAN_SLOT_TESTICLES) + if(G && istype(G, /obj/item/organ/genital/eggsack)) + return TRUE return FALSE -/mob/living/carbon/human/proc/is_bodypart_exposed(bodypart) - /mob/living/carbon/proc/is_groin_exposed(var/list/L) if(!L) L = get_equipped_items() @@ -188,9 +187,9 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE) message_admins("[src] gave everyone genitals.") for(var/mob/living/carbon/human/H in GLOB.mob_list) if(H.gender == MALE) - H.give_penis() - H.give_balls() + H.give_genital(/obj/item/organ/genital/penis) + H.give_genital(/obj/item/organ/genital/testicles) else - H.give_vagina() - H.give_womb() - H.give_breasts() + H.give_genital(/obj/item/organ/genital/vagina) + H.give_genital(/obj/item/organ/genital/womb) + H.give_genital(/obj/item/organ/genital/breasts) diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index c8a33959ed..b0b0f32345 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -61,6 +61,10 @@ for(var/K in GLOB.balls_shapes_list) var/datum/sprite_accessory/testicles/value = GLOB.balls_shapes_list[K] GLOB.balls_shapes_icons[K] = value.icon_state + + for(var/gpath in subtypesof(/obj/item/organ/genital)) + var/obj/item/organ/genital/G = gpath + GLOB.genitals_list[initial(G.name)] = gpath //END OF CIT CHANGES //Species diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 5ec839130a..81801cd6a2 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -154,7 +154,6 @@ "xenodorsal" = "Standard", "xenohead" = "Standard", "xenotail" = "Xenomorph Tail", - "exhibitionist" = FALSE, "genitals_use_skintone" = FALSE, "has_cock" = FALSE, "cock_shape" = pick(GLOB.cock_shapes_list), diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm index f70e3a3c68..156ee00d75 100644 --- a/code/datums/traits/neutral.dm +++ b/code/datums/traits/neutral.dm @@ -94,6 +94,41 @@ lose_text = "You don't feel as prudish as before." medical_record_text = "Patient exhibits a special gene that makes them immune to Crocin and Hexacrocin." +/datum/quirk/libido + name = "Nymphomania" + desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual." + value = 0 + mob_trait = TRAIT_NYMPHO + gain_text = "You are feeling extra wild." + lose_text = "You don't feel that burning sensation anymore." + +/datum/quirk/libido/add() + var/mob/living/M = quirk_holder + M.min_arousal = 16 + M.arousal_rate = 3 + +/datum/quirk/libido/remove() + var/mob/living/M = quirk_holder + M.min_arousal = initial(M.min_arousal) + M.arousal_rate = initial(M.arousal_rate) + +/datum/quirk/maso + name = "Masochism" + desc = "You are aroused by pain." + value = 0 + mob_trait = TRAIT_MASO + gain_text = "You desire to be hurt." + lose_text = "Pain has become less exciting for you." + +/datum/quirk/exhibitionism + name = "Exhibitionism" + desc = "You don't mind showing off your bare body to strangers, in fact you find it quite satistying. Not the best excuse to break Space Law anyway." //as if they'd care anyway. + value = 0 + medical_record_text = "Patient has been diagnosed with exhibitionistic disorder." + mob_trait = TRAIT_EXHIBITIONIST + gain_text = "You feel like exposing yourself to the world." + lose_text = "Indecent exposure doesn't sound as charming to you anymore." + /datum/quirk/assblastusa name = "Buns of Steel" desc = "You've never skipped ass day. With this trait, you are completely immune to all forms of ass slapping and anyone who tries to slap your rock hard ass usually gets a broken hand." diff --git a/code/modules/admin/create_mob.dm b/code/modules/admin/create_mob.dm index fad7410a6a..eb856237bf 100644 --- a/code/modules/admin/create_mob.dm +++ b/code/modules/admin/create_mob.dm @@ -25,6 +25,9 @@ H.facial_hair_color = H.hair_color H.eye_color = random_eye_color() H.dna.blood_type = random_blood_type() + H.saved_underwear = H.underwear + H.saved_undershirt = H.undershirt + H.saved_socks = H.socks // Mutant randomizing, doesn't affect the mob appearance unless it's the specific mutant. H.dna.features["mcolor"] = random_short_color() diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 54d75e8437..bac9ed0c89 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -108,7 +108,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) "xenohead" = "Standard", "xenotail" = "Xenomorph Tail", "taur" = "None", - "exhibitionist" = FALSE, "genitals_use_skintone" = FALSE, "has_cock" = FALSE, "cock_shape" = "Human", @@ -790,7 +789,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat +="" dat += "

Citadel Preferences

" //Because fuck me if preferences can't be fucking modularized and expected to update in a reasonable timeframe. dat += "Arousal:[arousable == TRUE ? "Enabled" : "Disabled"]
" - dat += "Exhibitionist:[features["exhibitionist"] == TRUE ? "Yes" : "No"]
" dat += "Voracious MediHound sleepers: [(cit_toggles & MEDIHOUND_SLEEPER) ? "Yes" : "No"]
" dat += "Hear Vore Sounds: [(cit_toggles & EATING_NOISES) ? "Yes" : "No"]
" dat += "Hear Vore Digestion Sounds: [(cit_toggles & DIGESTION_NOISES) ? "Yes" : "No"]
" @@ -2048,8 +2046,6 @@ GLOBAL_LIST_EMPTY(preferences_datums) features["has_womb"] = FALSE if("has_womb") features["has_womb"] = !features["has_womb"] - if("exhibitionist") - features["exhibitionist"] = !features["exhibitionist"] if("widescreenpref") widescreenpref = !widescreenpref user.client.change_view(CONFIG_GET(string/default_view)) diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index b9c5cb7ef9..175cd9613a 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -5,7 +5,7 @@ // You do not need to raise this if you are adding new values that have sane defaults. // Only raise this value when changing the meaning/format/name/layout of an existing value // where you would want the updater procs below to run -#define SAVEFILE_VERSION_MAX 20 +#define SAVEFILE_VERSION_MAX 21 /* SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Carn @@ -49,6 +49,11 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car pda_style = "mono" if(current_version < 20) pda_color = "#808000" + if(current_version < 21 && S["feature_exhibitionist"]) + var/datum/quirk/exhibitionism/E + var/quirk_name = initial(E.name) + neutral_quirks += quirk_name + all_quirks += quirk_name /datum/preferences/proc/load_path(ckey,filename="preferences.sav") if(!ckey) diff --git a/modular_citadel/code/datums/traits/neutral.dm b/modular_citadel/code/datums/traits/neutral.dm deleted file mode 100644 index 05aeb27361..0000000000 --- a/modular_citadel/code/datums/traits/neutral.dm +++ /dev/null @@ -1,33 +0,0 @@ -// Citadel-specific Neutral Traits - -/datum/quirk/libido - name = "Nymphomania" - desc = "You're always feeling a bit in heat. Also, you get aroused faster than usual." - value = 0 - mob_trait = TRAIT_NYMPHO - gain_text = "You are feeling extra wild." - lose_text = "You don't feel that burning sensation anymore." - -/datum/quirk/libido/add() - var/mob/living/M = quirk_holder - M.min_arousal = 16 - M.arousal_rate = 3 - -/datum/quirk/libido/remove() - var/mob/living/M = quirk_holder - M.min_arousal = initial(M.min_arousal) - M.arousal_rate = initial(M.arousal_rate) - -/datum/quirk/libido/on_process() - var/mob/living/M = quirk_holder - if(M.canbearoused == FALSE) - to_chat(quirk_holder, "Having high libido is useless when you can't feel arousal at all!") - qdel(src) - -/datum/quirk/maso - name = "Masochism" - desc = "You are aroused by pain." - value = 0 - mob_trait = TRAIT_MASO - gain_text = "You desire to be hurt." - lose_text = "Pain has become less exciting for you." diff --git a/modular_citadel/code/modules/arousal/arousal.dm b/modular_citadel/code/modules/arousal/arousal.dm index 27f7576e7f..8826cb0774 100644 --- a/modular_citadel/code/modules/arousal/arousal.dm +++ b/modular_citadel/code/modules/arousal/arousal.dm @@ -19,11 +19,6 @@ var/hidden_undershirt = FALSE var/hidden_socks = FALSE -/mob/living/carbon/human/New() - ..() - saved_underwear = underwear - saved_undershirt = undershirt - //Species vars /datum/species var/arousal_gain_rate = AROUSAL_START_VALUE //Rate at which this species becomes aroused @@ -35,60 +30,53 @@ //Mob procs /mob/living/carbon/human/proc/underwear_toggle() set name = "Toggle undergarments" - set category = "Object" - if(ishuman(src)) - var/mob/living/carbon/human/humz = src - var/confirm = input(src, "Select what part of your form to alter", "Undergarment Toggling", "Cancel") in list("Top", "Bottom", "Socks", "All", "Cancel") - if(confirm == "Top") - humz.hidden_undershirt = !humz.hidden_undershirt + set category = "IC" - if(confirm == "Bottom") - humz.hidden_underwear = !humz.hidden_underwear + var/confirm = input(src, "Select what part of your form to alter", "Undergarment Toggling") as null|anything in list("Top", "Bottom", "Socks", "All") + if(!confirm) + return + if(confirm == "Top") + hidden_undershirt = !hidden_undershirt - if(confirm == "Socks") - humz.hidden_socks = !humz.hidden_socks + if(confirm == "Bottom") + hidden_underwear = !hidden_underwear - if(confirm == "All") - humz.hidden_undershirt = !humz.hidden_undershirt - humz.hidden_underwear = !humz.hidden_underwear - humz.hidden_socks = !humz.hidden_socks + if(confirm == "Socks") + hidden_socks = !hidden_socks - if(confirm == "Cancel") - return - src.update_body() + if(confirm == "All") + var/on_off = (hidden_undershirt || hidden_underwear || hidden_socks) ? FALSE : TRUE + hidden_undershirt = on_off + hidden_underwear = on_off + hidden_socks = on_off - else - to_chat(src, "Humans only. How the fuck did you get this verb anyway.") + update_body() -/mob/living/proc/handle_arousal() - - -/mob/living/carbon/handle_arousal() - if(canbearoused && dna) - var/datum/species/S - S = dna.species - if(S && !(SSmobs.times_fired % 36) && getArousalLoss() < max_arousal)//Totally stolen from breathing code. Do this every 36 ticks. - adjustArousalLoss(arousal_rate * S.arousal_gain_rate) - if(dna.features["exhibitionist"] && client) - var/amt_nude = 0 - if(is_chest_exposed() && (getorganslot("breasts"))) - amt_nude++ - if(is_groin_exposed()) - if(getorganslot("penis")) - amt_nude++ - if(getorganslot("vagina")) - amt_nude++ - if(amt_nude) - var/watchers = 0 - for(var/mob/_M in view(world.view, src)) - var/mob/living/M = _M - if(!istype(M)) - continue - if(M.client && !M.stat && !M.eye_blind && (locate(src) in viewers(world.view,M))) - watchers++ - if(watchers) - adjustArousalLoss((amt_nude * watchers) + S.arousal_gain_rate) +/mob/living/proc/handle_arousal(times_fired) + return +/mob/living/carbon/handle_arousal(times_fired) + if(!canbearoused || !dna) + return + var/datum/species/S = dna.species + if(!S || (times_fired % 36) || !getArousalLoss() >= max_arousal)//Totally stolen from breathing code. Do this every 36 ticks. + return + var/our_loss = arousal_rate * S.arousal_gain_rate + if(HAS_TRAIT(src, TRAIT_EXHIBITIONIST) && client) + var/amt_nude = 0 + for(var/obj/item/organ/genital/G in internal_organs) + if(G.is_exposed()) + amt_nude++ + if(amt_nude) + var/watchers = 0 + for(var/mob/living/L in view(world.view, src)) + if(!istype(L)) + continue + if(L.client && !L.stat && !L.eye_blind && (locate(src) in viewers(world.view, L))) + watchers++ + if(watchers) + our_loss += (amt_nude * watchers) + S.arousal_gain_rate + adjustArousalLoss(our_loss) /mob/living/proc/getArousalLoss() return arousalloss @@ -138,8 +126,6 @@ S = GLOB.breasts_shapes_list[G.shape] if(S?.alt_aroused) G.aroused_state = isPercentAroused(G.aroused_amount) - if(getArousalLoss() >= ((max_arousal / 100) * 33)) - G.aroused_state = TRUE else G.aroused_state = FALSE G.update_appearance() @@ -147,54 +133,18 @@ /mob/living/proc/update_arousal_hud() return FALSE -/datum/species/proc/update_arousal_hud(mob/living/carbon/human/H) - return FALSE - /mob/living/carbon/human/update_arousal_hud() - if(!client || !hud_used) - return FALSE - if(dna.species.update_arousal_hud()) + if(!client || !(hud_used?.arousal)) return FALSE if(!canbearoused) hud_used.arousal.icon_state = "" return FALSE + if(stat == DEAD) + hud_used.arousal.icon_state = "arousal0" else - if(hud_used.arousal) - if(stat == DEAD) - hud_used.arousal.icon_state = "arousal0" - return TRUE - if(getArousalLoss() == max_arousal) - hud_used.arousal.icon_state = "arousal100" - return TRUE - if(getArousalLoss() >= (max_arousal / 100) * 90)//M O D U L A R , W O W - hud_used.arousal.icon_state = "arousal90" - return TRUE - if(getArousalLoss() >= (max_arousal / 100) * 80)//M O D U L A R , W O W - hud_used.arousal.icon_state = "arousal80" - return TRUE - if(getArousalLoss() >= (max_arousal / 100) * 70)//M O D U L A R , W O W - hud_used.arousal.icon_state = "arousal70" - return TRUE - if(getArousalLoss() >= (max_arousal / 100) * 60)//M O D U L A R , W O W - hud_used.arousal.icon_state = "arousal60" - return TRUE - if(getArousalLoss() >= (max_arousal / 100) * 50)//M O D U L A R , W O W - hud_used.arousal.icon_state = "arousal50" - return TRUE - if(getArousalLoss() >= (max_arousal / 100) * 40)//M O D U L A R , W O W - hud_used.arousal.icon_state = "arousal40" - return TRUE - if(getArousalLoss() >= (max_arousal / 100) * 30)//M O D U L A R , W O W - hud_used.arousal.icon_state = "arousal30" - return TRUE - if(getArousalLoss() >= (max_arousal / 100) * 20)//M O D U L A R , W O W - hud_used.arousal.icon_state = "arousal10" - return TRUE - if(getArousalLoss() >= (max_arousal / 100) * 10)//M O D U L A R , W O W - hud_used.arousal.icon_state = "arousal10" - return TRUE - else - hud_used.arousal.icon_state = "arousal0" + var/value = FLOOR(getPercentAroused(), 10) + hud_used.arousal.icon_state = "arousal[value]" + return TRUE /obj/screen/arousal name = "arousal" @@ -213,7 +163,6 @@ to_chat(M, "Arousal is disabled. Feature is unavailable.") - /mob/living/proc/mob_climax()//This is just so I can test this shit without being forced to add actual content to get rid of arousal. Will be a very basic proc for a while. set name = "Masturbate" set category = "IC" @@ -221,212 +170,150 @@ if(mb_cd_timer <= world.time) //start the cooldown even if it fails mb_cd_timer = world.time + mb_cd_length - if(getArousalLoss() >= ((max_arousal / 100) * 33))//33% arousal or greater required - src.visible_message("[src] starts masturbating!", \ + if(getArousalLoss() >= 33)//one third of average max_arousal or greater required + visible_message("[src] starts masturbating!", \ "You start masturbating.") if(do_after(src, 30, target = src)) - src.visible_message("[src] relieves [p_them()]self!", \ + visible_message("[src] relieves [p_them()]self!", \ "You have relieved yourself.") SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) setArousalLoss(min_arousal) else to_chat(src, "You aren't aroused enough for that.") +/obj/item/organ/genital/proc/climaxable(mob/living/carbon/human/H, silent = FALSE) //returns the fluid source (ergo reagents holder) if found. + if(producing) + . = reagents + else + if(linked_organ) + . = linked_organ.reagents + else if(!silent) + to_chat(H, "Your [name] is unable to produce it's own fluids, it's missing the organs for it.") + +/mob/living/carbon/human/proc/do_climax(datum/reagents/R, atom/target, obj/item/organ/genital/G, spill = TRUE) + if(!G) + return + SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + if(!target || !R) + return + var/turfing = isturf(target) + if(spill & R.total_volume >= 5) + R.reaction(turfing ? target : target.loc, TOUCH, 1, 0) + if(!turfing) + R.trans_to(target, R.total_volume * (spill ? G.fluid_transfer_factor : 1)) + R.clear_reagents() //These are various procs that we'll use later, split up for readability instead of having one, huge proc. //For all of these, we assume the arguments given are proper and have been checked beforehand. /mob/living/carbon/human/proc/mob_masturbate(obj/item/organ/genital/G, mb_time = 30) //Masturbation, keep it gender-neutral - var/total_fluids = 0 - var/datum/reagents/fluid_source = null - - if(G.producing) //Can it produce its own fluids, such as breasts? - fluid_source = G.reagents - else - if(!G.linked_organ) - to_chat(src, "Your [G.name] is unable to produce it's own fluids, it's missing the organs for it.") - return - fluid_source = G.linked_organ.reagents - total_fluids = fluid_source.total_volume + var/datum/reagents/fluid_source = G.climaxable(src) + if(!fluid_source) + return + var/obj/item/organ/genital/PP = G.can_masturbate_with == MASTURBATE_LINKED_ORGAN ? G.linked_organ : G + if(!PP) + to_chat(src, "You shudder, unable to cum with your [name].") if(mb_time) - src.visible_message("[src] starts to [G.masturbation_verb] [p_their()] [G.name].", \ - "You start to [G.masturbation_verb] your [G.name].", \ + visible_message("[src] starts to [G.masturbation_verb] [p_their()] [G.name].", \ "You start to [G.masturbation_verb] your [G.name].") - - if(do_after(src, mb_time, target = src)) - if(total_fluids > 5) - fluid_source.reaction(src.loc, TOUCH, 1, 0) - fluid_source.clear_reagents() - src.visible_message("[src] orgasms, cumming[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""]!", \ - "You cum[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""].", \ - "You have relieved yourself.") - SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) - if(G.can_climax) - setArousalLoss(min_arousal) - + if(!do_after(src, mb_time, target = src) || !G.climaxable(src, TRUE)) + return + visible_message("[src] orgasms, [PP.orgasm_verb][isturf(loc) ? " onto [loc]" : ""]!", \ + "You orgasm, [PP.orgasm_verb][isturf(loc) ? " onto [loc]" : ""].") + do_climax(fluid_source, loc, G) /mob/living/carbon/human/proc/mob_climax_outside(obj/item/organ/genital/G, mb_time = 30) //This is used for forced orgasms and other hands-free climaxes - var/total_fluids = 0 - var/datum/reagents/fluid_source = null - var/unable_to_come = FALSE - - if(G.producing) //Can it produce its own fluids, such as breasts? - fluid_source = G.reagents - total_fluids = fluid_source.total_volume - else - if(!G.linked_organ) - unable_to_come = TRUE - else - fluid_source = G.linked_organ.reagents - total_fluids = fluid_source.total_volume - - if(unable_to_come) - src.visible_message("[src] shudders, their [G.name] unable to cum.", \ - "Your [G.name] cannot cum, giving no relief.", \ + var/datum/reagents/fluid_source = G.climaxable(src, TRUE) + if(!fluid_source) + visible_message("[src] shudders, their [G.name] unable to cum.", \ "Your [G.name] cannot cum, giving no relief.") - else - total_fluids = fluid_source.total_volume - if(mb_time) //as long as it's not instant, give a warning - src.visible_message("[src] looks like they're about to cum.", \ - "You feel yourself about to orgasm.", \ - "You feel yourself about to orgasm.") - if(do_after(src, mb_time, target = src)) - if(total_fluids > 5) - fluid_source.reaction(src.loc, TOUCH, 1, 0) - fluid_source.clear_reagents() - src.visible_message("[src] orgasms[istype(src.loc, /turf/open/floor) ? ", spilling onto [src.loc]" : ""], using [p_their()] [G.name]!", \ - "You climax[istype(src.loc, /turf/open/floor) ? ", spilling onto [src.loc]" : ""] with your [G.name].", \ - "You climax using your [G.name].") - SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) - if(G.can_climax) - setArousalLoss(min_arousal) - + return + if(mb_time) //as long as it's not instant, give a warning + visible_message("[src] looks like they're about to cum.", \ + "You feel yourself about to orgasm.") + if(!do_after(src, mb_time, target = src) || !G.climaxable(src, TRUE)) + return + visible_message("[src] orgasms[isturf(loc) ? " onto [loc]" : ""], using [p_their()] [G.name]!", \ + "You climax[isturf(loc) ? " onto [loc]" : ""] with your [G.name].") + do_climax(fluid_source, loc, G) /mob/living/carbon/human/proc/mob_climax_partner(obj/item/organ/genital/G, mob/living/L, spillage = TRUE, mb_time = 30) //Used for climaxing with any living thing - var/total_fluids = 0 - var/datum/reagents/fluid_source = null - - if(G.producing) //Can it produce its own fluids, such as breasts? - fluid_source = G.reagents - else - if(!G.linked_organ) - to_chat(src, "Your [G.name] is unable to produce it's own fluids, it's missing the organs for it.") - return - fluid_source = G.linked_organ.reagents - total_fluids = fluid_source.total_volume + var/datum/reagents/fluid_source = G.climaxable(src) + if(!fluid_source) + return if(mb_time) //Skip warning if this is an instant climax. - src.visible_message("[src] is about to climax with [L]!", \ - "You're about to climax with [L]!", \ - "You're preparing to climax with someone!") + visible_message("[src] is about to climax with [L]!", \ + "You're about to climax with [L]!") + if(!do_after(src, mb_time, target = src) || !in_range(src, L) || !G.climaxable(src, TRUE)) + return if(spillage) - if(do_after(src, mb_time, target = src) && in_range(src, L)) - fluid_source.trans_to(L, total_fluids*G.fluid_transfer_factor) - total_fluids -= total_fluids*G.fluid_transfer_factor - if(total_fluids > 5) - fluid_source.reaction(L.loc, TOUCH, 1, 0) - fluid_source.clear_reagents() - src.visible_message("[src] climaxes with [L][spillage ? ", overflowing and spilling":""], using [p_their()] [G.name]!", \ - "You orgasm with [L][spillage ? ", spilling out of them":""], using your [G.name].", \ - "You have climaxed with someone[spillage ? ", spilling out of them":""], using your [G.name].") - SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) - SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) - if(G.can_climax) - setArousalLoss(min_arousal) + visible_message("[src] climaxes with [L], overflowing and spilling, using [p_their()] [G.name]!", \ + "You orgasm with [L], spilling out of them, using your [G.name].") else //knots and other non-spilling orgasms - if(do_after(src, mb_time, target = src) && in_range(src, L)) - fluid_source.trans_to(L, total_fluids) - total_fluids = 0 - src.visible_message("[src] climaxes with [L], [p_their()] [G.name] spilling nothing!", \ - "You ejaculate with [L], your [G.name] spilling nothing.", \ - "You have climaxed inside someone, your [G.name] spilling nothing.") - SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) - SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) - if(G.can_climax) - setArousalLoss(min_arousal) + visible_message("[src] climaxes with [L], [p_their()] [G.name] spilling nothing!", \ + "You ejaculate with [L], your [G.name] spilling nothing.") + SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + do_climax(fluid_source, spillage ? loc : L, G, spillage) /mob/living/carbon/human/proc/mob_fill_container(obj/item/organ/genital/G, obj/item/reagent_containers/container, mb_time = 30) //For beaker-filling, beware the bartender - var/total_fluids = 0 - var/datum/reagents/fluid_source = null - - if(G.producing) //Can it produce its own fluids, such as breasts? - fluid_source = G.reagents - else - if(!G.linked_organ) - to_chat(src, "Your [G.name] is unable to produce it's own fluids, it's missing the organs for it.") + var/datum/reagents/fluid_source = G.climaxable(src) + if(!fluid_source) + return + if(mb_time) + visible_message("[src] starts to [G.masturbation_verb] their [G.name] over [container].", \ + "You start to [G.masturbation_verb] your [G.name] over [container].") + if(!do_after(src, mb_time, target = src) || !in_range(src, container) || !G.climaxable(src, TRUE)) return - fluid_source = G.linked_organ.reagents - total_fluids = fluid_source.total_volume - - //if(!container) //Something weird happened - // to_chat(src, "You need a container to do this!") - // return - - src.visible_message("[src] starts to [G.masturbation_verb] their [G.name] over [container].", \ - "You start to [G.masturbation_verb] your [G.name] over [container].", \ - "You start to [G.masturbation_verb] your [G.name] over something.") - if(do_after(src, mb_time, target = src) && in_range(src, container)) - fluid_source.trans_to(container, total_fluids) - src.visible_message("[src] uses [p_their()] [G.name] to fill [container]!", \ - "You used your [G.name] to fill [container].", \ - "You have relieved some pressure.") - SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) - if(G.can_climax) - setArousalLoss(min_arousal) + visible_message("[src] uses [p_their()] [G.name] to fill [container]!", \ + "You used your [G.name] to fill [container].") + do_climax(fluid_source, container, G, FALSE) /mob/living/carbon/human/proc/pick_masturbate_genitals() - var/obj/item/organ/genital/ret_organ var/list/genitals_list = list() var/list/worn_stuff = get_equipped_items() for(var/obj/item/organ/genital/G in internal_organs) - if(G.can_masturbate_with) //filter out what you can't masturbate with - if(G.is_exposed(worn_stuff)) //Nude or through_clothing - genitals_list += G + if(G.can_masturbate_with && G.is_exposed(worn_stuff)) //filter out what you can't masturbate with + if(G.can_masturbate_with == MASTURBATE_LINKED_ORGAN && !G.linked_organ) + continue + genitals_list += G if(genitals_list.len) - ret_organ = input(src, "with what?", "Masturbate", null) as null|obj in genitals_list + var/obj/item/organ/genital/ret_organ = input(src, "with what?", "Masturbate", null) as null|obj in genitals_list return ret_organ - return null //error stuff /mob/living/carbon/human/proc/pick_climax_genitals() - var/obj/item/organ/genital/ret_organ var/list/genitals_list = list() var/list/worn_stuff = get_equipped_items() for(var/obj/item/organ/genital/G in internal_organs) - if(G.can_climax) //filter out what you can't masturbate with - if(G.is_exposed(worn_stuff)) //Nude or through_clothing - genitals_list += G + if(G.can_climax && G.is_exposed(worn_stuff)) //filter out what you can't masturbate with + genitals_list += G if(genitals_list.len) - ret_organ = input(src, "with what?", "Climax", null) as null|obj in genitals_list + var/obj/item/organ/genital/ret_organ = input(src, "with what?", "Climax", null) as null|obj in genitals_list return ret_organ - return null //error stuff /mob/living/carbon/human/proc/pick_partner() var/list/partners = list() - if(src.pulling) - partners += src.pulling //Yes, even objects for now - if(src.pulledby) - partners += src.pulledby + if(pulling) + partners += pulling + if(pulledby) + partners += pulledby //Now we got both of them, let's check if they're proper - for(var/I in partners) - if(isliving(I)) - if(iscarbon(I)) - var/mob/living/carbon/C = I - if(!C.exposed_genitals.len) //Nothing through_clothing - if(!C.is_groin_exposed()) //No pants undone - if(!C.is_chest_exposed()) //No chest exposed - partners -= I //Then not proper, remove them - else - partners -= I //No fucking objects + for(var/mob/living/L in partners) + if(iscarbon(L)) + var/mob/living/carbon/C = L + if(!C.exposed_genitals.len && !C.is_groin_exposed() && !C.is_chest_exposed()) //Nothing through_clothing, no proper partner. + partners -= C //NOW the list should only contain correct partners if(!partners.len) - return null //No one left. - return input(src, "With whom?", "Sexual partner", null) in partners //pick one, default to null + return //No one left. + var/mob/living/target = input(src, "With whom?", "Sexual partner", null) as null|anything in partners //pick one, default to null + if(target && in_range(src, target)) + return target /mob/living/carbon/human/proc/pick_climax_container() - var/obj/item/reagent_containers/SC = null var/list/containers_list = list() for(var/obj/item/reagent_containers/container in held_items) @@ -434,12 +321,21 @@ containers_list += container if(containers_list.len) - SC = input(src, "Into or onto what?(Cancel for nowhere)", null) as null|obj in containers_list - if(SC) - if(in_range(src, SC)) - return SC + var/obj/item/reagent_containers/SC = input(src, "Into or onto what?(Cancel for nowhere)", null) as null|obj in containers_list + if(SC && in_range(src, SC)) + return SC return null //If nothing correct, give null. +/mob/living/carbon/human/proc/available_rosie_palms(silent = FALSE) + if(restrained(TRUE)) //TRUE ignores grabs + if(!silent) + to_chat(src, "You can't do that while restrained!") + return FALSE + if(!get_num_arms() || !get_empty_held_indexes()) + if(!silent) + to_chat(src, "You need at least one free arm.") + return FALSE + return TRUE //Here's the main proc itself /mob/living/carbon/human/mob_climax(forced_climax=FALSE) //Forced is instead of the other proc, makes you cum if you have the tools for it, ignoring restraints @@ -447,49 +343,47 @@ if(!forced_climax) //Don't spam the message to the victim if forced to come too fast to_chat(src, "You need to wait [DisplayTimeText((mb_cd_timer - world.time), TRUE)] before you can do that again!") return - mb_cd_timer = (world.time + mb_cd_length) - + mb_cd_timer = world.time + mb_cd_length if(canbearoused && has_dna()) - if(stat==2) - to_chat(src, "You can't do that while dead!") + if(stat == DEAD) + if(!forced_climax) + to_chat(src, "You can't do that while dead!") return if(forced_climax) //Something forced us to cum, this is not a masturbation thing and does not progress to the other checks - for(var/obj/item/organ/O in internal_organs) - if(istype(O, /obj/item/organ/genital)) - var/obj/item/organ/genital/G = O - if(!G.can_climax) //Skip things like wombs and testicles - continue - var/mob/living/partner - var/check_target - var/list/worn_stuff = get_equipped_items() + for(var/obj/item/organ/genital/G in internal_organs) + if(!G.can_climax) //Skip things like wombs and testicles + continue + var/mob/living/partner + var/check_target + var/list/worn_stuff = get_equipped_items() - if(G.is_exposed(worn_stuff)) - if(src.pulling) //Are we pulling someone? Priority target, we can't be making option menus for this, has to be quick - if(isliving(src.pulling)) //Don't fuck objects - check_target = src.pulling - if(src.pulledby && !check_target) //prioritise pulled over pulledby - if(isliving(src.pulledby)) - check_target = src.pulledby - //Now we should have a partner, or else we have to come alone - if(check_target) - if(iscarbon(check_target)) //carbons can have clothes - var/mob/living/carbon/C = check_target - if(C.exposed_genitals.len || C.is_groin_exposed() || C.is_chest_exposed()) //Are they naked enough? - partner = C - else //A cat is fine too - partner = check_target - if(partner) //Did they pass the clothing checks? - mob_climax_partner(G, partner, mb_time = 0) //Instant climax due to forced - continue //You've climaxed once with this organ, continue on - //not exposed OR if no partner was found while exposed, climax alone - mob_climax_outside(G, mb_time = 0) //removed climax timer for sudden, forced orgasms + 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 return //If we get here, then this is not a forced climax and we gotta check a few things. - if(stat==1) //No sleep-masturbation, you're unconscious. + if(stat == UNCONSCIOUS) //No sleep-masturbation, you're unconscious. to_chat(src, "You must be conscious to do that!") return if(getArousalLoss() < 33) //flat number instead of percentage @@ -497,91 +391,38 @@ return //Ok, now we check what they want to do. - var/choice = input(src, "Select sexual activity", "Sexual activity:") in list("Masturbate", "Climax alone", "Climax with partner", "Fill container") + var/choice = input(src, "Select sexual activity", "Sexual activity:") as null|anything in list("Masturbate", "Climax alone", "Climax with partner", "Fill container") switch(choice) if("Masturbate") - if(restrained(TRUE)) //TRUE ignores grabs - to_chat(src, "You can't do that while restrained!") - return - var/free_hands = get_num_arms() - if(!free_hands) - to_chat(src, "You need at least one free arm.") - return - for(var/helditem in held_items)//how many hands are free - if(isobj(helditem)) - free_hands-- - if(free_hands <= 0) - to_chat(src, "You're holding too many things.") + if(!available_rosie_palms()) return //We got hands, let's pick an organ - var/obj/item/organ/genital/picked_organ - picked_organ = pick_masturbate_genitals() - if(picked_organ) + var/obj/item/organ/genital/picked_organ = pick_masturbate_genitals() + if(picked_organ && available_rosie_palms(TRUE)) mob_masturbate(picked_organ) return - else //They either lack organs that can masturbate, or they didn't pick one. - to_chat(src, "You cannot masturbate without choosing genitals.") - return if("Climax alone") - if(restrained(TRUE)) //TRUE ignores grabs - to_chat(src, "You can't do that while restrained!") + if(!available_rosie_palms()) return - var/free_hands = get_num_arms() - if(!free_hands) - to_chat(src, "You need at least one free arm.") - return - for(var/helditem in held_items)//how many hands are free - if(isobj(helditem)) - free_hands-- - if(free_hands <= 0) - to_chat(src, "You're holding too many things.") - return - //We got hands, let's pick an organ - var/obj/item/organ/genital/picked_organ - picked_organ = pick_climax_genitals() - if(picked_organ) + var/obj/item/organ/genital/picked_organ = pick_climax_genitals() + if(picked_organ && available_rosie_palms(TRUE)) mob_climax_outside(picked_organ) - return - else //They either lack organs that can masturbate, or they didn't pick one. - to_chat(src, "You cannot climax without choosing genitals.") - return if("Climax with partner") //We need no hands, we can be restrained and so on, so let's pick an organ - var/obj/item/organ/genital/picked_organ - picked_organ = pick_climax_genitals() + 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 anything in list("Yes", "No") - if(spillage == "Yes") - mob_climax_partner(picked_organ, partner, TRUE) - else - mob_climax_partner(picked_organ, partner, FALSE) - return - else - to_chat(src, "You cannot do this alone.") - return - else //They either lack organs that can masturbate, or they didn't pick one. - to_chat(src, "You cannot climax without choosing genitals.") - return + var/spillage = input(src, "Would your fluids spill outside?", "Choose overflowing option", "Yes") as null|anything in list("Yes", "No") + if(spillage && in_range(src, partner)) + mob_climax_partner(picked_organ, partner, spillage == "Yes" ? TRUE : FALSE) if("Fill container") //We'll need hands and no restraints. - if(restrained(TRUE)) //TRUE ignores grabs - to_chat(src, "You can't do that while restrained!") - return - var/free_hands = get_num_arms() - if(!free_hands) - to_chat(src, "You need at least one free arm.") - return - for(var/helditem in held_items)//how many hands are free - if(isobj(helditem)) - free_hands-- - if(free_hands <= 0) - to_chat(src, "You're holding too many things.") + if(!available_rosie_palms()) return //We got hands, let's pick an organ var/obj/item/organ/genital/picked_organ @@ -589,14 +430,6 @@ 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) + if(fluid_container && available_rosie_palms(TRUE)) mob_fill_container(picked_organ, fluid_container) - return - else - to_chat(src, "You cannot do this without anything to fill.") - return - else //They either lack organs that can climax, or they didn't pick one. - to_chat(src, "You cannot fill anything without choosing genitals.") - return - else //Somehow another option was taken, maybe something interrupted the selection or it was cancelled - return //Just end it in that case. + return \ No newline at end of file diff --git a/modular_citadel/code/modules/arousal/organs/genitals.dm b/modular_citadel/code/modules/arousal/organs/_genitals.dm similarity index 60% rename from modular_citadel/code/modules/arousal/organs/genitals.dm rename to modular_citadel/code/modules/arousal/organs/_genitals.dm index 63d6834409..2222624050 100644 --- a/modular_citadel/code/modules/arousal/organs/genitals.dm +++ b/modular_citadel/code/modules/arousal/organs/_genitals.dm @@ -6,8 +6,9 @@ var/list/genital_flags = list() var/can_masturbate_with = FALSE var/masturbation_verb = "masturbate" + var/orgasm_verb = "cumming" //present continous var/can_climax = FALSE - var/fluid_transfer_factor = 0.0 //How much would a partner get in them if they climax using this? + var/fluid_transfer_factor = 0 //How much would a partner get in them if they climax using this? var/size = 2 //can vary between num or text, just used in icon_state strings var/fluid_id = null var/fluid_max_volume = 50 @@ -18,48 +19,49 @@ var/aroused_state = FALSE //Boolean used in icon_state strings var/aroused_amount = 50 //This is a num from 0 to 100 for arousal percentage for when to use arousal state icons. var/obj/item/organ/genital/linked_organ + var/linked_organ_slot //only one of the two organs needs this to be set up. update_link() will handle linking the rest. var/through_clothes = FALSE var/internal = FALSE var/hidden = FALSE + 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() . = ..() - if(!reagents) + if(fluid_id) create_reagents(fluid_max_volume) + if(producing) + reagents.add_reagent(fluid_id, fluid_max_volume) update() /obj/item/organ/genital/Destroy() - remove_ref() + if(linked_organ) + update_link(TRUE)//this should remove any other links it has if(owner) - Remove(owner, 1)//this should remove references to it, so it can be GCd correctly - update_link()//this should remove any other links it has + Remove(owner, TRUE)//this should remove references to it, so it can be GCd correctly return ..() -/obj/item/organ/genital/proc/update() +/obj/item/organ/genital/proc/update(removing = FALSE) if(QDELETED(src)) return update_size() update_appearance() - update_link() + if(linked_organ_slot || (linked_organ && removing)) + update_link(removing) //exposure and through-clothing code /mob/living/carbon var/list/exposed_genitals = list() //Keeping track of them so we don't have to iterate through every genitalia and see if exposed /obj/item/organ/genital/proc/is_exposed() - if(!owner) - return FALSE - if(hidden) - return FALSE - if(internal) + if(!owner || hidden || internal) return FALSE if(through_clothes) return TRUE switch(zone) //update as more genitals are added - if("chest") + if(BODY_ZONE_CHEST) return owner.is_chest_exposed() - if("groin") + if(BODY_ZONE_PRECISE_GROIN) return owner.is_groin_exposed() return FALSE @@ -107,22 +109,37 @@ picked_organ.toggle_visibility(picked_visibility) return - - - /obj/item/organ/genital/proc/update_size() return /obj/item/organ/genital/proc/update_appearance() return -/obj/item/organ/genital/proc/update_link() - return +/obj/item/organ/genital/on_life() + if(!reagents || !owner) + return + reagents.maximum_volume = fluid_max_volume + if(fluid_id && producing) + generate_fluid() -/obj/item/organ/genital/proc/remove_ref() - if(linked_organ) - linked_organ.linked_organ = null +/obj/item/organ/genital/proc/generate_fluid() + if(owner.stat != DEAD && reagents.total_volume < reagents.maximum_volume) + reagents.isolate_reagent(fluid_id)//remove old reagents if it changed and just clean up generally + reagents.add_reagent(fluid_id, (fluid_mult * fluid_rate))//generate the cum + return TRUE + return FALSE + +/obj/item/organ/genital/proc/update_link(removing = FALSE) + if(!removing && owner) + linked_organ = owner.getorganslot(linked_organ_slot) + if(linked_organ) + linked_organ.linked_organ = src + return TRUE + else + if(linked_organ) + linked_organ.linked_organ = null linked_organ = null + return FALSE /obj/item/organ/genital/Insert(mob/living/carbon/M, special = 0) ..() @@ -130,127 +147,42 @@ /obj/item/organ/genital/Remove(mob/living/carbon/M, special = 0) ..() - update() + update(TRUE) //proc to give a player their genitals and stuff when they log in -/mob/living/carbon/human/proc/give_genitals(clean=0)//clean will remove all pre-existing genitals. proc will then give them any genitals that are enabled in their DNA +/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) - var/obj/item/organ/genital/GtoClean - for(GtoClean in internal_organs) - qdel(GtoClean) + for(var/obj/item/organ/genital/G in internal_organs) + qdel(G) if (NOGENITALS in dna.species.species_traits) return - //Order should be very important. FIRST vagina, THEN testicles, THEN penis, as this affects the order they are rendered in. if(dna.features["has_vag"]) - give_vagina() + give_genital(/obj/item/organ/genital/vagina) if(dna.features["has_womb"]) - give_womb() + give_genital(/obj/item/organ/genital/womb) if(dna.features["has_balls"]) - give_balls() + give_genital(/obj/item/organ/genital/testicles) if(dna.features["has_breasts"]) // since we have multi-boobs as a thing, we'll want to at least draw over these. but not over the pingas. - give_breasts() + give_genital(/obj/item/organ/genital/breasts) if(dna.features["has_cock"]) - give_penis() + give_genital(/obj/item/organ/genital/penis) + /* if(dna.features["has_ovi"]) - give_ovipositor() + give_genital(/obj/item/organ/genital/ovipositor) if(dna.features["has_eggsack"]) - give_eggsack() + give_genital(/obj/item/organ/genital/eggsack) + */ -/mob/living/carbon/human/proc/give_penis() - if(!dna) +/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 - if(NOGENITALS in dna.species.species_traits) - return FALSE - if(!getorganslot("penis")) - var/obj/item/organ/genital/penis/P = new - P.Insert(src) - if(P) - if(dna.species.use_skintones && dna.features["genitals_use_skintone"]) - P.color = "#[skintone2hex(skin_tone)]" - else - P.color = "#[dna.features["cock_color"]]" - P.length = dna.features["cock_length"] - P.girth_ratio = dna.features["cock_girth_ratio"] - P.shape = dna.features["cock_shape"] - P.update() + G = new + if(istype(G, /obj/item/organ/genital)) //badminnery-proofing. + G.get_features(src) + G.Insert(src) -/mob/living/carbon/human/proc/give_balls() - if(!dna) - return FALSE - if(NOGENITALS in dna.species.species_traits) - return FALSE - if(!getorganslot("testicles")) - var/obj/item/organ/genital/testicles/T = new - T.Insert(src) - if(T) - if(dna.species.use_skintones && dna.features["genitals_use_skintone"]) - T.color = "#[skintone2hex(skin_tone)]" - else - T.color = "#[dna.features["balls_color"]]" - T.size = dna.features["balls_size"] - T.sack_size = dna.features["balls_sack_size"] - T.shape = dna.features["balls_shape"] - if(dna.features["balls_shape"] == "Hidden") - T.internal = TRUE - else - T.internal = FALSE - T.fluid_id = dna.features["balls_fluid"] - T.fluid_rate = dna.features["balls_cum_rate"] - T.fluid_mult = dna.features["balls_cum_mult"] - T.fluid_efficiency = dna.features["balls_efficiency"] - T.update() - -/mob/living/carbon/human/proc/give_breasts() - if(!dna) - return FALSE - if(NOGENITALS in dna.species.species_traits) - return FALSE - if(!getorganslot("breasts")) - var/obj/item/organ/genital/breasts/B = new - B.Insert(src) - if(B) - if(dna.species.use_skintones && dna.features["genitals_use_skintone"]) - B.color = "#[skintone2hex(skin_tone)]" - else - B.color = "#[dna.features["breasts_color"]]" - B.size = dna.features["breasts_size"] - B.shape = dna.features["breasts_shape"] - B.fluid_id = dna.features["breasts_fluid"] - B.update() - - -/mob/living/carbon/human/proc/give_ovipositor() +/obj/item/organ/genital/proc/get_features(datum/dna/D) return -/mob/living/carbon/human/proc/give_eggsack() - return - -/mob/living/carbon/human/proc/give_vagina() - if(!dna) - return FALSE - if(NOGENITALS in dna.species.species_traits) - return FALSE - if(!getorganslot("vagina")) - var/obj/item/organ/genital/vagina/V = new - V.Insert(src) - if(V) - if(dna.species.use_skintones && dna.features["genitals_use_skintone"]) - V.color = "#[skintone2hex(skin_tone)]" - else - V.color = "[dna.features["vag_color"]]" - V.shape = "[dna.features["vag_shape"]]" - V.update() - -/mob/living/carbon/human/proc/give_womb() - if(!dna) - return FALSE - if(NOGENITALS in dna.species.species_traits) - return FALSE - if(!getorganslot("womb")) - var/obj/item/organ/genital/womb/W = new - W.Insert(src) - if(W) - W.update() - /datum/species/proc/genitals_layertext(layer) switch(layer) @@ -267,7 +199,7 @@ if(ishuman(user)) var/mob/living/carbon/human/H = user H.update_genitals() - ..() + . = ..() /mob/living/carbon/human/doUnEquip(obj/item/I, force) . = ..() @@ -276,20 +208,16 @@ update_genitals() /mob/living/carbon/human/proc/update_genitals() - if(src && !QDELETED(src)) + if(!QDELETED(src)) dna.species.handle_genitals(src) /datum/species/proc/handle_genitals(mob/living/carbon/human/H) if(!H)//no args CRASH("H = null") - if(!LAZYLEN(H.internal_organs))//if they have no organs, we're done - return - if(NOGENITALS in species_traits)//golems and such - return - if(HAS_TRAIT(H, TRAIT_HUSK)) + if(!LAZYLEN(H.internal_organs) || (NOGENITALS in species_traits) || HAS_TRAIT(H, TRAIT_HUSK)) return - var/list/genitals_to_add = list() + var/list/genitals_to_add[GENITAL_LAYER_INDEX_LENGTH] var/list/relevant_layers = list(GENITALS_BEHIND_LAYER, GENITALS_ADJ_LAYER, GENITALS_FRONT_LAYER) var/list/standing = list() var/size @@ -300,18 +228,16 @@ //start scanning for genitals //var/list/worn_stuff = H.get_equipped_items()//cache this list so it's not built again - for(var/obj/item/organ/O in H.internal_organs) - if(isgenital(O)) - var/obj/item/organ/genital/G = O - if(G.hidden) - return //we're gunna just hijack this for updates. - if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes - genitals_to_add += H.getorganslot(G.slot) + for(var/obj/item/organ/genital/G in H.internal_organs) + if(G.hidden) + return //we're gunna just hijack this for updates. + if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes + LAZYADD(genitals_to_add[G.layer_index], G) //Now we added all genitals that aren't internal and should be rendered //start applying overlays for(var/layer in relevant_layers) - var/layertext = genitals_layertext(layer) + var/layertext = flatten_list(genitals_layertext(layer)) for(var/obj/item/organ/genital/G in genitals_to_add) var/datum/sprite_accessory/S size = G.size @@ -357,3 +283,4 @@ for(var/L in relevant_layers) H.apply_overlay(L) + diff --git a/modular_citadel/code/modules/arousal/organs/breasts.dm b/modular_citadel/code/modules/arousal/organs/breasts.dm index 1223f0b616..f6d5673a53 100644 --- a/modular_citadel/code/modules/arousal/organs/breasts.dm +++ b/modular_citadel/code/modules/arousal/organs/breasts.dm @@ -1,38 +1,20 @@ /obj/item/organ/genital/breasts - name = "breasts" - desc = "Female milk producing organs." - icon_state = "breasts" - icon = 'modular_citadel/icons/obj/genitals/breasts.dmi' - zone = "chest" - slot = "breasts" - size = BREASTS_SIZE_DEF - fluid_id = "milk" - var/amount = 2 - producing = TRUE - shape = "pair" - can_masturbate_with = TRUE - masturbation_verb = "massage" - can_climax = TRUE - fluid_transfer_factor = 0.5 - -/obj/item/organ/genital/breasts/Initialize() - . = ..() - reagents.add_reagent(fluid_id, fluid_max_volume) - -/obj/item/organ/genital/breasts/on_life() - if(QDELETED(src)) - return - if(!reagents || !owner) - return - reagents.maximum_volume = fluid_max_volume - if(fluid_id && producing) - generate_milk() - -/obj/item/organ/genital/breasts/proc/generate_milk() - if(owner.stat == DEAD) - return FALSE - reagents.isolate_reagent(fluid_id) - reagents.add_reagent(fluid_id, (fluid_mult * fluid_rate)) + name = "breasts" + desc = "Female milk producing organs." + icon_state = "breasts" + icon = 'modular_citadel/icons/obj/genitals/breasts.dmi' + zone = BODY_ZONE_CHEST + slot = ORGAN_SLOT_BREASTS + size = BREASTS_SIZE_DEF + fluid_id = "milk" + var/amount = 2 + producing = TRUE + shape = "pair" + can_masturbate_with = TRUE + masturbation_verb = "massage" + orgasm_verb = "leaking" + can_climax = TRUE + fluid_transfer_factor = 0.5 /obj/item/organ/genital/breasts/update_appearance() var/lowershape = lowertext(shape) @@ -65,3 +47,13 @@ var/mob/living/carbon/human/H = owner icon_state = sanitize_text(string) H.update_genitals() + +/obj/item/organ/genital/breasts/get_features(mob/living/carbon/human/H) + var/datum/dna/D = H.dna + if(D.species.use_skintones && D.features["genitals_use_skintone"]) + color = "#[skintone2hex(H.skin_tone)]" + else + color = "#[D.features["breasts_color"]]" + size = D.features["breasts_size"] + shape = D.features["breasts_shape"] + fluid_id = D.features["breasts_fluid"] diff --git a/modular_citadel/code/modules/arousal/organs/eggsack.dm b/modular_citadel/code/modules/arousal/organs/eggsack.dm index 402d246e40..3282bad5f9 100644 --- a/modular_citadel/code/modules/arousal/organs/eggsack.dm +++ b/modular_citadel/code/modules/arousal/organs/eggsack.dm @@ -1,14 +1,14 @@ /obj/item/organ/genital/eggsack - name = "Egg sack" - desc = "An egg producing reproductive organ." - icon_state = "egg_sack" - icon = 'modular_citadel/icons/obj/genitals/ovipositor.dmi' - zone = "groin" - slot = "testicles" - color = null //don't use the /genital color since it already is colored + name = "Egg sack" + desc = "An egg producing reproductive organ." + icon_state = "egg_sack" + icon = 'modular_citadel/icons/obj/genitals/ovipositor.dmi' + zone = BODY_ZONE_PRECISE_GROIN + slot = ORGAN_SLOT_TESTICLES + linked_organ_slot = ORGAN_SLOT_PENIS + color = null //don't use the /genital color since it already is colored internal = TRUE var/egg_girth = EGG_GIRTH_DEF var/cum_mult = CUM_RATE_MULT var/cum_rate = CUM_RATE var/cum_efficiency = CUM_EFFICIENCY - var/obj/item/organ/ovipositor/linked_ovi diff --git a/modular_citadel/code/modules/arousal/organs/genitals_sprite_accessories.dm b/modular_citadel/code/modules/arousal/organs/genitals_sprite_accessories.dm index b913a90fb6..4ba2e373a2 100644 --- a/modular_citadel/code/modules/arousal/organs/genitals_sprite_accessories.dm +++ b/modular_citadel/code/modules/arousal/organs/genitals_sprite_accessories.dm @@ -5,11 +5,9 @@ //DICKS,COCKS,PENISES,WHATEVER YOU WANT TO CALL THEM /datum/sprite_accessory/penis icon = 'modular_citadel/icons/obj/genitals/penis_onmob.dmi' - icon_state = null name = "penis" //the preview name of the accessory - gender_specific = 0 //Might be needed somewhere down the list. color_src = "cock_color" - locked = 0 + alt_aroused = TRUE /datum/sprite_accessory/penis/human icon_state = "human" @@ -62,27 +60,21 @@ icon_state = "testicle" name = "testicle" //the preview name of the accessory color_src = "balls_color" - locked = 0 /datum/sprite_accessory/testicles/hidden - icon_state = "hidden" + icon_state = "none" name = "Hidden" - alt_aroused = TRUE /datum/sprite_accessory/testicles/single icon_state = "single" name = "Single" - alt_aroused = TRUE //Vaginas /datum/sprite_accessory/vagina icon = 'modular_citadel/icons/obj/genitals/vagina_onmob.dmi' icon_state = null name = "vagina" - gender_specific = 0 color_src = "vag_color" - locked = 0 - alt_aroused = FALSE //if this is TRUE, then the genitals will use an alternate sprite for aroused states /datum/sprite_accessory/vagina/human icon_state = "human" @@ -114,35 +106,28 @@ //BREASTS BE HERE /datum/sprite_accessory/breasts icon = 'modular_citadel/icons/obj/genitals/breasts_onmob.dmi' - icon_state = null name = "breasts" - gender_specific = 0 color_src = "breasts_color" - locked = 0 + alt_aroused = TRUE /datum/sprite_accessory/breasts/pair icon_state = "pair" name = "Pair" - alt_aroused = TRUE /datum/sprite_accessory/breasts/quad icon_state = "quad" name = "Quad" - alt_aroused = TRUE /datum/sprite_accessory/breasts/sextuple icon_state = "sextuple" name = "Sextuple" - alt_aroused = TRUE //OVIPOSITORS BE HERE /datum/sprite_accessory/ovipositor icon = 'modular_citadel/icons/obj/genitals/penis_onmob.dmi' icon_state = null name = "Ovipositor" //the preview name of the accessory - gender_specific = 0 //Might be needed somewhere down the list. color_src = "cock_color" - locked = 0 /datum/sprite_accessory/ovipositor/knotted icon_state = "knotted" diff --git a/modular_citadel/code/modules/arousal/organs/ovipositor.dm b/modular_citadel/code/modules/arousal/organs/ovipositor.dm index 76bf60d93c..92b608f905 100644 --- a/modular_citadel/code/modules/arousal/organs/ovipositor.dm +++ b/modular_citadel/code/modules/arousal/organs/ovipositor.dm @@ -3,14 +3,13 @@ desc = "An egg laying reproductive organ." icon_state = "ovi_knotted_2" icon = 'modular_citadel/icons/obj/genitals/ovipositor.dmi' - zone = "groin" - slot = "penis" - w_class = 3 + zone = BODY_ZONE_PRECISE_GROIN + slot = ORGAN_SLOT_PENIS shape = "knotted" size = 3 + layer_index = PENIS_LAYER_INDEX var/length = 6 //inches var/girth = 0 var/girth_ratio = COCK_GIRTH_RATIO_DEF //citadel_defines.dm for these defines var/knot_girth_ratio = KNOT_GIRTH_RATIO_DEF var/list/oviflags = list() - var/obj/item/organ/eggsack/linked_eggsack diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/modular_citadel/code/modules/arousal/organs/penis.dm index b6cb8fa4b2..2593460a32 100644 --- a/modular_citadel/code/modules/arousal/organs/penis.dm +++ b/modular_citadel/code/modules/arousal/organs/penis.dm @@ -1,22 +1,23 @@ /obj/item/organ/genital/penis - name = "penis" - desc = "A male reproductive organ." - icon_state = "penis" - icon = 'modular_citadel/icons/obj/genitals/penis.dmi' - zone = "groin" - slot = ORGAN_SLOT_PENIS - can_masturbate_with = TRUE - masturbation_verb = "stroke" - can_climax = TRUE - fluid_transfer_factor = 0.5 - size = 2 //arbitrary value derived from length and girth for sprites. - var/length = 6 //inches - var/cached_length //used to detect a change in length - var/girth = 0 - var/girth_ratio = COCK_GIRTH_RATIO_DEF //0.73; check citadel_defines.dm - var/knot_girth_ratio = KNOT_GIRTH_RATIO_DEF - var/list/dickflags = list() - var/list/knotted_types = list("knotted", "barbed, knotted") + name = "penis" + desc = "A male reproductive organ." + icon_state = "penis" + icon = 'modular_citadel/icons/obj/genitals/penis.dmi' + zone = BODY_ZONE_PRECISE_GROIN + slot = ORGAN_SLOT_PENIS + can_masturbate_with = TRUE + masturbation_verb = "stroke" + can_climax = TRUE + fluid_transfer_factor = 0.5 + size = 2 //arbitrary value derived from length and girth for sprites. + layer_index = PENIS_LAYER_INDEX + var/length = 6 //inches + var/cached_length //used to detect a change in length + var/girth = 0 + var/girth_ratio = COCK_GIRTH_RATIO_DEF //0.73; check citadel_defines.dm + var/knot_girth_ratio = KNOT_GIRTH_RATIO_DEF + var/list/dickflags = list() + var/list/knotted_types = list("knotted", "barbed, knotted") /obj/item/organ/genital/penis/update_size() if(length == cached_length) @@ -38,7 +39,7 @@ /obj/item/organ/genital/penis/update_appearance() var/string var/lowershape = lowertext(shape) - desc = "You see [aroused_state ? "an erect" : "a flaccid"] [lowershape] penis. You estimate it's about [round(length, 0.25)] inch[round(length, 0.25) != 1 ? "es" : ""] long and [round(girth, 0.25)] inch[round(girth, 0.25) != 1 ? "es" : ""] in girth." + desc = "You see [aroused_state ? "an erect" : "a flaccid"] [lowershape] [name]. You estimate it's about [round(length, 0.25)] inch[round(length, 0.25) != 1 ? "es" : ""] long and [round(girth, 0.25)] inch[round(girth, 0.25) != 1 ? "es" : ""] in girth." if(owner) if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"]) @@ -54,13 +55,12 @@ icon_state = sanitize_text(string) H.update_genitals() -/obj/item/organ/genital/penis/update_link() - if(owner) - linked_organ = (owner.getorganslot("testicles")) - if(linked_organ) - linked_organ.linked_organ = src - linked_organ.size = size +/obj/item/organ/genital/penis/get_features(mob/living/carbon/human/H) + var/datum/dna/D = H.dna + if(D.species.use_skintones && D.features["genitals_use_skintone"]) + color = "#[skintone2hex(H.skin_tone)]" else - if(linked_organ) - linked_organ.linked_organ = null - linked_organ = null + color = "#[D.features["cock_color"]]" + length = D.features["cock_length"] + girth_ratio = D.features["cock_girth_ratio"] + shape = D.features["cock_shape"] diff --git a/modular_citadel/code/modules/arousal/organs/testicles.dm b/modular_citadel/code/modules/arousal/organs/testicles.dm index 1e6b4d62d4..de7b6d6f70 100644 --- a/modular_citadel/code/modules/arousal/organs/testicles.dm +++ b/modular_citadel/code/modules/arousal/organs/testicles.dm @@ -1,56 +1,34 @@ /obj/item/organ/genital/testicles - name = "testicles" - desc = "A male reproductive organ." - icon_state = "testicles" - icon = 'modular_citadel/icons/obj/genitals/testicles.dmi' - zone = "groin" - slot = "testicles" - size = BALLS_SIZE_MIN - var/size_name = "average" - shape = "single" - var/sack_size = BALLS_SACK_SIZE_DEF - fluid_id = "semen" - producing = TRUE - can_masturbate_with = FALSE - masturbation_verb = "massage" - can_climax = TRUE - var/sent_full_message = TRUE //defaults to 1 since they're full to start + name = "testicles" + desc = "A male reproductive organ." + icon_state = "testicles" + icon = 'modular_citadel/icons/obj/genitals/testicles.dmi' + zone = BODY_ZONE_PRECISE_GROIN + slot = ORGAN_SLOT_TESTICLES + size = BALLS_SIZE_MIN + linked_organ_slot = ORGAN_SLOT_PENIS + var/size_name = "average" + shape = "single" + var/sack_size = BALLS_SACK_SIZE_DEF + fluid_id = "semen" + producing = TRUE + can_masturbate_with = MASTURBATE_LINKED_ORGAN + masturbation_verb = "massage" + layer_index = TESTICLES_LAYER_INDEX + var/size_linked = FALSE -/obj/item/organ/genital/testicles/Initialize() +/obj/item/organ/genital/testicles/generate_fluid() + if(!linked_organ && !update_link()) + return FALSE . = ..() - reagents.add_reagent(fluid_id, fluid_max_volume) + if(.) + send_full_message() -/obj/item/organ/genital/testicles/on_life() - if(QDELETED(src)) - return - if(reagents && producing) - generate_cum() - -/obj/item/organ/genital/testicles/proc/generate_cum() - reagents.maximum_volume = fluid_max_volume - if(reagents.total_volume >= reagents.maximum_volume) - if(!sent_full_message) - send_full_message() - sent_full_message = TRUE - return FALSE - sent_full_message = FALSE - update_link() - if(!linked_organ) - return FALSE - reagents.isolate_reagent(fluid_id)//remove old reagents if it changed and just clean up generally - reagents.add_reagent(fluid_id, (fluid_mult * fluid_rate))//generate the cum - -/obj/item/organ/genital/testicles/update_link() - if(owner && !QDELETED(src)) - linked_organ = (owner.getorganslot("penis")) - if(linked_organ) - linked_organ.linked_organ = src - size = linked_organ.size - - else - if(linked_organ) - linked_organ.linked_organ = null - linked_organ = null +/obj/item/organ/genital/testicles/update_link(removing = FALSE) + . = ..() + if(. && !size_linked) + size = linked_organ.size + size_linked = TRUE /obj/item/organ/genital/testicles/proc/send_full_message(msg = "Your balls finally feel full, again.") if(owner && istext(msg)) @@ -59,19 +37,16 @@ /obj/item/organ/genital/testicles/update_appearance() switch(size) - if(0.1 to 1) + if(BALLS_SIZE_MIN) size_name = "average" - if(1.1 to 2) + if(BALLS_SIZE_DEF) size_name = "enlarged" - if(2.1 to INFINITY) + if(BALLS_SIZE_MAX) size_name = "engorged" else size_name = "nonexistant" - if(!internal) - desc = "You see an [size_name] pair of testicles." - else - desc = "They don't have any testicles you can see." + desc = "You see an [size_name] pair of testicles." if(owner) var/string @@ -87,3 +62,21 @@ var/mob/living/carbon/human/H = owner icon_state = sanitize_text(string) H.update_genitals() + +/obj/item/organ/genital/testicles/get_features(mob/living/carbon/human/H) + var/datum/dna/D = H.dna + if(D.species.use_skintones && D.features["genitals_use_skintone"]) + color = "#[skintone2hex(H.skin_tone)]" + else + color = "#[D.features["balls_color"]]" + size = D.features["balls_size"] + sack_size = D.features["balls_sack_size"] + shape = D.features["balls_shape"] + if(D.features["balls_shape"] == "Hidden") + internal = TRUE + else + internal = FALSE + fluid_id = D.features["balls_fluid"] + fluid_rate = D.features["balls_cum_rate"] + fluid_mult = D.features["balls_cum_mult"] + fluid_efficiency = D.features["balls_efficiency"] diff --git a/modular_citadel/code/modules/arousal/organs/vagina.dm b/modular_citadel/code/modules/arousal/organs/vagina.dm index 8c15aa5437..af2beb5f79 100644 --- a/modular_citadel/code/modules/arousal/organs/vagina.dm +++ b/modular_citadel/code/modules/arousal/organs/vagina.dm @@ -1,25 +1,24 @@ /obj/item/organ/genital/vagina - name = "vagina" - desc = "A female reproductive organ." - icon = 'modular_citadel/icons/obj/genitals/vagina.dmi' - icon_state = "vagina" - zone = "groin" - slot = "vagina" - size = 1 //There is only 1 size right now - can_masturbate_with = TRUE - masturbation_verb = "finger" - can_climax = TRUE + name = "vagina" + desc = "A female reproductive organ." + icon = 'modular_citadel/icons/obj/genitals/vagina.dmi' + icon_state = ORGAN_SLOT_VAGINA + zone = BODY_ZONE_PRECISE_GROIN + slot = "vagina" + size = 1 //There is only 1 size right now + can_masturbate_with = TRUE + masturbation_verb = "finger" + can_climax = TRUE fluid_transfer_factor = 0.1 //Yes, some amount is exposed to you, go get your AIDS - w_class = 3 - var/cap_length = 8//D E P T H (cap = capacity) - var/cap_girth = 12 + layer_index = VAGINA_LAYER_INDEX + var/cap_length = 8//D E P T H (cap = capacity) + var/cap_girth = 12 var/cap_girth_ratio = 1.5 - var/clits = 1 - var/clit_diam = 0.25 - var/clit_len = 0.25 + var/clits = 1 + var/clit_diam = 0.25 + var/clit_len = 0.25 var/list/vag_types = list("tentacle", "dentata", "hairy", "spade", "furred") - /obj/item/organ/genital/vagina/update_appearance() var/string //Keeping this code here, so making multiple sprites for the different kinds is easier. var/lowershape = lowertext(shape) @@ -63,12 +62,10 @@ icon_state = sanitize_text(string) H.update_genitals() -/obj/item/organ/genital/vagina/update_link() - if(owner) - linked_organ = (owner.getorganslot("womb")) - if(linked_organ) - linked_organ.linked_organ = src +/obj/item/organ/genital/vagina/get_features(mob/living/carbon/human/H) + var/datum/dna/D = H.dna + if(D.species.use_skintones && D.features["genitals_use_skintone"]) + color = "#[skintone2hex(H.skin_tone)]" else - if(linked_organ) - linked_organ.linked_organ = null - linked_organ = null + color = "[D.features["vag_color"]]" + shape = "[D.features["vag_shape"]]" diff --git a/modular_citadel/code/modules/arousal/organs/womb.dm b/modular_citadel/code/modules/arousal/organs/womb.dm index 686d9059a0..d99206d0f1 100644 --- a/modular_citadel/code/modules/arousal/organs/womb.dm +++ b/modular_citadel/code/modules/arousal/organs/womb.dm @@ -1,41 +1,11 @@ /obj/item/organ/genital/womb - name = "womb" - desc = "A female reproductive organ." - icon = 'modular_citadel/icons/obj/genitals/vagina.dmi' - icon_state = "womb" - zone = "groin" - slot = "womb" - internal = TRUE - fluid_id = "femcum" - producing = TRUE - -/obj/item/organ/genital/womb/Initialize() - . = ..() - reagents.add_reagent(fluid_id, fluid_max_volume) - -/obj/item/organ/genital/womb/on_life() - if(QDELETED(src)) - return - if(reagents && producing) - generate_femcum() - -/obj/item/organ/genital/womb/proc/generate_femcum() - reagents.maximum_volume = fluid_max_volume - update_link() - if(!linked_organ) - return FALSE - reagents.isolate_reagent(fluid_id)//remove old reagents if it changed and just clean up generally - reagents.add_reagent(fluid_id, (fluid_mult * fluid_rate))//generate the cum - -/obj/item/organ/genital/womb/update_link() - if(owner) - linked_organ = (owner.getorganslot("vagina")) - if(linked_organ) - linked_organ.linked_organ = src - else - if(linked_organ) - linked_organ.linked_organ = null - linked_organ = null - -/obj/item/organ/genital/womb/Destroy() - return ..() + name = "womb" + desc = "A female reproductive organ." + icon = 'modular_citadel/icons/obj/genitals/vagina.dmi' + icon_state = "womb" + zone = BODY_ZONE_PRECISE_GROIN + slot = ORGAN_SLOT_WOMB + internal = TRUE + fluid_id = "femcum" + producing = TRUE + linked_organ_slot = ORGAN_SLOT_VAGINA \ No newline at end of file diff --git a/modular_citadel/code/modules/client/preferences_savefile.dm b/modular_citadel/code/modules/client/preferences_savefile.dm index 2921f70684..be9e92d4c3 100644 --- a/modular_citadel/code/modules/client/preferences_savefile.dm +++ b/modular_citadel/code/modules/client/preferences_savefile.dm @@ -32,7 +32,6 @@ WRITE_FILE(S["feature_ipc_antenna"], features["ipc_antenna"]) //Citadel WRITE_FILE(S["feature_genitals_use_skintone"], features["genitals_use_skintone"]) - WRITE_FILE(S["feature_exhibitionist"], features["exhibitionist"]) WRITE_FILE(S["feature_mcolor2"], features["mcolor2"]) WRITE_FILE(S["feature_mcolor3"], features["mcolor3"]) WRITE_FILE(S["feature_mam_body_markings"], features["mam_body_markings"]) diff --git a/modular_citadel/code/modules/mob/living/carbon/human/life.dm b/modular_citadel/code/modules/mob/living/carbon/human/life.dm index e728d70c97..fbaa1b4b58 100644 --- a/modular_citadel/code/modules/mob/living/carbon/human/life.dm +++ b/modular_citadel/code/modules/mob/living/carbon/human/life.dm @@ -1,7 +1,7 @@ -/mob/living/carbon/human/Life() +/mob/living/carbon/human/Life(seconds, times_fired) //citadel code if(stat != DEAD) - handle_arousal() + handle_arousal(times_fired) . = ..() /mob/living/carbon/human/calculate_affecting_pressure(pressure) diff --git a/modular_citadel/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/modular_citadel/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index fa6ded8065..0e6c12053a 100644 --- a/modular_citadel/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/modular_citadel/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -78,42 +78,30 @@ else H.facial_hair_style = "Shaved" //handle normal hair - var/new_style = input(owner, "Select a hair style", "Hair Alterations") as null|anything in GLOB.hair_styles_list + var/new_style = input(owner, "Select a hair style", "Hair Alterations") as null|anything in GLOB.hair_styles_list if(new_style) H.hair_style = new_style H.update_hair() else if (select_alteration == "Genitals") - var/list/organs = list() var/operation = input("Select organ operation.", "Organ Manipulation", "cancel") in list("add sexual organ", "remove sexual organ", "cancel") switch(operation) if("add sexual organ") - var/new_organ = input("Select sexual organ:", "Organ Manipulation") in list("Penis", "Testicles", "Breasts", "Vagina", "Womb", "Cancel") - if(new_organ == "Penis") - H.give_penis() - else if(new_organ == "Testicles") - H.give_balls() - else if(new_organ == "Breasts") - H.give_breasts() - else if(new_organ == "Vagina") - H.give_vagina() - else if(new_organ == "Womb") - H.give_womb() - else + var/new_organ = input("Select sexual organ:", "Organ Manipulation") as null|anything in GLOB.genitals_list + if(!new_organ) return + H.give_genital(GLOB.genitals_list[new_organ]) + if("remove sexual organ") + var/list/organs = list() for(var/obj/item/organ/genital/X in H.internal_organs) var/obj/item/organ/I = X organs["[I.name] ([I.type])"] = I - var/obj/item/organ = input("Select sexual organ:", "Organ Manipulation", null) in organs - organ = organs[organ] - if(!organ) + var/obj/item/O = input("Select sexual organ:", "Organ Manipulation", null) as null|anything in organs + var/obj/item/organ/genital/G = organs[O] + if(!G) return - var/obj/item/organ/genital/O - if(isorgan(organ)) - O = organ - O.Remove(H) - organ.forceMove(get_turf(H)) - qdel(organ) + G.forceMove(get_turf(H)) + qdel(G) H.update_genitals() else if (select_alteration == "Ears") @@ -203,8 +191,8 @@ if(new_shape) H.dna.features["cock_shape"] = new_shape H.update_genitals() - H.give_balls() - H.give_penis() + H.give_genital(/obj/item/organ/genital/testicles) + H.give_genital(/obj/item/organ/genital/penis) H.apply_overlay() @@ -216,8 +204,8 @@ if(new_shape) H.dna.features["vag_shape"] = new_shape H.update_genitals() - H.give_womb() - H.give_vagina() + H.give_genital(/obj/item/organ/genital/womb) + H.give_genital(/obj/item/organ/genital/vagina) H.apply_overlay() else if (select_alteration == "Penis Length") @@ -229,8 +217,8 @@ H.dna.features["cock_length"] = max(min( round(text2num(new_length)), COCK_SIZE_MAX),COCK_SIZE_MIN) H.update_genitals() H.apply_overlay() - H.give_balls() - H.give_penis() + H.give_genital(/obj/item/organ/genital/testicles) + H.give_genital(/obj/item/organ/genital/penis) else if (select_alteration == "Breast Size") for(var/obj/item/organ/genital/breasts/X in H.internal_organs) @@ -241,7 +229,7 @@ H.dna.features["breasts_size"] = new_size H.update_genitals() H.apply_overlay() - H.give_breasts() + H.give_genital(/obj/item/organ/genital/breasts) else if (select_alteration == "Breast Shape") for(var/obj/item/organ/genital/breasts/X in H.internal_organs) @@ -252,7 +240,7 @@ H.dna.features["breasts_shape"] = new_shape H.update_genitals() H.apply_overlay() - H.give_breasts() + H.give_genital(/obj/item/organ/genital/breasts) else return diff --git a/modular_citadel/icons/obj/genitals/testicles_onmob.dmi b/modular_citadel/icons/obj/genitals/testicles_onmob.dmi index 33659cf13cb42239e1fc3a2e8ccf3c02ff42ea26..7d4d2610c5337d0877fd9d741c38998893444576 100644 GIT binary patch delta 554 zcmV+_0@eNZ1+oNFiBL{Q4GJ0x0000DNk~Le0002s0002s1Oos70O$jE(f|Me6;Mo6 zMZmzo)YR1W-sjr1vg+B~<;Kgvz`!ul@9_Wt00DGTPE!Ct=GbNc0069!P!xZXK@Ng2 z5JlJRDH>R7D0S;X(nf0{S7?ZgbP~jbY4rMn96%j*|1aLWWNscbK#O z0#@$iYx_T2a;4=8so_e^3aNkI5PRSW)%=P1;ss^T%om#<#JO^{{k;Ag^Y-h|ENe+x z0003KNklWH z0{{ScN7EDnhj1SI-)!9Z91`bg`8@W&Qv3Ol7Ooo@9n-wF?mhqjfL~KOPl3|@=eOt( z>Rs-CrOOx!W*g?^{#Q;qT`!@(rFs|pU#UH=dqDsIfK9~y_m>fcVL2W9Usev-kIU)Y s|Dvz*52)AWbcOymyHKorp9v561}X^=h=s}*u>b%707*qoM6N<$f}&*w)Bpeg literal 759 zcmeAS@N?(olHy`uVBq!ia0y~yU~B+k7G|JG*vl0?KuRdUC&cx@fdf~rT={nI`K>LR zUfsO&^w{Z}CW78TS;mqezhDN3XE)M-oG(=&5hX6E#mPmP1tppJc?=8{bCynXw_}%}Keknxc>Bd#9`$GO? z9)BR;e53oW+2c1)Z@*a9J86#PYin`)*#fgOmZu8kcKo|_JE2K_*S%SHQl2e1&zZhf z{%{Rn`u2@GZ&%L!&r&RM#wT#zs;Fewz_3NjgiNQh1bZ5Uu2|{hD|#?Q(C4#n!)NP- z8BO9-%F->wcWgY;tNQa?i^=0-T;^da$*q#s_qUZDPEaktG3V{ggSm$s1Xu&4 zgB$KLE@E<-WX-PC@UPl)$(%h6ZCCpa3cY`tlKC$s{Lz=~uYtkFkYUh!(81pBpVx`- z`OB>~eB%ZQGJI$}wqdT`v&o;$wO+rio3%>p+tG?_yIK5e-!p9u`!37`QuD(l@#d`A z?@xc)78+Cj{MmBNSD&?Szx*1z;9Kp3tM&^&-sP9+{(OKDr1Z(@ch950hd$r@`)5Ub zk=^e3^*>oR0onIA{jAo0KL1xGNKu36jrUEBXWxAcciQ*MX6a)^s{=U+8sE1+TYVms zBp4X(z7*lf>HhiTPw%O^x@tRi;paE^-w}Jf_Gk3ezkfdb6_ri+XBQx|!1Vq*f!GQS zpyR>1O8mck-TCwE{rFWo)}KEc|LtP4OX0zUU!D8x%Z=nDH diff --git a/tgstation.dme b/tgstation.dme index 722ebae9be..7c9fa1e899 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2844,7 +2844,6 @@ #include "modular_citadel\code\datums\mood_events\moodular.dm" #include "modular_citadel\code\datums\mutations\hulk.dm" #include "modular_citadel\code\datums\status_effects\debuffs.dm" -#include "modular_citadel\code\datums\traits\neutral.dm" #include "modular_citadel\code\datums\wires\airlock.dm" #include "modular_citadel\code\datums\wires\autoylathe.dm" #include "modular_citadel\code\game\area\cit_areas.dm" @@ -2912,9 +2911,9 @@ #include "modular_citadel\code\modules\admin\secrets.dm" #include "modular_citadel\code\modules\admin\topic.dm" #include "modular_citadel\code\modules\arousal\arousal.dm" +#include "modular_citadel\code\modules\arousal\organs\_genitals.dm" #include "modular_citadel\code\modules\arousal\organs\breasts.dm" #include "modular_citadel\code\modules\arousal\organs\eggsack.dm" -#include "modular_citadel\code\modules\arousal\organs\genitals.dm" #include "modular_citadel\code\modules\arousal\organs\genitals_sprite_accessories.dm" #include "modular_citadel\code\modules\arousal\organs\ovipositor.dm" #include "modular_citadel\code\modules\arousal\organs\penis.dm" From fd2f2ae1af2b6192cf705a7aa21760401ab9ea4d Mon Sep 17 00:00:00 2001 From: Ghommie Date: Tue, 23 Jul 2019 07:21:03 +0200 Subject: [PATCH 02/58] update, bitflags. --- code/__DEFINES/citadel_defines.dm | 4 +- code/__HELPERS/global_lists.dm | 3 +- .../code/modules/arousal/arousal.dm | 4 +- .../code/modules/arousal/organs/_genitals.dm | 42 +++++++++---------- .../code/modules/arousal/organs/eggsack.dm | 1 + .../code/modules/arousal/organs/ovipositor.dm | 1 + .../code/modules/arousal/organs/testicles.dm | 3 +- 7 files changed, 32 insertions(+), 26 deletions(-) diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 8b75784ab2..b366a792e5 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -25,7 +25,9 @@ #define GENITAL_LAYER_INDEX_LENGTH 4 //keep it updated with each new index added, thanks. -#define MASTURBATE_LINKED_ORGAN 2 //special value used to pass our mission to the linked organ +//genital flags +#define GENITAL_BLACKLISTED (1 << 0) //for genitals that shouldn't be added to GLOB.genitals_list. +#define MASTURBATE_LINKED_ORGAN (1<<1) //used to pass our mission to the linked organ #define COCK_SIZE_MIN 1 #define COCK_SIZE_MAX 20 diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index b0b0f32345..96f2d404f8 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -64,7 +64,8 @@ for(var/gpath in subtypesof(/obj/item/organ/genital)) var/obj/item/organ/genital/G = gpath - GLOB.genitals_list[initial(G.name)] = gpath + if(!CHECK_BITFIELD(initial(G.genital_flags), GENITAL_BLACKLISTED)) + GLOB.genitals_list[initial(G.name)] = gpath //END OF CIT CHANGES //Species diff --git a/modular_citadel/code/modules/arousal/arousal.dm b/modular_citadel/code/modules/arousal/arousal.dm index 8826cb0774..924c507e7d 100644 --- a/modular_citadel/code/modules/arousal/arousal.dm +++ b/modular_citadel/code/modules/arousal/arousal.dm @@ -209,7 +209,7 @@ var/datum/reagents/fluid_source = G.climaxable(src) if(!fluid_source) return - var/obj/item/organ/genital/PP = G.can_masturbate_with == MASTURBATE_LINKED_ORGAN ? G.linked_organ : G + var/obj/item/organ/genital/PP = CHECK_BITFIELD(G.genital_flags, MASTURBATE_LINKED_ORGAN) ? G.linked_organ : G if(!PP) to_chat(src, "You shudder, unable to cum with your [name].") if(mb_time) @@ -274,7 +274,7 @@ for(var/obj/item/organ/genital/G in internal_organs) if(G.can_masturbate_with && G.is_exposed(worn_stuff)) //filter out what you can't masturbate with - if(G.can_masturbate_with == MASTURBATE_LINKED_ORGAN && !G.linked_organ) + if(CHECK_BITFIELD(G.genital_flags, MASTURBATE_LINKED_ORGAN) && !G.linked_organ) continue genitals_list += G if(genitals_list.len) diff --git a/modular_citadel/code/modules/arousal/organs/_genitals.dm b/modular_citadel/code/modules/arousal/organs/_genitals.dm index 2222624050..c4c3eaa9f1 100644 --- a/modular_citadel/code/modules/arousal/organs/_genitals.dm +++ b/modular_citadel/code/modules/arousal/organs/_genitals.dm @@ -1,28 +1,28 @@ /obj/item/organ/genital color = "#fcccb3" - w_class = WEIGHT_CLASS_NORMAL - var/shape = "human" - var/sensitivity = AROUSAL_START_VALUE - var/list/genital_flags = list() - var/can_masturbate_with = FALSE - var/masturbation_verb = "masturbate" - var/orgasm_verb = "cumming" //present continous - var/can_climax = FALSE - var/fluid_transfer_factor = 0 //How much would a partner get in them if they climax using this? - var/size = 2 //can vary between num or text, just used in icon_state strings - var/fluid_id = null - var/fluid_max_volume = 50 - var/fluid_efficiency = 1 - var/fluid_rate = 1 - var/fluid_mult = 1 - var/producing = FALSE - var/aroused_state = FALSE //Boolean used in icon_state strings - var/aroused_amount = 50 //This is a num from 0 to 100 for arousal percentage for when to use arousal state icons. + w_class = WEIGHT_CLASS_NORMAL + var/shape = "human" + var/sensitivity = AROUSAL_START_VALUE + var/genital_flags + var/can_masturbate_with = FALSE + var/masturbation_verb = "masturbate" + var/orgasm_verb = "cumming" //present continous + var/can_climax = FALSE + var/fluid_transfer_factor = 0 //How much would a partner get in them if they climax using this? + var/size = 2 //can vary between num or text, just used in icon_state strings + var/fluid_id = null + var/fluid_max_volume = 50 + var/fluid_efficiency = 1 + var/fluid_rate = 1 + var/fluid_mult = 1 + var/producing = FALSE + var/aroused_state = FALSE //Boolean used in icon_state strings + var/aroused_amount = 50 //This is a num from 0 to 100 for arousal percentage for when to use arousal state icons. var/obj/item/organ/genital/linked_organ var/linked_organ_slot //only one of the two organs needs this to be set up. update_link() will handle linking the rest. - var/through_clothes = FALSE - var/internal = FALSE - var/hidden = FALSE + var/through_clothes = FALSE + var/internal = FALSE + var/hidden = FALSE 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() diff --git a/modular_citadel/code/modules/arousal/organs/eggsack.dm b/modular_citadel/code/modules/arousal/organs/eggsack.dm index 3282bad5f9..624b2c24cd 100644 --- a/modular_citadel/code/modules/arousal/organs/eggsack.dm +++ b/modular_citadel/code/modules/arousal/organs/eggsack.dm @@ -5,6 +5,7 @@ icon = 'modular_citadel/icons/obj/genitals/ovipositor.dmi' zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_TESTICLES + genital_flags = GENITAL_BLACKLISTED //unimplemented linked_organ_slot = ORGAN_SLOT_PENIS color = null //don't use the /genital color since it already is colored internal = TRUE diff --git a/modular_citadel/code/modules/arousal/organs/ovipositor.dm b/modular_citadel/code/modules/arousal/organs/ovipositor.dm index 92b608f905..c26424d296 100644 --- a/modular_citadel/code/modules/arousal/organs/ovipositor.dm +++ b/modular_citadel/code/modules/arousal/organs/ovipositor.dm @@ -5,6 +5,7 @@ icon = 'modular_citadel/icons/obj/genitals/ovipositor.dmi' zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_PENIS + genital_flags = GENITAL_BLACKLISTED //unimplemented shape = "knotted" size = 3 layer_index = PENIS_LAYER_INDEX diff --git a/modular_citadel/code/modules/arousal/organs/testicles.dm b/modular_citadel/code/modules/arousal/organs/testicles.dm index de7b6d6f70..c67d6a49a4 100644 --- a/modular_citadel/code/modules/arousal/organs/testicles.dm +++ b/modular_citadel/code/modules/arousal/organs/testicles.dm @@ -7,12 +7,13 @@ slot = ORGAN_SLOT_TESTICLES size = BALLS_SIZE_MIN linked_organ_slot = ORGAN_SLOT_PENIS + genital_flags = MASTURBATE_LINKED_ORGAN var/size_name = "average" shape = "single" var/sack_size = BALLS_SACK_SIZE_DEF fluid_id = "semen" producing = TRUE - can_masturbate_with = MASTURBATE_LINKED_ORGAN + can_masturbate_with = TRUE masturbation_verb = "massage" layer_index = TESTICLES_LAYER_INDEX var/size_linked = FALSE From 376f6e8b4adfe74516942577a3b86de12501cb02 Mon Sep 17 00:00:00 2001 From: Ghommie Date: Tue, 23 Jul 2019 23:54:11 +0200 Subject: [PATCH 03/58] arousal states won't persist after death anymore. --- code/modules/surgery/organs/organ_internal.dm | 4 +++- .../code/modules/arousal/organs/_genitals.dm | 14 ++++++++++---- .../code/modules/arousal/organs/breasts.dm | 1 + .../code/modules/arousal/organs/penis.dm | 16 ++++++++-------- .../code/modules/arousal/organs/testicles.dm | 7 +++++-- .../code/modules/arousal/organs/vagina.dm | 1 + .../icons/obj/genitals/testicles_onmob.dmi | Bin 562 -> 561 bytes 7 files changed, 28 insertions(+), 15 deletions(-) diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index b16967b6b0..a17b983689 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -16,7 +16,7 @@ /obj/item/organ/proc/Insert(mob/living/carbon/M, special = 0, drop_if_replaced = TRUE) if(!iscarbon(M) || owner == M) - return + return FALSE var/obj/item/organ/replaced = M.getorganslot(slot) if(replaced) @@ -33,6 +33,7 @@ for(var/X in actions) var/datum/action/A = X A.Grant(M) + return TRUE //Special is for instant replacement like autosurgeons /obj/item/organ/proc/Remove(mob/living/carbon/M, special = 0) @@ -46,6 +47,7 @@ for(var/X in actions) var/datum/action/A = X A.Remove(M) + return TRUE /obj/item/organ/proc/on_find(mob/living/finder) diff --git a/modular_citadel/code/modules/arousal/organs/_genitals.dm b/modular_citadel/code/modules/arousal/organs/_genitals.dm index c4c3eaa9f1..292cc5f4ee 100644 --- a/modular_citadel/code/modules/arousal/organs/_genitals.dm +++ b/modular_citadel/code/modules/arousal/organs/_genitals.dm @@ -113,6 +113,8 @@ return /obj/item/organ/genital/proc/update_appearance() + if(!owner || owner.stat == DEAD) + aroused_state = FALSE return /obj/item/organ/genital/on_life() @@ -142,12 +144,16 @@ return FALSE /obj/item/organ/genital/Insert(mob/living/carbon/M, special = 0) - ..() - update() + . = ..() + if(.) + update() + RegisterSignal(owner, COMSIG_MOB_DEATH, .proc/update_appearance) /obj/item/organ/genital/Remove(mob/living/carbon/M, special = 0) - ..() - update(TRUE) + . = ..() + if(.) + update(TRUE) + UnregisterSignal(M, COMSIG_MOB_DEATH) //proc to give a player their genitals and stuff when they log in /mob/living/carbon/human/proc/give_genitals(clean = FALSE)//clean will remove all pre-existing genitals. proc will then give them any genitals that are enabled in their DNA diff --git a/modular_citadel/code/modules/arousal/organs/breasts.dm b/modular_citadel/code/modules/arousal/organs/breasts.dm index f6d5673a53..3fec45006b 100644 --- a/modular_citadel/code/modules/arousal/organs/breasts.dm +++ b/modular_citadel/code/modules/arousal/organs/breasts.dm @@ -17,6 +17,7 @@ fluid_transfer_factor = 0.5 /obj/item/organ/genital/breasts/update_appearance() + . = ..() var/lowershape = lowertext(shape) switch(lowershape) if("pair") diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/modular_citadel/code/modules/arousal/organs/penis.dm index 2593460a32..5ab9868895 100644 --- a/modular_citadel/code/modules/arousal/organs/penis.dm +++ b/modular_citadel/code/modules/arousal/organs/penis.dm @@ -16,27 +16,27 @@ var/girth = 0 var/girth_ratio = COCK_GIRTH_RATIO_DEF //0.73; check citadel_defines.dm var/knot_girth_ratio = KNOT_GIRTH_RATIO_DEF - var/list/dickflags = list() var/list/knotted_types = list("knotted", "barbed, knotted") /obj/item/organ/genital/penis/update_size() if(length == cached_length) return + var/new_size switch(length) if(-INFINITY to 5) - size = 1 + new_size = 1 if(5 to 9) - size = 2 + new_size = 2 if(15 to INFINITY) - size = 3//no new sprites for anything larger yet -/* if(9 to 15) - size = 3 - if(15 to INFINITY) - size = 3*/ + new_size = 3 //no new sprites for anything larger yet. girth = (length * girth_ratio) cached_length = length + if(linked_organ) + linked_organ.update_size(new_size - size) + size = new_size /obj/item/organ/genital/penis/update_appearance() + . = ..() var/string var/lowershape = lowertext(shape) desc = "You see [aroused_state ? "an erect" : "a flaccid"] [lowershape] [name]. You estimate it's about [round(length, 0.25)] inch[round(length, 0.25) != 1 ? "es" : ""] long and [round(girth, 0.25)] inch[round(girth, 0.25) != 1 ? "es" : ""] in girth." diff --git a/modular_citadel/code/modules/arousal/organs/testicles.dm b/modular_citadel/code/modules/arousal/organs/testicles.dm index c67d6a49a4..2e1b330095 100644 --- a/modular_citadel/code/modules/arousal/organs/testicles.dm +++ b/modular_citadel/code/modules/arousal/organs/testicles.dm @@ -36,7 +36,9 @@ to_chat(owner, msg) return TRUE -/obj/item/organ/genital/testicles/update_appearance() +/obj/item/organ/genital/testicles/update_size(new_size) + if(new_size) + size = CLAMP(size + new_size, BALLS_SIZE_MIN, BALLS_SIZE_MAX) switch(size) if(BALLS_SIZE_MIN) size_name = "average" @@ -47,8 +49,9 @@ else size_name = "nonexistant" +/obj/item/organ/genital/testicles/update_appearance() + . = ..() desc = "You see an [size_name] pair of testicles." - if(owner) var/string if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"]) diff --git a/modular_citadel/code/modules/arousal/organs/vagina.dm b/modular_citadel/code/modules/arousal/organs/vagina.dm index af2beb5f79..1b4b088015 100644 --- a/modular_citadel/code/modules/arousal/organs/vagina.dm +++ b/modular_citadel/code/modules/arousal/organs/vagina.dm @@ -20,6 +20,7 @@ var/list/vag_types = list("tentacle", "dentata", "hairy", "spade", "furred") /obj/item/organ/genital/vagina/update_appearance() + . = ..() var/string //Keeping this code here, so making multiple sprites for the different kinds is easier. var/lowershape = lowertext(shape) var/details diff --git a/modular_citadel/icons/obj/genitals/testicles_onmob.dmi b/modular_citadel/icons/obj/genitals/testicles_onmob.dmi index 7d4d2610c5337d0877fd9d741c38998893444576..65eb24268f99929355d5d90054cf8d6a1c2b3a97 100644 GIT binary patch delta 193 zcmV;y06zb+1hE8=Qh%#@R9JLGWpiV4X>fFDZ*Bkpc$}ruK@P$o5CzaRoPxA#O#!zq zY#@q>T!A!pEF`ri4AJY`)&r=po4@$;lF8Jp)kkBQx)}O|h~Y7@J=<*?N?xH)ehyMl z;voz^eFCN~!8}$8Foo*~=rByf2#&kP9n`s^qz@67J(S#HcQuD)=3k1fJ{hb2?}}Vh v6reH}l?5o@VD^F6YW9iqVNnFjd|3Vf*GyZrzWy8X+Uw7#l4CKm2LUSq=#E*> delta 194 zcmV;z06qV)1hNE>Qh%&^R9JLGWpiV4X>fFDZ*Bkpc$}q@K@Ng25JlJRDH>R7D0S;X z(nf0{S7?ZgbP~jbY4rMn96%j*|1aLWWNscQ%-_{sLC+Hq)$ From 6000f96dbc4de60f1088f06a3e7586aff7d307ca Mon Sep 17 00:00:00 2001 From: Ghommie Date: Wed, 24 Jul 2019 02:00:30 +0200 Subject: [PATCH 04/58] deleted some boolean variables in favor of bitflags. --- code/__DEFINES/citadel_defines.dm | 8 ++++- code/_globalvars/bitfields.dm | 10 ++++++ .../code/modules/arousal/arousal.dm | 12 +++---- .../code/modules/arousal/organs/_genitals.dm | 32 +++++++------------ .../code/modules/arousal/organs/breasts.dm | 7 ++-- .../code/modules/arousal/organs/eggsack.dm | 3 +- .../code/modules/arousal/organs/penis.dm | 3 +- .../code/modules/arousal/organs/testicles.dm | 8 ++--- .../code/modules/arousal/organs/vagina.dm | 3 +- .../code/modules/arousal/organs/womb.dm | 3 +- 10 files changed, 43 insertions(+), 46 deletions(-) diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index b366a792e5..035e660176 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -27,7 +27,13 @@ //genital flags #define GENITAL_BLACKLISTED (1 << 0) //for genitals that shouldn't be added to GLOB.genitals_list. -#define MASTURBATE_LINKED_ORGAN (1<<1) //used to pass our mission to the linked organ +#define GENITAL_INTERNAL (1<<1) +#define GENITAL_HIDDEN (1<<2) +#define GENITAL_THROUGH_CLOTHES (1<<3) +#define GENITAL_FUID_PRODUCTION (1<<4) +#define CAN_MASTURBATE_WITH (1<<5) +#define MASTURBATE_LINKED_ORGAN (1<<6) //used to pass our mission to the linked organ +#define CAN_CLIMAX_WITH (1<<7) #define COCK_SIZE_MIN 1 #define COCK_SIZE_MAX 20 diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index bb9fc98b8e..3c7af9af7e 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -177,4 +177,14 @@ GLOBAL_LIST_INIT(bitfields, list( "CAN_CARRY" = CAN_CARRY, "CAN_RESIST" = CAN_RESIST ), + "genital_flags" = list( + "GENITAL_BLACKLISTED" = GENITAL_BLACKLISTED, + "GENITAL_INTERNAL" = GENITAL_INTERNAL, + "GENITAL_HIDDEN" = GENITAL_HIDDEN, + "GENITAL_THROUGH_CLOTHES" = GENITAL_THROUGH_CLOTHES, + "GENITAL_FUID_PRODUCTION" = GENITAL_FUID_PRODUCTION, + "CAN_MASTURBATE_WITH" = CAN_MASTURBATE_WITH, + "MASTURBATE_LINKED_ORGAN" = MASTURBATE_LINKED_ORGAN, + "CAN_CLIMAX_WITH" = CAN_CLIMAX_WITH + ) )) \ No newline at end of file diff --git a/modular_citadel/code/modules/arousal/arousal.dm b/modular_citadel/code/modules/arousal/arousal.dm index 924c507e7d..f5b27b2c15 100644 --- a/modular_citadel/code/modules/arousal/arousal.dm +++ b/modular_citadel/code/modules/arousal/arousal.dm @@ -182,13 +182,13 @@ to_chat(src, "You aren't aroused enough for that.") /obj/item/organ/genital/proc/climaxable(mob/living/carbon/human/H, silent = FALSE) //returns the fluid source (ergo reagents holder) if found. - if(producing) + if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION)) . = reagents else if(linked_organ) . = linked_organ.reagents - else if(!silent) - to_chat(H, "Your [name] is unable to produce it's own fluids, it's missing the organs for it.") + if(!. && !silent) + to_chat(H, "Your [name] is unable to produce it's own fluids, it's missing the organs for it.") /mob/living/carbon/human/proc/do_climax(datum/reagents/R, atom/target, obj/item/organ/genital/G, spill = TRUE) if(!G) @@ -273,7 +273,7 @@ var/list/worn_stuff = get_equipped_items() for(var/obj/item/organ/genital/G in internal_organs) - if(G.can_masturbate_with && G.is_exposed(worn_stuff)) //filter out what you can't masturbate with + if(CHECK_BITFIELD(G.genital_flags, CAN_MASTURBATE_WITH) && G.is_exposed(worn_stuff)) //filter out what you can't masturbate with if(CHECK_BITFIELD(G.genital_flags, MASTURBATE_LINKED_ORGAN) && !G.linked_organ) continue genitals_list += G @@ -287,7 +287,7 @@ var/list/worn_stuff = get_equipped_items() for(var/obj/item/organ/genital/G in internal_organs) - if(G.can_climax && G.is_exposed(worn_stuff)) //filter out what you can't masturbate with + if(CHECK_BITFIELD(G.genital_flags, CAN_CLIMAX_WITH) && G.is_exposed(worn_stuff)) //filter out what you can't masturbate with genitals_list += G if(genitals_list.len) var/obj/item/organ/genital/ret_organ = input(src, "with what?", "Climax", null) as null|obj in genitals_list @@ -352,7 +352,7 @@ 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(!G.can_climax) //Skip things like wombs and testicles + if(!CHECK_BITFIELD(G.genital_flags, CAN_CLIMAX_WITH)) //Skip things like wombs and testicles continue var/mob/living/partner var/check_target diff --git a/modular_citadel/code/modules/arousal/organs/_genitals.dm b/modular_citadel/code/modules/arousal/organs/_genitals.dm index 292cc5f4ee..38c39d4756 100644 --- a/modular_citadel/code/modules/arousal/organs/_genitals.dm +++ b/modular_citadel/code/modules/arousal/organs/_genitals.dm @@ -3,11 +3,9 @@ w_class = WEIGHT_CLASS_NORMAL var/shape = "human" var/sensitivity = AROUSAL_START_VALUE - var/genital_flags - var/can_masturbate_with = FALSE + var/genital_flags //see citadel_defines.dm var/masturbation_verb = "masturbate" var/orgasm_verb = "cumming" //present continous - var/can_climax = FALSE var/fluid_transfer_factor = 0 //How much would a partner get in them if they climax using this? var/size = 2 //can vary between num or text, just used in icon_state strings var/fluid_id = null @@ -15,21 +13,17 @@ var/fluid_efficiency = 1 var/fluid_rate = 1 var/fluid_mult = 1 - var/producing = FALSE var/aroused_state = FALSE //Boolean used in icon_state strings var/aroused_amount = 50 //This is a num from 0 to 100 for arousal percentage for when to use arousal state icons. var/obj/item/organ/genital/linked_organ var/linked_organ_slot //only one of the two organs needs this to be set up. update_link() will handle linking the rest. - var/through_clothes = FALSE - var/internal = FALSE - var/hidden = FALSE 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() . = ..() if(fluid_id) create_reagents(fluid_max_volume) - if(producing) + if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION)) reagents.add_reagent(fluid_id, fluid_max_volume) update() @@ -53,9 +47,9 @@ 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 || hidden || internal) + if(!owner || CHECK_BITFIELD(genital_flags, GENITAL_INTERNAL|GENITAL_HIDDEN)) return FALSE - if(through_clothes) + if(CHECK_BITFIELD(genital_flags, GENITAL_THROUGH_CLOTHES)) return TRUE switch(zone) //update as more genitals are added @@ -69,18 +63,18 @@ /obj/item/organ/genital/proc/toggle_visibility(visibility) switch(visibility) if("Always visible") - through_clothes = TRUE - hidden = FALSE + ENABLE_BITFIELD(genital_flags, GENITAL_THROUGH_CLOTHES) + DISABLE_BITFIELD(genital_flags, GENITAL_HIDDEN) if(!(src in owner.exposed_genitals)) owner.exposed_genitals += src if("Hidden by clothes") - through_clothes = FALSE - hidden = TRUE + DISABLE_BITFIELD(genital_flags, GENITAL_THROUGH_CLOTHES) + DISABLE_BITFIELD(genital_flags, GENITAL_HIDDEN) if(src in owner.exposed_genitals) owner.exposed_genitals -= src if("Always hidden") - through_clothes = FALSE - hidden = TRUE + DISABLE_BITFIELD(genital_flags, GENITAL_THROUGH_CLOTHES) + ENABLE_BITFIELD(genital_flags, GENITAL_HIDDEN) if(src in owner.exposed_genitals) owner.exposed_genitals -= src @@ -97,7 +91,7 @@ for(var/obj/item/organ/O in internal_organs) if(isgenital(O)) var/obj/item/organ/genital/G = O - if(!G.internal) + if(!CHECK_BITFIELD(G.genital_flags, GENITAL_INTERNAL)) genital_list += G if(!genital_list.len) //There is nothing to expose return @@ -121,7 +115,7 @@ if(!reagents || !owner) return reagents.maximum_volume = fluid_max_volume - if(fluid_id && producing) + if(fluid_id && CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION)) generate_fluid() /obj/item/organ/genital/proc/generate_fluid() @@ -235,8 +229,6 @@ //start scanning for genitals //var/list/worn_stuff = H.get_equipped_items()//cache this list so it's not built again for(var/obj/item/organ/genital/G in H.internal_organs) - if(G.hidden) - return //we're gunna just hijack this for updates. if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes LAZYADD(genitals_to_add[G.layer_index], G) //Now we added all genitals that aren't internal and should be rendered diff --git a/modular_citadel/code/modules/arousal/organs/breasts.dm b/modular_citadel/code/modules/arousal/organs/breasts.dm index 3fec45006b..6079c9364f 100644 --- a/modular_citadel/code/modules/arousal/organs/breasts.dm +++ b/modular_citadel/code/modules/arousal/organs/breasts.dm @@ -7,13 +7,10 @@ slot = ORGAN_SLOT_BREASTS size = BREASTS_SIZE_DEF fluid_id = "milk" - var/amount = 2 - producing = TRUE shape = "pair" - can_masturbate_with = TRUE + genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_FUID_PRODUCTION masturbation_verb = "massage" orgasm_verb = "leaking" - can_climax = TRUE fluid_transfer_factor = 0.5 /obj/item/organ/genital/breasts/update_appearance() @@ -32,7 +29,7 @@ desc += " You estimate that they're [uppertext(size)]-cups." else desc += " You wouldn't measure them in cup sizes." - if(producing && aroused_state) + if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION) && aroused_state) desc += " They're leaking [fluid_id]." var/string if(owner) diff --git a/modular_citadel/code/modules/arousal/organs/eggsack.dm b/modular_citadel/code/modules/arousal/organs/eggsack.dm index 624b2c24cd..ebdefd2371 100644 --- a/modular_citadel/code/modules/arousal/organs/eggsack.dm +++ b/modular_citadel/code/modules/arousal/organs/eggsack.dm @@ -5,10 +5,9 @@ icon = 'modular_citadel/icons/obj/genitals/ovipositor.dmi' zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_TESTICLES - genital_flags = GENITAL_BLACKLISTED //unimplemented + genital_flags = GENITAL_INTERNAL|GENITAL_BLACKLISTED //unimplemented linked_organ_slot = ORGAN_SLOT_PENIS color = null //don't use the /genital color since it already is colored - internal = TRUE var/egg_girth = EGG_GIRTH_DEF var/cum_mult = CUM_RATE_MULT var/cum_rate = CUM_RATE diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/modular_citadel/code/modules/arousal/organs/penis.dm index 5ab9868895..0441f78774 100644 --- a/modular_citadel/code/modules/arousal/organs/penis.dm +++ b/modular_citadel/code/modules/arousal/organs/penis.dm @@ -5,9 +5,8 @@ icon = 'modular_citadel/icons/obj/genitals/penis.dmi' zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_PENIS - can_masturbate_with = TRUE masturbation_verb = "stroke" - can_climax = TRUE + genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH fluid_transfer_factor = 0.5 size = 2 //arbitrary value derived from length and girth for sprites. layer_index = PENIS_LAYER_INDEX diff --git a/modular_citadel/code/modules/arousal/organs/testicles.dm b/modular_citadel/code/modules/arousal/organs/testicles.dm index 2e1b330095..e06a10b9fc 100644 --- a/modular_citadel/code/modules/arousal/organs/testicles.dm +++ b/modular_citadel/code/modules/arousal/organs/testicles.dm @@ -7,13 +7,11 @@ slot = ORGAN_SLOT_TESTICLES size = BALLS_SIZE_MIN linked_organ_slot = ORGAN_SLOT_PENIS - genital_flags = MASTURBATE_LINKED_ORGAN + genital_flags = CAN_MASTURBATE_WITH|MASTURBATE_LINKED_ORGAN|GENITAL_FUID_PRODUCTION var/size_name = "average" shape = "single" var/sack_size = BALLS_SACK_SIZE_DEF fluid_id = "semen" - producing = TRUE - can_masturbate_with = TRUE masturbation_verb = "massage" layer_index = TESTICLES_LAYER_INDEX var/size_linked = FALSE @@ -77,9 +75,7 @@ sack_size = D.features["balls_sack_size"] shape = D.features["balls_shape"] if(D.features["balls_shape"] == "Hidden") - internal = TRUE - else - internal = FALSE + ENABLE_BITFIELD(genital_flags, GENITAL_INTERNAL) fluid_id = D.features["balls_fluid"] fluid_rate = D.features["balls_cum_rate"] fluid_mult = D.features["balls_cum_mult"] diff --git a/modular_citadel/code/modules/arousal/organs/vagina.dm b/modular_citadel/code/modules/arousal/organs/vagina.dm index 1b4b088015..0df954fd79 100644 --- a/modular_citadel/code/modules/arousal/organs/vagina.dm +++ b/modular_citadel/code/modules/arousal/organs/vagina.dm @@ -6,9 +6,8 @@ zone = BODY_ZONE_PRECISE_GROIN slot = "vagina" size = 1 //There is only 1 size right now - can_masturbate_with = TRUE + genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH masturbation_verb = "finger" - can_climax = TRUE 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) diff --git a/modular_citadel/code/modules/arousal/organs/womb.dm b/modular_citadel/code/modules/arousal/organs/womb.dm index d99206d0f1..3c4ce225f4 100644 --- a/modular_citadel/code/modules/arousal/organs/womb.dm +++ b/modular_citadel/code/modules/arousal/organs/womb.dm @@ -5,7 +5,6 @@ icon_state = "womb" zone = BODY_ZONE_PRECISE_GROIN slot = ORGAN_SLOT_WOMB - internal = TRUE + genital_flags = GENITAL_INTERNAL|GENITAL_FUID_PRODUCTION fluid_id = "femcum" - producing = TRUE linked_organ_slot = ORGAN_SLOT_VAGINA \ No newline at end of file From 6623dd48968b19858155d28799cce5a39c402900 Mon Sep 17 00:00:00 2001 From: Ghommie Date: Wed, 24 Jul 2019 02:03:52 +0200 Subject: [PATCH 05/58] As if they'd care anyway. --- code/datums/traits/neutral.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm index 156ee00d75..3c7894f250 100644 --- a/code/datums/traits/neutral.dm +++ b/code/datums/traits/neutral.dm @@ -122,7 +122,7 @@ /datum/quirk/exhibitionism name = "Exhibitionism" - desc = "You don't mind showing off your bare body to strangers, in fact you find it quite satistying. Not the best excuse to break Space Law anyway." //as if they'd care anyway. + desc = "You don't mind showing off your bare body to strangers, in fact you find it quite satistying." value = 0 medical_record_text = "Patient has been diagnosed with exhibitionistic disorder." mob_trait = TRAIT_EXHIBITIONIST From 30292c385b77ad5d2e52feb100a7ea89106ff6cb Mon Sep 17 00:00:00 2001 From: Ghommie Date: Wed, 24 Jul 2019 02:07:59 +0200 Subject: [PATCH 06/58] moving files. --- .../code/modules/arousal/{organs/_genitals.dm => genitals.dm} | 0 .../arousal/{organs => }/genitals_sprite_accessories.dm | 0 tgstation.dme | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename modular_citadel/code/modules/arousal/{organs/_genitals.dm => genitals.dm} (100%) rename modular_citadel/code/modules/arousal/{organs => }/genitals_sprite_accessories.dm (100%) diff --git a/modular_citadel/code/modules/arousal/organs/_genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm similarity index 100% rename from modular_citadel/code/modules/arousal/organs/_genitals.dm rename to modular_citadel/code/modules/arousal/genitals.dm diff --git a/modular_citadel/code/modules/arousal/organs/genitals_sprite_accessories.dm b/modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm similarity index 100% rename from modular_citadel/code/modules/arousal/organs/genitals_sprite_accessories.dm rename to modular_citadel/code/modules/arousal/genitals_sprite_accessories.dm diff --git a/tgstation.dme b/tgstation.dme index 7c9fa1e899..c872760203 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2911,10 +2911,10 @@ #include "modular_citadel\code\modules\admin\secrets.dm" #include "modular_citadel\code\modules\admin\topic.dm" #include "modular_citadel\code\modules\arousal\arousal.dm" -#include "modular_citadel\code\modules\arousal\organs\_genitals.dm" +#include "modular_citadel\code\modules\arousal\genitals.dm" +#include "modular_citadel\code\modules\arousal\genitals_sprite_accessories.dm" #include "modular_citadel\code\modules\arousal\organs\breasts.dm" #include "modular_citadel\code\modules\arousal\organs\eggsack.dm" -#include "modular_citadel\code\modules\arousal\organs\genitals_sprite_accessories.dm" #include "modular_citadel\code\modules\arousal\organs\ovipositor.dm" #include "modular_citadel\code\modules\arousal\organs\penis.dm" #include "modular_citadel\code\modules\arousal\organs\testicles.dm" From 56f2a8f8846093f681d6d744230b31ca5aafdf11 Mon Sep 17 00:00:00 2001 From: Ghommie Date: Thu, 25 Jul 2019 04:29:21 +0200 Subject: [PATCH 07/58] Fixes oversized tennis balls, testing and fixing. --- code/__DEFINES/citadel_defines.dm | 16 +- code/__HELPERS/_cit_helpers.dm | 10 +- .../code/modules/arousal/arousal.dm | 229 ++++++++++-------- .../code/modules/arousal/genitals.dm | 33 +-- .../code/modules/arousal/organs/penis.dm | 6 +- .../code/modules/arousal/organs/testicles.dm | 13 +- 6 files changed, 162 insertions(+), 145 deletions(-) diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 035e660176..04e9c52527 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -26,14 +26,14 @@ #define GENITAL_LAYER_INDEX_LENGTH 4 //keep it updated with each new index added, thanks. //genital flags -#define GENITAL_BLACKLISTED (1 << 0) //for genitals that shouldn't be added to GLOB.genitals_list. -#define GENITAL_INTERNAL (1<<1) -#define GENITAL_HIDDEN (1<<2) -#define GENITAL_THROUGH_CLOTHES (1<<3) -#define GENITAL_FUID_PRODUCTION (1<<4) -#define CAN_MASTURBATE_WITH (1<<5) -#define MASTURBATE_LINKED_ORGAN (1<<6) //used to pass our mission to the linked organ -#define CAN_CLIMAX_WITH (1<<7) +#define GENITAL_BLACKLISTED (1<<0) //for genitals that shouldn't be added to GLOB.genitals_list. +#define GENITAL_INTERNAL (1<<1) +#define GENITAL_HIDDEN (1<<2) +#define GENITAL_THROUGH_CLOTHES (1<<3) +#define GENITAL_FUID_PRODUCTION (1<<4) +#define CAN_MASTURBATE_WITH (1<<5) +#define MASTURBATE_LINKED_ORGAN (1<<6) //used to pass our mission to the linked organ +#define CAN_CLIMAX_WITH (1<<7) #define COCK_SIZE_MIN 1 #define COCK_SIZE_MAX 20 diff --git a/code/__HELPERS/_cit_helpers.dm b/code/__HELPERS/_cit_helpers.dm index d75dd31b46..1c7b4aeb99 100644 --- a/code/__HELPERS/_cit_helpers.dm +++ b/code/__HELPERS/_cit_helpers.dm @@ -158,18 +158,20 @@ GLOBAL_VAR_INIT(miscreants_allowed, FALSE) return TRUE return FALSE -/mob/living/carbon/proc/is_groin_exposed(var/list/L) +/mob/living/carbon/proc/is_groin_exposed(list/L) if(!L) L = get_equipped_items() - for(var/obj/item/I in L) + for(var/A in L) + var/obj/item/I = A if(I.body_parts_covered & GROIN) return FALSE return TRUE -/mob/living/carbon/proc/is_chest_exposed(var/list/L) +/mob/living/carbon/proc/is_chest_exposed(list/L) if(!L) L = get_equipped_items() - for(var/obj/item/I in L) + for(var/A in L) + var/obj/item/I = A if(I.body_parts_covered & CHEST) return FALSE return TRUE diff --git a/modular_citadel/code/modules/arousal/arousal.dm b/modular_citadel/code/modules/arousal/arousal.dm index f5b27b2c15..83a5622f49 100644 --- a/modular_citadel/code/modules/arousal/arousal.dm +++ b/modular_citadel/code/modules/arousal/arousal.dm @@ -139,8 +139,6 @@ if(!canbearoused) hud_used.arousal.icon_state = "" return FALSE - if(stat == DEAD) - hud_used.arousal.icon_state = "arousal0" else var/value = FLOOR(getPercentAroused(), 10) hud_used.arousal.icon_state = "arousal[value]" @@ -194,6 +192,7 @@ if(!G) return SEND_SIGNAL(src, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) + setArousalLoss(min_arousal) if(!target || !R) return var/turfing = isturf(target) @@ -217,8 +216,8 @@ "You start to [G.masturbation_verb] your [G.name].") if(!do_after(src, mb_time, target = src) || !G.climaxable(src, TRUE)) return - visible_message("[src] orgasms, [PP.orgasm_verb][isturf(loc) ? " onto [loc]" : ""]!", \ - "You orgasm, [PP.orgasm_verb][isturf(loc) ? " onto [loc]" : ""].") + visible_message("[src] orgasms, [PP.orgasm_verb][isturf(loc) ? " onto [loc]" : ""] with [p_their()] [PP.name]!", \ + "You orgasm, [PP.orgasm_verb][isturf(loc) ? " onto [loc]" : ""] with your [PP.name].") do_climax(fluid_source, loc, G) /mob/living/carbon/human/proc/mob_climax_outside(obj/item/organ/genital/G, mb_time = 30) //This is used for forced orgasms and other hands-free climaxes @@ -268,33 +267,35 @@ "You used your [G.name] to fill [container].") do_climax(fluid_source, container, G, FALSE) -/mob/living/carbon/human/proc/pick_masturbate_genitals() - var/list/genitals_list = list() +/mob/living/carbon/human/proc/pick_masturbate_genitals(silent = FALSE) + var/list/genitals_list var/list/worn_stuff = get_equipped_items() for(var/obj/item/organ/genital/G in internal_organs) if(CHECK_BITFIELD(G.genital_flags, CAN_MASTURBATE_WITH) && G.is_exposed(worn_stuff)) //filter out what you can't masturbate with if(CHECK_BITFIELD(G.genital_flags, MASTURBATE_LINKED_ORGAN) && !G.linked_organ) continue - genitals_list += G - if(genitals_list.len) - var/obj/item/organ/genital/ret_organ = input(src, "with what?", "Masturbate", null) as null|obj in genitals_list + LAZYADD(genitals_list, G) + if(LAZYLEN(genitals_list)) + var/obj/item/organ/genital/ret_organ = input(src, "with what?", "Masturbate", null) as null|obj in genitals_list return ret_organ + else if(!silent) + to_chat(src, "You cannot masturbate without available genitals.") - -/mob/living/carbon/human/proc/pick_climax_genitals() - var/list/genitals_list = list() +/mob/living/carbon/human/proc/pick_climax_genitals(silent = FALSE) + var/list/genitals_list var/list/worn_stuff = get_equipped_items() for(var/obj/item/organ/genital/G in internal_organs) if(CHECK_BITFIELD(G.genital_flags, CAN_CLIMAX_WITH) && G.is_exposed(worn_stuff)) //filter out what you can't masturbate with - genitals_list += G - if(genitals_list.len) - var/obj/item/organ/genital/ret_organ = input(src, "with what?", "Climax", null) as null|obj in genitals_list + 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, "You cannot climax without available genitals.") - -/mob/living/carbon/human/proc/pick_partner() +/mob/living/carbon/human/proc/pick_partner(silent = FALSE) var/list/partners = list() if(pulling) partners += pulling @@ -308,30 +309,42 @@ partners -= C //NOW the list should only contain correct partners if(!partners.len) + if(!silent) + to_chat(src, "You cannot do this alone.") return //No one left. var/mob/living/target = input(src, "With whom?", "Sexual partner", null) as null|anything in partners //pick one, default to null if(target && in_range(src, target)) return target -/mob/living/carbon/human/proc/pick_climax_container() +/mob/living/carbon/human/proc/pick_climax_container(silent = FALSE) var/list/containers_list = list() - for(var/obj/item/reagent_containers/container in held_items) - if(container.is_open_container() || istype(container, /obj/item/reagent_containers/food/snacks)) - containers_list += container + for(var/obj/item/reagent_containers/C in held_items) + if(C.is_open_container() || istype(C, /obj/item/reagent_containers/food/snacks)) + containers_list += C + for(var/obj/item/reagent_containers/C in range(1, src)) + if((C.is_open_container() || istype(C, /obj/item/reagent_containers/food/snacks)) && CanReach(C)) + containers_list += C if(containers_list.len) var/obj/item/reagent_containers/SC = input(src, "Into or onto what?(Cancel for nowhere)", null) as null|obj in containers_list - if(SC && in_range(src, SC)) + if(SC && CanReach(SC)) return SC - return null //If nothing correct, give null. + else if(!silent) + to_chat(src, "You cannot do this without an appropriate container.") -/mob/living/carbon/human/proc/available_rosie_palms(silent = FALSE) +/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, "You can't do that while restrained!") 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, "You need at least one free arm.") return FALSE @@ -343,93 +356,97 @@ if(!forced_climax) //Don't spam the message to the victim if forced to come too fast to_chat(src, "You need to wait [DisplayTimeText((mb_cd_timer - world.time), TRUE)] before you can do that again!") return - mb_cd_timer = world.time + mb_cd_length - if(canbearoused && has_dna()) - if(stat == DEAD) - if(!forced_climax) - to_chat(src, "You can't do that while dead!") - 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(!canbearoused || !has_dna()) + return + if(stat == DEAD) + if(!forced_climax) + to_chat(src, "You can't do that while dead!") + 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 - return - //If we get here, then this is not a forced climax and we gotta check a few things. + if(G.is_exposed(worn_stuff)) + if(pulling) //Are we pulling someone? Priority target, we can't be making option menus for this, has to be quick + if(isliving(pulling)) //Don't fuck objects + check_target = pulling + if(pulledby && !check_target) //prioritise pulled over pulledby + if(isliving(pulledby)) + check_target = pulledby + //Now we should have a partner, or else we have to come alone + if(check_target) + if(iscarbon(check_target)) //carbons can have clothes + var/mob/living/carbon/C = check_target + if(C.exposed_genitals.len || C.is_groin_exposed() || C.is_chest_exposed()) //Are they naked enough? + partner = C + else //A cat is fine too + partner = check_target + if(partner) //Did they pass the clothing checks? + mob_climax_partner(G, partner, mb_time = 0) //Instant climax due to forced + continue //You've climaxed once with this organ, continue on + //not exposed OR if no partner was found while exposed, climax alone + mob_climax_outside(G, mb_time = 0) //removed climax timer for sudden, forced orgasms + //Now all genitals that could climax, have. + //Since this was a forced climax, we do not need to continue with the other stuff + mb_cd_timer = world.time + mb_cd_length + return + //If we get here, then this is not a forced climax and we gotta check a few things. - if(stat == UNCONSCIOUS) //No sleep-masturbation, you're unconscious. - to_chat(src, "You must be conscious to do that!") - return - if(getArousalLoss() < 33) //flat number instead of percentage - to_chat(src, "You aren't aroused enough for that!") - return + if(stat == UNCONSCIOUS) //No sleep-masturbation, you're unconscious. + to_chat(src, "You must be conscious to do that!") + return + if(getArousalLoss() < 33) //flat number instead of percentage + to_chat(src, "You aren't aroused enough for that!") + return - //Ok, now we check what they want to do. - var/choice = input(src, "Select sexual activity", "Sexual activity:") as null|anything in list("Masturbate", "Climax alone", "Climax with partner", "Fill container") + //Ok, now we check what they want to do. + var/choice = input(src, "Select sexual activity", "Sexual activity:") as null|anything in list("Masturbate", "Climax alone", "Climax with partner", "Fill container") + if(!choice) + return - switch(choice) - if("Masturbate") - if(!available_rosie_palms()) - return - //We got hands, let's pick an organ - var/obj/item/organ/genital/picked_organ = pick_masturbate_genitals() - if(picked_organ && available_rosie_palms(TRUE)) - mob_masturbate(picked_organ) - return + switch(choice) + if("Masturbate") + if(!available_rosie_palms()) + return + //We got hands, let's pick an organ + var/obj/item/organ/genital/picked_organ = pick_masturbate_genitals() + if(picked_organ && available_rosie_palms(TRUE)) + mob_masturbate(picked_organ) + return - if("Climax alone") - if(!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 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("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()) - 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)) - mob_fill_container(picked_organ, fluid_container) - return \ No newline at end of file + 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 \ No newline at end of file diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm index 38c39d4756..3545c96a50 100644 --- a/modular_citadel/code/modules/arousal/genitals.dm +++ b/modular_citadel/code/modules/arousal/genitals.dm @@ -47,7 +47,7 @@ var/list/exposed_genitals = list() //Keeping track of them so we don't have to iterate through every genitalia and see if exposed /obj/item/organ/genital/proc/is_exposed() - if(!owner || CHECK_BITFIELD(genital_flags, GENITAL_INTERNAL|GENITAL_HIDDEN)) + if(!owner || CHECK_BITFIELD(genital_flags, GENITAL_INTERNAL) || CHECK_BITFIELD(genital_flags, GENITAL_HIDDEN)) return FALSE if(CHECK_BITFIELD(genital_flags, GENITAL_THROUGH_CLOTHES)) return TRUE @@ -58,8 +58,6 @@ if(BODY_ZONE_PRECISE_GROIN) return owner.is_groin_exposed() - return FALSE - /obj/item/organ/genital/proc/toggle_visibility(visibility) switch(visibility) if("Always visible") @@ -119,7 +117,7 @@ generate_fluid() /obj/item/organ/genital/proc/generate_fluid() - if(owner.stat != DEAD && reagents.total_volume < reagents.maximum_volume) + if(reagents.total_volume < reagents.maximum_volume) reagents.isolate_reagent(fluid_id)//remove old reagents if it changed and just clean up generally reagents.add_reagent(fluid_id, (fluid_mult * fluid_rate))//generate the cum return TRUE @@ -137,13 +135,13 @@ linked_organ = null return FALSE -/obj/item/organ/genital/Insert(mob/living/carbon/M, special = 0) +/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) + RegisterSignal(owner, COMSIG_MOB_DEATH, .proc/update) -/obj/item/organ/genital/Remove(mob/living/carbon/M, special = 0) +/obj/item/organ/genital/Remove(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE) . = ..() if(.) update(TRUE) @@ -176,12 +174,11 @@ /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 - if(istype(G, /obj/item/organ/genital)) //badminnery-proofing. - G.get_features(src) + G = new G + G.get_features(src) G.Insert(src) -/obj/item/organ/genital/proc/get_features(datum/dna/D) +/obj/item/organ/genital/proc/get_features(mob/living/carbon/human/H) return /datum/species/proc/genitals_layertext(layer) @@ -217,7 +214,6 @@ if(!LAZYLEN(H.internal_organs) || (NOGENITALS in species_traits) || HAS_TRAIT(H, TRAIT_HUSK)) return - var/list/genitals_to_add[GENITAL_LAYER_INDEX_LENGTH] var/list/relevant_layers = list(GENITALS_BEHIND_LAYER, GENITALS_ADJ_LAYER, GENITALS_FRONT_LAYER) var/list/standing = list() var/size @@ -228,15 +224,22 @@ //start scanning for genitals //var/list/worn_stuff = H.get_equipped_items()//cache this list so it's not built again + + var/list/gen_index[GENITAL_LAYER_INDEX_LENGTH] + var/list/genitals_to_add for(var/obj/item/organ/genital/G in H.internal_organs) if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes - LAZYADD(genitals_to_add[G.layer_index], G) + LAZYADD(gen_index[G.layer_index], G) + for(var/L in gen_index) + if(L) //skip nulls + LAZYADD(genitals_to_add, L) //Now we added all genitals that aren't internal and should be rendered //start applying overlays for(var/layer in relevant_layers) - var/layertext = flatten_list(genitals_layertext(layer)) - for(var/obj/item/organ/genital/G in genitals_to_add) + var/layertext = genitals_layertext(layer) + for(var/A in genitals_to_add) + var/obj/item/organ/genital/G = A var/datum/sprite_accessory/S size = G.size aroused_state = G.aroused_state diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/modular_citadel/code/modules/arousal/organs/penis.dm index 0441f78774..b387fa96f5 100644 --- a/modular_citadel/code/modules/arousal/organs/penis.dm +++ b/modular_citadel/code/modules/arousal/organs/penis.dm @@ -22,11 +22,11 @@ return var/new_size switch(length) - if(-INFINITY to 5) + if(-INFINITY to 6) new_size = 1 - if(5 to 9) + if(6 to 12) new_size = 2 - if(15 to INFINITY) + if(12 to INFINITY) new_size = 3 //no new sprites for anything larger yet. girth = (length * girth_ratio) cached_length = length diff --git a/modular_citadel/code/modules/arousal/organs/testicles.dm b/modular_citadel/code/modules/arousal/organs/testicles.dm index e06a10b9fc..06f40b5b51 100644 --- a/modular_citadel/code/modules/arousal/organs/testicles.dm +++ b/modular_citadel/code/modules/arousal/organs/testicles.dm @@ -9,7 +9,7 @@ linked_organ_slot = ORGAN_SLOT_PENIS genital_flags = CAN_MASTURBATE_WITH|MASTURBATE_LINKED_ORGAN|GENITAL_FUID_PRODUCTION var/size_name = "average" - shape = "single" + shape = "Single" var/sack_size = BALLS_SACK_SIZE_DEF fluid_id = "semen" masturbation_verb = "massage" @@ -20,20 +20,16 @@ if(!linked_organ && !update_link()) return FALSE . = ..() - if(.) - send_full_message() + if(. && reagents.holder_full()) + to_chat(owner, "Your balls finally feel full, again.") /obj/item/organ/genital/testicles/update_link(removing = FALSE) . = ..() if(. && !size_linked) size = linked_organ.size + update() size_linked = TRUE -/obj/item/organ/genital/testicles/proc/send_full_message(msg = "Your balls finally feel full, again.") - if(owner && istext(msg)) - to_chat(owner, msg) - return TRUE - /obj/item/organ/genital/testicles/update_size(new_size) if(new_size) size = CLAMP(size + new_size, BALLS_SIZE_MIN, BALLS_SIZE_MAX) @@ -71,7 +67,6 @@ color = "#[skintone2hex(H.skin_tone)]" else color = "#[D.features["balls_color"]]" - size = D.features["balls_size"] sack_size = D.features["balls_sack_size"] shape = D.features["balls_shape"] if(D.features["balls_shape"] == "Hidden") From 44a28066a16607219a1caa478509fe77b06f3e47 Mon Sep 17 00:00:00 2001 From: Ghommie Date: Thu, 25 Jul 2019 04:44:34 +0200 Subject: [PATCH 08/58] coding exasperation. --- modular_citadel/code/modules/arousal/arousal.dm | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/modular_citadel/code/modules/arousal/arousal.dm b/modular_citadel/code/modules/arousal/arousal.dm index 83a5622f49..6c9da17289 100644 --- a/modular_citadel/code/modules/arousal/arousal.dm +++ b/modular_citadel/code/modules/arousal/arousal.dm @@ -69,10 +69,8 @@ amt_nude++ if(amt_nude) var/watchers = 0 - for(var/mob/living/L in view(world.view, src)) - if(!istype(L)) - continue - if(L.client && !L.stat && !L.eye_blind && (locate(src) in viewers(world.view, L))) + for(var/mob/living/L in view(src)) + if(L.client && !L.stat && !L.eye_blind && (src in view(L))) watchers++ if(watchers) our_loss += (amt_nude * watchers) + S.arousal_gain_rate From 36ffd3d6a8d69d3ac75145080d0ada2f06f53874 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Sun, 1 Sep 2019 03:35:36 +0200 Subject: [PATCH 09/58] More lines. --- code/__DEFINES/misc.dm | 27 ++++---- .../code/modules/arousal/genitals.dm | 40 ++++++------ .../chemistry/reagents/enlargement.dm | 61 +++++++++---------- 3 files changed, 62 insertions(+), 66 deletions(-) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index c71780e7e9..8a0db9ad9c 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -51,24 +51,25 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s //Human Overlays Indexes///////// //LOTS OF CIT CHANGES HERE. BE CAREFUL WHEN UPSTREAM ADDS MORE LAYERS -#define MUTATIONS_LAYER 31 //mutations. Tk headglows, cold resistance glow, etc -#define GENITALS_BEHIND_LAYER 30 //Some genitalia needs to be behind everything, such as with taurs (Taurs use body_behind_layer -#define BODY_BEHIND_LAYER 29 //certain mutantrace features (tail when looking south) that must appear behind the body parts -#define BODYPARTS_LAYER 28 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag -#define MARKING_LAYER 27 //Matrixed body markings because clashing with snouts? -#define BODY_ADJ_LAYER 26 //certain mutantrace features (snout, body markings) that must appear above the body parts -#define GENITALS_FRONT_LAYER 25 //Draws some genitalia above clothes and the TAUR body if need be. -#define BODY_LAYER 24 //underwear, undershirts, socks, eyes, lips(makeup) -#define FRONT_MUTATIONS_LAYER 23 //mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes) -#define DAMAGE_LAYER 22 //damage indicators (cuts and burns) -#define UNIFORM_LAYER 21 -#define ID_LAYER 20 +#define MUTATIONS_LAYER 32 //mutations. Tk headglows, cold resistance glow, etc +#define GENITALS_BEHIND_LAYER 31 //Some genitalia needs to be behind everything, such as with taurs (Taurs use body_behind_layer +#define BODY_BEHIND_LAYER 30 //certain mutantrace features (tail when looking south) that must appear behind the body parts +#define BODYPARTS_LAYER 29 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag +#define MARKING_LAYER 28 //Matrixed body markings because clashing with snouts? +#define BODY_ADJ_LAYER 27 //certain mutantrace features (snout, body markings) that must appear above the body parts +#define GENITALS_FRONT_LAYER 26 //Draws some genitalia above clothes and the TAUR body if need be. +#define BODY_LAYER 25 //underwear, undershirts, socks, eyes, lips(makeup) +#define FRONT_MUTATIONS_LAYER 24 //mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes) +#define DAMAGE_LAYER 23 //damage indicators (cuts and burns) +#define UNIFORM_LAYER 22 +#define ID_LAYER 21 #define HANDS_PART_LAYER 20 #define SHOES_LAYER 19 #define GLOVES_LAYER 18 #define EARS_LAYER 17 #define BODY_TAUR_LAYER 16 #define SUIT_LAYER 15 +#define GENITALS_EXPOSED_LAYER 14 #define GLASSES_LAYER 13 #define BELT_LAYER 12 //Possible make this an overlay of somethign required to wear a belt? #define SUIT_STORE_LAYER 11 @@ -82,7 +83,7 @@ Will print: "/mob/living/carbon/human/death" (you can optionally embed it in a s #define HANDS_LAYER 3 #define BODY_FRONT_LAYER 2 #define FIRE_LAYER 1 //If you're on fire -#define TOTAL_LAYERS 30 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_; +#define TOTAL_LAYERS 32 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_; //Human Overlay Index Shortcuts for alternate_worn_layer, layers //Because I *KNOW* somebody will think layer+1 means "above" diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm index 5632aa7eef..f8e404713d 100644 --- a/modular_citadel/code/modules/arousal/genitals.dm +++ b/modular_citadel/code/modules/arousal/genitals.dm @@ -166,7 +166,7 @@ give_genital(/obj/item/organ/genital/womb) if(dna.features["has_balls"]) give_genital(/obj/item/organ/genital/testicles) - if(dna.features["has_breasts"]) // since we have multi-boobs as a thing, we'll want to at least draw over these. but not over the pingas. + if(dna.features["has_breasts"]) give_genital(/obj/item/organ/genital/breasts) if(dna.features["has_cock"]) give_genital(/obj/item/organ/genital/penis) @@ -183,6 +183,7 @@ G = new G G.get_features(src) G.Insert(src) + return G /obj/item/organ/genital/proc/get_features(mob/living/carbon/human/H) return @@ -191,8 +192,6 @@ switch(layer) if(GENITALS_BEHIND_LAYER) return "BEHIND" - /*if(GENITALS_ADJ_LAYER) - return "ADJ"*/ if(GENITALS_FRONT_LAYER) return "FRONT" @@ -227,14 +226,12 @@ if(!canbearoused) ADD_TRAIT(src, TRAIT_PHARMA, "pharma")//Prefs prevent unwanted organs. return - for(var/obj/item/organ/O in internal_organs) + for(var/O in internal_organs) if(istype(O, /obj/item/organ/genital)) organCheck = TRUE - if(/obj/item/organ/genital/penis) - //dna.features["has_cock"] = TRUE + if(istype(O, /obj/item/organ/genital/penis)) willyCheck = TRUE - if(/obj/item/organ/genital/breasts) - //dna.features["has_breasts"] = TRUE//Goddamnit get in there. + if(istype(O, /obj/item/organ/genital/breasts)) breastCheck = TRUE if(organCheck == FALSE) if(ishuman(src) && dna.species.id == "human") @@ -260,10 +257,7 @@ CRASH("H = null") if(!LAZYLEN(H.internal_organs) || ((NOGENITALS in species_traits) && !H.genital_override) || HAS_TRAIT(H, TRAIT_HUSK)) return - var/list/relevant_layers = list(GENITALS_BEHIND_LAYER, GENITALS_FRONT_LAYER) //GENITALS_ADJ_LAYER removed - var/list/standing = list() - var/size - var/aroused_state + var/list/relevant_layers = list(GENITALS_BEHIND_LAYER, GENITALS_FRONT_LAYER) for(var/L in relevant_layers) //Less hardcode H.remove_overlay(L) @@ -271,21 +265,25 @@ var/list/gen_index[GENITAL_LAYER_INDEX_LENGTH] var/list/genitals_to_add + var/list/fully_exposed for(var/obj/item/organ/genital/G in H.internal_organs) if(G.is_exposed()) //Checks appropriate clothing slot and if it's through_clothes LAZYADD(gen_index[G.layer_index], G) for(var/L in gen_index) if(L) //skip nulls LAZYADD(genitals_to_add, L) + if(!genitals_to_add) + return //Now we added all genitals that aren't internal and should be rendered //start applying overlays for(var/layer in relevant_layers) + var/list/standing = list() var/layertext = genitals_layertext(layer) for(var/A in genitals_to_add) var/obj/item/organ/genital/G = A var/datum/sprite_accessory/S - size = G.size - aroused_state = G.aroused_state + var/size = G.size + var/aroused_state = G.aroused_state switch(G.type) if(/obj/item/organ/genital/penis) S = GLOB.cock_shapes_list[G.shape] @@ -296,9 +294,6 @@ if(/obj/item/organ/genital/breasts) S = GLOB.breasts_shapes_list[G.shape] - - - if(!S || S.icon_state == "none") continue @@ -322,11 +317,16 @@ if("vag_color") genital_overlay.color = "#[H.dna.features["vag_color"]]" - standing += genital_overlay + if(layer == GENITALS_FRONT_LAYER && CHECK_BITFIELD(G.genital_flags, GENITAL_THROUGH_CLOTHES)) + LAZYADD(fully_exposed, genital_overlay) // to be added to a layer with higher priority than clothes, hence the name of the bitflag. + else + standing += genital_overlay if(LAZYLEN(standing)) - H.overlays_standing[layer] = standing.Copy() - standing = list() + H.overlays_standing[layer] = standing + + if(LAZYLEN(fully_exposed)) + H.overlays_standing[GENITALS_EXPOSED_LAYER] = fully_exposed for(var/L in relevant_layers) H.apply_overlay(L) diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm index 01a0e75710..a4c4e352ac 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm @@ -31,16 +31,13 @@ InverseChem = "BEsmaller" //At really impure vols, it just becomes 100% inverse can_synth = FALSE -/datum/reagent/fermi/breast_enlarger/on_mob_add(mob/living/carbon/M) +/datum/reagent/fermi/breast_enlarger/on_mob_metabolize(mob/living/M) . = ..() if(!ishuman(M)) //The monkey clause if(volume >= 15) //To prevent monkey breast farms var/turf/T = get_turf(M) var/obj/item/organ/genital/breasts/B = new /obj/item/organ/genital/breasts(T) - var/list/seen = viewers(8, T) - for(var/mob/S in seen) - to_chat(S, "A pair of breasts suddenly fly out of the [M]!") - //var/turf/T2 = pick(turf in view(5, M)) + M.visible_message("A pair of breasts suddenly fly out of the [M]!") var/T2 = get_random_station_turf() M.adjustBruteLoss(25) M.Knockdown(50) @@ -51,7 +48,7 @@ log_game("FERMICHEM: [M] ckey: [M.key] has ingested Sucubus milk") var/mob/living/carbon/human/H = M H.genital_override = TRUE - var/obj/item/organ/genital/breasts/B = H.getorganslot("breasts") + var/obj/item/organ/genital/breasts/B = H.getorganslot(ORGAN_SLOT_BREASTS) if(!B) H.emergent_genital_call() return @@ -103,7 +100,7 @@ M.adjustOxyLoss(5, 0) M.apply_damage(1, BRUTE, target) B.update() - ..() + return ..() /datum/reagent/fermi/breast_enlarger/overdose_process(mob/living/carbon/M) //Turns you into a female if male and ODing, doesn't touch nonbinary and object genders. @@ -135,7 +132,7 @@ var/obj/item/organ/genital/womb/nW = new nW.Insert(M) W = nW - ..() + return ..() /datum/reagent/fermi/BEsmaller name = "Modesty milk" @@ -159,7 +156,7 @@ return..() B.cached_size = B.cached_size - 0.05 B.update() - ..() + return ..() /datum/reagent/fermi/BEsmaller_hypo name = "Rectify milk" //Rectify @@ -171,19 +168,18 @@ var/sizeConv = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5) can_synth = TRUE -/datum/reagent/fermi/BEsmaller_hypo/on_mob_add(mob/living/carbon/M) +/datum/reagent/fermi/BEsmaller_hypo/on_mob_metabolize(mob/living/M) . = ..() - if(!M.getorganslot("vagina")) - if(M.dna.features["has_vag"]) - var/obj/item/organ/genital/vagina/nV = new - nV.Insert(M) - if(!M.getorganslot("womb")) - if(M.dna.features["has_womb"]) - var/obj/item/organ/genital/womb/nW = new - nW.Insert(M) + if(!ishuman(M)) + return + var/mob/living/carbon/human/H = M + if(!H.getorganslot(ORGAN_SLOT_VAGINA) && H.dna.features["has_vag"]) + H.give_genital(/obj/item/organ/genital/vagina) + if(!H.getorganslot(ORGAN_SLOT_WOMB) && H.dna.features["has_womb"]) + H.give_genital(/obj/item/organ/genital/womb) /datum/reagent/fermi/BEsmaller_hypo/on_mob_life(mob/living/carbon/M) - var/obj/item/organ/genital/breasts/B = M.getorganslot("breasts") + var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS) if(!B) return..() if(!M.dna.features["has_breasts"])//Fast fix for those who don't want it. @@ -195,7 +191,7 @@ else if(B.cached_size < (sizeConv[M.dna.features["breasts_size"]])+0.1) B.cached_size = B.cached_size + 0.05 B.update() - ..() + return ..() //////////////////////////////////////////////////////////////////////////////////////////////////// // PENIS ENLARGE @@ -216,15 +212,13 @@ InverseChem = "PEsmaller" //At really impure vols, it just becomes 100% inverse and shrinks instead. can_synth = FALSE -/datum/reagent/fermi/penis_enlarger/on_mob_add(mob/living/carbon/M) +/datum/reagent/fermi/penis_enlarger/on_mob_metabolize(mob/living/M) . = ..() if(!ishuman(M)) //Just monkeying around. if(volume >= 15) //to prevent monkey penis farms var/turf/T = get_turf(M) var/obj/item/organ/genital/penis/P = new /obj/item/organ/genital/penis(T) - var/list/seen = viewers(8, T) - for(var/mob/S in seen) - to_chat(S, "A penis suddenly flies out of the [M]!") + M.visible_message("A penis suddenly flies out of the [M]!") var/T2 = get_random_station_turf() M.adjustBruteLoss(25) M.Knockdown(50) @@ -234,7 +228,7 @@ return var/mob/living/carbon/human/H = M H.genital_override = TRUE - var/obj/item/organ/genital/penis/P = M.getorganslot("penis") + var/obj/item/organ/genital/penis/P = M.getorganslot(ORGAN_SLOT_PENIS) if(!P) H.emergent_genital_call() return @@ -277,7 +271,7 @@ M.apply_damage(2.5, BRUTE, target) P.update() - ..() + return ..() /datum/reagent/fermi/penis_enlarger/overdose_process(mob/living/carbon/M) //Turns you into a male if female and ODing, doesn't touch nonbinary and object genders. //Acute hepatic pharmacokinesis. @@ -306,7 +300,7 @@ var/obj/item/organ/genital/testicles/nT = new nT.Insert(M) T = nT - ..() + return ..() /datum/reagent/fermi/PEsmaller // Due to cozmo's request...! name = "Chastity draft" @@ -342,12 +336,13 @@ metabolization_rate = 0.5 can_synth = TRUE -/datum/reagent/fermi/PEsmaller_hypo/on_mob_add(mob/living/carbon/M) +/datum/reagent/fermi/PEsmaller_hypo/on_mob_metabolize(mob/living/M) . = ..() - if(!M.getorganslot("testicles")) - if(M.dna.features["has_balls"]) - var/obj/item/organ/genital/testicles/nT = new - nT.Insert(M) + if(!ishuman(M)) + return + var/mob/living/carbon/human/H = M + if(!H.getorganslot(ORGAN_SLOT_TESTICLES) && H.dna.features["has_balls"]) + H.give_genital(/obj/item/organ/genital/testicles) /datum/reagent/fermi/PEsmaller_hypo/on_mob_life(mob/living/carbon/M) var/obj/item/organ/genital/penis/P = M.getorganslot(ORGAN_SLOT_PENIS) @@ -362,4 +357,4 @@ else if(P.cached_length < (M.dna.features["cock_length"]+0.1)) P.cached_length = P.cached_length + 0.1 P.update() - ..() + return ..() From e66b95b9c9dd5da1d214b10112244d88438e71f8 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Sun, 1 Sep 2019 05:58:57 +0200 Subject: [PATCH 10/58] More lines of code rewriting fermis' mess. --- .../code/modules/arousal/genitals.dm | 12 +++-- .../code/modules/arousal/organs/breasts.dm | 54 +++++++++++-------- .../code/modules/arousal/organs/penis.dm | 10 ++-- .../chemistry/reagents/enlargement.dm | 35 +++++------- 4 files changed, 56 insertions(+), 55 deletions(-) diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm index f8e404713d..7b3b637e26 100644 --- a/modular_citadel/code/modules/arousal/genitals.dm +++ b/modular_citadel/code/modules/arousal/genitals.dm @@ -19,13 +19,17 @@ var/linked_organ_slot //only one of the two organs needs this to be set up. update_link() will handle linking the rest. 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() +/obj/item/organ/genital/Initialize(mapload, mob/living/carbon/human/H) . = ..() if(fluid_id) create_reagents(fluid_max_volume) if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION)) reagents.add_reagent(fluid_id, fluid_max_volume) - update() + if(H) + get_features(H) + Insert(H) + else + update() /obj/item/organ/genital/Destroy() if(linked_organ) @@ -180,9 +184,7 @@ /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 - G.get_features(src) - G.Insert(src) + G = new G(null, src) return G /obj/item/organ/genital/proc/get_features(mob/living/carbon/human/H) diff --git a/modular_citadel/code/modules/arousal/organs/breasts.dm b/modular_citadel/code/modules/arousal/organs/breasts.dm index c862e21bc5..08b99eabfa 100644 --- a/modular_citadel/code/modules/arousal/organs/breasts.dm +++ b/modular_citadel/code/modules/arousal/organs/breasts.dm @@ -12,10 +12,17 @@ masturbation_verb = "massage" orgasm_verb = "leaking" fluid_transfer_factor = 0.5 - var/breast_values = list ("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5, "f" = 6, "g" = 7, "h" = 8, "i" = 9, "j" = 10, "k" = 11, "l" = 12, "m" = 13, "n" = 14, "o" = 15, "huge" = 16, "flat" = 0) + var/list/static/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 //for enlargement SHOULD BE A NUMBER var/prev_size //For flavour texts SHOULD BE A LETTER +/obj/item/organ/genital/breasts/Initialize(mapload, mob/living/carbon/human/H) + if(!H) + cached_size = size + size = breast_values[size] + prev_size = size + return ..() + /obj/item/organ/genital/breasts/update_appearance() . = ..() var/lowershape = lowertext(shape) @@ -28,14 +35,13 @@ desc = "You see three sets of breasts, running from their chest to their belly." else desc = "You see some breasts, they seem to be quite exotic." - if(cached_size > 16) + if(size == "huge") desc = "You see [pick("some serious honkers", "a real set of badonkers", "some dobonhonkeros", "massive dohoonkabhankoloos", "two big old tonhongerekoogers", "a couple of giant bonkhonagahoogs", "a pair of humongous hungolomghnonoloughongous")]. Their volume is way beyond cupsize now, measuring in about [round(cached_size)]cm in diameter." - else if (!isnum(size)) + else if (size == "flat") desc += " They're very small and flatchested, however." else desc += " You estimate that they're [uppertext(size)]-cups." - //string = "breasts_[lowertext(shape)]_[size]-s" if(CHECK_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION) && aroused_state) desc += " They're leaking [fluid_id]." @@ -62,38 +68,40 @@ //this is far too lewd wah /obj/item/organ/genital/breasts/update_size()//wah - if(cached_size == size) - return 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, "You feel your breasts shrinking away from your body as your chest flattens out.") + to_chat(owner, "You feel your breasts shrinking away from your body as your chest flattens out.") QDEL_IN(src, 1) + return var/enlargement = FALSE - switch(cached_size) - if(0 to 0.99) //If flatchested + switch(round(cached_size)) + if(0) //flatchested size = "flat" - if(16 to INFINITY) //if Rediculous + if(1 to 8) //modest + size = breast_values[round(cached_size)] + if(9 to 15) //massive + size = breast_values[round(cached_size)] + enlargement = TRUE + if(16 to INFINITY) //rediculous size = "huge" enlargement = TRUE - if(owner && !enlargement) - if(!owner.has_status_effect(/datum/status_effect/chem/breast_enlarger)) + if(owner) + var/status_effect = owner.has_status_effect(/datum/status_effect/chem/breast_enlarger) + if(enlargement && !status_effect) owner.apply_status_effect(/datum/status_effect/chem/breast_enlarger) - size = breast_values[round(cached_size)] + else if(status_effect) + owner.remove_status_effect(/datum/status_effect/chem/breast_enlarger) if(round(cached_size) < 16)//Because byond doesn't count from 0, I have to do this. - if(isnum(prev_size)) - prev_size = breast_values[prev_size] if(owner) var/mob/living/carbon/human/H = owner if (breast_values[size] > breast_values[prev_size]) - to_chat(H, "Your breasts [pick("swell up to", "flourish into", "expand into", "burst forth into", "grow eagerly into", "amplify into")] a [uppertext(size)]-cup.") + to_chat(H, "Your breasts [pick("swell up to", "flourish into", "expand into", "burst forth into", "grow eagerly into", "amplify into")] a [uppertext(size)]-cup.") H.dna.species.handle_genitals(src) else if (breast_values[size] > 0.5) - to_chat(H, "Your breasts [pick("shrink down to", "decrease into", "diminish into", "deflate into", "shrivel regretfully into", "contracts into")] a [uppertext(size)]-cup.") + to_chat(H, "Your breasts [pick("shrink down to", "decrease into", "diminish into", "deflate into", "shrivel regretfully into", "contracts into")] a [uppertext(size)]-cup.") H.dna.species.handle_genitals(src) prev_size = size - else - size = "huge" /obj/item/organ/genital/breasts/get_features(mob/living/carbon/human/H) var/datum/dna/D = H.dna @@ -107,12 +115,12 @@ if(!isnum(size)) if(size == "flat") cached_size = 0 - prev_size = 0 - else if (cached_size == "huge") - prev_size = "huge" + else if (size == "huge") + cached_size = 16 else cached_size = breast_values[size] - prev_size = size + prev_size = size else cached_size = size + size = breast_values[size] prev_size = size diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/modular_citadel/code/modules/arousal/organs/penis.dm index ff5f216f2f..c79a522405 100644 --- a/modular_citadel/code/modules/arousal/organs/penis.dm +++ b/modular_citadel/code/modules/arousal/organs/penis.dm @@ -19,8 +19,6 @@ var/list/knotted_types = list("knotted", "barbed, knotted") /obj/item/organ/genital/penis/update_size() - if(cached_length == length) - return if(cached_length < 0)//I don't actually know what round() does to negative numbers, so to be safe!! if(owner) to_chat(owner, "You feel your tallywacker shrinking away from your body as your groin flattens out!") @@ -31,13 +29,13 @@ var/new_size var/enlargement = FALSE switch(round(cached_length)) - if(0 to 6.99) //If modest size + if(0 to 6) //If modest size new_size = 1 - if(7 to 10.99) //If large + if(7 to 10) //If large size = 2 - if(11 to 19.99) //If massive + if(11 to 19) //If massive size = 3 - if(20 to 34.99) //If massive and due for large effects + if(20 to 34) //If massive and due for large effects size = 3 enlargement = TRUE if(35 to INFINITY) //If comical diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm index a4c4e352ac..87e1567eda 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm @@ -52,10 +52,6 @@ if(!B) H.emergent_genital_call() return - if(!B.size == "huge") - var/sizeConv = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5) - B.prev_size = B.size - B.cached_size = sizeConv[B.size] /datum/reagent/fermi/breast_enlarger/on_mob_life(mob/living/carbon/M) //Increases breast size if(!ishuman(M))//Just in case @@ -87,7 +83,7 @@ nB.color = skintone2hex(H.skin_tone) nB.size = "flat" nB.cached_size = 0 - nB.prev_size = 0 + nB.prev_size = "flat" to_chat(M, "Your chest feels warm, tingling with newfound sensitivity.") M.reagents.remove_reagent(id, 5) B = nB @@ -123,15 +119,13 @@ P.cached_length = P.cached_length - 0.05 P.update() if(T) - T.Remove(M) + qdel(T) if(!V) - var/obj/item/organ/genital/vagina/nV = new - nV.Insert(M) - V = nV + V = new + V.Insert(M) if(!W) - var/obj/item/organ/genital/womb/nW = new - nW.Insert(M) - W = nW + W = new + W.Insert(M) return ..() /datum/reagent/fermi/BEsmaller @@ -232,8 +226,6 @@ if(!P) H.emergent_genital_call() return - P.prev_length = P.length - P.cached_length = P.length /datum/reagent/fermi/penis_enlarger/on_mob_life(mob/living/carbon/M) //Increases penis size, 5u = +1 inch. if(!ishuman(M)) @@ -273,7 +265,9 @@ P.update() return ..() -/datum/reagent/fermi/penis_enlarger/overdose_process(mob/living/carbon/M) //Turns you into a male if female and ODing, doesn't touch nonbinary and object genders. +/datum/reagent/fermi/penis_enlarger/overdose_process(mob/living/carbon/human/M) //Turns you into a male if female and ODing, doesn't touch nonbinary and object genders. + if(!istype(M)) + return ..() //Acute hepatic pharmacokinesis. if(HAS_TRAIT(M, TRAIT_PHARMA)) var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) @@ -292,14 +286,13 @@ if(B) B.cached_size = B.cached_size - 0.05 B.update() - if(V) - V.Remove(M) + if(M.getorganslot(ORGAN_SLOT_VAGINA)) + qdel(V) if(W) - W.Remove(M) + qdel(W) if(!T) - var/obj/item/organ/genital/testicles/nT = new - nT.Insert(M) - T = nT + T = new + T.Insert(M) return ..() /datum/reagent/fermi/PEsmaller // Due to cozmo's request...! From 6dbac16c74065a6a0c486cc8bb4b33ac33d8491b Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 3 Oct 2019 04:31:11 +0200 Subject: [PATCH 11/58] Sanitizing the fermis code biohazard. --- code/__DEFINES/citadel_defines.dm | 21 --- code/__DEFINES/status_effects.dm | 3 + .../objects/items/devices/compressionkit.dm | 41 ++-- .../chemistry/reagents/other_reagents.dm | 18 -- .../code/datums/status_effects/chems.dm | 170 ++++++++--------- .../code/modules/arousal/genitals.dm | 34 ++-- .../code/modules/arousal/organs/breasts.dm | 63 ++++--- .../code/modules/arousal/organs/penis.dm | 33 ++-- .../chemistry/reagents/enlargement.dm | 176 ++++++++---------- 9 files changed, 251 insertions(+), 308 deletions(-) diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 785dd15417..53e3723912 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -67,27 +67,6 @@ #define BREASTS_VOLUME_BASE 50 //base volume for the reagents in the breasts, multiplied by the size then multiplier. 50u for A cups, 850u for HH cups. #define BREASTS_VOLUME_MULT 1 //global multiplier for breast volume. -#define BREASTS_SIZE_FLAT 0 -#define BREASTS_SIZE_A 1 -#define BREASTS_SIZE_AA 1.5 -#define BREASTS_SIZE_B 2 -#define BREASTS_SIZE_BB 2.5 -#define BREASTS_SIZE_C 3 -#define BREASTS_SIZE_CC 3.5 -#define BREASTS_SIZE_D 4 -#define BREASTS_SIZE_DD 4.5 -#define BREASTS_SIZE_E 5 -#define BREASTS_SIZE_EE 5.5 -#define BREASTS_SIZE_F 6 -#define BREASTS_SIZE_FF 6.5 -#define BREASTS_SIZE_G 7 -#define BREASTS_SIZE_GG 7.5//Are these even real sizes? The world may never know because cup sizes make no fucking sense. -#define BREASTS_SIZE_H 8 -#define BREASTS_SIZE_HH 8.5//Largest size, ever. For now. - -#define BREASTS_SIZE_MIN BREASTS_SIZE_A -#define BREASTS_SIZE_DEF BREASTS_SIZE_C -#define BREASTS_SIZE_MAX BREASTS_SIZE_HH #define MILK_RATE 5 #define MILK_RATE_MULT 1 diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 3cd64af8c7..05309333af 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -72,6 +72,9 @@ #define STATUS_EFFECT_ICHORIAL_STAIN /datum/status_effect/ichorial_stain //Prevents a servant from being revived by vitality matrices for one minute. +#define STATUS_EFFECT_BREASTS_ENLARGEMENT /datum/status_effect/chem/breast_enlarger //Applied slowdown due to the ominous bulk. + +#define STATUS_EFFECT_PENIS_ENLARGEMENT //More applied slowdown, just like the above. ///////////// // NEUTRAL // ///////////// diff --git a/code/game/objects/items/devices/compressionkit.dm b/code/game/objects/items/devices/compressionkit.dm index 5ac958328d..a5a9377690 100644 --- a/code/game/objects/items/devices/compressionkit.dm +++ b/code/game/objects/items/devices/compressionkit.dm @@ -89,30 +89,23 @@ else to_chat(user, "Anomalous error. Summon a coder.") - if(istype(target, /mob/living)) - var/mob/living/victim = target - if(istype(victim, /mob/living/carbon/human)) - if(user.zone_selected == "groin") // pp smol. There's probably a smarter way to do this but im retarded. If you have a simpler method let me know. - var/list/organs = victim.getorganszone("groin") - for(var/internal_organ in organs) - if(istype(internal_organ, /obj/item/organ/genital/penis)) - var/obj/item/organ/genital/penis/O = internal_organ - playsound(get_turf(src), 'sound/weapons/flash.ogg', 50, 1) - victim.visible_message("[user] is preparing to shrink [victim]\'s [O.name] with their bluespace compression kit!") - if(do_mob(user, victim, 40) && charges > 0 && O.length > 0) - victim.visible_message("[user] has shrunk [victim]\'s [O.name]!") - playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 50, 1) - sparks() - flash_lighting_fx(3, 3, LIGHT_COLOR_CYAN) - charges -= 1 - O.length -= 5 - if(O.length < 1) - victim.visible_message("[user]\'s [O.name] vanishes!") - qdel(O) // no pp for you - else - O.update_size() - O.update_appearance() - + else if(ishuman(target) && user.zone_selected == BODY_ZONE_PRECISE_GROIN) + var/mob/living/carbon/human/H = target + var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS) + if(!P) + return + playsound(get_turf(src), 'sound/weapons/flash.ogg', 50, 1) + H.visible_message("[user] is preparing to shrink [H]\'s [P.name] with their bluespace compression kit!") + if(do_mob(user, H, 40) && charges > 0 && P.length > 0) + H.visible_message("[user] has shrunk [H]\'s [P.name]!") + playsound(get_turf(src), 'sound/weapons/emitter2.ogg', 50, 1) + sparks() + flash_lighting_fx(3, 3, LIGHT_COLOR_CYAN) + charges -= 1 + var/p_name = P.name + P.modify_size(-5) + if(QDELETED(P)) + H.visible_message("[H]\'s [p_name] vanishes!") /obj/item/compressionkit/attackby(obj/item/I, mob/user, params) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 2f7a8652ba..669ac602dc 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1965,24 +1965,6 @@ M.emote("nya") ..() -//Kept for legacy, I think it will break everything if you enable it. -/datum/reagent/penis_enlargement - name = "Penis Enlargement" - id = "penis_enlargement" - description = "A patented chemical forumula by Doctor Ronald Hyatt that is guaranteed to bring maximum GROWTH and LENGTH to your penis, today!" - color = "#888888" - taste_description = "chinese dragon powder" - metabolization_rate = INFINITY //So it instantly removes all of itself. Don't want to put strain on the system. - -/datum/reagent/penis_enlargement/on_mob_life(mob/living/carbon/C) - var/obj/item/organ/genital/penis/P = C.getorganslot(ORGAN_SLOT_PENIS) - if(P) - var/added_length = round(volume/30,0.01) //Every 30u gives an extra inch. Rounded to the nearest 0.01 so float fuckery doesn't occur with the division by 30. - if(added_length >= 0.20) //Only add the length if it's greater than or equal to 0.2. This is to prevent people from smoking the reagents and causing the penis to update constantly. - P.length += added_length - P.update() - ..() - /datum/reagent/changeling_string name = "UNKNOWN" id = "changeling_sting_real" diff --git a/modular_citadel/code/datums/status_effects/chems.dm b/modular_citadel/code/datums/status_effects/chems.dm index 4bc83d2af6..a14c490999 100644 --- a/modular_citadel/code/datums/status_effects/chems.dm +++ b/modular_citadel/code/datums/status_effects/chems.dm @@ -37,64 +37,62 @@ alert_type = null var/moveCalc = 1 var/cachedmoveCalc = 1 + var/last_checked_size //used to prevent potential cpu waste from happening every tick. -/datum/status_effect/chem/breast_enlarger/on_apply(mob/living/carbon/human/H)//Removes clothes, they're too small to contain you. You belong to space now. +/datum/status_effect/chem/breast_enlarger/on_apply()//Removes clothes, they're too small to contain you. You belong to space now. log_game("FERMICHEM: [owner]'s breasts has reached comical sizes. ID: [owner.key]") - var/mob/living/carbon/human/o = owner - var/items = o.get_contents() - for(var/obj/item/W in items) - if(W == o.w_uniform || W == o.wear_suit) - o.dropItemToGround(W, TRUE) - playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1) - to_chat(o, "Your clothes give, ripping into peices under the strain of your swelling breasts! Unless you manage to reduce the size of your breasts, there's no way you're going to be able to put anything on over these melons..!") - o.visible_message("[o]'s chest suddenly bursts forth, ripping their clothes off!'") - else - to_chat(o, "Your bountiful bosom is so rich with mass, you seriously doubt you'll be able to fit any clothes over it.") - return ..() + var/mob/living/carbon/human/H = owner + var/message = FALSE + if(H.w_uniform) + H.dropItemToGround(H.w_uniform, TRUE) + message = TRUE + if(H.wear_suit) + H.dropItemToGround(H.wear_suit, TRUE) + message = TRUE + if(message) + playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1) + H.visible_message("[H]'s chest suddenly bursts forth, ripping their clothes off!'", \ + "Your clothes give, ripping into peices under the strain of your swelling breasts! Unless you manage to reduce the size of your breasts, there's no way you're going to be able to put anything on over these melons..!") + else + to_chat(H, "Your bountiful bosom is so rich with mass, you seriously doubt you'll be able to fit any clothes over it.") + return ..() -/datum/status_effect/chem/breast_enlarger/tick(mob/living/carbon/human/H)//If you try to wear clothes, you fail. Slows you down if you're comically huge - var/mob/living/carbon/human/o = owner - var/obj/item/organ/genital/breasts/B = o.getorganslot("breasts") - moveCalc = 1+((round(B.cached_size) - 9)/3) //Afffects how fast you move, and how often you can click. +/datum/status_effect/chem/breast_enlarger/tick()//If you try to wear clothes, you fail. Slows you down if you're comically huge + var/mob/living/carbon/human/H = owner + var/obj/item/organ/genital/breasts/B = H.getorganslot(ORGAN_SLOT_BREASTS) if(!B) - o.remove_movespeed_modifier(BREAST_MOVEMENT_SPEED) - sizeMoveMod(1) - owner.remove_status_effect(src) - var/items = o.get_contents() - for(var/obj/item/W in items) - if(W == o.w_uniform || W == o.wear_suit) - o.dropItemToGround(W, TRUE) - playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1) - to_chat(owner, "Your enormous breasts are way too large to fit anything over them!") + H.remove_status_effect(src) + return + moveCalc = 1+((round(B.cached_size) - 9)/3) //Afffects how fast you move, and how often you can click. + var/message = FALSE + if(H.w_uniform) + H.dropItemToGround(H.w_uniform, TRUE) + message = TRUE + if(H.wear_suit) + H.dropItemToGround(H.wear_suit, TRUE) + message = TRUE + if(message) + playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1) + to_chat(H, "Your enormous breasts are way too large to fit anything over them!") + + if(last_checked_size != B.cached_size) + H.add_movespeed_modifier(BREAST_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc) + sizeMoveMod(moveCalc) + if (B.size == "huge") if(prob(1)) to_chat(owner, "Your back is feeling sore.") - var/target = o.get_bodypart(BODY_ZONE_CHEST) - o.apply_damage(0.1, BRUTE, target) - if(!B.cached_size == B.breast_values[B.prev_size]) - o.add_movespeed_modifier(BREAST_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc) - sizeMoveMod(moveCalc) - return ..() - else if (B.breast_values[B.size] > B.breast_values[B.prev_size]) - o.add_movespeed_modifier(BREAST_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc) - sizeMoveMod(moveCalc) - else if (B.breast_values[B.size] < B.breast_values[B.prev_size]) - o.add_movespeed_modifier(BREAST_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc) - sizeMoveMod(moveCalc) - if((B.cached_size) < 16) - switch(round(B.cached_size)) - if(9) - if (B.breast_values[B.prev_size] != B.breast_values[B.size]) - to_chat(o, "Your expansive chest has become a more managable size, liberating your movements.") - if(10 to INFINITY) - if (B.breast_values[B.prev_size] != B.breast_values[B.size]) - to_chat(H, "Your indulgent busom is so substantial, it's affecting your movements!") + var/target = H.get_bodypart(BODY_ZONE_CHEST) + H.apply_damage(0.1, BRUTE, target) + else if(prob(1)) - to_chat(owner, "Your back is feeling a little sore.") - ..() + to_chat(H, "Your back is feeling a little sore.") + last_checked_size = B.cached_size + ..() -/datum/status_effect/chem/breast_enlarger/on_remove(mob/living/carbon/M) +/datum/status_effect/chem/breast_enlarger/on_remove() log_game("FERMICHEM: [owner]'s breasts has reduced to an acceptable size. ID: [owner.key]") + to_chat(owner, "Your expansive chest has become a more managable size, liberating your movements.") owner.remove_movespeed_modifier(BREAST_MOVEMENT_SPEED) sizeMoveMod(1) @@ -112,51 +110,57 @@ alert_type = null var/bloodCalc var/moveCalc + var/last_checked_size //used to prevent potential cpu waste, just like the above. -/datum/status_effect/chem/penis_enlarger/on_apply(mob/living/carbon/human/H)//Removes clothes, they're too small to contain you. You belong to space now. +/datum/status_effect/chem/penis_enlarger/on_apply()//Removes clothes, they're too small to contain you. You belong to space now. log_game("FERMICHEM: [owner]'s dick has reached comical sizes. ID: [owner.key]") - var/mob/living/carbon/human/o = owner - var/items = o.get_contents() - if(o.w_uniform || o.wear_suit) - to_chat(o, "Your clothes give, ripping into peices under the strain of your swelling pecker! Unless you manage to reduce the size of your emancipated trouser snake, there's no way you're going to be able to put anything on over this girth..!") - owner.visible_message("[o]'s schlong suddenly bursts forth, ripping their clothes off!'") + var/mob/living/carbon/human/H = owner + var/message = FALSE + if(H.w_uniform) + H.dropItemToGround(H.w_uniform, TRUE) + message = TRUE + if(H.wear_suit) + H.dropItemToGround(H.wear_suit, TRUE) + message = TRUE + if(message) + playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1) + H.visible_message("[H]'s schlong suddenly bursts forth, ripping their clothes off!'", \ + "Your clothes give, ripping into peices under the strain of your swelling pecker! Unless you manage to reduce the size of your emancipated trouser snake, there's no way you're going to be able to put anything on over this girth..!") else - to_chat(o, "Your emancipated trouser snake is so ripe with girth, you seriously doubt you'll be able to fit any clothes over it.") - for(var/obj/item/W in items) - if(W == o.w_uniform || W == o.wear_suit) - o.dropItemToGround(W, TRUE) - playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1) + to_chat(H, "Your emancipated trouser snake is so ripe with girth, you seriously doubt you'll be able to fit any clothes over it.") return ..() -/datum/status_effect/chem/penis_enlarger/tick(mob/living/carbon/M) - var/mob/living/carbon/human/o = owner - var/obj/item/organ/genital/penis/P = o.getorganslot("penis") +/datum/status_effect/chem/penis_enlarger/tick() + var/mob/living/carbon/human/H = owner + var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS) + if(!P) + owner.remove_status_effect(src) + return moveCalc = 1+((round(P.length) - 21)/3) //effects how fast you can move bloodCalc = 1+((round(P.length) - 21)/15) //effects how much blood you need (I didn' bother adding an arousal check because I'm spending too much time on this organ already.) - if(!P) - o.remove_movespeed_modifier(DICK_MOVEMENT_SPEED) - o.ResetBloodVol() - owner.remove_status_effect(src) - var/items = o.get_contents() - for(var/obj/item/W in items) - if(W == o.w_uniform || W == o.wear_suit) - o.dropItemToGround(W, TRUE) - playsound(o.loc, 'sound/items/poster_ripped.ogg', 50, 1) - to_chat(owner, "Your enormous package is way to large to fit anything over!") - switch(round(P.cached_length)) - if(21) - to_chat(o, "Your rascally willy has become a more managable size, liberating your movements.") - o.remove_movespeed_modifier(DICK_MOVEMENT_SPEED) - o.AdjustBloodVol(bloodCalc) - if(22 to INFINITY) - if(prob(2)) - to_chat(o, "Your indulgent johnson is so substantial, it's taking all your blood and affecting your movements!") - o.add_movespeed_modifier(DICK_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc) - o.AdjustBloodVol(bloodCalc) + + var/message = FALSE + if(H.w_uniform) + H.dropItemToGround(H.w_uniform, TRUE) + message = TRUE + if(H.wear_suit) + H.dropItemToGround(H.wear_suit, TRUE) + message = TRUE + if(message) + playsound(H.loc, 'sound/items/poster_ripped.ogg', 50, 1) + to_chat(H, "Your enormous package is way to large to fit anything over!") + + if(P.length < 22 && H.has_movespeed_modifier(DICK_MOVEMENT_SPEED)) + to_chat(owner, "Your rascally willy has become a more managable size, liberating your movements.") + H.remove_movespeed_modifier(DICK_MOVEMENT_SPEED) + else if(P.length >= 22 && !H.has_movespeed_modifier(DICK_MOVEMENT_SPEED)) + to_chat(H, "Your indulgent johnson is so substantial, it's taking all your blood and affecting your movements!") + H.add_movespeed_modifier(DICK_MOVEMENT_SPEED, TRUE, 100, NONE, override = TRUE, multiplicative_slowdown = moveCalc) + H.AdjustBloodVol(bloodCalc) ..() -/datum/status_effect/chem/penis_enlarger/on_remove(mob/living/carbon/human/o) +/datum/status_effect/chem/penis_enlarger/on_remove() log_game("FERMICHEM: [owner]'s dick has reduced to an acceptable size. ID: [owner.key]") owner.remove_movespeed_modifier(DICK_MOVEMENT_SPEED) owner.ResetBloodVol() diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm index 7b3b637e26..593874496a 100644 --- a/modular_citadel/code/modules/arousal/genitals.dm +++ b/modular_citadel/code/modules/arousal/genitals.dm @@ -105,6 +105,9 @@ picked_organ.toggle_visibility(picked_visibility) return +/obj/item/organ/genital/proc/modify_size(modifier, min = -INFINITY, max = INFINITY) + return + /obj/item/organ/genital/proc/update_size() return @@ -215,34 +218,23 @@ if(!QDELETED(src)) dna.species.handle_genitals(src) -//fermichem procs -/mob/living/carbon/human/proc/Force_update_genitals(mob/living/carbon/human/H) //called in fermiChem - dna.species.handle_genitals(src)//should work. - //dna.species.handle_breasts(src) - //Checks to see if organs are new on the mob, and changes their colours so that they don't get crazy colours. /mob/living/carbon/human/proc/emergent_genital_call() - var/organCheck = FALSE - var/breastCheck = FALSE - var/willyCheck = FALSE if(!canbearoused) - ADD_TRAIT(src, TRAIT_PHARMA, "pharma")//Prefs prevent unwanted organs. - return - for(var/O in internal_organs) - if(istype(O, /obj/item/organ/genital)) - organCheck = TRUE - if(istype(O, /obj/item/organ/genital/penis)) - willyCheck = TRUE - if(istype(O, /obj/item/organ/genital/breasts)) - breastCheck = TRUE + return FALSE + + var/organCheck = locate(/obj/item/organ/genital) in internal_organs + var/breastCheck = getorganslot(ORGAN_SLOT_BREASTS) + var/willyCheck = getorganslot(ORGAN_SLOT_PENIS) + if(organCheck == FALSE) if(ishuman(src) && dna.species.id == "human") dna.features["genitals_use_skintone"] = TRUE dna.species.use_skintones = TRUE if(MUTCOLORS) if(src.dna.species.fixed_mut_color) - dna.features["cock_color"] = "[src.dna.species.fixed_mut_color]" - dna.features["breasts_color"] = "[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"]]" @@ -252,7 +244,7 @@ dna.features["breasts_color"] = dna.features["cock_color"] else if (willyCheck == FALSE) dna.features["cock_color"] = dna.features["breasts_color"] - return + return TRUE /datum/species/proc/handle_genitals(mob/living/carbon/human/H)//more like handle sadness if(!H)//no args @@ -263,6 +255,7 @@ for(var/L in relevant_layers) //Less hardcode H.remove_overlay(L) + H.remove_overlay(GENITALS_EXPOSED_LAYER) //start scanning for genitals var/list/gen_index[GENITAL_LAYER_INDEX_LENGTH] @@ -329,6 +322,7 @@ if(LAZYLEN(fully_exposed)) H.overlays_standing[GENITALS_EXPOSED_LAYER] = fully_exposed + H.apply_overlay(GENITALS_EXPOSED_LAYER) for(var/L in relevant_layers) H.apply_overlay(L) diff --git a/modular_citadel/code/modules/arousal/organs/breasts.dm b/modular_citadel/code/modules/arousal/organs/breasts.dm index 08b99eabfa..fe502ab66e 100644 --- a/modular_citadel/code/modules/arousal/organs/breasts.dm +++ b/modular_citadel/code/modules/arousal/organs/breasts.dm @@ -5,22 +5,21 @@ icon = 'modular_citadel/icons/obj/genitals/breasts.dmi' zone = BODY_ZONE_CHEST slot = ORGAN_SLOT_BREASTS - size = BREASTS_SIZE_DEF + size = "c" //refer to the breast_values static list below for the cups associated number values fluid_id = "milk" shape = "pair" genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH|GENITAL_FUID_PRODUCTION masturbation_verb = "massage" orgasm_verb = "leaking" fluid_transfer_factor = 0.5 - var/list/static/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 //for enlargement SHOULD BE A NUMBER - var/prev_size //For flavour texts SHOULD BE A LETTER + 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, mob/living/carbon/human/H) if(!H) - cached_size = size - size = breast_values[size] - prev_size = size + cached_size = breast_values[size] + prev_size = cached_size return ..() /obj/item/organ/genital/breasts/update_appearance() @@ -67,41 +66,47 @@ //Rediculous 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 == prev_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, "You feel your breasts shrinking away from your body as your chest flattens out.") QDEL_IN(src, 1) return var/enlargement = FALSE - switch(round(cached_size)) + switch(rounded_cached) if(0) //flatchested size = "flat" if(1 to 8) //modest - size = breast_values[round(cached_size)] + size = breast_values[rounded_cached] if(9 to 15) //massive - size = breast_values[round(cached_size)] + 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(/datum/status_effect/chem/breast_enlarger) + var/status_effect = owner.has_status_effect(STATUS_EFFECT_BREASTS_ENLARGEMENT) if(enlargement && !status_effect) - owner.apply_status_effect(/datum/status_effect/chem/breast_enlarger) + owner.apply_status_effect(STATUS_EFFECT_BREASTS_ENLARGEMENT) else if(status_effect) - owner.remove_status_effect(/datum/status_effect/chem/breast_enlarger) + owner.remove_status_effect(STATUS_EFFECT_BREASTS_ENLARGEMENT) - if(round(cached_size) < 16)//Because byond doesn't count from 0, I have to do this. - if(owner) - var/mob/living/carbon/human/H = owner - if (breast_values[size] > breast_values[prev_size]) - to_chat(H, "Your breasts [pick("swell up to", "flourish into", "expand into", "burst forth into", "grow eagerly into", "amplify into")] a [uppertext(size)]-cup.") - H.dna.species.handle_genitals(src) - else if (breast_values[size] > 0.5) - to_chat(H, "Your breasts [pick("shrink down to", "decrease into", "diminish into", "deflate into", "shrivel regretfully into", "contracts into")] a [uppertext(size)]-cup.") - H.dna.species.handle_genitals(src) - prev_size = size + 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, "Your breasts [pick("swell up to", "flourish into", "expand into", "burst forth into", "grow eagerly into", "amplify into")] a [uppertext(size)]-cup.") + else if (rounded_cached < r_prev_size) + to_chat(H, "Your breasts [pick("shrink down to", "decrease into", "diminish into", "deflate into", "shrivel regretfully into", "contracts into")] a [uppertext(size)]-cup.") /obj/item/organ/genital/breasts/get_features(mob/living/carbon/human/H) var/datum/dna/D = H.dna @@ -112,15 +117,11 @@ size = D.features["breasts_size"] shape = D.features["breasts_shape"] fluid_id = D.features["breasts_fluid"] + if(!D.features["breasts_producing"]) + DISABLE_BITFIELD(genital_flags, GENITAL_FUID_PRODUCTION) if(!isnum(size)) - if(size == "flat") - cached_size = 0 - else if (size == "huge") - cached_size = 16 - else - cached_size = breast_values[size] - prev_size = size + cached_size = breast_values[size] else cached_size = size size = breast_values[size] - prev_size = size + prev_size = cached_size diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/modular_citadel/code/modules/arousal/organs/penis.dm index c79a522405..5df9f30fdd 100644 --- a/modular_citadel/code/modules/arousal/organs/penis.dm +++ b/modular_citadel/code/modules/arousal/organs/penis.dm @@ -12,42 +12,47 @@ layer_index = PENIS_LAYER_INDEX var/length = 6 //inches var/prev_length = 6 //really should be renamed to prev_length - var/cached_length //used to detect a change in length var/girth = 4.38 var/girth_ratio = COCK_GIRTH_RATIO_DEF //0.73; check citadel_defines.dm - var/knot_girth_ratio = KNOT_GIRTH_RATIO_DEF - var/list/knotted_types = list("knotted", "barbed, knotted") + +/obj/item/organ/genital/penis/modify_size(modifier, min = -INFINITY, max = INFINITY) + var/new_value = CLAMP(length + modifier, min, max) + if(new_value == prev_length) + return + prev_length = length + length = CLAMP(length + modifier, min, max) + update() /obj/item/organ/genital/penis/update_size() - if(cached_length < 0)//I don't actually know what round() does to negative numbers, so to be safe!! + if(length < 0)//I don't actually know what round() does to negative numbers, so to be safe!! if(owner) to_chat(owner, "You feel your tallywacker shrinking away from your body as your groin flattens out!") 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(round(cached_length)) + switch(rounded_length) if(0 to 6) //If modest size new_size = 1 if(7 to 10) //If large - size = 2 + new_size = 2 if(11 to 19) //If massive - size = 3 + new_size = 3 if(20 to 34) //If massive and due for large effects - size = 3 + new_size = 3 enlargement = TRUE if(35 to INFINITY) //If comical - size = 4 //no new sprites for anything larger yet + new_size = 4 //no new sprites for anything larger yet enlargement = TRUE - length = cached_length if(owner) - var/status_effect = owner.has_status_effect(/datum/status_effect/chem/penis_enlarger) + var/status_effect = owner.has_status_effect(STATUS_EFFECT_PENIS_ENLARGEMENT) if(enlargement && !status_effect) - owner.apply_status_effect(/datum/status_effect/chem/penis_enlarger) + owner.apply_status_effect(STATUS_EFFECT_PENIS_ENLARGEMENT) else if(status_effect) - owner.remove_status_effect(/datum/status_effect/chem/penis_enlarger) + owner.remove_status_effect(STATUS_EFFECT_PENIS_ENLARGEMENT) if(linked_organ) linked_organ.update_size(new_size - size) size = new_size @@ -57,7 +62,6 @@ to_chat(owner, "Your [pick(GLOB.gentlemans_organ_names)] [pick("swells up to", "flourishes into", "expands into", "bursts forth into", "grows eagerly into", "amplifys into")] a [uppertext(round(length))] inch penis.") else if ((round(length) < round(prev_length)) && (length > 0.5)) to_chat(owner, "Your [pick(GLOB.gentlemans_organ_names)] [pick("shrinks down to", "decreases into", "diminishes into", "deflates into", "shrivels regretfully into", "contracts into")] a [uppertext(round(length))] inch penis.") - prev_length = length icon_state = sanitize_text("penis_[shape]_[size]") girth = (length * girth_ratio)//Is it just me or is this ludicous, why not make it exponentially decay? @@ -92,4 +96,3 @@ girth_ratio = D.features["cock_girth_ratio"] shape = D.features["cock_shape"] prev_length = length - cached_length = length diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm index 87e1567eda..d6e0297581 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm @@ -30,6 +30,7 @@ InverseChemVal = 0.35 InverseChem = "BEsmaller" //At really impure vols, it just becomes 100% inverse can_synth = FALSE + var/message_spam = FALSE /datum/reagent/fermi/breast_enlarger/on_mob_metabolize(mob/living/M) . = ..() @@ -45,13 +46,9 @@ B.throw_at(T2, 8, 1) M.reagents.remove_reagent(id, volume) return - log_game("FERMICHEM: [M] ckey: [M.key] has ingested Sucubus milk") var/mob/living/carbon/human/H = M - H.genital_override = TRUE - var/obj/item/organ/genital/breasts/B = H.getorganslot(ORGAN_SLOT_BREASTS) - if(!B) - H.emergent_genital_call() - return + if(!H.getorganslot(ORGAN_SLOT_BREASTS) && H.emergent_genital_call()) + H.genital_override = TRUE /datum/reagent/fermi/breast_enlarger/on_mob_life(mob/living/carbon/M) //Increases breast size if(!ishuman(M))//Just in case @@ -62,46 +59,45 @@ if(!B) //If they don't have breasts, give them breasts. //If they have Acute hepatic pharmacokinesis, then route processing though liver. - if(HAS_TRAIT(M, TRAIT_PHARMA)) - var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) + if(HAS_TRAIT(H, TRAIT_PHARMA) || !H.canbearoused) + var/obj/item/organ/liver/L = H.getorganslot(ORGAN_SLOT_LIVER) if(L) - L.swelling+= 0.05 - return..() + L.swelling += 0.05 else - M.adjustToxLoss(1) - return..() + H.adjustToxLoss(1) + return..() //otherwise proceed as normal - var/obj/item/organ/genital/breasts/nB = new - nB.Insert(M) - if(nB) - if(M.dna.species.use_skintones && M.dna.features["genitals_use_skintone"]) - nB.color = skintone2hex(H.skin_tone) - else if(M.dna.features["breasts_color"]) - nB.color = "#[M.dna.features["breasts_color"]]" - else - nB.color = skintone2hex(H.skin_tone) - nB.size = "flat" - nB.cached_size = 0 - nB.prev_size = "flat" - to_chat(M, "Your chest feels warm, tingling with newfound sensitivity.") - M.reagents.remove_reagent(id, 5) - B = nB + B = new + if(H.dna.species.use_skintones && H.dna.features["genitals_use_skintone"]) + B.color = skintone2hex(H.skin_tone) + else if(M.dna.features["breasts_color"]) + B.color = "#[M.dna.features["breasts_color"]]" + else + B.color = skintone2hex(H.skin_tone) + B.size = "flat" + B.cached_size = 0 + B.prev_size = 0 + to_chat(H, "Your chest feels warm, tingling with newfound sensitivity.") + H.reagents.remove_reagent(id, 5) + B.Insert(H) + //If they have them, increase size. If size is comically big, limit movement and rip clothes. - B.cached_size = B.cached_size + 0.05 - if (B.cached_size >= 8.5 && B.cached_size < 9) - if(H.w_uniform || H.wear_suit) - var/target = M.get_bodypart(BODY_ZONE_CHEST) - to_chat(M, "Your breasts begin to strain against your clothes tightly!") - M.adjustOxyLoss(5, 0) - M.apply_damage(1, BRUTE, target) - B.update() + B.modify_size(0.05) + + if (ISINRANGE_EX(B.cached_size, 8.5, 9) && (H.w_uniform || H.wear_suit)) + var/target = H.get_bodypart(BODY_ZONE_CHEST) + if(!message_spam) + to_chat(H, "Your breasts begin to strain against your clothes tightly!") + message_spam = TRUE + H.adjustOxyLoss(5, 0) + H.apply_damage(1, BRUTE, target) return ..() /datum/reagent/fermi/breast_enlarger/overdose_process(mob/living/carbon/M) //Turns you into a female if male and ODing, doesn't touch nonbinary and object genders. //Acute hepatic pharmacokinesis. - if(HAS_TRAIT(M, TRAIT_PHARMA)) + if(HAS_TRAIT(M, TRAIT_PHARMA) || !M.canbearoused) var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) L.swelling+= 0.05 return ..() @@ -116,8 +112,7 @@ M.visible_message("[M] suddenly looks more feminine!", "You suddenly feel more feminine!") if(P) - P.cached_length = P.cached_length - 0.05 - P.update() + P.modify_size(-0.05) if(T) qdel(T) if(!V) @@ -141,15 +136,14 @@ var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS) if(!B) //Acute hepatic pharmacokinesis. - if(HAS_TRAIT(M, TRAIT_PHARMA)) + if(HAS_TRAIT(M, TRAIT_PHARMA) || !M.canbearoused) var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) L.swelling-= 0.05 return ..() //otherwise proceed as normal return..() - B.cached_size = B.cached_size - 0.05 - B.update() + B.modify_size(-0.05) return ..() /datum/reagent/fermi/BEsmaller_hypo @@ -176,15 +170,13 @@ var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS) if(!B) return..() - if(!M.dna.features["has_breasts"])//Fast fix for those who don't want it. - B.cached_size = B.cached_size - 0.1 - B.update() - else if(B.cached_size > (sizeConv[M.dna.features["breasts_size"]]+0.1)) - B.cached_size = B.cached_size - 0.05 - B.update() - else if(B.cached_size < (sizeConv[M.dna.features["breasts_size"]])+0.1) - B.cached_size = B.cached_size + 0.05 - B.update() + var/optimal_size = B.breast_values[M.dna.features["breasts_size"]] + if(!optimal_size)//Fast fix for those who don't want it. + B.modify_size(-0.1) + else if(B.cached_size > optimal_size) + B.modify_size(-0.05, optimal_size) + else if(B.cached_size < optimal_size) + B.modify_size(0.05, 0, optimal_size) return ..() //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -205,6 +197,7 @@ InverseChemVal = 0.35 InverseChem = "PEsmaller" //At really impure vols, it just becomes 100% inverse and shrinks instead. can_synth = FALSE + var/message_spam = FALSE /datum/reagent/fermi/penis_enlarger/on_mob_metabolize(mob/living/M) . = ..() @@ -221,55 +214,48 @@ M.reagents.remove_reagent(id, volume) return var/mob/living/carbon/human/H = M - H.genital_override = TRUE - var/obj/item/organ/genital/penis/P = M.getorganslot(ORGAN_SLOT_PENIS) - if(!P) - H.emergent_genital_call() - return + if(!H.getorganslot(ORGAN_SLOT_PENIS) && H.emergent_genital_call()) + H.genital_override = TRUE /datum/reagent/fermi/penis_enlarger/on_mob_life(mob/living/carbon/M) //Increases penis size, 5u = +1 inch. if(!ishuman(M)) - return + return ..() var/mob/living/carbon/human/H = M - var/obj/item/organ/genital/penis/P = M.getorganslot(ORGAN_SLOT_PENIS) + var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS) if(!P)//They do have a preponderance for escapism, or so I've heard. //If they have Acute hepatic pharmacokinesis, then route processing though liver. - if(HAS_TRAIT(M, TRAIT_PHARMA)) - var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) + if(HAS_TRAIT(H, TRAIT_PHARMA) || !H.canbearoused) + var/obj/item/organ/liver/L = H.getorganslot(ORGAN_SLOT_LIVER) if(L) - L.swelling+= 0.05 - return..() + L.swelling += 0.05 else - M.adjustToxLoss(1) - return..() + H.adjustToxLoss(1) + return ..() //otherwise proceed as normal - var/obj/item/organ/genital/penis/nP = new - nP.Insert(M) - if(nP) - nP.length = 1 - to_chat(M, "Your groin feels warm, as you feel a newly forming bulge down below.") - nP.cached_length = 1 - nP.prev_length = 1 - M.reagents.remove_reagent(id, 5) - P = nP + P = new + P.length = 1 + to_chat(H, "Your groin feels warm, as you feel a newly forming bulge down below.") + P.prev_length = 1 + H.reagents.remove_reagent(id, 5) + P.Insert(H) - P.cached_length = P.cached_length + 0.1 - if (P.cached_length >= 20.5 && P.cached_length < 21) - if(H.w_uniform || H.wear_suit) - var/target = M.get_bodypart(BODY_ZONE_CHEST) - to_chat(M, "Your cock begin to strain against your clothes tightly!") - M.apply_damage(2.5, BRUTE, target) + P.modify_size(0.1) + if (ISINRANGE_EX(P.length, 20.5, 21) && (H.w_uniform || H.wear_suit)) + var/target = H.get_bodypart(BODY_ZONE_CHEST) + if(!message_spam) + to_chat(H, "Your cock begin to strain against your clothes tightly!") + message_spam = TRUE + H.apply_damage(2.5, BRUTE, target) - P.update() return ..() /datum/reagent/fermi/penis_enlarger/overdose_process(mob/living/carbon/human/M) //Turns you into a male if female and ODing, doesn't touch nonbinary and object genders. if(!istype(M)) return ..() //Acute hepatic pharmacokinesis. - if(HAS_TRAIT(M, TRAIT_PHARMA)) + if(HAS_TRAIT(M, TRAIT_PHARMA) || !M.canbearoused) var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) L.swelling+= 0.05 return..() @@ -284,8 +270,7 @@ M.visible_message("[M] suddenly looks more masculine!", "You suddenly feel more masculine!") if(B) - B.cached_size = B.cached_size - 0.05 - B.update() + B.modify_size(-0.05) if(M.getorganslot(ORGAN_SLOT_VAGINA)) qdel(V) if(W) @@ -305,6 +290,8 @@ can_synth = FALSE /datum/reagent/fermi/PEsmaller/on_mob_life(mob/living/carbon/M) + if(!ishuman(M)) + return ..() var/mob/living/carbon/human/H = M var/obj/item/organ/genital/penis/P = H.getorganslot(ORGAN_SLOT_PENIS) if(!P) @@ -312,12 +299,9 @@ if(HAS_TRAIT(M, TRAIT_PHARMA)) var/obj/item/organ/liver/L = M.getorganslot(ORGAN_SLOT_LIVER) L.swelling-= 0.05 - return..() - - //otherwise proceed as normal return..() - P.cached_length = P.cached_length - 0.1 - P.update() + + P.modify_size(-0.1) ..() /datum/reagent/fermi/PEsmaller_hypo @@ -334,6 +318,8 @@ if(!ishuman(M)) return var/mob/living/carbon/human/H = M + if(!H.getorganslot(ORGAN_SLOT_PENIS) && H.dna.features["has_cock"]) + H.give_genital(/obj/item/organ/genital/penis) if(!H.getorganslot(ORGAN_SLOT_TESTICLES) && H.dna.features["has_balls"]) H.give_genital(/obj/item/organ/genital/testicles) @@ -341,13 +327,11 @@ var/obj/item/organ/genital/penis/P = M.getorganslot(ORGAN_SLOT_PENIS) if(!P) return ..() - if(!M.dna.features["has_cock"])//Fast fix for those who don't want it. - P.cached_length = P.cached_length - 0.2 - P.update() - else if(P.cached_length > (M.dna.features["cock_length"]+0.1)) - P.cached_length = P.cached_length - 0.1 - P.update() - else if(P.cached_length < (M.dna.features["cock_length"]+0.1)) - P.cached_length = P.cached_length + 0.1 - P.update() + var/optimal_size = M.dna.features["cock_length"] + if(!optimal_size)//Fast fix for those who don't want it. + P.modify_size(-0.2) + else if(P.length > optimal_size) + P.modify_size(-0.1, optimal_size) + else if(P.length < optimal_size) + P.modify_size(0.1, 0, optimal_size) return ..() From 8a36c007cd3384f14b1e6f3a6d347044d82250db Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 3 Oct 2019 04:38:36 +0200 Subject: [PATCH 12/58] unatomized sin. --- code/modules/mob/living/carbon/human/species.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index d2e8cab240..9e3b40c9d3 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -507,7 +507,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(H.hidden_underwear) H.underwear = "Nude" else - H.saved_underwear = H.underwear + H.underwear = H.saved_underwear var/datum/sprite_accessory/underwear/bottom/B = GLOB.underwear_list[H.underwear] if(B) var/mutable_appearance/MA = mutable_appearance(B.icon, B.icon_state, -BODY_LAYER) @@ -519,7 +519,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(H.hidden_undershirt) H.undershirt = "Nude" else - H.saved_undershirt = H.undershirt + H.undershirt = H.saved_undershirt var/datum/sprite_accessory/underwear/top/T = GLOB.undershirt_list[H.undershirt] if(T) var/mutable_appearance/MA @@ -535,7 +535,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(H.hidden_socks) H.socks = "Nude" else - H.saved_socks = H.socks + H.socks = H.saved_socks var/datum/sprite_accessory/underwear/socks/S = GLOB.socks_list[H.socks] if(S) var/digilegs = (DIGITIGRADE in species_traits) ? "_d" : "" From 7c77f2d2e3b7c90c8f1a54f6b4bf5b2a0835b233 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 3 Oct 2019 08:57:35 +0200 Subject: [PATCH 13/58] testing... --- code/__DEFINES/status_effects.dm | 2 +- .../code/modules/arousal/genitals.dm | 14 +++++++++++--- .../code/modules/arousal/organs/breasts.dm | 4 ++-- .../code/modules/arousal/organs/penis.dm | 10 ++++++---- .../code/modules/arousal/organs/testicles.dm | 15 +++++---------- modular_citadel/icons/obj/genitals/hud.dmi | Bin 2019 -> 1992 bytes 6 files changed, 25 insertions(+), 20 deletions(-) diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index 05309333af..135a8eb679 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -74,7 +74,7 @@ #define STATUS_EFFECT_BREASTS_ENLARGEMENT /datum/status_effect/chem/breast_enlarger //Applied slowdown due to the ominous bulk. -#define STATUS_EFFECT_PENIS_ENLARGEMENT //More applied slowdown, just like the above. +#define STATUS_EFFECT_PENIS_ENLARGEMENT /datum/status_effect/chem/penis_enlarger //More applied slowdown, just like the above. ///////////// // NEUTRAL // ///////////// diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm index 593874496a..d94f70ecef 100644 --- a/modular_citadel/code/modules/arousal/genitals.dm +++ b/modular_citadel/code/modules/arousal/genitals.dm @@ -16,7 +16,7 @@ var/aroused_state = FALSE //Boolean used in icon_state strings var/aroused_amount = 50 //This is a num from 0 to 100 for arousal percentage for when to use arousal state icons. var/obj/item/organ/genital/linked_organ - var/linked_organ_slot //only one of the two organs needs this to be set up. update_link() will handle linking the rest. + var/linked_organ_slot //used for linking an apparatus' organ to its other half on update_link(). var/layer_index = GENITAL_LAYER_INDEX //Order should be very important. FIRST vagina, THEN testicles, THEN penis, as this affects the order they are rendered in. /obj/item/organ/genital/Initialize(mapload, mob/living/carbon/human/H) @@ -114,7 +114,6 @@ /obj/item/organ/genital/proc/update_appearance() if(!owner || owner.stat == DEAD) aroused_state = FALSE - return /obj/item/organ/genital/on_life() if(!reagents || !owner) @@ -138,9 +137,13 @@ /obj/item/organ/genital/proc/update_link(removing = FALSE) if(!removing && owner) + if(linked_organ) + return linked_organ = owner.getorganslot(linked_organ_slot) if(linked_organ) linked_organ.linked_organ = src + linked_organ.upon_link() + upon_link() return TRUE else if(linked_organ) @@ -148,11 +151,15 @@ 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) + RegisterSignal(owner, COMSIG_MOB_DEATH, .proc/update_appearance) /obj/item/organ/genital/Remove(mob/living/carbon/M, special = FALSE, drop_if_replaced = TRUE) . = ..() @@ -313,6 +320,7 @@ genital_overlay.color = "#[H.dna.features["vag_color"]]" if(layer == GENITALS_FRONT_LAYER && CHECK_BITFIELD(G.genital_flags, GENITAL_THROUGH_CLOTHES)) + genital_overlay.layer = -GENITALS_EXPOSED_LAYER LAZYADD(fully_exposed, genital_overlay) // to be added to a layer with higher priority than clothes, hence the name of the bitflag. else standing += genital_overlay diff --git a/modular_citadel/code/modules/arousal/organs/breasts.dm b/modular_citadel/code/modules/arousal/organs/breasts.dm index fe502ab66e..6299f68b6c 100644 --- a/modular_citadel/code/modules/arousal/organs/breasts.dm +++ b/modular_citadel/code/modules/arousal/organs/breasts.dm @@ -68,7 +68,7 @@ /obj/item/organ/genital/breasts/modify_size(modifier, min = -INFINITY, max = INFINITY) var/new_value = CLAMP(cached_size + modifier, min, max) - if(new_value == prev_size) + if(new_value == cached_size) return prev_size = cached_size cached_size = new_value @@ -97,7 +97,7 @@ 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(status_effect) + 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. diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/modular_citadel/code/modules/arousal/organs/penis.dm index 5df9f30fdd..6b9e5024df 100644 --- a/modular_citadel/code/modules/arousal/organs/penis.dm +++ b/modular_citadel/code/modules/arousal/organs/penis.dm @@ -7,6 +7,7 @@ slot = ORGAN_SLOT_PENIS masturbation_verb = "stroke" genital_flags = CAN_MASTURBATE_WITH|CAN_CLIMAX_WITH + linked_organ_slot = ORGAN_SLOT_TESTICLES fluid_transfer_factor = 0.5 size = 2 //arbitrary value derived from length and girth for sprites. layer_index = PENIS_LAYER_INDEX @@ -17,13 +18,13 @@ /obj/item/organ/genital/penis/modify_size(modifier, min = -INFINITY, max = INFINITY) var/new_value = CLAMP(length + modifier, min, max) - if(new_value == prev_length) + if(new_value == length) return prev_length = length length = CLAMP(length + modifier, min, max) update() -/obj/item/organ/genital/penis/update_size() +/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, "You feel your tallywacker shrinking away from your body as your groin flattens out!") @@ -51,10 +52,11 @@ 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(status_effect) + else if(!enlargement && status_effect) owner.remove_status_effect(STATUS_EFFECT_PENIS_ENLARGEMENT) if(linked_organ) - linked_organ.update_size(new_size - size) + linked_organ.size = CLAMP(size + new_size, BALLS_SIZE_MIN, BALLS_SIZE_MAX) + linked_organ.update() size = new_size if(owner) diff --git a/modular_citadel/code/modules/arousal/organs/testicles.dm b/modular_citadel/code/modules/arousal/organs/testicles.dm index 06f40b5b51..547674a5f1 100644 --- a/modular_citadel/code/modules/arousal/organs/testicles.dm +++ b/modular_citadel/code/modules/arousal/organs/testicles.dm @@ -14,7 +14,6 @@ fluid_id = "semen" masturbation_verb = "massage" layer_index = TESTICLES_LAYER_INDEX - var/size_linked = FALSE /obj/item/organ/genital/testicles/generate_fluid() if(!linked_organ && !update_link()) @@ -23,16 +22,12 @@ if(. && reagents.holder_full()) to_chat(owner, "Your balls finally feel full, again.") -/obj/item/organ/genital/testicles/update_link(removing = FALSE) - . = ..() - if(. && !size_linked) - size = linked_organ.size - update() - size_linked = TRUE +/obj/item/organ/genital/testicles/upon_link() + size = linked_organ.size + update_size() + update_appearance() -/obj/item/organ/genital/testicles/update_size(new_size) - if(new_size) - size = CLAMP(size + new_size, BALLS_SIZE_MIN, BALLS_SIZE_MAX) +/obj/item/organ/genital/testicles/update_size(modified = FALSE) switch(size) if(BALLS_SIZE_MIN) size_name = "average" diff --git a/modular_citadel/icons/obj/genitals/hud.dmi b/modular_citadel/icons/obj/genitals/hud.dmi index bf2adcb1fcdb9c7ca35d186f72e62ced787db730..f8c8643fe0c9a7fc80760f703b441094123a338e 100644 GIT binary patch delta 1163 zcmV;61a$l356BOYBmu{YCy699jBp11#Esqz2-1Q1C? zK~!jg?U?6VQehZ}A2X76S#Sd|E;(z}bamFdHE8JG$h|R-Z=HNzV{$fZ;O4Av(zID~ z504g}UM;=N)4QdYXA2LH=FOTman1``wHAs*K5g3iip^8(+qR95NF;3CO5mLLYv&)( zzC*`Oox61H)*YZnx2|0}e|PHGp?!dVJHP+oB|V8=z5Dd(9VqP^M7{_7puW;T^X^6T zlvrLszy1RT4jMdo(2(GvA;X4`7#T7&c!+rq9MHet|L}xNAeSo?a=B6w8pf4KLlsKv z7RU&*A2oW+*l`xdPnZ}oX>!QK3FEDM?3mG`&^>30QlYY-mWPKyoOP4KQzHDjfTD)lC0{k8#B3G=m zvx=l_t%!`k?_u?tsI?SCtyzuVLv+l#^%Sg&iN^0CcEiR^6l~lOi{Arm-m;Z~Et{F} zuxv^XGwuOy+)TT5+rq81J8{f=fV=nZKX^#;;QqZwf0f|@9zS{d?D_L&PoF%l z91rm5MS4a?`U{HJhu@RDeD&((A2fCk@cMP-dX}mSV&9{B)V@dcsC|#>>G~bFr|oy# zp03|g=opNzuK6%ZOfm3r*`&*2%r z2!G>?k@w5LB7^ zFV^|WNlYX%U!C}0JbK?3XP0FC_>onTUHoqzfB%aEWhEuDK#HH=0`C6j5(M{89)JHA dQ@;IGmY>1YmMPi=>Q(>%002ovPDHLkV1j69TRs2) delta 1190 zcmV;X1X=sY591GzBmv5?C9ncB0RI4yk&%v$j*^m+m6es3mzR{3lxS#Zo}QkXnwpN0 zG{yh`00DGTPE!Ct=GbNc005Aa1p|VABw8g-g~|%9elFn12LL#klEB&BPI&+T1S?5I zK~!jg?U?6Rl3^H!?=q97Eoj)Xz>@Zk-b%7vHW=DoV0-VKrK#;{d+)vX-n*>S5JNHQ zl#=#8^fJUu-fr^YdHo>Qx8J!q@WA05xE=rxR*Dt(DqbRYmSAVG|MA`>eM$;{a;Jcu z-v8mfN|i2CwoJM5zP9OGz8pJCm-2Ge`&6h{sdA+%LXmBXgjLvCv4W4QzG}7VHT?W) z)~a2nu4UG(Q@d78KffB)t5tQ)``4>4mPi5`Gz^qlrZli&g8+#{T)&>bYrawACQX|) zZ_%<<>o#rM0km)1rgf{9Et)rfYuco7BX@XN2c~1E&Ye32$-4xzpMfa2i#*7(J2D+) z)&q3y*1bp1UcGwu?$bA$DX(pb?d!$ZdkLc^7RTH98s$5_6J zzILXH3DO0CSpE_l-eNLP(ejI%dGiJ`3J;%=6dGqJbo13#{&zd=dzJ~=17cF+M zge7+^TDX9|ho#FRmU9rXY$<&YD zrOQ{Y+PQN18t)$9`i+~nZdPh>a)MNcl+oSzX z+hhGs+k^C-HeP5$qkRA2<9nsXKI66Tr1U+A65trHcUiJNoCAHbjNFs=y*fqDL5kWHPu%yP z4Tcn_7!03X@#KB4O-*x3s@646z5k7A>8VagPc!EH9MbOpFDCKVe27h7ay<3^_ZFJI ziT~o8N%+TK63_jB=YGI~=YGI*KVZdkKj5M0Li>IIfp-6YW6K)e4j==VPcY2Ty$k3rh^c>iON_C4DF7+AlPdK|3ZNj(bI z@1!0_r~hvHkq6UviOzi<$C#eMEwhoc_ Date: Thu, 3 Oct 2019 19:08:11 +0200 Subject: [PATCH 14/58] hopefully a performance improvement to stop genitalia from having to update everytime. --- code/__DEFINES/inventory.dm | 3 +++ code/modules/mob/living/carbon/human/inventory.dm | 4 +++- modular_citadel/code/modules/arousal/genitals.dm | 7 +++---- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index 24d381d1a8..7f1360d3ac 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -237,3 +237,6 @@ GLOBAL_LIST_INIT(security_wintercoat_allowed, typecacheof(list( //Internals checker #define GET_INTERNAL_SLOTS(C) list(C.head, C.wear_mask) + +//Slots that won't trigger humans' update_genitals() on equip(). +GLOBAL_LIST_INIT(no_genitals_update_slots, list(SLOT_L_STORE, SLOT_R_STORE, SLOT_S_STORE, SLOT_IN_BACKPACK, SLOT_LEGCUFFED, SLOT_HANDCUFFED, SLOT_HANDS, SLOT_GENERC_DEXTROUS_STORAGE)) diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index d35df6b789..084dbd83ef 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -79,7 +79,8 @@ //This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible() /mob/living/carbon/human/equip_to_slot(obj/item/I, slot) - if(!..()) //a check failed or the item has already found its slot + . = ..() + if(!.) //a check failed or the item has already found its slot return var/not_handled = FALSE //Added in case we make this type path deeper one day @@ -136,6 +137,7 @@ update_inv_s_store() else to_chat(src, "You are trying to equip this item to an unsupported inventory slot. Report this to a coder!") + not_handled = TRUE //Item is handled and in slot, valid to call callback, for this proc should always be true if(!not_handled) diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm index d94f70ecef..68759218c7 100644 --- a/modular_citadel/code/modules/arousal/genitals.dm +++ b/modular_citadel/code/modules/arousal/genitals.dm @@ -209,11 +209,10 @@ //procs to handle sprite overlays being applied to humans -/obj/item/equipped(mob/user, slot) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - H.update_genitals() +/mob/living/carbon/human/equip_to_slot(obj/item/I, slot) . = ..() + if(!. && !(slot in GLOB.no_genitals_update_slots)) //the item was successfully equipped, and the chosen slot wasn't merely storage or hands. + update_genitals() /mob/living/carbon/human/doUnEquip(obj/item/I, force) . = ..() From 59e6ed701479c9fc883970ae2a6d21a7c80e8680 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 3 Oct 2019 19:09:47 +0200 Subject: [PATCH 15/58] inventory.dm is a mess too. --- modular_citadel/code/modules/arousal/genitals.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm index 68759218c7..34c52fe51d 100644 --- a/modular_citadel/code/modules/arousal/genitals.dm +++ b/modular_citadel/code/modules/arousal/genitals.dm @@ -211,7 +211,7 @@ /mob/living/carbon/human/equip_to_slot(obj/item/I, slot) . = ..() - if(!. && !(slot in GLOB.no_genitals_update_slots)) //the item was successfully equipped, and the chosen slot wasn't merely storage or hands. + if(!. && I && slot && !(slot in GLOB.no_genitals_update_slots)) //the item was successfully equipped, and the chosen slot wasn't merely storage or hands. update_genitals() /mob/living/carbon/human/doUnEquip(obj/item/I, force) From 6bd0b85e54bc18efe5f3cd40e1b396e825c07f76 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 3 Oct 2019 19:32:11 +0200 Subject: [PATCH 16/58] I'd rather add a redundant get_held_index_of_item(I) than allow it to render privates over and over again. --- modular_citadel/code/modules/arousal/genitals.dm | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/modular_citadel/code/modules/arousal/genitals.dm b/modular_citadel/code/modules/arousal/genitals.dm index 34c52fe51d..9ecf67e4b0 100644 --- a/modular_citadel/code/modules/arousal/genitals.dm +++ b/modular_citadel/code/modules/arousal/genitals.dm @@ -211,12 +211,15 @@ /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 or hands. + 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) +/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(!.) + if(!. || no_update) return update_genitals() From ce0ba51b61b31fa4430b9519fecfd18b0b5ceb11 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Fri, 25 Oct 2019 12:52:32 +0200 Subject: [PATCH 17/58] Fixing schlongs and death. --- modular_citadel/code/modules/arousal/organs/penis.dm | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modular_citadel/code/modules/arousal/organs/penis.dm b/modular_citadel/code/modules/arousal/organs/penis.dm index 6b9e5024df..17cd35c144 100644 --- a/modular_citadel/code/modules/arousal/organs/penis.dm +++ b/modular_citadel/code/modules/arousal/organs/penis.dm @@ -38,11 +38,11 @@ switch(rounded_length) if(0 to 6) //If modest size new_size = 1 - if(7 to 10) //If large + if(7 to 11) //If large new_size = 2 - if(11 to 19) //If massive + if(12 to 20) //If massive new_size = 3 - if(20 to 34) //If massive and due for large effects + if(21 to 34) //If massive and due for large effects new_size = 3 enlargement = TRUE if(35 to INFINITY) //If comical From cbf74f63c8d85e3ee1e6126366ea5daa5b2b9c3a Mon Sep 17 00:00:00 2001 From: Poojawa Date: Tue, 29 Oct 2019 00:00:48 -0500 Subject: [PATCH 18/58] Level Order listing --- code/controllers/subsystem/job.dm | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index ea7e7ce812..efa6b8b59d 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -4,7 +4,7 @@ SUBSYSTEM_DEF(job) flags = SS_NO_FIRE var/list/occupations = list() //List of all jobs - var/list/name_occupations = list() //Dict of all jobs, keys are titles + var/list/datum/job/name_occupations = list() //Dict of all jobs, keys are titles var/list/type_occupations = list() //Dict of all jobs, keys are types var/list/unassigned = list() //Players who need jobs var/initial_players_to_assign = 0 //used for checking against population caps @@ -14,6 +14,8 @@ SUBSYSTEM_DEF(job) var/overflow_role = "Assistant" + var/list/level_order = list(JP_HIGH,JP_MEDIUM,JP_LOW) + /datum/controller/subsystem/job/Initialize(timeofday) SSmapping.HACK_LoadMapConfig() if(!occupations.len) @@ -119,7 +121,7 @@ SUBSYSTEM_DEF(job) if(player.mind && job.title in player.mind.restricted_roles) JobDebug("FOC incompatible with antagonist role, Player: [player]") continue - if(player.client.prefs.job_preferences["[job.title]"] == level) + if(player.client.prefs.job_preferences[job.title] == level) JobDebug("FOC pass, Player: [player], Level:[level]") candidates += player return candidates @@ -181,7 +183,7 @@ SUBSYSTEM_DEF(job) //it locates a head or runs out of levels to check //This is basically to ensure that there's atleast a few heads in the round /datum/controller/subsystem/job/proc/FillHeadPosition() - for(var/level = 1 to 3) + for(var/level in level_order) for(var/command_position in GLOB.command_positions) var/datum/job/job = GetJob(command_position) if(!job) @@ -218,7 +220,7 @@ SUBSYSTEM_DEF(job) if(!job) return 0 for(var/i = job.total_positions, i > 0, i--) - for(var/level = 1 to 3) + for(var/level in level_order) var/list/candidates = list() candidates = FindOccupationCandidates(job, level) if(candidates.len) @@ -304,8 +306,7 @@ SUBSYSTEM_DEF(job) // Loop through all levels from high to low var/list/shuffledoccupations = shuffle(occupations) - var/list/levels = list(JP_HIGH,JP_MEDIUM,JP_LOW) - for(var/level in levels) + for(var/level in level_order) //Check the head jobs first each level CheckHeadPositions(level) @@ -334,7 +335,7 @@ SUBSYSTEM_DEF(job) if(job.required_playtime_remaining(player.client)) JobDebug("DO player not enough xp, Player: [player], Job:[job.title]") continue - + if(!player.client.prefs.pref_species.qualifies_for_rank(job.title, player.client.prefs.features)) JobDebug("DO non-human failed, Player: [player], Job:[job.title]") continue @@ -344,7 +345,7 @@ SUBSYSTEM_DEF(job) continue // If the player wants that job on this level, then try give it to him. - if(player.client.prefs.job_preferences["[job.title]"] == level) + if(player.client.prefs.job_preferences[job.title] == level) // If the job isn't filled if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1) JobDebug("DO pass, Player: [player], Level:[level], Job:[job.title]") @@ -475,7 +476,6 @@ SUBSYSTEM_DEF(job) to_chat(M, "[job.custom_spawn_text]") if(CONFIG_GET(number/minimal_access_threshold)) to_chat(M, "As this station was initially staffed with a [CONFIG_GET(flag/jobs_have_minimal_access) ? "full crew, only your job's necessities" : "skeleton crew, additional access may"] have been added to your ID card.") - if(job && H) if(job.dresscodecompliant)// CIT CHANGE - dress code compliance equip_loadout(N, H) // CIT CHANGE - allows players to spawn with loadout items @@ -551,7 +551,7 @@ SUBSYSTEM_DEF(job) if(job.required_playtime_remaining(player.client)) young++ continue - switch(player.client.prefs.job_preferences["[job.title]"]) + switch(player.client.prefs.job_preferences[job.title]) if(JP_HIGH) high++ if(JP_MEDIUM) @@ -698,4 +698,4 @@ SUBSYSTEM_DEF(job) . |= player.mind /datum/controller/subsystem/job/proc/JobDebug(message) - log_job_debug(message) + log_job_debug(message) \ No newline at end of file From cb88fd1a44d13410d7976b09e1001c5335810024 Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 28 Oct 2019 22:58:35 -0700 Subject: [PATCH 19/58] added dynamic antag injection to config --- .../configuration/entries/game_options.dm | 16 ++++++++++++++++ code/game/gamemodes/dynamic/dynamic.dm | 4 ++++ config/game_options.txt | 6 ++++++ 3 files changed, 26 insertions(+) diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index fb974c85bc..18a7ae524d 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -376,6 +376,22 @@ config_entry_value = 6 min_val = 1 +/datum/config_entry/number/dynamic_midround_delay_min + config_entry_value = 15 + min_val = 1 + +/datum/config_entry/number/dynamic_midround_delay_max + config_entry_value = 35 + min_val = 1 + +/datum/config_entry/number/dynamic_latejoin_delay_min + config_entry_value = 5 + min_val = 1 + +/datum/config_entry/number/dynamic_latejoin_delay_min + config_entry_value = 25 + min_val = 1 + /datum/config_entry/keyed_list/dynamic_cost key_mode = KEY_MODE_TEXT value_mode = VALUE_MODE_NUM diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index 24cfddd14f..4e02379b12 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -111,6 +111,10 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1) ..() pop_per_requirement = CONFIG_GET(number/dynamic_pop_per_requirement) GLOB.dynamic_high_pop_limit = CONFIG_GET(number/dynamic_high_pop_limit) + GLOB.dynamic_latejoin_delay_min = CONFIG_GET(number/dynamic_latejoin_delay_min)*600 + GLOB.dynamic_latejoin_delay_max = CONFIG_GET(number/dynamic_latejoin_delay_max)*600 + GLOB.dynamic_midround_delay_min = CONFIG_GET(number/dynamic_midround_delay_min)*600 + GLOB.dynamic_midround_delay_max = CONFIG_GET(number/dynamic_midround_delay_max)*600 /datum/game_mode/dynamic/admin_panel() var/list/dat = list("Game Mode Panel

Game Mode Panel

") diff --git a/config/game_options.txt b/config/game_options.txt index ca58e58a5b..0194d66c02 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -258,6 +258,12 @@ EVENTS_MIN_PLAYERS_MUL 1 ### DYNAMIC MODE ### +## Injection delays: how long (in minutes) will pass before a midround or latejoin antag is injected. +DYNAMIC_MIDROUND_DELAY_MIN 15 +DYNAMIC_MIDROUND_DELAY_MAX 35 +DYNAMIC_LATEJOIN_DELAY_MIN 5 +DYNAMIC_LATEJOIN_DELAY_MAX 25 + ## How many roundstart players required for high population override to take effect. DYNAMIC_HIGH_POP_LIMIT 55 From df3d5ab51fec7dd8f7d3f7f4d7c399f3f578d131 Mon Sep 17 00:00:00 2001 From: Putnam Date: Mon, 28 Oct 2019 23:05:22 -0700 Subject: [PATCH 20/58] always gotta be one, at least --- code/controllers/configuration/entries/game_options.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 18a7ae524d..759c1baf2f 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -388,7 +388,7 @@ config_entry_value = 5 min_val = 1 -/datum/config_entry/number/dynamic_latejoin_delay_min +/datum/config_entry/number/dynamic_latejoin_delay_max config_entry_value = 25 min_val = 1 From 22c87b07913000b083e65b3f46a612a59a092460 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 29 Oct 2019 14:09:47 +0000 Subject: [PATCH 21/58] Bump pillow from 5.1.0 to 6.2.0 in /tools/mapmerge2 Bumps [pillow](https://github.com/python-pillow/Pillow) from 5.1.0 to 6.2.0. - [Release notes](https://github.com/python-pillow/Pillow/releases) - [Changelog](https://github.com/python-pillow/Pillow/blob/master/CHANGES.rst) - [Commits](https://github.com/python-pillow/Pillow/compare/5.1.0...6.2.0) Signed-off-by: dependabot[bot] --- tools/mapmerge2/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/mapmerge2/requirements.txt b/tools/mapmerge2/requirements.txt index adb42438e7..d24cb40dcc 100644 --- a/tools/mapmerge2/requirements.txt +++ b/tools/mapmerge2/requirements.txt @@ -1,3 +1,3 @@ pygit2==0.27.2 bidict==0.13.1 -Pillow==5.1.0 +Pillow==6.2.0 From 6a64647ee8a2c345cbf6c8e1e8718bedc2f2b155 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Tue, 29 Oct 2019 19:45:10 +0100 Subject: [PATCH 22/58] Fixing dogborg sleepers runtimes, how atrocious... --- .../objects/items/devices/dogborg_sleeper.dm | 249 ++++++++---------- 1 file changed, 103 insertions(+), 146 deletions(-) diff --git a/code/game/objects/items/devices/dogborg_sleeper.dm b/code/game/objects/items/devices/dogborg_sleeper.dm index c1a9136f76..3c945f464e 100644 --- a/code/game/objects/items/devices/dogborg_sleeper.dm +++ b/code/game/objects/items/devices/dogborg_sleeper.dm @@ -6,8 +6,7 @@ icon = 'icons/mob/dogborg.dmi' icon_state = "sleeper" w_class = WEIGHT_CLASS_TINY - var/mob/living/carbon/patient = null - var/mob/living/silicon/robot/hound = null + var/mob/living/carbon/patient var/inject_amount = 10 var/min_health = -100 var/cleaning = FALSE @@ -61,8 +60,18 @@ /obj/item/dogborg/sleeper/Exit(atom/movable/O) return 0 +/obj/item/dogborg/sleeper/proc/get_host() + if(!loc) + return + if(iscyborg(loc)) + return loc + else if(iscyborg(loc.loc)) + return loc.loc //cursed cyborg code + /obj/item/dogborg/sleeper/afterattack(mob/living/carbon/target, mob/living/silicon/user, proximity) - hound = loc + var/mob/living/silicon/robot/hound = get_host() + if(!hound) + return if(!proximity) return if(!iscarbon(target)) @@ -82,7 +91,8 @@ if(!in_range(src, target)) //Proximity is probably old news by now, do a new check. return //If they moved away, you can't eat them. - if(patient) return //If you try to eat two people at once, you can only eat one. + if(patient) + return //If you try to eat two people at once, you can only eat one. else //If you don't have someone in you, proceed. if(!isjellyperson(target) && ("toxin" in injection_chems)) @@ -94,14 +104,17 @@ target.forceMove(src) target.reset_perspective(src) target.ExtinguishMob() //The tongue already puts out fire stacks but being put into the sleeper shouldn't allow you to keep burning. - update_gut() + update_gut(hound) user.visible_message("[voracious ? "[hound]'s [src.name] lights up and expands as [target] slips inside into their [src.name]." : "[hound]'s sleeper indicator lights up as [target] is scooped up into [hound.p_their()] [src]."]", \ "Your [voracious ? "[src.name] lights up as [target] slips into" : "sleeper indicator light shines brightly as [target] is scooped inside"] your [src]. Life support functions engaged.") message_admins("[key_name(hound)] has sleeper'd [key_name(patient)] as a dogborg. [ADMIN_JMP(src)]") playsound(hound, 'sound/effects/bin_close.ogg', 100, 1) /obj/item/dogborg/sleeper/container_resist(mob/living/user) - hound = loc + var/mob/living/silicon/robot/hound = get_host() + if(!hound) + go_out(user) + return user.changeNext_move(CLICK_CD_BREAKOUT) user.last_special = world.time + CLICK_CD_BREAKOUT if(user.a_intent == INTENT_HELP) @@ -113,55 +126,41 @@ "[voracious ? "You start struggling inside of [src]'s tight, flexible confines," : "You start pounding against the metallic walls of [src],"] trying to trigger the release... (this will take about [DisplayTimeText(breakout_time)].)", \ "You hear a [voracious ? "couple of thumps" : "loud banging noise"] coming from within [hound].") if(do_after(user, breakout_time, target = src)) - if(!user || user.stat != CONSCIOUS || user.loc != src ) - return user.visible_message("[user] successfully broke out of [hound.name]!", \ "You successfully break out of [hound.name]!") - go_out() + go_out(user, hound) -/obj/item/dogborg/sleeper/proc/go_out(var/target) - hound = loc - hound.setClickCooldown(50) - var/voracious = TRUE - if(!hound.client || !(hound.client.prefs.cit_toggles & MEDIHOUND_SLEEPER)) - voracious = FALSE - else - for(var/mob/M in contents) - if(!M.client || !(M.client.prefs.cit_toggles & MEDIHOUND_SLEEPER)) - voracious = FALSE - if(length(contents) > 0) - hound.visible_message("[voracious ? "[hound] empties out [hound.p_their()] contents via [hound.p_their()] release port." : "[hound]'s underside slides open with an audible clunk before [hound.p_their()] [src] flips over, carelessly dumping its contents onto the ground below [hound.p_them()] before closing right back up again."]", \ - "[voracious ? "You empty your contents via your release port." : "You open your sleeper hatch, quickly releasing all of the contents within before closing it again."]") - if(target) - if(iscarbon(target)) - var/mob/living/carbon/person = target - person.forceMove(get_turf(src)) - person.reset_perspective() - else - var/obj/T = target - T.loc = hound.loc +/obj/item/dogborg/sleeper/proc/go_out(atom/movable/target, mob/living/silicon/robot/hound) + var/voracious = hound ? TRUE : FALSE + var/list/targets = target && hound ? list(target) : contents + if(hound) + hound.setClickCooldown(50) + if(!hound.client || !(hound.client.prefs.cit_toggles & MEDIHOUND_SLEEPER)) + voracious = FALSE else - for(var/C in contents) - if(iscarbon(C)) - var/mob/living/carbon/person = C - person.forceMove(get_turf(src)) - person.reset_perspective() - else - var/obj/T = C - T.loc = hound.loc - items_preserved.Cut() - update_gut() - cleaning = FALSE + for(var/mob/M in targets) + if(!M.client || !(M.client.prefs.cit_toggles & MEDIHOUND_SLEEPER)) + voracious = FALSE + if(length(targets)) + if(hound) + hound.visible_message("[voracious ? "[hound] empties out [hound.p_their()] contents via [hound.p_their()] release port." : "[hound]'s underside slides open with an audible clunk before [hound.p_their()] [src] flips over, carelessly dumping its contents onto the ground below [hound.p_them()] before closing right back up again."]", \ + "[voracious ? "You empty your contents via your release port." : "You open your sleeper hatch, quickly releasing all of the contents within before closing it again."]") + for(var/a in contents) + var/atom/movable/AM = a + AM.forceMove(get_turf(src)) + if(ismob(AM)) + var/mob/M = AM + M.reset_perspective() playsound(loc, voracious ? 'sound/effects/splat.ogg' : 'sound/effects/bin_close.ogg', 50, 1) - - else //You clicked eject with nothing in you, let's just reset stuff to be sure. - items_preserved.Cut() - cleaning = FALSE - update_gut() + items_preserved.Cut() + cleaning = FALSE + if(hound) + update_gut(hound) /obj/item/dogborg/sleeper/attack_self(mob/user) - if(..()) + . = ..() + if(. || !iscyborg(user)) return ui_interact(user) @@ -219,30 +218,31 @@ return data /obj/item/dogborg/sleeper/ui_act(action, params) - if(..()) + . = ..() + if(. || !iscyborg(usr)) return switch(action) if("eject") - go_out() + go_out(null, usr) . = TRUE if("inject") var/chem = params["chem"] if(!patient) return - inject_chem(chem) + inject_chem(chem, usr) . = TRUE if("cleaning") if(!contents) to_chat(src, "Your [src] is already cleaned.") return if(patient) - to_chat(patient, "[hound.name]'s [src] fills with caustic enzymes around you!") + to_chat(patient, "[usr.name]'s [src] fills with caustic enzymes around you!") to_chat(src, "Cleaning process enabled.") - clean_cycle() + clean_cycle(usr) . = TRUE -/obj/item/dogborg/sleeper/proc/update_gut() +/obj/item/dogborg/sleeper/proc/update_gut(mob/living/silicon/robot/hound) //Well, we HAD one, what happened to them? var/prociconupdate = FALSE var/currentenvy = hound.sleeper_nv @@ -291,7 +291,7 @@ //Update icon and return new patient hound.update_icons() - return(C) + return //Cleaning looks better with red on, even with nobody in it if(cleaning && !patient) @@ -307,8 +307,10 @@ hound.update_icons() //Gurgleborg process -/obj/item/dogborg/sleeper/proc/clean_cycle() +/obj/item/dogborg/sleeper/proc/clean_cycle(mob/living/silicon/robot/hound) //Sanity + if(!hound) + return for(var/I in items_preserved) if(!(I in contents)) items_preserved -= I @@ -320,13 +322,12 @@ if(cleaning_cycles) cleaning_cycles-- cleaning = TRUE - for(var/mob/living/carbon/human/T in (touchable_items)) - if((T.status_flags & GODMODE) || !T.digestable) - items_preserved += T + for(var/mob/living/carbon/C in (touchable_items)) + if((C.status_flags & GODMODE) || !C.digestable) + items_preserved += C else - T.adjustBruteLoss(2) - T.adjustFireLoss(3) - update_gut() + C.adjustBruteLoss(2) + C.adjustFireLoss(3) if(contents) var/atom/target = pick(touchable_items) if(iscarbon(target)) //Handle the target being a mob @@ -359,7 +360,6 @@ if(!T.dropItemToGround(W)) qdel(W) qdel(T) - update_gut() //Handle the target being anything but a mob else if(isobj(target)) var/obj/T = target @@ -374,12 +374,10 @@ cleaning_cycles = initial(cleaning_cycles) cleaning = FALSE to_chat(hound, "Your [src] chimes it ends its self-cleaning cycle.")//Belly is entirely empty - update_gut() if(!length(contents)) to_chat(hound, "Your [src] is now clean. Ending self-cleaning cycle.") cleaning = FALSE - update_gut() //sound effects if(prob(50)) @@ -397,13 +395,17 @@ else if(H in contents) H.playsound_local(source, null, 65, falloff = 0, S = prey_digest) + update_gut(hound) + if(cleaning) - addtimer(CALLBACK(src, .proc/clean_cycle), 50) + addtimer(CALLBACK(src, .proc/clean_cycle, hound), 50) /obj/item/dogborg/sleeper/proc/CheckAccepted(obj/item/I) return is_type_in_typecache(I, important_items) -/obj/item/dogborg/sleeper/proc/inject_chem(chem) +/obj/item/dogborg/sleeper/proc/inject_chem(chem, mob/living/silicon/robot/hound) + if(!hound) + return if(hound.cell.charge <= 800) //This is so borgs don't kill themselves with it. Remember, 750 charge used every injection. to_chat(hound, "You don't have enough power to synthesize fluids.") return @@ -438,40 +440,27 @@ else . = ..() -/obj/item/dogborg/sleeper/K9/afterattack(var/atom/movable/target, mob/living/silicon/user, proximity) - hound = loc +/obj/item/dogborg/sleeper/K9/afterattack(mob/living/carbon/target, mob/living/silicon/user, proximity) + var/mob/living/silicon/robot/hound = get_host() + if(!hound || !istype(target) || !proximity || target.anchored) + return + if (!target.devourable) + to_chat(user, "The target registers an error code. Unable to insert into [src].") + return + if(target) + to_chat(user,"Your [src] is already occupied.") + return + if(target.buckled) + to_chat(user,"[target] is buckled and can not be put into your [src].") + return + user.visible_message("[hound.name] is ingesting [target] into their [src].", "You start ingesting [target] into your [src.name]...") + if(do_after(user, 30, target = target) && !patient && !target.buckled) + target.forceMove(src) + target.reset_perspective(src) + update_gut(hound) + user.visible_message("[hound.name]'s mobile brig clunks in series as [target] slips inside.", "Your mobile brig groans lightly as [target] slips inside.") + playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) // Really don't need ERP sound effects for robots - if(!istype(target)) - return - if(!proximity) - return - if(target.anchored) - return - if(isobj(target)) - to_chat(user, "You are above putting such trash inside of yourself.") - return - if(iscarbon(target)) - var/mob/living/carbon/brigman = target - if (!brigman.devourable) - to_chat(user, "The target registers an error code. Unable to insert into [src].") - return - if(patient) - to_chat(user,"Your [src] is already occupied.") - return - if(brigman.buckled) - to_chat(user,"[brigman] is buckled and can not be put into your [src].") - return - user.visible_message("[hound.name] is ingesting [brigman] into their [src].", "You start ingesting [brigman] into your [src.name]...") - if(do_after(user, 30, target = brigman) && !patient && !brigman.buckled) - if(!in_range(src, brigman)) //Proximity is probably old news by now, do a new check. - return //If they moved away, you can't eat them. - brigman.forceMove(src) - brigman.reset_perspective(src) - update_gut() - user.visible_message("[hound.name]'s mobile brig clunks in series as [brigman] slips inside.", "Your mobile brig groans lightly as [brigman] slips inside.") - playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) // Really don't need ERP sound effects for robots - return - return /obj/item/dogborg/sleeper/compactor //Janihound gut. name = "garbage processor" @@ -489,31 +478,25 @@ else . = ..() -/obj/item/dogborg/sleeper/compactor/afterattack(var/atom/movable/target, mob/living/silicon/user, proximity)//GARBO NOMS - hound = loc - var/obj/item/target_obj = target - if(!istype(target)) - return - if(!proximity) - return - if(target.anchored) +/obj/item/dogborg/sleeper/compactor/afterattack(atom/movable/target, mob/living/silicon/user, proximity)//GARBO NOMS + var/mob/living/silicon/robot/hound = get_host() + if(!hound || !istype(target) || !proximity || target.anchored) return if(length(contents) > (max_item_count - 1)) to_chat(user,"Your [src] is full. Eject or process contents to continue.") return - if(isobj(target)) - if(CheckAccepted(target)) - to_chat(user,"\The [target] registers an error code to your [src]") + if(isitem(target)) + var/obj/item/I = target + if(CheckAccepted(I)) + to_chat(user,"[I] registers an error code to your [src]") return - if(target_obj.w_class > WEIGHT_CLASS_NORMAL) - to_chat(user,"\The [target] is too large to fit into your [src]") + if(I.w_class > WEIGHT_CLASS_NORMAL) + to_chat(user,"[I] is too large to fit into your [src]") return - user.visible_message("[hound.name] is ingesting [target.name] into their [src.name].", "You start ingesting [target] into your [src.name]...") + user.visible_message("[hound.name] is ingesting [I] into their [src.name].", "You start ingesting [target] into your [src.name]...") if(do_after(user, 15, target = target) && length(contents) < max_item_count) - if(!in_range(src, target)) //Proximity is probably old news by now, do a new check. - return //If they moved away, you can't eat them. This still applies to items, don't magically eat things I picked up already. - target.forceMove(src) - user.visible_message("[hound.name]'s garbage processor groans lightly as [target.name] slips inside.", "Your garbage compactor groans lightly as [target] slips inside.") + I.forceMove(src) + I.visible_message("[hound.name]'s garbage processor groans lightly as [I] slips inside.", "Your garbage compactor groans lightly as [I] slips inside.") playsound(hound, 'sound/machines/disposalflush.ogg', 50, 1) if(length(contents) > 11) //grow that tum after a certain junk amount hound.sleeper_r = 1 @@ -523,9 +506,9 @@ hound.update_icons() return - else if(iscarbon(target)) - var/mob/living/carbon/trashman = target - if (!trashman.devourable) + if(iscarbon(target) || issilicon(target)) + var/mob/living/trashman = target + if(!trashman.devourable) to_chat(user, "[target] registers an error code to your [src]") return if(patient) @@ -536,34 +519,8 @@ return user.visible_message("[hound.name] is ingesting [trashman] into their [src].", "You start ingesting [trashman] into your [src.name]...") if(do_after(user, 30, target = trashman) && !patient && !trashman.buckled && length(contents) < max_item_count) - if(!in_range(src, trashman)) //Proximity is probably old news by now, do a new check. - return //If they moved away, you can't eat them. trashman.forceMove(src) trashman.reset_perspective(src) update_gut() user.visible_message("[hound.name]'s garbage processor groans lightly as [trashman] slips inside.", "Your garbage compactor groans lightly as [trashman] slips inside.") playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) - return - else if(issilicon(target)) - var/mob/living/silicon/trashbot = target - if (!trashbot.devourable) - to_chat(user, "[target] registers an error code to your [src]") - return - if(patient) - to_chat(user,"Your [src] is already occupied.") - return - if(trashbot.buckled) - to_chat(user,"[trashbot] is buckled and can not be put into your [src].") - return - user.visible_message("[hound.name] is ingesting [trashbot] into their [src].", "You start ingesting [trashbot] into your [src.name]...") - if(do_after(user, 30, target = trashbot) && !patient && !trashbot.buckled && length(contents) < max_item_count) - if(!in_range(src, trashbot)) //Proximity is probably old news by now, do a new check. - return //If they moved away, you can't eat them. - trashbot.forceMove(src) - trashbot.reset_perspective(src) - update_gut() - user.visible_message("[hound.name]'s garbage processor groans lightly as [trashbot] slips inside.", "Your garbage compactor groans lightly as [trashbot] slips inside.") - playsound(hound, 'sound/effects/bin_close.ogg', 80, 1) - return - - return From 9f00423bbdc084c28c69b51cc5dc57c2d30edc63 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Tue, 29 Oct 2019 21:51:00 +0100 Subject: [PATCH 23/58] Fixing the deep space gorilla. --- _maps/RandomRuins/SpaceRuins/bigape.dmm | 8 +++----- .../mob/living/simple_animal/hostile/gorilla/gorilla.dm | 9 ++++++++- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/_maps/RandomRuins/SpaceRuins/bigape.dmm b/_maps/RandomRuins/SpaceRuins/bigape.dmm index 09e85e129d..602f1737e0 100644 --- a/_maps/RandomRuins/SpaceRuins/bigape.dmm +++ b/_maps/RandomRuins/SpaceRuins/bigape.dmm @@ -56,11 +56,9 @@ /obj/structure/chair/sofa{ dir = 4 }, -/mob/living/simple_animal/hostile/gorilla{ - AIStatus = null; - desc = "There is no need to be upset."; - dir = 4; - name = "Familiar Gorilla" +/mob/living/simple_animal/hostile/gorilla/familiar{ + icon_state = "crawling"; + dir = 4 }, /turf/open/floor/plating/beach/sand, /area/ruin/powered) diff --git a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm index 5d1db8d35e..6866df01d5 100644 --- a/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm +++ b/code/modules/mob/living/simple_animal/hostile/gorilla/gorilla.dm @@ -2,7 +2,7 @@ #define GORILLA_TOTAL_LAYERS 1 /mob/living/simple_animal/hostile/gorilla - name = "Gorilla" + name = "gorilla" desc = "A ground-dwelling, predominantly herbivorous ape that inhabits the forests of central Africa." icon = 'icons/mob/gorilla.dmi' icon_state = "crawling" @@ -108,3 +108,10 @@ playsound(src, 'sound/creatures/gorilla.ogg', 200) oogas = 0 +/mob/living/simple_animal/hostile/gorilla/familiar + name = "familiar gorilla" + desc = "There is no need to be upset." + unique_name = FALSE + AIStatus = AI_OFF + atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0) + minbodytemp = 0 \ No newline at end of file From 54f8c290052e5bf4b8924ecac199ce8465c3af0a Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Tue, 29 Oct 2019 23:33:35 +0100 Subject: [PATCH 24/58] Fixing riding component runtimes, how drifting... --- code/datums/components/riding.dm | 47 +++++++++---------- code/game/objects/buckling.dm | 1 - .../carbon/human/species_types/zombies.dm | 2 +- 3 files changed, 24 insertions(+), 26 deletions(-) diff --git a/code/datums/components/riding.dm b/code/datums/components/riding.dm index 0af90f694c..dcdbd5ca4b 100644 --- a/code/datums/components/riding.dm +++ b/code/datums/components/riding.dm @@ -18,6 +18,7 @@ var/ride_check_rider_incapacitated = FALSE var/ride_check_rider_restrained = FALSE var/ride_check_ridden_incapacitated = FALSE + var/list/offhands = list() // keyed list containing all the current riding offsets associated by mob /datum/component/riding/Initialize() if(!ismovableatom(parent)) @@ -299,36 +300,34 @@ M.throw_at(target, 14, 5, AM) M.Knockdown(60) -/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1, riding_target_override = null) - var/atom/movable/AM = parent - var/amount_equipped = 0 +/datum/component/riding/proc/equip_buckle_inhands(mob/living/carbon/human/user, amount_required = 1, mob/living/riding_target_override) + var/list/equipped + var/mob/living/L = riding_target_override ? riding_target_override : user for(var/amount_needed = amount_required, amount_needed > 0, amount_needed--) - var/obj/item/riding_offhand/inhand = new /obj/item/riding_offhand(user) - if(!riding_target_override) - inhand.rider = user - else - inhand.rider = riding_target_override - inhand.parent = AM - if(user.put_in_hands(inhand, TRUE)) - amount_equipped++ - else + var/obj/item/riding_offhand/inhand = new + inhand.rider = L + inhand.parent = parent + if(!user.put_in_hands(inhand, TRUE)) + qdel(inhand) // it isn't going to be added to offhands anyway break + LAZYADD(equipped, src) + var/amount_equipped = LAZYLEN(equipped) + if(amount_equipped) + LAZYADD(offhands[L], amount_equipped) if(amount_equipped >= amount_required) return TRUE - else - unequip_buckle_inhands(user) - return FALSE + unequip_buckle_inhands(L) + return FALSE /datum/component/riding/proc/unequip_buckle_inhands(mob/living/carbon/user) - var/atom/movable/AM = parent - for(var/obj/item/riding_offhand/O in user.contents) - if(O.parent != AM) - CRASH("RIDING OFFHAND ON WRONG MOB") - continue - if(O.selfdeleting) - continue - else - qdel(O) + for(var/a in offhands[user]) + LAZYREMOVE(offhands[user], a) + if(a) //edge cases null entries + var/obj/item/riding_offhand/O = a + if(O.parent != parent) + CRASH("RIDING OFFHAND ON WRONG MOB") + else if(!O.selfdeleting) + qdel(O) return TRUE /obj/item/riding_offhand diff --git a/code/game/objects/buckling.dm b/code/game/objects/buckling.dm index 693d32e545..9c3df5395f 100644 --- a/code/game/objects/buckling.dm +++ b/code/game/objects/buckling.dm @@ -89,7 +89,6 @@ buckled_mob.clear_alert("buckled") buckled_mobs -= buckled_mob SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, buckled_mob, force) - SEND_SIGNAL(src, COMSIG_MOVABLE_UNBUCKLE, src, force) post_unbuckle_mob(.) diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index a1dce4fb0f..c50677c54c 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -66,7 +66,7 @@ playsound(C, pick(spooks), 50, TRUE, 10) //Congrats you somehow died so hard you stopped being a zombie -/datum/species/zombie/infectious/spec_death(mob/living/carbon/C) +/datum/species/zombie/infectious/spec_death(gibbed, mob/living/carbon/C) . = ..() var/obj/item/organ/zombie_infection/infection infection = C.getorganslot(ORGAN_SLOT_ZOMBIE) From 1b8bda7040485138dd867ba0f968f04e02d17667 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Wed, 30 Oct 2019 00:48:51 +0100 Subject: [PATCH 25/58] Fixes some average runtimes, how null... --- code/modules/mob/living/carbon/life.dm | 2 +- code/modules/surgery/organs/eyes.dm | 2 +- code/modules/surgery/surgery.dm | 2 +- code/modules/vore/eating/belly_obj.dm | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index 5b18e95235..ca139cace7 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -98,7 +98,7 @@ var/datum/gas_mixture/breath if(!getorganslot(ORGAN_SLOT_BREATHING_TUBE)) - if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL) || lungs.organ_flags & ORGAN_FAILING) + if(health <= HEALTH_THRESHOLD_FULLCRIT || (pulledby && pulledby.grab_state >= GRAB_KILL) || !lungs || lungs.organ_flags & ORGAN_FAILING) losebreath++ //You can't breath at all when in critical or when being choked, so you're going to miss a breath else if(health <= crit_threshold) diff --git a/code/modules/surgery/organs/eyes.dm b/code/modules/surgery/organs/eyes.dm index 95258c709a..faaa1c63ad 100644 --- a/code/modules/surgery/organs/eyes.dm +++ b/code/modules/surgery/organs/eyes.dm @@ -338,7 +338,7 @@ /obj/item/organ/eyes/robotic/glow/proc/start_visuals() if(!islist(eye_lighting)) regenerate_light_effects() - if((eye_lighting.len < light_beam_distance) || !on_mob) + if((LAZYLEN(eye_lighting) < light_beam_distance) || !on_mob) regenerate_light_effects() sync_light_effects() update_visuals() diff --git a/code/modules/surgery/surgery.dm b/code/modules/surgery/surgery.dm index e81cbf528f..a920ea765a 100644 --- a/code/modules/surgery/surgery.dm +++ b/code/modules/surgery/surgery.dm @@ -92,7 +92,7 @@ return TRUE if(iscyborg(user) && user.a_intent != INTENT_HARM) //to save asimov borgs a LOT of heartache return TRUE - if(tool.item_flags & SURGICAL_TOOL) //Just because you used the wrong tool it doesn't mean you meant to whack the patient with it + if(tool && tool.item_flags & SURGICAL_TOOL) //Just because you used the wrong tool it doesn't mean you meant to whack the patient with it to_chat(user, "This step requires a different tool!") return TRUE diff --git a/code/modules/vore/eating/belly_obj.dm b/code/modules/vore/eating/belly_obj.dm index 741aff5f9a..5c2b45dace 100644 --- a/code/modules/vore/eating/belly_obj.dm +++ b/code/modules/vore/eating/belly_obj.dm @@ -158,7 +158,7 @@ /obj/belly/Destroy() SSbellies.belly_list -= src - if(owner) + if(owner?.vore_organs) owner.vore_organs -= src owner = null . = ..() From 005c87bdf6771a28ad1571e8572cc41024d7d1cc Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Wed, 30 Oct 2019 01:31:29 +0100 Subject: [PATCH 26/58] I'm making a joke title, don't ban me github. --- code/modules/clothing/head/vg_hats.dm | 14 --------- code/modules/clothing/spacesuits/vg_spess.dm | 19 ------------ icons/obj/citvending.dmi | Bin 6338 -> 4504 bytes .../code/game/machinery/vending.dm | 29 ------------------ 4 files changed, 62 deletions(-) diff --git a/code/modules/clothing/head/vg_hats.dm b/code/modules/clothing/head/vg_hats.dm index dc245cd39a..87f64baf13 100644 --- a/code/modules/clothing/head/vg_hats.dm +++ b/code/modules/clothing/head/vg_hats.dm @@ -82,13 +82,6 @@ item_state = "nr_helmet" icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi' -/obj/item/clothing/head/stalhelm - name = "Stalhelm" - desc = "Ein Helm, um die Nazi-Interesse an fremden Raumstationen zu sichern." - icon_state = "stalhelm" - item_state = "stalhelm" - icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi' - /obj/item/clothing/head/panzer name = "Panzer Cap" desc = "Command any mech in style." @@ -96,13 +89,6 @@ item_state = "panzercap" icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi' -/obj/item/clothing/head/naziofficer - name = "Officer Cap" - desc = "Style is all that matters." - icon_state = "officercap" - item_state = "officercap" - icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi' - /obj/item/clothing/head/russobluecamohat name = "russian blue camo beret" desc = "A symbol of discipline, honor, and lots and lots of removal of some type of skewered food." diff --git a/code/modules/clothing/spacesuits/vg_spess.dm b/code/modules/clothing/spacesuits/vg_spess.dm index e6b1c7a1ee..517539f3af 100644 --- a/code/modules/clothing/spacesuits/vg_spess.dm +++ b/code/modules/clothing/spacesuits/vg_spess.dm @@ -1,24 +1,5 @@ //VG Ports -/obj/item/clothing/head/helmet/space/hardsuit/nazi - name = "nazi hardhelmet" - desc = "This is the face of das vaterland's top elite. Gas or energy are your only escapes." - item_state = "hardsuit0-nazi" - icon_state = "hardsuit0-nazi" - armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 20) - item_color = "nazi" - icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi' - -/obj/item/clothing/suit/space/hardsuit/nazi - name = "nazi hardsuit" - desc = "The attire of a true krieger. All shall fall, and only das vaterland will remain." - item_state = "hardsuit-nazi" - icon_state = "hardsuit-nazi" - slowdown = 1 - armor = list(melee = 40, bullet = 30, laser = 30, energy = 15, bomb = 35, bio = 100, rad = 20) - allowed = list(/obj/item/gun,/obj/item/flashlight,/obj/item/tank,/obj/item/melee/) - helmettype = /obj/item/clothing/head/helmet/space/hardsuit/nazi - icon = 'modular_citadel/icons/obj/clothing/vg_clothes.dmi' /obj/item/clothing/head/helmet/space/hardsuit/soviet name = "soviet hardhelmet" diff --git a/icons/obj/citvending.dmi b/icons/obj/citvending.dmi index 37c2c8fcf1d13871417597ec0331aee40fde9c41..8f836b7eb5116b0def626f06c1194214e9ea2a8f 100644 GIT binary patch literal 4504 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 literal 6338 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 diff --git a/modular_citadel/code/game/machinery/vending.dm b/modular_citadel/code/game/machinery/vending.dm index 6a91810173..a71175c345 100755 --- a/modular_citadel/code/game/machinery/vending.dm +++ b/modular_citadel/code/game/machinery/vending.dm @@ -72,32 +72,7 @@ /obj/item/reagent_containers/glass/bottle/hexacrocin = 10 ) refill_canister = /obj/item/vending_refill/kink -/* -/obj/machinery/vending/nazivend - name = "Nazivend" - desc = "A vending machine containing Nazi German supplies. A label reads: \"Remember the gorrilions lost.\"" - icon = 'icons/obj/citvending.dmi' - icon_state = "nazi" - vend_reply = "SIEG HEIL!" - product_slogans = "Das Vierte Reich wird zuruckkehren!;ENTFERNEN JUDEN!;Billiger als die Juden jemals geben!;Rader auf dem adminbus geht rund und rund.;Warten Sie, warum wir wieder hassen Juden?- *BZZT*" - products = list( - /obj/item/clothing/head/stalhelm = 20, - /obj/item/clothing/head/panzer = 20, - /obj/item/clothing/suit/soldiercoat = 20, - // /obj/item/clothing/under/soldieruniform = 20, - /obj/item/clothing/shoes/jackboots = 20 - ) - contraband = list( - /obj/item/clothing/head/naziofficer = 10, - // /obj/item/clothing/suit/officercoat = 10, - // /obj/item/clothing/under/officeruniform = 10, - /obj/item/clothing/suit/space/hardsuit/nazi = 3, - /obj/item/gun/energy/plasma/MP40k = 4 - ) - premium = list() - refill_canister = /obj/item/vending_refill/nazi -*/ /obj/machinery/vending/sovietvend name = "KomradeVendtink" desc = "Rodina-mat' zovyot!" @@ -137,10 +112,6 @@ icon = 'modular_citadel/icons/vending_restock.dmi' icon_state = "refill_kink" -/obj/item/vending_refill/nazi - machine_name = "nazivend" - icon_state = "refill_nazi" - /obj/item/vending_refill/soviet machine_name = "sovietvend" icon_state = "refill_soviet" From bb197c2251d989453424cf490517a9d0b04c1840 Mon Sep 17 00:00:00 2001 From: Putnam Date: Wed, 30 Oct 2019 01:34:03 -0700 Subject: [PATCH 27/58] allows heal viruses not to hurt slimes --- code/datums/diseases/advance/symptoms/heal.dm | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index 1ab3456c22..9b81868958 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -79,7 +79,7 @@ if(M.getToxLoss() && prob(5)) to_chat(M, "Your skin tingles as the starlight seems to heal you.") - M.adjustToxLoss(-(4 * heal_amt)) //most effective on toxins + M.adjustToxLoss(-(4 * heal_amt), forced = TRUE) //most effective on toxins var/list/parts = M.get_damaged_bodyparts(1,1) @@ -368,7 +368,8 @@ level = 8 passive_message = "You feel an odd attraction to plasma." var/temp_rate = 1 - threshold_desc = "Transmission 6: Increases temperature adjustment rate.
\ + var/heals_slimes = FALSE + threshold_desc = "Transmission 6: Increases temperature adjustment rate and heals toxin lovers.
\ Stage Speed 7: Increases healing speed." /datum/symptom/heal/plasma/Start(datum/disease/advance/A) @@ -410,7 +411,7 @@ if(prob(5)) to_chat(M, "You feel warmer.") - M.adjustToxLoss(-heal_amt) + M.adjustToxLoss(-heal_amt, forced = (temp_rate == 4)) var/list/parts = M.get_damaged_bodyparts(1,1) if(!parts.len) @@ -435,7 +436,7 @@ symptom_delay_max = 1 passive_message = "Your skin glows faintly for a moment." var/cellular_damage = FALSE - threshold_desc = "Transmission 6: Additionally heals cellular damage.
\ + threshold_desc = "Transmission 6: Additionally heals cellular damage and toxin lovers.
\ Resistance 7: Increases healing speed." /datum/symptom/heal/radiation/Start(datum/disease/advance/A) @@ -468,7 +469,7 @@ if(cellular_damage) M.adjustCloneLoss(-heal_amt * 0.5) - M.adjustToxLoss(-(2 * heal_amt)) + M.adjustToxLoss(-(2 * heal_amt), forced = cellular_damage) var/list/parts = M.get_damaged_bodyparts(1,1) From b86c5059d5744e3cde19fc4b060fe8031653e41d Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Wed, 30 Oct 2019 13:17:12 +0100 Subject: [PATCH 28/58] [s] modkit uninstall() calling forceMove() calling loc.Exited() calling modkit.uninstall() calling f... --- code/modules/projectiles/guns/energy/kinetic_accelerator.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm index df8eba00ed..646b4bd57d 100644 --- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm +++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm @@ -331,9 +331,9 @@ uninstall(KA) /obj/item/borg/upgrade/modkit/proc/uninstall(obj/item/gun/energy/kinetic_accelerator/KA, forcemove = TRUE) + KA.modkits -= src if(forcemove) forceMove(get_turf(KA)) - KA.modkits -= src /obj/item/borg/upgrade/modkit/proc/modify_projectile(obj/item/projectile/kinetic/K) From f6feeb93eaa735ea54cfadf1e37238f27a7741af Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Wed, 30 Oct 2019 16:47:44 +0100 Subject: [PATCH 29/58] Mapping in arcade dirs. --- .../LavaRuins/lavaland_surface_golem_ship.dmm | 18 +- .../lavaland_surface_syndicate_base1.dmm | 103 +++-- _maps/RandomZLevels/moonoutpost19.dmm | 15 +- _maps/RandomZLevels/research.dmm | 428 +++++++++--------- _maps/map_files/BoxStation/BoxStation.dmm | 49 +- .../map_files/Deltastation/DeltaStation2.dmm | 114 ++++- _maps/map_files/OmegaStation/OmegaStation.dmm | 32 +- _maps/map_files/PubbyStation/PubbyStation.dmm | 46 +- _maps/shuttles/emergency_cere.dmm | 34 +- code/game/machinery/computer/arcade.dm | 3 +- 10 files changed, 469 insertions(+), 373 deletions(-) diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm index 8015f25696..2c6eda9f90 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_golem_ship.dmm @@ -68,7 +68,10 @@ /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) "k" = ( -/obj/machinery/computer/arcade/battle, +/obj/machinery/computer/arcade/battle{ + icon_state = "arcade"; + dir = 4 + }, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) "l" = ( @@ -105,6 +108,13 @@ /obj/machinery/computer/shuttle, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) +"s" = ( +/obj/machinery/computer/arcade/orion_trail{ + icon_state = "arcade"; + dir = 4 + }, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/golem_ship) "t" = ( /obj/structure/extinguisher_cabinet{ pixel_y = 30 @@ -142,10 +152,6 @@ /obj/machinery/reagentgrinder, /turf/open/floor/mineral/titanium/purple, /area/ruin/powered/golem_ship) -"y" = ( -/obj/machinery/computer/arcade/orion_trail, -/turf/open/floor/mineral/titanium/purple, -/area/ruin/powered/golem_ship) "z" = ( /obj/structure/extinguisher_cabinet{ pixel_y = -30 @@ -332,7 +338,7 @@ l l j l -y +s b a a diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm index 8e0d9a523a..2ec5b88792 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm @@ -167,6 +167,56 @@ }, /turf/open/floor/plating, /area/ruin/unpowered/syndicate_lava_base/circuits) +"av" = ( +/obj/structure/bed/roller, +/obj/machinery/iv_drip, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/mob/living/carbon/monkey{ + faction = list("neutral","Syndicate") + }, +/turf/open/floor/plasteel/dark, +/area/ruin/unpowered/syndicate_lava_base/testlab) +"aw" = ( +/obj/machinery/light/small, +/obj/structure/bed/roller, +/obj/machinery/iv_drip, +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/mob/living/carbon/monkey{ + faction = list("neutral","Syndicate") + }, +/turf/open/floor/plasteel/dark, +/area/ruin/unpowered/syndicate_lava_base/testlab) +"ax" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/computer/arcade/orion_trail{ + icon_state = "arcade"; + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/ruin/unpowered/syndicate_lava_base/bar) "aF" = ( /obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer3{ dir = 4 @@ -790,26 +840,6 @@ /obj/structure/disposalpipe/trunk, /turf/open/floor/plating/asteroid/basalt/lava_land_surface, /area/ruin/unpowered/syndicate_lava_base/virology) -"ej" = ( -/obj/structure/bed/roller, -/obj/machinery/iv_drip, -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/mob/living/carbon/monkey{ - faction = list("neutral","Syndicate") - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/ruin/unpowered/syndicate_lava_base/testlab) "ek" = ( /obj/structure/grille, /obj/structure/window/plastitanium, @@ -1136,27 +1166,6 @@ /obj/structure/disposalpipe/segment, /turf/closed/wall/mineral/plastitanium/nodiagonal, /area/ruin/unpowered/syndicate_lava_base/virology) -"eK" = ( -/obj/machinery/light/small, -/obj/structure/bed/roller, -/obj/machinery/iv_drip, -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/mob/living/carbon/monkey{ - faction = list("neutral","Syndicate") - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/ruin/unpowered/syndicate_lava_base/testlab) "eL" = ( /obj/machinery/door/airlock/hatch{ name = "Monkey Pen"; @@ -5148,12 +5157,6 @@ /obj/item/clothing/mask/gas, /turf/open/floor/plating, /area/ruin/unpowered/syndicate_lava_base/arrivals) -"mt" = ( -/obj/machinery/computer/arcade/orion_trail, -/obj/effect/decal/cleanable/dirt, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plasteel/dark, -/area/ruin/unpowered/syndicate_lava_base/bar) "mu" = ( /obj/item/twohanded/required/kirbyplants{ icon_state = "plant-22" @@ -7340,8 +7343,8 @@ ae ae ae ae -ej -eK +av +aw ae fD ad @@ -7362,7 +7365,7 @@ kH jN jZ lU -mt +ax mU np nP diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm index c251a338a5..ddc8778ac1 100644 --- a/_maps/RandomZLevels/moonoutpost19.dmm +++ b/_maps/RandomZLevels/moonoutpost19.dmm @@ -16,6 +16,13 @@ heat_capacity = 1e+006 }, /area/awaymission/moonoutpost19/hive) +"ae" = ( +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/awaymission/moonoutpost19/arrivals) "ag" = ( /obj/structure/alien/weeds, /obj/structure/alien/weeds{ @@ -6408,10 +6415,6 @@ heat_capacity = 1e+006 }, /area/awaymission/moonoutpost19/arrivals) -"mB" = ( -/obj/machinery/computer/arcade, -/turf/open/floor/plasteel/dark, -/area/awaymission/moonoutpost19/arrivals) "mC" = ( /obj/machinery/vending/cigarette, /obj/structure/sign/poster/contraband/smoke{ @@ -43385,7 +43388,7 @@ la lq jk mj -mB +ae hJ ba ba @@ -43642,7 +43645,7 @@ jN lr jj mj -mB +ae hI ba ba diff --git a/_maps/RandomZLevels/research.dmm b/_maps/RandomZLevels/research.dmm index 3a58d85143..2499270d8f 100644 --- a/_maps/RandomZLevels/research.dmm +++ b/_maps/RandomZLevels/research.dmm @@ -245,10 +245,38 @@ }, /turf/open/floor/plating, /area/awaymission/research/interior/engineering) +"aS" = ( +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/mob/living/carbon/monkey, +/turf/open/floor/plasteel, +/area/awaymission/research/interior/genetics) "aT" = ( /mob/living/simple_animal/hostile/syndicate/melee/sword, /turf/open/floor/plating, /area/awaymission/research/interior/engineering) +"aU" = ( +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/mob/living/carbon/human, +/turf/open/floor/plasteel, +/area/awaymission/research/interior/genetics) "aV" = ( /obj/item/stack/sheet/plasteel, /obj/effect/turf_decal/tile/yellow{ @@ -326,6 +354,23 @@ icon_state = "damaged4" }, /area/awaymission/research/interior/engineering) +"bc" = ( +/obj/structure/window/reinforced{ + dir = 4 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/mob/living/carbon/monkey, +/turf/open/floor/plasteel, +/area/awaymission/research/interior/genetics) "bd" = ( /turf/open/floor/plasteel{ icon_state = "damaged3" @@ -903,6 +948,17 @@ /obj/machinery/light/small, /turf/open/floor/plating, /area/awaymission/research/interior/maint) +"co" = ( +/obj/item/ammo_casing/c45, +/obj/effect/turf_decal/tile/yellow{ + dir = 1 + }, +/obj/effect/turf_decal/tile/yellow{ + dir = 8 + }, +/mob/living/simple_animal/hostile/syndicate, +/turf/open/floor/plasteel/white, +/area/awaymission/research/interior) "cp" = ( /turf/closed/wall/r_wall, /area/awaymission/research/interior) @@ -1195,19 +1251,19 @@ /turf/open/floor/plating, /area/awaymission/research/interior/genetics) "cT" = ( -/mob/living/carbon/monkey, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/turf_decal/tile/red{ dir = 1 }, -/obj/effect/turf_decal/tile/purple, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/turf_decal/tile/red, +/obj/effect/turf_decal/tile/red{ dir = 4 }, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/turf_decal/tile/red{ dir = 8 }, +/mob/living/simple_animal/hostile/nanotrasen/ranged, /turf/open/floor/plasteel, -/area/awaymission/research/interior/genetics) +/area/awaymission/research/interior/security) "cU" = ( /obj/machinery/door/window/eastright, /obj/effect/turf_decal/tile/purple{ @@ -1253,7 +1309,9 @@ /turf/open/floor/plasteel, /area/awaymission/research/interior/genetics) "cX" = ( -/mob/living/carbon/human, +/obj/structure/window/reinforced{ + dir = 8 + }, /obj/effect/turf_decal/tile/purple{ dir = 1 }, @@ -1264,6 +1322,7 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, +/mob/living/carbon/human, /turf/open/floor/plasteel, /area/awaymission/research/interior/genetics) "cY" = ( @@ -1356,22 +1415,15 @@ /turf/open/floor/plasteel, /area/awaymission/research/interior/genetics) "di" = ( -/obj/structure/window/reinforced{ - dir = 4 - }, -/mob/living/carbon/monkey, /obj/effect/turf_decal/tile/purple{ dir = 1 }, -/obj/effect/turf_decal/tile/purple, /obj/effect/turf_decal/tile/purple{ dir = 4 }, -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/research/interior/genetics) +/mob/living/simple_animal/hostile/nanotrasen/ranged, +/turf/open/floor/plasteel/white, +/area/awaymission/research/interior/cryo) "dj" = ( /obj/effect/decal/cleanable/blood, /obj/item/stack/rods, @@ -1416,14 +1468,14 @@ /turf/open/floor/plasteel/white, /area/awaymission/research/interior) "dn" = ( -/obj/item/ammo_casing/c45, -/mob/living/simple_animal/hostile/syndicate, /obj/effect/turf_decal/tile/yellow{ dir = 1 }, +/obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ - dir = 8 + dir = 4 }, +/mob/living/simple_animal/hostile/syndicate, /turf/open/floor/plasteel/white, /area/awaymission/research/interior) "do" = ( @@ -1675,7 +1727,6 @@ /turf/open/floor/plasteel, /area/awaymission/research/interior/security) "dI" = ( -/mob/living/simple_animal/hostile/nanotrasen/ranged, /obj/effect/turf_decal/tile/red{ dir = 1 }, @@ -1686,7 +1737,8 @@ /obj/effect/turf_decal/tile/red{ dir = 8 }, -/turf/open/floor/plasteel, +/mob/living/simple_animal/hostile/nanotrasen/ranged/smg, +/turf/open/floor/plasteel/white, /area/awaymission/research/interior/security) "dJ" = ( /obj/structure/rack, @@ -1777,11 +1829,7 @@ }, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/genetics) -"dQ" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/mob/living/carbon/human, +"dP" = ( /obj/effect/turf_decal/tile/purple{ dir = 1 }, @@ -1792,8 +1840,23 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, +/mob/living/simple_animal/hostile/nanotrasen/ranged, +/turf/open/floor/plasteel/white, +/area/awaymission/research/interior/cryo) +"dQ" = ( +/obj/effect/turf_decal/tile/purple{ + dir = 1 + }, +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ + dir = 4 + }, +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/mob/living/simple_animal/hostile/nanotrasen, /turf/open/floor/plasteel, -/area/awaymission/research/interior/genetics) +/area/awaymission/research/interior/cryo) "dR" = ( /obj/structure/cable{ icon_state = "4-8" @@ -2144,15 +2207,15 @@ /turf/open/floor/plasteel/white, /area/awaymission/research/interior/cryo) "eB" = ( -/mob/living/simple_animal/hostile/nanotrasen/ranged, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/turf_decal/tile/red{ dir = 1 }, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/turf_decal/tile/red{ dir = 4 }, +/mob/living/simple_animal/hostile/nanotrasen/ranged/smg, /turf/open/floor/plasteel/white, -/area/awaymission/research/interior/cryo) +/area/awaymission/research/interior/security) "eC" = ( /obj/item/ammo_casing/c9mm, /obj/effect/turf_decal/tile/purple{ @@ -2214,16 +2277,22 @@ /turf/open/floor/plasteel/white, /area/awaymission/research/interior) "eL" = ( -/mob/living/simple_animal/hostile/syndicate, -/obj/effect/turf_decal/tile/yellow{ +/obj/structure/window/reinforced{ + dir = 8 + }, +/obj/effect/turf_decal/tile/purple{ dir = 1 }, -/obj/effect/turf_decal/tile/yellow, -/obj/effect/turf_decal/tile/yellow{ +/obj/effect/turf_decal/tile/purple, +/obj/effect/turf_decal/tile/purple{ dir = 4 }, -/turf/open/floor/plasteel/white, -/area/awaymission/research/interior) +/obj/effect/turf_decal/tile/purple{ + dir = 8 + }, +/mob/living/carbon/monkey, +/turf/open/floor/plasteel, +/area/awaymission/research/interior/genetics) "eM" = ( /obj/item/ammo_casing/c45, /obj/item/ammo_casing/c45, @@ -2846,19 +2915,19 @@ /turf/open/floor/plasteel/white, /area/awaymission/research/interior/security) "fY" = ( -/mob/living/simple_animal/hostile/nanotrasen/ranged/smg, -/obj/effect/turf_decal/tile/red{ +/obj/effect/turf_decal/tile/green{ dir = 1 }, -/obj/effect/turf_decal/tile/red, -/obj/effect/turf_decal/tile/red{ +/obj/effect/turf_decal/tile/green, +/obj/effect/turf_decal/tile/green{ dir = 4 }, -/obj/effect/turf_decal/tile/red{ +/obj/effect/turf_decal/tile/green{ dir = 8 }, +/mob/living/simple_animal/hostile/syndicate/ranged/smg, /turf/open/floor/plasteel/white, -/area/awaymission/research/interior/security) +/area/awaymission/research/interior) "fZ" = ( /obj/structure/cable{ icon_state = "1-2" @@ -2966,6 +3035,23 @@ }, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/secure) +"gi" = ( +/obj/effect/turf_decal/tile/red{ + dir = 1 + }, +/obj/effect/turf_decal/tile/red{ + dir = 4 + }, +/mob/living/simple_animal/bot/secbot/beepsky{ + desc = "A beefy variant of the standard securitron model."; + emagged = 1; + faction = list("nanotrasenprivate"); + health = 50; + maxHealth = 50; + name = "Officer Genesky" + }, +/turf/open/floor/plasteel/white, +/area/awaymission/research/interior/security) "gj" = ( /obj/structure/cable{ icon_state = "4-8" @@ -3115,19 +3201,13 @@ /turf/open/floor/plasteel/white, /area/awaymission/research/interior/cryo) "gv" = ( -/mob/living/simple_animal/hostile/nanotrasen/ranged, -/obj/effect/turf_decal/tile/purple{ - dir = 1 - }, -/obj/effect/turf_decal/tile/purple, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/turf_decal/tile/green, +/obj/effect/turf_decal/tile/green{ dir = 4 }, -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, +/mob/living/simple_animal/hostile/syndicate, /turf/open/floor/plasteel/white, -/area/awaymission/research/interior/cryo) +/area/awaymission/research/interior) "gw" = ( /obj/effect/mob_spawn/human/doctor{ brute_damage = 145; @@ -3508,6 +3588,35 @@ }, /turf/open/floor/plasteel/white, /area/awaymission/research/interior) +"gW" = ( +/obj/structure/sign/directions/security{ + dir = 1; + pixel_x = 32; + pixel_y = 40 + }, +/obj/structure/sign/directions/engineering{ + dir = 1; + pixel_x = 32; + pixel_y = 33 + }, +/obj/structure/sign/directions/science{ + dir = 1; + pixel_x = 32; + pixel_y = 26 + }, +/obj/effect/turf_decal/tile/green{ + dir = 1 + }, +/obj/effect/turf_decal/tile/green, +/obj/effect/turf_decal/tile/green{ + dir = 4 + }, +/obj/effect/turf_decal/tile/green{ + dir = 8 + }, +/mob/living/simple_animal/hostile/syndicate/ranged/smg, +/turf/open/floor/plasteel/white, +/area/awaymission/research/interior) "gX" = ( /obj/effect/decal/cleanable/blood/drip, /obj/effect/turf_decal/tile/purple{ @@ -3660,19 +3769,19 @@ /turf/open/floor/plasteel/white, /area/awaymission/research/interior/security) "hj" = ( -/mob/living/simple_animal/hostile/nanotrasen, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/effect/turf_decal/tile/purple, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ dir = 4 }, -/obj/effect/turf_decal/tile/purple{ +/obj/effect/turf_decal/tile/blue{ dir = 8 }, -/turf/open/floor/plasteel, -/area/awaymission/research/interior/cryo) +/mob/living/simple_animal/hostile/syndicate/ranged/smg, +/turf/open/floor/plasteel/white, +/area/awaymission/research/interior/medbay) "hk" = ( /obj/effect/decal/cleanable/blood, /obj/effect/turf_decal/tile/purple{ @@ -3736,15 +3845,19 @@ /turf/open/floor/plasteel/white, /area/awaymission/research/interior/security) "hq" = ( -/mob/living/simple_animal/hostile/nanotrasen/ranged/smg, -/obj/effect/turf_decal/tile/red{ +/obj/effect/turf_decal/tile/blue{ dir = 1 }, -/obj/effect/turf_decal/tile/red{ +/obj/effect/turf_decal/tile/blue, +/obj/effect/turf_decal/tile/blue{ dir = 4 }, +/obj/effect/turf_decal/tile/blue{ + dir = 8 + }, +/mob/living/simple_animal/hostile/syndicate, /turf/open/floor/plasteel/white, -/area/awaymission/research/interior/security) +/area/awaymission/research/interior/medbay) "hr" = ( /obj/structure/cable{ icon_state = "1-2" @@ -3799,6 +3912,15 @@ }, /turf/open/floor/plasteel/white, /area/awaymission/research/interior/cryo) +"hw" = ( +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 8 + }, +/turf/open/floor/plasteel/yellowsiding{ + dir = 4 + }, +/area/awaymission/research/interior/dorm) "hx" = ( /obj/structure/cable{ icon_state = "2-4" @@ -4066,23 +4188,6 @@ }, /turf/open/floor/plasteel/dark, /area/awaymission/research/interior/genetics) -"hW" = ( -/obj/structure/window/reinforced{ - dir = 8 - }, -/mob/living/carbon/monkey, -/obj/effect/turf_decal/tile/purple{ - dir = 1 - }, -/obj/effect/turf_decal/tile/purple, -/obj/effect/turf_decal/tile/purple{ - dir = 4 - }, -/obj/effect/turf_decal/tile/purple{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/awaymission/research/interior/genetics) "hX" = ( /obj/structure/rack, /obj/effect/spawner/lootdrop/maintenance, @@ -4139,20 +4244,6 @@ }, /turf/open/floor/plating, /area/awaymission/research/interior/maint) -"if" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/smg, -/obj/effect/turf_decal/tile/green{ - dir = 1 - }, -/obj/effect/turf_decal/tile/green, -/obj/effect/turf_decal/tile/green{ - dir = 4 - }, -/obj/effect/turf_decal/tile/green{ - dir = 8 - }, -/turf/open/floor/plasteel/white, -/area/awaymission/research/interior) "ig" = ( /obj/structure/cable{ icon_state = "2-4" @@ -4186,23 +4277,6 @@ }, /turf/open/floor/plasteel/white, /area/awaymission/research/interior/security) -"ij" = ( -/mob/living/simple_animal/bot/secbot/beepsky{ - desc = "A beefy variant of the standard securitron model."; - emagged = 1; - faction = list("nanotrasenprivate"); - health = 50; - maxHealth = 50; - name = "Officer Genesky" - }, -/obj/effect/turf_decal/tile/red{ - dir = 1 - }, -/obj/effect/turf_decal/tile/red{ - dir = 4 - }, -/turf/open/floor/plasteel/white, -/area/awaymission/research/interior/security) "ik" = ( /obj/structure/cable{ icon_state = "1-2" @@ -4546,14 +4620,6 @@ }, /turf/open/floor/plasteel/freezer, /area/awaymission/research/interior/bathroom) -"iQ" = ( -/mob/living/simple_animal/hostile/syndicate, -/obj/effect/turf_decal/tile/green, -/obj/effect/turf_decal/tile/green{ - dir = 4 - }, -/turf/open/floor/plasteel/white, -/area/awaymission/research/interior) "iR" = ( /turf/open/floor/plasteel, /area/awaymission/research/interior/maint) @@ -4723,35 +4789,6 @@ }, /turf/open/floor/plasteel, /area/awaymission/research/interior) -"jr" = ( -/obj/structure/sign/directions/security{ - dir = 1; - pixel_x = 32; - pixel_y = 40 - }, -/obj/structure/sign/directions/engineering{ - dir = 1; - pixel_x = 32; - pixel_y = 33 - }, -/obj/structure/sign/directions/science{ - dir = 1; - pixel_x = 32; - pixel_y = 26 - }, -/mob/living/simple_animal/hostile/syndicate/ranged/smg, -/obj/effect/turf_decal/tile/green{ - dir = 1 - }, -/obj/effect/turf_decal/tile/green, -/obj/effect/turf_decal/tile/green{ - dir = 4 - }, -/obj/effect/turf_decal/tile/green{ - dir = 8 - }, -/turf/open/floor/plasteel/white, -/area/awaymission/research/interior) "js" = ( /obj/effect/turf_decal/tile/blue, /obj/effect/turf_decal/tile/blue{ @@ -4976,20 +5013,6 @@ }, /turf/open/floor/plasteel/white, /area/awaymission/research/interior/medbay) -"jP" = ( -/mob/living/simple_animal/hostile/syndicate/ranged/smg, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel/white, -/area/awaymission/research/interior/medbay) "jQ" = ( /obj/effect/decal/cleanable/blood/drip, /obj/effect/turf_decal/tile/blue{ @@ -5591,9 +5614,6 @@ dir = 8 }, /area/awaymission/research/interior/dorm) -"ln" = ( -/turf/open/floor/plasteel, -/area/space/nearstation) "lo" = ( /obj/structure/table/wood, /obj/structure/bedsheetbin, @@ -5613,20 +5633,6 @@ }, /turf/open/floor/plasteel/white, /area/awaymission/research/interior/medbay) -"lr" = ( -/mob/living/simple_animal/hostile/syndicate, -/obj/effect/turf_decal/tile/blue{ - dir = 1 - }, -/obj/effect/turf_decal/tile/blue, -/obj/effect/turf_decal/tile/blue{ - dir = 4 - }, -/obj/effect/turf_decal/tile/blue{ - dir = 8 - }, -/turf/open/floor/plasteel/white, -/area/awaymission/research/interior/medbay) "ls" = ( /obj/structure/table, /obj/item/storage/firstaid/regular, @@ -5867,12 +5873,6 @@ /obj/effect/landmark/awaystart, /turf/open/floor/wood, /area/awaymission/research/interior/dorm) -"lU" = ( -/obj/machinery/computer/arcade, -/turf/open/floor/plasteel/yellowsiding{ - dir = 4 - }, -/area/awaymission/research/interior/dorm) "lV" = ( /obj/machinery/light/small{ dir = 1 @@ -38316,7 +38316,7 @@ ea ev fd fE -gv +dP ev fd fE @@ -38565,10 +38565,10 @@ aH cm cw cx -cT +aS dh dq -cT +aS ea ev fc @@ -38823,7 +38823,7 @@ cd cx cx cU -di +bc dr dr ea @@ -39603,7 +39603,7 @@ ey fG gw gR -hj +dQ hu hK cK @@ -40367,7 +40367,7 @@ cx cW dh du -dQ +cX ea eA fd @@ -40377,7 +40377,7 @@ ev fd fE ea -hW +eL ib ib iz @@ -40621,12 +40621,12 @@ aH ce cc cx -cX +aU dh dv dh ea -eB +di fc fH gx @@ -40637,7 +40637,7 @@ ea dh dv dh -cT +aS cx cm cw @@ -40651,7 +40651,7 @@ kr jn jF jF -ln +jF kc lL jk @@ -41143,7 +41143,7 @@ ea ev fh fI -gv +dP ev fc fE @@ -43224,8 +43224,8 @@ lc lp lp lN -lU -lU +hw +hw lY aP cd @@ -44224,7 +44224,7 @@ dl dz cZ ek -eL +dn fl eJ eZ @@ -44238,7 +44238,7 @@ ir hZ hZ hZ -iQ +gv hZ hZ hA @@ -44490,7 +44490,7 @@ hl hl hl hl -if +fY is hl hl @@ -44734,7 +44734,7 @@ cs cC cP TD -dn +co dB da em @@ -44756,7 +44756,7 @@ ia ia ia ia -jr +gW jI hl kv @@ -47584,7 +47584,7 @@ aO iW iW ju -jP +hj kh iW iW @@ -48361,7 +48361,7 @@ kg kM jh jw -lr +hq kg iW cd @@ -48855,7 +48855,7 @@ fq fW gK fW -hq +eB do dH dH @@ -49366,7 +49366,7 @@ dT eo eR fr -fY +dI gK fW ho @@ -49646,7 +49646,7 @@ kg kL kZ lg -lr +hq lD iW lW @@ -50389,7 +50389,7 @@ ad aH aO do -dI +cT dH dH eS @@ -50401,7 +50401,7 @@ fW fW fW fW -ij +gi do hD aH @@ -50672,7 +50672,7 @@ jw km kB kO -jP +hj lj lw lI diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index 125da46b81..cf1b2c6835 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -372,7 +372,10 @@ /turf/open/space, /area/space/nearstation) "aaU" = ( -/obj/machinery/computer/arcade, +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 4 + }, /turf/open/floor/plasteel, /area/security/prison) "aaV" = ( @@ -6019,6 +6022,18 @@ }, /turf/open/floor/plasteel, /area/security/processing) +"amd" = ( +/obj/effect/turf_decal/tile/red{ + dir = 8 + }, +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 4 + }, +/turf/open/floor/plasteel/white/corner{ + dir = 1 + }, +/area/hallway/secondary/exit) "ame" = ( /obj/structure/cable{ icon_state = "1-2" @@ -6225,6 +6240,17 @@ }, /turf/open/floor/plating, /area/maintenance/solars/port/fore) +"amB" = ( +/obj/effect/turf_decal/tile/bar, +/obj/effect/turf_decal/tile/bar{ + dir = 1 + }, +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 1 + }, +/turf/open/floor/plasteel, +/area/crew_quarters/bar) "amC" = ( /turf/open/floor/plating, /area/maintenance/port/fore) @@ -19937,15 +19963,6 @@ dir = 1 }, /area/chapel/main) -"aUL" = ( -/obj/machinery/computer/arcade, -/obj/effect/turf_decal/tile/red{ - dir = 8 - }, -/turf/open/floor/plasteel/white/corner{ - dir = 1 - }, -/area/hallway/secondary/exit) "aUM" = ( /obj/machinery/camera{ c_tag = "Arrivals Bay 2"; @@ -22268,14 +22285,6 @@ }, /turf/open/floor/plasteel, /area/crew_quarters/bar) -"baa" = ( -/obj/machinery/computer/arcade, -/obj/effect/turf_decal/tile/bar, -/obj/effect/turf_decal/tile/bar{ - dir = 1 - }, -/turf/open/floor/plasteel, -/area/crew_quarters/bar) "bab" = ( /obj/machinery/light, /obj/machinery/firealarm{ @@ -91961,7 +91970,7 @@ aUf aQc aXi aQc -baa +amB aJC bcq bcq @@ -106349,7 +106358,7 @@ aCR aCR aCR aTl -aUL +amd aVW aXD aZj diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 79b7561ebb..e500c85640 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -173,6 +173,88 @@ /obj/effect/landmark/xeno_spawn, /turf/open/space, /area/solar/starboard/fore) +"aav" = ( +/obj/effect/decal/cleanable/cobweb, +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) +"aaw" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/starboard/fore) +"aax" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/starboard/fore) +"aay" = ( +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 1 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) +"aaz" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/starboard/fore) +"aaA" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 1 + }, +/turf/open/floor/plating, +/area/maintenance/starboard/fore) +"aaB" = ( +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 1 + }, +/turf/open/floor/plating, +/area/security/prison) "aaE" = ( /obj/structure/lattice/catwalk, /turf/open/space, @@ -4563,11 +4645,6 @@ }, /turf/open/floor/plasteel, /area/maintenance/starboard/fore) -"anz" = ( -/obj/machinery/computer/arcade, -/obj/effect/decal/cleanable/cobweb, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) "anA" = ( /obj/structure/cable/white{ icon_state = "0-2" @@ -7122,10 +7199,6 @@ }, /turf/open/floor/plating, /area/maintenance/starboard/fore) -"arX" = ( -/obj/machinery/computer/arcade, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) "arY" = ( /obj/structure/table/wood, /obj/item/toy/talking/codex_gigas, @@ -7156,11 +7229,6 @@ }, /turf/open/floor/plasteel/dark, /area/maintenance/starboard/fore) -"asa" = ( -/obj/machinery/computer/arcade, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, -/area/maintenance/starboard/fore) "asb" = ( /obj/machinery/airalarm{ dir = 1; @@ -21997,10 +22065,6 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden, /turf/open/floor/plating, /area/security/prison) -"aRi" = ( -/obj/machinery/computer/arcade, -/turf/open/floor/plating, -/area/security/prison) "aRj" = ( /obj/structure/cable/white{ icon_state = "0-2" @@ -170617,7 +170681,7 @@ aox apu aqy arb -aoy +aax aig auA avU @@ -170874,7 +170938,7 @@ aoy apv aqz apu -arX +aay aig auB avU @@ -171383,8 +171447,8 @@ aiC akU alI amE -anz -aox +aav +aaw apw aqA apy @@ -171902,7 +171966,7 @@ aiC apy apy apu -aox +aaz atw auD avW @@ -172159,7 +172223,7 @@ aoB apz apw apv -asa +aaA atw auE avW @@ -182715,7 +182779,7 @@ aFn aMn aNI aPr -aRi +aaB aKV aUC aWk diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm index a87c17836c..a7ab212bd6 100644 --- a/_maps/map_files/OmegaStation/OmegaStation.dmm +++ b/_maps/map_files/OmegaStation/OmegaStation.dmm @@ -1279,6 +1279,22 @@ }, /turf/open/floor/plasteel, /area/science/mixing) +"abQ" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/computer/arcade{ + dir = 4 + }, +/turf/open/floor/plasteel/dark, +/area/maintenance/port) "abR" = ( /obj/structure/lattice, /turf/open/space, @@ -37164,20 +37180,6 @@ }, /turf/open/floor/plasteel, /area/hallway/primary/starboard) -"dEa" = ( -/obj/machinery/computer/arcade, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/maintenance/port) "dFV" = ( /obj/machinery/atmospherics/pipe/simple/green/visible{ dir = 4 @@ -76194,7 +76196,7 @@ aZp bak bbc bbQ -dEa +abQ bdD beu sKE diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index 698eb6cd5a..9ae92b26d4 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -35,6 +35,30 @@ icon_state = "platingdmg3" }, /area/maintenance/department/science) +"aae" = ( +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 8 + }, +/turf/open/floor/plasteel/dark, +/area/security/prison) +"aaf" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/computer/arcade{ + icon_state = "arcade"; + dir = 1 + }, +/turf/open/floor/plasteel/dark, +/area/crew_quarters/heads/captain) "abf" = ( /obj/structure/bed, /turf/open/floor/plating, @@ -1621,10 +1645,6 @@ }, /turf/open/floor/plasteel/dark, /area/security/prison) -"afI" = ( -/obj/machinery/computer/arcade, -/turf/open/floor/plasteel/dark, -/area/security/prison) "afJ" = ( /obj/effect/landmark/carpspawn, /turf/open/space/basic, @@ -13685,20 +13705,6 @@ }, /turf/open/floor/plasteel/dark, /area/crew_quarters/heads/captain) -"aGm" = ( -/obj/machinery/computer/arcade, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel/dark, -/area/crew_quarters/heads/captain) "aGn" = ( /obj/item/twohanded/required/kirbyplants/photosynthetic{ layer = 3.1 @@ -83601,7 +83607,7 @@ aeu aeI lGp aeU -afI +aae aeU dUk agy @@ -90832,7 +90838,7 @@ aCC aDG aBm aFz -aGm +aaf awR aHQ aIO diff --git a/_maps/shuttles/emergency_cere.dmm b/_maps/shuttles/emergency_cere.dmm index 23de211226..f49e70aeb9 100644 --- a/_maps/shuttles/emergency_cere.dmm +++ b/_maps/shuttles/emergency_cere.dmm @@ -591,6 +591,22 @@ /obj/machinery/recharger, /turf/open/floor/mineral/plastitanium/red/brig, /area/shuttle/escape) +"bh" = ( +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/tile/neutral, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 + }, +/obj/effect/turf_decal/tile/neutral{ + dir = 8 + }, +/obj/machinery/computer/arcade{ + dir = 4 + }, +/turf/open/floor/plasteel, +/area/shuttle/escape) "bj" = ( /turf/open/floor/mech_bay_recharge_floor, /area/shuttle/escape) @@ -1181,20 +1197,6 @@ }, /turf/open/floor/plasteel/white, /area/shuttle/escape) -"cz" = ( -/obj/machinery/computer/arcade, -/obj/effect/turf_decal/tile/neutral{ - dir = 1 - }, -/obj/effect/turf_decal/tile/neutral, -/obj/effect/turf_decal/tile/neutral{ - dir = 4 - }, -/obj/effect/turf_decal/tile/neutral{ - dir = 8 - }, -/turf/open/floor/plasteel, -/area/shuttle/escape) "cA" = ( /obj/machinery/light{ dir = 8 @@ -1815,8 +1817,8 @@ ab ad cn cn -cz -cz +bh +bh cn cn ab diff --git a/code/game/machinery/computer/arcade.dm b/code/game/machinery/computer/arcade.dm index b988bd8d35..8d950f8458 100644 --- a/code/game/machinery/computer/arcade.dm +++ b/code/game/machinery/computer/arcade.dm @@ -86,7 +86,8 @@ /obj/item/circuitboard/computer/arcade/amputation = 2) var/thegame = pickweight(gameodds) var/obj/item/circuitboard/CB = new thegame() - new CB.build_path(loc, CB) + var/obj/machinery/computer/arcade/A = new CB.build_path(loc, CB) + A.setDir(dir) return INITIALIZE_HINT_QDEL //The below object acts as a spawner with a wide array of possible picks, most being uninspired references to past/current player characters. //Nevertheless, this keeps its ratio constant with the sum of all the others prizes. From 05dc64fd0ae8bd661a52abbd8baf668266f827b1 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Wed, 30 Oct 2019 21:47:33 +0100 Subject: [PATCH 30/58] Obligatory changes for 513 kevinz forgot about. --- Dockerfile | 2 +- code/__DEFINES/citadel_defines.dm | 2 +- code/__DEFINES/misc.dm | 2 +- code/datums/components/phantomthief.dm | 21 ++++++--------------- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/Dockerfile b/Dockerfile index ec3694c7e8..ad347079cd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM tgstation/byond:512.1488 as base +FROM tgstation/byond:513.1490 as base FROM base as build_base diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 3301def4a1..d4ec6a7d3f 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -15,7 +15,7 @@ #define ui_boxvore "EAST-5:22,SOUTH+1:6" //Filters -#define CIT_FILTER_STAMINACRIT filter(type="drop_shadow", x=0, y=0, size=-3, border=0, color="#04080F") +#define CIT_FILTER_STAMINACRIT filter(type="drop_shadow", x=0, y=0, size=-3, color="#04080F") //organ defines #define COCK_SIZE_MIN 1 diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 94a189ff07..38fd102b19 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -489,7 +489,7 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define PDAIMG(what) {""} //Filters -#define AMBIENT_OCCLUSION list("type"="drop_shadow","x"=0,"y"=-2,"size"=4,"border"=4,"color"="#04080FAA") +#define AMBIENT_OCCLUSION list("type"="drop_shadow","x"=0,"y"=-2,"size"=4,"color"="#04080FAA") #define EYE_BLUR(size) list("type"="blur", "size"=size) #define GRAVITY_MOTION_BLUR list("type"="motion_blur","x"=0,"y"=0) diff --git a/code/datums/components/phantomthief.dm b/code/datums/components/phantomthief.dm index ff1c48936f..7afe64994f 100644 --- a/code/datums/components/phantomthief.dm +++ b/code/datums/components/phantomthief.dm @@ -7,33 +7,24 @@ var/filter_x var/filter_y var/filter_size - var/filter_border var/filter_color -/datum/component/wearertargeting/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _border = 0, _color = "#E62111", list/_valid_slots = list(SLOT_GLASSES)) +/datum/component/wearertargeting/phantomthief/Initialize(_x = -2, _y = 0, _size = 0, _color = "#E62111", list/_valid_slots = list(SLOT_GLASSES)) . = ..() if(. == COMPONENT_INCOMPATIBLE) return filter_x = _x filter_y = _y filter_size = _size - filter_border = _border filter_color = _color valid_slots = _valid_slots /datum/component/wearertargeting/phantomthief/proc/handlefilterstuff(datum/source, mob/user, combatmodestate) - if(istype(user)) - var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color) - if(!combatmodestate) - user.filters -= thefilter - else - user.filters += thefilter - -/datum/component/wearertargeting/phantomthief/proc/stripdesiredfilter(mob/user) - if(istype(user)) - var/thefilter = filter(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, border = filter_border, color = filter_color) - user.filters -= thefilter + if(!combatmodestate) + user.remove_filter("phantomthief") + else + user.add_filter("phantomthief", 4, list(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, color = filter_color)) /datum/component/wearertargeting/phantomthief/on_drop(datum/source, mob/user) . = ..() - stripdesiredfilter(user) + user.remove_filter("phantomthief") From 56b65130fb00693ccc7312dad361d47fa9615cbe Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 31 Oct 2019 01:17:21 +0100 Subject: [PATCH 31/58] Modernizing ratvarian computer sprites. --- code/game/machinery/computer/_computer.dm | 6 +++--- icons/obj/computer.dmi | Bin 118008 -> 129964 bytes 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/game/machinery/computer/_computer.dm b/code/game/machinery/computer/_computer.dm index 3c3f0e7f0f..fb46229bdb 100644 --- a/code/game/machinery/computer/_computer.dm +++ b/code/game/machinery/computer/_computer.dm @@ -34,9 +34,9 @@ /obj/machinery/computer/ratvar_act() if(!clockwork) clockwork = TRUE - icon_screen = "ratvar[rand(1, 4)]" - icon_keyboard = "ratvar_key[rand(1, 6)]" - icon_state = "ratvarcomputer[rand(1, 4)]" + icon_screen = "ratvar[rand(1, 3)]" + icon_keyboard = "ratvar_key[rand(1, 2)]" + icon_state = "ratvarcomputer" update_icon() /obj/machinery/computer/narsie_act() diff --git a/icons/obj/computer.dmi b/icons/obj/computer.dmi index d22002935fa08ae475f23d11a029eb4cd92dd785..74ca14803975fc0d9d9c86cc1d77b3f7451083f4 100644 GIT binary patch literal 129964 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 z�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]-T$xM#K150g=rN(qZ zCWba_p9mG=`fA9a=OOBVkdPbt%mD-QJ!7K#9lH>Mnf7?!VOc#((|T*-y}q?)!yLZl zvp)PUGt_G5Sy3MQqKTAa2l6_W^A5(yJ2B4*ov@|#L|te=l0I!iGO!fU3t56eSG*|Uq{0KHy*F+hBwgUAg1|5H{GfJyf4MkP4;)a({%XAw*PjL3Gw{j z3l#R(9YSkrj-vRXZo4lWo)-@1FLF9|0fj}>35edAuh4GT+u%LORJmu@pGXT%D(27CbtcYN%m?73G!1XN z`3U%}1|6f`*X3D#}_eZ12O8sJ4LeKlQLMb?iq_|Ss44Y z(qoy$AL`vWCB0cnRvGSr{W*$hwh>7aaVXr(U6>p)0i|(MxuD*bUVEmqg-u1$_V(0` z_0)bkN)&@B#(tuc7io_Nl#$>RIQC2+X(wfq2;A-g;=Va07>&viaHFkL`0_=D0jeyE zTRrF^UNsR=&%KFrD7zC|W3L#}6?_rT%?g->omeRwr;!}B4j*~#UxBhN@gIB(-m0NXRgD>d# z8S^C#9`{|HvaJ=0T%P4h zqo>YuxtFaEky{yvPL$sqPlU@OSoelYcNH-&P%(awKYVqbDK8R1+8Lc3Kxc+|qq^oq z5C_w0NP-oifLX*9PY+YGdP#dJ3ieRX5^P@Asaxg1vhA_V2aYib${&*A{5a`5EQ8%B z?>0j>3^2PrF26o7!`STnl*9T57x3xx z)o%q}cAMjPL2PwtjD9s1b##>uIDtm%{jXWwsq%!!3g)a|S&Ha>ymVf=@Xj0=Z)C(g z7|VFHKfb-_lm}au1()1#-F#rpNfr+-2pCPny%>&lg<}zv6{|)FaE3b#39zOkL}k{O z3z<#G2C24iG(wvJQUHXJu{z-`g{0U4-+D)F5?eSu%qc%*D7u}EWz^1oiZgO?=c&pjTF`ziKZS>yt&INvrK!Ta{xp;|%RFa;LN= zWQ5S?&kQ~;+K~6|V#%+~(?)3Lvcdu)Cw9Cra#OcVSh^52{>#tt%s?R&C457zBN7K> zeX0KxPCJvkAp)0U<#e_$X*nwA`}mTHVDYC`@43vEag1#*Yt~JUPjLd(cmrcmt;j(U z<~aS%acHy<>7Q#w^ExP`ak`AMU(HApHuu?JMlx*lYZ7zn4$Xk%$AKh|F_lsxI#P#$FwBh1tOSO z_}z4OifI+GLJtDKf-OfA4M~t)j3Uen+#S1>ddXe(ku~Xz0CsXH1Xv2Eq6ry@EHO7$O(ugRjC~!QLzt z{Sf>>-3`5`wqUa(0UuhQ=TqhY2zFZUY|vau`(R#AA?3npgL_T6OzVkXiLG%yRL019 zPJe18<-4oDxS;?q&!N-s&(kl2zandNUoItl5zZlY@TZgll#I}hN6t8k_6~0}O+ker z3Cq1_$79ZC-O+81zjb3q_t?`G7i7ASV565y>-{}>v30`v8KdzD{q@8N+9WdS`)&cB zwzPV4CCFXuaV3#ak!%<9aLvA;j6b1AJbf;kzQ-U_dRJqW_pI@7%a^(0Z~gdUXNyrK zyVy@USJ-lqy`Z*Eki{&C_+L=tWz<$-m3RHPn)f@U%2N{%(*e$c9*tb_EHsT+(ftG} zpNps3(edWfZ^1M$vjdozWCXLzsC8nYv2|5%q*|@fdyK)Wn?yV+OU~U7I`*1bNic;8 zceqSXr(7P(K_KmCv=?8y*>Z{SmcV7hhAP;{2?5~*@lleX1cbNnaCJjQh#XjJly1H7IyJ8@MGg z!pDHeLEcGwht>Tjgsz@W{&H4DOjuRW-bRzZJDPJKFX^=S{&aw@5*rS0w=S( zS~!ut3t`i<&E9ZFe|_p^5BbGpV0>wJLA&D^ak2AQD~yx%`31F1&)@6I z^qFUE_GV949IT0@)6np{J=1#$dKFOvOySnmjh=BJJ*B^rI3cSaI{t+%XB#$1u<;6` zGXlKt)J`pIGWGVPhzvE57`Qy3UXLxhdUs^!wGtro2RCwhggRkKm6JV

D(+0P&3s_>=*EG6FJB!t&l?iY&P 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

-+9Vl}(uu>b@j(ExFA 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⪳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

Bpc1RR+Z9lnaF?zQH!zvkS*r!E%wwMh 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 E2FDjs-T(jq From 1e911cd5b267f8a7413f28c6ad883245e33fba0a Mon Sep 17 00:00:00 2001 From: Persi Date: Wed, 30 Oct 2019 21:16:49 -0400 Subject: [PATCH 32/58] Patches an exploit that allows the crew to shoot the Ark from the Reebe dressing room. --- _maps/map_files/generic/City_of_Cogs.dmm | 70 ++++++++++++------------ 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/_maps/map_files/generic/City_of_Cogs.dmm b/_maps/map_files/generic/City_of_Cogs.dmm index 584564ba2a..e1e7659ce3 100644 --- a/_maps/map_files/generic/City_of_Cogs.dmm +++ b/_maps/map_files/generic/City_of_Cogs.dmm @@ -26979,9 +26979,9 @@ ab ab ab ab -ab -ab -ab +ae +ae +ae ab ab ab @@ -27235,11 +27235,11 @@ ab ab ab ab -ab -ab -ab -ab -ab +ae +ag +ag +ag +ae ab ab ab @@ -27492,11 +27492,11 @@ ab ab ab ab -ab -ab -ab -ab -ab +ae +ag +ag +ag +ae aF aF aF @@ -27747,8 +27747,8 @@ ab ab ab ab -ae -ae +ab +ab ah ah ai @@ -28003,9 +28003,9 @@ ab ab ab ab -ae -ag -ag +ab +ab +ab ah ar aj @@ -28260,9 +28260,9 @@ ab ab ab ab -ae -ag -ag +ab +ab +ab ah as aj @@ -28517,9 +28517,9 @@ ab ab ab ab -ae -ag -ag +ab +ab +ab ah VP aj @@ -28775,8 +28775,8 @@ ab ab ab ab -ae -ae +ab +ab ah ah ay @@ -29033,7 +29033,7 @@ ab ab ab ab -ae +ab an au aj @@ -33657,7 +33657,7 @@ ab ab ab ab -ae +ab ah al aj @@ -33914,7 +33914,7 @@ ab ab ab ab -ae +ab ai bE aj @@ -34171,7 +34171,7 @@ ab ab ab ab -ae +ab ah al aj @@ -34688,11 +34688,11 @@ ab ab ab ab -ab -ab -ab -ab -ab +ae +ae +ag +ae +ae aF aF aF From 57dd768950810d5d17a344acbff89b9c9f33684c Mon Sep 17 00:00:00 2001 From: Putnam Date: Wed, 30 Oct 2019 23:11:50 -0700 Subject: [PATCH 33/58] makes cloning have no 2-second delay --- code/game/machinery/computer/cloning.dm | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 5cbd2d8975..c19e0be343 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -296,15 +296,13 @@ loading = 1 src.updateUsrDialog() - playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) say("Initiating scan...") - spawn(20) - src.scan_occupant(scanner.occupant) - - loading = 0 - src.updateUsrDialog() - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + src.scan_occupant(scanner.occupant) + + loading = 0 + src.updateUsrDialog() + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) //No locking an open scanner. From 9f97f768da2021c6d8fdf2a4edc09796d9b21860 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Thu, 31 Oct 2019 18:59:00 +0100 Subject: [PATCH 34/58] Respriting the ore redemption and miner vending machines. --- icons/obj/machines/mining_machines.dmi | Bin 4139 -> 4485 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/icons/obj/machines/mining_machines.dmi b/icons/obj/machines/mining_machines.dmi index 28d608125d70aac951964a6b3b9832d9fa03db02..aa60e7100c0d102ac4043f03a5139af7c201aa5d 100644 GIT binary patch literal 4485 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 delta 4099 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 Date: Thu, 31 Oct 2019 22:40:11 +0100 Subject: [PATCH 35/58] Ports "Replaces the rpg loot datum with a component and makes some suffixes have real effects" & co --- code/__DEFINES/components.dm | 7 + code/__DEFINES/fantasy_affixes.dm | 5 + code/__DEFINES/is_helpers.dm | 4 + code/datums/components/bane.dm | 45 +++++ code/datums/components/fantasy/_fantasy.dm | 140 +++++++++++++++ code/datums/components/fantasy/affix.dm | 13 ++ code/datums/components/fantasy/prefixes.dm | 68 +++++++ code/datums/components/fantasy/suffixes.dm | 170 ++++++++++++++++++ code/datums/components/igniter.dm | 37 ++++ code/datums/components/knockback.dm | 44 +++++ code/datums/components/lifesteal.dm | 39 ++++ code/datums/components/shrapnel.dm | 39 ++++ code/datums/components/summoning.dm | 69 +++++++ code/datums/components/tactical.dm | 42 +++++ .../machinery/porta_turret/portable_turret.dm | 1 + code/game/objects/items.dm | 6 +- code/game/objects/items/robot/robot_items.dm | 4 +- code/game/objects/structures/flora.dm | 15 +- code/modules/events/wizard/rpgloot.dm | 81 +-------- .../living/simple_animal/hostile/hostile.dm | 4 +- code/modules/power/singularity/emitter.dm | 1 + .../modules/projectiles/ammunition/_firing.dm | 7 +- .../ammunition/caseless/_caseless.dm | 2 +- code/modules/projectiles/gun.dm | 4 +- code/modules/projectiles/projectile.dm | 5 + tgstation.dme | 12 ++ 26 files changed, 766 insertions(+), 98 deletions(-) create mode 100644 code/__DEFINES/fantasy_affixes.dm create mode 100644 code/datums/components/bane.dm create mode 100644 code/datums/components/fantasy/_fantasy.dm create mode 100644 code/datums/components/fantasy/affix.dm create mode 100644 code/datums/components/fantasy/prefixes.dm create mode 100644 code/datums/components/fantasy/suffixes.dm create mode 100644 code/datums/components/igniter.dm create mode 100644 code/datums/components/knockback.dm create mode 100644 code/datums/components/lifesteal.dm create mode 100644 code/datums/components/shrapnel.dm create mode 100644 code/datums/components/summoning.dm create mode 100644 code/datums/components/tactical.dm diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm index 7ed8ee558b..3a680d1c90 100644 --- a/code/__DEFINES/components.dm +++ b/code/__DEFINES/components.dm @@ -157,6 +157,10 @@ // /mob/living/carbon signals #define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity)) +// /mob/living/simple_animal/hostile signals +#define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget" + #define COMPONENT_HOSTILE_NO_ATTACK 1 + // /obj signals #define COMSIG_OBJ_DECONSTRUCT "obj_deconstruct" //from base of obj/deconstruct(): (disassembled) #define COMSIG_OBJ_BREAK "obj_break" //from base of /obj/obj_break(): (damage_flag) @@ -206,6 +210,9 @@ // /obj/item/pen signals #define COMSIG_PEN_ROTATED "pen_rotated" //called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user) +// /obj/item/projectile signals (sent to the firer) +#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit" // from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle) +#define COMSIG_PROJECTILE_BEFORE_FIRE "projectile_before_fire" // from base of /obj/item/projectile/proc/fire(): (obj/item/projectile, atom/original_target) // /mob/living/carbon/human signals #define COMSIG_HUMAN_MELEE_UNARMED_ATTACK "human_melee_unarmed_attack" //from mob/living/carbon/human/UnarmedAttack(): (atom/target) diff --git a/code/__DEFINES/fantasy_affixes.dm b/code/__DEFINES/fantasy_affixes.dm new file mode 100644 index 0000000000..709d414d11 --- /dev/null +++ b/code/__DEFINES/fantasy_affixes.dm @@ -0,0 +1,5 @@ +#define AFFIX_PREFIX (1 << 0) +#define AFFIX_SUFFIX (1 << 1) + +#define AFFIX_GOOD (1 << 0) +#define AFFIX_EVIL (1 << 1) \ No newline at end of file diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 0dee8bd1e8..70010eeffc 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -219,6 +219,10 @@ GLOBAL_LIST_INIT(pointed_types, typecacheof(list( #define isbodypart(A) (istype(A, /obj/item/bodypart)) +#define isprojectile(A) (istype(A, /obj/item/projectile)) + +#define isgun(A) (istype(A, /obj/item/gun)) + //Assemblies #define isassembly(O) (istype(O, /obj/item/assembly)) diff --git a/code/datums/components/bane.dm b/code/datums/components/bane.dm new file mode 100644 index 0000000000..84f8010270 --- /dev/null +++ b/code/datums/components/bane.dm @@ -0,0 +1,45 @@ +/datum/component/bane + dupe_mode = COMPONENT_DUPE_ALLOWED + + var/mobtype + var/speciestype + var/damage_multiplier + +/datum/component/bane/Initialize(mobtype, damage_multiplier=1) + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + + if(ispath(mobtype, /mob/living)) + src.mobtype = mobtype + else if(ispath(mobtype, /datum/species)) + speciestype = mobtype + else + return COMPONENT_INCOMPATIBLE + + src.damage_multiplier = damage_multiplier + +/datum/component/bane/RegisterWithParent() + if(speciestype) + RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/speciesCheck) + else + RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/mobCheck) + +/datum/component/bane/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_ITEM_AFTERATTACK) + +/datum/component/bane/proc/speciesCheck(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) + if(!is_species(target, speciestype)) + return + activate(source, target, user) + +/datum/component/bane/proc/mobCheck(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) + if(!istype(target, mobtype)) + return + activate(source, target, user) + +/datum/component/bane/proc/activate(obj/item/source, mob/living/target, mob/attacker) + if(attacker.a_intent != INTENT_HARM) + return + + var/extra_damage = max(0, source.force * damage_multiplier) + target.apply_damage(extra_damage, source.damtype, attacker.zone_selected) diff --git a/code/datums/components/fantasy/_fantasy.dm b/code/datums/components/fantasy/_fantasy.dm new file mode 100644 index 0000000000..86e016784a --- /dev/null +++ b/code/datums/components/fantasy/_fantasy.dm @@ -0,0 +1,140 @@ +/datum/component/fantasy + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + + var/quality + + var/canFail + var/announce + + var/originalName + var/list/affixes + var/list/appliedComponents + + var/static/list/affixListing + +/datum/component/fantasy/Initialize(quality, list/affixes = list(), canFail=FALSE, announce=FALSE) + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + + src.quality = quality || randomQuality() + src.canFail = canFail + src.announce = announce + + src.affixes = affixes + appliedComponents = list() + randomAffixes() + +/datum/component/fantasy/Destroy() + unmodify() + affixes = null + return ..() + +/datum/component/fantasy/RegisterWithParent() + var/obj/item/master = parent + originalName = master.name + modify() + +/datum/component/fantasy/UnregisterFromParent() + unmodify() + +/datum/component/fantasy/InheritComponent(datum/component/fantasy/newComp, original, list/arguments) + unmodify() + if(newComp) + quality += newComp.quality + canFail = newComp.canFail + announce = newComp.announce + else + arguments.len = 5 // This is done to replicate what happens when an arglist smaller than the necessary arguments is given + quality += arguments[1] + canFail = arguments[4] || canFail + announce = arguments[5] || announce + modify() + +/datum/component/fantasy/proc/randomQuality() + var/quality = pick(1;15, 2;14, 2;13, 2;12, 3;11, 3;10, 3;9, 4;8, 4;7, 4;6, 5;5, 5;4, 5;3, 6;2, 6;1, 6;0) + if(prob(50)) + quality = -quality + return quality + +/datum/component/fantasy/proc/randomAffixes(force) + if(!affixListing) + affixListing = list() + for(var/T in subtypesof(/datum/fantasy_affix)) + var/datum/fantasy_affix/affix = new T + affixListing[affix] = affix.weight + + if(length(affixes)) + if(!force) + return + affixes = list() + + var/alignment + if(quality >= 0) + alignment |= AFFIX_GOOD + if(quality <= 0) + alignment |= AFFIX_EVIL + + var/usedSlots = NONE + for(var/i in 1 to max(1, abs(quality))) // We want at least 1 affix applied + var/datum/fantasy_affix/affix = pickweight(affixListing) + if(affix.placement & usedSlots) + continue + if(!(affix.alignment & alignment)) + continue + if(!affix.validate(src)) + continue + affixes += affix + usedSlots |= affix.placement + +/datum/component/fantasy/proc/modify() + var/obj/item/master = parent + + master.force = max(0, master.force + quality) + master.throwforce = max(0, master.throwforce + quality) + master.armor = master.armor?.modifyAllRatings(quality) + + var/newName = originalName + for(var/i in affixes) + var/datum/fantasy_affix/affix = i + newName = affix.apply(src, newName) + + if(quality != 0) + newName = "[newName] [quality > 0 ? "+" : ""][quality]" + + if(canFail && prob((quality - 9)*10)) + var/turf/place = get_turf(parent) + place.visible_message("[parent] violently glows blue for a while, then evaporates.") + master.burn() + return + else if(announce) + announce() + + master.name = newName + +/datum/component/fantasy/proc/unmodify() + var/obj/item/master = parent + + for(var/i in affixes) + var/datum/fantasy_affix/affix = i + affix.remove(src) + for(var/i in appliedComponents) + qdel(i) + + master.force = max(0, master.force - quality) + master.throwforce = max(0, master.throwforce - quality) + master.armor = master.armor?.modifyAllRatings(-quality) + + master.name = originalName + +/datum/component/fantasy/proc/announce() + var/turf/location = get_turf(parent) + var/span + var/effect_description + if(quality >= 0) + span = "" + effect_description = "shimmering golden glow" + else + span = "" + effect_description = "mottled black glow" + + location.visible_message("[span][originalName] is covered by a [effect_description] and then transforms into [parent]!") diff --git a/code/datums/components/fantasy/affix.dm b/code/datums/components/fantasy/affix.dm new file mode 100644 index 0000000000..ad1f44ce4d --- /dev/null +++ b/code/datums/components/fantasy/affix.dm @@ -0,0 +1,13 @@ +/datum/fantasy_affix + var/placement // A bitflag of "slots" this affix takes up, for example pre/suffix + var/alignment + var/weight = 10 + +// For those occasional affixes which only make sense in certain circumstances +/datum/fantasy_affix/proc/validate(datum/component/fantasy/comp) + return TRUE + +/datum/fantasy_affix/proc/apply(datum/component/fantasy/comp, newName) + return newName + +/datum/fantasy_affix/proc/remove(datum/component/fantasy/comp) diff --git a/code/datums/components/fantasy/prefixes.dm b/code/datums/components/fantasy/prefixes.dm new file mode 100644 index 0000000000..702ec9329a --- /dev/null +++ b/code/datums/components/fantasy/prefixes.dm @@ -0,0 +1,68 @@ +/datum/fantasy_affix/cosmetic_prefixes + placement = AFFIX_PREFIX + alignment = AFFIX_GOOD | AFFIX_EVIL + + var/list/goodPrefixes + var/list/badPrefixes + +/datum/fantasy_affix/cosmetic_prefixes/New() + goodPrefixes = list( + "greater", + "major", + "blessed", + "superior", + "empowered", + "honed", + "true", + "glorious", + "robust", + ) + badPrefixes = list( + "lesser", + "minor", + "blighted", + "inferior", + "enfeebled", + "rusted", + "unsteady", + "tragic", + "gimped", + "cursed", + ) + + weight = (length(goodPrefixes) + length(badPrefixes)) * 10 + +/datum/fantasy_affix/cosmetic_prefixes/apply(datum/component/fantasy/comp, newName) + if(comp.quality > 0 || (comp.quality == 0 && prob(50))) + return "[pick(goodPrefixes)] [newName]" + else + return "[pick(badPrefixes)] [newName]" + +/datum/fantasy_affix/tactical + placement = AFFIX_PREFIX + alignment = AFFIX_GOOD + weight = 1 // Very powerful, no one should have such power + +/datum/fantasy_affix/tactical/apply(datum/component/fantasy/comp, newName) + var/obj/item/master = comp.parent + comp.appliedComponents += master.AddComponent(/datum/component/tactical) + return "tactical [newName]" + +/datum/fantasy_affix/pyromantic + placement = AFFIX_PREFIX + alignment = AFFIX_GOOD + +/datum/fantasy_affix/pyromantic/apply(datum/component/fantasy/comp, newName) + var/obj/item/master = comp.parent + comp.appliedComponents += master.AddComponent(/datum/component/igniter, CLAMP(comp.quality, 1, 10)) + return "pyromantic [newName]" + +/datum/fantasy_affix/vampiric + placement = AFFIX_PREFIX + alignment = AFFIX_GOOD + weight = 5 + +/datum/fantasy_affix/vampiric/apply(datum/component/fantasy/comp, newName) + var/obj/item/master = comp.parent + comp.appliedComponents += master.AddComponent(/datum/component/lifesteal, comp.quality) + return "vampiric [newName]" \ No newline at end of file diff --git a/code/datums/components/fantasy/suffixes.dm b/code/datums/components/fantasy/suffixes.dm new file mode 100644 index 0000000000..f32ca50595 --- /dev/null +++ b/code/datums/components/fantasy/suffixes.dm @@ -0,0 +1,170 @@ +/datum/fantasy_affix/cosmetic_suffixes + placement = AFFIX_SUFFIX + alignment = AFFIX_GOOD | AFFIX_EVIL + + var/list/goodSuffixes + var/list/badSuffixes + +/datum/fantasy_affix/cosmetic_suffixes/New() + goodSuffixes = list( + "dexterity", + "constitution", + "intelligence", + "wisdom", + "charisma", + "the forest", + "the hills", + "the plains", + "the sea", + "the sun", + "the moon", + "the void", + "the world", + "many secrets", + "many tales", + "many colors", + "rending", + "sundering", + "the night", + "the day", + ) + badSuffixes = list( + "draining", + "burden", + "discomfort", + "awkwardness", + "poor hygiene", + "timidity", + ) + + weight = (length(goodSuffixes) + length(badSuffixes)) * 10 + +/datum/fantasy_affix/cosmetic_suffixes/apply(datum/component/fantasy/comp, newName) + if(comp.quality > 0 || (comp.quality == 0 && prob(50))) + return "[newName] of [pick(goodSuffixes)]" + else + return "[newName] of [pick(badSuffixes)]" + +//////////// Good suffixes +/datum/fantasy_affix/bane + placement = AFFIX_SUFFIX + alignment = AFFIX_GOOD + weight = 20 + +/datum/fantasy_affix/bane/apply(datum/component/fantasy/comp, newName) + . = ..() + // This is set up to be easy to add to these lists as I expect it will need modifications + var/static/list/possible_mobtypes + if(!possible_mobtypes) + // The base list of allowed mob/species types + possible_mobtypes = typecacheof(list( + /mob/living/simple_animal, + /mob/living/carbon, + /datum/species, + )) + // Some particular types to disallow if they're too broad/abstract + possible_mobtypes -= list( + /mob/living/simple_animal/hostile, + ) + // Some types to remove them and their subtypes + possible_mobtypes -= typecacheof(list( + /mob/living/carbon/human/species, + )) + + var/mob/picked_mobtype = pick(possible_mobtypes) + // This works even with the species picks since we're only accessing the name + + var/obj/item/master = comp.parent + comp.appliedComponents += master.AddComponent(/datum/component/bane, picked_mobtype) + return "[newName] of [initial(picked_mobtype.name)] slaying" + +/datum/fantasy_affix/summoning + placement = AFFIX_SUFFIX + alignment = AFFIX_GOOD + weight = 5 + +/datum/fantasy_affix/summoning/apply(datum/component/fantasy/comp, newName) + . = ..() + // This is set up to be easy to add to these lists as I expect it will need modifications + var/static/list/possible_mobtypes + if(!possible_mobtypes) + // The base list of allowed mob/species types + possible_mobtypes = typecacheof(list( + /mob/living/simple_animal, + /mob/living/carbon, + /datum/species, + )) + // Some particular types to disallow if they're too broad/abstract + possible_mobtypes -= list( + /mob/living/simple_animal/hostile, + ) + // Some types to remove them and their subtypes + possible_mobtypes -= typecacheof(list( + /mob/living/carbon/human/species, + /mob/living/simple_animal/hostile/megafauna, + )) + + var/mob/picked_mobtype = pick(possible_mobtypes) + // This works even with the species picks since we're only accessing the name + + var/obj/item/master = comp.parent + var/max_mobs = max(CEILING(comp.quality/2, 1), 1) + var/spawn_delay = 300 - 30 * comp.quality + comp.appliedComponents += master.AddComponent(/datum/component/summoning, list(picked_mobtype), 100, max_mobs, spawn_delay) + return "[newName] of [initial(picked_mobtype.name)] summoning" + +/datum/fantasy_affix/shrapnel + placement = AFFIX_SUFFIX + alignment = AFFIX_GOOD + +/datum/fantasy_affix/shrapnel/validate(datum/component/fantasy/comp) + if(isgun(comp.parent)) + return TRUE + return FALSE + +/datum/fantasy_affix/shrapnel/apply(datum/component/fantasy/comp, newName) + . = ..() + // higher means more likely + var/list/weighted_projectile_types = list(/obj/item/projectile/meteor = 1, + /obj/item/projectile/energy/nuclear_particle = 1, + /obj/item/projectile/beam/pulse = 1, + /obj/item/projectile/bullet/honker = 15, + /obj/item/projectile/temp = 15, + /obj/item/projectile/ion = 15, + /obj/item/projectile/magic/door = 15, + /obj/item/projectile/magic/locker = 15, +// /obj/item/projectile/magic/fetch = 15, + /obj/item/projectile/beam/emitter = 15, +// /obj/item/projectile/magic/flying = 15, + /obj/item/projectile/energy/net = 15, + /obj/item/projectile/bullet/incendiary/c9mm = 15, + /obj/item/projectile/temp/hot = 15, + /obj/item/projectile/beam/disabler = 15) + + var/obj/item/projectile/picked_projectiletype = pickweight(weighted_projectile_types) + + var/obj/item/master = comp.parent + comp.appliedComponents += master.AddComponent(/datum/component/shrapnel, picked_projectiletype) + return "[newName] of [initial(picked_projectiletype.name)] shrapnel" + +/datum/fantasy_affix/strength + placement = AFFIX_SUFFIX + alignment = AFFIX_GOOD + +/datum/fantasy_affix/strength/apply(datum/component/fantasy/comp, newName) + . = ..() + var/obj/item/master = comp.parent + comp.appliedComponents += master.AddComponent(/datum/component/knockback, CEILING(comp.quality/2, 1), FLOOR(comp.quality/10, 1)) + return "[newName] of strength" + +//////////// Bad suffixes + +/datum/fantasy_affix/fool + placement = AFFIX_SUFFIX + alignment = AFFIX_EVIL + +/datum/fantasy_affix/fool/apply(datum/component/fantasy/comp, newName) + . = ..() + var/obj/item/master = comp.parent + comp.appliedComponents += master.AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg'=1), 50) + return "[newName] of the fool" diff --git a/code/datums/components/igniter.dm b/code/datums/components/igniter.dm new file mode 100644 index 0000000000..b40383e828 --- /dev/null +++ b/code/datums/components/igniter.dm @@ -0,0 +1,37 @@ + +/datum/component/igniter + var/fire_stacks + +/datum/component/igniter/Initialize(fire_stacks=1) + if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent)) + return COMPONENT_INCOMPATIBLE + + src.fire_stacks = fire_stacks + +/datum/component/igniter/RegisterWithParent() + if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc + RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit) + else if(isitem(parent)) + RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack) + else if(ishostile(parent)) + RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget) + +/datum/component/igniter/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT)) + +/datum/component/igniter/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) + if(!proximity_flag) + return + do_igniter(target) + +/datum/component/igniter/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target) + do_igniter(target) + +/datum/component/igniter/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle) + do_igniter(target) + +/datum/component/igniter/proc/do_igniter(atom/target) + if(isliving(target)) + var/mob/living/L = target + L.adjust_fire_stacks(fire_stacks) + L.IgniteMob() \ No newline at end of file diff --git a/code/datums/components/knockback.dm b/code/datums/components/knockback.dm new file mode 100644 index 0000000000..b4fcaa2dd8 --- /dev/null +++ b/code/datums/components/knockback.dm @@ -0,0 +1,44 @@ +/datum/component/knockback + var/throw_distance + var/throw_anchored + +/datum/component/knockback/Initialize(throw_distance=1) + if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent)) + return COMPONENT_INCOMPATIBLE + + src.throw_distance = throw_distance + src.throw_anchored = throw_anchored + +/datum/component/knockback/RegisterWithParent() + if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc + RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit) + else if(isitem(parent)) + RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack) + else if(ishostile(parent)) + RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget) + +/datum/component/knockback/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT)) + +/datum/component/knockback/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) + if(!proximity_flag) + return + do_knockback(target, user, get_dir(source, target)) + +/datum/component/knockback/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target) + do_knockback(target, attacker, get_dir(attacker, target)) + +/datum/component/knockback/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle) + do_knockback(target, null, angle2dir(Angle)) + +/datum/component/knockback/proc/do_knockback(atom/target, mob/thrower, throw_dir) + if(!ismovableatom(target) || throw_dir == null) + return + var/atom/movable/throwee = target + if(throwee.anchored && !throw_anchored) + return + if(throw_distance < 0) + throw_dir = turn(throw_dir, 180) + throw_distance *= -1 + var/atom/throw_target = get_edge_target_turf(throwee, throw_dir) + throwee.safe_throw_at(throw_target, throw_distance, 1, thrower) diff --git a/code/datums/components/lifesteal.dm b/code/datums/components/lifesteal.dm new file mode 100644 index 0000000000..c7a78e10a3 --- /dev/null +++ b/code/datums/components/lifesteal.dm @@ -0,0 +1,39 @@ + +/datum/component/lifesteal + var/flat_heal // heals a constant amount every time a hit occurs + var/static/list/damage_heal_order = list(BRUTE, BURN, OXY) + +/datum/component/lifesteal/Initialize(flat_heal=0) + if(!isitem(parent) && !ishostile(parent) && !isgun(parent)) + return COMPONENT_INCOMPATIBLE + + src.flat_heal = flat_heal + +/datum/component/lifesteal/RegisterWithParent() + if(isgun(parent)) + RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit) + else if(isitem(parent)) + RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack) + else if(ishostile(parent)) + RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget) + +/datum/component/lifesteal/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT)) + +/datum/component/lifesteal/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) + if(!proximity_flag) + return + do_lifesteal(user, target) + +/datum/component/lifesteal/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target) + do_lifesteal(attacker, target) + +/datum/component/lifesteal/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle) + do_lifesteal(firer, target) + +/datum/component/lifesteal/proc/do_lifesteal(atom/heal_target, atom/damage_target) + if(isliving(heal_target) && isliving(damage_target)) + var/mob/living/healing = heal_target + var/mob/living/damaging = damage_target + if(damaging.stat != DEAD) + healing.heal_ordered_damage(flat_heal, damage_heal_order) diff --git a/code/datums/components/shrapnel.dm b/code/datums/components/shrapnel.dm new file mode 100644 index 0000000000..a911221f26 --- /dev/null +++ b/code/datums/components/shrapnel.dm @@ -0,0 +1,39 @@ + +/datum/component/shrapnel + var/projectile_type + var/radius // shoots a projectile for every turf on this radius from the hit target + var/override_projectile_range + +/datum/component/shrapnel/Initialize(projectile_type, radius=1, override_projectile_range) + if(!isgun(parent) && !ismachinery(parent) && !isstructure(parent)) + return COMPONENT_INCOMPATIBLE + + src.projectile_type = projectile_type + src.radius = radius + src.override_projectile_range = override_projectile_range + +/datum/component/shrapnel/RegisterWithParent() + if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc + RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit) + +/datum/component/shrapnel/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_PROJECTILE_ON_HIT)) + +/datum/component/shrapnel/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle) + do_shrapnel(firer, target) + +/datum/component/shrapnel/proc/do_shrapnel(mob/firer, atom/target) + if(radius < 1) + return + var/turf/target_turf = get_turf(target) + for(var/turf/shootat_turf in RANGE_TURFS(radius, target) - RANGE_TURFS(radius-1, target)) + var/obj/item/projectile/P = new projectile_type(target_turf) + + //Shooting Code: + P.range = radius+1 + if(override_projectile_range) + P.range = override_projectile_range + P.preparePixelProjectile(shootat_turf, target) + P.firer = firer // don't hit ourself that would be really annoying + P.permutated += target // don't hit the target we hit already with the flak + P.fire() diff --git a/code/datums/components/summoning.dm b/code/datums/components/summoning.dm new file mode 100644 index 0000000000..552959603d --- /dev/null +++ b/code/datums/components/summoning.dm @@ -0,0 +1,69 @@ + +/datum/component/summoning + var/list/mob_types = list() + var/spawn_chance // chance for the mob to spawn on hit in percent + var/max_mobs + var/spawn_delay // delay in spawning between mobs (deciseconds) + var/spawn_text + var/spawn_sound + var/list/faction + + var/last_spawned_time = 0 + var/list/spawned_mobs = list() + +/datum/component/summoning/Initialize(mob_types, spawn_chance=100, max_mobs=3, spawn_delay=100, spawn_text="appears out of nowhere", spawn_sound='sound/magic/summon_magic.ogg', faction) + if(!isitem(parent) && !ishostile(parent) && !isgun(parent) && !ismachinery(parent) && !isstructure(parent)) + return COMPONENT_INCOMPATIBLE + + src.mob_types = mob_types + src.spawn_chance = spawn_chance + src.max_mobs = max_mobs + src.spawn_delay = spawn_delay + src.spawn_text = spawn_text + src.spawn_sound = spawn_sound + src.faction = faction + +/datum/component/summoning/RegisterWithParent() + if(ismachinery(parent) || isstructure(parent) || isgun(parent)) // turrets, etc + RegisterSignal(parent, COMSIG_PROJECTILE_ON_HIT, .proc/projectile_hit) + else if(isitem(parent)) + RegisterSignal(parent, COMSIG_ITEM_AFTERATTACK, .proc/item_afterattack) + else if(ishostile(parent)) + RegisterSignal(parent, COMSIG_HOSTILE_ATTACKINGTARGET, .proc/hostile_attackingtarget) + +/datum/component/summoning/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_ITEM_AFTERATTACK, COMSIG_HOSTILE_ATTACKINGTARGET, COMSIG_PROJECTILE_ON_HIT)) + +/datum/component/summoning/proc/item_afterattack(obj/item/source, atom/target, mob/user, proximity_flag, click_parameters) + if(!proximity_flag) + return + do_spawn_mob(get_turf(target), user) + +/datum/component/summoning/proc/hostile_attackingtarget(mob/living/simple_animal/hostile/attacker, atom/target) + do_spawn_mob(get_turf(target), attacker) + +/datum/component/summoning/proc/projectile_hit(atom/fired_from, atom/movable/firer, atom/target, Angle) + do_spawn_mob(get_turf(target), firer) + +/datum/component/summoning/proc/do_spawn_mob(atom/spawn_location, summoner) + if(spawned_mobs.len >= max_mobs) + return 0 + if(last_spawned_time > world.time) + return 0 + if(!prob(spawn_chance)) + return 0 + last_spawned_time = world.time + spawn_delay + var/chosen_mob_type = pick(mob_types) + var/mob/living/simple_animal/L = new chosen_mob_type(spawn_location) + if(ishostile(L)) + var/mob/living/simple_animal/hostile/H = L + H.friends += summoner // do not attack our summon boy + spawned_mobs += L + if(faction != null) + L.faction = faction + RegisterSignal(L, COMSIG_MOB_DEATH, .proc/on_spawned_death) // so we can remove them from the list, etc (for mobs with corpses) + playsound(spawn_location,spawn_sound, 50, 1) + spawn_location.visible_message("[L] [spawn_text].") + +/datum/component/summoning/proc/on_spawned_death(mob/killed, gibbed) + spawned_mobs -= killed \ No newline at end of file diff --git a/code/datums/components/tactical.dm b/code/datums/components/tactical.dm new file mode 100644 index 0000000000..5917fc3009 --- /dev/null +++ b/code/datums/components/tactical.dm @@ -0,0 +1,42 @@ + +/datum/component/tactical + var/allowed_slot + +/datum/component/tactical/Initialize(allowed_slot) + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + + src.allowed_slot = allowed_slot + +/datum/component/tactical/RegisterWithParent() + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/modify) + RegisterSignal(parent, COMSIG_ITEM_DROPPED, .proc/unmodify) + +/datum/component/tactical/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED)) + unmodify() + +/datum/component/fantasy/Destroy() + unmodify() + return ..() + +/datum/component/tactical/proc/modify(obj/item/source, mob/user, slot) + if(allowed_slot && slot != allowed_slot) + unmodify() + return + + var/obj/item/master = parent + var/image/I = image(icon = master.icon, icon_state = master.icon_state, loc = user) + I.copy_overlays(master) + I.override = TRUE + source.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "sneaking_mission", I) + I.layer = ABOVE_MOB_LAYER + +/datum/component/tactical/proc/unmodify(obj/item/source, mob/user) + var/obj/item/master = source || parent + if(!user) + if(!ismob(master.loc)) + return + user = master.loc + + user.remove_alt_appearance("sneaking_mission") diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 165170cf0f..7aaab0d8ea 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -562,6 +562,7 @@ //Shooting Code: A.preparePixelProjectile(target, T) A.firer = src + A.fired_from = src A.fire() return A diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 9ce2e66abf..4f81a875f1 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -97,9 +97,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) // non-clothing items var/datum/dog_fashion/dog_fashion = null - var/datum/rpg_loot/rpg_loot = null - - //Tooltip vars var/force_string //string form of an item's force. Edit this var only to set a custom force string var/last_force_string_check = 0 @@ -124,7 +121,7 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) actions_types = null if(GLOB.rpg_loot_items) - rpg_loot = new(src) + AddComponent(/datum/component/fantasy) if(force_string) item_flags |= FORCE_STRING_OVERRIDE @@ -149,7 +146,6 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) m.temporarilyRemoveItemFromInventory(src, TRUE) for(var/X in actions) qdel(X) - QDEL_NULL(rpg_loot) return ..() /obj/item/proc/check_allowed_items(atom/target, not_inside, target_self) diff --git a/code/game/objects/items/robot/robot_items.dm b/code/game/objects/items/robot/robot_items.dm index d6effe0727..77bc7ed810 100644 --- a/code/game/objects/items/robot/robot_items.dm +++ b/code/game/objects/items/robot/robot_items.dm @@ -430,7 +430,7 @@ A.BB.nodamage = FALSE A.BB.speed = 0.5 playsound(src.loc, 'sound/machines/click.ogg', 50, 1) - A.fire_casing(target, user, params, 0, 0, null, 0) + A.fire_casing(target, user, params, 0, 0, null, 0, src) user.visible_message("[user] blasts a flying lollipop at [target]!") check_amount() @@ -446,7 +446,7 @@ A.BB.speed = 0.5 A.BB.color = rgb(rand(0, 255), rand(0, 255), rand(0, 255)) playsound(src.loc, 'sound/weapons/bulletflyby3.ogg', 50, 1) - A.fire_casing(target, user, params, 0, 0, null, 0) + A.fire_casing(target, user, params, 0, 0, null, 0, src) user.visible_message("[user] shoots a high-velocity gumball at [target]!") check_amount() diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index 7c73a1fd8c..12529fb9e0 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -300,18 +300,9 @@ throw_speed = 2 throw_range = 4 - -/obj/item/twohanded/required/kirbyplants/equipped(mob/living/user) - var/image/I = image(icon = 'icons/obj/flora/plants.dmi' , icon_state = src.icon_state, loc = user) - I.copy_overlays(src) - I.override = 1 - add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, "sneaking_mission", I) - I.layer = ABOVE_MOB_LAYER - ..() - -/obj/item/twohanded/required/kirbyplants/dropped(mob/living/user) - ..() - user.remove_alt_appearance("sneaking_mission") +/obj/item/twohanded/required/kirbyplants/Initialize() + . = ..() + AddComponent(/datum/component/tactical) /obj/item/twohanded/required/kirbyplants/random icon = 'icons/obj/flora/_flora.dmi' diff --git a/code/modules/events/wizard/rpgloot.dm b/code/modules/events/wizard/rpgloot.dm index 3d560aefb8..bf3104450e 100644 --- a/code/modules/events/wizard/rpgloot.dm +++ b/code/modules/events/wizard/rpgloot.dm @@ -8,8 +8,11 @@ /datum/round_event/wizard/rpgloot/start() var/upgrade_scroll_chance = 0 for(var/obj/item/I in world) - if(!istype(I.rpg_loot)) - I.rpg_loot = new(I) + CHECK_TICK + if(!(I.flags_1 & INITIALIZED_1)) + continue + + I.AddComponent(/datum/component/fantasy) if(istype(I, /obj/item/storage)) var/obj/item/storage/S = I @@ -31,86 +34,20 @@ var/upgrade_amount = 1 var/can_backfire = TRUE - var/one_use = TRUE + var/uses = 1 /obj/item/upgradescroll/afterattack(obj/item/target, mob/user , proximity) . = ..() if(!proximity || !istype(target)) return - var/datum/rpg_loot/rpg_loot_datum = target.rpg_loot - if(!istype(rpg_loot_datum)) - target.rpg_loot = rpg_loot_datum = new /datum/rpg_loot(target) + target.AddComponent(/datum/component/fantasy, upgrade_amount, null, null, can_backfire, TRUE) - var/quality = rpg_loot_datum.quality - - if(can_backfire && (quality > 9 && prob((quality - 9)*10))) - to_chat(user, "[target] violently glows blue for a while, then evaporates.") - target.burn() - else - to_chat(user, "[target] glows blue and seems vaguely \"better\"!") - rpg_loot_datum.modify(upgrade_amount) - - if(one_use) + if(--uses <= 0) qdel(src) /obj/item/upgradescroll/unlimited name = "unlimited foolproof item fortification scroll" desc = "Somehow, this piece of paper can be applied to items to make them \"better\". This scroll is made from the tongues of dead paper wizards, and can be used an unlimited number of times, with no drawbacks." - one_use = FALSE + uses = INFINITY can_backfire = FALSE - -/datum/rpg_loot - var/positive_prefix = "okay" - var/negative_prefix = "weak" - var/suffix = "something profound" - var/quality = 0 - - var/obj/item/attached - var/original_name - -/datum/rpg_loot/New(attached_item=null) - attached = attached_item - - randomise() - -/datum/rpg_loot/Destroy() - attached = null - -/datum/rpg_loot/proc/randomise() - var/static/list/prefixespositive = list("greater", "major", "blessed", "superior", "empowered", "honed", "true", "glorious", "robust") - var/static/list/prefixesnegative = list("lesser", "minor", "blighted", "inferior", "enfeebled", "rusted", "unsteady", "tragic", "gimped") - var/static/list/suffixes = list("orc slaying", "elf slaying", "corgi slaying", "strength", "dexterity", "constitution", "intelligence", "wisdom", "charisma", "the forest", "the hills", "the plains", "the sea", "the sun", "the moon", "the void", "the world", "the fool", "many secrets", "many tales", "many colors", "rending", "sundering", "the night", "the day") - - var/new_quality = pick(1;15, 2;14, 2;13, 2;12, 3;11, 3;10, 3;9, 4;8, 4;7, 4;6, 5;5, 5;4, 5;3, 6;2, 6;1, 6;0) - - suffix = pick(suffixes) - positive_prefix = pick(prefixespositive) - negative_prefix = pick(prefixesnegative) - - if(prob(50)) - new_quality = -new_quality - - modify(new_quality) - -/datum/rpg_loot/proc/rename() - var/obj/item/I = attached - if(!original_name) - original_name = I.name - if(quality < 0) - I.name = "[negative_prefix] [original_name] of [suffix] [quality]" - else if(quality == 0) - I.name = "[original_name] of [suffix]" - else if(quality > 0) - I.name = "[positive_prefix] [original_name] of [suffix] +[quality]" - -/datum/rpg_loot/proc/modify(quality_mod) - var/obj/item/I = attached - quality += quality_mod - - I.force = max(0,I.force + quality_mod) - I.throwforce = max(0,I.throwforce + quality_mod) - - I.armor = I.armor.modifyAllRatings(quality) - - rename() diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index 368c5ad4a8..9cd0504315 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -344,6 +344,7 @@ /mob/living/simple_animal/hostile/proc/AttackingTarget() + SEND_SIGNAL(src, COMSIG_HOSTILE_ATTACKINGTARGET, target) in_melee = TRUE if(vore_active) if(isliving(target)) @@ -426,12 +427,13 @@ if(casingtype) var/obj/item/ammo_casing/casing = new casingtype(startloc) playsound(src, projectilesound, 100, 1) - casing.fire_casing(targeted_atom, src, null, null, null, ran_zone()) + casing.fire_casing(targeted_atom, src, null, null, null, ran_zone(), src) else if(projectiletype) var/obj/item/projectile/P = new projectiletype(startloc) playsound(src, projectilesound, 100, 1) P.starting = startloc P.firer = src + P.fired_from = src P.yo = targeted_atom.y - startloc.y P.xo = targeted_atom.x - startloc.x if(AIStatus != AI_ON)//Don't want mindless mobs to have their movement screwed up firing in space diff --git a/code/modules/power/singularity/emitter.dm b/code/modules/power/singularity/emitter.dm index 4d6ede69d1..71a8565d26 100644 --- a/code/modules/power/singularity/emitter.dm +++ b/code/modules/power/singularity/emitter.dm @@ -199,6 +199,7 @@ if(prob(35)) sparks.start() P.firer = user ? user : src + P.fired_from = src if(last_projectile_params) P.p_x = last_projectile_params[2] P.p_y = last_projectile_params[3] diff --git a/code/modules/projectiles/ammunition/_firing.dm b/code/modules/projectiles/ammunition/_firing.dm index 441088c78c..a83042c90a 100644 --- a/code/modules/projectiles/ammunition/_firing.dm +++ b/code/modules/projectiles/ammunition/_firing.dm @@ -1,8 +1,8 @@ -/obj/item/ammo_casing/proc/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread) +/obj/item/ammo_casing/proc/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread, atom/fired_from) distro += variance for (var/i = max(1, pellets), i > 0, i--) var/targloc = get_turf(target) - ready_proj(target, user, quiet, zone_override) + ready_proj(target, user, quiet, zone_override, fired_from) if(distro) //We have to spread a pixel-precision bullet. throw_proj was called before so angles should exist by now... if(randomspread) spread = round((rand() - 0.5) * distro) @@ -20,11 +20,12 @@ update_icon() return 1 -/obj/item/ammo_casing/proc/ready_proj(atom/target, mob/living/user, quiet, zone_override = "") +/obj/item/ammo_casing/proc/ready_proj(atom/target, mob/living/user, quiet, zone_override = "", fired_from) if (!BB) return BB.original = target BB.firer = user + BB.fired_from = fired_from if (zone_override) BB.def_zone = zone_override else diff --git a/code/modules/projectiles/ammunition/caseless/_caseless.dm b/code/modules/projectiles/ammunition/caseless/_caseless.dm index a6b65f79e3..11f7b8670d 100644 --- a/code/modules/projectiles/ammunition/caseless/_caseless.dm +++ b/code/modules/projectiles/ammunition/caseless/_caseless.dm @@ -3,7 +3,7 @@ firing_effect_type = null heavy_metal = FALSE -/obj/item/ammo_casing/caseless/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread) +/obj/item/ammo_casing/caseless/fire_casing(atom/target, mob/living/user, params, distro, quiet, zone_override, spread, atom/fired_from) if (..()) //successfully firing moveToNullspace() QDEL_NULL(src) diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 4004bc81ae..6694d42dce 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -233,7 +233,7 @@ else //Smart spread sprd = round((((rand_spr/burst_size) * iteration) - (0.5 + (rand_spr * 0.25))) * (randomized_gun_spread + randomized_bonus_spread), 1) - if(!chambered.fire_casing(target, user, params, ,suppressed, zone_override, sprd)) + if(!chambered.fire_casing(target, user, params, ,suppressed, zone_override, sprd, src)) shoot_with_empty_chamber(user) firing_burst = FALSE return FALSE @@ -280,7 +280,7 @@ to_chat(user, " [src] is lethally chambered! You don't want to risk harming anyone...") return sprd = round((rand() - 0.5) * DUALWIELD_PENALTY_EXTRA_MULTIPLIER * (randomized_gun_spread + randomized_bonus_spread)) - if(!chambered.fire_casing(target, user, params, , suppressed, zone_override, sprd)) + if(!chambered.fire_casing(target, user, params, , suppressed, zone_override, sprd, src)) shoot_with_empty_chamber(user) return else diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index dca7a6087c..e1122f7eaa 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -17,6 +17,7 @@ resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF var/def_zone = "" //Aiming at var/atom/movable/firer = null//Who shot it + var/atom/fired_from = null // the atom that the projectile was fired from (gun, turret) var/suppressed = FALSE //Attack message var/candink = FALSE //Can this projectile play the dink sound when hitting the head? var/yo = null @@ -131,6 +132,8 @@ return TRUE /obj/item/projectile/proc/on_hit(atom/target, blocked = FALSE) + if(fired_from) + SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_ON_HIT, firer, target, Angle) var/turf/target_loca = get_turf(target) var/hitx @@ -356,6 +359,8 @@ pixel_move(1, FALSE) /obj/item/projectile/proc/fire(angle, atom/direct_target) + if(fired_from) + SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_BEFORE_FIRE, src, original) //If no angle needs to resolve it from xo/yo! if(!log_override && firer && original) log_combat(firer, original, "fired at", src, "from [get_area_name(src, TRUE)]") diff --git a/tgstation.dme b/tgstation.dme index c13db8171d..ba6ac3cc99 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -45,6 +45,7 @@ #include "code\__DEFINES\donator_groupings.dm" #include "code\__DEFINES\events.dm" #include "code\__DEFINES\exports.dm" +#include "code\__DEFINES\fantasy_affixes.dm" #include "code\__DEFINES\flags.dm" #include "code\__DEFINES\food.dm" #include "code\__DEFINES\footsteps.dm" @@ -344,6 +345,7 @@ #include "code\datums\components\_component.dm" #include "code\datums\components\anti_magic.dm" #include "code\datums\components\armor_plate.dm" +#include "code\datums\components\bane.dm" #include "code\datums\components\bouncy.dm" #include "code\datums\components\butchering.dm" #include "code\datums\components\caltrop.dm" @@ -357,9 +359,12 @@ #include "code\datums\components\empprotection.dm" #include "code\datums\components\footstep.dm" #include "code\datums\components\forced_gravity.dm" +#include "code\datums\components\igniter.dm" #include "code\datums\components\infective.dm" #include "code\datums\components\jousting.dm" +#include "code\datums\components\knockback.dm" #include "code\datums\components\knockoff.dm" +#include "code\datums\components\lifesteal.dm" #include "code\datums\components\lockon_aiming.dm" #include "code\datums\components\magnetic_catch.dm" #include "code\datums\components\material_container.dm" @@ -375,16 +380,23 @@ #include "code\datums\components\remote_materials.dm" #include "code\datums\components\riding.dm" #include "code\datums\components\rotation.dm" +#include "code\datums\components\shrapnel.dm" #include "code\datums\components\slippery.dm" #include "code\datums\components\spooky.dm" #include "code\datums\components\squeak.dm" #include "code\datums\components\stationloving.dm" +#include "code\datums\components\summoning.dm" #include "code\datums\components\swarming.dm" +#include "code\datums\components\tactical.dm" #include "code\datums\components\thermite.dm" #include "code\datums\components\uplink.dm" #include "code\datums\components\virtual_reality.dm" #include "code\datums\components\wearertargeting.dm" #include "code\datums\components\wet_floor.dm" +#include "code\datums\components\fantasy\_fantasy.dm" +#include "code\datums\components\fantasy\affix.dm" +#include "code\datums\components\fantasy\prefixes.dm" +#include "code\datums\components\fantasy\suffixes.dm" #include "code\datums\components\storage\storage.dm" #include "code\datums\components\storage\concrete\_concrete.dm" #include "code\datums\components\storage\concrete\bag_of_holding.dm" From 848c9dce0068e285da32578cb7ff7a607bb161ed Mon Sep 17 00:00:00 2001 From: Putnam Date: Thu, 31 Oct 2019 16:39:02 -0700 Subject: [PATCH 36/58] Revert "makes cloning have no 2-second delay" This reverts commit 57dd768950810d5d17a344acbff89b9c9f33684c. --- code/game/machinery/computer/cloning.dm | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index c19e0be343..5cbd2d8975 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -296,13 +296,15 @@ loading = 1 src.updateUsrDialog() + playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) say("Initiating scan...") - src.scan_occupant(scanner.occupant) - - loading = 0 - src.updateUsrDialog() - playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + spawn(20) + src.scan_occupant(scanner.occupant) + + loading = 0 + src.updateUsrDialog() + playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) //No locking an open scanner. From d81d1c6b2d4dd894ac14c87476c9ad4d5275d8a2 Mon Sep 17 00:00:00 2001 From: Putnam Date: Thu, 31 Oct 2019 16:39:54 -0700 Subject: [PATCH 37/58] actually make it lock instead --- code/game/machinery/computer/cloning.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 5cbd2d8975..03949503e1 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -298,13 +298,14 @@ src.updateUsrDialog() playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) say("Initiating scan...") - + scanner.locked = TRUE spawn(20) src.scan_occupant(scanner.occupant) loading = 0 src.updateUsrDialog() playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) + scanner.locked = FALSE //No locking an open scanner. From 64b812254851b3d3f17a6350fadd3c2807fc528f Mon Sep 17 00:00:00 2001 From: Putnam Date: Thu, 31 Oct 2019 16:46:04 -0700 Subject: [PATCH 38/58] made it go back to previous locked state instead --- code/game/machinery/computer/cloning.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/code/game/machinery/computer/cloning.dm b/code/game/machinery/computer/cloning.dm index 03949503e1..43cfbdb33b 100644 --- a/code/game/machinery/computer/cloning.dm +++ b/code/game/machinery/computer/cloning.dm @@ -298,6 +298,7 @@ src.updateUsrDialog() playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) say("Initiating scan...") + var/prev_locked = scanner.locked scanner.locked = TRUE spawn(20) src.scan_occupant(scanner.occupant) @@ -305,7 +306,7 @@ loading = 0 src.updateUsrDialog() playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) - scanner.locked = FALSE + scanner.locked = prev_locked //No locking an open scanner. From 1f53f5ee72e124d938de553d654f7ae68fe944d2 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 31 Oct 2019 19:27:06 -0500 Subject: [PATCH 39/58] Automatic changelog generation for PR #8948 [ci skip] --- html/changelogs/AutoChangeLog-pr-8948.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-8948.yml diff --git a/html/changelogs/AutoChangeLog-pr-8948.yml b/html/changelogs/AutoChangeLog-pr-8948.yml new file mode 100644 index 0000000000..af3d28eb34 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-8948.yml @@ -0,0 +1,9 @@ +author: "Ghommie" +delete-after: True +changes: + - code_imp: "Cleaned up the absolute state of the arousal module." + - refactor: "refactored exhibitionism into a quirk." + - tweak: "arousal states won't persist after death." + - bugfix: "Fixes testicles size adjective thing." + - bugfix: "undergarments toggling now works instead of just making underwear disappear and not come back." + - tweak: "The \"Always visible\" genitals setting will now display them above clothes." From ab92421e20fc3ebfae87a3a1b9bf94f51f90553e Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Thu, 31 Oct 2019 19:27:41 -0500 Subject: [PATCH 40/58] Automatic changelog generation for PR #9677 [ci skip] --- html/changelogs/AutoChangeLog-pr-9677.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-9677.yml diff --git a/html/changelogs/AutoChangeLog-pr-9677.yml b/html/changelogs/AutoChangeLog-pr-9677.yml new file mode 100644 index 0000000000..8b8608ff29 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9677.yml @@ -0,0 +1,4 @@ +author: "Putnam3145" +delete-after: True +changes: + - tweak: "Made the clone scanner lock while it's scanning." From 9506a78429d059c7bb7db55d4399cedd78fb9dd6 Mon Sep 17 00:00:00 2001 From: Putnam Date: Fri, 1 Nov 2019 18:46:31 -0700 Subject: [PATCH 41/58] whoops replaced this var with a simpler check --- code/datums/diseases/advance/symptoms/heal.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/datums/diseases/advance/symptoms/heal.dm b/code/datums/diseases/advance/symptoms/heal.dm index 9b81868958..8b205db756 100644 --- a/code/datums/diseases/advance/symptoms/heal.dm +++ b/code/datums/diseases/advance/symptoms/heal.dm @@ -368,7 +368,6 @@ level = 8 passive_message = "You feel an odd attraction to plasma." var/temp_rate = 1 - var/heals_slimes = FALSE threshold_desc = "Transmission 6: Increases temperature adjustment rate and heals toxin lovers.
\ Stage Speed 7: Increases healing speed." From 874cdfefb89b2e4b82c1a3f90f594c43ecbccd48 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Sat, 2 Nov 2019 14:03:14 +0100 Subject: [PATCH 42/58] fixing storage implant transplant. --- code/game/objects/items/implants/implant_storage.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/game/objects/items/implants/implant_storage.dm b/code/game/objects/items/implants/implant_storage.dm index 1f44b5318e..bbe63cb7f5 100644 --- a/code/game/objects/items/implants/implant_storage.dm +++ b/code/game/objects/items/implants/implant_storage.dm @@ -12,7 +12,7 @@ /obj/item/implant/storage/removed(source, silent = FALSE, special = 0) if(!special) - qdel(pocket) + QDEL_NULL(pocket) else pocket?.moveToNullspace() return ..() @@ -29,7 +29,7 @@ return FALSE . = ..() if(.) - if(pocket) + if(!QDELETED(pocket)) pocket.forceMove(target) else pocket = new(target) From 91625b6e6068ef17b0ad2433042e136ed546b05a Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Sat, 2 Nov 2019 14:15:31 +0100 Subject: [PATCH 43/58] item/doMove() calling dropped() callign qdel(src) because of DROPDEL. --- code/game/objects/items/implants/implant_storage.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/game/objects/items/implants/implant_storage.dm b/code/game/objects/items/implants/implant_storage.dm index bbe63cb7f5..1dfc0b4580 100644 --- a/code/game/objects/items/implants/implant_storage.dm +++ b/code/game/objects/items/implants/implant_storage.dm @@ -41,7 +41,6 @@ desc = "A tiny yet spacious pocket, usually found implanted inside sneaky syndicate agents and nowhere else." component_type = /datum/component/storage/concrete/implant resistance_flags = INDESTRUCTIBLE //A bomb! - item_flags = DROPDEL /obj/item/implanter/storage name = "implanter (storage)" From 1bf10c0435507ac1a9d5b440e23f780fd508d9cd Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Sat, 2 Nov 2019 15:50:54 +0100 Subject: [PATCH 44/58] Improving Jacqueen's teleportation area selection. --- code/modules/holiday/halloween/jacqueen.dm | 54 +++++++++++----------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm index ed9254c295..0180f083a3 100644 --- a/code/modules/holiday/halloween/jacqueen.dm +++ b/code/modules/holiday/halloween/jacqueen.dm @@ -95,45 +95,45 @@ last_poof = world.realtime var/datum/reagents/R = new/datum/reagents(100)//Hey, just in case. var/datum/effect_system/smoke_spread/chem/s = new() - R.add_reagent("secretcatchem", (10)) + R.add_reagent("secretcatchem", 10) s.set_up(R, 0, loc) s.start() visible_message("[src] disappears in a puff of smoke!") canmove = TRUE health = 25 - var/hp_list = list() - for(var/obj/machinery/holopad/hp in world) - hp_list += hp + var/list/areas = list() + for(var/A in GLOB.teleportlocs) + if(findtextEx(A, "AI") + continue + areas += GLOB.teleportlocs[A] - var/nono_areas = list("AI ") + //Try to go to populated areas + var/list/pop_areas = list() + for(var/M in GLOB.player_list) + var/area/A = get_area(M) + pop_areas += A - for(var/i = 0, i <= 6, i+=1) //Attempts a jump 6 times. - var/obj/machinery/holopad/hp = pick(hp_list) - if(forceMove(pick(hp.loc))) + var/list/cool_places = uniquemergelist(areas, pop_areas) - var/jacq_please_no = FALSE - for(var/no_area in nono_areas) - var/turf/L1 = hp.loc - if(!L1) //Incase the area isn't a turf (i.e. in a locker) - continue - var/area/L2 = L1.loc - if(L2) - if(findtext(L2.name, no_area)) - jacq_please_no = TRUE + if(!cool_places) + cool_places = areas - if(jacq_please_no) - i-=1 + for(var/i in 1 to 6) //Attempts a jump up to 6 times. + var/area/A = pick(cool_places) + var/list/L = list() + + if(i != 6) // We need to teleport away, no matter what. + for(var/turf/T in get_area_turfs(A.type)) + if(!is_blocked_turf(T)) + L += T + if(!L.len) + cool_places -= A continue - //Try to go to populated areas - var/list/seen = viewers(8, get_turf(src)) - for(var/victim in seen) - if(ishuman(victim)) - if(z == cached_z) - return TRUE - - + if(!do_teleport(src, pick(L), channel = TELEPORT_CHANNEL_MAGIC)) + return TRUE + cool_places -= A return FALSE /mob/living/simple_animal/jacq/proc/gender_check(mob/living/carbon/C) From a949f84557e922d26b9db802528f80de2e3171f0 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Sat, 2 Nov 2019 16:00:48 +0100 Subject: [PATCH 45/58] missing bits. --- code/modules/holiday/halloween/jacqueen.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm index 0180f083a3..c77de912f9 100644 --- a/code/modules/holiday/halloween/jacqueen.dm +++ b/code/modules/holiday/halloween/jacqueen.dm @@ -104,7 +104,7 @@ var/list/areas = list() for(var/A in GLOB.teleportlocs) - if(findtextEx(A, "AI") + if(findtextEx(A, "AI")) continue areas += GLOB.teleportlocs[A] @@ -116,7 +116,7 @@ var/list/cool_places = uniquemergelist(areas, pop_areas) - if(!cool_places) + if(!cool_places.len) cool_places = areas for(var/i in 1 to 6) //Attempts a jump up to 6 times. From 3193e3ce20544f22546db9f3b27e0538f4d34aed Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Sat, 2 Nov 2019 16:12:37 +0100 Subject: [PATCH 46/58] fix. --- code/modules/holiday/halloween/jacqueen.dm | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm index c77de912f9..4b5874d3e5 100644 --- a/code/modules/holiday/halloween/jacqueen.dm +++ b/code/modules/holiday/halloween/jacqueen.dm @@ -121,15 +121,16 @@ for(var/i in 1 to 6) //Attempts a jump up to 6 times. var/area/A = pick(cool_places) - var/list/L = list() + var/list/area_turfs = list(get_area_turfs(A.type)) if(i != 6) // We need to teleport away, no matter what. - for(var/turf/T in get_area_turfs(A.type)) + for(var/t in area_turfs) + var/turf/T = t if(!is_blocked_turf(T)) - L += T - if(!L.len) - cool_places -= A - continue + L -= T + if(!L.len) + cool_places -= A + continue if(!do_teleport(src, pick(L), channel = TELEPORT_CHANNEL_MAGIC)) return TRUE From 50fc1004bace7d480599f9d3a38a148baa676a91 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Sat, 2 Nov 2019 16:46:02 +0100 Subject: [PATCH 47/58] Actually holopads, so they won't end up in maintenance... --- code/game/machinery/hologram.dm | 11 +++---- code/modules/holiday/halloween/jacqueen.dm | 34 +++++++--------------- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/code/game/machinery/hologram.dm b/code/game/machinery/hologram.dm index 893f36acb3..79aef8ba7b 100644 --- a/code/game/machinery/hologram.dm +++ b/code/game/machinery/hologram.dm @@ -24,6 +24,8 @@ Possible to do for anyone motivated enough: * Holopad */ +GLOBAL_LIST_EMPTY(network_holopads) + #define HOLOPAD_PASSIVE_POWER_USAGE 1 #define HOLOGRAM_POWER_USAGE 2 @@ -55,7 +57,6 @@ Possible to do for anyone motivated enough: var/record_user //user that inititiated the recording var/obj/effect/overlay/holo_pad_hologram/replay_holo //replay hologram var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging - var/static/list/holopads = list() var/obj/effect/overlay/holoray/ray var/ringing = FALSE var/offset = FALSE @@ -96,7 +97,7 @@ Possible to do for anyone motivated enough: /obj/machinery/holopad/Initialize() . = ..() if(on_network) - holopads += src + GLOB.network_holopads += src /obj/machinery/holopad/Destroy() if(outgoing_call) @@ -116,7 +117,7 @@ Possible to do for anyone motivated enough: QDEL_NULL(disk) - holopads -= src + GLOB.network_holopads -= src return ..() /obj/machinery/holopad/power_change() @@ -260,7 +261,7 @@ Possible to do for anyone motivated enough: temp += "
Main Menu" if(usr.loc == loc) var/list/callnames = list() - for(var/I in holopads) + for(var/I in GLOB.network_holopads) var/area/A = get_area(I) if(A) LAZYADD(callnames[A], I) @@ -474,7 +475,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/ var/obj/effect/overlay/holo_pad_hologram/h = masters[holo_owner] if(!h || h.HC) //Holocalls can't change source. return FALSE - for(var/pad in holopads) + for(var/pad in GLOB.network_holopads) var/obj/machinery/holopad/another = pad if(another == src) continue diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm index 4b5874d3e5..3ad4149700 100644 --- a/code/modules/holiday/halloween/jacqueen.dm +++ b/code/modules/holiday/halloween/jacqueen.dm @@ -102,39 +102,27 @@ canmove = TRUE health = 25 - var/list/areas = list() - for(var/A in GLOB.teleportlocs) - if(findtextEx(A, "AI")) - continue - areas += GLOB.teleportlocs[A] - //Try to go to populated areas var/list/pop_areas = list() for(var/M in GLOB.player_list) var/area/A = get_area(M) pop_areas += A - var/list/cool_places = uniquemergelist(areas, pop_areas) + var/list/targets = list() + for(var/H in GLOB.network_holopads) + var/area/A = get_area(H) + if(findtextEx(A, "AI") || !(A in pop_areas) || !is_station_level(H)) + continue + targets += H - if(!cool_places.len) - cool_places = areas + if(!targets) + targets = GLOB.generic_event_spawns for(var/i in 1 to 6) //Attempts a jump up to 6 times. - var/area/A = pick(cool_places) - var/list/area_turfs = list(get_area_turfs(A.type)) - - if(i != 6) // We need to teleport away, no matter what. - for(var/t in area_turfs) - var/turf/T = t - if(!is_blocked_turf(T)) - L -= T - if(!L.len) - cool_places -= A - continue - - if(!do_teleport(src, pick(L), channel = TELEPORT_CHANNEL_MAGIC)) + var/atom/A = pick(targets) + if(!do_teleport(src, A, channel = TELEPORT_CHANNEL_MAGIC)) return TRUE - cool_places -= A + targets -= A return FALSE /mob/living/simple_animal/jacq/proc/gender_check(mob/living/carbon/C) From f4587b4260bebfb45350dff74a102b9dcd93a072 Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Sat, 2 Nov 2019 16:47:25 +0100 Subject: [PATCH 48/58] This is very unprofessional. Yet I'm no google architect. --- code/modules/holiday/halloween/jacqueen.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm index 3ad4149700..a8111a3e3d 100644 --- a/code/modules/holiday/halloween/jacqueen.dm +++ b/code/modules/holiday/halloween/jacqueen.dm @@ -120,7 +120,7 @@ for(var/i in 1 to 6) //Attempts a jump up to 6 times. var/atom/A = pick(targets) - if(!do_teleport(src, A, channel = TELEPORT_CHANNEL_MAGIC)) + if(do_teleport(src, A, channel = TELEPORT_CHANNEL_MAGIC)) return TRUE targets -= A return FALSE From 2653a2965dc630cb76c5a3e1d30fa3aa0eb4aa1d Mon Sep 17 00:00:00 2001 From: Ghommie <42542238+Ghommie@users.noreply.github.com> Date: Sat, 2 Nov 2019 20:46:33 +0100 Subject: [PATCH 49/58] How about we only check the living? --- code/modules/holiday/halloween/jacqueen.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/modules/holiday/halloween/jacqueen.dm b/code/modules/holiday/halloween/jacqueen.dm index a8111a3e3d..f67c099309 100644 --- a/code/modules/holiday/halloween/jacqueen.dm +++ b/code/modules/holiday/halloween/jacqueen.dm @@ -104,8 +104,8 @@ //Try to go to populated areas var/list/pop_areas = list() - for(var/M in GLOB.player_list) - var/area/A = get_area(M) + for(var/mob/living/L in GLOB.player_list) + var/area/A = get_area(L) pop_areas += A var/list/targets = list() From b12d7842d60b21b2e8d6575f35f3cea4ea0d8613 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sun, 3 Nov 2019 07:11:23 -0600 Subject: [PATCH 50/58] Automatic changelog generation for PR #9686 [ci skip] --- html/changelogs/AutoChangeLog-pr-9686.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-9686.yml diff --git a/html/changelogs/AutoChangeLog-pr-9686.yml b/html/changelogs/AutoChangeLog-pr-9686.yml new file mode 100644 index 0000000000..18e411c3dc --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9686.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed storage implant transplant." From 23b6881453b77762a9df8e843cde55fddb74edb1 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sun, 3 Nov 2019 07:14:15 -0600 Subject: [PATCH 51/58] Automatic changelog generation for PR #9679 [ci skip] --- html/changelogs/AutoChangeLog-pr-9679.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-9679.yml diff --git a/html/changelogs/AutoChangeLog-pr-9679.yml b/html/changelogs/AutoChangeLog-pr-9679.yml new file mode 100644 index 0000000000..b2b3a718c4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9679.yml @@ -0,0 +1,5 @@ +author: "ninjanomnom and WhoneedSpacee" +delete-after: True +changes: + - rscadd: "Some rpg affixes now have special effects" + - rscadd: "New RPGLoot modifiers: Vampirism which heals you when you attack, Pyromantic which sets things you hit on fire. Shrapnel which causes projectiles fired from a gun to fire projectiles in a radius when they hit something. Finally, Summoning which summons mobs that sometimes aid you in combat." From 5d2678a2b615ef2a59c7c0a06c8343fb62c76caa Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sun, 3 Nov 2019 07:14:57 -0600 Subject: [PATCH 52/58] Automatic changelog generation for PR #9675 [ci skip] --- html/changelogs/AutoChangeLog-pr-9675.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-9675.yml diff --git a/html/changelogs/AutoChangeLog-pr-9675.yml b/html/changelogs/AutoChangeLog-pr-9675.yml new file mode 100644 index 0000000000..35d9110f7b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9675.yml @@ -0,0 +1,4 @@ +author: "PersianXerxes" +delete-after: True +changes: + - tweak: "Relocates cult catwalks outside the Reebe dressing room." From 6873f0b0cbe49ee1f643f73fc61a732c130ad272 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sun, 3 Nov 2019 07:15:19 -0600 Subject: [PATCH 53/58] Automatic changelog generation for PR #9674 [ci skip] --- html/changelogs/AutoChangeLog-pr-9674.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-9674.yml diff --git a/html/changelogs/AutoChangeLog-pr-9674.yml b/html/changelogs/AutoChangeLog-pr-9674.yml new file mode 100644 index 0000000000..9ca51c9b0e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9674.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - imageadd: "Updated ratvarian computer sprites." From e8c7afb69c3904221964460fff483c5749bed849 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sun, 3 Nov 2019 07:18:03 -0600 Subject: [PATCH 54/58] Automatic changelog generation for PR #9668 [ci skip] --- html/changelogs/AutoChangeLog-pr-9668.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-9668.yml diff --git a/html/changelogs/AutoChangeLog-pr-9668.yml b/html/changelogs/AutoChangeLog-pr-9668.yml new file mode 100644 index 0000000000..b892f7c3ea --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9668.yml @@ -0,0 +1,5 @@ +author: "Putnam3145" +delete-after: True +changes: + - balance: "Made starlight condensation not kill slime people." + - balance: "Added not-killing-slime-people to the transmission threshold of plasma fixation and radioactive resonance." From a2c1881990f0dc3cba2bcbddf997a6e6d1f27da8 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sun, 3 Nov 2019 07:20:08 -0600 Subject: [PATCH 55/58] Automatic changelog generation for PR #9659 [ci skip] --- html/changelogs/AutoChangeLog-pr-9659.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-9659.yml diff --git a/html/changelogs/AutoChangeLog-pr-9659.yml b/html/changelogs/AutoChangeLog-pr-9659.yml new file mode 100644 index 0000000000..2590aec672 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9659.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Buffed the deep space familiar gorilla against runtimes." From 75914dd0856b6c8df38c5da27e6f0d1b1e75f0db Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sun, 3 Nov 2019 07:20:32 -0600 Subject: [PATCH 56/58] Automatic changelog generation for PR #9658 [ci skip] --- html/changelogs/AutoChangeLog-pr-9658.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-9658.yml diff --git a/html/changelogs/AutoChangeLog-pr-9658.yml b/html/changelogs/AutoChangeLog-pr-9658.yml new file mode 100644 index 0000000000..199f847c4e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9658.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Fixed dogborg sleepers. Just don't tell me what is exactly fixed, cause I don't want to find out." From 193e54c6a81734ff37dd343bd18acc93797ffc03 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sun, 3 Nov 2019 07:21:26 -0600 Subject: [PATCH 57/58] Automatic changelog generation for PR #9654 [ci skip] --- html/changelogs/AutoChangeLog-pr-9654.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-9654.yml diff --git a/html/changelogs/AutoChangeLog-pr-9654.yml b/html/changelogs/AutoChangeLog-pr-9654.yml new file mode 100644 index 0000000000..420697aec5 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9654.yml @@ -0,0 +1,4 @@ +author: "Putnam3145" +delete-after: True +changes: + - config: "Added dynamic midround/latejoin antag injection to the config." From 4e8c8ad335bdfd4118dfaac5f4708f1f8190b9a4 Mon Sep 17 00:00:00 2001 From: CitadelStationBot Date: Sun, 3 Nov 2019 07:24:56 -0600 Subject: [PATCH 58/58] Automatic changelog generation for PR #9687 [ci skip] --- html/changelogs/AutoChangeLog-pr-9687.yml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 html/changelogs/AutoChangeLog-pr-9687.yml diff --git a/html/changelogs/AutoChangeLog-pr-9687.yml b/html/changelogs/AutoChangeLog-pr-9687.yml new file mode 100644 index 0000000000..3bc1644806 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-9687.yml @@ -0,0 +1,4 @@ +author: "Ghommie" +delete-after: True +changes: + - bugfix: "Refactored how Jacqueen teleportation destination is selected, preventing them from teleporting on off-station holopads."