diff --git a/code/__DEFINES/~~~splurt_defines/DNA.dm b/code/__DEFINES/~~~splurt_defines/DNA.dm
index 5f6e5f3bfe859..e2bef644ca42f 100644
--- a/code/__DEFINES/~~~splurt_defines/DNA.dm
+++ b/code/__DEFINES/~~~splurt_defines/DNA.dm
@@ -1,3 +1,12 @@
+///Upstream edits
+//Sizecode
+#undef BODY_SIZE_MAX
+#undef BODY_SIZE_MIN
+
+#define BODY_SIZE_MAX CONFIG_GET(number/body_size_max)
+#define BODY_SIZE_MIN CONFIG_GET(number/body_size_min)
+
+
///arachnid organ slots
#define ORGAN_SLOT_EXTERNAL_MANDIBLES "mandibles"
#define ORGAN_SLOT_EXTERNAL_SPINNERET "spinneret"
diff --git a/code/__DEFINES/~~~splurt_defines/dcs/signals.dm b/code/__DEFINES/~~~splurt_defines/dcs/signals.dm
new file mode 100644
index 0000000000000..83d0cbf595380
--- /dev/null
+++ b/code/__DEFINES/~~~splurt_defines/dcs/signals.dm
@@ -0,0 +1,13 @@
+/*
+ * # COMSIG_MICRO_PICKUP_FEET
+ * From /datum/element/mob_holder/micro
+ * Used by signals for determining whether you can pick up someone with your feet, kinky.
+*/
+#define COMSIG_MICRO_PICKUP_FEET "micro_force_grabbed"
+
+/*
+ * # COMSIG_MOB_RESIZED
+ * From /mob/living
+ * Used by signals for whenever a mob has changed sizes.
+*/
+#define COMSIG_MOB_RESIZED "mob_resized"
diff --git a/code/__DEFINES/~~~splurt_defines/sizecode.dm b/code/__DEFINES/~~~splurt_defines/sizecode.dm
new file mode 100644
index 0000000000000..20a7bd30d1a00
--- /dev/null
+++ b/code/__DEFINES/~~~splurt_defines/sizecode.dm
@@ -0,0 +1,46 @@
+//I am not a coder. Please fucking tear apart my code, and insult me for how awful I am at coding. Please and thank you. -Dahlular
+//alright bet -BoxBoy
+#define RESIZE_MACRO 6
+#define RESIZE_HUGE 4
+#define RESIZE_BIG 2
+#define RESIZE_NORMAL 1
+#define RESIZE_SMALL 0.75
+#define RESIZE_TINY 0.50
+#define RESIZE_MICRO 0.25
+
+//averages
+#define RESIZE_A_MACROHUGE (RESIZE_MACRO + RESIZE_HUGE) / 2
+#define RESIZE_A_HUGEBIG (RESIZE_HUGE + RESIZE_BIG) / 2
+#define RESIZE_A_BIGNORMAL (RESIZE_BIG + RESIZE_NORMAL) / 2
+#define RESIZE_A_NORMALSMALL (RESIZE_NORMAL + RESIZE_SMALL) / 2
+#define RESIZE_A_SMALLTINY (RESIZE_SMALL + RESIZE_TINY) / 2
+#define RESIZE_A_TINYMICRO (RESIZE_TINY + RESIZE_MICRO) / 2
+
+/*
+ * # get_size(mob/living/target)
+ * Grabs the size of your critter, works for any living creature even carbons with dna
+ * Now, please don't tell me your creature has a dna but it's very snowflakey, then i say you should rewrite your mob
+ * instead of touching this file.
+*/
+/proc/get_size(mob/living/target)
+ if(!target)
+ CRASH("get_size(NULL) was called")
+ if(!istype(target))
+ CRASH("get_size() called with an invalid target, only use this for /mob/living!")
+ var/datum/dna/has_dna = target.has_dna()
+ if(ishuman(target) && has_dna)
+ return has_dna.features["body_size"]
+ else
+ return target.size_multiplier
+
+/*
+ * # COMPARE_SIZES(mob/living/user, mob/living/target)
+ * Returns how bigger or smaller the target is in comparison to user
+ * Example:
+ * - user = 2, target = 1, result = 0.5
+ * - user = 1, target = 2, result = 2
+ * Args:
+ * - user = /mob/living
+ * - target = /mob/living
+*/
+#define COMPARE_SIZES(user, target) abs((get_size(user) / get_size(target)))
diff --git a/code/datums/dna.dm b/code/datums/dna.dm
index 43e105dacbd0a..b1a9598bc216b 100644
--- a/code/datums/dna.dm
+++ b/code/datums/dna.dm
@@ -135,7 +135,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block())
//SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION
destination.dna.mutant_bodyparts = mutant_bodyparts.Copy()
destination.dna.body_markings = body_markings.Copy()
- destination.dna.update_body_size()
+ // destination.dna.update_body_size() //SPLURT EDIT
//SKYRAT EDIT ADDITION END
if(transfer_SE)
destination.dna.mutation_index = mutation_index
diff --git a/code/datums/mutations/body.dm b/code/datums/mutations/body.dm
index a3ecf3df70931..b564ed70037d1 100644
--- a/code/datums/mutations/body.dm
+++ b/code/datums/mutations/body.dm
@@ -199,7 +199,7 @@
return
// SKYRAT EDIT END
ADD_TRAIT(owner, TRAIT_GIANT, GENETIC_MUTATION)
- owner.update_transform(1.25)
+ // owner.update_transform(1.25) //SPLURT EDIT
owner.visible_message(span_danger("[owner] suddenly grows!"), span_notice("Everything around you seems to shrink.."))
/datum/mutation/human/gigantism/on_losing(mob/living/carbon/human/owner)
diff --git a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm
index f936caa1d51ef..4a27ceac39484 100644
--- a/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm
+++ b/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm
@@ -36,7 +36,7 @@
animal.health = min(animal.maxHealth, animal.health * 1.5)
animal.melee_damage_lower = max((animal.melee_damage_lower * 2), 10)
animal.melee_damage_upper = max((animal.melee_damage_upper * 2), 10)
- animal.update_transform(2)
+ // animal.update_transform(2) //SPLURT EDIT
animal.AddElement(/datum/element/wall_tearer)
to_chat(user, span_info("You increase the size of [animal], giving [animal.p_them()] a surge of strength!"))
qdel(src)
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index c3a4544e50718..fbd19dff25496 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -51,6 +51,12 @@
if (length(status_examines))
. += status_examines
+ //SPLURT EDIT ADDITION - Sizecode
+ var/list/size_examines = get_size_examine_info(user)
+ if (length(size_examines))
+ . += size_examines
+ //SPLURT EDIT ADDITION END
+
if(get_bodypart(BODY_ZONE_HEAD) && !get_organ_by_type(/obj/item/organ/internal/brain))
. += span_deadsay("It appears that [t_his] brain is missing...")
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index d7564c4d3ed06..ed7cb625f0b7c 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -220,6 +220,13 @@
if(moving_diagonally)//no mob swap during diagonal moves.
return TRUE
+ //SPLURT EDIT ADDITION BEGIN - FEATURE_NAME - (sizecode)
+ //handle micro bumping on help intent
+ if(resolve_intent_name(combat_mode) == "help")
+ if(handle_micro_bump_helping(M))
+ return TRUE
+ //SPLURT EDIT ADDITION END
+
if(!M.buckled && !M.has_buckled_mobs())
if(can_mobswap_with(M))
//switch our position with M
@@ -254,6 +261,10 @@
//not if he's not CANPUSH of course
if(!(M.status_flags & CANPUSH))
return TRUE
+ //SPLURT EDIT ADDITION BEGIN - FEATURE_NAME - (sizecode)
+ if(handle_micro_bump_other(M))
+ return TRUE
+ //SPLURT EDIT ADDITION END
if(isliving(M))
var/mob/living/L = M
if(HAS_TRAIT(L, TRAIT_PUSHIMMUNE))
@@ -2034,11 +2045,6 @@ GLOBAL_LIST_EMPTY(fire_appearances)
if(NAMEOF(src, body_position))
set_body_position(var_value)
. = TRUE
- if(NAMEOF(src, current_size))
- if(var_value == 0) //prevents divisions of and by zero.
- return FALSE
- update_transform(var_value/current_size)
- . = TRUE
if(!isnull(.))
datum_flags |= DF_VAR_EDITED
diff --git a/config/config.txt b/config/config.txt
index 5aa4b1073493e..fed4b53870d8e 100644
--- a/config/config.txt
+++ b/config/config.txt
@@ -13,6 +13,7 @@ $include auxtools.txt
# SPLURT configs
$include splurt/discord.txt
+$include splurt/fetish_content.txt
# You can use the @ character at the beginning of a config option to lock it from being edited in-game
# Example usage:
diff --git a/config/splurt/fetish_content.txt b/config/splurt/fetish_content.txt
new file mode 100644
index 0000000000000..8de4731cd6da0
--- /dev/null
+++ b/config/splurt/fetish_content.txt
@@ -0,0 +1,11 @@
+## Body size configs, the feature will be disabled if both min and max have the same value.
+BODY_SIZE_MIN 0.1
+BODY_SIZE_MAX 2.00
+
+## Multiplier used in the smaller strides slowdown calculation.
+## Doesn't apply to floating or crawling mobs.
+BODY_SIZE_SLOWDOWN_MULTIPLIER 0
+
+## Macro health size cap ##
+## Macros no longer get more health after their size reaches this value ##
+#MACRO_HEALTH_CAP 3.5
diff --git a/modular_skyrat/master_files/code/modules/client/preferences/body_size.dm b/modular_skyrat/master_files/code/modules/client/preferences/body_size.dm
index afb8364f20cb4..02dbb1dde79e2 100644
--- a/modular_skyrat/master_files/code/modules/client/preferences/body_size.dm
+++ b/modular_skyrat/master_files/code/modules/client/preferences/body_size.dm
@@ -2,8 +2,12 @@
category = PREFERENCE_CATEGORY_SECONDARY_FEATURES
savefile_identifier = PREFERENCE_CHARACTER
savefile_key = "body_size"
+ //SPLURT EDIT CHANGE - Sizecode
+ /*
minimum = BODY_SIZE_MIN
maximum = BODY_SIZE_MAX
+ */
+ //SPLURT EDIT END
step = 0.01
/datum/preference/numeric/body_size/is_accessible(datum/preferences/preferences)
diff --git a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm
index 78627bf7ff635..e081de6452c4d 100644
--- a/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm
+++ b/modular_skyrat/modules/customization/modules/mob/living/carbon/human/species/roundstartslime.dm
@@ -318,8 +318,13 @@
alterer.remove_quirk(/datum/quirk/oversized)
new_body_size = new_body_size * 0.01
+ //SPLURT EDIT CHANGE - Sizecode
+ /*
alterer.dna.features["body_size"] = new_body_size
alterer.dna.update_body_size()
+ */
+ alterer.update_size(new_body_size)
+ //SPLURT EDIT CHANGE END
if("Genitals")
alter_genitals(alterer)
diff --git a/modular_zubbers/code/datums/components/vore/vore.dm b/modular_zubbers/code/datums/components/vore/vore.dm
index a2f94d0f05af1..825a2a14181ae 100644
--- a/modular_zubbers/code/datums/components/vore/vore.dm
+++ b/modular_zubbers/code/datums/components/vore/vore.dm
@@ -370,19 +370,20 @@
return FALSE
return TRUE
-/datum/component/vore/proc/vore_other()
+/datum/component/vore/proc/vore_other(mob/living/prey)
var/mob/living/pred = parent
- if(!check_vore_grab(pred))
+ if(!prey)
+ prey = pred.pulling
+ if(!check_vore_grab(pred) && !istype(prey.loc, /obj/item/clothing/head/mob_holder))
to_chat(parent, span_danger("You must have a[ishuman(pred) ? "n aggressive" : ""] grab to eat someone."))
return
- var/mob/living/prey = pred.pulling
if(!check_vore_preferences(parent, pred, prey))
return
#ifdef VORE_DELAY
pred.visible_message(span_danger("[pred] is attempting to [lowertext(selected_belly.insert_verb)] [prey] into their [lowertext(selected_belly.name)]!"), pref_to_check = /datum/preference/toggle/erp/vore_enable)
if(!do_after(pred, VORE_DELAY, prey))
return
- if(!check_vore_grab(pred) || !check_vore_preferences(parent, pred, prey, assume_active_consent = TRUE))
+ if((!check_vore_grab(pred) && !istype(prey.loc, /obj/item/clothing/head/mob_holder)) || !check_vore_preferences(parent, pred, prey, assume_active_consent = TRUE))
return
#endif
pred.visible_message(span_danger("[pred] manages to [lowertext(selected_belly.insert_verb)] [prey] into their [lowertext(selected_belly.name)]!"), pref_to_check = /datum/preference/toggle/erp/vore_enable)
@@ -408,14 +409,15 @@
prey.visible_message(span_danger("[prey] manages to make [pred] [lowertext(pred_component.selected_belly.insert_verb)] [prey] into their [lowertext(pred_component.selected_belly.name)]!"), pref_to_check = /datum/preference/toggle/erp/vore_enable)
pred_component.complete_vore(prey)
-/datum/component/vore/proc/feed_other_to_other(mob/living/pred)
+/datum/component/vore/proc/feed_other_to_other(mob/living/pred, mob/living/prey)
var/mob/living/feeder = parent
- if(!check_vore_grab(feeder))
+ if(!prey)
+ prey = feeder.pulling
+ if(!check_vore_grab(feeder) && !istype(prey.loc, /obj/item/clothing/head/mob_holder))
to_chat(feeder, span_danger("You must have a[ishuman(feeder) ? "n aggressive" : ""] grab to feed someone to someone else."))
return
if(!feeder.can_perform_action(pred, pred.interaction_flags_click | FORBID_TELEKINESIS_REACH))
return
- var/mob/living/prey = feeder.pulling
if(!check_vore_preferences(feeder, pred, prey))
return
// check_vore_preferences asserts this exists
@@ -424,7 +426,7 @@
feeder.visible_message(span_danger("[feeder] is attempting to make [pred] [lowertext(pred_component.selected_belly.insert_verb)] [prey] into their [lowertext(pred_component.selected_belly.name)]!"), pref_to_check = /datum/preference/toggle/erp/vore_enable)
if(!do_after(feeder, VORE_DELAY, pred))
return
- if(!check_vore_grab(feeder) || !check_vore_preferences(feeder, pred, prey, assume_active_consent = TRUE))
+ if((!check_vore_grab(pred) && !istype(prey.loc, /obj/item/clothing/head/mob_holder)) || !check_vore_preferences(feeder, pred, prey, assume_active_consent = TRUE))
return
if(!feeder.can_perform_action(pred, pred.interaction_flags_click | FORBID_TELEKINESIS_REACH))
return
diff --git a/modular_zzplurt/code/controllers/configuration/entries/fetish_content.dm b/modular_zzplurt/code/controllers/configuration/entries/fetish_content.dm
new file mode 100644
index 0000000000000..c5a5f6fbd34ef
--- /dev/null
+++ b/modular_zzplurt/code/controllers/configuration/entries/fetish_content.dm
@@ -0,0 +1,20 @@
+//Body size configs, the feature will be disabled if both min and max have the same value.
+/datum/config_entry/number/body_size_min
+ default = 0.8
+ min_val = 0.1 //to avoid issues with zeros and negative values.
+ max_val = RESIZE_DEFAULT_SIZE
+ integer = FALSE
+
+/datum/config_entry/number/body_size_max
+ default = 1.5
+ min_val = RESIZE_DEFAULT_SIZE
+ integer = FALSE
+
+/datum/config_entry/number/body_size_slowdown_multiplier
+ default = 0
+ min_val = 0
+ integer = FALSE
+
+/datum/config_entry/number/macro_health_cap
+ default = 3.5 //21 ft
+ integer = FALSE
diff --git a/modular_zzplurt/code/datums/dna.dm b/modular_zzplurt/code/datums/dna.dm
new file mode 100644
index 0000000000000..9d9f249ef313a
--- /dev/null
+++ b/modular_zzplurt/code/datums/dna.dm
@@ -0,0 +1,64 @@
+/datum/dna
+ var/last_capped_size //For some reason this feels dirty... I suppose it should go somewhere else
+
+/datum/dna/transfer_identity(mob/living/carbon/destination, transfer_SE, transfer_species)
+ var/old_size = destination.dna.features["body_size"]
+ . = ..()
+ destination.update_size(get_size(destination), old_size)
+
+/mob/living/carbon/human/hardset_dna(unique_identity, list/mutation_index, list/default_mutation_genes, newreal_name, newblood_type, datum/species/mrace, newfeatures, list/mutations, force_transfer_mutations)
+ var/old_size = dna.features["body_size"]
+ . = ..()
+ update_size(get_size(src), old_size)
+
+/datum/dna/copy_dna(datum/dna/new_dna)
+ . = ..()
+ if(holder)
+ holder.adjust_mobsize(get_size(holder))
+
+/datum/dna/update_body_size()
+ if(!holder || species.body_size_restricted || current_body_size == features["body_size"])
+ return ..()
+
+ holder.remove_movespeed_modifier(/datum/movespeed_modifier/small_stride)
+
+ . = ..()
+
+ if(get_size(holder) >= (RESIZE_A_BIGNORMAL + RESIZE_NORMAL) / 2)
+ holder.small_sprite.Grant(holder)
+ else
+ holder.small_sprite.Remove(holder)
+
+ if(!iscarbon(holder))
+ return
+
+ /* Needs genital updates
+ var/mob/living/carbon/C = holder
+ for(var/obj/item/organ/genital/G in C.internal_organs)
+ if(istype(G))
+ G.update()
+ */
+
+ var/new_slowdown = (abs(get_size(holder) - 1) * CONFIG_GET(number/body_size_slowdown_multiplier))
+ holder.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/small_stride, TRUE, new_slowdown)
+
+ var/size_cap = CONFIG_GET(number/macro_health_cap)
+ if((size_cap > 0) && (get_size(holder) > size_cap))
+ last_capped_size = (last_capped_size ? last_capped_size : current_body_size)
+ return
+ if(last_capped_size)
+ current_body_size = last_capped_size
+ last_capped_size = null
+ var/healthmod_old = ((current_body_size * 75) - 75)
+ var/healthmod_new = ((get_size(holder) * 75) - 75)
+ var/healthchange = healthmod_new - healthmod_old
+ holder.maxHealth += healthchange
+ holder.health += healthchange
+
+/mob/living/carbon/set_species(datum/species/mrace, icon_update, pref_load, list/override_features, list/override_mutantparts, list/override_markings)
+ . = ..()
+ adjust_mobsize(get_size(src))
+
+/datum/preference/choiced/species/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/prefs)
+ . = ..()
+ target.adjust_mobsize(get_size(target))
diff --git a/modular_zzplurt/code/datums/elements/holder_micro.dm b/modular_zzplurt/code/datums/elements/holder_micro.dm
new file mode 100644
index 0000000000000..2dd3eef7c5c96
--- /dev/null
+++ b/modular_zzplurt/code/datums/elements/holder_micro.dm
@@ -0,0 +1,244 @@
+/datum/element/mob_holder/micro
+
+/datum/element/mob_holder/micro/Attach(datum/target, worn_state, alt_worn, right_hand, left_hand, inv_slots = NONE, proctype, escape_on_find)
+ . = ..()
+
+ RegisterSignal(target, COMSIG_CLICK_ALT, PROC_REF(mob_try_pickup_micro), TRUE)
+ RegisterSignal(target, COMSIG_MICRO_PICKUP_FEET, PROC_REF(mob_pickup_micro_feet))
+ RegisterSignal(target, COMSIG_MOB_RESIZED, PROC_REF(on_resize))
+
+/datum/element/mob_holder/micro/Detach(datum/source, force)
+ . = ..()
+ UnregisterSignal(source, COMSIG_MICRO_PICKUP_FEET)
+
+/datum/element/mob_holder/micro/proc/on_resize(mob/living/micro, new_size, old_size)
+ var/obj/item/clothing/head/mob_holder/holder = micro.loc
+ if(istype(holder))
+ var/mob/living/living = get_atom_on_turf(micro.loc, /mob/living)
+ if(living && (COMPARE_SIZES(living, micro)) < 2.0)
+ living.visible_message(span_warning("\The [living] drops [micro] as [micro.p_they()] grow\s too big to carry."),
+ span_warning("You drop \The [living] as [living.p_they()] grow\s too big to carry."))
+ holder.release()
+ else if(!istype(living)) // Somehow a inside a mob_holder and the mob_holder isn't inside any livings? release.
+ holder.release()
+
+/datum/element/mob_holder/micro/on_examine(mob/living/source, mob/user, list/examine_list)
+ if(ishuman(user) && !istype(source.loc, /obj/item/clothing/head/mob_holder) && (COMPARE_SIZES(user, source)) >= 2.0)
+ examine_list += span_notice("Looks like [source.p_they(FALSE)] can be picked up using Alt+Click and grab intent!")
+
+/// Do not inherit from /mob_holder, interactions are different.
+/datum/element/mob_holder/micro/on_requesting_context_from_item(
+ obj/source,
+ list/context,
+ obj/item/held_item,
+ mob/living/user,
+)
+
+ LAZYSET(context, SCREENTIP_CONTEXT_ALT_LMB, "Pick up")
+ return CONTEXTUAL_SCREENTIP_SET
+
+/datum/element/mob_holder/micro/proc/mob_pickup_micro(mob/living/source, mob/user)
+ var/obj/item/clothing/head/mob_holder/micro/holder = new(get_turf(source), source, worn_state, alt_worn, right_hand, left_hand, inv_slots)
+ if(!holder)
+ return
+
+ user.put_in_hands(holder)
+ return
+
+//shoehorned (get it?) and lazy way to do instant foot pickups cause haha funny.
+/datum/element/mob_holder/micro/proc/mob_pickup_micro_feet(mob/living/source, mob/user)
+ var/obj/item/clothing/head/mob_holder/micro/holder = new(get_turf(source), source, worn_state, alt_worn, right_hand, left_hand, inv_slots)
+ if(!holder)
+ return
+ user.equip_to_slot(holder, ITEM_SLOT_FEET)
+ return
+
+/datum/element/mob_holder/micro/proc/mob_try_pickup_micro(mob/living/carbon/source, mob/living/carbon/user)
+ if(!(resolve_intent_name(user.combat_mode) == "grab"))
+ return FALSE
+ if(!ishuman(user) || !user.Adjacent(source) || user.incapacitated)
+ return FALSE
+ if(source == user)
+ to_chat(user, span_warning("You can't pick yourself up."))
+ source.balloon_alert(user, "cannot pick yourself!")
+ return FALSE
+ if(COMPARE_SIZES(user, source) < 2.0)
+ to_chat(user, span_warning("They're too big to pick up!"))
+ source.balloon_alert(user, "too big to pick up!")
+ return FALSE
+ if(user.get_active_held_item())
+ to_chat(user, span_warning("Your hands are full!"))
+ source.balloon_alert(user, "hands are full!")
+ return FALSE
+ if(source.buckled)
+ to_chat(user, span_warning("[source] is buckled to something!"))
+ source.balloon_alert(user, "buckled to something!")
+ return FALSE
+ source.visible_message(span_warning("[user] starts picking up [source]."), \
+ span_userdanger("[user] starts picking you up!"))
+ source.balloon_alert(user, "picking up")
+ var/time_required = COMPARE_SIZES(source, user) * 4 SECONDS //Scale how fast the pickup will be depending on size difference
+ if(!do_after(user, time_required, source))
+ return FALSE
+
+ if(user.get_active_held_item())
+ to_chat(user, span_warning("Your hands are full!"))
+ source.balloon_alert(user, "hands full!")
+ return FALSE
+ if(source.buckled)
+ to_chat(user, span_warning("[source] is buckled to something!"))
+ source.balloon_alert(user, "buckled!")
+ return FALSE
+
+ source.visible_message(span_warning("[user] picks up [source]!"),
+ span_userdanger("[user] picks you up!"))
+ source.drop_all_held_items()
+ mob_pickup_micro(source, user)
+ return TRUE
+
+/obj/item/clothing/head/mob_holder/micro
+ name = "micro"
+ desc = "Another person, small enough to fit in your hand."
+ icon = null
+ icon_state = null
+ worn_icon = null
+ inhand_icon_state = null
+ lefthand_file = null
+ righthand_file = null
+ slot_flags = ITEM_SLOT_FEET | ITEM_SLOT_HEAD | ITEM_SLOT_ID | ITEM_SLOT_BACK | ITEM_SLOT_NECK
+ w_class = null //handled by their size
+ item_flags = INEDIBLE_CLOTHING
+
+/obj/item/clothing/head/mob_holder/micro/Initialize(mapload, mob/living/M, worn_state, head_icon, lh_icon, rh_icon, worn_slot_flags)
+ . = ..()
+ item_flags &= ~ABSTRACT
+ //Updating the visuals when the mob updates doesn't work (it disappears)
+ //RegisterSignals(held_mob, list(COMSIG_CARBON_APPLY_OVERLAY, COMSIG_CARBON_REMOVE_OVERLAY, COMSIG_ATOM_EXAMINE), PROC_REF(update_visuals))
+
+/obj/item/clothing/head/mob_holder/micro/release(del_on_release, display_messages)
+ UnregisterSignal(held_mob, list(COMSIG_MOB_EQUIPPED_ITEM, COMSIG_MOB_UNEQUIPPED_ITEM))
+ return ..()
+
+/obj/item/clothing/head/mob_holder/micro/Destroy()
+ UnregisterSignal(src, COMSIG_ATOM_EXAMINE)
+ . = ..()
+
+/obj/item/clothing/head/mob_holder/micro/examine(mob/user)
+ return held_mob.examine(user)
+
+/obj/item/clothing/head/mob_holder/micro/container_resist_act(mob/living/resisting)
+ if(resisting.incapacitated)
+ to_chat(resisting, span_warning("You can't escape while you're restrained like this!"))
+ return
+ var/mob/living/carrier = get_atom_on_turf(src, /mob/living)
+ visible_message(span_warning("[resisting] begins to squirm in [carrier]'s grasp!"))
+ var/time_required = COMPARE_SIZES(carrier, resisting) / 4 SECONDS //Scale how fast the resisting will be depending on size difference
+ if(!do_after(resisting, time_required, carrier, IGNORE_TARGET_LOC_CHANGE | IGNORE_HELD_ITEM))
+ if(!resisting || resisting.stat != CONSCIOUS || resisting.loc != src)
+ return
+ visible_message(span_warning("[src] stops resisting."))
+ return
+ visible_message(span_warning("[src] escapes [carrier]!"))
+ release()
+
+/obj/item/clothing/head/mob_holder/micro/assume_air(datum/gas_mixture/giver)
+ var/turf/location = get_turf(src)
+ return location.assume_air(giver)
+
+/obj/item/clothing/head/mob_holder/micro/remove_air(amount)
+ var/turf/location = get_turf(src)
+ return location.remove_air(amount)
+
+/obj/item/clothing/head/mob_holder/micro/return_air()
+ var/turf/location = get_turf(src)
+ return location.return_air()
+
+/obj/item/clothing/head/mob_holder/micro/mouse_drop_dragged(atom/M, mob/user, src_location, over_location, params)
+ . = ..()
+ if(M != usr)
+ return
+ if(usr == src)
+ return
+ if(!Adjacent(usr))
+ return
+ if(istype(M,/mob/living/silicon/ai))
+ return
+ var/mob/living/carbon/human/O = held_mob
+ if(istype(O))
+ O.MouseDrop(usr)
+
+/obj/item/clothing/head/mob_holder/micro/attack_self(mob/living/user)
+ if(world.time <= user.next_click)
+ return
+ user.changeNext_move(CLICK_CD_MELEE)
+ var/mob/living/carbon/human/M = held_mob
+ if(istype(M))
+ switch(resolve_intent_name(user.combat_mode))
+ if("harm") //TO:DO, rework all of these interactions to be a lot more in depth
+ visible_message(span_danger("[user] slams their fist down on [M]!"))
+ playsound(loc, 'sound/items/weapons/punch1.ogg', 50, 1)
+ M.adjustBruteLoss(5)
+ if("disarm")
+ visible_message(span_danger("[user] pins [M] down with a finger!"))
+ playsound(loc, 'sound/effects/bodyfall/bodyfall1.ogg', 50, 1)
+ M.adjustStaminaLoss(10)
+ if("grab")
+ visible_message(span_danger("[user] squeezes their fist around [M]!"))
+ playsound(loc, 'sound/items/weapons/thudswoosh.ogg', 50, 1)
+ M.adjustOxyLoss(5)
+ else
+ M.help_shake_act(user)
+
+/obj/item/clothing/head/mob_holder/micro/attacked_by(obj/item/I, mob/living/user)
+ return held_mob?.attacked_by(I, user) || ..()
+
+/mob/living/Adjacent(atom/neighbor)
+ . = ..()
+ var/obj/item/clothing/head/mob_holder/micro/micro_holder = loc
+ if(istype(micro_holder))
+ return micro_holder.Adjacent(neighbor)
+
+/obj/item/clothing/head/mob_holder/micro/attack(mob/living/eater, mob/living/holder)
+ var/datum/component/vore/vore = holder.GetComponent(/datum/component/vore)
+ if(!vore)
+ return ..()
+
+ if(holder == eater) // Parent wants to eat pulled
+ vore.vore_other(held_mob)
+ else
+ vore.feed_other_to_other(eater, held_mob)
+
+/obj/item/clothing/head/mob_holder/micro/Exited(mob/living/totally_not_vored, direction)
+ // Transferred to a belly? Get rid of this before it puts us on the floor
+ if(istype(totally_not_vored.loc, /obj/vore_belly))
+ held_mob = null
+ qdel(src)
+ return ..()
+
+/obj/item/clothing/head/mob_holder/micro/GetAccess()
+ . = ..()
+ var/obj/item/held = held_mob.get_active_held_item()
+ if(held)
+ . += held.GetAccess()
+ var/mob/living/carbon/human/human_micro = held_mob
+ if(istype(human_micro))
+ . += human_micro.wear_id?.GetAccess()
+
+/obj/item/clothing/head/mob_holder/micro/GetID()
+ . = ..()
+ if(.)
+ return
+ var/obj/item/held = held_mob.get_active_held_item()
+ if(isidcard(held))
+ return held
+ var/mob/living/carbon/human/human_micro = held_mob
+ if(istype(human_micro) && isidcard(human_micro.wear_id))
+ return human_micro.wear_id
+
+/obj/item/clothing/head/mob_holder/micro/update_visuals(mob/living/carbon/human/tiny_person)
+ . = ..()
+ transform = null
+
+// And right here i throw all of those error sprites in the trash
+/obj/item/clothing/head/mob_holder/micro/build_worn_icon(default_layer, default_icon_file, isinhands, female_uniform, override_state, override_file, mutant_styles)
+ return null
diff --git a/modular_zzplurt/code/datums/elements/mob_holder.dm b/modular_zzplurt/code/datums/elements/mob_holder.dm
new file mode 100644
index 0000000000000..99e8eeb75a176
--- /dev/null
+++ b/modular_zzplurt/code/datums/elements/mob_holder.dm
@@ -0,0 +1,79 @@
+/datum/element/mob_holder
+ element_flags = ELEMENT_BESPOKE | ELEMENT_DETACH_ON_HOST_DESTROY
+ argument_hash_start_idx = 2
+ var/worn_state
+ var/alt_worn
+ var/right_hand
+ var/left_hand
+ var/inv_slots
+ var/proctype //if present, will be invoked on headwear generation.
+
+/datum/element/mob_holder/Attach(datum/target, worn_state, alt_worn, right_hand, left_hand, inv_slots = NONE, proctype)
+ . = ..()
+
+ if(!isliving(target))
+ return ELEMENT_INCOMPATIBLE
+
+ src.worn_state = worn_state
+ src.alt_worn = alt_worn
+ src.right_hand = right_hand
+ src.left_hand = left_hand
+ src.inv_slots = inv_slots
+ src.proctype = proctype
+
+ RegisterSignal(target, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, PROC_REF(on_requesting_context_from_item))
+ RegisterSignal(target, COMSIG_CLICK_ALT, PROC_REF(mob_try_pickup))
+ RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine))
+
+/datum/element/mob_holder/Detach(datum/source, force)
+ . = ..()
+ UnregisterSignal(source, list(COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, COMSIG_CLICK_ALT, COMSIG_ATOM_EXAMINE))
+
+/datum/element/mob_holder/proc/on_examine(mob/living/source, mob/user, list/examine_list)
+ if(ishuman(user) && !istype(source.loc, /obj/item/clothing/head/mob_holder))
+ examine_list += span_notice("Looks like [source.p_they(FALSE)] can be picked up with Alt+Click!")
+
+/datum/element/mob_holder/proc/on_requesting_context_from_item(
+ obj/source,
+ list/context,
+ obj/item/held_item,
+ mob/living/user,
+)
+ SIGNAL_HANDLER
+
+ if(ishuman(user))
+ LAZYSET(context, SCREENTIP_CONTEXT_ALT_LMB, "Pick up")
+ return CONTEXTUAL_SCREENTIP_SET
+
+/datum/element/mob_holder/proc/mob_try_pickup(mob/living/source, mob/user)
+ if(!ishuman(user) || !user.Adjacent(source) || user.incapacitated)
+ return FALSE
+ if(user.get_active_held_item())
+ to_chat(user, span_warning("Your hands are full!"))
+ return FALSE
+ if(source.buckled)
+ to_chat(user, span_warning("[source] is buckled to something!"))
+ return FALSE
+ if(source == user)
+ to_chat(user, span_warning("You can't pick yourself up."))
+ return FALSE
+ source.visible_message(span_warning("[user] starts picking up [source]."), \
+ span_userdanger("[user] starts picking you up!"))
+ if(!do_after(user, 2 SECONDS, target = source) || source.buckled)
+ return FALSE
+
+ source.visible_message(span_warning("[user] picks up [source]!"), \
+ span_userdanger("[user] picks you up!"))
+ to_chat(user, span_notice("You pick [source] up."))
+ source.drop_all_held_items()
+ var/obj/item/clothing/head/mob_holder/holder = new(get_turf(source), source, worn_state, alt_worn, right_hand, left_hand, inv_slots)
+
+ if(proctype)
+ INVOKE_ASYNC(src, proctype, source, holder, user)
+ user.put_in_hands(holder)
+ return TRUE
+
+/datum/element/mob_holder/proc/drone_worn_icon(mob/living/basic/drone/D, obj/item/clothing/head/mob_holder/holder, mob/user)
+ var/new_state = "[D.visualAppearance]_hat"
+ holder.inhand_icon_state = new_state
+ holder.icon_state = new_state
diff --git a/modular_zzplurt/code/datums/mutations/body.dm b/modular_zzplurt/code/datums/mutations/body.dm
new file mode 100644
index 0000000000000..3fa33068e9de5
--- /dev/null
+++ b/modular_zzplurt/code/datums/mutations/body.dm
@@ -0,0 +1,10 @@
+/datum/mutation/human/gigantism/on_acquiring(mob/living/carbon/human/owner)
+ if(..())
+ return
+
+ owner.update_size(1.25)
+
+/datum/mutation/human/gigantism/on_losing(mob/living/carbon/human/owner)
+ if(..())
+ return
+ owner.update_size(0.8)
diff --git a/modular_zzplurt/code/datums/traits/neutral/oversized.dm b/modular_zzplurt/code/datums/traits/neutral/oversized.dm
new file mode 100644
index 0000000000000..6d720d25a7e5b
--- /dev/null
+++ b/modular_zzplurt/code/datums/traits/neutral/oversized.dm
@@ -0,0 +1,7 @@
+/datum/quirk/oversized/add(client/client_source)
+ . = ..()
+ quirk_holder.adjust_mobsize()
+
+/datum/quirk/oversized/remove()
+ . = ..()
+ quirk_holder.adjust_mobsize()
diff --git a/modular_zzplurt/code/game/objects/items/lewd_items/size_items.dm b/modular_zzplurt/code/game/objects/items/lewd_items/size_items.dm
new file mode 100644
index 0000000000000..a06eabcce32ac
--- /dev/null
+++ b/modular_zzplurt/code/game/objects/items/lewd_items/size_items.dm
@@ -0,0 +1,12 @@
+/obj/item/clothing/neck/size_collar
+ warning_given = TRUE //don't ruin the fun
+
+/datum/component/temporary_size
+ allowed_areas = list() //Allow for use anywhere
+
+/datum/component/temporary_size/apply_size(size_to_apply)
+ . = ..()
+
+ if(.)
+ var/mob/living/carbon/human/human_parent = parent
+ human_parent.adjust_mobsize(size_to_apply)
diff --git a/modular_zzplurt/code/modules/cargo/packs/general.dm b/modular_zzplurt/code/modules/cargo/packs/general.dm
new file mode 100644
index 0000000000000..58f2afeaf9528
--- /dev/null
+++ b/modular_zzplurt/code/modules/cargo/packs/general.dm
@@ -0,0 +1,11 @@
+/datum/supply_pack/misc/prospacillin //size changing should be hard to achieve; so enjoy the price tag.
+ name = "Prospacillin Bottle"
+ desc = "An extremely expensive solution of growth serum known as Prospacillin. Effects are permanent upon consumption, and growth is slow."
+ cost = 100000
+ contains = list(/obj/item/reagent_containers/cup/bottle/prospacillin)
+
+/datum/supply_pack/misc/diminicillin //size changing should be hard to achieve; so enjoy the price tag.
+ name = "Diminicillin Bottle"
+ desc = "An extremely expensive solution of shrinking serum known as Diminicillin. Effects are permanent upon consumption, and shrinking is slow."
+ cost = 100000
+ contains = list(/obj/item/reagent_containers/cup/bottle/diminicillin)
diff --git a/modular_zzplurt/code/modules/client/preferences/body_size.dm b/modular_zzplurt/code/modules/client/preferences/body_size.dm
new file mode 100644
index 0000000000000..f3653c262b461
--- /dev/null
+++ b/modular_zzplurt/code/modules/client/preferences/body_size.dm
@@ -0,0 +1,16 @@
+/datum/preference/numeric/body_size/create_default_value()
+ minimum = BODY_SIZE_MIN
+ maximum = BODY_SIZE_MAX
+ . = ..()
+
+/datum/preference/toggle/scaled_appearance
+ category = PREFERENCE_CATEGORY_SECONDARY_FEATURES
+ savefile_identifier = PREFERENCE_CHARACTER
+ savefile_key = "scaled_appearance"
+ default_value = FALSE
+
+/datum/preference/toggle/scaled_appearance/is_accessible(datum/preferences/preferences)
+ . = ..()
+
+/datum/preference/toggle/scaled_appearance/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences)
+ target.fuzzy = value
diff --git a/modular_zzplurt/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm b/modular_zzplurt/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm
new file mode 100644
index 0000000000000..18b76812bf1b5
--- /dev/null
+++ b/modular_zzplurt/code/modules/mob/living/basic/space_fauna/wumborian_fugu/fugu_gland.dm
@@ -0,0 +1,4 @@
+/obj/item/fugu_gland/interact_with_atom(mob/living/interacting_with, mob/living/user, list/modifiers)
+ . = ..()
+ if(. == ITEM_INTERACT_SUCCESS)
+ interacting_with.update_size(2)
diff --git a/modular_zzplurt/code/modules/mob/living/carbon/examine.dm b/modular_zzplurt/code/modules/mob/living/carbon/examine.dm
new file mode 100644
index 0000000000000..0297f0e9f7370
--- /dev/null
+++ b/modular_zzplurt/code/modules/mob/living/carbon/examine.dm
@@ -0,0 +1,14 @@
+/mob/living/carbon/proc/get_size_examine_info(mob/living/user)
+ . = list()
+
+ var/t_He = p_they()
+
+ //Approximate character height based on current sprite scale
+ var/dispSize = round(12*get_size(src)) // gets the character's sprite size percent and converts it to the nearest half foot
+ if(dispSize % 2) // returns 1 or 0. 1 meaning the height is not exact and the code below will execute, 0 meaning the height is exact and the else will trigger.
+ dispSize = dispSize - 1 //makes it even
+ dispSize = dispSize / 2 //rounds it out
+ . += "[t_He] appear\s to be around [dispSize] and a half feet tall."
+ else
+ dispSize = dispSize / 2
+ . += "[t_He] appear\s to be around [dispSize] feet tall."
diff --git a/modular_zzplurt/code/modules/mob/living/carbon/human/human.dm b/modular_zzplurt/code/modules/mob/living/carbon/human/human.dm
index 7992e19f25052..6d6f4de9f2fe6 100644
--- a/modular_zzplurt/code/modules/mob/living/carbon/human/human.dm
+++ b/modular_zzplurt/code/modules/mob/living/carbon/human/human.dm
@@ -1,3 +1,12 @@
/mob/living/carbon/human
/// Are we currently in combat focus?
var/combat_focus = FALSE
+
+/mob/living/carbon/human/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/mob_holder/micro)
+
+/mob/living/carbon/human/on_entered(datum/source, mob/living/carbon/human/moving)
+ . = ..()
+ if(istype(moving) && resting && resolve_intent_name(moving.combat_mode) != "help")
+ moving.handle_micro_bump_other(src)
diff --git a/modular_zzplurt/code/modules/mob/living/living.dm b/modular_zzplurt/code/modules/mob/living/living.dm
index 44e8544302ad1..cbe746cfda2be 100644
--- a/modular_zzplurt/code/modules/mob/living/living.dm
+++ b/modular_zzplurt/code/modules/mob/living/living.dm
@@ -25,3 +25,54 @@
to_chat(src, span_userdanger("An admin has [!admin_sleeping ? "un": ""]slept you."))
log_admin("[key_name(admin)] toggled admin-sleep on [key_name(src)].")
message_admins("[key_name_admin(admin)] toggled admin-sleep on [key_name_admin(src)].")
+
+/mob/living
+ var/size_multiplier = RESIZE_NORMAL
+
+/// Returns false on failure
+/mob/living/proc/update_size(new_size, cur_size)
+ if(!new_size)
+ return FALSE
+ if(!cur_size)
+ cur_size = get_size(src)
+ if(ishuman(src))
+ var/mob/living/carbon/human/H = src
+ if(new_size == cur_size)
+ return FALSE
+ H.dna.features["body_size"] = new_size
+ H.dna.update_body_size(cur_size)
+ else
+ if(new_size == cur_size)
+ return FALSE
+ size_multiplier = new_size
+ current_size = new_size / cur_size
+ update_transform()
+ adjust_mobsize(new_size)
+ SEND_SIGNAL(src, COMSIG_MOB_RESIZED, new_size, cur_size)
+ return TRUE
+
+/mob/living/proc/adjust_mobsize(size)
+ switch(size)
+ if(0 to 0.4)
+ mob_size = MOB_SIZE_TINY
+ if(0.41 to 0.8)
+ mob_size = MOB_SIZE_SMALL
+ if(0.81 to 1.2)
+ mob_size = MOB_SIZE_HUMAN
+ if(1.21 to INFINITY)
+ mob_size = MOB_SIZE_LARGE
+
+/mob/living/vv_edit_var(var_name, var_value)
+ switch(var_name)
+ if(NAMEOF(src, current_size))
+ update_size(var_value)
+ . = TRUE
+ if(NAMEOF(src, size_multiplier))
+ update_size(var_value)
+ . = TRUE
+
+ if(!isnull(.))
+ datum_flags |= DF_VAR_EDITED
+ return
+
+ return ..()
diff --git a/modular_zzplurt/code/modules/mob/living/living_defines.dm b/modular_zzplurt/code/modules/mob/living/living_defines.dm
index bfc77190412cf..a7dcec758c947 100644
--- a/modular_zzplurt/code/modules/mob/living/living_defines.dm
+++ b/modular_zzplurt/code/modules/mob/living/living_defines.dm
@@ -2,3 +2,5 @@
// Admin CC
var/admin_frozen = FALSE
var/admin_sleeping = FALSE
+ var/datum/action/sizecode_smallsprite/small_sprite = new
+ var/fuzzy = FALSE
diff --git a/modular_zzplurt/code/modules/mob/living/living_update_icons.dm b/modular_zzplurt/code/modules/mob/living/living_update_icons.dm
new file mode 100644
index 0000000000000..750bac29735d3
--- /dev/null
+++ b/modular_zzplurt/code/modules/mob/living/living_update_icons.dm
@@ -0,0 +1,5 @@
+/mob/living/update_transform(resize)
+ appearance_flags |= PIXEL_SCALE
+ if(fuzzy)
+ appearance_flags &= ~PIXEL_SCALE
+ . = ..()
diff --git a/modular_zzplurt/code/modules/movespeed/modifiers/components.dm b/modular_zzplurt/code/modules/movespeed/modifiers/components.dm
new file mode 100644
index 0000000000000..3ba8d7519a62b
--- /dev/null
+++ b/modular_zzplurt/code/modules/movespeed/modifiers/components.dm
@@ -0,0 +1,6 @@
+#define MOVESPEED_ID_STOMP "STEPPY"
+
+/datum/movespeed_modifier/stomp
+ id = MOVESPEED_ID_STOMP
+ movetypes = GROUND
+ multiplicative_slowdown = 10
diff --git a/modular_zzplurt/code/modules/movespeed/modifiers/innate.dm b/modular_zzplurt/code/modules/movespeed/modifiers/innate.dm
new file mode 100644
index 0000000000000..c4cc996d6f9cf
--- /dev/null
+++ b/modular_zzplurt/code/modules/movespeed/modifiers/innate.dm
@@ -0,0 +1,4 @@
+/datum/movespeed_modifier/small_stride
+ blacklisted_movetypes = (FLOATING)
+ variable = TRUE
+ flags = IGNORE_NOSLOW
diff --git a/modular_zzplurt/code/modules/reagents/reagent_containers/cups/sizeitems.dm b/modular_zzplurt/code/modules/reagents/reagent_containers/cups/sizeitems.dm
new file mode 100644
index 0000000000000..699593cd83852
--- /dev/null
+++ b/modular_zzplurt/code/modules/reagents/reagent_containers/cups/sizeitems.dm
@@ -0,0 +1,16 @@
+
+/obj/item/reagent_containers/cup/bottle/prospacillin
+ name = "Prospacillin Bottle"
+ desc = "An incredibly expensive bottle used by Nanotrasen command. It has golden engravings and reeks of corporate greed."
+ w_class = WEIGHT_CLASS_TINY
+ icon = 'modular_zzplurt/icons/obj/drinks.dmi'
+ icon_state = "prospacillin"
+ list_reagents = list(/datum/reagent/growthchem = 15)
+
+/obj/item/reagent_containers/cup/bottle/diminicillin
+ name = "Diminicillin Bottle"
+ desc = "An incredibly expensive bottle used by Nanotrasen command. It has golden engravings and reeks of corporate greed."
+ w_class = WEIGHT_CLASS_TINY
+ icon = 'modular_zzplurt/icons/obj/drinks.dmi'
+ icon_state = "diminicillin"
+ list_reagents = list(/datum/reagent/shrinkchem = 15)
diff --git a/modular_zzplurt/code/modules/resize/resizing.dm b/modular_zzplurt/code/modules/resize/resizing.dm
new file mode 100644
index 0000000000000..77db7484e122a
--- /dev/null
+++ b/modular_zzplurt/code/modules/resize/resizing.dm
@@ -0,0 +1,167 @@
+//handle the big steppy, except nice
+/mob/living/proc/handle_micro_bump_helping(mob/living/target)
+ if(ishuman(src))
+ var/mob/living/carbon/human/user = src
+
+ if(target.pulledby == user)
+ return FALSE
+
+ //Micro is on a table.
+ var/turf/steppyspot = target.loc
+ for(var/thing in steppyspot.contents)
+ if(istype(thing, /obj/structure/table))
+ return TRUE
+
+ //Both small.
+ if(get_size(user) <= RESIZE_A_TINYMICRO && get_size(target) <= RESIZE_A_TINYMICRO)
+ now_pushing = 0
+ user.forceMove(target.loc)
+ return TRUE
+
+ //Doing messages
+ if(COMPARE_SIZES(user, target) >= 2) //if the initiator is twice the size of the micro
+ now_pushing = 0
+ user.forceMove(target.loc)
+
+ //Smaller person being stepped on
+ if(iscarbon(src))
+ if(istype(user) && user.dna.features["taur"] == "Naga" || user.dna.features["taur"] == "Tentacle")
+ target.visible_message(span_notice("[src] carefully slithers around [target]."), span_notice("[src]'s huge tail slithers besides you."))
+ else
+ target.visible_message(span_notice("[src] carefully steps over [target]."), span_notice("[src] steps over you carefully."))
+ return TRUE
+
+ //Smaller person stepping under a larger person
+ if(COMPARE_SIZES(target, user) >= 2)
+ user.forceMove(target.loc)
+ now_pushing = 0
+ micro_step_under(target)
+ return TRUE
+
+//Stepping on disarm intent -- TO DO, OPTIMIZE ALL OF THIS SHIT
+/mob/living/proc/handle_micro_bump_other(mob/living/target)
+ ASSERT(isliving(target))
+ if(ishuman(src))
+ var/mob/living/carbon/human/user = src
+
+ if(target.pulledby == user)
+ return FALSE
+
+ //If on a table, don't
+ var/turf/steppyspot = target.loc
+ for(var/thing in steppyspot.contents)
+ if(istype(thing, /obj/structure/table))
+ return TRUE
+
+ //Both small
+ if(get_size(user) <= RESIZE_A_TINYMICRO && get_size(target) <= RESIZE_A_TINYMICRO)
+ now_pushing = 0
+ user.forceMove(target.loc)
+ return TRUE
+
+ if(COMPARE_SIZES(user, target) >= 2)
+ log_combat(user, target, "stepped on", addition="[resolve_intent_name(user.combat_mode)] trample")
+ if((user.mobility_flags & MOBILITY_MOVE) && !user.buckled)
+ switch(resolve_intent_name(user.combat_mode))
+ if("disarm")
+ now_pushing = 0
+ user.forceMove(target.loc)
+ user.sizediffStamLoss(target)
+ user.add_movespeed_modifier(/datum/movespeed_modifier/stomp, TRUE) //Full stop
+ addtimer(CALLBACK(user, TYPE_PROC_REF(/mob, remove_movespeed_modifier), MOVESPEED_ID_STOMP, TRUE), 3) //0.3 seconds
+ if(iscarbon(user))
+ if(istype(user) && user.dna.features["taur"] == "Naga" || user.dna.features["taur"] == "Tentacle")
+ target.visible_message(span_danger("[src] carefully rolls their tail over [target]!"), span_danger("[src]'s huge tail rolls over you!"))
+ else
+ target.visible_message(span_danger("[src] carefully steps on [target]!"), span_danger("[src] steps onto you with force!"))
+ return TRUE
+
+ if("harm")
+ now_pushing = 0
+ user.forceMove(target.loc)
+ user.sizediffStamLoss(target)
+ user.sizediffBruteloss(target)
+ playsound(loc, 'sound/misc/splort.ogg', 50, 1)
+ user.add_movespeed_modifier(/datum/movespeed_modifier/stomp, TRUE)
+ addtimer(CALLBACK(user, TYPE_PROC_REF(/mob, remove_movespeed_modifier), MOVESPEED_ID_STOMP, TRUE), 1 SECONDS) //1 second
+ //user.Stun(20)
+ if(iscarbon(user))
+ if(istype(user) && (user.dna.features["taur"] == "Naga" || user.dna.features["taur"] == "Tentacle"))
+ target.visible_message(span_danger("[src] mows down [target] under their tail!"), span_userdanger("[src] plows their tail over you mercilessly!"))
+ else
+ target.visible_message(span_danger("[src] slams their foot down on [target], crushing them!"), span_userdanger("[src] crushes you under their foot!"))
+ return TRUE
+
+ if("grab")
+ now_pushing = 0
+ user.forceMove(target.loc)
+ user.sizediffStamLoss(target)
+ user.sizediffStun(target)
+ user.add_movespeed_modifier(/datum/movespeed_modifier/stomp, TRUE)
+ addtimer(CALLBACK(user, TYPE_PROC_REF(/mob, remove_movespeed_modifier), MOVESPEED_ID_STOMP, TRUE), 7)//About 3/4th a second
+ if(iscarbon(user))
+ var/feetCover = (user.wear_suit && (user.wear_suit.body_parts_covered & FEET)) || (user.w_uniform && (user.w_uniform.body_parts_covered & FEET) || (user.shoes && (user.shoes.body_parts_covered & FEET)))
+ if(feetCover)
+ if(user?.dna?.features["taur"] == "Naga" || user?.dna?.features["taur"] == "Tentacle")
+ target.visible_message(span_danger("[src] pins [target] under their tail!"), span_danger("[src] pins you beneath their tail!"))
+ else
+ target.visible_message(span_danger("[src] pins [target] helplessly underfoot!"), span_danger("[src] pins you underfoot!"))
+ return TRUE
+ else
+ if(user?.dna?.features["taur"] == "Naga" || user?.dna?.features["taur"] == "Tentacle")
+ target.visible_message(span_danger("[user] snatches up [target] underneath their tail!"), span_userdanger("[src]'s tail winds around you and snatches you in its coils!"))
+ //target.mob_pickup_micro_feet(user)
+ SEND_SIGNAL(target, COMSIG_MICRO_PICKUP_FEET, user)
+ else
+ target.visible_message(span_danger("[user] stomps down on [target], curling their toes and picking them up!"), span_userdanger("[src]'s toes pin you down and curl around you, picking you up!"))
+ //target.mob_pickup_micro_feet(user)
+ SEND_SIGNAL(target, COMSIG_MICRO_PICKUP_FEET, user)
+ return TRUE
+
+ if(COMPARE_SIZES(target, user) >= 2)
+ user.forceMove(target.loc)
+ now_pushing = 0
+ micro_step_under(target)
+ return TRUE
+
+/mob/living/proc/macro_step_around(mob/living/target)
+ if(ishuman(src))
+ var/mob/living/carbon/human/validmob = src
+ if(validmob?.dna?.features["taur"] == "Naga" || validmob?.dna?.features["taur"] == "Tentacle")
+ visible_message(span_notice("[validmob] carefully slithers around [target]."), span_notice("You carefully slither around [target]."))
+ else
+ visible_message(span_notice("[validmob] carefully steps around [target]."), span_notice("You carefully steps around [target]."))
+
+//smaller person stepping under another person... TO DO, fix and allow special interactions with naga legs to be seen
+/mob/living/proc/micro_step_under(mob/living/target)
+ if(ishuman(src))
+ var/mob/living/carbon/human/validmob = src
+ if(validmob?.dna?.features["taur"] == "Naga" || validmob?.dna?.features["taur"] == "Tentacle")
+ visible_message(span_notice("[validmob] bounds over [validmob]'s tail."), span_notice("You jump over [target]'s thick tail."))
+ else
+ visible_message(span_notice("[validmob] runs between [validmob]'s legs."), span_notice("You run between [target]'s legs."))
+
+//Proc for scaling stamina damage on size difference
+/mob/living/carbon/proc/sizediffStamLoss(mob/living/carbon/target)
+ var/S = COMPARE_SIZES(src, target) * 25 //macro divided by micro, times 25
+ target.Knockdown(S) //final result in stamina knockdown
+
+//Proc for scaling stuns on size difference (for grab intent)
+/mob/living/carbon/proc/sizediffStun(mob/living/carbon/target)
+ var/T = COMPARE_SIZES(src, target) * 2 //Macro divided by micro, times 2
+ target.Stun(T)
+
+//Proc for scaling brute damage on size difference
+/mob/living/carbon/proc/sizediffBruteloss(mob/living/carbon/target)
+ var/B = COMPARE_SIZES(src, target) * 3 //macro divided by micro, times 3
+ target.adjustBruteLoss(B) //final result in brute loss
+
+//Proc for instantly grabbing valid size difference. Code optimizations soon(TM)
+/*
+/mob/living/proc/sizeinteractioncheck(mob/living/target)
+ if(abs(get_effective_size()/target.get_effective_size())>=2.0 && get_effective_size()>target.get_effective_size())
+ return FALSE
+ else
+ return TRUE
+*/
+//Clothes coming off at different sizes, and health/speed/stam changes as well
diff --git a/modular_zzplurt/code/modules/resize/sizechems.dm b/modular_zzplurt/code/modules/resize/sizechems.dm
new file mode 100644
index 0000000000000..43ab3cba2559a
--- /dev/null
+++ b/modular_zzplurt/code/modules/resize/sizechems.dm
@@ -0,0 +1,111 @@
+//Size Chemicals, now with better and less cringy names.
+//TO DO: USE BETTER FERMICHEM TO MAKE ALL OF THESE CHEMICALS MORE INTERACTIVE
+
+//Sizechem reagent
+/datum/reagent/sizechem
+ name = "Cell-Volume Altering Base"
+ description = "A stabilized compound liquid, used as a basis for increasing or decreasing the size of living matter with more recipes."
+ color = "#C900CC"
+ taste_description = "regret"
+ metabolization_rate = 0.25
+
+//Sizechem reaction
+/datum/chemical_reaction/sizechem
+ results = list(/datum/reagent/sizechem = 0.3)
+ required_reagents = list(/datum/reagent/growthserum = 0.15, /datum/reagent/gold = 0.15, /datum/reagent/acetone = 0.15)
+ required_temp = 1
+ mix_message = "the reaction rapidly alters in size!"
+ optimal_temp = 630
+ overheat_temp = 635
+ optimal_ph_min = 5
+ optimal_ph_max = 5.5
+ determin_ph_range = 2
+ temp_exponent_factor = 4
+ ph_exponent_factor = 4
+ thermic_constant = -10
+ H_ion_release = 0.02
+ rate_up_lim = 1
+ purity_min = 0.2
+ reaction_flags = REACTION_HEAT_ARBITARY
+
+//Growthchem reagent
+/datum/reagent/growthchem
+ name = "Prospacillin"
+ description = "A stabilized altercation of size-altering liquids, this one appears to increase cell volume."
+ color = "#E70C0C"
+ taste_description = "a sharp, fiery and intoxicating flavour"
+ overdose_threshold = 10
+ metabolization_rate = 0.25
+
+//Growthchem reaction
+/datum/chemical_reaction/growthchem
+ results = list(/datum/reagent/growthchem = 0.25)
+ required_reagents = list(/datum/reagent/sizechem = 0.15, /datum/reagent/consumable/condensedcapsaicin = 0.15, /datum/reagent/drug/aphrodisiac = 0.30)
+ required_temp = 1
+ mix_message = "the reaction appears to grow!"
+ optimal_temp = 730
+ overheat_temp = 735
+ optimal_ph_min = 3
+ optimal_ph_max = 3.5
+ determin_ph_range = 2
+ temp_exponent_factor = 4
+ ph_exponent_factor = 4
+ thermic_constant = -10
+ H_ion_release = 0.02
+ rate_up_lim = 1
+ purity_min = 0.2
+ reaction_flags = REACTION_HEAT_ARBITARY
+
+//Growthchem effects
+/datum/reagent/growthchem/on_mob_add(mob/living/M)
+ . = ..()
+ log_game("SIZECODE: [M] ckey: [M.key] has ingested growthchem.")
+
+/datum/reagent/growthchem/on_mob_life(mob/living/M)
+ var/size = get_size(M)
+ if(size < RESIZE_MACRO)
+ M.update_size(0.025)
+ M.visible_message(span_danger("[pick("[M] grows!", "[M] expands in size!", "[M] pushes outwards in stature!")]"), span_danger("[pick("You feel your body fighting for space and growing!", "The world contracts inwards in every direction!", "You feel your muscles expand, and your surroundings shrink!")]"))
+ ..()
+ . = 1
+
+//Shrinkchem reagent
+/datum/reagent/shrinkchem
+ name = "Diminicillin"
+ description = "A stabilized altercation of size-altering liquids, this one appears to decrease cell volume."
+ color = "#0C26E7"
+ taste_description = "a pungent, acidic and jittery flavour"
+ overdose_threshold = 10
+ metabolization_rate = 0.50
+
+//Shrinchem reaction
+/datum/chemical_reaction/shrinkchem
+ results = list(/datum/reagent/shrinkchem = 0.25)
+ required_reagents = list(/datum/reagent/sizechem = 0.15, /datum/reagent/consumable/frostoil = 0.15, /datum/reagent/drug = 0.30)
+ required_temp = 1
+ mix_message = "the reaction appears to shrink!"
+ optimal_temp = 150
+ overheat_temp = 350
+ optimal_ph_min = 3
+ optimal_ph_max = 4.5
+ determin_ph_range = 2
+ temp_exponent_factor = 4
+ ph_exponent_factor = 4
+ thermic_constant = -10
+ H_ion_release = 0.02
+ rate_up_lim = 1
+ purity_min = 0.2
+ reaction_flags = REACTION_HEAT_ARBITARY
+
+//Shrinkchem effects
+/datum/reagent/shrinkchem/on_mob_add(mob/living/M)
+ . = ..()
+ log_game("SIZECODE: [M] ckey: [M.key] has ingested shrinkchem.")
+
+/datum/reagent/shrinkchem/on_mob_life(mob/living/M)
+ var/size = get_size(M)
+ if(size > RESIZE_MICRO)
+ M.update_size(0.025)
+ M.visible_message(span_danger("[pick("[M] shrinks down!", "[M] dwindles in size!", "[M] compresses down!")]"), span_danger("[pick("You feel your body compressing in size!", "The world pushes outwards in every direction!", "You feel your muscles contract, and your surroundings grow!")]"))
+ ..()
+ . = 1
diff --git a/modular_zzplurt/code/modules/resize/sizegun.dm b/modular_zzplurt/code/modules/resize/sizegun.dm
new file mode 100644
index 0000000000000..cee98c0e86244
--- /dev/null
+++ b/modular_zzplurt/code/modules/resize/sizegun.dm
@@ -0,0 +1,85 @@
+/obj/projectile/sizelaser
+ name = "sizeray laser"
+ icon_state = "omnilaser"
+ hitsound = null
+ damage = 5
+ damage_type = STAMINA
+ pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
+
+/obj/projectile/sizelaser/shrinkray
+ icon_state = "bluelaser"
+
+/obj/projectile/sizelaser/growthray
+ icon_state = "laser"
+
+/obj/projectile/sizelaser/shrinkray/on_hit(atom/target, blocked = 0, pierce_hit)
+ . = ..()
+ if(isliving(target))
+ var/mob/living/living = target
+ var/new_size = RESIZE_NORMAL
+ switch(get_size(target))
+ if(RESIZE_MACRO to INFINITY)
+ new_size = RESIZE_HUGE
+ if(RESIZE_HUGE to RESIZE_MACRO)
+ new_size = RESIZE_BIG
+ if(RESIZE_BIG to RESIZE_HUGE)
+ new_size = RESIZE_NORMAL
+ if(RESIZE_NORMAL to RESIZE_BIG)
+ new_size = RESIZE_SMALL
+ if(RESIZE_SMALL to RESIZE_NORMAL)
+ new_size = RESIZE_TINY
+ if(RESIZE_TINY to RESIZE_SMALL)
+ new_size = RESIZE_MICRO
+ if((0 - INFINITY) to RESIZE_NORMAL)
+ new_size = RESIZE_MICRO
+ living.update_size(new_size)
+
+/obj/projectile/sizelaser/growthray/on_hit(atom/target, blocked = 0, pierce_hit)
+ . = ..()
+ if(isliving(target))
+ var/mob/living/living = target
+ var/new_size = RESIZE_NORMAL
+ switch(get_size(target))
+ if(RESIZE_HUGE to RESIZE_MACRO)
+ new_size = RESIZE_MACRO
+ if(RESIZE_BIG to RESIZE_HUGE)
+ new_size = RESIZE_HUGE
+ if(RESIZE_NORMAL to RESIZE_BIG)
+ new_size = RESIZE_BIG
+ if(RESIZE_SMALL to RESIZE_NORMAL)
+ new_size = RESIZE_NORMAL
+ if(RESIZE_TINY to RESIZE_SMALL)
+ new_size = RESIZE_SMALL
+ if(RESIZE_MICRO to RESIZE_TINY)
+ new_size = RESIZE_TINY
+ if((0 - INFINITY) to RESIZE_MICRO)
+ new_size = RESIZE_MICRO
+ living.update_size(new_size)
+
+/obj/item/ammo_casing/energy/laser/growthray
+ projectile_type = /obj/projectile/sizelaser/growthray
+ select_name = "Growth"
+
+/obj/item/ammo_casing/energy/laser/shrinkray
+ projectile_type = /obj/projectile/sizelaser/shrinkray
+ select_name = "Shrink"
+
+//Gun
+/obj/item/gun/energy/laser/sizeray
+ name = "size ray"
+ icon_state = "bluetag"
+ desc = "Debug size manipulator. You probably shouldn't have this!"
+ inhand_icon_state = null
+ ammo_type = list(/obj/item/ammo_casing/energy/laser/shrinkray, /obj/item/ammo_casing/energy/laser/growthray)
+ selfcharge = TRUE
+ charge_delay = 5
+ ammo_x_offset = 2
+ clumsy_check = 1
+
+/obj/item/gun/energy/laser/sizeray/update_overlays()
+ . = ..()
+ var/current_index = select
+ if(current_index == 1)
+ icon_state = "redtag"
+ else
+ icon_state = "bluetag"
diff --git a/modular_zzplurt/code/modules/resize/smallsprite_action.dm b/modular_zzplurt/code/modules/resize/smallsprite_action.dm
new file mode 100644
index 0000000000000..505468f41678d
--- /dev/null
+++ b/modular_zzplurt/code/modules/resize/smallsprite_action.dm
@@ -0,0 +1,27 @@
+//Technically the same as /datum/action/small_sprite but for our macro players (I'm one of them)
+
+/datum/action/sizecode_smallsprite
+ name = "Toggle Giant Sprite"
+ desc = "Others will always see you as giant"
+ button_icon = 'icons/hud/screen_gen.dmi'
+ button_icon_state = "healthdoll_OVERLAY"
+ background_icon_state = "bg_alien"
+ var/small = FALSE
+ //var/image/small_icon
+
+/datum/action/sizecode_smallsprite/Trigger(trigger_flags)
+ . = ..()
+ if(!owner)
+ return
+
+ if(!small)
+ var/image/I = image(icon = owner.icon, icon_state = owner.icon_state, loc = owner, layer = owner.layer, pixel_x = owner.pixel_x, pixel_y = owner.pixel_y)
+ I.override = TRUE
+ I.overlays += owner.overlays
+ owner.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic, "smallsprite_sizecode", I)
+ //small_icon = I
+ else
+ owner.remove_alt_appearance("smallsprite_sizecode")
+
+ small = !small
+ return TRUE
diff --git a/modular_zzplurt/icons/obj/drinks.dmi b/modular_zzplurt/icons/obj/drinks.dmi
new file mode 100644
index 0000000000000..c611c9131c7a6
Binary files /dev/null and b/modular_zzplurt/icons/obj/drinks.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 1051796e54a09..ab2988c8099ee 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -517,9 +517,11 @@
#include "code\__DEFINES\~~~splurt_defines\inventory.dm"
#include "code\__DEFINES\~~~splurt_defines\keybinding.dm"
#include "code\__DEFINES\~~~splurt_defines\mobs.dm"
+#include "code\__DEFINES\~~~splurt_defines\sizecode.dm"
#include "code\__DEFINES\~~~splurt_defines\species_clothing_paths.dm"
#include "code\__DEFINES\~~~splurt_defines\strippable.dm"
#include "code\__DEFINES\~~~splurt_defines\underwear.dm"
+#include "code\__DEFINES\~~~splurt_defines\dcs\signals.dm"
#include "code\__DEFINES\~~~splurt_defines\traits\declarations.dm"
#include "code\__HELPERS\_auxtools_api.dm"
#include "code\__HELPERS\_dreamluau.dm"
@@ -9378,15 +9380,22 @@
#include "modular_zzplurt\code\_onclick\hud\hud.dm"
#include "modular_zzplurt\code\_onclick\hud\human.dm"
#include "modular_zzplurt\code\controllers\configuration\entries\discord.dm"
+#include "modular_zzplurt\code\controllers\configuration\entries\fetish_content.dm"
#include "modular_zzplurt\code\controllers\subsystem\discord.dm"
+#include "modular_zzplurt\code\datums\dna.dm"
#include "modular_zzplurt\code\datums\outfit.dm"
#include "modular_zzplurt\code\datums\sprite_accessories.dm"
#include "modular_zzplurt\code\datums\components\crafting\crafting.dm"
+#include "modular_zzplurt\code\datums\elements\holder_micro.dm"
+#include "modular_zzplurt\code\datums\elements\mob_holder.dm"
#include "modular_zzplurt\code\datums\keybinding\human.dm"
#include "modular_zzplurt\code\datums\keybinding\living.dm"
+#include "modular_zzplurt\code\datums\mutations\body.dm"
+#include "modular_zzplurt\code\datums\traits\neutral\oversized.dm"
#include "modular_zzplurt\code\game\objects\items.dm"
#include "modular_zzplurt\code\game\objects\items\holy_weapons.dm"
#include "modular_zzplurt\code\game\objects\items\devices\transfer_valve.dm"
+#include "modular_zzplurt\code\game\objects\items\lewd_items\size_items.dm"
#include "modular_zzplurt\code\modules\admin\player_panel.dm"
#include "modular_zzplurt\code\modules\admin\playtimes.dm"
#include "modular_zzplurt\code\modules\admin\transform.dm"
@@ -9394,8 +9403,10 @@
#include "modular_zzplurt\code\modules\asset_cache\assets\inventory.dm"
#include "modular_zzplurt\code\modules\atmospherics\machinery\portable\canister.dm"
#include "modular_zzplurt\code\modules\barks\bark_list.dm"
+#include "modular_zzplurt\code\modules\cargo\packs\general.dm"
#include "modular_zzplurt\code\modules\client\click.dm"
#include "modular_zzplurt\code\modules\client\client_procs.dm"
+#include "modular_zzplurt\code\modules\client\preferences\body_size.dm"
#include "modular_zzplurt\code\modules\client\preferences\clothing.dm"
#include "modular_zzplurt\code\modules\client\preferences\mutant_parts.dm"
#include "modular_zzplurt\code\modules\client\preferences\player_panel.dm"
@@ -9424,6 +9435,9 @@
#include "modular_zzplurt\code\modules\mob\living\emote.dm"
#include "modular_zzplurt\code\modules\mob\living\living.dm"
#include "modular_zzplurt\code\modules\mob\living\living_defines.dm"
+#include "modular_zzplurt\code\modules\mob\living\living_update_icons.dm"
+#include "modular_zzplurt\code\modules\mob\living\basic\space_fauna\wumborian_fugu\fugu_gland.dm"
+#include "modular_zzplurt\code\modules\mob\living\carbon\examine.dm"
#include "modular_zzplurt\code\modules\mob\living\carbon\human\_species.dm"
#include "modular_zzplurt\code\modules\mob\living\carbon\human\human.dm"
#include "modular_zzplurt\code\modules\mob\living\carbon\human\human_defense.dm"
@@ -9433,7 +9447,14 @@
#include "modular_zzplurt\code\modules\mob\living\carbon\human\inventory.dm"
#include "modular_zzplurt\code\modules\mob\living\carbon\human\life.dm"
#include "modular_zzplurt\code\modules\mob\living\carbon\human\species.dm"
+#include "modular_zzplurt\code\modules\movespeed\modifiers\components.dm"
+#include "modular_zzplurt\code\modules\movespeed\modifiers\innate.dm"
#include "modular_zzplurt\code\modules\reagents\chemistry\machinery\chem_dispenser.dm"
+#include "modular_zzplurt\code\modules\reagents\reagent_containers\cups\sizeitems.dm"
+#include "modular_zzplurt\code\modules\resize\resizing.dm"
+#include "modular_zzplurt\code\modules\resize\sizechems.dm"
+#include "modular_zzplurt\code\modules\resize\sizegun.dm"
+#include "modular_zzplurt\code\modules\resize\smallsprite_action.dm"
#include "modular_zzplurt\code\modules\species\_species.dm"
#include "modular_zzplurt\code\modules\species\arachnid.dm"
#include "modular_zzplurt\code\modules\species\teshari.dm"
diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/splurt/genitals.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/splurt/genitals.tsx
new file mode 100644
index 0000000000000..3a7668656a962
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/splurt/genitals.tsx
@@ -0,0 +1,7 @@
+import { CheckboxInput, FeatureToggle } from '../../base';
+
+export const scaled_appearance: FeatureToggle = {
+ name: 'Scaled Appearance',
+ description: 'Make your character use a sharp or fuzzy appearance.',
+ component: CheckboxInput,
+};