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 => (
+
))}
-
+
) : (
You don't seem to have any genitals...
@@ -248,6 +288,71 @@ const GenitalVisibilityTab = (props, context) => {
);
};
+const GenitalManagerTab = (props, context) => {
+ const { act, data } = useBackend(context);
+ const isTargetSelf = data.isTargetSelf;
+ const genital_fluids = data.genital_fluids || [];
+ const genital_interactibles = data.genital_interactibles || [];
+ return (
+ genital_fluids.length || genital_interactibles.length ? (
+ <>
+
+
+ {genital_fluids.map(genital => (
+
+
+
+ ))}
+
+
+
+ {genital_interactibles.map(genital => (
+
+ {
+ genital.equipments.length ? (
+ <>
+ Equipments:
+
+ {genital.equipments.map(equipment => (
+
+ {equipment}
+
+ ))}
+
+
+ >
+ ) : null
+ }
+
+ {genital.possible_choices.map(choice => (
+
+ ))}
+
+ >
+ ) : (
+
+ {
+ isTargetSelf
+ ? "You don't seem to have any genitals... Or any that you could do anything with"
+ : "They don't seem to have any genitals... Or any that you could do anything with"
+ }
+
+ )
+ );
+};
+
const CharacterPrefsTab = (props, context) => {
const { act, data } = useBackend(context);
const {
@@ -259,7 +364,7 @@ const CharacterPrefsTab = (props, context) => {
extreme_harm,
} = data;
return (
-
+
) : (null)}
-
+
);
};