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 6d972b674adf6..08e862aaf519f 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -135,6 +135,7 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) /datum/dna/proc/transfer_identity(mob/living/carbon/destination, transfer_SE = FALSE, transfer_species = TRUE) if(!istype(destination)) return + var/old_size = destination.dna.features["body_size"] destination.dna.unique_enzymes = unique_enzymes destination.dna.unique_identity = unique_identity destination.dna.blood_type = blood_type @@ -145,7 +146,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.update_size(get_size(destination), old_size) //SKYRAT EDIT ADDITION END if(transfer_SE) destination.dna.mutation_index = mutation_index @@ -647,6 +648,10 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) dna.features = newfeatures dna.generate_unique_features() + var/old_size = dna.features["body_size"] + dna.features = newfeatures + update_size(get_size(src), old_size) + if(mrace) var/datum/species/newrace = new mrace.type newrace.copy_properties_from(mrace) diff --git a/code/datums/elements/mob_holder.dm b/code/datums/elements/mob_holder.dm new file mode 100644 index 0000000000000..7013e79fa62a3 --- /dev/null +++ b/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/code/datums/mutations/body.dm b/code/datums/mutations/body.dm index d9cb4aabd2580..50e3ea2b70958 100644 --- a/code/datums/mutations/body.dm +++ b/code/datums/mutations/body.dm @@ -200,7 +200,7 @@ return // SKYRAT EDIT END ADD_TRAIT(owner, TRAIT_GIANT, GENETIC_MUTATION) - owner.update_transform(1.25) + owner.update_size(1.25) 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) @@ -212,6 +212,7 @@ REMOVE_TRAIT(owner, TRAIT_GIANT, GENETIC_MUTATION) return // SKYRAT EDIT END + owner.update_size(0.75) //Clumsiness has a very large amount of small drawbacks depending on item. /datum/mutation/human/clumsy diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index f6d477afbb923..fdb2d0b920c9c 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -52,6 +52,8 @@ // such that you never actually cared about checking if something is *edible*. var/obj/item/food/clothing/moth_snack + var/ignore_abstract = FALSE + /obj/item/clothing/Initialize(mapload) if(clothing_flags & VOICEBOX_TOGGLABLE) actions_types += list(/datum/action/item_action/toggle_voice_box) @@ -60,7 +62,7 @@ if(can_be_bloody && ((body_parts_covered & FEET) || (flags_inv & HIDESHOES))) LoadComponent(/datum/component/bloodysoles) AddElement(/datum/element/attack_equip) - if(!icon_state) + if(!icon_state && !ignore_abstract) item_flags |= ABSTRACT /obj/item/clothing/mouse_drop_dragged(atom/over_object, mob/user, src_location, over_location, params) 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..f2cf66be23a62 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_size(2) 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/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 68d4c211f6b31..e06bd3ffc2548 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -176,6 +176,16 @@ if (length(status_examines)) . += status_examines + //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." + var/appears_dead = FALSE var/just_sleeping = FALSE diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 717762a408d12..95d64fa59fbae 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -344,6 +344,12 @@ //called when something steps onto a human /mob/living/carbon/human/proc/on_entered(datum/source, atom/movable/AM) SIGNAL_HANDLER + + //Hyper Change - Step on people + var/mob/living/carbon/human/H = AM + if(istype(H) && resting && resolve_intent_name(H.combat_mode) != "help") + H.handle_micro_bump_other(src) + spreadFire(AM) /mob/living/carbon/human/proc/canUseHUD() diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index b0cf90334bec5..fcda93b77dee4 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -220,6 +220,11 @@ if(moving_diagonally)//no mob swap during diagonal moves. return TRUE + //handle micro bumping on help intent + if(resolve_intent_name(combat_mode) == "help") + if(handle_micro_bump_helping(M)) + return TRUE + if(!M.buckled && !M.has_buckled_mobs()) if(can_mobswap_with(M)) //switch our position with M @@ -254,6 +259,8 @@ //not if he's not CANPUSH of course if(!(M.status_flags & CANPUSH)) return TRUE + if(handle_micro_bump_other(M)) + return TRUE if(isliving(M)) var/mob/living/L = M if(HAS_TRAIT(L, TRAIT_PUSHIMMUNE)) @@ -2045,10 +2052,11 @@ GLOBAL_LIST_EMPTY(fire_appearances) 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 + update_size(var_value) + return TRUE + if(NAMEOF(src, size_multiplier)) + update_size(var_value) + return TRUE if(!isnull(.)) datum_flags |= DF_VAR_EDITED diff --git a/modular_zubbers/code/datums/components/vore/_defines.dm b/modular_zubbers/code/datums/components/vore/_defines.dm index 48c7d797be585..1450524d91982 100644 --- a/modular_zubbers/code/datums/components/vore/_defines.dm +++ b/modular_zubbers/code/datums/components/vore/_defines.dm @@ -23,7 +23,7 @@ /// If true, prevents mobs in crit or death from engaging in vore #define NO_DEAD TRUE /// If true, mobs with no player cannot be pred or prey -#define REQUIRES_PLAYER TRUE +#define REQUIRES_PLAYER FALSE /// Makes every mob spawn with a vore component, just for testing // #define VORE_TESTING_ALL_MOBS_ARE_VORE_MOBS /// Number of rolling backups bellies will keep diff --git a/modular_zubbers/code/datums/components/vore/vore.dm b/modular_zubbers/code/datums/components/vore/vore.dm index a2f94d0f05af1..9b7c6dc6728da 100644 --- a/modular_zubbers/code/datums/components/vore/vore.dm +++ b/modular_zubbers/code/datums/components/vore/vore.dm @@ -237,13 +237,13 @@ vore_mode_action.unset_ranged_ability(user) vore_mode_action.build_all_button_icons(UPDATE_BUTTON_BACKGROUND | UPDATE_BUTTON_STATUS) - if(!check_vore_grab(user)) + if(!check_vore_grab(user, clicked_on)) to_chat(user, span_danger("You must have an aggressive grab to do vore.")) return TRUE var/mob/living/pulled = user.pulling if(clicked_on == user) // Parent wants to eat pulled - vore_other() + vore_other(clicked_on) else if(clicked_on == pulled) // Parent wants to feed themselves to pulled feed_self_to_other() else // Parent wants to feed pulled to clicked_on @@ -362,75 +362,84 @@ return TRUE -/proc/check_vore_grab(mob/living/grabber) - var/mob/living/grabee = grabber.pulling - if(!istype(grabee)) +/proc/check_vore_grab(mob/living/grabber, mob/living/grabbed) + . = FALSE + if(QDELETED(grabber)) return FALSE - if(ishuman(grabber) && grabber.grab_state < GRAB_AGGRESSIVE) + if(QDELETED(grabbed)) return FALSE + if(ishuman(grabber) && grabber.grab_state >= GRAB_AGGRESSIVE) + . = TRUE + if(istype(grabbed.loc, /obj/item/clothing/head/mob_holder)) + . = TRUE 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, prey)) to_chat(parent, span_danger("You must have a[ishuman(pred) ? "n aggressive" : ""] grab to eat someone.")) - return - var/mob/living/prey = pred.pulling + return FALSE if(!check_vore_preferences(parent, pred, prey)) - return + return FALSE #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)) - return + return FALSE + if(!check_vore_grab(pred, prey) || !check_vore_preferences(parent, pred, prey, assume_active_consent = TRUE)) + return FALSE #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) complete_vore(prey) + return TRUE /datum/component/vore/proc/feed_self_to_other() var/mob/living/prey = parent - if(!check_vore_grab(prey)) - to_chat(parent, span_danger("You must have a[ishuman(prey) ? "n aggressive" : ""] grab to feed yourself to someone.")) - return var/mob/living/pred = prey.pulling + if(!check_vore_grab(prey, pred)) + to_chat(parent, span_danger("You must have a[ishuman(prey) ? "n aggressive" : ""] grab to feed yourself to someone.")) + return FALSE if(!check_vore_preferences(parent, pred, prey)) - return + return FALSE // check_vore_preferences asserts this exists var/datum/component/vore/pred_component = pred.GetComponent(/datum/component/vore) #ifdef VORE_DELAY prey.visible_message(span_danger("[prey] 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(prey, VORE_DELAY, pred)) - return - if(!check_vore_grab(prey) || !check_vore_preferences(parent, pred, prey, assume_active_consent = TRUE)) - return + return FALSE + if(!check_vore_grab(prey, pred) || !check_vore_preferences(parent, pred, prey, assume_active_consent = TRUE)) + return FALSE #endif 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) + return TRUE -/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, prey)) to_chat(feeder, span_danger("You must have a[ishuman(feeder) ? "n aggressive" : ""] grab to feed someone to someone else.")) - return + return FALSE if(!feeder.can_perform_action(pred, pred.interaction_flags_click | FORBID_TELEKINESIS_REACH)) - return - var/mob/living/prey = feeder.pulling + return FALSE if(!check_vore_preferences(feeder, pred, prey)) - return + return FALSE // check_vore_preferences asserts this exists var/datum/component/vore/pred_component = pred.GetComponent(/datum/component/vore) #ifdef VORE_DELAY 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)) - return + return FALSE + if(!check_vore_grab(feeder, prey) || !check_vore_preferences(feeder, pred, prey, assume_active_consent = TRUE)) + return FALSE if(!feeder.can_perform_action(pred, pred.interaction_flags_click | FORBID_TELEKINESIS_REACH)) - return + return FALSE #endif feeder.visible_message(span_danger("[feeder] 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) + return TRUE /datum/component/vore/proc/complete_vore(mob/living/prey) prey.forceMove(selected_belly) 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..f8792d13077a7 --- /dev/null +++ b/modular_zzplurt/code/datums/elements/holder_micro.dm @@ -0,0 +1,221 @@ +/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 = 'icons/obj/fluff/general.dmi' + icon_state = "error" // Some idiots determined that not having a state makes the item abstract, happy now? + worn_icon = null + inhand_icon_state = 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 + ignore_abstract = TRUE // it didn't help still + +/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/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/bodyfall1.ogg', 50, 1) + M.adjustStaminaLoss(10) + if("grab") + visible_message(span_danger("[user] squeezes their fist around [M]!")) + playsound(loc, 'sound/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 FALSE + + if(holder == eater) // Parent wants to eat pulled + . = vore.vore_other(held_mob) + else // Parent wants to feed pulled to clicked_on + . = 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 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..ae0e91ba1ab53 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,7 @@ /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) diff --git a/modular_zzplurt/code/modules/mob/living/living.dm b/modular_zzplurt/code/modules/mob/living/living.dm index 44e8544302ad1..c877d5c2347d1 100644 --- a/modular_zzplurt/code/modules/mob/living/living.dm +++ b/modular_zzplurt/code/modules/mob/living/living.dm @@ -25,3 +25,39 @@ 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 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/resize/resizing.dm b/modular_zzplurt/code/modules/resize/resizing.dm new file mode 100644 index 0000000000000..92c5d84771751 --- /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, /mob/.proc/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, /mob/.proc/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, /mob/.proc/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..39238ba8d6134 --- /dev/null +++ b/modular_zzplurt/code/modules/resize/sizechems.dm @@ -0,0 +1,130 @@ +//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" + can_synth = FALSE + metabolization_rate = 0.25 + +//Sizechem reaction +/datum/chemical_reaction/sizechem + name = "Cell-Volume Altering Base" + id = /datum/reagent/sizechem + mix_message = "the reaction rapidly alters in size!" + required_reagents = list(/datum/reagent/growthserum = 0.15, /datum/reagent/medicine/clonexadone = 0.15, /datum/reagent/gold = 0.15, /datum/reagent/acetone = 0.15) + results = list(/datum/reagent/sizechem = 0.3) + required_temp = 1 + //Fermichem vars + OptimalTempMin = 600 // Lower area of bell curve for determining heat based rate reactions + OptimalTempMax = 630 // Upper end for above + ExplodeTemp = 635 // Temperature at which reaction explodes + OptimalpHMin = 5 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase) + OptimalpHMax = 5.5 // Higest value for above + ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) + CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) + CurveSharpT = 4 // How sharp the temperature exponential curve is (to the power of value) + CurveSharppH = 4 // How sharp the pH exponential curve is (to the power of value) + ThermicConstant = -10 // Temperature change per 1u produced + HIonRelease = 0.02 // pH change per 1u reaction (inverse for some reason) + RateUpLim = 1 // Optimal/max rate possible if all conditions are perfect + FermiChem = TRUE // If the chemical uses the Fermichem reaction mechanics + FermiExplode = FALSE // If the chemical explodes in a special way + PurityMin = 0.2 + +//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 + can_synth = FALSE //DO NOT MAKE THIS SNYTHESIZABLE, THESE CHEMS ARE SUPPOSED TO NOT BE USED COMMONLY + +//Growthchem reaction +/datum/chemical_reaction/growthchem + name = "Prospacillin" + id = /datum/reagent/growthchem + mix_message = "the reaction appears to grow!" + required_reagents = list(/datum/reagent/sizechem = 0.15, /datum/reagent/consumable/condensedcapsaicin = 0.15, /datum/reagent/drug/aphrodisiac = 0.30) + results = list(/datum/reagent/growthchem = 0.25) + required_temp = 1 + OptimalTempMin = 700 // Lower area of bell curve for determining heat based rate reactions + OptimalTempMax = 730 // Upper end for above + ExplodeTemp = 735 // Temperature at which reaction explodes + OptimalpHMin = 3 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase) + OptimalpHMax = 3.5 // Higest value for above + ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) + CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) + CurveSharpT = 4 // How sharp the temperature exponential curve is (to the power of value) + CurveSharppH = 4 // How sharp the pH exponential curve is (to the power of value) + ThermicConstant = -10 // Temperature change per 1u produced + HIonRelease = 0.02 // pH change per 1u reaction (inverse for some reason) + RateUpLim = 1 // Optimal/max rate possible if all conditions are perfect + FermiChem = TRUE // If the chemical uses the Fermichem reaction mechanics + FermiExplode = FALSE // If the chemical explodes in a special way + PurityMin = 0.2 + +//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 + can_synth = FALSE //SAME STORY AS ABOVE + +//Shrinchem reaction +/datum/chemical_reaction/shrinkchem + name = "Diminicillin" + id = /datum/reagent/shrinkchem + mix_message = "the reaction appears to shrink!" + required_reagents = list(/datum/reagent/sizechem = 0.15, /datum/reagent/consumable/frostoil = 0.15, /datum/reagent/drug = 0.30) + results = list(/datum/reagent/shrinkchem = 0.25) + required_temp = 1 + OptimalTempMin = 100 // Lower area of bell curve for determining heat based rate reactions + OptimalTempMax = 150 // Upper end for above + ExplodeTemp = 350 // Temperature at which reaction explodes + OptimalpHMin = 3 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase) + OptimalpHMax = 4.5 // Higest value for above + ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase) + CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst) + CurveSharpT = 4 // How sharp the temperature exponential curve is (to the power of value) + CurveSharppH = 4 // How sharp the pH exponential curve is (to the power of value) + ThermicConstant = -10 // Temperature change per 1u produced + HIonRelease = 0.02 // pH change per 1u reaction (inverse for some reason) + RateUpLim = 1 // Optimal/max rate possible if all conditions are perfect + FermiChem = TRUE // If the chemical uses the Fermichem reaction mechanics + FermiExplode = FALSE // If the chemical explodes in a special way + PurityMin = 0.2 + +//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/tgstation.dme b/tgstation.dme index dec04d704ffc9..b9f19702b0dfe 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -515,9 +515,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" @@ -1626,6 +1628,7 @@ #include "code\datums\elements\mirage_border.dm" #include "code\datums\elements\mob_access.dm" #include "code\datums\elements\mob_grabber.dm" +#include "code\datums\elements\mob_holder.dm" #include "code\datums\elements\mob_killed_tally.dm" #include "code\datums\elements\move_force_on_death.dm" #include "code\datums\elements\movement_turf_changer.dm" @@ -9292,6 +9295,7 @@ #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\keybinding\human.dm" #include "modular_zzplurt\code\datums\keybinding\living.dm" #include "modular_zzplurt\code\game\objects\items.dm" @@ -9342,7 +9346,10 @@ #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\reagents\chemistry\machinery\chem_dispenser.dm" +#include "modular_zzplurt\code\modules\resize\resizing.dm" +#include "modular_zzplurt\code\modules\resize\sizegun.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"