diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 9de0dbe7c5..d23fe74bd2 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -123,6 +123,7 @@ ///from base of [/atom/update_icon]: (signalOut, did_anything) #define COMSIG_ATOM_UPDATED_ICON "atom_updated_icon" #define COMSIG_ATOM_ENTERED "atom_entered" //from base of atom/Entered(): (atom/movable/entering, /atom) +#define COMSIG_ATOM_ENTERING "atom_entering" #define COMSIG_ATOM_EXIT "atom_exit" //from base of atom/Exit(): (/atom/movable/exiting, /atom/newloc) #define COMPONENT_ATOM_BLOCK_EXIT 1 #define COMSIG_ATOM_EXITED "atom_exited" //from base of atom/Exited(): (atom/movable/exiting, atom/newloc) diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index 71586b5093..4e3677f2f9 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -227,6 +227,13 @@ "vag_visibility" = GEN_VISIBLE_NO_UNDIES, "butt_visibility" = GEN_VISIBLE_NO_UNDIES, "belly_visibility" = GEN_VISIBLE_NO_UNDIES, + "cock_stuffing" = FALSE, + "balls_stuffing" = FALSE, + "vag_stuffing" = FALSE, + "breasts_stuffing" = FALSE, + "butt_stuffing" = FALSE, + "belly_stuffing" = FALSE, + "inert_eggs" = FALSE, //Hyper's custom fluids "balls_fluid" = /datum/reagent/consumable/semen, "womb_fluid" = /datum/reagent/consumable/semen/femcum, diff --git a/code/__SPLURTCODE/DEFINES/cit_defines.dm b/code/__SPLURTCODE/DEFINES/cit_defines.dm index ac8bdcc053..a5f60f92ff 100644 --- a/code/__SPLURTCODE/DEFINES/cit_defines.dm +++ b/code/__SPLURTCODE/DEFINES/cit_defines.dm @@ -1,2 +1,10 @@ //Damage stuffs #define LUST_DAMAGE "lust" + +#define GEN_REMOVE_EQUIPMENT "Remove Equipment" +#define GEN_INSERT_EQUIPMENT "Insert Equipment" + +#define GENITAL_CAN_STUFF (1<<14) +#define GEN_ALLOW_EGG_STUFFING "Allows egg stuffing" + +GLOBAL_LIST_INIT(genitals_interactions, list(GEN_REMOVE_EQUIPMENT, GEN_INSERT_EQUIPMENT)) diff --git a/code/__SPLURTCODE/DEFINES/pregnancy.dm b/code/__SPLURTCODE/DEFINES/pregnancy.dm new file mode 100644 index 0000000000..76922580b0 --- /dev/null +++ b/code/__SPLURTCODE/DEFINES/pregnancy.dm @@ -0,0 +1,2 @@ +#define PREGNANCY_STAGES 4 +#define PREGNANCY_STAGE_DURATION 5 MINUTES diff --git a/code/__SPLURTCODE/DEFINES/signals.dm b/code/__SPLURTCODE/DEFINES/signals.dm index 89e7a516c8..43df4522e7 100644 --- a/code/__SPLURTCODE/DEFINES/signals.dm +++ b/code/__SPLURTCODE/DEFINES/signals.dm @@ -1 +1,6 @@ #define COMSIG_MOB_CAME "mob_came" +#define COMSIG_HEALTH_SCAN "health_scan" +#define COMSIG_ORGAN_INSERTED "organ_inserted" +#define COMSIG_ORGAN_REMOVED "organ_removed" +#define COMSIG_MOB_CLIMAX "mob_coomed" +#define COMSIG_OBJ_WRITTEN_ON "written_on" diff --git a/code/__SPLURTCODE/DEFINES/traits.dm b/code/__SPLURTCODE/DEFINES/traits.dm index ca38e795dc..38226680d4 100644 --- a/code/__SPLURTCODE/DEFINES/traits.dm +++ b/code/__SPLURTCODE/DEFINES/traits.dm @@ -1,6 +1,8 @@ #define SLAVER_TRAIT "slaver" +#define PREGNANCY_TRAIT "pregnancy" #define TRAIT_HYPNOTIC_GAZE "Hypnotic Gaze" +#define TRAIT_PREGNANT "pregnant" #define TRAIT_FLOORED "floored" #define IGNORE_FAKE_Z_AXIS "ignore_fake_z_axis" diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 4077f86e52..343d7171b3 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -1099,6 +1099,7 @@ /atom/Entered(atom/movable/AM, atom/oldLoc) SEND_SIGNAL(src, COMSIG_ATOM_ENTERED, AM, oldLoc) + SEND_SIGNAL(AM, COMSIG_ATOM_ENTERING, src, oldLoc) /atom/Exit(atom/movable/AM, atom/newLoc) . = ..() diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm index 0d062b893f..10bb6c9dc5 100644 --- a/code/game/objects/items/devices/scanners.dm +++ b/code/game/objects/items/devices/scanners.dm @@ -463,6 +463,7 @@ GENETICS SCANNER msg += "Detected cybernetic modifications:\n" msg += "[cyberimp_detect]\n" to_chat(user, examine_block(msg)) + SEND_SIGNAL(M, COMSIG_HEALTH_SCAN, user)//SPLURT EDIT ADD - gregnancy SEND_SIGNAL(M, COMSIG_NANITE_SCAN, user, FALSE) /proc/chemscan(mob/living/user, mob/living/M) diff --git a/code/modules/arousal/arousal.dm b/code/modules/arousal/arousal.dm index 42f0933d5f..c4abf94043 100644 --- a/code/modules/arousal/arousal.dm +++ b/code/modules/arousal/arousal.dm @@ -73,11 +73,11 @@ var/condomning if(istype(G, /obj/item/organ/genital/penis)) var/obj/item/organ/genital/penis/P = G - condomning = P.equipment[GENITAL_EQUIPEMENT_CONDOM] + condomning = locate(/obj/item/genital_equipment/condom) in P.contents G.generate_fluid(R) log_message("Climaxed using [G] with [target]", LOG_EMOTE) if(condomning) - to_chat(src, "You feel the condom bubble outwards and fill up with your spunk, plopping on the floor") + to_chat(src, "You feel the condom bubble outwards and fill up with your spunk") R.trans_to(condomclimax(), R.total_volume) else if(spill && R.total_volume >= 5) @@ -121,7 +121,7 @@ to_chat(src,"You climax [(Lgen) ? "in [L]'s [Lgen.name]" : "with [L]"], your [G.name] spilling nothing.") to_chat(L,"[src] climaxes [(Lgen) ? "in your [Lgen.name]" : "with you"], [p_their()] [G.name] spilling nothing!") //SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "orgasm", /datum/mood_event/orgasm) //Sandstorm edit - do_climax(fluid_source, spillage ? loc : L, G, spillage) + do_climax(fluid_source, spillage ? loc : L, G, spillage,, Lgen) //L.receive_climax(src, Lgen, 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 diff --git a/code/modules/arousal/genitals.dm b/code/modules/arousal/genitals.dm index 723903b1a5..b79736461f 100644 --- a/code/modules/arousal/genitals.dm +++ b/code/modules/arousal/genitals.dm @@ -81,7 +81,8 @@ return owner.is_groin_exposed() /obj/item/organ/genital/proc/toggle_visibility(visibility, update = TRUE) - genital_flags &= ~(GENITAL_THROUGH_CLOTHES|GENITAL_HIDDEN|GENITAL_UNDIES_HIDDEN) + if(visibility != GEN_ALLOW_EGG_STUFFING) + genital_flags &= ~(GENITAL_THROUGH_CLOTHES|GENITAL_HIDDEN|GENITAL_UNDIES_HIDDEN) if(owner) owner.exposed_genitals -= src switch(visibility) @@ -101,6 +102,10 @@ genital_flags |= GENITAL_HIDDEN if(owner) owner.log_message("Hid their [src] completely",LOG_EMOTE) + if(GEN_ALLOW_EGG_STUFFING) + TOGGLE_BITFIELD(genital_flags, GENITAL_CAN_STUFF) + if(owner) + owner.log_message("Allowed egg stuffing in their [src]",LOG_EMOTE) if(update && owner && ishuman(owner)) //recast to use update genitals proc var/mob/living/carbon/human/H = owner diff --git a/code/modules/arousal/organs/breasts.dm b/code/modules/arousal/organs/breasts.dm index 425a032946..53892b24d8 100644 --- a/code/modules/arousal/organs/breasts.dm +++ b/code/modules/arousal/organs/breasts.dm @@ -131,6 +131,8 @@ size = breast_values[size] prev_size = cached_size toggle_visibility(D.features["breasts_visibility"], FALSE) + if(D.features["breasts_stuffing"]) + toggle_visibility(GEN_ALLOW_EGG_STUFFING, FALSE) #undef BREASTS_ICON_MIN_SIZE #undef BREASTS_ICON_MAX_SIZE diff --git a/code/modules/arousal/organs/butt.dm b/code/modules/arousal/organs/butt.dm index 09f76e83f0..526bc28ff1 100644 --- a/code/modules/arousal/organs/butt.dm +++ b/code/modules/arousal/organs/butt.dm @@ -91,3 +91,5 @@ prev_size = size size_cached = size toggle_visibility(D.features["butt_visibility"], FALSE) + if(D.features["butt_stuffing"]) + toggle_visibility(GEN_ALLOW_EGG_STUFFING, FALSE) diff --git a/code/modules/arousal/organs/penis.dm b/code/modules/arousal/organs/penis.dm index 2beac2a90a..9e986d9bbb 100644 --- a/code/modules/arousal/organs/penis.dm +++ b/code/modules/arousal/organs/penis.dm @@ -99,3 +99,5 @@ shape = D.features["cock_shape"] prev_length = length toggle_visibility(D.features["cock_visibility"], FALSE) + if(D.features["cock_stuffing"]) + toggle_visibility(GEN_ALLOW_EGG_STUFFING, FALSE) diff --git a/code/modules/arousal/organs/testicles.dm b/code/modules/arousal/organs/testicles.dm index 75ac1aac79..66a29feaaf 100644 --- a/code/modules/arousal/organs/testicles.dm +++ b/code/modules/arousal/organs/testicles.dm @@ -69,3 +69,8 @@ fluid_mult = D.features["balls_cum_mult"] fluid_efficiency = D.features["balls_efficiency"] toggle_visibility(D.features["balls_visibility"], FALSE) + if(D.features["balls_stuffing"]) + toggle_visibility(GEN_ALLOW_EGG_STUFFING, FALSE) + if(D.features["inert_eggs"]) + AddComponent(/datum/component/ovipositor) + diff --git a/code/modules/arousal/organs/vagina.dm b/code/modules/arousal/organs/vagina.dm index 58661bd3ec..2f83e453c3 100644 --- a/code/modules/arousal/organs/vagina.dm +++ b/code/modules/arousal/organs/vagina.dm @@ -74,3 +74,5 @@ color = "[D.features["vag_color"]]" shape = "[D.features["vag_shape"]]" toggle_visibility(D.features["vag_visibility"], FALSE) + if(D.features["vag_stuffing"]) + toggle_visibility(GEN_ALLOW_EGG_STUFFING, FALSE) diff --git a/code/modules/arousal/organs/womb.dm b/code/modules/arousal/organs/womb.dm index 3958a71b14..6b9cf581a3 100644 --- a/code/modules/arousal/organs/womb.dm +++ b/code/modules/arousal/organs/womb.dm @@ -8,3 +8,8 @@ genital_flags = GENITAL_INTERNAL|GENITAL_FUID_PRODUCTION|HAS_EQUIPMENT fluid_id = /datum/reagent/consumable/semen/femcum linked_organ_slot = ORGAN_SLOT_VAGINA + +/obj/item/organ/genital/womb/get_features(mob/living/carbon/human/H) + var/datum/dna/D = H.dna + if(D.features["inert_eggs"]) + AddComponent(/datum/component/ovipositor) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index b46ccd6471..03e16002b7 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -218,6 +218,13 @@ GLOBAL_LIST_EMPTY(preferences_datums) "vag_visibility" = GEN_VISIBLE_NO_UNDIES, "butt_visibility" = GEN_VISIBLE_NO_UNDIES, "belly_visibility" = GEN_VISIBLE_NO_UNDIES, +"cock_stuffing" = FALSE, +"balls_stuffing" = FALSE, +"vag_stuffing" = FALSE, +"breasts_stuffing" = FALSE, +"butt_stuffing" = FALSE, +"belly_stuffing" = FALSE, +"inert_eggs" = FALSE, "ipc_screen" = "Sunburst", "ipc_antenna" = "None", "flavor_text" = "", @@ -361,6 +368,19 @@ GLOBAL_LIST_EMPTY(preferences_datums) var/list/tcg_cards = list() var/list/tcg_decks = list() + //SPLURT EDIT - gregnancy + /// Does john spaceman's cum actually impregnate people? + var/virility = 0 + /// Can john spaceman get gregnant if all conditions are right? (has a womb and is not on contraceptives) + var/fertility = 0 + /// Does john spaceman look like a gluttonous slob if he pregent? + var/pregnancy_inflation = FALSE + /// Self explanitory + var/pregnancy_breast_growth = FALSE + + var/egg_shell = "chicken" + //SPLURT END + /datum/preferences/New(client/C) parent = C @@ -834,6 +854,20 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Lust tolerance:[lust_tolerance]" dat += "Sexual potency:[sexual_potency]" dat += "" + + //SPLURT EDIT BEGIN - gregnancy preferences + dat += "" + dat += "

