diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 98153f06a4..7d391b2147 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -8,7 +8,7 @@ //organ defines #define COCK_SIZE_MIN 1 -#define COCK_SIZE_MAX 24 +#define COCK_SIZE_MAX 20 #define COCK_GIRTH_RATIO_MAX 1.25 #define COCK_GIRTH_RATIO_DEF 0.75 @@ -18,18 +18,16 @@ #define KNOT_GIRTH_RATIO_DEF 2.1 #define KNOT_GIRTH_RATIO_MIN 1.25 -#define BALLS_VOLUME_BASE 50 +#define BALLS_VOLUME_BASE 25 #define BALLS_VOLUME_MULT 1 #define BALLS_SIZE_MIN 1 -#define BALLS_SIZE_SMALL 2 -#define BALLS_SIZE_NORMAL 3 -#define BALLS_SIZE_BIG 4 -#define BALLS_SIZE_BIGGER 5 -#define BALLS_SIZE_BIGGEST 6 +#define BALLS_SIZE_DEF 3 #define BALLS_SIZE_MAX 7 +#define BALLS_SACK_SIZE_MIN 1 #define BALLS_SACK_SIZE_DEF 8 +#define BALLS_SACK_SIZE_MAX 40 #define CUM_RATE 5 #define CUM_RATE_MULT 1 @@ -60,6 +58,7 @@ #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 diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 535e7a1010..dab4471330 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -31,19 +31,25 @@ #define FRIDAY_13TH "Friday the 13th" //Human Overlays Indexes///////// -#define MUTATIONS_LAYER 26 //mutations. Tk headglows, cold resistance glow, etc -#define BODY_BEHIND_LAYER 25 //certain mutantrace features (tail when looking south) that must appear behind the body parts -#define BODYPARTS_LAYER 24 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag -#define BODY_ADJ_LAYER 23 //certain mutantrace features (snout, body markings) that must appear above the body parts -#define BODY_LAYER 22 //underwear, undershirts, socks, eyes, lips(makeup) -#define FRONT_MUTATIONS_LAYER 21 //mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes) -#define DAMAGE_LAYER 20 //damage indicators (cuts and burns) -#define UNIFORM_LAYER 19 -#define ID_LAYER 18 -#define SHOES_LAYER 17 -#define GLOVES_LAYER 16 -#define EARS_LAYER 15 -#define SUIT_LAYER 14 +//citadel code +#define MUTATIONS_LAYER 31 //mutations. Tk headglows, cold resistance glow, etc +#define BODY_BEHIND_LAYER 30 //certain mutantrace features (tail when looking south) that must appear behind the body parts +#define GENITALS_BEHIND_LAYER 29 +#define BODYPARTS_LAYER 28 //Initially "AUGMENTS", this was repurposed to be a catch-all bodyparts flag +#define BODY_ADJ_LAYER 27 //certain mutantrace features (snout, body markings) that must appear above the body parts +#define GENITALS_ADJ_LAYER 26 +#define BODY_LAYER 25 //underwear, undershirts, socks, eyes, lips(makeup) +#define GENITALS_FRONT_LAYER 24 +#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 SHOES_LAYER 19 +#define GLOVES_LAYER 18 +#define EARS_LAYER 17 +#define SUIT_LAYER 16 +#define BODY_TAUR_LAYER 15 +#define GENITALS_FRONT_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 @@ -57,7 +63,7 @@ #define HANDS_LAYER 3 #define BODY_FRONT_LAYER 2 #define FIRE_LAYER 1 //If you're on fire -#define TOTAL_LAYERS 26 //KEEP THIS UP-TO-DATE OR SHIT WILL BREAK ;_; +#define TOTAL_LAYERS 31 //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/code/__DEFINES/preferences.dm b/code/__DEFINES/preferences.dm index 63c051061d..f26b750492 100644 --- a/code/__DEFINES/preferences.dm +++ b/code/__DEFINES/preferences.dm @@ -28,8 +28,9 @@ #define CHAT_GHOSTWHISPER 128 #define CHAT_GHOSTPDA 256 #define CHAT_GHOSTRADIO 512 +#define CHAT_LOOC 1024 -#define TOGGLES_DEFAULT_CHAT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_PULLR|CHAT_GHOSTWHISPER|CHAT_GHOSTPDA|CHAT_GHOSTRADIO) +#define TOGGLES_DEFAULT_CHAT (CHAT_OOC|CHAT_DEAD|CHAT_GHOSTEARS|CHAT_GHOSTSIGHT|CHAT_PRAYER|CHAT_RADIO|CHAT_PULLR|CHAT_GHOSTWHISPER|CHAT_GHOSTPDA|CHAT_GHOSTRADIO|CHAT_LOOC) #define PARALLAX_INSANE -1 //for show offs #define PARALLAX_HIGH 0 //default. diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm index f0c42311b6..79429cff2c 100644 --- a/code/__HELPERS/global_lists.dm +++ b/code/__HELPERS/global_lists.dm @@ -37,6 +37,7 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, wings_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/wings_open, wings_open_list) + //citadel code //mammal bodyparts (fucking furries) init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_body_markings, mam_body_markings_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/mam_tails, mam_tails_list) @@ -52,6 +53,9 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_head, xeno_head_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_tail, xeno_tail_list) init_sprite_accessory_subtypes(/datum/sprite_accessory/xeno_dorsal, xeno_dorsal_list) + //genitals + init_sprite_accessory_subtypes(/datum/sprite_accessory/penis, cock_shapes_list) + init_sprite_accessory_subtypes(/datum/sprite_accessory/breasts, breasts_size_list) //Species for(var/spath in subtypesof(/datum/species)) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index b57d5b2548..02dc12ddd9 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -47,7 +47,7 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/socks, socks_list) return pick(socks_list) -/proc/random_features() +/proc/random_features(penis=0,balls=0,vagina=0,womb=0,breasts=0) if(!tails_list_human.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/human, tails_list_human) if(!tails_list_lizard.len) @@ -68,9 +68,87 @@ init_sprite_accessory_subtypes(/datum/sprite_accessory/body_markings, body_markings_list) if(!wings_list.len) init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, wings_list) + if(!cock_shapes_list.len) + init_sprite_accessory_subtypes(/datum/sprite_accessory/penis, cock_shapes_list) + if(ishuman(src)) + var/mob/living/carbon/human/H = src + if(H.gender == MALE) + penis = 1 + balls = 1 + vagina = 0 + womb = 0 + breasts = 0 + if(H.gender == FEMALE) + penis = 0 + balls = 0 + vagina = 1 + womb = 1 + breasts = 1 - //For now we will always return none for tail_human and ears. - return(list("mcolor" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), "tail_lizard" = pick(tails_list_lizard), "tail_human" = "None", "wings" = "None", "snout" = pick(snouts_list), "horns" = pick(horns_list), "ears" = "None", "frills" = pick(frills_list), "spines" = pick(spines_list), "body_markings" = pick(body_markings_list), "legs" = "Normal Legs")) + return(list( + "mcolor" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), + "mcolor2" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), + "mcolor3" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), + "tail_lizard" = pick(tails_list_lizard), + "tail_human" = "None", + "wings" = "None", + "snout" = pick(snouts_list), + "horns" = pick(horns_list), + "ears" = "None", + "frills" = pick(frills_list), + "spines" = pick(spines_list), + "body_markings" = pick(body_markings_list), + "legs" = "Normal Legs", + "taur" = "None", + "mam_body_markings" = "None", + "mam_ears" = "None", + "mam_tail" = "None", + "mam_tail_animated" = "None", + "xenodorsal" = "None", + "xenohead" = "None", + "xenotail" = "None", + "exhibitionist" = FALSE, + "has_cock" = FALSE, + "cock_shape" = "human", + "cock_length" = 6, + "cock_girth_ratio" = COCK_GIRTH_RATIO_DEF, + "cock_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), + "has_sheath" = FALSE, + "sheath_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), + "has_balls" = FALSE, + "balls_internal" = FALSE, + "balls_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), + "balls_amount" = 2, + "balls_sack_size" = BALLS_SACK_SIZE_DEF, + "balls_size" = BALLS_SIZE_DEF, + "balls_cum_rate" = CUM_RATE, + "balls_cum_mult" = CUM_RATE_MULT, + "balls_efficiency" = CUM_EFFICIENCY, + "balls_fluid" = "semen", + "has_ovi" = FALSE, + "ovi_shape" = "knotted", + "ovi_length" = 6, + "ovi_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), + "has_eggsack" = FALSE, + "eggsack_internal" = TRUE, + "eggsack_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), + "eggsack_size" = BALLS_SACK_SIZE_DEF, + "eggsack_egg_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), + "eggsack_egg_size" = EGG_GIRTH_DEF, + "has_breasts" = FALSE, + "breasts_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), + "breasts_size" = pick(breasts_size_list), + "breasts_fluid" = "milk", + "has_vag" = FALSE, + "vag_color" = pick("FFFFFF","7F7F7F", "7FFF7F", "7F7FFF", "FF7F7F", "7FFFFF", "FF7FFF", "FFFF7F"), + "vag_clits" = 1, + "vag_clit_diam" = 0.25, + "vag_clit_len" = 0.25, + "has_womb" = FALSE, + "womb_cum_rate" = CUM_RATE, + "womb_cum_mult" = CUM_RATE_MULT, + "womb_efficiency" = CUM_EFFICIENCY, + "womb_fluid" = "femcum")) /proc/random_hair_style(gender) switch(gender) diff --git a/code/_globalvars/configuration.dm b/code/_globalvars/configuration.dm index cb3e38a92f..075289e320 100644 --- a/code/_globalvars/configuration.dm +++ b/code/_globalvars/configuration.dm @@ -9,6 +9,9 @@ var/changelog_hash = "" var/ooc_allowed = 1 // used with admin verbs to disable ooc - not a config option apparently var/dooc_allowed = 1 +//citadel code +var/looc_allowed = 1 +var/dlooc_allowed = 1 var/abandon_allowed = 1 var/enter_allowed = 1 var/guests_allowed = 1 diff --git a/code/citadel/_cit_helpers.dm b/code/citadel/_cit_helpers.dm new file mode 100644 index 0000000000..a48158d42c --- /dev/null +++ b/code/citadel/_cit_helpers.dm @@ -0,0 +1,163 @@ +//THIS FILE CONTAINS CONSTANTS, PROCS, DEFINES, AND OTHER THINGS// +//////////////////////////////////////////////////////////////////// +/mob/proc/setClickCooldown(var/timeout) + next_move = max(world.time + timeout, next_move) + +/proc/get_matrix_largest() + var/matrix/mtrx=new() + return mtrx.Scale(2) +/proc/get_matrix_large() + var/matrix/mtrx=new() + return mtrx.Scale(1.5) +/proc/get_matrix_norm() + var/matrix/mtrx=new() + return mtrx +/proc/get_matrix_small() + var/matrix/mtrx=new() + return mtrx.Scale(0.8) +/proc/get_matrix_smallest() + var/matrix/mtrx=new() + return mtrx.Scale(0.65) + +proc/get_racelist(var/mob/user)//This proc returns a list of species that 'user' has available to them. It searches the list of ckeys attached to the 'whitelist' var for a species and also checks if they're an admin. + for(var/spath in subtypesof(/datum/species)) + var/datum/species/S = new spath() + var/list/wlist = S.whitelist + if(S.whitelisted && (wlist.Find(user.ckey) || wlist.Find(user.key) || user.client.holder)) //If your ckey is on the species whitelist or you're an admin: + whitelisted_species_list[S.id] = S.type //Add the species to their available species list. + else if(!S.whitelisted && S.roundstart) //Normal roundstart species will be handled here. + whitelisted_species_list[S.id] = S.type + + return whitelisted_species_list + + //Mammal Species +var/global/list/mam_body_markings_list = list() +var/global/list/mam_ears_list = list() +var/global/list/mam_tails_list = list() +var/global/list/mam_tails_animated_list = list() +var/global/list/taur_list = list() + + //Exotic Species +var/global/list/exotic_tails_list = list() +var/global/list/exotic_tails_animated_list = list() +var/global/list/exotic_ears_list = list() +var/global/list/exotic_head_list = list() +var/global/list/exotic_back_list = list() + + //Xenomorph Species +var/global/list/xeno_head_list = list() //I forgot the ' = list()' part for the longest time and couldn't figure out what was wrong. *facepalm +var/global/list/xeno_tail_list = list() +var/global/list/xeno_dorsal_list = list() + + + //Genitals and Arousal Lists +var/global/list/cock_shapes_list = list()//global_lists.dm for the list initializations +var/global/list/breasts_size_list = list() +var/global/list/cum_into_containers_list = list(/obj/item/weapon/reagent_containers/food/snacks/pie) +var/global/list/dick_nouns = list("dick","cock","member","shaft") +var/global/list/cum_id_list = list("semen") +var/global/list/milk_id_list = list("milk") +//mentor stuff +var/list/mentors = list() + +/client/proc/reload_mentors() + set name = "Reload Mentors" + set category = "Admin" + if(!src.holder) return + message_admins("[key_name_admin(usr)] manually reloaded mentors") + +//Flavor Text +/mob/living/carbon/human/verb/set_flavor() + set name = "Set Flavor Text" + set desc = "Sets an extended description of your character's features." + set category = "IC" + + flavor_text = copytext(sanitize(input(usr, "Please enter your new flavor text.", "Flavor text", null) as text), 1) + +//LOOC toggles +/client/verb/listen_looc() + set name = "Show/Hide LOOC" + set category = "Preferences" + set desc = "Toggles seeing LocalOutOfCharacter chat" + prefs.chat_toggles ^= CHAT_LOOC + prefs.save_preferences() + src << "You will [(prefs.chat_toggles & CHAT_LOOC) ? "now" : "no longer"] see messages on the LOOC channel." + feedback_add_details("admin_verb","TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/datum/admins/proc/togglelooc() + set category = "Server" + set desc="Fukken metagamers" + set name="Toggle LOOC" + toggle_looc() + log_admin("[key_name(usr)] toggled LOOC.") + message_admins("[key_name_admin(usr)] toggled LOOC.") + feedback_add_details("admin_verb","TLOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! + +/proc/toggle_looc(toggle = null) + if(toggle != null) //if we're specifically en/disabling ooc + if(toggle != looc_allowed) + looc_allowed = toggle + else + return + else //otherwise just toggle it + looc_allowed = !looc_allowed + world << "The LOOC channel has been globally [looc_allowed ? "enabled" : "disabled"]." + +/datum/admins/proc/toggleloocdead() + set category = "Server" + set desc="Toggle dis bitch" + set name="Toggle Dead LOOC" + dlooc_allowed = !( dlooc_allowed ) + + log_admin("[key_name(usr)] toggled OOC.") + message_admins("[key_name_admin(usr)] toggled Dead OOC.") + feedback_add_details("admin_verb","TDLOOC") //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 1 + return 0 + +/mob/living/carbon/proc/has_balls() + if(getorganslot("balls")) + if(istype(getorganslot("balls"), /obj/item/organ/genital/testicles)) + return 1 + return 0 + +/mob/living/carbon/proc/has_vagina() + if(getorganslot("vagina")) + return 1 + return 0 + +/mob/living/carbon/proc/has_breasts() + if(getorganslot("breasts")) + return 1 + return 0 + +/mob/living/carbon/proc/has_ovipositor() + if(getorganslot("penis"))//shared slot + if(istype(getorganslot("penis"), /obj/item/organ/genital/ovipositor)) + return 1 + return 0 + +/mob/living/carbon/human/proc/has_eggsack() + if(getorganslot("balls")) + if(istype(getorganslot("balls"), /obj/item/organ/genital/eggsack)) + return 1 + return 0 + +/mob/living/carbon/human/proc/is_bodypart_exposed(bodypart) + +/mob/living/carbon/proc/is_groin_exposed() + for(var/obj/item/I in get_equipped_items()) + if(I.body_parts_covered & GROIN) + return 0 + return 1 + +/mob/living/carbon/proc/is_chest_exposed() + for(var/obj/item/I in get_equipped_items()) + if(I.body_parts_covered & CHEST) + return 0 + return 1 \ No newline at end of file diff --git a/code/citadel/_helpers.dm b/code/citadel/_helpers.dm deleted file mode 100644 index c0b0c0769b..0000000000 --- a/code/citadel/_helpers.dm +++ /dev/null @@ -1,68 +0,0 @@ -//THIS FILE CONTAINS CONSTANTS, PROCS, DEFINES, AND OTHER THINGS// -//////////////////////////////////////////////////////////////////// -/mob/proc/setClickCooldown(var/timeout) - next_move = max(world.time + timeout, next_move) - -/proc/get_matrix_largest() - var/matrix/mtrx=new() - return mtrx.Scale(2) -/proc/get_matrix_large() - var/matrix/mtrx=new() - return mtrx.Scale(1.5) -/proc/get_matrix_norm() - var/matrix/mtrx=new() - return mtrx -/proc/get_matrix_small() - var/matrix/mtrx=new() - return mtrx.Scale(0.8) -/proc/get_matrix_smallest() - var/matrix/mtrx=new() - return mtrx.Scale(0.65) - -proc/get_racelist(var/mob/user)//This proc returns a list of species that 'user' has available to them. It searches the list of ckeys attached to the 'whitelist' var for a species and also checks if they're an admin. - for(var/spath in subtypesof(/datum/species)) - var/datum/species/S = new spath() - var/list/wlist = S.whitelist - if(S.whitelisted && (wlist.Find(user.ckey) || wlist.Find(user.key) || user.client.holder)) //If your ckey is on the species whitelist or you're an admin: - whitelisted_species_list[S.id] = S.type //Add the species to their available species list. - else if(!S.whitelisted && S.roundstart) //Normal roundstart species will be handled here. - whitelisted_species_list[S.id] = S.type - - return whitelisted_species_list - - //Mammal Species -var/global/list/mam_body_markings_list = list() -var/global/list/mam_ears_list = list() -var/global/list/mam_tails_list = list() -var/global/list/mam_tails_animated_list = list() -var/global/list/taur_list = list() - - //Exotic Species -var/global/list/exotic_tails_list = list() -var/global/list/exotic_tails_animated_list = list() -var/global/list/exotic_ears_list = list() -var/global/list/exotic_head_list = list() -var/global/list/exotic_back_list = list() - - //Xenomorph Species -var/global/list/xeno_head_list = list() //I forgot the ' = list()' part for the longest time and couldn't figure out what was wrong. *facepalm -var/global/list/xeno_tail_list = list() -var/global/list/xeno_dorsal_list = list() - - -//mentor stuff - -var/list/mentors = list() - -/client/proc/reload_mentors() - set name = "Reload Mentors" - set category = "Admin" - if(!src.holder) return - message_admins("[key_name_admin(usr)] manually reloaded mentors") - -/mob/living/carbon/human/verb/set_flavor() - set name = "Set Flavor Text" - set desc = "Sets an extended description of your character's features." - set category = "IC" - - flavor_text = copytext(sanitize(input(usr, "Please enter your new flavor text.", "Flavor text", null) as text), 1) diff --git a/code/citadel/cit_arousal.dm b/code/citadel/cit_arousal.dm index ff77bb06e0..d4aa1716b3 100644 --- a/code/citadel/cit_arousal.dm +++ b/code/citadel/cit_arousal.dm @@ -6,33 +6,56 @@ var/arousal_rate = 1 //The base rate that arousal will increase in this mob. var/arousal_loss_rate = 1 //How easily arousal can be relieved for this mob. var/canbearoused = FALSE //Mob-level disabler for arousal. Starts off and can be enabled as features are added for different mob types. - var/mb_cd_length = 100 //10 second cooldown for masturbating because fuck spam + var/mb_cd_length = 50 //5 second cooldown for masturbating because fuck spam var/mb_cd_timer = 0 //The timer itself /mob/living/carbon/human canbearoused = TRUE + var/saved_underwear = ""//saves their underwear so it can be toggled later + var/saved_undershirt = "" + +/mob/living/carbon/human/New() + ..() + saved_underwear = underwear + saved_undershirt = undershirt + //Species vars /datum/species var/arousal_gain_rate = 1 //Rate at which this species becomes aroused var/arousal_lose_rate = 1 //Multiplier for how easily arousal can be relieved + var/list/cum_fluids = list("semen") + var/list/milk_fludis = list("milk") + var/list/femcum_fluids = list("femcum") //Mob procs /mob/living/Life() - if(stat != DEAD) - handle_arousal() - ..() - /mob/living/proc/handle_arousal() return /mob/living/carbon/handle_arousal() - ..() - var/datum/species/S - if(has_dna()) + if(canbearoused && dna) + var/datum/species/S S = dna.species - if(S && SSmob.times_fired%36==2 && getArousalLoss() < 100)//Totally stolen from breathing code. Do this every 36 ticks. - adjustArousalLoss(arousal_rate * S.arousal_gain_rate) + if(S && SSmob.times_fired%36==2 && getArousalLoss() < max_arousal)//Totally stolen from breathing code. Do this every 36 ticks. + adjustArousalLoss(arousal_rate * S.arousal_gain_rate) + if(dna.features["exhibitionist"]) + var/amt_nude = 0 + if(is_chest_exposed() && (gender == FEMALE || getorganslot("breasts"))) + amt_nude++ + if(is_groin_exposed()) + if(getorganslot("penis")) + amt_nude++ + if(getorganslot("vagina")) + amt_nude++ + var/mob/living/M + var/watchers = 0 + for(M in view(world.view, src)) + if(M.client && !M.stat && !M.eye_blind && (locate(src) in viewers(world.view,M))) + watchers++ + if(watchers && amt_nude) + adjustArousalLoss((amt_nude * watchers) + S.arousal_gain_rate) + /mob/living/proc/getArousalLoss() return arousalloss @@ -55,35 +78,11 @@ return ((100 / max_arousal) * arousalloss) /mob/living/proc/isPercentAroused(percentage)//returns true if the mob's arousal (measured in a percent of 100) is greater than the arg percentage. - if(!isnum(percentage)) - return FALSE + if(!isnum(percentage) || percentage > 100 || percentage < 0) + CRASH("Provided percentage is invalid") if(getPercentAroused() >= percentage) return TRUE -/mob/living/proc/mob_masturbate()//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" - if(canbearoused && !restrained() && !stat) - 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!", \ - "You start masturbating.") - if(do_after(src, 100, target = src)) - src.visible_message("[src] relieves themself!", \ - "You have relieved yourself.") - setArousalLoss(min_arousal) - /* - switch(gender) - if(MALE) - PoolOrNew(/obj/effect/decal/cleanable/semen, loc) - if(FEMALE) - PoolOrNew(/obj/effect/decal/cleanable/femcum, loc) - */ - else - src << "You aren't aroused enough for that." - //H U D// /mob/living/proc/updatearousal() update_arousal_hud() @@ -143,6 +142,7 @@ /obj/screen/arousal name = "arousal" icon_state = "arousal0" + icon = 'code/citadel/icons/hud.dmi' screen_loc = ui_arousal /obj/screen/arousal/Click() @@ -154,3 +154,135 @@ return 1 else M << "Arousal is disabled. Feature is unavailable." + + + +/mob/living/proc/mob_masturbate()//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" + if(canbearoused && !restrained() && !stat) + 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!", \ + "You start masturbating.") + if(do_after(src, 30, target = src)) + src.visible_message("[src] relieves themself!", \ + "You have relieved yourself.") + setArousalLoss(min_arousal) + /* + switch(gender) + if(MALE) + PoolOrNew(/obj/effect/decal/cleanable/semen, loc) + if(FEMALE) + PoolOrNew(/obj/effect/decal/cleanable/femcum, loc) + */ + else + src << "You aren't aroused enough for that." + +/mob/living/carbon/human/mob_masturbate() + if(mb_cd_timer > world.time) + src << "You need to wait [round((mb_cd_timer - world.time)/(20))] seconds before you can do that again!" + return + var/list/genitals_list = list() + var/obj/item/organ/genital/SG = null//originally selected_genital + var/list/containers_list = list() + var/obj/item/weapon/reagent_containers/SC = null + var/datum/reagents/fluid_source = null + var/into_container = 0 + var/arms = get_num_arms() + var/free_hands = arms + var/total_cum = 0 + var/finished = 0 + var/mb_time = 30 + mb_cd_timer = (world.time + mb_cd_length) + if(canbearoused && has_dna()) + if(restrained()) + src << "You can't do that while restrained!" + return + if(stat) + src << "You must be conscious to do that!" + return + if(getArousalLoss() < 33)//flat number instead of percentage + src << "You aren't aroused enough for that!" + return + if(!is_groin_exposed()) + src << "You need to undress, first!" + return + if(!arms) + src << "You need at least one arm." + return + for(var/helditem in held_items)//how many hands are free + if(isobj(helditem)) + free_hands-- + if(free_hands <= 0) + src << "You need at least one free hand." + return + for(var/obj/item/organ/genital/G in internal_organs) + if(G.can_masturbate_with)//filter out what you can't masturbate with + genitals_list += G + if(genitals_list.len) + SG = input(src, "with what?", "Masturbate") as null|obj in genitals_list + if(SG) + for(var/obj/item/weapon/reagent_containers/container in held_items) + if(container.is_open_container() || istype(container, /obj/item/weapon/reagent_containers/food/snacks/pie)) + containers_list += container + if(containers_list.len) + SC = input(src, "Into or onto what?(Cancel for nowhere)", "Masturbate") as null|obj in containers_list + if(SC) + if(in_range(src, SC)) + into_container = 1 + SG.update() + switch(SG.type) + + //Penis + if(/obj/item/organ/genital/penis) + var/obj/item/organ/genital/penis/P = SG + if(!P.linked_balls) + src << "Grow a pair!" + return + fluid_source = P.linked_balls.reagents + total_cum = fluid_source.total_volume + if(into_container)//into a glass or beaker or whatever + src.visible_message("[src] starts [pick("jerking off","stroking")] their [SG] over [SC].", \ + "You start jerking off over [SC.name].", \ + "You start masturbating.") + if(do_after(src, mb_time, target = src) && in_range(src, SC)) + fluid_source.trans_to(SC, total_cum) + src.visible_message("[src] orgasms, [pick("cumming into", "emptying themself into")] [SC]!", \ + "You cum into [SC].", \ + "You have relieved yourself.") + finished = 1 + + else//not into a container + src.visible_message("[src] starts [pick("jerking off","stroking")] their [pick(dick_nouns)].", \ + "You start jerking off your [pick(dick_nouns)].", \ + "You start masturbating.") + if(do_after(src, mb_time, target = src)) + if(total_cum > 5) + fluid_source.reaction(src.loc, TOUCH, 1, 0) + fluid_source.clear_reagents() + src.visible_message("[src] orgasms, [pick("shooting cum", "draining their balls")][istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""]!", \ + "You cum[istype(src.loc, /turf/open/floor) ? " onto [src.loc]" : ""].", \ + "You have relieved yourself.") + finished = 1 + + else//backup message, just in case + src.visible_message("[src] starts masturbating!", \ + "You start masturbating.") + if(do_after(src, mb_time, target = src)) + src.visible_message("[src] [pick("relieves themself!", "shudders and moans in orgasm!")]", \ + "You have relieved yourself.") + finished = 1 + if(finished) + setArousalLoss(min_arousal) + + else + src << "You have no genitals!" + return + +/mob/living/carbon/proc/force_orgasm(intensity) + if(canbearoused && has_dna() && (has_penis() || has_vagina())) + return 1 + return 0 \ No newline at end of file diff --git a/code/citadel/cit_genemods.dm b/code/citadel/cit_genemods.dm new file mode 100644 index 0000000000..2279ab972b --- /dev/null +++ b/code/citadel/cit_genemods.dm @@ -0,0 +1,22 @@ +//Will include consumable gene mods in the future. + +/obj/item/weapon/genemod + name = "genetic modifier" + desc = "Microbodies which can grow, morph, or otherwise change an organism into something else." + icon = 'icons/obj/items.dmi' + icon_state = "dnainjector" + throw_speed = 3 + throw_range = 5 + w_class = WEIGHT_CLASS_TINY + origin_tech = "biotech=3" + var/applied_region = "chest" + var/list/add_mutations = list() + var/list/remove_mutations = list() + + var/list/add_mutations_static = list() + var/list/remove_mutations_static = list() + + var/used = 0 + +/obj/item/weapon/genemod/proc/use(mob/living/carbon/human/target) + return \ No newline at end of file diff --git a/code/citadel/kegs.dm b/code/citadel/cit_kegs.dm similarity index 100% rename from code/citadel/kegs.dm rename to code/citadel/cit_kegs.dm diff --git a/code/citadel/cit_reagents.dm b/code/citadel/cit_reagents.dm index 5b982656cc..794a3ad553 100644 --- a/code/citadel/cit_reagents.dm +++ b/code/citadel/cit_reagents.dm @@ -30,17 +30,15 @@ icon = 'code/citadel/icons/effects.dmi' icon_state = "semen1" random_icon_states = list("semen1", "semen2", "semen3", "semen4") -// blood_state = BLOOD_STATE_SEMEN -// bloodiness = MAX_SHOE_BLOODINESS /obj/effect/decal/cleanable/semen/New() + ..() dir = pick(1,2,4,8) - ..() -/obj/effect/decal/cleanable/semen/replace_decal(obj/effect/decal/cleanable/semen/S) -// if(S.reagent_DNA["semen"]) -// reagent_DNA["semen"] |= S.reagent_DNA["semen"] - ..() +/datum/reagent/consumable/semen/reaction_turf(turf/T, reac_volume) + if(!isspaceturf(T)) + var/obj/effect/decal/cleanable/reagentdecal = new/obj/effect/decal/cleanable/semen(T) + reagentdecal.reagents.add_reagent("semen", reac_volume) /datum/reagent/consumable/femcum name = "Female Ejaculate" @@ -65,14 +63,27 @@ bloodiness = null /obj/effect/decal/cleanable/femcum/New() - dir = pick(1,2,4,8) ..() + dir = pick(1,2,4,8) /obj/effect/decal/cleanable/femcum/replace_decal(obj/effect/decal/cleanable/femcum/F) if (F.blood_DNA) blood_DNA |= F.blood_DNA.Copy() ..() +/datum/reagent/consumable/femcum/reaction_turf(turf/T, reac_volume) + if(!istype(T)) + return + if(reac_volume < 3) + return + + var/obj/effect/decal/cleanable/femcum/S = locate() in T + if(!S) + S = new(T) + S.reagents.add_reagent("semen", reac_volume) + if(data["blood_DNA"]) + S.blood_DNA[data["blood_DNA"]] = data["blood_type"] + //aphrodisiac & anaphrodisiac /datum/reagent/aphrodisiac diff --git a/code/citadel/icons/breasts.dmi b/code/citadel/icons/breasts.dmi new file mode 100644 index 0000000000..7735fad868 Binary files /dev/null and b/code/citadel/icons/breasts.dmi differ diff --git a/code/citadel/icons/breasts_onmob.dmi b/code/citadel/icons/breasts_onmob.dmi new file mode 100644 index 0000000000..12f23ad56d Binary files /dev/null and b/code/citadel/icons/breasts_onmob.dmi differ diff --git a/code/citadel/icons/dildo.dmi b/code/citadel/icons/dildo.dmi new file mode 100644 index 0000000000..22eb48c9cf Binary files /dev/null and b/code/citadel/icons/dildo.dmi differ diff --git a/code/citadel/icons/effects.dmi b/code/citadel/icons/effects.dmi index 9a99bc085a..cc8be21dd4 100644 Binary files a/code/citadel/icons/effects.dmi and b/code/citadel/icons/effects.dmi differ diff --git a/code/citadel/icons/hud.dmi b/code/citadel/icons/hud.dmi new file mode 100644 index 0000000000..bf2adcb1fc Binary files /dev/null and b/code/citadel/icons/hud.dmi differ diff --git a/code/citadel/icons/onahole.dmi b/code/citadel/icons/onahole.dmi new file mode 100644 index 0000000000..030ebcc69d Binary files /dev/null and b/code/citadel/icons/onahole.dmi differ diff --git a/code/citadel/icons/ovipositor.dmi b/code/citadel/icons/ovipositor.dmi new file mode 100644 index 0000000000..81d857417f Binary files /dev/null and b/code/citadel/icons/ovipositor.dmi differ diff --git a/code/citadel/icons/penis.dmi b/code/citadel/icons/penis.dmi new file mode 100644 index 0000000000..56f7f12803 Binary files /dev/null and b/code/citadel/icons/penis.dmi differ diff --git a/code/citadel/icons/penis_onmob.dmi b/code/citadel/icons/penis_onmob.dmi new file mode 100644 index 0000000000..628ed11068 Binary files /dev/null and b/code/citadel/icons/penis_onmob.dmi differ diff --git a/code/citadel/icons/vagina_onmob.dmi b/code/citadel/icons/vagina_onmob.dmi new file mode 100644 index 0000000000..867ede99d5 Binary files /dev/null and b/code/citadel/icons/vagina_onmob.dmi differ diff --git a/code/citadel/organs.dm b/code/citadel/organs.dm deleted file mode 100644 index 7ba1fd0ac2..0000000000 --- a/code/citadel/organs.dm +++ /dev/null @@ -1,45 +0,0 @@ -/obj/item/organ/stomach - name = "stomach" - icon_state = "stomach" - zone = "chest" - slot = "stomach" - w_class = 3 - -/obj/item/organ/stomach/prepare_eat() - var/obj/S = ..() - S.reagents.add_reagent("sacid", 2) - return S - -/obj/item/organ/penis - name = "penis" - icon_state = "penis" - zone = "groin" - slot = "penis" - w_class = 3 - var/shape = "human" - var/size = "normal" - var/testicles - -/obj/item/organ/testicles - name = "testicles" - icon_state = "testicles" - zone = "groin" - slot = "testicles" - w_class = 3 - var/size = "normal" - -/obj/item/organ/vagina - name = "vagina" - icon_state = "vagina" - zone = "groin" - slot = "vagina" - w_class = 3 - var/shape = "human" - var/ovaries - -/obj/item/organ/womb - name = "womb" - icon_state = "womb" - zone = "groin" - slot = "womb" - w_class = 3 diff --git a/code/citadel/organs/breasts.dm b/code/citadel/organs/breasts.dm new file mode 100644 index 0000000000..41ebb2d0f8 --- /dev/null +++ b/code/citadel/organs/breasts.dm @@ -0,0 +1,32 @@ +/obj/item/organ/genital/breasts + name = "breasts" + desc = "Female milk producing organs." + icon_state = "breasts" + icon = 'code/citadel/icons/breasts.dmi' + zone = "chest" + slot = "breasts" + w_class = 3 + size = "e" + fluid_id = "milk" + var/cup_size = BREASTS_SIZE_DEF + var/amount = 2 + producing = TRUE + +/obj/item/organ/genital/breasts/New() + ..() + create_reagents(fluid_max_volume) + reagents.add_reagent(fluid_id, fluid_max_volume) + update() + +/obj/item/organ/genital/breasts/on_life() + reagents.maximum_volume = fluid_max_volume + if(fluid_id && producing) + generate_milk() + +/obj/item/organ/genital/breasts/proc/generate_milk() + if(!owner) + return FALSE + if(owner.stat == DEAD) + return FALSE + reagents.isolate_reagent(fluid_id) + reagents.add_reagent(fluid_id, (fluid_mult * fluid_rate)) \ No newline at end of file diff --git a/code/citadel/organs/eggsack.dm b/code/citadel/organs/eggsack.dm new file mode 100644 index 0000000000..e760ef6035 --- /dev/null +++ b/code/citadel/organs/eggsack.dm @@ -0,0 +1,14 @@ +/obj/item/organ/genital/eggsack + name = "egg sack" + desc = "An egg producing reproductive organ." + icon_state = "egg_sack" + icon = 'code/citadel/icons/ovipositor.dmi' + zone = "groin" + slot = "testicles" + w_class = 3 + var/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/code/citadel/organs/genitals.dm b/code/citadel/organs/genitals.dm new file mode 100644 index 0000000000..1cd904fd83 --- /dev/null +++ b/code/citadel/organs/genitals.dm @@ -0,0 +1,233 @@ +/obj/item/organ/genital + color = "#fcccb3" + var/shape = "human" + var/sensitivity = 1 + var/list/genital_flags = list() + var/can_masturbate_with = 0 + 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 + +/obj/item/organ/genital/New() + ..() + reagents = create_reagents(fluid_max_volume) + +/obj/item/organ/genital/proc/update() + return + +/obj/item/organ/genital/proc/update_size() + return + +/obj/item/organ/genital/proc/update_appearance() + return + +/obj/item/organ/genital/proc/update_link() + + +/obj/item/organ/genital/Insert(mob/living/carbon/M, special = 0) + ..() + update() +/obj/item/organ/genital/Remove(mob/living/carbon/M, special = 0) + ..() + update() + +//proc to give a player their genitals and stuff when they log in +/mob/living/carbon/human/proc/give_genitals(clean=0)//clean will remove all pre-existing genitals. proc will then give them any genitals that are enabled in their DNA + if(clean) + var/obj/item/organ/genital/GtoClean + for(GtoClean in internal_organs) + GtoClean.Remove(src) + qdel(GtoClean) + if(dna.features["has_cock"]) + give_penis() + if(dna.features["has_balls"]) + give_balls() + else if(dna.features["has_ovi"]) + give_ovipositor() + if(dna.features["has_eggsack"]) + give_eggsack() + if(dna.features["has_breasts"]) + give_breasts() + if(dna.features["has_vag"]) + give_vagina() + if(dna.features["has_womb"]) + give_womb() + +/mob/living/carbon/human/proc/give_penis() + if(!dna) + return FALSE + if(NOGENITALS in dna.species.species_traits) + return FALSE + if(!getorganslot("penis")) + var/obj/item/organ/genital/penis/P = new + P.Insert(src) + if(P) + if(dna.species.use_skintones && dna.features["genitals_use_skintone"]) + P.color = skintone2hex(skin_tone) + else + P.color = dna.features["cock_color"] + P.length = dna.features["cock_length"] + P.girth_ratio = dna.features["cock_girth_ratio"] + P.shape = dna.features["cock_shape"] + P.update() + +/mob/living/carbon/human/proc/give_balls() + if(!dna) + return FALSE + if(NOGENITALS in dna.species.species_traits) + return FALSE + if(!getorganslot("testicles")) + var/obj/item/organ/genital/testicles/T = new + T.Insert(src) + if(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["bals_size"] + T.sack_size = dna.features["balls_sack_size"] + 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(!has_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) + B.cup_size = dna.features["breasts_size"] + B.fluid_id = dna.features["breasts_fluid"] + B.update() + + +/mob/living/carbon/human/proc/give_ovipositor() +/mob/living/carbon/human/proc/give_eggsack() +/mob/living/carbon/human/proc/give_vagina() + if(!has_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(dna.species.use_skintones && dna.features["genitals_use_skintone"]) + V.color = skintone2hex(skin_tone) + else + V.color = dna.features["vag_color"] + V.update() +/mob/living/carbon/human/proc/give_womb() + if(!has_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) + W.update() + + +/datum/species/proc/genitals_layertext(layer) + switch(layer) + if(GENITALS_BEHIND_LAYER) + return "BEHIND" + if(GENITALS_ADJ_LAYER) + return "ADJ" + if(GENITALS_FRONT_LAYER) + return "FRONT" + +//procs to handle sprite overlays being applied to humans + +/obj/item/equipped(mob/user, slot) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.update_genitals() + ..() + +/mob/living/carbon/human/doUnEquip(obj/item/I, force) + . = ..() + if(!.) + return + update_genitals() + +/mob/living/carbon/human/proc/update_genitals() + dna.species.handle_genitals(src) + +/datum/species/proc/handle_genitals(mob/living/carbon/human/H) + if(!H) + CRASH("H = null") + if(!H.internal_organs.len) + return + if(NOGENITALS in species_traits) + return + + var/list/genitals_to_add = list() + var/list/relevent_layers = list(GENITALS_BEHIND_LAYER, GENITALS_ADJ_LAYER, GENITALS_FRONT_LAYER) + var/list/standing = list() + var/size + + H.remove_overlay(GENITALS_BEHIND_LAYER) + H.remove_overlay(GENITALS_ADJ_LAYER) + H.remove_overlay(GENITALS_FRONT_LAYER) + + if(H.disabilities & HUSK) + return + //start scanning for genitals + if(H.has_penis() && H.is_groin_exposed()) + genitals_to_add += H.getorganslot("penis") + if(H.has_breasts() && H.is_chest_exposed()) + genitals_to_add += H.getorganslot("breasts") + if(H.has_vagina() && H.is_groin_exposed()) + genitals_to_add += H.getorganslot("vagina") + var/image/I + //start applying overlays + for(var/layer in relevent_layers) + var/layertext = genitals_layertext(layer) + for(var/obj/item/organ/genital/G in genitals_to_add) + var/datum/sprite_accessory/S + switch(G.type) + if(/obj/item/organ/genital/penis) + S = cock_shapes_list[G.shape] + size = G.size + + if(!S || S.icon_state == "none") + continue + var/icon_string + icon_string = "[G.slot]_[S.icon_state]_[size]_[layertext]" + I = image("icon" = S.icon, "icon_state" = icon_string, "layer" =- layer) + if(S.center) + I = center_image(I,S.dimension_x,S.dimension_y) + switch(S.color_src) + if("cock_color") + I.color = "#[H.dna.features["cock_color"]]" + if("breasts_color") + I.color = "#[H.dna.features["breasts_color"]]" + if(MUTCOLORS) + if(fixed_mut_color) + I.color = "#[fixed_mut_color]" + else + I.color = "#[H.dna.features["mcolor"]]" + if(MUTCOLORS2) + if(fixed_mut_color2) + I.color = "#[fixed_mut_color2]" + else + I.color = "#[H.dna.features["mcolor2"]]" + if(MUTCOLORS3) + if(fixed_mut_color3) + I.color = "#[fixed_mut_color3]" + else + I.color = "#[H.dna.features["mcolor3"]]" + standing += I + H.overlays_standing[layer] = standing.Copy() + standing = list() + + H.apply_overlay(GENITALS_BEHIND_LAYER) + H.apply_overlay(GENITALS_ADJ_LAYER) + H.apply_overlay(GENITALS_FRONT_LAYER) \ No newline at end of file diff --git a/code/citadel/organs/genitals_sprite_accessories.dm b/code/citadel/organs/genitals_sprite_accessories.dm new file mode 100644 index 0000000000..376017f73b --- /dev/null +++ b/code/citadel/organs/genitals_sprite_accessories.dm @@ -0,0 +1,116 @@ +//DICKS,COCKS,PENISES,WHATEVER YOU WANT TO CALL THEM +/datum/sprite_accessory/penis + icon = 'code/citadel/icons/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 + +/datum/sprite_accessory/penis/none + icon_state = "none" + name = "None" + +/datum/sprite_accessory/penis/human + icon_state = "human" + name = "Human" + +/datum/sprite_accessory/penis/knotted + icon_state = "knotted" + name = "Knotted" + +/datum/sprite_accessory/penis/flared + icon_state = "flared" + name = "Flared" + +/datum/sprite_accessory/penis/barbknot + icon_state = "barbknot" + name = "Barbed, Knotted" + +/datum/sprite_accessory/penis/tapered + icon_state = "tapered" + name = "Tapered" + +//BREASTS BE HERE +/datum/sprite_accessory/breasts + icon = 'code/citadel/icons/breasts_onmob.dmi' + icon_state = null + name = "breasts" + gender_specific = 0 + color_src = MUTCOLORS2 //I'll have skin_tone override this if the species uses them + locked = 0 +/*!!ULTRACOMPRESSEDEDITION!!*/ +/datum/sprite_accessory/breasts/none + icon_state = "none" + name = "None" +/datum/sprite_accessory/breasts/a + icon_state = "a" + name = "A" +/datum/sprite_accessory/breasts/aa + icon_state = "a" + name = "AA" +/datum/sprite_accessory/breasts/b + icon_state = "b" + name = "B" +/datum/sprite_accessory/breasts/bb + icon_state = "b" + name = "BB" +/datum/sprite_accessory/breasts/c + icon_state = "c" + name = "C" +/datum/sprite_accessory/breasts/cc + icon_state = "c" + name = "CC" +/datum/sprite_accessory/breasts/d + icon_state = "d" + name = "D" +/datum/sprite_accessory/breasts/dd + icon_state = "d" + name = "DD" +/datum/sprite_accessory/breasts/e + icon_state = "e" + name = "E" +/datum/sprite_accessory/breasts/ee + icon_state = "e" + name = "EE" +/datum/sprite_accessory/breasts/f + icon_state = "f" + name = "F" + locked = 1 +/datum/sprite_accessory/breasts/ff + icon_state = "f" + name = "FF" + locked = 1 +/datum/sprite_accessory/breasts/g + icon_state = "g" + name = "G" + locked = 1 +/datum/sprite_accessory/breasts/gg + icon_state = "g" + name = "GG" + locked = 1 +/datum/sprite_accessory/breasts/h + icon_state = "h" + name = "H" + locked = 1 +/datum/sprite_accessory/breasts/hh + icon_state = "h" + name = "HH" + locked = 1 + +//OVIPOSITORS BE HERE +/datum/sprite_accessory/ovipositor + icon = 'code/citadel/icons/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 = "none" + name = "None" + +/datum/sprite_accessory/ovipositor/knotted + icon_state = "knotted" + name = "Knotted" diff --git a/code/citadel/organs/ovipositor.dm b/code/citadel/organs/ovipositor.dm new file mode 100644 index 0000000000..b54b93bc93 --- /dev/null +++ b/code/citadel/organs/ovipositor.dm @@ -0,0 +1,17 @@ +/obj/item/organ/genital/ovipositor + name = "ovipositor" + desc = "An egg laying reproductive organ." + icon_state = "ovi_knotted_2" + icon = 'code/citadel/icons/ovipositor.dmi' + zone = "groin" + slot = "penis" + w_class = 3 + shape = "knotted" + size = 3 + 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/code/citadel/organs/penis.dm b/code/citadel/organs/penis.dm new file mode 100644 index 0000000000..7427503a99 --- /dev/null +++ b/code/citadel/organs/penis.dm @@ -0,0 +1,60 @@ +/obj/item/organ/genital/penis + name = "penis" + desc = "A male reproductive organ." + icon_state = "penis" + icon = 'code/citadel/icons/penis.dmi' + zone = "groin" + slot = "penis" + w_class = 3 + color = null + can_masturbate_with = 1 + size = 2 //arbitrary value derived from length and girth for sprites. + var/length = 6 //inches + 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("", "barbknot") + var/obj/item/organ/genital/testicles/linked_balls + +/obj/item/organ/genital/penis/New() + ..() + update() + +/obj/item/organ/genital/penis/update() + update_size() + update_appearance() + update_link() + +/obj/item/organ/genital/penis/update_size() + switch(length) + if(-INFINITY to 5) + size = 1 + if(5 to 9) + size = 2 + if(9 to 12) + size = 3//no new sprites for anything larger + if(9 to 15) + size = 3 + if(15 to INFINITY) + size = 3 + girth = (length * girth_ratio) + +/obj/item/organ/genital/penis/update_appearance() + var/string = "penis_[shape]_[size]" + icon_state = sanitize_text(string) +// name = "[shape] penis" + desc = "That's a [lowertext(shape)] penis. You estimate it's about [round(length, 0.25)] inch[length > 1 ? "es" : ""] long and [round(girth, 0.25)] inch[length > 1 ? "es" : ""] around." + if(!owner) + return + color = sanitize_hexcolor(owner.dna.features["cock_color"], 6, 0) + +/obj/item/organ/genital/penis/update_link() + if(owner) + linked_balls = (owner.getorganslot("testicles")) + if(linked_balls) + linked_balls.linked_penis = src + else + if(linked_balls) + linked_balls.linked_penis = null + linked_balls = null diff --git a/code/citadel/organs/testicles.dm b/code/citadel/organs/testicles.dm new file mode 100644 index 0000000000..9f2b0bacf2 --- /dev/null +++ b/code/citadel/organs/testicles.dm @@ -0,0 +1,60 @@ +/obj/item/organ/genital/testicles + name = "testicles" + desc = "A male reproductive organ." + icon_state = "testicles" + icon = 'code/citadel/icons/penis.dmi' + zone = "groin" + slot = "testicles" + w_class = 3 + var/internal = FALSE + size = BALLS_SIZE_DEF + var/sack_size = BALLS_SACK_SIZE_DEF + fluid_id = "semen" + producing = TRUE + var/sent_full_message = 1 //defaults to 1 since they're full to start + var/obj/item/organ/genital/penis/linked_penis + +/obj/item/organ/genital/testicles/New() + ..() + create_reagents(fluid_max_volume) + reagents.add_reagent(fluid_id, fluid_max_volume) + +/obj/item/organ/genital/testicles/on_life() + if(fluid_id && 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 < 0) + send_full_message() + sent_full_message = 1 + return FALSE + sent_full_message = 0 + if(!owner && linked_penis) + if(linked_penis.linked_balls == src) + linked_penis.linked_balls = null + linked_penis = null + return FALSE + if(!reagents) + create_reagents(fluid_max_volume) + update_link() + if(!linked_penis) + 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) + linked_penis = (owner.getorganslot("penis")) + if(linked_penis) + linked_penis.linked_balls = src + else if(linked_penis != null) + linked_penis.linked_balls = null + linked_penis = null + +/obj/item/organ/genital/testicles/proc/send_full_message(msg = "Your balls finally feel full, again.") + if(owner && istext(msg)) + owner << msg + return TRUE + diff --git a/code/citadel/organs/vagina.dm b/code/citadel/organs/vagina.dm new file mode 100644 index 0000000000..1229c45be9 --- /dev/null +++ b/code/citadel/organs/vagina.dm @@ -0,0 +1,15 @@ +/obj/item/organ/genital/vagina + name = "vagina" + desc = "A female reproductive organ." + icon_state = "vagina" + zone = "groin" + slot = "vagina" + can_masturbate_with = 1 + w_class = 3 + var/wetness = 1 + var/capacity_length = 8//D E P T H + var/capacity_girth = 8 + var/clits = 1 + var/clit_diam = 0.25 + var/clit_len = 0.25 + var/obj/item/organ/womb/linked_womb diff --git a/code/citadel/organs/womb.dm b/code/citadel/organs/womb.dm new file mode 100644 index 0000000000..563b434c80 --- /dev/null +++ b/code/citadel/organs/womb.dm @@ -0,0 +1,9 @@ +/obj/item/organ/genital/womb + name = "womb" + desc = "A female reproductive organ." + icon_state = "womb" + zone = "groin" + slot = "womb" + w_class = 3 + fluid_id = "femcum" + var/obj/item/organ/genital/vagina/linked_vag diff --git a/code/datums/datumvars.dm b/code/datums/datumvars.dm index 2db9928edc..eba591ac50 100644 --- a/code/datums/datumvars.dm +++ b/code/datums/datumvars.dm @@ -91,7 +91,7 @@ CLONE:[M.getCloneLoss()] BRAIN:[M.getBrainLoss()] STAMINA:[M.getStaminaLoss()] - AROUSAL:[M.getArousalLoss()] + AROUSAL:[M.getArousalLoss()] "} else @@ -1148,6 +1148,8 @@ L.adjustCloneLoss(amount) if("stamina") L.adjustStaminaLoss(amount) + if("arousal") + L.adjustArousalLoss(amount) else usr << "You caused an error. DEBUG: Text:[Text] Mob:[L]" return diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 3efc7d82b2..b18620c896 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -375,6 +375,7 @@ var/global/image/fire_overlay = image("icon" = 'icons/effects/fire.dmi', "icon_s if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot. A.Grant(user) + //sometimes we only want to grant the item's action if it's equipped in a specific slot. /obj/item/proc/item_action_slot_check(slot, mob/user) if(slot == slot_in_backpack || slot == slot_legcuffed) //these aren't true slots, so avoid granting actions there diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm index 78c5ceba85..89182acc0f 100644 --- a/code/modules/admin/admin.dm +++ b/code/modules/admin/admin.dm @@ -493,7 +493,7 @@ var/global/BSACooldown = 0 set name="Toggle Dead OOC" dooc_allowed = !( dooc_allowed ) - log_admin("[key_name(usr)] toggled OOC.") + log_admin("[key_name(usr)] toggled Dead OOC.") message_admins("[key_name_admin(usr)] toggled Dead OOC.") feedback_add_details("admin_verb","TDOOC") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! /* diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 3915ee8df5..5a4123d75d 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -62,14 +62,79 @@ var/list/preferences_datums = list() var/skin_tone = "caucasian1" //Skin color var/eye_color = "000" //Eye color var/datum/species/pref_species = new /datum/species/human() //Mutant race - var/list/features = list("mcolor" = "FFF", "mcolor2" = "FFF","mcolor3" = "FFF", "tail_lizard" = "Smooth", "tail_human" = "None", "snout" = "Round", "horns" = "None", "ears" = "None", "wings" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None", "mam_body_markings" = "None", "mam_ears" = "None", "mam_tail" = "None", "mam_tail_animated" = "None", - "xenodorsal" = "None", "xenohead" = "None", "xenotail" = "None", "legs" = "Normal Legs", "taur" = "None") + var/list/features = list("mcolor" = "FFF", + "mcolor2" = "FFF", + "mcolor3" = "FFF", + "tail_lizard" = "Smooth", + "tail_human" = "None", + "snout" = "Round", + "horns" = "None", + "ears" = "None", + "wings" = "None", + "frills" = "None", + "spines" = "None", + "body_markings" = "None", + "mam_body_markings" = "None", + "mam_ears" = "None", + "mam_tail" = "None", + "mam_tail_animated" = "None", + "xenodorsal" = "None", + "xenohead" = "None", + "xenotail" = "None", + "legs" = "Normal Legs", + "taur" = "None", + "exhibitionist" = FALSE, + "genitals_use_skintone" = FALSE, + "has_cock" = FALSE, + "cock_shape" = "human", + "cock_length" = 6, + "cock_girth_ratio" = COCK_GIRTH_RATIO_DEF, + "cock_color" = "fff", + "has_sheath" = FALSE, + "sheath_color" = "fff", + "has_balls" = FALSE, + "balls_internal" = FALSE, + "balls_color" = "fff", + "balls_amount" = 2, + "balls_sack_size" = BALLS_SACK_SIZE_DEF, + "balls_size" = BALLS_SIZE_DEF, + "balls_cum_rate" = CUM_RATE, + "balls_cum_mult" = CUM_RATE_MULT, + "balls_efficiency" = CUM_EFFICIENCY, + "balls_fluid" = "semen", + "has_ovi" = FALSE, + "ovi_shape" = "knotted", + "ovi_length" = 6, + "ovi_color" = "fff", + "has_eggsack" = FALSE, + "eggsack_internal" = TRUE, + "eggsack_color" = "fff", + "eggsack_size" = BALLS_SACK_SIZE_DEF, + "eggsack_egg_color" = "fff", + "eggsack_egg_size" = EGG_GIRTH_DEF, + "has_breasts" = FALSE, + "breasts_color" = "fff", + "breasts_size" = "C", + "breasts_fluid" = "milk", + "has_vag" = FALSE, + "vag_color" = "fff", + "vag_clits" = 1, + "vag_clit_diam" = 0.25, + "vag_clit_len" = 0.25, + "has_womb" = FALSE, + "womb_cum_rate" = CUM_RATE, + "womb_cum_mult" = CUM_RATE_MULT, + "womb_efficiency" = CUM_EFFICIENCY, + "womb_fluid" = "femcum" + )//MAKE SURE TO UPDATE THE LIST IN MOBS.DM IF YOU'RE GOING TO ADD TO THIS LIST, OTHERWISE THINGS MIGHT GET FUCKEY + var/list/custom_names = list("clown", "mime", "ai", "cyborg", "religion", "deity") var/prefered_security_department = SEC_DEPT_RANDOM //Mob preview var/icon/preview_icon = null + var/icon/nude_preview_icon = null //Jobs, uses bitflags var/job_civilian_high = 0 @@ -90,7 +155,7 @@ var/list/preferences_datums = list() // Want randomjob if preferences already filled - Donkie var/joblessrole = BERANDOMJOB //defaults to 1 for fewer assistants - // 0 = character settings, 1 = game preferences + // 0 = character settings, 1 = game preferences, 2 = character appearance var/current_tab = 0 var/flavor_text = "" @@ -135,13 +200,18 @@ var/list/preferences_datums = list() /datum/preferences/proc/ShowChoices(mob/user) if(!user || !user.client) return - update_preview_icon() + if(current_tab == 2) + update_preview_icon(nude=TRUE) + else + update_preview_icon(nude=FALSE) user << browse_rsc(preview_icon, "previewicon.png") var/dat = "
| "
-
- if(config.mutant_races)
- dat += "Species: [pref_species.id] " - else - dat += "Species: Human " - - dat += "Underwear: [underwear] " - dat += "Undershirt: [undershirt] " - dat += "Socks: [socks] " - dat += "Backpack: [backbag] " - dat += "Uplink Spawn Location: [uplink_spawn_loc] | "
-
-
// dat += "Size: [character_size]"
-
- dat += "Skin Tone" - - dat += "[skin_tone]" - - dat += " | "
-
- if(HAIR in pref_species.species_traits)
-
- dat += ""
-
- dat += "Hair Style" - - dat += "[hair_style]" - dat += "< > " - dat += " Change " - - - dat += " | "
-
- dat += "Facial Hair Style" - - dat += "[facial_hair_style]" - dat += "< > " - dat += " Change " - - dat += " | "
-
- if(EYECOLOR in pref_species.species_traits)
-
- dat += ""
-
- dat += "Eye Color" - - dat += " Change" - - dat += " | "
-
- if(config.mutant_races) //We don't allow mutant bodyparts for humans either unless this is true.
-
- if((MUTCOLORS in pref_species.species_traits) || (MUTCOLORS_PARTSONLY in pref_species.species_traits))
-
- dat += ""
-
- dat += "Alien/Mutant Colors" - - dat += " Change" - - dat += " Change " - - dat += " Change " - - dat += " | "
-
- if("tail_lizard" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Tail" - - dat += "[features["tail_lizard"]]" - - dat += " | "
-
- if("snout" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Snout" - - dat += "[features["snout"]]" - - dat += " | "
-
- if("horns" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Horns" - - dat += "[features["horns"]]" - - dat += " | "
-
- if("frills" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Frills" - - dat += "[features["frills"]]" - - dat += " | "
-
- if("spines" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Spines" - - dat += "[features["spines"]]" - - dat += " | "
-
- if("body_markings" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Body Markings" - - dat += "[features["body_markings"]]" - - dat += " | "
-
- //Mammal bodyparts
- if("mam_body_markings" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Mammal Body Markings" - - dat += "[features["mam_body_markings"]]" - - dat += " | "
-
- if("mam_tail" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Tail" - - dat += "[features["mam_tail"]]" - - if("legs" in pref_species.mutant_bodyparts) - dat += " | "
-
- dat += "Legs" - - dat += "[features["legs"]]" - - dat += " | "
-
- if("mam_ears" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Ears" - - dat += "[features["mam_ears"]]" - - dat += " | "
-
- if("taur" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Taur Body" - - dat += "[features["taur"]]" - - dat += " | "
-
-//Xeno Bodyparts
- if("xenohead" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Head/Caste" - - dat += "[features["xenohead"]]" - - dat += " | "
-
- if("xenotail" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Tail" - - dat += "[features["xenotail"]]" - - dat += " | "
-
- if("xenodorsal" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Dorsal Tubes" - - dat += "[features["xenodorsal"]]" - - dat += " | "
-
- if(config.mutant_humans)
-
- if("tail_human" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Tail" - - dat += "[features["tail_human"]]" - - dat += " | "
-
- if("ears" in pref_species.mutant_bodyparts)
- dat += ""
-
- dat += "Ears" - - dat += "[features["ears"]]" - - dat += " | "
-
- if("wings" in pref_species.mutant_bodyparts && r_wings_list.len >1)
- dat += ""
-
- dat += "Wings" - - dat += "[features["wings"]]" - - dat += " | "
-
- dat += "
| " - - dat += " | "
-
- dat += "Options" - dat += "Arousal:[arousable == TRUE ? "Enabled" : "Disabled"]" - dat += " More Coming Soon(tm)" - - dat += " | "
-
-
- dat += "
"
dat += "General Settings" @@ -546,6 +356,7 @@ var/list/preferences_datums = list() else dat += "High" dat += "" +// dat += "Genital Colors:[features["genitals_use_skintone"] == TRUE ? "Skin Tone" : "Custom"] " dat += " | " @@ -573,6 +384,127 @@ var/list/preferences_datums = list() dat += " |
| "
+ dat += " " + dat += "Set Flavor Text " + if(lentext(flavor_text) <= 40) + if(!lentext(flavor_text)) + dat += "\[...\]" + else + dat += "[flavor_text]" + else + dat += "[TextPreview(flavor_text)]... " + if(config.mutant_races)//really don't need this check, but fuck un-tabbing all those lines + dat += " Body" + dat += "Gender: [gender == MALE ? "Male" : "Female"]" + dat += "Species:[pref_species.id] " + dat += "Random Body " + dat += "Always Random Body: [be_random_body ? "Yes" : "No"] " + if((MUTCOLORS in pref_species.species_traits) || (MUTCOLORS_PARTSONLY in pref_species.species_traits)) + dat += "Primary Color: Change " + dat += "Secondary Color: Change " + dat += "Tertiary Color: Change " + if(pref_species.use_skintones) + dat += "Skin Tone: [skin_tone] " + if(HAIR in pref_species.species_traits) + dat += "Hair Style: [hair_style] " + dat += "Hair Color: Change " + dat += "Facial Hair Style: [facial_hair_style] " + dat += "Facial Hair Color: Change " + if(EYECOLOR in pref_species.species_traits) + dat += "Eye Color: Change " + if("tail_lizard" in pref_species.mutant_bodyparts) + dat += "Tail: [features["tail_lizard"]] " + else if("mam_tail" in pref_species.mutant_bodyparts) + dat += "Tail: [features["mam_tail"]] " + else if("tail_human" in pref_species.mutant_bodyparts) + dat += "Tail: [features["tail_human"]] " + if("snout" in pref_species.mutant_bodyparts) + dat += "Snout: [features["snout"]] " + if("horns" in pref_species.mutant_bodyparts) + dat += "Snout: [features["horns"]] " + if("frills" in pref_species.mutant_bodyparts) + dat += "Frills: [features["frills"]] " + if("spines" in pref_species.mutant_bodyparts) + dat += "Spines: [features["spines"]] " + if("body_markings" in pref_species.mutant_bodyparts) + dat += "Body Markings: [features["body_markings"]] " + else if("mam_body_markings" in pref_species.mutant_bodyparts) + dat += "Body Markings: [features["mam_body_markings"]] " + if("mam_ears" in pref_species.mutant_bodyparts) + dat += "Ears: [features["mam_ears"]] " + else if("ears" in pref_species.mutant_bodyparts) + dat += "Ears: [features["ears"]] " + if("legs" in pref_species.mutant_bodyparts) + dat += "Legs: [features["legs"]] " + if("taur" in pref_species.mutant_bodyparts) + dat += "Taur: [features["taur"]] " + if("wings" in pref_species.mutant_bodyparts && r_wings_list.len >1) + dat += "Wings: [features["wings"]] " + if("xenohead" in pref_species.mutant_bodyparts) + dat += "Caste: [features["xenohead"]] " + if("xenotail" in pref_species.mutant_bodyparts) + dat += "Tail: [features["xenotail"]] " + if("xenodorsal" in pref_species.mutant_bodyparts) + dat += "Dorsal Tubes: [features["xenodorsal"]] " + + dat += " | "
+
+
+ dat += "Clothing & Equipment" +//underwear will be refactored later so it fits in with other wearable equipment and isn't just an overlay +// dat += "Underwear:[underwear]" +// dat += "Undershirt:[undershirt] " +// dat += "Socks:[socks] " + dat += "Backpack:[backbag] " + dat += "Uplink Location:[uplink_spawn_loc] " + + dat += " Genitals" + if(NOGENITALS in pref_species.species_traits) + dat += "Your species ([pref_species.name]) does not support genitals!" + else + dat += "Has Penis:[features["has_cock"] == TRUE ? "Yes" : "No"] " + if(features["has_cock"] == TRUE) + if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) + dat += "Penis Color: (Skin tone overriding) " + else + dat += "Penis Color: Change " +// dat += " " + dat += "Penis Shape: [features["cock_shape"]] " + dat += "Penis Length: [features["cock_length"]] inch(es) " + dat += "Has Testicles:[features["has_balls"] == TRUE ? "Yes" : "No"] " + if(features["has_balls"] == TRUE) + dat += "Testicles Color: Change " + dat += "Has Vagina:[features["has_vag"] == TRUE ? "Yes" : "No"] " + if(features["has_vag"]) + dat += "Vagina Color: Change " + dat += "Has Womb:[features["has_womb"] == TRUE ? "Yes" : "No"] " + dat += "Has Breasts:[features["has_breasts"] == TRUE ? "Yes" : "No"] " + if(features["has_breasts"]) +// if(pref_species.use_skintones) +// dat += "Color: (Skin tone overriding)" +// else +// dat += "Color: Change" + dat += "Cup Size:[features["breasts_size"]] " + /* + dat += " Ovipositor" + dat += "Has Ovipositor:[features["has_ovi"] == TRUE ? "Yes" : "No"]" + if(features["has_ovi"]) + dat += "Ovi Color: Change" + dat += "Eggsack" + dat += "Has Eggsack:[features["has_eggsack"] == TRUE ? "Yes" : "No"]" + if(features["has_eggsack"] == TRUE) + dat += "Color: Change" + dat += "Egg Color: Change" + dat += "Egg Size:[features["eggsack_egg_size"]]\" Diameter" + + dat += " | "
+ */
+
+
+ dat += "