mirror of
https://github.com/SPLURT-Station/S.P.L.U.R.T-Station-13.git
synced 2025-12-09 16:07:40 +00:00
Merge pull request #520 from Pin-alternative/rework
Reworks to genitals
This commit is contained in:
@@ -330,7 +330,7 @@
|
||||
var/obj/item/organ/genital/breasts/boobs = new(loc)
|
||||
if(features["has_breasts"])
|
||||
boobs.color = sanitize_hexcolor(features["breasts_color"], 6, TRUE)
|
||||
boobs.size = features["breasts_size"]
|
||||
boobs.size = GLOB.breast_values[features["breasts_size"]]
|
||||
boobs.shape = features["breasts_shape"]
|
||||
if(!features["breasts_producing"])
|
||||
boobs.genital_flags &= ~(GENITAL_FUID_PRODUCTION|CAN_CLIMAX_WITH|CAN_MASTURBATE_WITH)
|
||||
|
||||
@@ -190,7 +190,7 @@
|
||||
aroused_state = FALSE
|
||||
|
||||
/obj/item/organ/genital/proc/generate_fluid(datum/reagents/R)
|
||||
var/amount = clamp((fluid_rate * ((world.time - last_orgasmed) / (10 SECONDS)) * fluid_mult),0,fluid_max_volume)
|
||||
var/amount = get_fluid()
|
||||
R.clear_reagents()
|
||||
R.maximum_volume = fluid_max_volume
|
||||
if(fluid_id)
|
||||
@@ -325,7 +325,7 @@
|
||||
|
||||
var/obj/item/organ/genital/G = A
|
||||
var/datum/sprite_accessory/S
|
||||
var/size = G.size
|
||||
var/size = G.size_to_state()
|
||||
switch(G.type)
|
||||
if(/obj/item/organ/genital/penis)
|
||||
S = GLOB.cock_shapes_list[G.shape]
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
icon = 'icons/obj/genitals/breasts.dmi'
|
||||
zone = BODY_ZONE_CHEST
|
||||
slot = ORGAN_SLOT_BREASTS
|
||||
size = BREASTS_SIZE_DEF // "c". Refer to the breast_values static list below for the cups associated number values
|
||||
size = 3
|
||||
fluid_id = /datum/reagent/consumable/milk
|
||||
fluid_rate = MILK_RATE
|
||||
shape = DEF_BREASTS_SHAPE
|
||||
@@ -19,19 +19,12 @@
|
||||
orgasm_verb = "leaking"
|
||||
fluid_transfer_factor = 0.5
|
||||
layer_index = BREASTS_LAYER_INDEX
|
||||
var/static/list/breast_values = list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5, "f" = 6, "g" = 7, "h" = 8, "i" = 9, "j" = 10, "k" = 11, "l" = 12, "m" = 13, "n" = 14, "o" = 15, "huge" = 16, "massive" = 17, "giga" = 25, "impossible" = 30, "flat" = 0)
|
||||
var/cached_size //these two vars pertain size modifications and so should be expressed in NUMBERS.
|
||||
var/prev_size //former cached_size value, to allow update_size() to early return should be there no significant changes.
|
||||
|
||||
/obj/item/organ/genital/breasts/Initialize(mapload, do_update = TRUE)
|
||||
if(do_update)
|
||||
cached_size = breast_values[size]
|
||||
prev_size = cached_size
|
||||
return ..()
|
||||
|
||||
/obj/item/organ/genital/breasts/update_appearance()
|
||||
. = ..()
|
||||
var/lowershape = lowertext(shape)
|
||||
var/size_state = size_to_state()
|
||||
switch(lowershape)
|
||||
if("pair")
|
||||
desc = "You see a pair of breasts."
|
||||
@@ -41,13 +34,13 @@
|
||||
desc = "You see three sets of breasts, running from their chest to their belly."
|
||||
else
|
||||
desc = "You see some breasts, they seem to be quite exotic."
|
||||
if(size == "huge")
|
||||
desc = "You see [pick("some serious honkers", "a real set of badonkers", "some dobonhonkeros", "massive dohoonkabhankoloos", "two big old tonhongerekoogers", "a couple of giant bonkhonagahoogs", "a pair of humongous hungolomghnonoloughongous")]. Their volume is way beyond cupsize now, measuring in about [round(cached_size*(owner ? get_size(owner) : 1))]cm in diameter."
|
||||
if(size_state == "huge")
|
||||
desc = "You see [pick("some serious honkers", "a real set of badonkers", "some dobonhonkeros", "massive dohoonkabhankoloos", "two big old tonhongerekoogers", "a couple of giant bonkhonagahoogs", "a pair of humongous hungolomghnonoloughongous")]. Their volume is way beyond cupsize now, measuring in about [round(size*(owner ? get_size(owner) : 1))]cm in diameter."
|
||||
else
|
||||
if (size == "flat")
|
||||
if (size_state == "flat")
|
||||
desc += " They're very small and flatchested, however."
|
||||
else
|
||||
desc += " You estimate that they're [uppertext(size)]-cups."
|
||||
desc += " You estimate that they're [uppertext(size_state)]-cups."
|
||||
|
||||
if((genital_flags & GENITAL_FUID_PRODUCTION) && aroused_state)
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[fluid_id]
|
||||
@@ -55,7 +48,7 @@
|
||||
desc += " They're leaking [lowertext(R.name)]."
|
||||
var/datum/sprite_accessory/S = GLOB.breasts_shapes_list[shape]
|
||||
var/icon_shape = S ? S.icon_state : "pair"
|
||||
var/icon_size = clamp(breast_values[size], BREASTS_ICON_MIN_SIZE, BREASTS_ICON_MAX_SIZE)
|
||||
var/icon_size = clamp(GLOB.breast_values[size_state], BREASTS_ICON_MIN_SIZE, BREASTS_ICON_MAX_SIZE)
|
||||
icon_state = "breasts_[icon_shape]_[icon_size]"
|
||||
if(owner)
|
||||
if(owner.dna.species.use_skintones && owner.dna.features["genitals_use_skintone"])
|
||||
@@ -74,45 +67,49 @@
|
||||
//this is far too lewd wah
|
||||
|
||||
/obj/item/organ/genital/breasts/modify_size(modifier, min = -INFINITY, max = INFINITY)
|
||||
var/new_value = clamp(cached_size + modifier, min, max)
|
||||
if(new_value == cached_size)
|
||||
var/new_value = clamp(size + modifier, max(min, min_size ? min_size : -INFINITY), min(max_size ? max_size : INFINITY, max))
|
||||
if(new_value == size)
|
||||
return
|
||||
prev_size = cached_size
|
||||
cached_size = new_value
|
||||
prev_size = size
|
||||
size = new_value
|
||||
update()
|
||||
..()
|
||||
|
||||
/obj/item/organ/genital/breasts/size_to_state()
|
||||
var/str_size
|
||||
switch(size)
|
||||
if(0) //flatchested
|
||||
str_size = "flat"
|
||||
if(1 to 8) //modest
|
||||
str_size = GLOB.breast_values[size]
|
||||
if(9 to 15) //massive
|
||||
str_size = GLOB.breast_values[size]
|
||||
if(16 to 17) //ridiculous
|
||||
str_size = GLOB.breast_values[size]
|
||||
if(18 to 24) //AWOOOOGAAAAAAA
|
||||
str_size = "massive"
|
||||
if(25 to 29) //AWOOOOOOGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
str_size = "giga"
|
||||
if(30 to INFINITY) //AWWWWWWWWWWWWWOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOGGGGGAAAAAAAAAAAAAAAAAAAAAA
|
||||
str_size = "impossible"
|
||||
return str_size
|
||||
|
||||
/obj/item/organ/genital/breasts/update_size()//wah
|
||||
var/rounded_cached = round(cached_size)
|
||||
if(cached_size < 0)//I don't actually know what round() does to negative numbers, so to be safe!!fixed
|
||||
var/rounded_size = round(size)
|
||||
var/size_state = size_to_state()
|
||||
if(rounded_size < 0)//I don't actually know what round() does to negative numbers, so to be safe!!fixed
|
||||
if(owner)
|
||||
to_chat(owner, "<span class='warning'>You feel your breasts shrinking away from your body as your chest flattens out.</span>")
|
||||
QDEL_IN(src, 1)
|
||||
return
|
||||
switch(rounded_cached)
|
||||
if(0) //flatchested
|
||||
size = "flat"
|
||||
if(1 to 8) //modest
|
||||
size = breast_values[rounded_cached]
|
||||
if(9 to 15) //massive
|
||||
size = breast_values[rounded_cached]
|
||||
if(16 to 17) //ridiculous
|
||||
size = breast_values[rounded_cached]
|
||||
if(18 to 24) //AWOOOOGAAAAAAA
|
||||
size = "massive"
|
||||
if(25 to 29) //AWOOOOOOGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||
size = "giga"
|
||||
if(30 to INFINITY) //AWWWWWWWWWWWWWOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOGGGGGAAAAAAAAAAAAAAAAAAAAAA
|
||||
size = "impossible"
|
||||
|
||||
|
||||
if((rounded_cached < 18 || rounded_cached == 25 || rounded_cached == 30) && owner )//Because byond doesn't count from 0, I have to do this.
|
||||
if((rounded_size < 18 || rounded_size == 25 || rounded_size == 30) && owner )//Because byond doesn't count from 0, I have to do this.
|
||||
var/mob/living/carbon/human/H = owner
|
||||
var/r_prev_size = round(prev_size)
|
||||
if (rounded_cached > r_prev_size)
|
||||
to_chat(H, "<span class='warning'>Your breasts [pick("swell up to", "flourish into", "expand into", "burst forth into", "grow eagerly into", "amplify into")] a [uppertext(size)]-cup.</span>")
|
||||
else if (rounded_cached < r_prev_size)
|
||||
to_chat(H, "<span class='warning'>Your breasts [pick("shrink down to", "decrease into", "diminish into", "deflate into", "shrivel regretfully into", "contracts into")] a [uppertext(size)]-cup.</span>")
|
||||
if (rounded_size > r_prev_size)
|
||||
to_chat(H, "<span class='warning'>Your breasts [pick("swell up to", "flourish into", "expand into", "burst forth into", "grow eagerly into", "amplify into")] a [uppertext(size_state)]-cup.</span>")
|
||||
else if (rounded_size < r_prev_size)
|
||||
to_chat(H, "<span class='warning'>Your breasts [pick("shrink down to", "decrease into", "diminish into", "deflate into", "shrivel regretfully into", "contracts into")] a [uppertext(size_state)]-cup.</span>")
|
||||
|
||||
/obj/item/organ/genital/breasts/get_features(mob/living/carbon/human/H)
|
||||
var/datum/dna/D = H.dna
|
||||
@@ -120,16 +117,13 @@
|
||||
color = SKINTONE2HEX(H.skin_tone)
|
||||
else
|
||||
color = "#[D.features["breasts_color"]]"
|
||||
size = D.features["breasts_size"]
|
||||
size = GLOB.breast_values[D.features["breasts_size"]]
|
||||
max_size = D.features["breasts_max_size"]
|
||||
min_size = D.features["breasts_min_size"]
|
||||
shape = D.features["breasts_shape"]
|
||||
if(!D.features["breasts_producing"])
|
||||
genital_flags &= ~ (GENITAL_FUID_PRODUCTION|CAN_CLIMAX_WITH|CAN_MASTURBATE_WITH)
|
||||
if(!isnum(size))
|
||||
cached_size = breast_values[size]
|
||||
else
|
||||
cached_size = size
|
||||
size = breast_values[size]
|
||||
prev_size = cached_size
|
||||
prev_size = size
|
||||
toggle_visibility(D.features["breasts_visibility"], FALSE)
|
||||
if(D.features["breasts_stuffing"])
|
||||
toggle_visibility(GEN_ALLOW_EGG_STUFFING, FALSE)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
slot = ORGAN_SLOT_BUTT
|
||||
w_class = 3
|
||||
size = 0
|
||||
max_size = BUTT_SIZE_MAX
|
||||
var/size_name = "nonexistent"
|
||||
shape = "Pair" //turn this into a default constant if for some inexplicable reason we get more than one butt type but I doubt it.
|
||||
genital_flags = UPDATE_OWNER_APPEARANCE|GENITAL_UNDIES_HIDDEN|CAN_CUM_INTO|HAS_EQUIPMENT
|
||||
@@ -15,8 +16,8 @@
|
||||
var/prev_size //former size value, to allow update_size() to early return should be there no significant changes.
|
||||
layer_index = BUTT_LAYER_INDEX
|
||||
|
||||
/obj/item/organ/genital/butt/modify_size(modifier, min = -INFINITY, max = BUTT_SIZE_MAX)
|
||||
var/new_value = clamp(size_cached + modifier, min, max)
|
||||
/obj/item/organ/genital/butt/modify_size(modifier, min = -INFINITY, max = INFINITY)
|
||||
var/new_value = clamp(size_cached + modifier, max(min, min_size ? min_size : -INFINITY), min(max_size ? max_size : INFINITY, max))
|
||||
if(new_value == size_cached)
|
||||
return
|
||||
prev_size = size_cached
|
||||
@@ -88,6 +89,8 @@
|
||||
else
|
||||
color = "#[D.features["butt_color"]]"
|
||||
size = D.features["butt_size"]
|
||||
max_size = D.features["butt_max_size"]
|
||||
min_size = D.features["butt_min_size"]
|
||||
prev_size = size
|
||||
size_cached = size
|
||||
toggle_visibility(D.features["butt_visibility"], FALSE)
|
||||
|
||||
@@ -14,18 +14,20 @@
|
||||
shape = DEF_COCK_SHAPE
|
||||
size = 2 //arbitrary value derived from length and diameter for sprites.
|
||||
layer_index = PENIS_LAYER_INDEX
|
||||
var/length = 6 //inches
|
||||
|
||||
var/length = 6 //inches
|
||||
var/max_length = 9
|
||||
var/min_length = 2
|
||||
var/prev_length = 6 //really should be renamed to prev_length
|
||||
var/diameter = 4.38
|
||||
var/diameter_ratio = COCK_DIAMETER_RATIO_DEF //0.25; check citadel_defines.dm
|
||||
|
||||
/obj/item/organ/genital/penis/modify_size(modifier, min = -INFINITY, max = INFINITY)
|
||||
var/new_value = clamp(length + modifier, min, max)
|
||||
var/new_value = clamp(length + modifier, max(min, min_size ? min_size : -INFINITY), min(max_length ? max_length : INFINITY, max))
|
||||
if(new_value == length)
|
||||
return
|
||||
prev_length = length
|
||||
length = clamp(length + modifier, min, max)
|
||||
length = new_value
|
||||
update()
|
||||
..()
|
||||
|
||||
@@ -95,6 +97,8 @@
|
||||
else
|
||||
color = "#[D.features["cock_color"]]"
|
||||
length = D.features["cock_length"]
|
||||
max_length = D.features["cock_max_length"]
|
||||
min_length = D.features["cock_min_length"]
|
||||
diameter_ratio = D.features["cock_diameter_ratio"]
|
||||
shape = D.features["cock_shape"]
|
||||
prev_length = length
|
||||
|
||||
@@ -844,6 +844,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
tauric_shape = TRUE
|
||||
dat += "<b>Penis Shape:</b> <a style='display:block;width:120px' href='?_src_=prefs;preference=cock_shape;task=input'>[features["cock_shape"]][tauric_shape ? " (Taur)" : ""]</a>"
|
||||
dat += "<b>Penis Length:</b> <a style='display:block;width:120px' href='?_src_=prefs;preference=cock_length;task=input'>[features["cock_length"]] inch(es)</a>"
|
||||
dat += "<b>Max Length:</b><a style='display:block;width:120px' href='?_src_=prefs;preference=cock_max_length;task=input'>[features["cock_max_length"] ? features["cock_max_length"] : "Disabled"]</a>"
|
||||
dat += "<b>Min Length:</b><a style='display:block;width:120px' href='?_src_=prefs;preference=cock_min_length;task=input'>[features["cock_min_length"] ? features["cock_min_length"] : "Disabled"]</a>"
|
||||
dat += "<b>Diameter Ratio:</b> <a style='display:block;width:120px' href='?_src_=prefs;preference=cock_diameter_ratio;task=input'>[features["cock_diameter_ratio"]]</a>" //SPLURT Edit
|
||||
dat += "<b>Penis Visibility:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=cock_visibility;task=input'>[features["cock_visibility"]]</a>"
|
||||
dat += "<b>Egg Stuffing:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=cock_stuffing'>[features["cock_stuffing"] == TRUE ? "Yes" : "No"]</a>" //SPLURT Edit
|
||||
@@ -859,6 +861,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<b>Testicles Visibility:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=balls_visibility;task=input'>[features["balls_visibility"]]</a>"
|
||||
//SPLURT Edit
|
||||
dat += "<b>Egg Stuffing:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=balls_stuffing'>[features["balls_stuffing"] == TRUE ? "Yes" : "No"]</a>"
|
||||
dat += "<b>Max Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=balls_max_size;task=input'>[features["balls_max_size"] ? features["balls_max_size"] : "Disabled"]</a>"
|
||||
dat += "<b>Min Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=balls_min_size;task=input'>[features["balls_min_size"] ? features["balls_min_size"] : "Disabled"]</a>"
|
||||
dat += "<b>Produces:</b>"
|
||||
var/datum/reagent/balls_fluid = find_reagent_object_from_type(features["balls_fluid"])
|
||||
if(balls_fluid && (balls_fluid in GLOB.genital_fluids_list))
|
||||
@@ -907,6 +911,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<b>Lactates:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=breasts_producing'>[features["breasts_producing"] == TRUE ? "Yes" : "No"]</a>"
|
||||
//SPLURT Edit
|
||||
dat += "<b>Egg Stuffing:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=breasts_stuffing'>[features["breasts_stuffing"] == TRUE ? "Yes" : "No"]</a>"
|
||||
dat += "<b>Max Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=breasts_max_size;task=input'>[features["breasts_max_size"] ? features["breasts_max_size"] : "Disabled"]</a>"
|
||||
dat += "<b>Min Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=breasts_min_size;task=input'>[features["breasts_min_size"] ? features["breasts_min_size"] : "Disabled"]</a>"
|
||||
if(features["breasts_producing"] == TRUE)
|
||||
dat += "<b>Produces:</b>"
|
||||
var/datum/reagent/breasts_fluid = find_reagent_object_from_type(features["breasts_fluid"])
|
||||
@@ -930,6 +936,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<b>Butt Visibility:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=butt_visibility;task=input'>[features["butt_visibility"]]</a>"
|
||||
//SPLURT Edit
|
||||
dat += "<b>Egg Stuffing:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=butt_stuffing'>[features["butt_stuffing"] == TRUE ? "Yes" : "No"]</a>"
|
||||
dat += "<b>Max Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=butt_max_size;task=input'>[features["butt_max_size"] ? features["butt_max_size"] : "Disabled"]</a>"
|
||||
dat += "<b>Min Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=butt_min_size;task=input'>[features["butt_min_size"] ? features["butt_min_size"] : "Disabled"]</a>"
|
||||
dat += "<b>Butthole Sprite:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=has_anus'>[features["has_anus"] == TRUE ? "Yes" : "No"]</a>"
|
||||
if(features["has_anus"])
|
||||
dat += "<b>Butthole Color:</b></a><BR>"
|
||||
@@ -953,6 +961,8 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
dat += "<b>Color:</b></a><BR>"
|
||||
dat += "<span style='border: 1px solid #161616; background-color: #[features["belly_color"]];'><font color='[color_hex2num(features["belly_color"]) < 200 ? "FFFFFF" : "000000"]'>#[features["belly_color"]]</font></span> <a href='?_src_=prefs;preference=belly_color;task=input'>Change</a><br>"
|
||||
dat += "<b>Belly Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=belly_size;task=input'>[features["belly_size"]]</a>"
|
||||
dat += "<b>Max Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=belly_max_size;task=input'>[features["belly_max_size"] ? features["belly_max_size"] : "Disabled" ]</a>"
|
||||
dat += "<b>Min Size:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=belly_min_size;task=input'>[features["belly_min_size"] ? features["belly_min_size"] : "Disabled" ]</a>"
|
||||
dat += "<b>Belly Visibility:</b><a style='display:block;width:100px' href='?_src_=prefs;preference=belly_visibility;task=input'>[features["belly_visibility"]]</a>"
|
||||
dat += "<b>Egg Stuffing:</b><a style='display:block;width:50px' href='?_src_=prefs;preference=belly_stuffing'>[features["belly_stuffing"] == TRUE ? "Yes" : "No"]</a>"
|
||||
dat += "</td>"
|
||||
@@ -2987,6 +2997,82 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
if(n_vis)
|
||||
features["belly_visibility"] = n_vis
|
||||
|
||||
if("cock_max_length")
|
||||
var/max_B = CONFIG_GET(number/penis_max_inches_prefs)
|
||||
var/new_size = input(user, "Max size:\n([features["cock_length"]]-[max_B])(0 = disabled)", "Character Preference") as num|null
|
||||
if(new_size)
|
||||
features["cock_max_length"] = clamp(round(new_size), features["cock_length"], max_B)
|
||||
else
|
||||
features -= "cock_max_length"
|
||||
|
||||
if("balls_max_size")
|
||||
var/new_size = input(user, "Max size:\n([BALLS_SIZE_MIN]-[BALLS_SIZE_MAX])(0 = disabled)", "Character Preference") as num|null
|
||||
if(new_size)
|
||||
features["balls_max_size"] = clamp(round(new_size), BALLS_SIZE_MIN, BALLS_SIZE_MAX)
|
||||
else
|
||||
features -= "balls_max_size"
|
||||
|
||||
if("breasts_max_size")
|
||||
var/new_size = input(user, "Breast Max Size (cancel to disable)", "Character Preference") as null|anything in GLOB.breast_values
|
||||
if(new_size)
|
||||
features["breasts_max_size"] = new_size
|
||||
else
|
||||
features -= "breasts_max_size"
|
||||
|
||||
if("belly_max_size")
|
||||
var/max_B = CONFIG_GET(number/belly_max_size_prefs)
|
||||
var/new_size = input(user, "Max size:\n([features["belly_size"]]-[max_B])(0 = disabled)", "Character Preference") as num|null
|
||||
if(new_size)
|
||||
features["belly_max_size"] = clamp(round(new_size), features["belly_size"], max_B)
|
||||
else
|
||||
features -= "belly_max_size"
|
||||
|
||||
if("butt_max_size")
|
||||
var/max_B = CONFIG_GET(number/butt_max_size_prefs)
|
||||
var/new_size = input(user, "Max size:\n([features["butt_size"]]-[max_B])(0 = disabled)", "Character Preference") as num|null
|
||||
if(new_size)
|
||||
features["butt_max_size"] = clamp(round(new_size), features["butt_size"], max_B)
|
||||
else
|
||||
features -= "butt_max_size"
|
||||
|
||||
if("cock_min_length")
|
||||
var/min_B = CONFIG_GET(number/penis_min_inches_prefs)
|
||||
var/new_size = input(user, "Min size:\n([min_B]-[features["cock_length"]])(0 = disabled)", "Character Preference") as num|null
|
||||
if(new_size)
|
||||
features["cock_min_length"] = clamp(round(new_size), min_B, features["cock_length"])
|
||||
else
|
||||
features -= "cock_min_length"
|
||||
|
||||
if("balls_min_size")
|
||||
var/new_size = input(user, "Min size:\n([BALLS_SIZE_MIN]-[BALLS_SIZE_MAX])(0 = disabled)", "Character Preference") as num|null
|
||||
if(new_size)
|
||||
features["balls_min_size"] = clamp(round(new_size), BALLS_SIZE_MIN, BALLS_SIZE_MAX)
|
||||
else
|
||||
features -= "balls_min_size"
|
||||
|
||||
if("breasts_min_size")
|
||||
var/new_size = input(user, "Breast Min Size (cancel to disable)", "Character Preference") as null|anything in GLOB.breast_values
|
||||
if(new_size)
|
||||
features["breasts_min_size"] = new_size
|
||||
else
|
||||
features -= "breasts_min_size"
|
||||
|
||||
if("belly_min_size")
|
||||
var/min_B = CONFIG_GET(number/belly_min_size_prefs)
|
||||
var/new_size = input(user, "Min size:\n([min_B]-[features["belly_size"]])(0 = disabled)", "Character Preference") as num|null
|
||||
if(new_size)
|
||||
features["belly_min_size"] = clamp(round(new_size), min_B, features["belly_size"])
|
||||
else
|
||||
features -= "belly_min_size"
|
||||
|
||||
if("butt_min_size")
|
||||
var/min_B = CONFIG_GET(number/butt_min_size_prefs)
|
||||
var/new_size = input(user, "Min size:\n([min_B]-[features["butt_size"]])(0 = disabled)", "Character Preference") as num|null
|
||||
if(new_size)
|
||||
features["butt_min_size"] = clamp(round(new_size), min_B, features["butt_size"])
|
||||
else
|
||||
features -= "butt_min_size"
|
||||
|
||||
if("ooccolor")
|
||||
var/new_ooccolor = input(user, "Choose your OOC colour:", "Game Preference",ooccolor) as color|null
|
||||
if(new_ooccolor)
|
||||
@@ -4162,3 +4248,4 @@ GLOBAL_LIST_EMPTY(preferences_datums)
|
||||
#undef DEFAULT_SLOT_AMT
|
||||
#undef HANDS_SLOT_AMT
|
||||
#undef BACKPACK_SLOT_AMT
|
||||
|
||||
|
||||
@@ -1054,6 +1054,28 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
S["feature_inert_eggs"] >> features["inert_eggs"]
|
||||
|
||||
if(S["features_cock_max_length"])
|
||||
S["features_cock_max_length"] >> features["cock_max_length"]
|
||||
if(S["features_balls_max_size"])
|
||||
S["features_balls_max_size"] >> features["balls_max_size"]
|
||||
if(S["features_breasts_max_size"])
|
||||
S["features_breasts_max_size"] >> features["breasts_max_size"]
|
||||
if(S["features_belly_max_size"])
|
||||
S["features_belly_max_size"] >> features["belly_max_size"]
|
||||
if(S["features_butt_max_size"])
|
||||
S["features_butt_max_size"] >> features["butt_max_size"]
|
||||
|
||||
if(S["features_cock_min_length"])
|
||||
S["features_cock_min_length"] >> features["cock_min_length"]
|
||||
if(S["features_balls_min_size"])
|
||||
S["features_balls_min_size"] >> features["balls_min_size"]
|
||||
if(S["features_breasts_min_size"])
|
||||
S["features_breasts_min_size"] >> features["breasts_min_size"]
|
||||
if(S["features_belly_min_size"])
|
||||
S["features_belly_min_size"] >> features["belly_min_size"]
|
||||
if(S["features_butt_min_size"])
|
||||
S["features_butt_min_size"] >> features["butt_min_size"]
|
||||
|
||||
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))
|
||||
@@ -1413,6 +1435,19 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
|
||||
|
||||
WRITE_FILE(S["feature_inert_eggs"], features["inert_eggs"])
|
||||
|
||||
|
||||
WRITE_FILE(S["features_cock_max_length"], features["cock_max_length"])
|
||||
WRITE_FILE(S["features_balls_max_size"], features["balls_max_size"])
|
||||
WRITE_FILE(S["features_breasts_max_size"], features["breasts_max_size"])
|
||||
WRITE_FILE(S["features_belly_max_size"], features["belly_max_size"])
|
||||
WRITE_FILE(S["features_butt_max_size"], features["butt_max_size"])
|
||||
|
||||
WRITE_FILE(S["features_cock_min_length"], features["cock_min_length"])
|
||||
WRITE_FILE(S["features_balls_min_size"], features["balls_min_size"])
|
||||
WRITE_FILE(S["features_breasts_min_size"], features["breasts_min_size"])
|
||||
WRITE_FILE(S["features_belly_min_size"], features["belly_min_size"])
|
||||
WRITE_FILE(S["features_butt_min_size"], features["butt_min_size"])
|
||||
|
||||
WRITE_FILE(S["feature_neckfire"], features["neckfire"])
|
||||
WRITE_FILE(S["feature_neckfire_color"], features["neckfire_color"])
|
||||
|
||||
|
||||
@@ -68,8 +68,7 @@
|
||||
B.color = "#[M.dna.features["breasts_color"]]"
|
||||
else
|
||||
B.color = SKINTONE2HEX(H.skin_tone)
|
||||
B.size = "flat"
|
||||
B.cached_size = 0
|
||||
B.size = 0
|
||||
B.prev_size = 0
|
||||
to_chat(H, "<span class='warning'>Your chest feels warm, tingling with newfound sensitivity.</b></span>")
|
||||
H.reagents.remove_reagent(type, 5)
|
||||
@@ -145,12 +144,12 @@
|
||||
var/obj/item/organ/genital/breasts/B = M.getorganslot(ORGAN_SLOT_BREASTS)
|
||||
if(!B)
|
||||
return..()
|
||||
var/optimal_size = B.breast_values[M.dna.features["breasts_size"]]
|
||||
var/optimal_size = GLOB.breast_values[M.dna.features["breasts_size"]]
|
||||
if(!optimal_size)//Fast fix for those who don't want it.
|
||||
B.modify_size(-0.1)
|
||||
else if(B.cached_size > optimal_size)
|
||||
else if(B.size > optimal_size)
|
||||
B.modify_size(-0.05, optimal_size)
|
||||
else if(B.cached_size < optimal_size)
|
||||
else if(B.size < optimal_size)
|
||||
B.modify_size(0.05, 0, optimal_size)
|
||||
return ..()
|
||||
|
||||
@@ -238,7 +237,7 @@
|
||||
|
||||
if(B)
|
||||
B.modify_size(-0.05)
|
||||
if(V && (!B || B.cached_size <= 0))
|
||||
if(V && (!B || B.size <= 0))
|
||||
qdel(V)
|
||||
if(W && (!B || B.size <= 0))
|
||||
qdel(W)
|
||||
|
||||
@@ -136,14 +136,8 @@
|
||||
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)
|
||||
genital_entry["can_arouse"] = (
|
||||
!!CHECK_BITFIELD(genital.genital_flags, GENITAL_CAN_AROUSE) \
|
||||
&& !(HAS_TRAIT(get_genitals, TRAIT_PERMABONER) \
|
||||
@@ -169,37 +163,6 @@
|
||||
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 = self?.client.prefs
|
||||
if(prefs)
|
||||
//Getting char prefs
|
||||
@@ -294,28 +257,6 @@
|
||||
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 = parent_mob.client.prefs
|
||||
var/value = num_to_pref(params["value"])
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
if("f", "g", "h")
|
||||
modifier = 3
|
||||
else
|
||||
if(milkers.size in milkers.breast_values)
|
||||
modifier = clamp(milkers.breast_values[milkers.size] - 5, 0, INFINITY)
|
||||
if(milkers.size in GLOB.breast_values)
|
||||
modifier = clamp(GLOB.breast_values[milkers.size] - 5, 0, INFINITY)
|
||||
else
|
||||
modifier = 1
|
||||
target.reagents.add_reagent(milktype, rand(1,3 * modifier))
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
if("f", "g", "h")
|
||||
modifier = 3
|
||||
else
|
||||
if(B.size in B.breast_values)
|
||||
modifier = clamp(B.breast_values[B.size] - 5, 0, INFINITY)
|
||||
if(B.size in GLOB.breast_values)
|
||||
modifier = clamp(GLOB.breast_values[B.size] - 5, 0, INFINITY)
|
||||
else
|
||||
modifier = 1
|
||||
if(B.fluid_id)
|
||||
@@ -42,8 +42,8 @@
|
||||
if("f", "g", "h")
|
||||
modifier = 3
|
||||
else
|
||||
if(B.size in B.breast_values)
|
||||
modifier = clamp(B.breast_values[B.size] - 5, 0, INFINITY)
|
||||
if(B.size in GLOB.breast_values)
|
||||
modifier = clamp(GLOB.breast_values[B.size] - 5, 0, INFINITY)
|
||||
else
|
||||
modifier = 1
|
||||
if(B.fluid_id)
|
||||
@@ -63,8 +63,8 @@
|
||||
if("f", "g", "h")
|
||||
modifier = 3
|
||||
else
|
||||
if(B.size in B.breast_values)
|
||||
modifier = clamp(B.breast_values[B.size] - 5, 0, INFINITY)
|
||||
if(B.size in GLOB.breast_values)
|
||||
modifier = clamp(GLOB.breast_values[B.size] - 5, 0, INFINITY)
|
||||
else
|
||||
modifier = 1
|
||||
if(B.fluid_id)
|
||||
|
||||
@@ -79,8 +79,8 @@
|
||||
if("f", "g", "h")
|
||||
modifier = 3
|
||||
else
|
||||
if(milkers.size in milkers.breast_values)
|
||||
modifier = clamp(milkers.breast_values[milkers.size] - 5, 0, INFINITY)
|
||||
if(milkers.size in GLOB.breast_values)
|
||||
modifier = clamp(GLOB.breast_values[milkers.size] - 5, 0, INFINITY)
|
||||
else
|
||||
modifier = 1
|
||||
user.reagents.add_reagent(milktype, rand(1,3 * modifier))
|
||||
|
||||
@@ -15,3 +15,5 @@ GLOBAL_LIST_INIT(breast_nouns, list("breasts", "boobs", "honkers", "tatas", "tid
|
||||
GLOBAL_LIST_INIT(balls_nouns, list("balls", "nuts", "ballsack", "testicles", "sack", "cum orbs", "cum spheres", "cum tanks", "cum holders", "cum churners", "spunk orbs", "spunk spheres", "spunk tanks", "spunk holders", "spunk churners", "nut orbs", "nut spheres", "nut tanks", "nut holders", "nut churners", "jizz orbs", "jizz spheres", "jizz tanks", "jizz holders", "jizz churners", "seed orbs", "seed spheres", "seed tanks", "seed holders", "seed churners"))
|
||||
|
||||
GLOBAL_LIST_INIT(butt_nouns, list("ass", "butt", "dumptruck", "tush", "badonk", "booty", "rump", "behind"))
|
||||
|
||||
GLOBAL_LIST_INIT(breast_values, list("a" = 1, "b" = 2, "c" = 3, "d" = 4, "e" = 5, "f" = 6, "g" = 7, "h" = 8, "i" = 9, "j" = 10, "k" = 11, "l" = 12, "m" = 13, "n" = 14, "o" = 15, "huge" = 16, "massive" = 17, "giga" = 25, "impossible" = 30, "flat" = 0))
|
||||
|
||||
213
modular_splurt/code/datums/genitals/genitals_interface.dm
Normal file
213
modular_splurt/code/datums/genitals/genitals_interface.dm
Normal file
@@ -0,0 +1,213 @@
|
||||
/// Attempts to open the tgui menu
|
||||
/mob/living/verb/genital_menu()
|
||||
set name = "Genitals Menu"
|
||||
set desc = "Manage your genital, or someone else's."
|
||||
set category = "IC"
|
||||
set src in view(usr.client)
|
||||
|
||||
if(!iscarbon(usr))
|
||||
return
|
||||
if(!usr.mind) //Mindless boys, honestly just don't, it's better this way
|
||||
return
|
||||
if(!usr.mind.genitals_menu_holder)
|
||||
usr.mind.genitals_menu_holder= new(usr.mind)
|
||||
|
||||
usr.mind.genitals_menu_holder.target = src
|
||||
usr.mind.genitals_menu_holder.ui_interact(usr)
|
||||
|
||||
/datum/mind
|
||||
var/datum/genitals_menu/genitals_menu_holder
|
||||
|
||||
/datum/mind/New(key)
|
||||
. = ..()
|
||||
genitals_menu_holder = new(src)
|
||||
|
||||
/datum/genitals_menu
|
||||
var/mob/living/carbon/target
|
||||
|
||||
/datum/genitals_menu/ui_state(mob/user)
|
||||
return GLOB.conscious_state
|
||||
|
||||
/datum/genitals_menu/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "GenitalConfig", "Genitals")
|
||||
ui.open()
|
||||
|
||||
/datum/genitals_menu/ui_data(mob/user)
|
||||
. = ..()
|
||||
var/mob/living/carbon/genital_holder = target || user
|
||||
var/user_is_target = genital_holder == user
|
||||
.["istargetself"] = user_is_target
|
||||
if(!user_is_target)
|
||||
.["target_name"] = genital_holder.name
|
||||
var/list/genitals = list()
|
||||
for(var/obj/item/organ/genital/genital in genital_holder.internal_organs) //Only get the genitals
|
||||
if(CHECK_BITFIELD(genital.genital_flags, GENITAL_INTERNAL)) //Not those though
|
||||
continue
|
||||
|
||||
var/list/genital_entry = list()
|
||||
genital_entry["img"] = icon2base64(getFlatIcon(genital, no_anim=TRUE))
|
||||
genital_entry["name"] = "[capitalize(genital.name)]" //Prevents code from adding a prefix
|
||||
genital_entry["key"] = REF(genital) //The key is the reference to the object
|
||||
|
||||
genital_entry["description"] = genital.desc + "\n [genital.linked_organ ? "Linked organ: [genital.linked_organ.name]" : ""]"
|
||||
|
||||
if(user_is_target)
|
||||
var/visibility = "Invalid"
|
||||
if(CHECK_BITFIELD(genital.genital_flags, GENITAL_THROUGH_CLOTHES))
|
||||
visibility = "Always visible"
|
||||
else if(CHECK_BITFIELD(genital.genital_flags, GENITAL_UNDIES_HIDDEN))
|
||||
visibility = "Hidden by underwear"
|
||||
else if(CHECK_BITFIELD(genital.genital_flags, GENITAL_HIDDEN))
|
||||
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)
|
||||
genital_entry["can_arouse"] = (
|
||||
!!CHECK_BITFIELD(genital.genital_flags, GENITAL_CAN_AROUSE) \
|
||||
&& !(HAS_TRAIT(genital_holder, TRAIT_PERMABONER) \
|
||||
|| HAS_TRAIT(genital_holder, TRAIT_NEVERBONER)))
|
||||
genital_entry["arousal_state"] = genital.aroused_state
|
||||
if(istype(genital, /obj/item/organ/genital/penis))
|
||||
var/obj/item/organ/genital/penis/peepee = genital
|
||||
genital_entry["max_size"] = peepee.max_length ? peepee.max_length : 0
|
||||
genital_entry["min_size"] = peepee.min_length ? peepee.min_length : 0
|
||||
else
|
||||
genital_entry["max_size"] = genital.max_size ? genital.max_size : 0
|
||||
genital_entry["min_size"] = genital.min_size ? genital.min_size : 0
|
||||
|
||||
//fluids
|
||||
if(CHECK_BITFIELD(genital.genital_flags, GENITAL_FUID_PRODUCTION) || CHECK_BITFIELD(genital?.linked_organ?.genital_flags, GENITAL_FUID_PRODUCTION))
|
||||
var/fluids = genital.get_fluid_fraction()
|
||||
genital_entry["fluid"] = fluids
|
||||
|
||||
//equipments
|
||||
if(genital.is_exposed())
|
||||
var/list/equipments = list()
|
||||
for(var/obj/equipment in genital.contents)
|
||||
var/list/equipment_entry = list()
|
||||
equipment_entry["name"] = equipment.name
|
||||
equipment_entry["key"] = REF(equipment)
|
||||
equipments += list(equipment_entry)
|
||||
genital_entry["possible_equipment_choices"] = GLOB.genitals_interactions
|
||||
genital_entry["equipments"] = equipments
|
||||
|
||||
genitals += list(genital_entry)
|
||||
|
||||
if(!genital_holder.getorganslot(ORGAN_SLOT_ANUS) && user_is_target)
|
||||
var/simulated_ass = list()
|
||||
simulated_ass["name"] = "Anus"
|
||||
simulated_ass["key"] = "anus"
|
||||
var/visibility = "Invalid"
|
||||
switch(genital_holder.anus_exposed)
|
||||
if(1)
|
||||
visibility = "Always visible"
|
||||
if(0)
|
||||
visibility = "Hidden by underwear"
|
||||
else
|
||||
visibility = "Always hidden"
|
||||
simulated_ass["visibility"] = visibility
|
||||
simulated_ass["possible_choices"] = GLOB.genitals_visibility_toggles - GEN_VISIBLE_NO_CLOTHES
|
||||
genitals += list(simulated_ass)
|
||||
.["genitals"] = genitals
|
||||
|
||||
/datum/genitals_menu/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
|
||||
if(..())
|
||||
return
|
||||
switch(action)
|
||||
if("genital")
|
||||
var/mob/living/carbon/self = usr
|
||||
if(self != target)
|
||||
return FALSE
|
||||
if("visibility" in params)
|
||||
if(params["genital"] == "anus")
|
||||
self.anus_toggle_visibility(params["visibility"])
|
||||
return TRUE
|
||||
var/obj/item/organ/genital/genital = locate(params["genital"], self.internal_organs)
|
||||
if(genital && (genital in self.internal_organs))
|
||||
genital.toggle_visibility(params["visibility"])
|
||||
return TRUE
|
||||
if("set_arousal" in params)
|
||||
var/obj/item/organ/genital/genital = locate(params["genital"], self.internal_organs)
|
||||
if(!genital || (genital \
|
||||
&& (!CHECK_BITFIELD(genital.genital_flags, GENITAL_CAN_AROUSE) \
|
||||
|| HAS_TRAIT(self, TRAIT_PERMABONER) \
|
||||
|| HAS_TRAIT(self, TRAIT_NEVERBONER))))
|
||||
return FALSE
|
||||
var/original_state = genital.aroused_state
|
||||
genital.set_aroused_state(params["set_arousal"])// i'm not making it just `!aroused_state` because
|
||||
if(original_state != genital.aroused_state) // someone just might port skyrat's new genitals
|
||||
to_chat(self, "<span class='userlove'>[genital.aroused_state ? genital.arousal_verb : genital.unarousal_verb].</span>")
|
||||
. = TRUE
|
||||
else
|
||||
to_chat(self, "<span class='userlove'>You can't make that genital [genital.aroused_state ? "unaroused" : "aroused"]!</span>")
|
||||
. = FALSE
|
||||
genital.update_appearance()
|
||||
if(ishuman(self))
|
||||
var/mob/living/carbon/human/human = self
|
||||
human.update_genitals()
|
||||
return
|
||||
if("max_size" in params)
|
||||
var/obj/item/organ/genital/genital = locate(params["genital"], self.internal_organs)
|
||||
if(!genital)
|
||||
return FALSE
|
||||
if(istype(genital, /obj/item/organ/genital/penis))
|
||||
var/obj/item/organ/genital/penis/peepee = genital
|
||||
if(params["max_size"])
|
||||
var/new_max_size = clamp(params["max_size"], peepee.length, INFINITY)
|
||||
peepee.max_length = new_max_size
|
||||
else
|
||||
peepee.max_length = 0
|
||||
else
|
||||
if(params["max_size"])
|
||||
var/new_max_size = clamp(params["max_size"], genital.size, INFINITY)
|
||||
genital.max_size = new_max_size
|
||||
else
|
||||
genital.max_size = 0
|
||||
if("min_size" in params)
|
||||
var/obj/item/organ/genital/genital = locate(params["genital"], self.internal_organs)
|
||||
if(!genital)
|
||||
return FALSE
|
||||
if(istype(genital, /obj/item/organ/genital/penis))
|
||||
var/obj/item/organ/genital/penis/peepee = genital
|
||||
var/new_min_size = clamp(params["min_size"], 0, peepee.length)
|
||||
peepee.min_length = new_min_size
|
||||
else
|
||||
var/new_min_size = clamp(params["min_size"], 0, genital.size)
|
||||
genital.min_size = new_min_size
|
||||
else
|
||||
return FALSE
|
||||
if("equipment")
|
||||
var/mob/living/carbon/actual_target = target || usr
|
||||
var/mob/living/carbon/self = usr
|
||||
if(get_dist(actual_target, self) > 1)
|
||||
to_chat(self, span_warning("You're too far away!"))
|
||||
return FALSE
|
||||
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["equipment_action"])
|
||||
if("remove")
|
||||
var/obj/item/selected_item = locate(params["equipment"], genital.contents)
|
||||
if(selected_item)
|
||||
if(!do_mob(self, actual_target, 5 SECONDS))
|
||||
return FALSE
|
||||
if(!self.put_in_hands(selected_item))
|
||||
self.transferItemToLoc(get_turf(self))
|
||||
return TRUE
|
||||
return FALSE
|
||||
if("insert")
|
||||
var/obj/item/stuff = self.get_active_held_item()
|
||||
if(!istype(stuff))
|
||||
to_chat(self, span_warning("You need to hold an item to insert it!"))
|
||||
return FALSE
|
||||
stuff.insert_item_organ(self, self, genital)
|
||||
@@ -139,7 +139,7 @@
|
||||
for(var/obj/item/organ/genital/genital in buckled_mob.internal_organs)
|
||||
if(istype(genital, /obj/item/organ/genital/breasts))
|
||||
var/obj/item/organ/genital/breasts/breasts = genital
|
||||
points_awarded += breasts.fluid_rate + breasts.breast_values[breasts.size] // Breasts use letters instead of numbers!
|
||||
points_awarded += breasts.fluid_rate + GLOB.breast_values[breasts.size]
|
||||
continue
|
||||
points_awarded += genital.fluid_rate + genital.size
|
||||
points_awarded *= tier
|
||||
|
||||
@@ -55,10 +55,17 @@
|
||||
return
|
||||
|
||||
if(locate(src.type) in target_organ.contents)
|
||||
to_chat(user, span_notice("\The <b>[target]</b>'s [target_organ] already has a rod inside!"))
|
||||
if(user == target)
|
||||
to_chat(user, span_notice("You already have a rod inside your [target_organ]!"))
|
||||
else
|
||||
to_chat(user, span_notice("\The <b>[target]</b>'s [target_organ] already has a rod inside!"))
|
||||
return
|
||||
|
||||
target.visible_message(span_warning("\The <b>[user]</b> is trying to insert a rod inside \the <b>[target]</b>!"),\
|
||||
if(user == target)
|
||||
target.visible_message(span_warning("\The <b>[user]</b> is trying to insert a rod inside themselves!"),\
|
||||
span_warning("You try to insert a rod inside yourself!"))
|
||||
else
|
||||
target.visible_message(span_warning("\The <b>[user]</b> is trying to insert a rod inside \the <b>[target]</b>!"),\
|
||||
span_warning("\The <b>[user]</b> is trying to insert a rod inside you!"))
|
||||
|
||||
if(!do_mob(user, target, 4 SECONDS))
|
||||
@@ -81,15 +88,18 @@
|
||||
return
|
||||
|
||||
if(locate(src.type) in target_organ.contents)
|
||||
to_chat(user, span_notice("\The <b>[target]</b>'s [target_organ] already has a vibrator inside!"))
|
||||
if(user == target)
|
||||
to_chat(user, span_notice("You already have a vibrator inside your [target_organ]!"))
|
||||
else
|
||||
to_chat(user, span_notice("\The <b>[target]</b>'s [target_organ] already has a vibrator inside!"))
|
||||
return
|
||||
|
||||
if(style == "long")
|
||||
target.visible_message(span_warning("\The <b>[user]</b> is trying to insert a vibrator inside \the <b>[target]</b>!"),\
|
||||
span_warning("\The <b>[user]</b> is trying to insert a vibrator inside you!"))
|
||||
if(user == target)
|
||||
target.visible_message(span_warning("\The <b>[user]</b> is trying to [style == "long" ? "insert" : "attach"] a vibrator [style == "long" ? "inside" : "to"] themselves!"),\
|
||||
span_warning("You try to [style == "long" ? "insert" : "attach"] a vibrator [style == "long" ? "inside" : "to"] yourself!"))
|
||||
else
|
||||
target.visible_message(span_userlove("\The <b>[user]</b> is trying to attach a vibrator to \the <b>[target]</b>!"),\
|
||||
span_warning("\The <b>[user]</b> is trying to attach a vibrator to you!"))
|
||||
target.visible_message(span_warning("\The <b>[user]</b> is trying to [style == "long" ? "insert" : "attach"] a vibrator [style == "long" ? "inside" : "to"] \the <b>[target]</b>!"),\
|
||||
span_warning("\The <b>[user]</b> is trying to [style == "long" ? "insert" : "attach"] a vibrator [style == "long" ? "inside" : "to"] you!"))
|
||||
|
||||
if(!do_mob(user, target, 5 SECONDS))
|
||||
return
|
||||
@@ -115,7 +125,11 @@
|
||||
to_chat(user, span_warning("This genital can't be stuffed!"))
|
||||
return
|
||||
|
||||
target.visible_message(span_warning("\The <b>[user]</b> is trying to insert an egg inside \the <b>[target]</b>!"),\
|
||||
if(user == target)
|
||||
target.visible_message(span_warning("\The <b>[user]</b> is trying to insert an egg inside themselves!"),\
|
||||
span_warning("You try to insert an egg inside yourself!"))
|
||||
else
|
||||
target.visible_message(span_warning("\The <b>[user]</b> is trying to insert an egg inside \the <b>[target]</b>!"),\
|
||||
span_warning("\The <b>[user]</b> is trying to insert an egg inside you!"))
|
||||
|
||||
if(!do_mob(user, target, 5 SECONDS))
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
if(do_after(src, rand(10, 20), 0, target)) //did they get deleted in that second?
|
||||
// var/main_fluid = lowertext(fluid_source.get_master_reagent_name()) // doesn't work no more (should delete probably)
|
||||
var/main_fluid = G.get_fluid_name()
|
||||
var/fluid_ammount = clamp((G.fluid_rate * ((world.time - G.last_orgasmed) / (10 SECONDS)) * G.fluid_mult),0,G.fluid_max_volume)
|
||||
var/fluid_ammount = G.get_fluid()
|
||||
if (fluid_ammount <= 2)
|
||||
to_chat(src, span_revennotice("[target.p_their(TRUE)] [G.name] spasms pitifully, almost nothing will come out."))
|
||||
else
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
/obj/item/organ/genital
|
||||
var/max_size = 6
|
||||
var/min_size = 1
|
||||
var/datum/reagents/climax_fluids
|
||||
var/datum/reagent/original_fluid_id
|
||||
var/datum/reagent/default_fluid_id
|
||||
@@ -10,6 +12,15 @@
|
||||
fluid_max_volume += (modifier*2.5)*(get_size(owner)-1)
|
||||
fluid_rate += (modifier/10)*(get_size(owner)-1)
|
||||
|
||||
/obj/item/organ/genital/proc/size_to_state()
|
||||
return size
|
||||
|
||||
/obj/item/organ/genital/proc/get_fluid()
|
||||
return clamp(fluid_rate * ((world.time - last_orgasmed) / (10 SECONDS)) * fluid_mult, 0, fluid_max_volume)
|
||||
|
||||
/obj/item/organ/genital/proc/get_fluid_fraction()
|
||||
return get_fluid() / fluid_max_volume
|
||||
|
||||
/obj/item/organ/genital/proc/climax_modify_size(mob/living/partner, obj/item/organ/genital/source_gen)
|
||||
return
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
if(!owner)
|
||||
return
|
||||
|
||||
/obj/item/organ/genital/belly/modify_size(modifier, min = -INFINITY, max = BELLY_SIZE_MAX)
|
||||
var/new_value = clamp(size_cached + modifier, min, max)
|
||||
/obj/item/organ/genital/belly/modify_size(modifier, min = -INFINITY, max = INFINITY)
|
||||
var/new_value = clamp(size_cached + modifier, max(min, min_size ? min_size : -INFINITY), min(max_size ? max_size : INFINITY, max))
|
||||
if(new_value == size_cached)
|
||||
return
|
||||
prev_size = size_cached
|
||||
@@ -95,6 +95,8 @@
|
||||
else
|
||||
color = "#[D.features["belly_color"]]"
|
||||
size = D.features["belly_size"]
|
||||
max_size = D.features["belly_max_size"]
|
||||
min_size = D.features["belly_min_size"]
|
||||
prev_size = size
|
||||
size_cached = size
|
||||
original_fluid_id = fluid_id
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
fluid_id = initial(fluid_id)
|
||||
original_fluid_id = fluid_id
|
||||
. = ..()
|
||||
fluid_max_volume += ((cached_size - breast_values[initial(size)])*2.5)*(owner ? get_size(owner) : 1)
|
||||
fluid_rate += ((cached_size - breast_values[initial(size)])/10)*(owner ? get_size(owner) : 1)
|
||||
fluid_max_volume += ((size - initial(size))*2.5)*(owner ? get_size(owner) : 1)
|
||||
fluid_rate += ((size - initial(size))/10)*(owner ? get_size(owner) : 1)
|
||||
|
||||
/obj/item/organ/genital/breasts/climax_modify_size(mob/living/partner, obj/item/organ/genital/source_gen)
|
||||
if(!(owner.client?.prefs.cit_toggles & BREAST_ENLARGEMENT))
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
/obj/item/organ/genital/testicles
|
||||
default_fluid_id = /datum/reagent/consumable/semen
|
||||
|
||||
/obj/item/organ/genital/testicles/get_fluid()
|
||||
if(linked_organ)
|
||||
return clamp(linked_organ.fluid_rate * ((world.time - linked_organ.last_orgasmed) / (10 SECONDS)) * linked_organ.fluid_mult, 0, linked_organ.fluid_max_volume)
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/item/organ/genital/testicles/get_fluid_fraction()
|
||||
if(linked_organ)
|
||||
return get_fluid() / linked_organ.fluid_max_volume
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/item/organ/genital/testicles/get_features(mob/living/carbon/human/H)
|
||||
var/datum/dna/D = H.dna
|
||||
if(D.features["balls_fluid"])
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
/obj/item/organ/genital/womb
|
||||
default_fluid_id = /datum/reagent/consumable/semen/femcum
|
||||
|
||||
/obj/item/organ/genital/womb/get_fluid()
|
||||
if(linked_organ)
|
||||
return clamp(linked_organ.fluid_rate * ((world.time - linked_organ.last_orgasmed) / (10 SECONDS)) * linked_organ.fluid_mult, 0, linked_organ.fluid_max_volume)
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/item/organ/genital/womb/get_fluid_fraction()
|
||||
if(linked_organ)
|
||||
return get_fluid() / linked_organ.fluid_max_volume
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/item/organ/genital/womb/get_features(mob/living/carbon/human/H)
|
||||
var/datum/dna/D = H.dna
|
||||
if(D.features["womb_fluid"])
|
||||
|
||||
@@ -4350,6 +4350,7 @@
|
||||
#include "modular_splurt\code\datums\elements\smalltalk.dm"
|
||||
#include "modular_splurt\code\datums\elements\spooky.dm"
|
||||
#include "modular_splurt\code\datums\elements\wuv.dm"
|
||||
#include "modular_splurt\code\datums\genitals\genitals_interface.dm"
|
||||
#include "modular_splurt\code\datums\interactions\cuddling.dm"
|
||||
#include "modular_splurt\code\datums\interactions\rope.dm"
|
||||
#include "modular_splurt\code\datums\interactions\lewd\_lewd.dm"
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// Themes
|
||||
import './styles/main.scss';
|
||||
import './styles/themes/abductor.scss';
|
||||
import './styles/themes/hotpink.scss';
|
||||
import './styles/themes/cardtable.scss';
|
||||
import './styles/themes/hackerman.scss';
|
||||
import './styles/themes/malfunction.scss';
|
||||
|
||||
313
tgui/packages/tgui/interfaces/GenitalConfig.tsx
Normal file
313
tgui/packages/tgui/interfaces/GenitalConfig.tsx
Normal file
@@ -0,0 +1,313 @@
|
||||
|
||||
import { filter } from 'common/collections';
|
||||
import { flow } from 'common/fp';
|
||||
import { createSearch } from 'common/string';
|
||||
import { useBackend, useLocalState } from '../backend';
|
||||
import { BlockQuote, Button, LabeledList, Icon, NumberInput, Input, Section, Table, Tabs, Stack, ProgressBar, Divider } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
|
||||
type GenitalInfo = {
|
||||
istargetself: boolean,
|
||||
target_name: String,
|
||||
genitals: GenitalData[];
|
||||
}
|
||||
|
||||
type GenitalData = {
|
||||
img: string,
|
||||
name: string,
|
||||
key: string,
|
||||
description: string,
|
||||
visibility: string,
|
||||
extras: string,
|
||||
extra_choices: string[],
|
||||
possible_choices: string[],
|
||||
can_arouse: boolean,
|
||||
arousal_state: boolean,
|
||||
fluid: number,
|
||||
possible_equipment_choices: string[],
|
||||
min_size: number,
|
||||
max_size: number,
|
||||
equipments: Equipment[],
|
||||
}
|
||||
|
||||
type Equipment = {
|
||||
name: string,
|
||||
key: string,
|
||||
}
|
||||
|
||||
export const GenitalConfig = (props, context) => {
|
||||
const { act, data } = useBackend<GenitalInfo>(context);
|
||||
const genitals = data.genitals || [];
|
||||
const [tabIndex, setTabIndex] = useLocalState(context, 'tabIndex', 0);
|
||||
return (
|
||||
<Window
|
||||
width={850}
|
||||
height={600}
|
||||
theme="hotpink"
|
||||
resizable>
|
||||
<Window.Content scrollable={false}>
|
||||
{data.target_name ? (
|
||||
<Section>
|
||||
Interacting with <b>{data.target_name}</b>
|
||||
</Section>
|
||||
) : null}
|
||||
{genitals.length ? (
|
||||
<>
|
||||
<Section title="Genital">
|
||||
<Stack vertical>
|
||||
<Stack.Item>
|
||||
<Tabs fluid textAlign="center">
|
||||
{genitals.map((genital, index) => (
|
||||
<Tabs.Tab
|
||||
key={index}
|
||||
selected={tabIndex === index}
|
||||
onClick={() => setTabIndex(index)}
|
||||
>
|
||||
{genital.name}
|
||||
</Tabs.Tab>
|
||||
))}
|
||||
</Tabs>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
{genitals[tabIndex].description}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Section>
|
||||
<Section title="Settings">
|
||||
<Stack grow>
|
||||
<Stack.Item grow>
|
||||
<Stack vertical>
|
||||
<Stack.Item>
|
||||
<Section>
|
||||
Fluid level:
|
||||
<ProgressBar
|
||||
key={genitals[tabIndex].key}
|
||||
value={
|
||||
genitals[tabIndex].fluid
|
||||
? genitals[tabIndex].fluid
|
||||
: 0.0
|
||||
}
|
||||
color="white"
|
||||
/>
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
{data.istargetself
|
||||
? <SelfConfig /> : null}
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Section>
|
||||
<Section
|
||||
title="Items Inserted"
|
||||
buttons={(
|
||||
<Button
|
||||
fluid
|
||||
content="Insert Item"
|
||||
onClick={() => act('equipment', {
|
||||
genital: genitals[tabIndex].key,
|
||||
equipment_action: "insert",
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
<Equipments />
|
||||
</Section>
|
||||
</>
|
||||
) : (
|
||||
<Section align="center">
|
||||
{data.target_name ? "They" : "You"} don't seem to have any genitals...
|
||||
Or any that you could interact with.
|
||||
</Section>
|
||||
)}
|
||||
</Window.Content>
|
||||
</Window>
|
||||
);
|
||||
};
|
||||
|
||||
const SelfConfig = (props, context) => {
|
||||
const [tabIndex] = useLocalState(context, 'tabIndex', 0);
|
||||
const { act, data } = useBackend<GenitalInfo>(context);
|
||||
const genital = data.genitals[tabIndex];
|
||||
return (
|
||||
<Stack.Item>
|
||||
<Stack grow>
|
||||
{genital.img ? (
|
||||
<Stack.Item>
|
||||
<img
|
||||
src={`data:image/jpeg;base64,${genital.img}`}
|
||||
style={{
|
||||
'vertical-align': 'middle',
|
||||
'horizontal-align': 'middle',
|
||||
}} />
|
||||
</Stack.Item>
|
||||
) : null}
|
||||
{typeof genital.max_size === "number" ? (
|
||||
<Stack.Item>
|
||||
<SizeButtons />
|
||||
</Stack.Item>
|
||||
) : null}
|
||||
<Stack.Item grow>
|
||||
<ToggleSettings />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
);
|
||||
};
|
||||
|
||||
const SizeButtons = (props, context) => {
|
||||
const [tabIndex] = useLocalState(context, 'tabIndex', 0);
|
||||
const { act, data } = useBackend<GenitalInfo>(context);
|
||||
const genital = data.genitals[tabIndex];
|
||||
return (
|
||||
<Section>
|
||||
<Stack>
|
||||
<Stack.Item>
|
||||
<Stack vertical>
|
||||
Max growth:
|
||||
<NumberInput
|
||||
value={genital.max_size}
|
||||
onChange={(e, value) => act('genital', {
|
||||
genital: genital.key,
|
||||
max_size: value,
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Stack vertical>
|
||||
Min shrink:
|
||||
<NumberInput
|
||||
value={genital.min_size}
|
||||
onChange={(e, value) => act('genital', {
|
||||
genital: genital.key,
|
||||
min_size: value,
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</Stack>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
|
||||
const ModeToIcon = {
|
||||
"Always visible": "eye",
|
||||
"Hidden by clothes": "tshirt",
|
||||
"Hidden by underwear": "low-vision",
|
||||
"Always hidden": "eye-slash",
|
||||
"Allows egg stuffing": "egg",
|
||||
};
|
||||
|
||||
const ToggleSettings = (props, context) => {
|
||||
const [tabIndex] = useLocalState(context, 'tabIndex', 0);
|
||||
const { act, data } = useBackend<GenitalInfo>(context);
|
||||
const genital = data.genitals[tabIndex];
|
||||
return (
|
||||
<Stack grow>
|
||||
{genital.possible_choices.map(choice => (
|
||||
<Stack.Item key={choice} grow>
|
||||
<Button
|
||||
textAlign="center"
|
||||
key={choice}
|
||||
tooltip={choice}
|
||||
icon={ModeToIcon[choice]}
|
||||
color={genital.visibility === choice ? "green" : "default"}
|
||||
onClick={() => act('genital', {
|
||||
genital: genital.key,
|
||||
visibility: choice,
|
||||
})}
|
||||
fluid
|
||||
/>
|
||||
</Stack.Item>
|
||||
))}
|
||||
<Stack.Item grow>
|
||||
<Button
|
||||
textAlign="center"
|
||||
key={genital.arousal_state}
|
||||
tooltip={genital.can_arouse
|
||||
? ((genital.arousal_state ? "Unarouse" : "Arouse") + " your " + genital.name.toLowerCase())
|
||||
: "You cannot modify arousal on your " + genital.name.toLowerCase()}
|
||||
icon="heart"
|
||||
color={genital.can_arouse ? (genital.arousal_state ? "green" : "default") : "grey"}
|
||||
onClick={() => act('genital', {
|
||||
genital: genital.key,
|
||||
set_arousal: !genital.arousal_state,
|
||||
})}
|
||||
fluid
|
||||
/>
|
||||
</Stack.Item>
|
||||
{genital.extra_choices instanceof Array
|
||||
? genital.extra_choices.map(choice => (
|
||||
<Stack.Item key={choice} grow>
|
||||
<Button
|
||||
textAlign="center"
|
||||
key={choice}
|
||||
tooltip={choice}
|
||||
icon={ModeToIcon[choice]}
|
||||
color={genital.extras === choice ? "green" : "default"}
|
||||
onClick={() => act('genital', {
|
||||
genital: genital.key,
|
||||
visibility: choice,
|
||||
})}
|
||||
fluid
|
||||
/>
|
||||
</Stack.Item>
|
||||
)) : null}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
const Equipments = (props, context) => {
|
||||
const [tabIndex] = useLocalState(context, 'tabIndex', 0);
|
||||
const { act, data } = useBackend<GenitalInfo>(context);
|
||||
const genital = data.genitals[tabIndex];
|
||||
const [searchText, setSearchText] = useLocalState(context, 'searchText', '');
|
||||
const items = prepareSearch(genital.equipments, searchText) || [];
|
||||
return (
|
||||
<Stack vertical>
|
||||
<Stack.Item>
|
||||
<Input
|
||||
fluid
|
||||
placeholder="Search for items.."
|
||||
onInput={(e, value) => setSearchText(value)}
|
||||
/>
|
||||
</Stack.Item>
|
||||
<Stack.Item>
|
||||
<Table mb={1}>
|
||||
{items.map((item, index) =>
|
||||
(
|
||||
<Table.Row key={index} className="candystripe">
|
||||
<Table.Cell bold>
|
||||
{item.name}
|
||||
</Table.Cell>
|
||||
<Table.Cell collapsing textAlign="center">
|
||||
<Button
|
||||
fluid
|
||||
content="Remove"
|
||||
onClick={() => act('equipment', {
|
||||
equipment: item.key,
|
||||
genital: genital.key,
|
||||
equipment_action: "remove",
|
||||
})}
|
||||
/>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
)
|
||||
)}
|
||||
</Table>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export const prepareSearch = (items, searchText = '') => {
|
||||
const testSearch = createSearch<Equipment>(searchText,
|
||||
item => item.name);
|
||||
return flow([
|
||||
// Optional search term
|
||||
searchText && filter(testSearch),
|
||||
])(items);
|
||||
};
|
||||
@@ -35,33 +35,12 @@ type GenitalData = {
|
||||
name: string,
|
||||
key: string,
|
||||
visibility: string,
|
||||
extras: string,
|
||||
extra_choices: string[],
|
||||
possible_choices: string[],
|
||||
can_arouse: boolean,
|
||||
arousal_state: boolean,
|
||||
always_accessible: boolean,
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -111,7 +90,7 @@ export const MobInteraction = (props, context) => {
|
||||
|
||||
return (
|
||||
<Window
|
||||
width={530}
|
||||
width={430}
|
||||
height={700}
|
||||
resizable>
|
||||
<Window.Content overflow="auto">
|
||||
@@ -167,9 +146,6 @@ export const MobInteraction = (props, context) => {
|
||||
<Tabs.Tab selected={tabIndex === 3} onClick={() => setTabIndex(3)}>
|
||||
Preferences
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab selected={tabIndex === 4} onClick={() => setTabIndex(4)}>
|
||||
Genital Manager
|
||||
</Tabs.Tab>
|
||||
</Tabs>
|
||||
{tabIndex === 0 && (
|
||||
<InteractionsTab />
|
||||
@@ -179,8 +155,6 @@ export const MobInteraction = (props, context) => {
|
||||
<CharacterPrefsTab />
|
||||
) || tabIndex === 3 && (
|
||||
<ContentPreferencesTab />
|
||||
) || tabIndex === 4 && (
|
||||
<GenitalManagerTab />
|
||||
) || ("Somehow, you've got into an invalid page, please report this.")}
|
||||
</Section>
|
||||
</Window.Content>
|
||||
@@ -263,7 +237,6 @@ const ModeToIcon = {
|
||||
"Hidden by clothes": "tshirt",
|
||||
"Hidden by underwear": "low-vision",
|
||||
"Always hidden": "eye-slash",
|
||||
"Allows egg stuffing": "egg",
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -315,19 +288,6 @@ const GenitalTab = (props, context) => {
|
||||
genital: genital.key,
|
||||
set_arousal: !genital.arousal_state,
|
||||
})} />
|
||||
{genital.extra_choices instanceof Array
|
||||
? genital.extra_choices.map(choice => (
|
||||
<Button
|
||||
width="50%"
|
||||
key={choice}
|
||||
tooltip={choice}
|
||||
icon={ModeToIcon[choice]}
|
||||
color={genital.extras === choice ? "green" : "default"}
|
||||
onClick={() => act('genital', {
|
||||
genital: genital.key,
|
||||
visibility: choice,
|
||||
})} />
|
||||
)) : null}
|
||||
<Button
|
||||
width="49%"
|
||||
key={genital.always_accessible}
|
||||
@@ -354,71 +314,6 @@ const GenitalTab = (props, context) => {
|
||||
);
|
||||
};
|
||||
|
||||
const GenitalManagerTab = (props, context) => {
|
||||
const { act, data } = useBackend<GenitalManagerInfo>(context);
|
||||
const isTargetSelf = data.isTargetSelf;
|
||||
const genital_fluids = data.genital_fluids || [];
|
||||
const genital_interactibles = data.genital_interactibles || [];
|
||||
return (
|
||||
genital_fluids.length || genital_interactibles.length ? (
|
||||
<>
|
||||
<Section title="Genital Fluids">
|
||||
<LabeledList>
|
||||
{genital_fluids.map(genital => (
|
||||
<LabeledList.Item key={genital['key']} label={genital['name']}>
|
||||
<ProgressBar
|
||||
key={genital['key']}
|
||||
value={genital['fluid'] ? genital['fluid'] : 0.0}
|
||||
color="white" />
|
||||
</LabeledList.Item>
|
||||
))}
|
||||
</LabeledList>
|
||||
</Section>
|
||||
<Section title="Actions">
|
||||
{genital_interactibles.map(genital => (
|
||||
<Section key={genital.key} title={genital.name}>
|
||||
{
|
||||
genital.equipments.length ? (
|
||||
<>
|
||||
<b>Equipments:</b>
|
||||
<Table direction="column">
|
||||
{genital.equipments.map(equipment => (
|
||||
<TableRow key={equipment}>
|
||||
{equipment}
|
||||
</TableRow>
|
||||
))}
|
||||
</Table>
|
||||
<Divider />
|
||||
</>
|
||||
) : null
|
||||
}
|
||||
|
||||
{genital.possible_choices.map(choice => (
|
||||
<Button
|
||||
key={choice}
|
||||
content={choice}
|
||||
tooltip={choice}
|
||||
onClick={() => act('genital_interaction', {
|
||||
genital: genital.key,
|
||||
action: choice,
|
||||
})} />
|
||||
))}
|
||||
</Section>
|
||||
))}
|
||||
</Section>
|
||||
</>
|
||||
) : (
|
||||
<Section align="center">
|
||||
{
|
||||
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"
|
||||
}
|
||||
</Section>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
const CharacterPrefsTab = (props, context) => {
|
||||
const { act, data } = useBackend<CharacterPrefsInfo>(context);
|
||||
const {
|
||||
@@ -430,7 +325,7 @@ const CharacterPrefsTab = (props, context) => {
|
||||
extreme_harm,
|
||||
} = data;
|
||||
return (
|
||||
<Stack direction="column">
|
||||
<Flex direction="column">
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="ERP Preference">
|
||||
<Button
|
||||
@@ -566,7 +461,7 @@ const CharacterPrefsTab = (props, context) => {
|
||||
</LabeledList.Item>
|
||||
) : (null)}
|
||||
</LabeledList>
|
||||
</Stack>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
54
tgui/packages/tgui/styles/themes/hotpink.scss
Normal file
54
tgui/packages/tgui/styles/themes/hotpink.scss
Normal file
@@ -0,0 +1,54 @@
|
||||
@use 'sass:color';
|
||||
@use 'sass:meta';
|
||||
|
||||
@use '../colors.scss' with (
|
||||
$primary: #ae4ab8,
|
||||
$fg-map-keys: (),
|
||||
$bg-map-keys: (),
|
||||
);
|
||||
@use '../base.scss' with (
|
||||
$color-bg: #662a6b,
|
||||
$color-bg-grad-spread: 6%,
|
||||
$border-radius: 2px,
|
||||
);
|
||||
|
||||
.theme-hotpink {
|
||||
// Atomic classes
|
||||
@include meta.load-css('../atomic/color.scss');
|
||||
|
||||
// Components
|
||||
@include meta.load-css('../components/Button.scss', $with: (
|
||||
'color-default': colors.$primary,
|
||||
'color-disabled': #363636,
|
||||
'color-selected': #465899,
|
||||
'color-caution': #be09a6,
|
||||
'color-danger': #be0909,
|
||||
));
|
||||
@include meta.load-css('../components/Input.scss', $with: (
|
||||
'border-color': colors.$primary,
|
||||
));
|
||||
@include meta.load-css('../components/NoticeBox.scss', $with: (
|
||||
'background-color': #a82d55,
|
||||
));
|
||||
@include meta.load-css('../components/NumberInput.scss', $with: (
|
||||
'border-color': colors.$primary,
|
||||
));
|
||||
@include meta.load-css('../components/ProgressBar.scss', $with: (
|
||||
'background-color': rgba(0, 0, 0, 0.5),
|
||||
));
|
||||
@include meta.load-css('../components/Section.scss');
|
||||
@include meta.load-css('../components/Tooltip.scss', $with: (
|
||||
'background-color': #a82d55,
|
||||
));
|
||||
|
||||
// Layouts
|
||||
@include meta.load-css('../layouts/Layout.scss');
|
||||
@include meta.load-css('../layouts/Window.scss');
|
||||
@include meta.load-css('../layouts/TitleBar.scss', $with: (
|
||||
'background-color': colors.$primary,
|
||||
));
|
||||
|
||||
.Layout__content {
|
||||
background-image: none;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user