Pregnancy preferences

" + dat += "Chance of impregnation:[virility ? virility : "Disabled"]" + dat += "Chance of getting pregnant:[fertility ? fertility : "Disabled"]" + dat += "Lay inert eggs:[features["inert_eggs"] == TRUE ? "Enabled" : "Disabled"]" + if(fertility) + dat += "Pregnancy inflation:[pregnancy_inflation ? "Enabled" : "Disabled"]" + dat += "Pregnancy breast growth:[pregnancy_breast_growth ? "Enabled" : "Disabled"]" + if(fertility || features["inert_eggs"]) + dat += "Egg shell:[egg_shell]" + dat += "" + //SPLURT EDIT END dat += APPEARANCE_CATEGORY_COLUMN if(NOGENITALS in pref_species.species_traits) dat += "Your species ([pref_species.name]) does not support genitals!
" @@ -860,6 +894,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Penis Length: [features["cock_length"]] inch(es)" dat += "Diameter Ratio: [features["cock_diameter_ratio"]]" dat += "Penis Visibility:[features["cock_visibility"]]" + dat += "Egg Stuffing:[features["cock_stuffing"] == TRUE ? "Yes" : "No"]" dat += "Has Testicles:[features["has_balls"] == TRUE ? "Yes" : "No"]" if(features["has_balls"]) if(pref_species.use_skintones && features["genitals_use_skintone"] == TRUE) @@ -870,6 +905,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "#[features["balls_color"]] Change
" dat += "Testicles Shape: [features["balls_shape"]]" dat += "Testicles Visibility:[features["balls_visibility"]]" + dat += "Egg Stuffing:[features["balls_stuffing"] == TRUE ? "Yes" : "No"]" dat += "Produces:" var/datum/reagent/balls_fluid = find_reagent_object_from_type(features["balls_fluid"]) if(balls_fluid && (balls_fluid in GLOB.genital_fluids_list)) @@ -889,6 +925,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Vagina Color:
" dat += "#[features["vag_color"]] Change
" dat += "Vagina Visibility:[features["vag_visibility"]]" + dat += "Egg Stuffing:[features["vag_stuffing"] == TRUE ? "Yes" : "No"]" dat += "Has Womb:[features["has_womb"] == TRUE ? "Yes" : "No"]" if(features["has_womb"] == TRUE) dat += "Produces:" @@ -912,6 +949,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Breasts Shape:[features["breasts_shape"]]" dat += "Breasts Visibility:[features["breasts_visibility"]]" dat += "Lactates:[features["breasts_producing"] == TRUE ? "Yes" : "No"]" + dat += "Egg Stuffing:[features["breasts_stuffing"] == TRUE ? "Yes" : "No"]" if(features["breasts_producing"] == TRUE) dat += "Produces:" var/datum/reagent/breasts_fluid = find_reagent_object_from_type(features["breasts_fluid"]) @@ -932,6 +970,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "#[features["butt_color"]] Change
" dat += "Butt Size:[features["butt_size"]]" dat += "Butt Visibility:[features["butt_visibility"]]" + dat += "Egg Stuffing:[features["butt_stuffing"] == TRUE ? "Yes" : "No"]" dat += "" dat += APPEARANCE_CATEGORY_COLUMN dat += "

Belly

" @@ -945,10 +984,11 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "#[features["belly_color"]] Change
" dat += "Belly Size:[features["belly_size"]]" dat += "Belly Visibility:[features["belly_visibility"]]" + dat += "Egg Stuffing:[features["belly_stuffing"] == TRUE ? "Yes" : "No"]" dat += "" if(pref_species.id == SPECIES_DULLAHAN) dat += APPEARANCE_CATEGORY_COLUMN - + dat += "

Neckfire

