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, +};