" dat += "[features["neckfire"] ? "Yes" : "No"]" if(features["neckfire"]) @@ -2047,6 +2087,28 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(user) user.mind?.hide_ckey = hide_ckey + //SPLURT EDIT BEGIN - gregnancy + if("virility") + var/viri = input(user, "Set the chance of you impregnating something (set to 0 to disable). \n(0 = minimum, 100 = maximum)", "Character Preference", virility) as num|null + virility = clamp(viri, 0, 100) + + if("fertility") + var/fert = input(user, "Set the chance of you getting impregnated (set to 0 to disable). \n(0 = minimum, 100 = maximum)", "Character Preference", fertility) as num|null + fertility = clamp(fert, 0, 100) + + if("egg_shell") + var/shell = input(user, "Pick a shell for your eggs", "Character Preferences") as null|anything in GLOB.egg_skins + if(shell) + egg_shell = shell + + if("pregnancy_inflation") + pregnancy_inflation = !pregnancy_inflation + + if("pregnancy_breast_growth") + pregnancy_breast_growth = !pregnancy_breast_growth + + //SPLURT EDIT END + if("hair") var/new_hair = input(user, "Choose your character's hair colour:", "Character Preference","#"+hair_color) as color|null if(new_hair) @@ -2266,7 +2328,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) features["neckfire_color"] = sanitize_hexcolor(new_neckfire_color, 6) else to_chat(user,"Invalid color. Your color is not bright enough.") - + if("ipc_screen") var/new_ipc_screen new_ipc_screen = input(user, "Choose your character's screen:", "Character Preference") as null|anything in GLOB.ipc_screens_list @@ -3145,7 +3207,20 @@ GLOBAL_LIST_EMPTY(preferences_datums) user.client.view_size.setDefault(getScreenSize(widescreenpref)) if("long_strip_menu") long_strip_menu = !long_strip_menu - + if("cock_stuffing") + features["cock_stuffing"] = !features["cock_stuffing"] + if("balls_stuffing") + features["balls_stuffing"] = !features["balls_stuffing"] + if("vag_stuffing") + features["vag_stuffing"] = !features["vag_stuffing"] + if("breasts_stuffing") + features["breasts_stuffing"] = !features["breasts_stuffing"] + if("butt_stuffing") + features["butt_stuffing"] = !features["butt_stuffing"] + if("belly_stuffing") + features["belly_stuffing"] = !features["belly_stuffing"] + if("inert_eggs") + features["inert_eggs"] = !features["inert_eggs"] if("pixel_size") switch(pixel_size) if(PIXEL_SCALING_AUTO) diff --git a/code/modules/client/preferences_savefile.dm b/code/modules/client/preferences_savefile.dm index fdf279c26e..369b6e88d5 100644 --- a/code/modules/client/preferences_savefile.dm +++ b/code/modules/client/preferences_savefile.dm @@ -759,6 +759,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car "vag_visibility" = GEN_VISIBLE_NO_UNDIES, "butt_visibility" = GEN_VISIBLE_NO_UNDIES, "belly_visibility" = GEN_VISIBLE_NO_UNDIES, +"cock_stuffing" = FALSE, +"balls_stuffing" = FALSE, +"vag_stuffing" = FALSE, +"breasts_stuffing" = FALSE, +"butt_stuffing" = FALSE, +"belly_stuffing" = FALSE, +"inert_eggs" = FALSE, "ipc_screen" = "Sunburst", "ipc_antenna" = "None", "flavor_text" = "", @@ -990,6 +997,15 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car S["vore_flags"] >> vore_flags S["vore_taste"] >> vore_taste S["vore_smell"] >> vore_smell + + S["feature_breasts_stuffing"] >> features["breasts_stuffing"] + S["feature_cock_stuffing"] >> features["cock_stuffing"] + S["feature_balls_stuffing"] >> features["balls_stuffing"] + S["feature_vag_stuffing"] >> features["vag_stuffing"] + S["feature_butt_stuffing"] >> features["butt_stuffing"] + S["feature_belly_stuffing"] >> features["belly_stuffing"] + S["feature_inert_eggs"] >> features["inert_eggs"] + var/char_vr_path = "[vr_path]/character_[default_slot]_v2.json" if(fexists(char_vr_path)) var/list/json_from_file = json_decode(file2text(char_vr_path)) @@ -1199,6 +1215,15 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car vore_smell = copytext(vore_smell, 1, MAX_TASTE_LEN) belly_prefs = SANITIZE_LIST(belly_prefs) + //SPLURT EDIT BEGIN - gregnancy + S["virile"] >> virility + S["fertile"] >> fertility + if(S["egg_shell"]) + S["egg_shell"] >> egg_shell + S["pregnancy_inflation"] >> pregnancy_inflation + S["pregnancy_breast_growth"] >> pregnancy_breast_growth + //SPLURT EDIT END + cit_character_pref_load(S) return 1 @@ -1288,12 +1313,14 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["feature_cock_diameter_ratio"], features["cock_diameter_ratio"]) WRITE_FILE(S["feature_cock_taur"], features["cock_taur"]) WRITE_FILE(S["feature_cock_visibility"], features["cock_visibility"]) + WRITE_FILE(S["feature_cock_stuffing"], features["cock_stuffing"]) WRITE_FILE(S["feature_has_balls"], features["has_balls"]) WRITE_FILE(S["feature_balls_color"], features["balls_color"]) WRITE_FILE(S["feature_balls_shape"], features["balls_shape"]) WRITE_FILE(S["feature_balls_size"], features["balls_size"]) WRITE_FILE(S["feature_balls_visibility"], features["balls_visibility"]) + WRITE_FILE(S["feature_balls_stuffing"], features["balls_stuffing"]) WRITE_FILE(S["feature_balls_shape"], features["balls_shape"]) WRITE_FILE(S["feature_balls_fluid"], features["balls_fluid"]) @@ -1304,11 +1331,13 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["feature_breasts_fluid"], features["breasts_fluid"]) WRITE_FILE(S["feature_breasts_producing"], features["breasts_producing"]) WRITE_FILE(S["feature_breasts_visibility"], features["breasts_visibility"]) + WRITE_FILE(S["feature_breasts_stuffing"], features["breasts_stuffing"]) WRITE_FILE(S["feature_has_vag"], features["has_vag"]) WRITE_FILE(S["feature_vag_shape"], features["vag_shape"]) WRITE_FILE(S["feature_vag_color"], features["vag_color"]) WRITE_FILE(S["feature_vag_visibility"], features["vag_visibility"]) + WRITE_FILE(S["feature_vag_stuffing"], features["vag_stuffing"]) WRITE_FILE(S["feature_has_womb"], features["has_womb"]) WRITE_FILE(S["feature_womb_fluid"], features["womb_fluid"]) @@ -1317,11 +1346,15 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car WRITE_FILE(S["feature_butt_color"], features["butt_color"]) WRITE_FILE(S["feature_butt_size"], features["butt_size"]) WRITE_FILE(S["feature_butt_visibility"], features["butt_visibility"]) + WRITE_FILE(S["feature_butt_stuffing"], features["butt_stuffing"]) WRITE_FILE(S["feature_has_belly"], features["has_belly"]) WRITE_FILE(S["feature_belly_color"], features["belly_color"]) WRITE_FILE(S["feature_belly_size"], features["belly_size"]) WRITE_FILE(S["feature_belly_visibility"], features["belly_visibility"]) + WRITE_FILE(S["feature_belly_stuffing"], features["belly_stuffing"]) + + WRITE_FILE(S["feature_inert_eggs"], features["inert_eggs"]) WRITE_FILE(S["feature_neckfire"], features["neckfire"]) WRITE_FILE(S["feature_neckfire_color"], features["neckfire_color"]) @@ -1393,8 +1426,14 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car if(islist(modified_limbs)) WRITE_FILE(S["modified_limbs"] , safe_json_encode(modified_limbs)) WRITE_FILE(S["chosen_limb_id"], chosen_limb_id) - WRITE_FILE(S["headshot"], features["headshot_link"]) //SPLURT edit - + //SPLURT EDIT BEGIN + WRITE_FILE(S["virile"], virility) + WRITE_FILE(S["fertile"], fertility) + WRITE_FILE(S["egg_shell"], egg_shell) + WRITE_FILE(S["pregnancy_inflation"], pregnancy_inflation) + WRITE_FILE(S["pregnancy_breast_growth"], pregnancy_breast_growth) + WRITE_FILE(S["headshot"], features["headshot_link"]) + //SPLURT EDIT END //gear loadout if(length(loadout_data)) diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index cb9570e02f..0bd91c5f35 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -171,6 +171,7 @@ label.apply_label() to_chat(user, "You have successfully renamed \the [oldname] to [O].") O.renamedByPlayer = TRUE + SEND_SIGNAL(O, COMSIG_OBJ_WRITTEN_ON, O.name) //SPLURT EDIT - EGG NAMING if(penchoice == "Change description") var/input = stripped_input(user,"Describe [O] here:", ,"[O.desc]", 350) diff --git a/code/modules/surgery/organs/organ_internal.dm b/code/modules/surgery/organs/organ_internal.dm index d4a2663374..1a600e2cc0 100644 --- a/code/modules/surgery/organs/organ_internal.dm +++ b/code/modules/surgery/organs/organ_internal.dm @@ -62,6 +62,7 @@ owner = M M.internal_organs |= src M.internal_organs_slot[slot] = src + SEND_SIGNAL(src, COMSIG_ORGAN_INSERTED)//SPLURT EDIT ADD - gregnancy moveToNullspace() for(var/X in actions) var/datum/action/A = X @@ -82,6 +83,7 @@ var/datum/action/A = X A.Remove(owner) . = owner //for possible subtypes specific post-removal code. + SEND_SIGNAL(src, COMSIG_ORGAN_REMOVED)//SPLURT EDIT ADD - gregnancy owner = null START_PROCESSING(SSobj, src) diff --git a/code/modules/vending/kinkmate.dm b/code/modules/vending/kinkmate.dm index a84f40f71d..86c9905aee 100644 --- a/code/modules/vending/kinkmate.dm +++ b/code/modules/vending/kinkmate.dm @@ -40,7 +40,8 @@ /obj/item/storage/pill_bottle/butt_enlargement = 10, /obj/item/reagent_containers/glass/bottle/crocin = 10, /obj/item/reagent_containers/glass/bottle/camphor = 5, - /obj/item/storage/daki = 4 + /obj/item/storage/daki = 4, + /obj/item/pregnancytest = 10, ) contraband = list( /obj/item/clothing/neck/petcollar/locked = 2, diff --git a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm index 351037e973..24b0fc0a76 100644 --- a/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm +++ b/modular_citadel/code/modules/reagents/chemistry/reagents/enlargement.dm @@ -101,8 +101,8 @@ W = new W.Insert(M) - if(M.has_quirk(/datum/quirk/infertile)) - M.remove_quirk(/datum/quirk/infertile) + //if(M.has_quirk(/datum/quirk/infertile)) + // M.remove_quirk(/datum/quirk/infertile) return ..() diff --git a/modular_sand/code/datums/interactions/interaction_interface.dm b/modular_sand/code/datums/interactions/interaction_interface.dm index 8b26b6c087..908301d3f5 100644 --- a/modular_sand/code/datums/interactions/interaction_interface.dm +++ b/modular_sand/code/datums/interactions/interaction_interface.dm @@ -97,8 +97,15 @@ visibility = "Always hidden" else visibility = "Hidden by clothes" + + var/extras = "None" + if(CHECK_BITFIELD(genital.genital_flags, GENITAL_CAN_STUFF)) + extras = "Allows egg stuffing" + + genital_entry["extras"] = extras genital_entry["visibility"] = visibility genital_entry["possible_choices"] = GLOB.genitals_visibility_toggles + genital_entry["extra_choices"] = list(GEN_ALLOW_EGG_STUFFING) genitals += list(genital_entry) if(iscarbon(self)) var/simulated_ass = list() @@ -117,6 +124,37 @@ genitals += list(simulated_ass) .["genitals"] = genitals + //Get their genitals + var/list/genital_fluids = list() + var/mob/living/carbon/target_genitals = target || self + if(istype(target_genitals)) + for(var/obj/item/organ/genital/genital in target_genitals.internal_organs) + if(!(CHECK_BITFIELD(genital.genital_flags, GENITAL_FUID_PRODUCTION))) + continue + var/fluids = (clamp(genital.fluid_rate * ((world.time - genital.last_orgasmed) / (10 SECONDS)) * genital.fluid_mult, 0, genital.fluid_max_volume) / genital.fluid_max_volume) + var/list/genital_entry = list() + genital_entry["name"] = "[genital.name]" + genital_entry["key"] = REF(genital) + genital_entry["fluid"] = fluids + genital_fluids += list(genital_entry) + .["genital_fluids"] = genital_fluids + + var/list/genital_interactibles = list() + if(istype(target_genitals)) + for(var/obj/item/organ/genital/genital in target_genitals.internal_organs) + if(!genital.is_exposed()) + continue + var/list/equipment_names = list() + for(var/obj/equipment in genital.contents) + equipment_names += equipment.name + var/list/genital_entry = list() + genital_entry["name"] = "[genital.name]" + genital_entry["key"] = REF(genital) + genital_entry["possible_choices"] = GLOB.genitals_interactions + genital_entry["equipments"] = equipment_names + genital_interactibles += list(genital_entry) + .["genital_interactibles"] = genital_interactibles + var/datum/preferences/prefs = usr?.client.prefs if(prefs) //Getting char prefs @@ -180,6 +218,28 @@ return TRUE else return FALSE + if("genital_interaction") + var/mob/living/carbon/actual_target = target || usr + var/mob/user = usr + var/obj/item/organ/genital/genital = locate(params["genital"], actual_target.internal_organs) + if(!(genital && (genital in actual_target.internal_organs))) + return FALSE + switch(params["action"]) + if(GEN_INSERT_EQUIPMENT) + var/obj/item/stuff = user.get_active_held_item() + if(!istype(stuff)) + to_chat(user, span_warning("You need to hold an item to insert it!")) + return FALSE + stuff.insert_item_organ(user, actual_target, genital) + if(GEN_REMOVE_EQUIPMENT) + var/obj/item/selected_item = input(user, "Pick an item to remove", "Removing item") as null|anything in genital.contents + if(selected_item) + if(!do_mob(user, actual_target, 5 SECONDS)) + return FALSE + if(!user.put_in_hands(selected_item)) + user.transferItemToLoc(get_turf(user)) + return TRUE + return FALSE if("char_pref") var/datum/preferences/prefs = usr.client.prefs var/value = num_to_pref(params["value"]) diff --git a/modular_sand/code/datums/traits/neutral.dm b/modular_sand/code/datums/traits/neutral.dm index bd161be5f4..33cc31da0d 100644 --- a/modular_sand/code/datums/traits/neutral.dm +++ b/modular_sand/code/datums/traits/neutral.dm @@ -11,7 +11,7 @@ var/datum/brain_trauma/severe/hypnotic_stupor/T = new() var/mob/living/carbon/human/H = quirk_holder H.gain_trauma(T, TRAUMA_RESILIENCE_ABSOLUTE) - +/* /datum/quirk/infertile name = "Infertile" desc = "For one reason or another you simply don't seem able to get pregnant, no matter how hard you try." @@ -21,3 +21,4 @@ gain_text = "Your womb starts feeling dry and empty, all the life in it begins to fade away..." lose_text = "You feel the warm blow of life flooding your womb, full of newfound, vibrant fertility!" medical_record_text = "Patient doesn't seem able to ovulate properly..." +*/ diff --git a/modular_sand/code/modules/arousal/arousal.dm b/modular_sand/code/modules/arousal/arousal.dm index 6bab60ae74..6b7df9b07c 100644 --- a/modular_sand/code/modules/arousal/arousal.dm +++ b/modular_sand/code/modules/arousal/arousal.dm @@ -14,7 +14,7 @@ if(LAZYLEN(receivers_list)) var/obj/item/organ/genital/ret_organ = input(src, desc, title, null) as null|obj in receivers_list return ret_organ - +/* /mob/living/proc/receive_climax(mob/living/partner, obj/item/organ/genital/receiver = null, obj/item/organ/genital/source_gen, spill = TRUE) if(!ishuman(src)) return @@ -36,3 +36,4 @@ var/obj/item/organ/genital/breasts/B = h_self.getorganslot(ORGAN_SLOT_BREASTS) if(B) B.fluid_rate *= 2 +*/ diff --git a/modular_splurt/code/_globalvars/lists/pregnancy.dm b/modular_splurt/code/_globalvars/lists/pregnancy.dm new file mode 100644 index 0000000000..c4d3ec6810 --- /dev/null +++ b/modular_splurt/code/_globalvars/lists/pregnancy.dm @@ -0,0 +1,3 @@ +GLOBAL_LIST_INIT(pregnancy_blocked_mob_typecache, typecacheof(list( + /mob/living/simple_animal/hostile/megafauna, +))) diff --git a/modular_splurt/code/datums/components/organ_inflation.dm b/modular_splurt/code/datums/components/organ_inflation.dm new file mode 100644 index 0000000000..b6d3540032 --- /dev/null +++ b/modular_splurt/code/datums/components/organ_inflation.dm @@ -0,0 +1,107 @@ +/datum/component/organ_inflation + dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS + + var/obj/item/organ/container + var/size + +/datum/component/organ_inflation/Initialize(added_size) + if(added_size < 0) + return COMPONENT_INCOMPATIBLE + if(!isitem(parent)) + return COMPONENT_INCOMPATIBLE + + size = added_size + + var/obj/item/thing = parent + + if(istype(thing.loc, /obj/item/organ)) + container = thing.loc + inflate_organ(size) + +/datum/component/organ_inflation/InheritComponent(datum/component/C, i_am_original, _size) + if(!i_am_original) + return + var/old_size = size + if(C) + var/datum/component/organ_inflation/other = C + size += other.size + else + size += _size + + if(abs(size - old_size) > 0 && container) + inflate_organ(size - old_size) + +/datum/component/organ_inflation/RegisterWithParent() + RegisterSignal(parent, COMSIG_ATOM_ENTERING, .proc/on_entering) + if(container) + register_container() + +/datum/component/organ_inflation/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_ATOM_ENTERING) + if(container) + unregister_container() + +/datum/component/organ_inflation/proc/register_container() + RegisterSignal(container, COMSIG_ORGAN_INSERTED, .proc/on_inserted) + RegisterSignal(container, COMSIG_ORGAN_REMOVED, .proc/on_removed) + +/datum/component/organ_inflation/proc/unregister_container() + UnregisterSignal(container, COMSIG_ORGAN_REMOVED) + UnregisterSignal(container, COMSIG_ORGAN_INSERTED) + +/datum/component/organ_inflation/Destroy(force) + if(container) + deflate_organ() + return ..() + +/datum/component/organ_inflation/proc/on_entering(datum/source, atom/destination, atom/oldLoc) + SIGNAL_HANDLER + if(istype(destination, /obj/item/organ)) + container = destination + register_container() + inflate_organ(size) + else if(container) + deflate_organ() + unregister_container() + container = null + +/datum/component/organ_inflation/proc/on_inserted(datum/source) + SIGNAL_HANDLER + inflate_organ(size) + +/datum/component/organ_inflation/proc/on_removed(datum/source) + SIGNAL_HANDLER + deflate_organ() + +/datum/component/organ_inflation/proc/inflate_organ(new_size) + if(!container.owner?.client?.prefs?.pregnancy_inflation) + return + + switch(container.slot) + if(ORGAN_SLOT_PENIS) + var/obj/item/organ/genital/penis/peenus = container.owner.getorganslot(ORGAN_SLOT_PENIS) + peenus?.modify_size(new_size) + if(ORGAN_SLOT_BREASTS) + var/obj/item/organ/genital/breasts/breasts = container.owner.getorganslot(ORGAN_SLOT_BREASTS) + breasts?.modify_size(new_size) + else + var/obj/item/organ/genital/belly/belly = container.owner.getorganslot(ORGAN_SLOT_BELLY) + if(!belly && ishuman(container.owner)) + var/mob/living/carbon/human/human_owner = container.owner + belly = human_owner.give_genital(/obj/item/organ/genital/belly) + belly?.modify_size(new_size) + +/datum/component/organ_inflation/proc/deflate_organ() + if(!container.owner) + return + + switch(container.slot) + if(ORGAN_SLOT_PENIS) + var/obj/item/organ/genital/penis/peenus = container.owner.getorganslot(ORGAN_SLOT_PENIS) + peenus?.modify_size(-size) + if(ORGAN_SLOT_BREASTS) + var/obj/item/organ/genital/breasts/breasts = container.owner.getorganslot(ORGAN_SLOT_BREASTS) + breasts?.modify_size(-size) + else + var/obj/item/organ/genital/belly/belly = container.owner.getorganslot(ORGAN_SLOT_BELLY) + belly?.modify_size(-size) diff --git a/modular_splurt/code/datums/components/pregnancy.dm b/modular_splurt/code/datums/components/pregnancy.dm new file mode 100644 index 0000000000..b39ae2d179 --- /dev/null +++ b/modular_splurt/code/datums/components/pregnancy.dm @@ -0,0 +1,485 @@ +/datum/component/pregnancy + + dupe_mode = COMPONENT_DUPE_UNIQUE + //can_transfer = TRUE + + /// type of baby the mother will plop out - needs to be subtype of /mob/living + var/baby_type = /mob/living/carbon/human + + var/obj/item/organ/container + var/mob/living/carrier + + var/datum/dna/father_dna + var/datum/dna/mother_dna + + var/list/mother_features + var/list/father_features + + var/egg_name + + var/stage = 0 + var/max_stage = PREGNANCY_STAGES + COOLDOWN_DECLARE(stage_time) + + var/added_size = 0 + /// this boolean is for identifying whether this preg is in the egg state or not + var/oviposition = TRUE + /// this boolean is for saving whether or not we should inflate the belly if appropriate + var/pregnancy_inflation = TRUE + /// breast growth + var/pregnancy_breast_growth = TRUE + /// whether the pregnancy is revealed or not, scanners will reveal this no matter what + var/revealed = FALSE + +/datum/component/pregnancy/Initialize(mob/living/_mother, mob/living/_father, _baby_type = /mob/living/carbon/human) + if(!isobj(parent)) + return COMPONENT_INCOMPATIBLE + + var/obj/item/thing = parent + + if(!isorgan(thing.loc)) + return COMPONENT_INCOMPATIBLE + + if(ispath(_baby_type, /mob/living)) + baby_type = _baby_type + else + stack_trace("Invalid baby_type given to pregnancy component!") + return COMPONENT_INCOMPATIBLE + + container = thing.loc + + var/obj/item/organ/nads = thing.loc + + if(nads.owner) + carrier = nads.owner + + if(iscarbon(_father)) + var/mob/living/carbon/cardad = _father + father_dna = new + cardad.dna.copy_dna(father_dna) + + if(iscarbon(_mother)) + var/mob/living/carbon/carmom = _mother + mother_dna = new + carmom.dna.copy_dna(mother_dna) + + if(ishuman(_father)) + var/mob/living/carbon/human/cardad = _father + LAZYINITLIST(father_features) + father_features["skin_tone"] = cardad.skin_tone + father_features["hair_color"] = cardad.hair_color + father_features["facial_hair_color"] = cardad.facial_hair_color + father_features["left_eye_color"] = cardad.left_eye_color + father_features["right_eye_color"] = cardad.right_eye_color + + if(ishuman(_mother)) + var/mob/living/carbon/human/carmom = _mother + LAZYINITLIST(mother_features) + mother_features["skin_tone"] = carmom.skin_tone + mother_features["hair_color"] = carmom.hair_color + mother_features["facial_hair_color"] = carmom.facial_hair_color + mother_features["left_eye_color"] = carmom.left_eye_color + mother_features["right_eye_color"] = carmom.right_eye_color + + pregnancy_inflation = carrier?.client?.prefs?.pregnancy_inflation + + pregnancy_breast_growth = carrier?.client?.prefs?.pregnancy_breast_growth + + if(carrier) + generic_pragency_start() + ADD_TRAIT(carrier, TRAIT_PREGNANT, PREGNANCY_TRAIT) + +/datum/component/pregnancy/RegisterWithParent() + if(carrier) + register_carrier() + RegisterSignal(parent, COMSIG_ATOM_ENTERING, .proc/on_entering) + RegisterSignal(parent, COMSIG_OBJ_BREAK, .proc/on_obj_break) + RegisterSignal(parent, COMSIG_OBJ_WRITTEN_ON, .proc/name_egg) + RegisterSignal(parent, COMSIG_PARENT_ATTACKBY, .proc/hatch) + RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/eg_status) + +/datum/component/pregnancy/UnregisterFromParent() + if(carrier) + unregister_carrier() + UnregisterSignal(parent, COMSIG_ATOM_ENTERING) + UnregisterSignal(parent, COMSIG_OBJ_BREAK) + UnregisterSignal(parent, COMSIG_OBJ_WRITTEN_ON) + UnregisterSignal(parent, COMSIG_PARENT_ATTACKBY) + UnregisterSignal(parent, COMSIG_PARENT_EXAMINE) + +/datum/component/pregnancy/proc/register_carrier() + RegisterSignal(carrier, COMSIG_MOB_DEATH, .proc/fetus_mortus) + RegisterSignal(carrier, COMSIG_LIVING_BIOLOGICAL_LIFE, .proc/handle_life) + RegisterSignal(carrier, COMSIG_HEALTH_SCAN, .proc/on_scan) + RegisterSignal(carrier, COMSIG_MOB_APPLY_DAMAGE, .proc/handle_damage) + if(oviposition) + RegisterSignal(carrier, COMSIG_MOB_CLIMAX, .proc/on_climax) + +/datum/component/pregnancy/proc/unregister_carrier() + UnregisterSignal(carrier, COMSIG_MOB_DEATH) + UnregisterSignal(carrier, COMSIG_LIVING_BIOLOGICAL_LIFE) + UnregisterSignal(carrier, COMSIG_HEALTH_SCAN) + UnregisterSignal(carrier, COMSIG_MOB_APPLY_DAMAGE) + UnregisterSignal(carrier, COMSIG_MOB_CLIMAX) + +/datum/component/pregnancy/Destroy() + if(carrier) + generic_pragency_end() + return ..() +/* +/datum/component/pregnancy/PreTransfer() + if(carrier) + generic_pragency_end() + oviposition = FALSE + +/datum/component/pregnancy/PostTransfer() + carrier = null + container = null + egg_name = null + + if(isliving(parent)) + carrier = parent + else if(isitem(parent)) + max_stage += 1 + else + return COMPONENT_INCOMPATIBLE +*/ + +/datum/component/pregnancy/proc/name_egg(datum/source, name) + SIGNAL_HANDLER + + egg_name = name + +/datum/component/pregnancy/proc/on_climax(datum/source, datum/reagents/senders_cum, atom/target, obj/item/organ/genital/sender, obj/item/organ/genital/receiver, spill) + SIGNAL_HANDLER + + if(isgenital(container)) + var/obj/item/organ/genital/stuff = container + if(stuff != sender && stuff.linked_organ != sender) + return FALSE + + if(stage < 2) + return FALSE + + if(receiver && isliving(target)) + if(CHECK_BITFIELD(receiver.genital_flags, GENITAL_CAN_STUFF)) + return lay_eg(receiver, senders_cum) + return lay_eg(get_turf(carrier), senders_cum) + +/datum/component/pregnancy/proc/on_obj_break(datum/source, damage_flag) + SIGNAL_HANDLER + + qdel(src) + +/datum/component/pregnancy/proc/on_entering(datum/source, atom/destination, atom/oldLoc) + SIGNAL_HANDLER + + if(istype(destination, /obj/item/organ)) + var/obj/item/organ/preg_container = destination + //severed wombs don't count, boyos + if(!preg_container.owner) + return + carrier = preg_container.owner + container = preg_container + pregnancy_inflation = carrier.client?.prefs?.pregnancy_inflation + pregnancy_breast_growth = carrier.client?.prefs?.pregnancy_breast_growth + register_carrier() + generic_pragency_start() + else if(carrier) + generic_pragency_end() + unregister_carrier() + carrier = null + container = null + +/datum/component/pregnancy/proc/handle_life(seconds) + SIGNAL_HANDLER + + if(oviposition) + handle_ovi_preg() + else + handle_incubation() + + if((stage >= 2) && !revealed) + revealed = TRUE + carrier.apply_status_effect(/datum/status_effect/pregnancy) + + if(stage > 3 && ishuman(carrier) && oviposition) + SEND_SIGNAL(carrier, COMSIG_ADD_MOOD_EVENT, "pregnancy", /datum/mood_event/pregnant_negative) + + if(COOLDOWN_FINISHED(src, stage_time)) + stage += 1 + stage = min(stage, max_stage) + if(ishuman(carrier) && stage >= 2) + inflate_organs(carrier) + COOLDOWN_START(src, stage_time, PREGNANCY_STAGE_DURATION) + +/datum/component/pregnancy/proc/inflate_organs(mob/living/carbon/human/gregnant) + //var/obj/item/organ/genital/belly/belly = gregnant.getorganslot(ORGAN_SLOT_BELLY) + var/obj/item/organ/genital/breasts/boob = gregnant.getorganslot(ORGAN_SLOT_BREASTS) + + if(added_size < 4) + added_size += 1 + else + return + parent.AddComponent(/datum/component/organ_inflation, 1) + //if(pregnancy_inflation) + // belly?.modify_size(1) + if(pregnancy_breast_growth) + boob?.modify_size(1) + +/datum/component/pregnancy/proc/handle_incubation() + if(carrier && (stage < max_stage) && prob(2)) + to_chat(carrier, span_warning("You feel \The [parent] moving a bit inside you!")) + if(carrier && (stage == max_stage) && prob(2)) + to_chat(carrier, span_warning("\The [parent] moves, it's probably ready to hatch!")) + +/datum/component/pregnancy/proc/hatch(datum/source, obj/item/I, mob/user, params) + SIGNAL_HANDLER + + if(stage < max_stage) + return + + playsound(parent, 'sound/effects/splat.ogg', 70, TRUE) + var/mob/living/babby = new baby_type(get_turf(parent)) + if(ishuman(babby)) + determine_baby_features(babby) + determine_baby_dna(babby) + INVOKE_ASYNC(GLOBAL_PROC, .proc/offer_control_to_babby, babby, user, egg_name) + var/obj/item = parent + item.forceMove(get_turf(parent)) + item.obj_break(MELEE) + qdel(src) + +/datum/component/pregnancy/proc/eg_status(datum/source, mob/user, list/examine_list) + SIGNAL_HANDLER + + if(stage >= max_stage) + examine_list += span_notice("\The [parent] seems ready to hatch! You can tap it with something to hatch it") + +///datum/component/pregnancy/proc/handle_preg() +// +// if(prob(60)) +// return +// if(stage < max_stage) +// return +// +// if(prob(50)) +// to_chat(carrier, span_warning("Something is moving inside you!")) +// else +// to_chat(carrier, span_userdanger("It hurts! Something is trying to come out!")) +// +// carrier.emote("scream") +// +// var/can_birth = TRUE +// if(ishuman(carrier)) +// var/mob/living/carbon/human/human_owner = carrier +// var/obj/item/bodypart/chest = human_owner.get_bodypart(BODY_ZONE_CHEST) +// if(LAZYLEN(human_owner.clothingonpart(chest))) +// can_birth = FALSE +// if(can_birth) +// playsound(carrier, 'sound/effects/splat.ogg', 70, TRUE) +// to_chat(carrier, span_nicegreen("The egg hatched!")) +// carrier.Knockdown(200, TRUE, TRUE) +// carrier.Stun(200, TRUE, TRUE) +// carrier.adjustStaminaLoss(200) +// var/mob/living/babby = new baby_type(get_turf(carrier)) +// if(ishuman(babby)) +// determine_baby_dna(babby) +// INVOKE_ASYNC(GLOBAL_PROC, .proc/offer_control_to_babby, babby, carrier, egg_name) +// SEND_SIGNAL(carrier, COMSIG_ADD_MOOD_EVENT, "pregnancy_end", /datum/mood_event/pregnant_positive) +// if(isitem(parent)) +// var/obj/item = parent +// item.forceMove(get_turf(carrier)) +// item.obj_break(MELEE) +// qdel(src) + +/datum/component/pregnancy/proc/handle_ovi_preg() + if(stage <= 2) + if(stage == 2 && prob(2)) + to_chat(carrier, span_notice("You feel something pressing lightly inside")) + return + if(prob(10)) + if(prob(50)) + to_chat(carrier, span_warning("Something presses hard against your anus! It's probably your egg!")) + else + to_chat(carrier, span_warning("You REALLY need to get this egg out!")) + carrier.emote("scream") + carrier.adjustStaminaLoss(15) + + lay_eg(get_turf(carrier)) + +/datum/component/pregnancy/proc/lay_eg(atom/location, datum/reagents/senders_cum) + to_chat(carrier, span_userlove("You feel your egg sliding slowly inside!")) + + if(prob(60)) + return FALSE + if(isorgan(location)) + var/obj/item/organ/recv = location + + if(!recv.owner) + return FALSE + + if(container && isgenital(container)) + var/obj/item/organ/genital/gen = container + if(!(gen.is_exposed() || gen.linked_organ?.is_exposed())) + return FALSE + + var/obj/item/oviposition_egg/eggo = parent + + eggo.icon_state = carrier.client?.prefs?.egg_shell ? ("egg_" + carrier.client.prefs.egg_shell) : "egg_chicken" + eggo.update_appearance() + + if(isorgan(location)) + var/obj/item/organ/recv = location + carrier.visible_message(span_userlove("[carrier] laid an egg!"), \ + span_userlove("You laid an egg inside [recv.owner]'s [recv]")) + else + carrier.visible_message(span_notice("[carrier] laid an egg!"), \ + span_nicegreen("The egg came out!")) + + if(senders_cum?.total_volume > 5) + senders_cum.reaction(location, TOUCH, 1, 0) + + playsound(carrier, 'sound/effects/splat.ogg', 70, TRUE) + carrier.Knockdown(200, TRUE, TRUE) + carrier.Stun(200, TRUE, TRUE) + carrier.adjustStaminaLoss(200) + SEND_SIGNAL(carrier, COMSIG_ADD_MOOD_EVENT, "pregnancy_end", /datum/mood_event/pregnant_positive) + + oviposition = FALSE + eggo.forceMove(location) + + return TRUE + +//not how genetics work but okay +/datum/component/pregnancy/proc/determine_baby_dna(mob/living/carbon/human/babby) + if(mother_dna && father_dna) + mother_dna.transfer_identity_random(father_dna, babby) + else if(mother_dna && !father_dna) + mother_dna.transfer_identity_random(babby.dna, babby) + else if(!mother_dna && father_dna) + father_dna.transfer_identity_random(babby.dna, babby) + +/datum/component/pregnancy/proc/determine_baby_features(mob/living/carbon/human/babby) + + var/list/final_features = list() + + transfer_randomized_list(final_features, mother_features, father_features) + + if(final_features["skin_tone"]) + babby.skin_tone = final_features["skin_tone"] + if(final_features["hair_color"]) + babby.hair_color = final_features["hair_color"] + if(final_features["facial_hair_color"]) + babby.facial_hair_color = final_features["facial_hair_color"] + if(final_features["left_eye_color"]) + babby.left_eye_color = final_features["left_eye_color"] + if(final_features["right_eye_color"]) + babby.right_eye_color = final_features["right_eye_color"] + + babby.hair_style = pick("Bedhead", "Bedhead 2", "Bedhead 3") + babby.facial_hair_style = "Shaved" + babby.underwear = "Nude" + babby.undershirt = "Nude" + babby.socks = "Nude" + + babby.saved_underwear = babby.underwear + babby.saved_undershirt = babby.undershirt + babby.saved_socks = babby.socks + +/datum/component/pregnancy/proc/generic_pragency_start() + if(revealed) + carrier.apply_status_effect(/datum/status_effect/pregnancy) + if(ishuman(carrier)) + human_pragency_start(carrier) + ADD_TRAIT(carrier, TRAIT_PREGNANT, PREGNANCY_TRAIT) + +/datum/component/pregnancy/proc/generic_pragency_end() + REMOVE_TRAIT(carrier, TRAIT_PREGNANT, PREGNANCY_TRAIT) + carrier.remove_status_effect(/datum/status_effect/pregnancy) + if(ishuman(carrier)) + human_pragency_end(carrier) + +/datum/component/pregnancy/proc/human_pragency_start(mob/living/carbon/human/gregnant) + /* + if(pregnancy_inflation) + //give them a king ass ripper belly initially + var/obj/item/organ/genital/belly/belly = gregnant.getorganslot(ORGAN_SLOT_BELLY) + if(!belly) + belly = gregnant.give_genital(/obj/item/organ/genital/belly) + if(added_size > 0) + belly.modify_size(added_size) + */ + if(pregnancy_breast_growth) + var/obj/item/organ/genital/breasts/boob = gregnant.getorganslot(ORGAN_SLOT_BREASTS) + if(!boob) + boob = gregnant.give_genital(/obj/item/organ/genital/breasts) + return TRUE + +/datum/component/pregnancy/proc/human_pragency_end(mob/living/carbon/human/gregnant) + /* + //get rid of king ass ripper belly + var/obj/item/organ/genital/belly/belly = gregnant.getorganslot(ORGAN_SLOT_BELLY) + if(pregnancy_inflation) + belly?.modify_size(-added_size) + */ + SEND_SIGNAL(gregnant, COMSIG_CLEAR_MOOD_EVENT, "pregnancy") + +/datum/component/pregnancy/proc/fetus_mortus() + SIGNAL_HANDLER + + if(!QDELETED(carrier) && get_turf(carrier) && (stage >= 2)) + if(!oviposition) + new /obj/effect/gibspawner/generic(get_turf(carrier)) + else + new /obj/effect/decal/cleanable/egg_smudge(get_turf(carrier)) + carrier.Knockdown(200, TRUE, TRUE) + carrier.Stun(200, TRUE, TRUE) + carrier.adjustStaminaLoss(200) + carrier.visible_message(span_danger("[carrier] has a miscarriage!"), \ + span_userdanger("Oh no! My baby is dead!")) + qdel(src) + +/datum/component/pregnancy/proc/on_scan(datum/source, mob/user) + SIGNAL_HANDLER + to_chat(user, span_notice("Pregnancy detected!")) + +//drop kicked +/datum/component/pregnancy/proc/handle_damage(datum/source, damage, damagetype, def_zone) + SIGNAL_HANDLER + + if(def_zone == BODY_ZONE_CHEST && damage > 20 && prob(40)) + fetus_mortus() + +/proc/offer_control_to_babby(mob/living/babby, mob/living/mommy, pre_named) + var/poll_message = "Do you want to play as [mommy]'s offspring?" + var/list/mob/candidates = pollCandidatesForMob(poll_message, ROLE_RESPAWN, null, FALSE, 120, babby) + if(!LAZYLEN(candidates)) + babby.real_name = random_unique_name(babby.gender) + babby.update_name() + return + + var/mob/player = pick(candidates) + + player.transfer_ckey(babby, TRUE) + + var/mommy_name = "someone" + if(!QDELETED(mommy)) + mommy_name = mommy.real_name + + to_chat(babby, "You are the son (or daughter) of [mommy_name]!") + + var/name + if(pre_named) + name = pre_named + else if(QDELETED(mommy)) + name = input(babby, "What will be your name?", "Name yourself") as null|text + else + name = input(mommy, "What will be your baby's name?", "Name the baby") as null|text + + if(!name) + babby.real_name = random_unique_name(babby.gender, ) + babby.update_name() + else + babby.real_name = name + babby.update_name() diff --git a/modular_splurt/code/datums/components/pregnancy_inert.dm b/modular_splurt/code/datums/components/pregnancy_inert.dm new file mode 100644 index 0000000000..ccbccf6968 --- /dev/null +++ b/modular_splurt/code/datums/components/pregnancy_inert.dm @@ -0,0 +1,121 @@ +#define EGG_STAGE_TIME 2 MINUTES + +/datum/component/ovipositor + dupe_mode = COMPONENT_DUPE_UNIQUE + + var/egg_type = "chicken" + var/mob/living/carrier + + var/egg_stage = 0 + var/eggs_stored = 1 + COOLDOWN_DECLARE(egg_timer) + +/datum/component/ovipositor/Initialize() + if(!isgenital(parent)) + return COMPONENT_INCOMPATIBLE + + var/obj/item/organ/genital = parent + + carrier = genital.owner + +/datum/component/ovipositor/RegisterWithParent() + RegisterSignal(parent, COMSIG_ORGAN_INSERTED, .proc/on_inserted) + RegisterSignal(parent, COMSIG_ORGAN_REMOVED, .proc/on_removed) + if(carrier) + register_carrier() + egg_type = carrier?.client?.prefs?.egg_shell ? carrier.client.prefs.egg_shell : "chicken" + +/datum/component/ovipositor/proc/register_carrier() + RegisterSignal(carrier, COMSIG_LIVING_BIOLOGICAL_LIFE, .proc/handle_life) + RegisterSignal(carrier, COMSIG_MOB_CLIMAX, .proc/on_climax) + +/datum/component/ovipositor/proc/unregister_carrier() + UnregisterSignal(carrier, COMSIG_LIVING_BIOLOGICAL_LIFE) + UnregisterSignal(carrier, COMSIG_MOB_CLIMAX) + +/datum/component/ovipositor/proc/on_inserted(datum/source) + SIGNAL_HANDLER + + var/obj/item/organ/genital/gen = parent + + if(gen.owner) + carrier = gen.owner + register_carrier() + +/datum/component/ovipositor/proc/on_removed(datum/source) + SIGNAL_HANDLER + + var/obj/item/organ/genital/gen = parent + + if(gen.owner) + unregister_carrier() + carrier = null + +/datum/component/ovipositor/proc/handle_life(seconds) + SIGNAL_HANDLER + + if(COOLDOWN_FINISHED(src, egg_timer)) + egg_stage += 1 + egg_stage = min(2, egg_stage) + COOLDOWN_START(src, egg_timer, EGG_STAGE_TIME) + + if(egg_stage == 2) + egg_stage = 0 + eggs_stored += 1 + eggs_stored = min(3, eggs_stored) + +/datum/component/ovipositor/proc/on_climax(datum/source, datum/reagents/senders_cum, atom/target, obj/item/organ/genital/sender, obj/item/organ/genital/receiver, spill) + SIGNAL_HANDLER + + var/obj/item/organ/genital/stuff = parent + if(stuff != sender && stuff.linked_organ != sender) + return FALSE + + if(eggs_stored <= 0) + return FALSE + + if(receiver && isliving(target)) + if(CHECK_BITFIELD(receiver.genital_flags, GENITAL_CAN_STUFF)) + return lay_eg(receiver, senders_cum) + return lay_eg(get_turf(carrier), senders_cum) + +/datum/component/ovipositor/proc/lay_eg(atom/location, datum/reagents/senders_cum) + to_chat(carrier, span_userlove("You feel your egg sliding slowly inside!")) + + if(prob(30)) + return FALSE + + if(isorgan(location)) + var/obj/item/organ/recv = location + + if(!recv.owner) + return FALSE + + var/obj/item/organ/genital/gen = parent + if(!(gen.is_exposed() || gen.linked_organ?.is_exposed())) + return FALSE + + var/obj/item/oviposition_egg/eggo = new(carrier) + + eggo.AddComponent(/datum/component/organ_inflation, 2) + + eggo.icon_state = "egg_" + egg_type + eggo.update_appearance() + + if(isorgan(location)) + var/obj/item/organ/recv = location + carrier.visible_message(span_userlove("[carrier] laid an egg!"), \ + span_userlove("You laid an egg inside [recv.owner]'s [recv]")) + else + carrier.visible_message(span_notice("[carrier] laid an egg!"), \ + span_nicegreen("The egg came out!")) + + playsound(carrier, 'sound/effects/splat.ogg', 70, TRUE) + + if(senders_cum?.total_volume > 5) + senders_cum.reaction(location, TOUCH, 1, 0) + + eggo.forceMove(location) + eggs_stored -= 1 + + return TRUE diff --git a/modular_splurt/code/datums/dna.dm b/modular_splurt/code/datums/dna.dm index 27f4c32c80..1bccb678b2 100644 --- a/modular_splurt/code/datums/dna.dm +++ b/modular_splurt/code/datums/dna.dm @@ -56,3 +56,61 @@ var/healthchange = healthmod_new - healthmod_old //Get ready to apply the new value, and subtract the old one. (Negative values become positive) holder.maxHealth += healthchange holder.health += healthchange + +#define TRANSFER_RANDOMIZED(destination, source1, source2) \ + if(prob(50)) { \ + destination = source1; \ + } else { \ + destination = source2; \ + } + +/proc/transfer_randomized_list(list/destination, list/list1, list/list2) + if(list1.len >= list2.len) + for(var/key1 as anything in list1) + var/val1 = list1[key1] + var/val2 = list2[key1] + if(prob(50) && val1) + destination[key1] = val1 + else if(val2) + destination[key1] = val2 + else + for(var/key2 as anything in list2) + var/val1 = list1[key2] + var/val2 = list2[key2] + if(prob(50) && val1) + destination[key2] = val1 + else if(val2) + destination[key2] = val2 + +/datum/dna/proc/transfer_identity_random(datum/dna/second_set, mob/living/carbon/destination) + if(!istype(destination)) + return + var/old_size = destination.dna.features["body_size"] + + TRANSFER_RANDOMIZED(destination.dna.blood_type, blood_type, second_set.blood_type) + TRANSFER_RANDOMIZED(destination.dna.skin_tone_override, skin_tone_override, second_set.skin_tone_override) + transfer_randomized_list(destination.dna.features, features, second_set.features) + transfer_randomized_list(destination.dna.temporary_mutations, temporary_mutations, second_set.temporary_mutations) + + if(prob(50)) + destination.set_species(species.type, FALSE) + destination.dna.species.say_mod = species.say_mod + destination.dna.custom_species = custom_species + else + destination.set_species(second_set.species.type, FALSE) + destination.dna.species.say_mod = second_set.species.say_mod + destination.dna.custom_species = second_set.custom_species + + destination.update_size(get_size(destination), old_size) + + destination.dna.update_dna_identity() + destination.dna.generate_dna_blocks() + + if(ishuman(destination)) + var/mob/living/carbon/human/H = destination + H.give_genitals(TRUE)//This gives the body the genitals of this DNA. Used for any transformations based on DNA + H.update_genitals() + + destination.updateappearance(icon_update=TRUE, mutcolor_update=TRUE, mutations_overlay_update=TRUE) + +#undef TRANSFER_RANDOMIZED diff --git a/modular_splurt/code/datums/interactions/lewd/_lewd.dm b/modular_splurt/code/datums/interactions/lewd/_lewd.dm index 85fabb32bf..4e0c5aca76 100644 --- a/modular_splurt/code/datums/interactions/lewd/_lewd.dm +++ b/modular_splurt/code/datums/interactions/lewd/_lewd.dm @@ -380,6 +380,8 @@ visible_message(message = "\The [src] [message]", ignored_mobs = get_unconsenting()) handle_post_sex(NORMAL_LUST, CUM_TARGET_BREASTS, user) +/* + /mob/living/proc/remove_equipment(mob/living/carbon/target) var/obj/item/organ/genital/holder = pick_receiving_organ(target, HAS_EQUIPMENT, "Remove equipment", "What genital?") if(!holder) @@ -393,6 +395,8 @@ if(gimme) holder.remove_equipment(src, gimme) +*/ + /mob/living/proc/nuzzle_belly(mob/living/target) var/message var/u_His = p_their() diff --git a/modular_splurt/code/datums/interactions/lewd/lewd_datums.dm b/modular_splurt/code/datums/interactions/lewd/lewd_datums.dm index c11b335955..828f4dbebe 100644 --- a/modular_splurt/code/datums/interactions/lewd/lewd_datums.dm +++ b/modular_splurt/code/datums/interactions/lewd/lewd_datums.dm @@ -443,35 +443,6 @@ playlewdinteractionsound(target, 'sound/items/bikehorn.ogg', 40, 1, -1) -/datum/interaction/lewd/remove_self_equipment - description = "Remove your genital's equipment" - require_user_hands = TRUE - interaction_sound = null - max_distance = 0 - user_is_target = TRUE - write_log_user = "messed with their genital equipment" - write_log_target = null - user_is_target = TRUE - -/datum/interaction/lewd/remove_self_equipment/display_interaction(mob/living/user) - if(!iscarbon(user)) - to_chat(user, "You don't seem like someone who'd use cock equipment my dude") - return - user.remove_equipment(user) - -/datum/interaction/lewd/remove_other_equipment - description = "Remove their genital's equipment" - require_user_hands = TRUE - interaction_sound = null - max_distance = 1 - write_log_user = null - write_log_target = "got their genital's equipment edited by" - -/datum/interaction/lewd/remove_other_equipment/display_interaction(mob/living/user, mob/living/target) - if(!iscarbon(target)) - to_chat(user, "[target.p_they()] don't look like someone who'd use balls equipment") - user.remove_equipment(target) - /datum/interaction/lewd/deflate_belly description = "Deflate belly" require_user_belly = REQUIRE_EXPOSED diff --git a/modular_splurt/code/datums/mood_events/preg_events.dm b/modular_splurt/code/datums/mood_events/preg_events.dm new file mode 100644 index 0000000000..35dcadfcd4 --- /dev/null +++ b/modular_splurt/code/datums/mood_events/preg_events.dm @@ -0,0 +1,8 @@ +/datum/mood_event/pregnant_negative + description = "THE BABY IS COMING OUT...\n" + mood_change = -7 + +/datum/mood_event/pregnant_positive + description = "The baby came out...phew\n" + mood_change = 3 + timeout = 2 MINUTES diff --git a/modular_splurt/code/datums/status_effects/pregnancy.dm b/modular_splurt/code/datums/status_effects/pregnancy.dm new file mode 100644 index 0000000000..b5bc6e7714 --- /dev/null +++ b/modular_splurt/code/datums/status_effects/pregnancy.dm @@ -0,0 +1,16 @@ +/** + * Who is the liar but he who denies that Jesus is the Christ? This is the antichrist, he who denies the Father and the Son. + * - John 2:22 + */ +/atom/movable/screen/alert/status_effect/pregnancy + name = "Pregnant" + desc = "Welp, you sure are pregnant." + icon = 'modular_splurt/icons/mob/screen_alert.dmi' + icon_state = "baby" + +/datum/status_effect/pregnancy + id = "pregnancy" + duration = -1 + tick = FALSE + alert_type = /atom/movable/screen/alert/status_effect/pregnancy + diff --git a/modular_splurt/code/game/object/items.dm b/modular_splurt/code/game/object/items.dm new file mode 100644 index 0000000000..b45807289f --- /dev/null +++ b/modular_splurt/code/game/object/items.dm @@ -0,0 +1,129 @@ +/obj/item/proc/insert_item_organ(mob/living/carbon/user, mob/living/carbon/target, obj/item/organ/genital/target_organ) + to_chat(user, span_warning("You can't insert this item!")) + return + +/obj/item/genital_equipment/condom/insert_item_organ(mob/living/carbon/user, mob/living/carbon/target, obj/item/organ/genital/target_organ) + if(!(target.client?.prefs?.erppref == "Yes")) + to_chat(user, span_warning("They don't want you to do that!")) + return + + if(!unwrapped) + to_chat(user, span_notice("You must remove the condom from the package first!")) + return + + var/obj/item/organ/genital/penis/ween = target_organ + if(!istype(ween)) + to_chat(user, span_notice("You can't put the condom on this genital!")) + return + + if(!target.has_penis(REQUIRE_EXPOSED)) + to_chat(user, span_notice("You can't find anywhere to put the condom!")) + return + + if(locate(src.type) in target_organ.contents) + to_chat(user, span_notice("\The [target] is already wearing a condom!")) + return + + target.visible_message(span_warning("\The [user] is trying to put a condom on \the [target]!"),\ + span_warning("\The [user] is trying to put a condom on you!")) + + if(!do_mob(user, target, 4 SECONDS)) + return + + if(!user.transferItemToLoc(src, target_organ)) + return + + playsound(target, 'modular_sand/sound/lewd/latex.ogg', 50, 1, -1) + to_chat(target, span_userlove("Your penis feels more safe!")) + +/obj/item/genital_equipment/sounding/insert_item_organ(mob/living/carbon/user, mob/living/carbon/target, obj/item/organ/genital/target_organ) + if(!(target.client?.prefs?.erppref == "Yes")) + to_chat(user, span_warning("They don't want you to do that!")) + return + + if(!unwrapped) + to_chat(user, span_notice("You must remove the rod from the package first!")) + return + + var/obj/item/organ/genital/penis/ween = target_organ + if(!istype(ween)) + to_chat(user, span_notice("You can't put the rod inside this genital!")) + return + + if(!target.has_penis(REQUIRE_EXPOSED)) + to_chat(user, span_notice("You can't find anywhere to put the rod!")) + return + + if(locate(src.type) in target_organ.contents) + to_chat(user, span_notice("\The [target]'s [target_organ] already has a rod inside!")) + return + + target.visible_message(span_warning("\The [user] is trying to insert a rod inside \the [target]!"),\ + span_warning("\The [user] is trying to insert a rod inside you!")) + + if(!do_mob(user, target, 4 SECONDS)) + return + + if(!user.transferItemToLoc(src, target_organ)) + return + + playsound(target, 'modular_sand/sound/lewd/champ_fingering.ogg', 50, 1, -1) + to_chat(target, span_userlove("Your penis feels stuffed and stretched!")) + owner = target + +/obj/item/electropack/vibrator/insert_item_organ(mob/living/carbon/user, mob/living/carbon/target, obj/item/organ/genital/target_organ) + if(!(target.client?.prefs?.erppref == "Yes")) + to_chat(user, span_warning("They don't want you to do that!")) + return + + if(style == "long" && !(istype(target_organ, /obj/item/organ/genital/vagina))) //long vibrators dont fit on anything but vaginas, but small ones fit everywhere + to_chat(user, "[src] is too big to fit there, use a smaller version.") + return + + if(locate(src.type) in target_organ.contents) + to_chat(user, span_notice("\The [target]'s [target_organ] already has a vibrator inside!")) + return + + if(style == "long") + target.visible_message(span_warning("\The [user] is trying to insert a vibrator inside \the [target]!"),\ + span_warning("\The [user] is trying to insert a vibrator inside you!")) + else + target.visible_message(span_userlove("\The [user] is trying to attach a vibrator to \the [target]!"),\ + span_warning("\The [user] is trying to attach a vibrator to you!")) + + if(!do_mob(user, target, 5 SECONDS)) + return + + if(!user.transferItemToLoc(src, target_organ)) + return + + if(style == "long") + to_chat(user, span_userlove("You attach [src] to \The [target]'s [target_organ].")) + else + to_chat(user, span_userlove("You attach [src] to \The [target]'s [target_organ].")) + + playsound(target, 'modular_sand/sound/lewd/champ_fingering.ogg', 50, 1, -1) + inside = TRUE + + +/obj/item/oviposition_egg/insert_item_organ(mob/living/carbon/user, mob/living/carbon/target, obj/item/organ/genital/target_organ) + if(!(target.client?.prefs?.erppref == "Yes")) + to_chat(user, span_warning("They don't want you to do that!")) + return + + if(!(CHECK_BITFIELD(target_organ.genital_flags, GENITAL_CAN_STUFF))) + to_chat(user, span_warning("This genital can't be stuffed!")) + return + + target.visible_message(span_warning("\The [user] is trying to insert an egg inside \the [target]!"),\ + span_warning("\The [user] is trying to insert an egg inside you!")) + + if(!do_mob(user, target, 5 SECONDS)) + return + + if(!user.transferItemToLoc(src, target_organ)) + return + + to_chat(target, span_userlove("Your [target_organ] feels stuffed and stretched!")) + + playsound(target, 'modular_sand/sound/lewd/champ_fingering.ogg', 50, 1, -1) diff --git a/modular_splurt/code/game/object/items/lewd_items/genital_equipment/condom.dm b/modular_splurt/code/game/object/items/lewd_items/genital_equipment/condom.dm index 77ae20ee86..f33c5cd052 100644 --- a/modular_splurt/code/game/object/items/lewd_items/genital_equipment/condom.dm +++ b/modular_splurt/code/game/object/items/lewd_items/genital_equipment/condom.dm @@ -7,7 +7,6 @@ icon = 'modular_splurt/icons/obj/condom.dmi' throwforce = 0 icon_state = "b_condom_wrapped" - equipment_slot = GENITAL_EQUIPEMENT_CONDOM var/unwrapped = 0 w_class = WEIGHT_CLASS_TINY @@ -27,6 +26,9 @@ icon_state = "b_condom_inflated_huge" ..() +/obj/item/genital_equipment/condom/on_reagent_change() + update_icon() + /obj/item/genital_equipment/condom/attack_self(mob/user) //Unwrap The Condom in hands if(!istype(user)) return @@ -37,13 +39,26 @@ to_chat(user, "You unwrap the condom.") playsound(user, 'sound/items/poster_ripped.ogg', 50, 1, -1) return + +/obj/item/genital_equipment/condom/throw_impact(atom/hit_atom) + . = ..() + if(!.) //if we're not being caught + splat(hit_atom) + +/obj/item/genital_equipment/condom/proc/splat(atom/movable/hit_atom) + if(isliving(loc)) + return + var/turf/T = get_turf(hit_atom) + new/obj/effect/decal/cleanable/semen(T) + playsound(T, 'sound/misc/splort.ogg', 50, TRUE) + qdel(src) // if(unwrapped == 1) // new /obj/item/clothing/head/condom(usr.loc) // qdel(src) // to_chat(user, "You roll the condom out.") // playsound(user, 'sound/lewd/latex.ogg', 50, 1, -1) // return - +/* /obj/item/genital_equipment/condom/attack(mob/living/carbon/C, mob/living/user) //apply the johnny on another person or yourself if(unwrapped == 0 ) @@ -73,6 +88,7 @@ return to_chat(user, "You can't find anywhere to put the condom on.") //Trying to put it on something without/or with a hidden +*/ /obj/item/clothing/head/condom //p name = "condom" @@ -93,7 +109,7 @@ /*P.colourtint = "" update_genitals()*/ */ - +/* /obj/item/genital_equipment/condom/filled name = "filled condom" icon_state = "b_condom_inflated" @@ -112,7 +128,8 @@ new/obj/effect/decal/cleanable/semen(T) playsound(T, 'sound/misc/splort.ogg', 50, TRUE) qdel(src) - +*/ +/* /obj/item/genital_equipment/condom/genital_remove_proccess(obj/item/organ/genital/G) if(!G.equipment[GENITAL_EQUIPEMENT_CONDOM]) return @@ -121,12 +138,12 @@ . = ..() qdel(src) +*/ + /mob/living/carbon/human/proc/condomclimax() - var/obj/item/genital_equipment/condom/filled/C = new var/obj/item/organ/genital/penis/P = getorganslot(ORGAN_SLOT_PENIS) - P.equipment.Remove(GENITAL_EQUIPEMENT_CONDOM) - C.loc = loc - return C + var/obj/item/genital_equipment/condom/condo = locate(/obj/item/genital_equipment/condom) in P.contents + return condo /* var/obj/item/genital_equipment/condom/filled/C = new diff --git a/modular_splurt/code/game/object/items/lewd_items/genital_equipment/sounding.dm b/modular_splurt/code/game/object/items/lewd_items/genital_equipment/sounding.dm index c57f00996e..d3aa33c6a9 100644 --- a/modular_splurt/code/game/object/items/lewd_items/genital_equipment/sounding.dm +++ b/modular_splurt/code/game/object/items/lewd_items/genital_equipment/sounding.dm @@ -5,7 +5,7 @@ throwforce = 0 icon_state = "sounding_wrapped" var/unwrapped = 0 - equipment_slot = GENITAL_EQUIPMENT_SOUNDING +// equipment_slot = GENITAL_EQUIPMENT_SOUNDING w_class = WEIGHT_CLASS_TINY /obj/item/genital_equipment/sounding/attack_self(mob/user) @@ -18,7 +18,7 @@ to_chat(user, "You unwrap the rod.") playsound(user, 'sound/items/poster_ripped.ogg', 50, 1, -1) return - +/* /obj/item/genital_equipment/sounding/attack(mob/living/carbon/C, mob/living/user) if(unwrapped == 0 ) @@ -53,7 +53,6 @@ . = ..() qdel(src) -/* /mob/living/carbon/human/proc/removesounding() var/obj/item/organ/genital/penis/P = getorganslot("penis") @@ -61,13 +60,13 @@ P.equipment.Remove(GENITAL_EQUIPMENT_SOUNDING) new /obj/item/genital_equipment/sounding/used_sounding(loc) to_chat(src, "The rod falls off from your penis.") -*/ + /obj/item/genital_equipment/sounding/used_sounding name = "sounding rod" icon_state = "sounding_rod" unwrapped = 2 w_class = WEIGHT_CLASS_TINY -/* + /mob/living/carbon/human/proc/soundingclimax() var/obj/item/organ/genital/penis/P = src.getorganslot("penis") diff --git a/modular_splurt/code/game/object/items/lewd_items/vibrator.dm b/modular_splurt/code/game/object/items/lewd_items/vibrator.dm index 6ef05c7dec..6d8a813c00 100644 --- a/modular_splurt/code/game/object/items/lewd_items/vibrator.dm +++ b/modular_splurt/code/game/object/items/lewd_items/vibrator.dm @@ -9,7 +9,6 @@ item_state = "vibe" w_class = WEIGHT_CLASS_SMALL //slot_flags = ITEM_SLOT_DENYPOCKET //no more pocket shockers - var/equipment_slot = GENITAL_EQUIPMENT_VIBRATOR var/mode = 1 var/style = "long" var/inside = FALSE @@ -59,7 +58,7 @@ Code: mode = 1 to_chat(user, "You twist the bottom of [src], setting it to the low setting.") return - +/* /obj/item/electropack/vibrator/attack(mob/living/carbon/C, mob/living/user) var/obj/item/organ/genital/picked_organ @@ -94,6 +93,7 @@ Code: else to_chat(user, "You don't see anywhere to attach this.") +*/ /obj/item/electropack/vibrator/receive_signal(datum/signal/signal) diff --git a/modular_splurt/code/game/object/items/oviposition.dm b/modular_splurt/code/game/object/items/oviposition.dm new file mode 100644 index 0000000000..b223a68e15 --- /dev/null +++ b/modular_splurt/code/game/object/items/oviposition.dm @@ -0,0 +1,54 @@ + +GLOBAL_LIST_INIT(egg_skins, list( \ + "xenomorph", \ + "badrecipe", \ + "chocolate", \ + "pellet", \ + "rock", \ + "chicken", \ + "slimeglob", \ + "synthetic", \ + "escapepod", \ + "cocoon", \ + "bugcocoon", \ + "yellow", \ + "blue", \ + "green", \ + "orange", \ + "purple", \ + "red", \ + "rainbow", \ + "pink", \ + "honeycomb", \ + "floppy", \ + "file", \ + "cd", \ + "spidercluster", \ + "dragon", \ + "corrupteddemon", \ + "holy", \ + "fish", \ + "insectoid", \ + "ashwalker", \ + "void", \ + "polychrome", \ + "ratvar", \ + "hybrid" \ +)) +//Oviposition egg, logic is at the pregnancy component +/obj/item/oviposition_egg + name = "egg" + desc = "An egg, this one looks suspiciously large though." + icon_state = "egg_chicken" + icon = 'modular_splurt/icons/obj/lewd_items/egg.dmi' + integrity_failure = 0.9 + obj_flags = UNIQUE_RENAME + +/obj/item/oviposition_egg/ComponentInitialize() + . = ..() + AddComponent(/datum/component/organ_inflation, 0) + +/obj/item/oviposition_egg/obj_break(damage_flag) + . = ..() + icon = 'modular_splurt/icons/obj/lewd_items/egg_broken.dmi' + update_appearance() diff --git a/modular_splurt/code/game/object/items/pregnancy_tester.dm b/modular_splurt/code/game/object/items/pregnancy_tester.dm new file mode 100644 index 0000000000..bcb49cce35 --- /dev/null +++ b/modular_splurt/code/game/object/items/pregnancy_tester.dm @@ -0,0 +1,59 @@ +/obj/item/pregnancytest + name = "pregnancy test" + desc = "A one time use small device, used to determine whether someone is pregnant or not." + icon = 'modular_splurt/icons/obj/pregnancytest.dmi' + throwforce= 0 + icon_state = "ptest" + custom_price = PRICE_REALLY_CHEAP + var/results + w_class = WEIGHT_CLASS_TINY + +/obj/item/pregnancytest/attack_self(mob/user) + . = ..() + if(QDELETED(src)) + return + if(!isliving(user)) + return + if(user.stat > CONSCIOUS)//unconscious or dead + return + + test(user, user) + +/obj/item/pregnancytest/examine(mob/user) + . = ..() + . += span_notice("[results ? "The display reads [results]" : "The display is empty, this tester is not yet used"].") + +/obj/item/pregnancytest/afterattack(atom/target, mob/user, proximity_flag, click_parameters) + . = ..() + if(user.zone_selected != BODY_ZONE_PRECISE_GROIN) + return + if(!isliving(target)) + return + var/mob/living/livingtar = target + if(iscarbon(target)) + var/mob/living/carbon/cartar = target + if(!cartar.is_groin_exposed()) + return + + test(livingtar, user) + +/obj/item/pregnancytest/proc/test(mob/living/target, mob/user) + if(results) + to_chat(user, span_warning("This tester is already used!")) + return + + var/obj/item/organ/container = target.getorganslot(ORGAN_SLOT_WOMB) + + results = "negative" + + for(var/obj/item/thing as anything in container.contents) + if(thing?.GetComponent(/datum/component/pregnancy)) + results = "positive" + break + + to_chat(user, span_notice("You use the tester.")) + + icon_state = results + name = "[results] pregnancy test" + + update_appearance() diff --git a/modular_splurt/code/modules/arousal/arousal.dm b/modular_splurt/code/modules/arousal/arousal.dm index d032d8ed18..aaee27e37b 100644 --- a/modular_splurt/code/modules/arousal/arousal.dm +++ b/modular_splurt/code/modules/arousal/arousal.dm @@ -2,36 +2,67 @@ . = ..() L.receive_climax(src, Lgen, G, spillage, forced = forced) -/mob/living/receive_climax(mob/living/partner, obj/item/organ/genital/receiver, obj/item/organ/genital/source_gen, spill, forced) - . = ..() +/mob/living/proc/receive_climax(mob/living/partner, obj/item/organ/genital/receiver, obj/item/organ/genital/source, spill, forced) + //gregnancy... + if(!spill && istype(source, /obj/item/organ/genital/penis) && \ + istype(receiver, /obj/item/organ/genital/vagina) && getorganslot(ORGAN_SLOT_WOMB)) + var/obj/item/organ/genital/penis/peenus = source + if(!(locate(/obj/item/genital_equipment/condom) in peenus.contents)) + impregnate(partner) if(!receiver || spill || forced) return - receiver.climax_modify_size(partner, source_gen) + receiver.climax_modify_size(partner, source) -/mob/living/carbon/human/do_climax(datum/reagents/R, atom/target, obj/item/organ/genital/G, spill, cover = FALSE) - if(!G) +//handles impregnation, also prefs +/mob/living/proc/impregnate(mob/living/partner, obj/item/organ/W, baby_type = /mob/living/carbon/human) + var/obj/item/organ/container = W + + if(!container) + container = getorganslot(ORGAN_SLOT_WOMB) + if(!container) + return + + var/can_impregnate = 100 + if(partner?.client?.prefs) + can_impregnate = partner.client.prefs.virility + var/can_get_pregnant = (client?.prefs?.fertility && !is_type_in_typecache(src.type, GLOB.pregnancy_blocked_mob_typecache)) + if(!(can_impregnate && can_get_pregnant)) + return + + var/avg = (can_impregnate + client.prefs.fertility) / 2 + + if(prob(avg)) + var/obj/item/oviposition_egg/eggo = new() + eggo.forceMove(container) + eggo.AddComponent(/datum/component/pregnancy, src, partner, baby_type) + +/mob/living/carbon/human/do_climax(datum/reagents/R, atom/target, obj/item/organ/genital/sender, spill, cover = FALSE, obj/item/organ/genital/receiver) + if(!sender) return if(!target || !R) return + if(SEND_SIGNAL(src, COMSIG_MOB_CLIMAX, R, target, sender, receiver, spill)) + return + var/cached_fluid if(isliving(target) && !spill) var/mob/living/L = target var/list/blacklist = L.client?.prefs.gfluid_blacklist - if((G.get_fluid_id() in blacklist) || ((/datum/reagent/blood in blacklist) && ispath(G.get_fluid_id(), /datum/reagent/blood))) - cached_fluid = G.get_fluid_id() - var/default = G.get_default_fluid() - G.set_fluid_id(default) + if((sender.get_fluid_id() in blacklist) || ((/datum/reagent/blood in blacklist) && ispath(sender.get_fluid_id(), /datum/reagent/blood))) + cached_fluid = sender.get_fluid_id() + var/default = sender.get_default_fluid() + sender.set_fluid_id(default) - if(istype(G, /obj/item/organ/genital/penis)) - var/obj/item/organ/genital/penis/bepis = G - if(bepis.equipment[GENITAL_EQUIPMENT_SOUNDING]) + if(istype(sender, /obj/item/organ/genital/penis)) + var/obj/item/organ/genital/penis/bepis = sender + if(locate(/obj/item/genital_equipment/sounding) in bepis.contents) spill = TRUE to_chat(src, "You feel your sounding rod being pushed out of your cockhole with the burst of jizz!") - bepis.equipment.Remove(GENITAL_EQUIPMENT_SOUNDING) - new /obj/item/genital_equipment/sounding/used_sounding(loc) + var/obj/item/genital_equipment/sounding/rod = locate(/obj/item/genital_equipment/sounding) in bepis.contents + rod.forceMove(get_turf(src)) if(cover) target.add_cum_overlay() @@ -39,7 +70,7 @@ . = ..() if(cached_fluid) - G.set_fluid_id(cached_fluid) + sender.set_fluid_id(cached_fluid) /mob/living/carbon/human/mob_fill_container(obj/item/organ/genital/G, obj/item/reagent_containers/container, mb_time, obj/item/milking_machine/M) if(!M) diff --git a/modular_splurt/code/modules/arousal/genitals.dm b/modular_splurt/code/modules/arousal/genitals.dm index eeb446d2b9..0b639672c0 100644 --- a/modular_splurt/code/modules/arousal/genitals.dm +++ b/modular_splurt/code/modules/arousal/genitals.dm @@ -45,6 +45,7 @@ /obj/item/organ/genital var/list/obj/item/equipment = list() +/* /obj/item/organ/genital/proc/remove_equipment(mob/living/carbon/remover, selection) var/obj/item/selected = equipment[selection] if(!selected) @@ -79,3 +80,4 @@ else selected.loc = owner.loc equipment.Remove(selection) +*/ diff --git a/modular_splurt/code/modules/arousal/organs/belly.dm b/modular_splurt/code/modules/arousal/organs/belly.dm index 00f6c25c39..5530d13314 100644 --- a/modular_splurt/code/modules/arousal/organs/belly.dm +++ b/modular_splurt/code/modules/arousal/organs/belly.dm @@ -101,6 +101,8 @@ fluid_max_volume += ((size - initial(size))*2.5)*(owner ? get_size(owner) : 1) fluid_rate += ((size - initial(size))/10)*(owner ? get_size(owner) : 1) toggle_visibility(D.features["belly_visibility"], FALSE) + if(D.features["belly_stuffing"]) + toggle_visibility(GEN_ALLOW_EGG_STUFFING, FALSE) /obj/item/organ/genital/belly/climax_modify_size(mob/living/partner, obj/item/organ/genital/source_gen, cum_hole) if(!(owner.client?.prefs.cit_toggles & BELLY_INFLATION)) diff --git a/modular_splurt/code/modules/cargo/bounties/assistant.dm b/modular_splurt/code/modules/cargo/bounties/assistant.dm index bd157042d9..42210acf6f 100644 --- a/modular_splurt/code/modules/cargo/bounties/assistant.dm +++ b/modular_splurt/code/modules/cargo/bounties/assistant.dm @@ -3,4 +3,11 @@ description = "Something wack is happening at Central Command, and now they requested some filled condoms?" reward = 1150 required_count = 5 - wanted_types = list(/obj/item/genital_equipment/condom/filled) + wanted_types = list(/obj/item/genital_equipment/condom) + +/datum/bounty/item/assistant/condom/applies_to(obj/O) + if(!..()) + return FALSE + var/obj/item/genital_equipment/condom/T = O + return T.reagents.total_volume > 0 + diff --git a/modular_splurt/code/modules/cargo/exports/lewd.dm b/modular_splurt/code/modules/cargo/exports/lewd.dm index 80ab9814f1..a6186671f1 100644 --- a/modular_splurt/code/modules/cargo/exports/lewd.dm +++ b/modular_splurt/code/modules/cargo/exports/lewd.dm @@ -2,5 +2,11 @@ /datum/export/gear/condom cost = 150 unit_name = "filled condom" - export_types = list(/obj/item/genital_equipment/condom/filled) + export_types = list(/obj/item/genital_equipment/condom) include_subtypes = TRUE + +/datum/export/gear/condom/applies_to(obj/O) + if(!..()) + return FALSE + var/obj/item/genital_equipment/condom/T = O + return T.reagents.total_volume > 0 diff --git a/modular_splurt/code/modules/mob/living/carbon/human/simple_animal/hostile/deathclaw/funclaw.dm b/modular_splurt/code/modules/mob/living/carbon/human/simple_animal/hostile/deathclaw/funclaw.dm index dbf172435a..81af399f1f 100644 --- a/modular_splurt/code/modules/mob/living/carbon/human/simple_animal/hostile/deathclaw/funclaw.dm +++ b/modular_splurt/code/modules/mob/living/carbon/human/simple_animal/hostile/deathclaw/funclaw.dm @@ -160,6 +160,7 @@ if(CUM_TARGET_VAGINA) if(M.is_bottomless() && M.has_vagina()) message = "rams its meaty cock into \the [M]'s pussy and fills it with sperm." + M.impregnate(src, M.getorganslot(ORGAN_SLOT_WOMB), src.type) else message = "cums on \the [M]'s belly." if(CUM_TARGET_ANUS) diff --git a/modular_splurt/icons/mob/screen_alert.dmi b/modular_splurt/icons/mob/screen_alert.dmi new file mode 100644 index 0000000000..c627ca9892 Binary files /dev/null and b/modular_splurt/icons/mob/screen_alert.dmi differ diff --git a/modular_splurt/icons/obj/lewd_items/egg.dmi b/modular_splurt/icons/obj/lewd_items/egg.dmi new file mode 100644 index 0000000000..4b70f7193a Binary files /dev/null and b/modular_splurt/icons/obj/lewd_items/egg.dmi differ diff --git a/modular_splurt/icons/obj/lewd_items/egg_broken.dmi b/modular_splurt/icons/obj/lewd_items/egg_broken.dmi new file mode 100644 index 0000000000..82b540ea1c Binary files /dev/null and b/modular_splurt/icons/obj/lewd_items/egg_broken.dmi differ diff --git a/modular_splurt/icons/obj/pregnancytest.dmi b/modular_splurt/icons/obj/pregnancytest.dmi new file mode 100644 index 0000000000..d7563cad12 Binary files /dev/null and b/modular_splurt/icons/obj/pregnancytest.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 36b372f853..2643e0894d 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -257,6 +257,7 @@ #include "code\__SPLURTCODE\DEFINES\lewd.dm" #include "code\__SPLURTCODE\DEFINES\login.dm" #include "code\__SPLURTCODE\DEFINES\mobs.dm" +#include "code\__SPLURTCODE\DEFINES\pregnancy.dm" #include "code\__SPLURTCODE\DEFINES\quirks.dm" #include "code\__SPLURTCODE\DEFINES\radiation.dm" #include "code\__SPLURTCODE\DEFINES\say.dm" @@ -4235,6 +4236,7 @@ #include "modular_splurt\code\_globalvars\lists\mapping.dm" #include "modular_splurt\code\_globalvars\lists\mobs.dm" #include "modular_splurt\code\_globalvars\lists\objects.dm" +#include "modular_splurt\code\_globalvars\lists\pregnancy.dm" #include "modular_splurt\code\_globalvars\lists\wendigo.dm" #include "modular_splurt\code\_onclick\observer.dm" #include "modular_splurt\code\_onclick\hud\new_player.dm" @@ -4262,8 +4264,11 @@ #include "modular_splurt\code\datums\status_effects.dm" #include "modular_splurt\code\datums\world_topic.dm" #include "modular_splurt\code\datums\components\chasm.dm" +#include "modular_splurt\code\datums\components\organ_inflation.dm" +#include "modular_splurt\code\datums\components\pregnancy.dm" #include "modular_splurt\code\datums\components\dullahan.dm" #include "modular_splurt\code\datums\components\nanites.dm" +#include "modular_splurt\code\datums\components\pregnancy_inert.dm" #include "modular_splurt\code\datums\components\size_normalized.dm" #include "modular_splurt\code\datums\components\crafting\recipes\recipes_misc.dm" #include "modular_splurt\code\datums\components\crafting\recipes\recipes_primal.dm" @@ -4284,9 +4289,11 @@ #include "modular_splurt\code\datums\mood_events\generic_positive_events.dm" #include "modular_splurt\code\datums\mood_events\mood_event.dm" #include "modular_splurt\code\datums\mood_events\needs_events.dm" +#include "modular_splurt\code\datums\mood_events\preg_events.dm" #include "modular_splurt\code\datums\mutations\telekenisis.dm" #include "modular_splurt\code\datums\ruins\lavaland.dm" #include "modular_splurt\code\datums\ruins\station.dm" +#include "modular_splurt\code\datums\status_effects\pregnancy.dm" #include "modular_splurt\code\datums\traits\defines.dm" #include "modular_splurt\code\datums\traits\good.dm" #include "modular_splurt\code\datums\traits\negative.dm" @@ -4315,6 +4322,7 @@ #include "modular_splurt\code\game\machinery\doors\shutters.dm" #include "modular_splurt\code\game\machinery\porta_turret\portable_turret.dm" #include "modular_splurt\code\game\mecha\combat\gygax.dm" +#include "modular_splurt\code\game\object\items.dm" #include "modular_splurt\code\game\object\effects\landmarks.dm" #include "modular_splurt\code\game\object\effects\spawners\lootdrop.dm" #include "modular_splurt\code\game\object\items\AI_modules.dm" @@ -4325,8 +4333,10 @@ #include "modular_splurt\code\game\object\items\mesmetron.dm" #include "modular_splurt\code\game\object\items\milking_machine.dm" #include "modular_splurt\code\game\object\items\miscellaneous.dm" +#include "modular_splurt\code\game\object\items\oviposition.dm" #include "modular_splurt\code\game\object\items\plaguedoc.dm" #include "modular_splurt\code\game\object\items\plushes.dm" +#include "modular_splurt\code\game\object\items\pregnancy_tester.dm" #include "modular_splurt\code\game\object\items\RCD.dm" #include "modular_splurt\code\game\object\items\toys.dm" #include "modular_splurt\code\game\object\items\weaponry.dm" diff --git a/tgui/packages/tgui/interfaces/MobInteraction.tsx b/tgui/packages/tgui/interfaces/MobInteraction.tsx index ca7146740b..84b95fe13a 100644 --- a/tgui/packages/tgui/interfaces/MobInteraction.tsx +++ b/tgui/packages/tgui/interfaces/MobInteraction.tsx @@ -2,7 +2,8 @@ import { filter, map, sortBy } from 'common/collections'; import { flow } from 'common/fp'; import { createSearch } from 'common/string'; import { useBackend, useLocalState } from '../backend'; -import { BlockQuote, Button, Flex, LabeledList, Icon, Input, Section, Table, Tabs, Stack } from '../components'; +import { BlockQuote, Button, LabeledList, Icon, Input, Section, Table, Tabs, Stack, ProgressBar, Divider } from '../components'; +import { TableRow } from '../components/Table'; import { Window } from '../layouts'; type HeaderInfo = { @@ -30,9 +31,30 @@ type GenitalData = { name: string, key: string, visibility: string, + extras: string, + extra_choices: string[], possible_choices: string[], } +type GenitalManagerInfo = { + isTargetSelf: boolean; + genital_fluids: GenitalFluid[]; + genital_interactibles: GenitalInteractionInfos[]; +} + +type GenitalInteractionInfos = { + name: string, + key: string, + possible_choices: string[], + equipments: string[], +} + +type GenitalFluid = { + name: string, + key: string, + fluids: number, +} + type CharacterPrefsInfo = { erp_pref: number, noncon_pref: number, @@ -78,7 +100,7 @@ export const MobInteraction = (props, context) => { return ( @@ -122,6 +144,9 @@ export const MobInteraction = (props, context) => { setTabIndex(3)}> Preferences + setTabIndex(4)}> + Genital Manager + {tabIndex === 0 && ( @@ -131,6 +156,8 @@ export const MobInteraction = (props, context) => { ) || tabIndex === 3 && ( + ) || tabIndex === 4 && ( + ) || ("Somehow, you've got into an invalid page, please report this.")} @@ -213,6 +240,7 @@ const ModeToIcon = { "Hidden by clothes": "tshirt", "Hidden by underwear": "low-vision", "Always hidden": "eye-slash", + "Allows egg stuffing": "egg", }; const GenitalVisibilityTab = (props, context) => { @@ -220,7 +248,7 @@ const GenitalVisibilityTab = (props, context) => { const genitals = data.genitals || []; return ( genitals.length ? ( - + {genitals.map(genital => ( @@ -235,10 +263,22 @@ const GenitalVisibilityTab = (props, context) => { visibility: choice, })} /> ))} + {genital.extra_choices instanceof Array + ? genital.extra_choices.map(choice => ( +