diff --git a/code/__DEFINES/movespeed_modification.dm b/code/__DEFINES/movespeed_modification.dm
index 9faa37ac..d224c0f1 100644
--- a/code/__DEFINES/movespeed_modification.dm
+++ b/code/__DEFINES/movespeed_modification.dm
@@ -32,7 +32,10 @@
#define MOVESPEED_ID_SANITY "MOOD_SANITY"
-#define MOVESPEED_ID_TASED_STATUS "TASED"
+#define MOVESPEED_ID_TASED_STATUS "MOOD_SANITY"
#define MOVESPEED_ID_PRONE_DRAGGING "PRONE_DRAG"
-#define MOVESPEED_ID_HUMAN_CARRYING "HUMAN_CARRY"
\ No newline at end of file
+#define MOVESPEED_ID_HUMAN_CARRYING "HUMAN_CARRY"
+
+#define MOVESPEED_ID_SHRUNK "SHRINK_SPEED_MODIFIER"
+#define MOVESPEED_ID_GROW "GROWTH_SPEED_MODIFIER"
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index 559d880f..19e71bcf 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -308,6 +308,9 @@
/obj/machinery/suit_storage_unit/attackby(obj/item/I, mob/user, params)
if(state_open && is_operational())
+ if(istype(I, /obj/item/clothing/head/mob_holder))
+ to_chat(user, "You can't quite fit that while you hold it!")
+ return
if(istype(I, /obj/item/clothing/suit))
if(suit)
to_chat(user, "The unit already contains a suit!.")
diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm
index af9e47f5..69e244a6 100644
--- a/code/game/machinery/washing_machine.dm
+++ b/code/game/machinery/washing_machine.dm
@@ -219,6 +219,10 @@
update_icon()
return
+ if(istype(W, /obj/item/clothing/head/mob_holder))
+ to_chat(user, "It's too unweildy to put in this way.")
+ return 1
+
else if(user.a_intent != INTENT_HARM)
if (!state_open)
diff --git a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm
index dd33f696..0755fdc7 100644
--- a/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm
+++ b/code/modules/food_and_drinks/kitchen_machinery/deep_fryer.dm
@@ -80,6 +80,9 @@ God bless America.
I.reagents.trans_to(src, I.reagents.total_volume)
qdel(I)
return
+ if(istype(I,/obj/item/clothing/head/mob_holder))
+ to_chat(user, "This does not fit in the fryer.") // TODO: Deepfrying instakills mobs, spawns a whole deep-fried mob.
+ return
if(!reagents.has_reagent("cooking_oil"))
to_chat(user, "[src] has no cooking oil to fry with!")
return
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 90ce091c..0afe2d08 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -159,22 +159,35 @@
return
//END OF CIT CHANGES
- var/atom/movable/thrown_thing
var/obj/item/I = src.get_active_held_item()
- if(!I)
- if(pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
- var/mob/living/throwable_mob = pulling
- if(!throwable_mob.buckled)
- thrown_thing = throwable_mob
+ var/atom/movable/thrown_thing
+ var/mob/living/throwable_mob
+
+ if(istype(I, /obj/item/clothing/head/mob_holder))
+ var/obj/item/clothing/head/mob_holder/holder = I
+ if(holder.held_mob)
+ throwable_mob = holder.held_mob
+ holder.release()
+
+ if(!I || throwable_mob)
+ if(!throwable_mob && pulling && isliving(pulling) && grab_state >= GRAB_AGGRESSIVE)
+ throwable_mob = pulling
+
+ if(throwable_mob && !throwable_mob.buckled)
+ thrown_thing = throwable_mob
+ if(pulling)
stop_pulling()
- if(HAS_TRAIT(src, TRAIT_PACIFISM))
- to_chat(src, "You gently let go of [throwable_mob].")
- adjustStaminaLossBuffered(25)//CIT CHANGE - throwing an entire person shall be very tiring
- var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
- var/turf/end_T = get_turf(target)
- if(start_T && end_T)
- log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
+ if(HAS_TRAIT(src, TRAIT_PACIFISM))
+ to_chat(src, "You gently let go of [throwable_mob].")
+ return
+
+ adjustStaminaLossBuffered(25)//CIT CHANGE - throwing an entire person shall be very tiring
+ var/turf/start_T = get_turf(loc) //Get the start and target tile for the descriptors
+ var/turf/end_T = get_turf(target)
+ if(start_T && end_T)
+
+ log_combat(src, throwable_mob, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]")
else if(!CHECK_BITFIELD(I.item_flags, ABSTRACT) && !HAS_TRAIT(I, TRAIT_NODROP))
thrown_thing = I
@@ -194,6 +207,8 @@
newtonian_move(get_dir(target, src))
thrown_thing.throw_at(target, thrown_thing.throw_range, thrown_thing.throw_speed, src)
+
+
/mob/living/carbon/restrained(ignore_grab)
. = (handcuffed || (!ignore_grab && pulledby && pulledby.grab_state >= GRAB_AGGRESSIVE))
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index 22da4634..b4ce85c0 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -16,6 +16,10 @@
msg += "[t_He] [t_is] wearing [wear_mask.get_examine_string(user)] on [t_his] face.\n"
if (wear_neck)
msg += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck.\n"
+ if(can_be_held)
+ msg += "[t_He] looks small enough to be picked up with Alt+Click!\n"
+
+
for(var/obj/item/I in held_items)
if(!(I.item_flags & ABSTRACT))
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index 1bfff1a9..50f63044 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -107,6 +107,10 @@
//Status effects
msg += status_effect_examines()
+ //Can be picked up?
+ if(can_be_held)
+ msg += "[t_He] looks small enough to be picked up with Alt+Click!\n"
+
//CIT CHANGES START HERE - adds genital details to examine text
if(LAZYLEN(internal_organs))
for(var/obj/item/organ/genital/dicc in internal_organs)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 6312db1e..bf843cad 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1098,4 +1098,8 @@
race = /datum/species/zombie/infectious
/mob/living/carbon/human/species/zombie/krokodil_addict
- race = /datum/species/krokodil_addict
\ No newline at end of file
+ race = /datum/species/krokodil_addict
+
+//define holder_type on nerds we wanna commit scoop to
+/mob/living/carbon/human
+ var/holder_type = /obj/item/clothing/head/mob_holder/micro
diff --git a/code/modules/mob/living/carbon/monkey/combat.dm b/code/modules/mob/living/carbon/monkey/combat.dm
index 25bc243f..92ad87f6 100644
--- a/code/modules/mob/living/carbon/monkey/combat.dm
+++ b/code/modules/mob/living/carbon/monkey/combat.dm
@@ -132,6 +132,10 @@
pickupTarget = null
pickupTimer = 0
else if(ismob(pickupTarget.loc)) // in someones hand
+ if(istype(pickupTarget, /obj/item/clothing/head/mob_holder/))
+ var/obj/item/clothing/head/mob_holder/h = pickupTarget
+ if(h && h.held_mob==src)
+ return//dont let them pickpocket themselves
var/mob/M = pickupTarget.loc
if(!pickpocketing)
pickpocketing = TRUE
diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm
index 7b44a01a..f8d05ec1 100644
--- a/code/modules/mob/living/carbon/monkey/monkey.dm
+++ b/code/modules/mob/living/carbon/monkey/monkey.dm
@@ -15,6 +15,7 @@
bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey,
/obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey)
hud_type = /datum/hud/monkey
+ can_be_held = "monkey"
/mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner)
verbs += /mob/living/proc/mob_sleep
@@ -45,6 +46,10 @@
SSmobs.cubemonkeys -= src
return ..()
+/mob/living/carbon/monkey/generate_mob_holder()
+ var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "monkey", 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi', TRUE)
+ return holder
+
/mob/living/carbon/monkey/create_internal_organs()
internal_organs += new /obj/item/organ/appendix
internal_organs += new /obj/item/organ/lungs
diff --git a/code/modules/mob/living/carbon/monkey/update_icons.dm b/code/modules/mob/living/carbon/monkey/update_icons.dm
index ff83b00f..8c3e905b 100644
--- a/code/modules/mob/living/carbon/monkey/update_icons.dm
+++ b/code/modules/mob/living/carbon/monkey/update_icons.dm
@@ -1,4 +1,3 @@
-
/mob/living/carbon/monkey/regenerate_icons()
if(!..())
update_body_parts()
@@ -77,4 +76,4 @@
/mob/living/carbon/monkey/update_hud_back(obj/item/I)
if(client && hud_used && hud_used.hud_shown)
I.screen_loc = ui_monkey_back
- client.screen += I
\ No newline at end of file
+ client.screen += I
diff --git a/code/modules/mob/living/carbon/update_icons.dm b/code/modules/mob/living/carbon/update_icons.dm
index aec1c86b..03df1cab 100644
--- a/code/modules/mob/living/carbon/update_icons.dm
+++ b/code/modules/mob/living/carbon/update_icons.dm
@@ -10,10 +10,29 @@
ntransform.TurnTo(lying_prev,lying)
if(lying == 0) //Lying to standing
final_pixel_y = get_standard_pixel_y_offset()
+ if(size_multiplier >= 1) //if its bigger than normal
+ ntransform.Translate(0,16 * (size_multiplier-1))
+ else
+ if(lying_prev == 90)
+ ntransform.Translate(16 * (size_multiplier-1),16 * (size_multiplier-1))
+
+ if(lying_prev == 270)
+ ntransform.Translate(-16 * (size_multiplier-1),16 * (size_multiplier-1))
+
else //if(lying != 0)
if(lying_prev == 0) //Standing to lying
pixel_y = get_standard_pixel_y_offset()
final_pixel_y = get_standard_pixel_y_offset(lying)
+ if(lying == 90) //Check the angle of the sprite to offset it accordingly.
+ ntransform.Translate(-16 * (size_multiplier-1),0)
+ if(size_multiplier < 1) //if its smaller than normal
+ ntransform.Translate(0,16 * (size_multiplier-1)) //we additionally offset the sprite downwards
+
+ if(lying == 270) //check the angle of the sprite to offset it accordingly
+ ntransform.Translate(16 * (size_multiplier-1),0)
+ if(size_multiplier < 1) //if its smaller than normal
+ ntransform.Translate(0,16 * (size_multiplier-1)) //we additionally offset the sprite downwards
+
if(dir & (EAST|WEST)) //Facing east or west
final_dir = pick(NORTH, SOUTH) //So you fall on your side rather than your face or ass
@@ -22,11 +41,40 @@
ntransform.Scale(resize)
resize = RESIZE_DEFAULT_SIZE
+ //Apply size multiplier, thank NeverExisted for this
+ if(size_multiplier != previous_size)
+ changed++
+ //now we offset the sprite
+ //Scaling affects offset. There's probably a smarter and easier way to do this, but this way it works for sure (?)
+ //Just to be clear. All this bullshit is needed because someone wanted to store the old transform matrix instead of using a new one each iteration
+ //Winfre is currently doing a great job at coating my nuts in slobber while i code this
+ if(!lying) //when standing. People of all sizes are affected equally
+ ntransform.Translate(0,-16 * (previous_size-1)) //reset the sprite
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly.
+ ntransform.Translate(0,16 * (size_multiplier-1)) //apply the new offset
+ else //when lying. Macros dont get an offset, Micros do. We must also check the cases when a micro becomes a macro and viceversa
+ if(previous_size <= 1 && size_multiplier <= 1) //micro stays a micro. We modify the side-offset
+ ntransform.Translate(0,-16 * (previous_size-1)) //reset the sprite
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly
+ ntransform.Translate(0,16 * (size_multiplier-1)) //apply the new offset
+
+ if(previous_size <= 1 && size_multiplier > 1) //micro becomes a macro. We remove the side-offset
+ ntransform.Translate(0,-16 * (previous_size-1)) //reset the sprite
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly
+
+ if(previous_size > 1 && size_multiplier <= 1) //macro becomes a micro. We add an offset
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly.
+ ntransform.Translate(0,16 * (size_multiplier-1)) //apply the new offset
+
+ if(previous_size > 1 && size_multiplier > 1) //macro stays a macro. We just scale the sprite with no offset changes
+ ntransform.Scale(size_multiplier/previous_size) //scale the sprite accordingly
+
+ previous_size = size_multiplier
+
if(changed)
animate(src, transform = ntransform, time = 2, pixel_y = final_pixel_y, dir = final_dir, easing = EASE_IN|EASE_OUT)
floating = 0 // If we were without gravity, the bouncing animation got stopped, so we make sure we restart it in next life().
-
/mob/living/carbon
var/list/overlays_standing[TOTAL_LAYERS]
diff --git a/code/modules/mob/living/inhand_holder.dm b/code/modules/mob/living/inhand_holder.dm
index b82e8cc4..bd51e930 100644
--- a/code/modules/mob/living/inhand_holder.dm
+++ b/code/modules/mob/living/inhand_holder.dm
@@ -5,80 +5,126 @@
desc = "Yell at coderbrush."
icon = null
icon_state = ""
- item_flags = DROPDEL
var/mob/living/held_mob
- var/can_head = TRUE
- var/destroying = FALSE
+ var/can_head = FALSE
+ w_class = WEIGHT_CLASS_BULKY
-/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/M, _worn_state, head_icon, lh_icon, rh_icon, _can_head = TRUE)
+/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/M, _worn_state, alt_worn, lh_icon, rh_icon, _can_head_override = FALSE)
. = ..()
- can_head = _can_head
- if(head_icon)
- alternate_worn_icon = head_icon
+
+ if(M)
+ M.setDir(SOUTH)
+ held_mob = M
+ M.forceMove(src)
+ appearance = M.appearance
+ name = M.name
+ desc = M.desc
+
+ if(_can_head_override)
+ can_head = _can_head_override
+ if(alt_worn)
+ alternate_worn_icon = alt_worn
if(_worn_state)
item_state = _worn_state
+ icon_state = _worn_state
if(lh_icon)
lefthand_file = lh_icon
if(rh_icon)
righthand_file = rh_icon
if(!can_head)
slot_flags = NONE
- deposit(M)
/obj/item/clothing/head/mob_holder/Destroy()
- destroying = TRUE
if(held_mob)
- release(FALSE)
+ release()
return ..()
-/obj/item/clothing/head/mob_holder/proc/deposit(mob/living/L)
- if(!istype(L))
- return FALSE
- L.setDir(SOUTH)
- update_visuals(L)
- held_mob = L
- L.forceMove(src)
- name = L.name
- desc = L.desc
- return TRUE
+/obj/item/clothing/head/mob_holder/dropped()
+ ..()
+ if(isturf(loc))//don't release on soft-drops
+ release()
-/obj/item/clothing/head/mob_holder/proc/update_visuals(mob/living/L)
- appearance = L.appearance
-
-/obj/item/clothing/head/mob_holder/proc/release(del_on_release = TRUE)
- if(!held_mob)
- if(del_on_release && !destroying)
- qdel(src)
- return FALSE
+/obj/item/clothing/head/mob_holder/proc/release()
if(isliving(loc))
var/mob/living/L = loc
- to_chat(L, "[held_mob] wriggles free!")
L.dropItemToGround(src)
- held_mob.forceMove(get_turf(held_mob))
- held_mob.reset_perspective()
- held_mob.setDir(SOUTH)
- held_mob.visible_message("[held_mob] uncurls!")
- held_mob = null
- if(del_on_release && !destroying)
- qdel(src)
- return TRUE
+ if(held_mob)
+ var/mob/living/m = held_mob
+ m.forceMove(get_turf(m))
+ m.reset_perspective()
+ m.setDir(SOUTH)
+ held_mob = null
+ qdel(src)
/obj/item/clothing/head/mob_holder/relaymove(mob/user)
- release()
+ return
/obj/item/clothing/head/mob_holder/container_resist()
+ if(isliving(loc))
+ var/mob/living/L = loc
+ visible_message("[src] escapes [L]!")
release()
-/obj/item/clothing/head/mob_holder/drone/deposit(mob/living/L)
- . = ..()
- if(!isdrone(L))
- qdel(src)
- name = "drone (hiding)"
- desc = "This drone is scared and has curled up into a ball!"
+/mob/living/proc/mob_pickup(mob/living/L)
+ var/obj/item/clothing/head/mob_holder/holder = generate_mob_holder()
+ if(!holder)
+ return
+ drop_all_held_items()
+ L.put_in_hands(holder)
+ return
-/obj/item/clothing/head/mob_holder/drone/update_visuals(mob/living/L)
- var/mob/living/simple_animal/drone/D = L
- if(!D)
- return ..()
- icon = 'icons/mob/drone.dmi'
- icon_state = "[D.visualAppearence]_hat"
+/mob/living/proc/mob_try_pickup(mob/living/user)
+ if(!ishuman(user) || !src.Adjacent(user) || user.incapacitated() || !can_be_held)
+ return FALSE
+ if(abs(user.get_effective_size()/src.get_effective_size()) < 2.0 )
+ to_chat(user, "They're too big to pick up!")
+ return FALSE
+ if(user.get_active_held_item())
+ to_chat(user, "Your hands are full!")
+ return FALSE
+ if(buckled)
+ to_chat(user, "[src] is buckled to something!")
+ return FALSE
+ if(src == user)
+ to_chat(user, "You can't pick yourself up.")
+ return FALSE
+ visible_message("[user] starts picking up [src].", \
+ "[user] starts picking you up!")
+ if(!do_after(user, 20, target = src))
+ return FALSE
+
+ if(user.get_active_held_item()||buckled)
+ return FALSE
+
+ visible_message("[user] picks up [src]!", \
+ "[user] picks you up!")
+ to_chat(user, "You pick [src] up.")
+ mob_pickup(user)
+ return TRUE
+
+/mob/living/AltClick(mob/user)
+ . = ..()
+ if(mob_try_pickup(user))
+ return TRUE
+
+/obj/item/clothing/head/mob_holder/assume_air(datum/gas_mixture/env)
+ var/atom/location = loc
+ if(!loc)
+ return //null
+ var/turf/T = get_turf(loc)
+ while(location != T)
+ location = location.loc
+ if(ismob(location))
+ return location.loc.assume_air(env)
+ return location.assume_air(env)
+
+/obj/item/clothing/head/mob_holder/remove_air(amount)
+ var/atom/location = loc
+ if(!loc)
+ return //null
+ var/turf/T = get_turf(loc)
+ while(location != T)
+ location = location.loc
+ if(ismob(location))
+ return location.loc.remove_air(amount)
+ return location.remove_air(amount)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index f311649d..70317492 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -40,6 +40,12 @@
QDEL_LIST(diseases)
return ..()
+
+/mob/living/proc/generate_mob_holder()
+ var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
+ return holder
+
+
/mob/living/proc/OpenCraftingMenu()
return
@@ -136,6 +142,11 @@
else if((M.restrained() || M.a_intent == INTENT_HELP) && (restrained() || a_intent == INTENT_HELP))
mob_swap = 1
if(mob_swap)
+
+ //handle micro bumping on help intent
+ if(handle_micro_bump_helping(M))
+ return 1
+
//switch our position with M
if(loc && !loc.Adjacent(M.loc))
return 1
@@ -168,6 +179,11 @@
//not if he's not CANPUSH of course
if(!(M.status_flags & CANPUSH))
return 1
+
+ //handle micro bumping on other intents
+ if(handle_micro_bump_other(M))
+ return 1
+
if(isliving(M))
var/mob/living/L = M
if(HAS_TRAIT(L, TRAIT_PUSHIMMUNE))
@@ -281,7 +297,11 @@
var/datum/disease/D = thing
if(D.spread_flags & DISEASE_SPREAD_CONTACT_SKIN)
ContactContractDisease(D)
-p
+
+ if(iscarbon(L))
+ var/mob/living/carbon/C = L
+ if(HAS_TRAIT(src, TRAIT_STRONG_GRABBER))
+ C.grippedby(src)
//mob verbs are a lot faster than object verbs
//for more info on why this is not atom/pull, see examinate() in mob.dm
@@ -1124,23 +1144,6 @@ p
if(can_be_held)
mob_try_pickup(over)
-/mob/living/proc/mob_pickup(mob/living/L)
- return
-
-/mob/living/proc/mob_try_pickup(mob/living/user)
- if(!ishuman(user))
- return
- if(user.get_active_held_item())
- to_chat(user, "Your hands are full!")
- return FALSE
- if(buckled)
- to_chat(user, "[src] is buckled to something!")
- return FALSE
- user.visible_message("[user] starts trying to scoop up [src]!")
- if(!do_after(user, 20, target = src))
- return FALSE
- mob_pickup(user)
- return TRUE
/mob/living/proc/get_static_viruses() //used when creating blood and other infective objects
if(!LAZYLEN(diseases))
@@ -1236,3 +1239,10 @@ p
update_canmove()
for(var/chem in healing_chems)
reagents.add_reagent(chem, healing_chems[chem])
+
+//retard edits below
+/mob/living
+ var/size_multiplier = 1 //multiplier for the mob's icon size atm
+ var/previous_size = 1
+ var/holder_default
+// can_be_held = "micro"
\ No newline at end of file
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index b6e2c16a..3740827b 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -108,7 +108,7 @@
var/list/obj/effect/proc_holder/abilities = list()
- var/can_be_held = FALSE //whether this can be picked up and held.
+ var/can_be_held = TRUE //whether this can be picked up and held. Currently needs to be on for sizecode to work, fix later.
var/radiation = 0 //If the mob is irradiated.
var/ventcrawl_layer = PIPING_LAYER_DEFAULT
diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm
index 7df851ec..4c47a606 100644
--- a/code/modules/mob/living/simple_animal/friendly/cat.dm
+++ b/code/modules/mob/living/simple_animal/friendly/cat.dm
@@ -31,6 +31,8 @@
var/mob/living/simple_animal/mouse/movement_target
gold_core_spawnable = FRIENDLY_SPAWN
collar_type = "cat"
+ can_be_held = "cat2"
+ size_multiplier = 0.5
do_footstep = TRUE
@@ -80,6 +82,7 @@
pass_flags = PASSMOB
mob_size = MOB_SIZE_SMALL
collar_type = "kitten"
+ can_be_held = "cat"
//RUNTIME IS ALIVE! SQUEEEEEEEE~
/mob/living/simple_animal/pet/cat/Runtime
@@ -262,6 +265,7 @@
attacked_sound = 'sound/items/eatfood.ogg'
deathmessage = "loses its false life and collapses!"
death_sound = "bodyfall"
+ can_be_held = "cak"
/mob/living/simple_animal/pet/cat/cak/CheckParts(list/parts)
..()
diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm
index c194233c..00f9350d 100644
--- a/code/modules/mob/living/simple_animal/friendly/dog.dm
+++ b/code/modules/mob/living/simple_animal/friendly/dog.dm
@@ -13,8 +13,10 @@
see_in_dark = 5
speak_chance = 1
turns_per_move = 10
+ size_multiplier = 0.5
do_footstep = TRUE
+ can_be_held = TRUE
//Corgis and pugs are now under one dog subtype
@@ -35,6 +37,7 @@
var/obj/item/inventory_back
var/shaved = FALSE
var/nofur = FALSE //Corgis that have risen past the material plane of existence.
+ can_be_held = "corgi"
/mob/living/simple_animal/pet/dog/corgi/Destroy()
QDEL_NULL(inventory_head)
@@ -63,6 +66,7 @@
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/pug = 3)
gold_core_spawnable = FRIENDLY_SPAWN
collar_type = "pug"
+ can_be_held = "pug"
/mob/living/simple_animal/pet/dog/corgi/exoticcorgi
name = "Exotic Corgi"
@@ -360,6 +364,7 @@
icon_dead = "old_corgi_dead"
desc = "At a ripe old age of [record_age] Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP
turns_per_move = 20
+ can_be_held = "old_corgi"
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
@@ -582,6 +587,7 @@
unsuitable_atmos_damage = 0
minbodytemp = TCMB
maxbodytemp = T0C + 40
+ can_be_held = "void_puppy"
/mob/living/simple_animal/pet/dog/corgi/puppy/void/Process_Spacemove(movement_dir = 0)
return 1 //Void puppies can navigate space.
@@ -603,6 +609,7 @@
response_harm = "kicks"
var/turns_since_scan = 0
var/puppies = 0
+ can_be_held = "lisa"
//Lisa already has a cute bow!
/mob/living/simple_animal/pet/dog/corgi/Lisa/Topic(href, href_list)
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index 6d312147..f880adb7 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -274,3 +274,7 @@
/mob/living/simple_animal/drone/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
return 0 //So they don't die trying to fix wiring
+
+/mob/living/simple_animal/drone/generate_mob_holder()
+ var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "[visualAppearence]_hat", null, null, null, TRUE)
+ return holder
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
index 33031fd8..e40eb585 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
@@ -29,28 +29,11 @@
if("Nothing")
return
-//ATTACK HAND IGNORING PARENT RETURN VALUE
+//picky up the drone c:
/mob/living/simple_animal/drone/attack_hand(mob/user)
- if(ishuman(user))
- if(stat == DEAD || status_flags & GODMODE || !can_be_held)
- ..()
- return
- if(user.get_active_held_item())
- to_chat(user, "Your hands are full!")
- return
- visible_message("[user] starts picking up [src].", \
- "[user] starts picking you up!")
- if(!do_after(user, 20, target = src))
- return
- visible_message("[user] picks up [src]!", \
- "[user] picks you up!")
- if(buckled)
- to_chat(user, "[src] is buckled to [buckled] and cannot be picked up!")
- return
- to_chat(user, "You pick [src] up.")
- drop_all_held_items()
- var/obj/item/clothing/head/mob_holder/drone/DH = new(get_turf(src), src)
- user.put_in_hands(DH)
+ ..()
+ if(user.a_intent == INTENT_HELP)
+ mob_try_pickup(user)
/mob/living/simple_animal/drone/proc/try_reactivate(mob/living/user)
var/mob/dead/observer/G = get_ghost()
diff --git a/code/modules/mob/living/simple_animal/friendly/fox.dm b/code/modules/mob/living/simple_animal/friendly/fox.dm
index 28b66c26..3f58ca59 100644
--- a/code/modules/mob/living/simple_animal/friendly/fox.dm
+++ b/code/modules/mob/living/simple_animal/friendly/fox.dm
@@ -18,7 +18,7 @@
response_disarm = "gently pushes aside"
response_harm = "kicks"
gold_core_spawnable = FRIENDLY_SPAWN
-
+ can_be_held = "fox"
do_footstep = TRUE
//Captain fox
diff --git a/code/modules/mob/living/simple_animal/friendly/lizard.dm b/code/modules/mob/living/simple_animal/friendly/lizard.dm
index e329dd3f..6076e412 100644
--- a/code/modules/mob/living/simple_animal/friendly/lizard.dm
+++ b/code/modules/mob/living/simple_animal/friendly/lizard.dm
@@ -23,6 +23,8 @@
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
var/static/list/edibles = typecacheof(list(/mob/living/simple_animal/butterfly, /mob/living/simple_animal/cockroach)) //list of atoms, however turfs won't affect AI, but will affect consumption.
+ can_be_held = "lizard"
+ size_multiplier = 0.5
/mob/living/simple_animal/hostile/lizard/CanAttack(atom/the_target)//Can we actually attack a possible target?
if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
@@ -39,3 +41,7 @@
return TRUE
else
return ..()
+
+/mob/living/simple_animal/hostile/lizard/generate_mob_holder()
+ var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "lizard", 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi', TRUE)
+ return holder
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index bf45c9cc..028bada0 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -25,6 +25,8 @@
var/body_color //brown, gray and white, leave blank for random
gold_core_spawnable = FRIENDLY_SPAWN
var/chew_probability = 1
+ can_be_held = TRUE
+ size_multiplier = 0.5
/mob/living/simple_animal/mouse/Initialize()
. = ..()
@@ -34,7 +36,7 @@
icon_state = "mouse_[body_color]"
icon_living = "mouse_[body_color]"
icon_dead = "mouse_[body_color]_dead"
-
+ can_be_held = "mouse_[body_color]"
/mob/living/simple_animal/mouse/proc/splat()
src.health = 0
@@ -87,14 +89,17 @@
/mob/living/simple_animal/mouse/white
body_color = "white"
icon_state = "mouse_white"
+ can_be_held = "mouse_white"
/mob/living/simple_animal/mouse/gray
body_color = "gray"
icon_state = "mouse_gray"
+ can_be_held = "mouse_gray"
/mob/living/simple_animal/mouse/brown
body_color = "brown"
icon_state = "mouse_brown"
+ can_be_held = "mouse_brown"
//TOM IS ALIVE! SQUEEEEEEEE~K :)
/mob/living/simple_animal/mouse/brown/Tom
@@ -118,3 +123,8 @@
/obj/item/reagent_containers/food/snacks/deadmouse/on_grind()
reagents.clear_reagents()
+
+/mob/living/simple_animal/mouse/generate_mob_holder()
+ var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
+ holder.w_class = WEIGHT_CLASS_TINY
+ return holder
diff --git a/code/modules/mob/living/simple_animal/friendly/sloth.dm b/code/modules/mob/living/simple_animal/friendly/sloth.dm
index 324fa107..fb114ace 100644
--- a/code/modules/mob/living/simple_animal/friendly/sloth.dm
+++ b/code/modules/mob/living/simple_animal/friendly/sloth.dm
@@ -22,7 +22,8 @@
maxHealth = 50
speed = 10
glide_size = 2
-
+ can_be_held = "sloth" //finally oranges can be held
+ size_multiplier = 0.5
do_footstep = TRUE
diff --git a/code/modules/recycling/disposal/bin.dm b/code/modules/recycling/disposal/bin.dm
index 871fd32b..1d152f72 100644
--- a/code/modules/recycling/disposal/bin.dm
+++ b/code/modules/recycling/disposal/bin.dm
@@ -102,9 +102,17 @@
return ..()
/obj/machinery/disposal/proc/place_item_in_disposal(obj/item/I, mob/user)
- I.forceMove(src)
- user.visible_message("[user.name] places \the [I] into \the [src].", "You place \the [I] into \the [src].")
-
+ if(istype(I, /obj/item/clothing/head/mob_holder))
+ var/obj/item/clothing/head/mob_holder/H = I
+ var/mob/living/m = H.held_mob
+ H.release()
+ if(m)
+ user.start_pulling(m, 1)
+ stuff_mob_in(m,user)
+ return//you don't want this going into disposals ever
+ if(user.temporarilyRemoveItemFromInventory(I)) //double-checks never hurt
+ I.forceMove(src)
+ user.visible_message("[user.name] places \the [I] into \the [src].", "You place \the [I] into \the [src].")
//mouse drop another mob or self
/obj/machinery/disposal/MouseDrop_T(mob/living/target, mob/living/user)
if(istype(target))
diff --git a/hyperstation/code/modules/resize/holder_micro.dm b/hyperstation/code/modules/resize/holder_micro.dm
new file mode 100644
index 00000000..6f3d7806
--- /dev/null
+++ b/hyperstation/code/modules/resize/holder_micro.dm
@@ -0,0 +1,8 @@
+// Micro Holders - Extends /obj/item/holder
+
+/obj/item/clothing/head/mob_holder/micro
+ name = "micro"
+ desc = "Another person, small enough to fit in your hand."
+ icon = null // I forgot how to fix this.
+ icon_state = ""
+ slot_flags = ITEM_SLOT_FEET | ITEM_SLOT_HEAD | ITEM_SLOT_ID
\ No newline at end of file
diff --git a/hyperstation/code/modules/resize/resizing.dm b/hyperstation/code/modules/resize/resizing.dm
new file mode 100644
index 00000000..48b542d0
--- /dev/null
+++ b/hyperstation/code/modules/resize/resizing.dm
@@ -0,0 +1,146 @@
+//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
+var/const/RESIZE_MACRO = 6
+var/const/RESIZE_HUGE = 4
+var/const/RESIZE_BIG = 2
+var/const/RESIZE_NORMAL = 1
+var/const/RESIZE_SMALL = 0.75
+var/const/RESIZE_TINY = 0.50
+var/const/RESIZE_MICRO = 0.25
+
+//averages
+var/const/RESIZE_A_MACROHUGE = (RESIZE_MACRO + RESIZE_HUGE) / 2
+var/const/RESIZE_A_HUGEBIG = (RESIZE_HUGE + RESIZE_BIG) / 2
+var/const/RESIZE_A_BIGNORMAL = (RESIZE_BIG + RESIZE_NORMAL) / 2
+var/const/RESIZE_A_NORMALSMALL = (RESIZE_NORMAL + RESIZE_SMALL) / 2
+var/const/RESIZE_A_SMALLTINY = (RESIZE_SMALL + RESIZE_TINY) / 2
+var/const/RESIZE_A_TINYMICRO = (RESIZE_TINY + RESIZE_MICRO) / 2
+
+//Scale up a mob's icon by the size_multiplier
+/mob/living/update_transform()
+ ASSERT(!iscarbon(src)) //the source isnt carbon should always be true
+ var/matrix/M = matrix() //matrix (M) variable
+ M.Scale(size_multiplier)
+ M.Translate(0, 16*(size_multiplier-1)) //translate by 16 * size_multiplier - 1 on Y axis
+ src.transform = M //the source of transform is M
+
+/mob/proc/get_effective_size()
+ return 100000
+
+mob/living/get_effective_size()
+ return src.size_multiplier
+
+/mob/living/proc/resize(var/new_size, var/animate = TRUE)
+ if(size_multiplier == new_size)
+ return 1
+
+ size_multiplier = new_size //Change size_multiplier so that other items can interact with them
+ src.update_transform() //WORK DAMN YOU
+
+//handle the big steppy, except nice
+/mob/living/proc/handle_micro_bump_helping(var/mob/living/tmob)
+
+ //Both small.
+ if(src.get_effective_size() <= RESIZE_A_SMALLTINY && tmob.get_effective_size() <= RESIZE_A_SMALLTINY)
+ now_pushing = 0
+ src.forceMove(tmob.loc)
+ return 1
+
+ //Doing messages
+ if(abs(get_effective_size()/tmob.get_effective_size()) >= 2) //if the initiator is twice the size of the micro
+ now_pushing = 0
+ src.forceMove(tmob.loc)
+
+ //Smaller person being stepped on
+ if(get_effective_size() > tmob.get_effective_size() && iscarbon(src))
+ if(istype(tmob) && istype(tmob, /datum/sprite_accessory/taur/naga))
+ to_chat(src,"You carefully slither around [tmob].")
+ to_chat(tmob,"[src]'s huge tail slithers beside you!")
+ else
+ to_chat(src,"You carefully step over [tmob].")
+ to_chat(tmob,"[src] steps over you carefully!")
+ return 1
+
+ //Smaller person stepping under a larger person
+ if(tmob.get_effective_size() > get_effective_size())
+ micro_step_under(tmob)
+ src.forceMove(tmob.loc)
+ now_pushing = 0
+ return 1
+
+//Stepping on disarm intent
+/mob/living/proc/handle_micro_bump_other(var/mob/living/tmob)
+ ASSERT(isliving(tmob))
+
+ //Both small
+ if(src.get_effective_size() <= RESIZE_A_SMALLTINY && tmob.get_effective_size() <= RESIZE_A_SMALLTINY)
+ now_pushing = 0
+ src.forceMove(tmob.loc)
+ return 1
+
+ if(abs(get_effective_size()/tmob.get_effective_size()) >= 2)
+ if(src.a_intent == "disarm" && src.canmove && !src.buckled)
+ now_pushing = 0
+ src.forceMove(tmob.loc)
+ if(get_effective_size() > tmob.get_effective_size() && iscarbon(src))
+ if(istype(tmob) && istype(tmob, /datum/sprite_accessory/taur/naga))
+ to_chat(src,"You carefully roll over [tmob] with your tail!")
+ to_chat(tmob,"[src]'s huge tail rolls over you!")
+ sizediffStamLoss(tmob)
+ else
+ to_chat(src,"You painfully but harmlessly step on [tmob]!")
+ to_chat(tmob,"[src] steps onto you with force!")
+ sizediffStamLoss(tmob)
+ return 1
+
+ if(src.a_intent == "harm" && src.canmove && !src.buckled)
+ now_pushing = 0
+ src.forceMove(tmob.loc)
+ if(get_effective_size() > tmob.get_effective_size() && iscarbon(src))
+ if(istype(tmob) && istype(tmob, /datum/sprite_accessory/taur/naga))
+ to_chat(src,"You grind [tmob] into the floor with your tail!")
+ to_chat(tmob,"[src]'s massive tail plows you into the floor!")
+ sizediffStamLoss(tmob)
+ sizediffBruteloss(tmob)
+ else
+ to_chat(src,"You pound [tmob] into the floor underfoot!")
+ to_chat(tmob,"[src] slams you into the ground, crushing you!")
+ sizediffStamLoss(tmob)
+ sizediffBruteloss(tmob)
+ return 1
+
+// if(src.a_inent == "grab"... goes here... WIP
+
+ if(tmob.get_effective_size() > get_effective_size())
+ micro_step_under(tmob)
+ src.forceMove(tmob.loc)
+ now_pushing = 0
+ return 1
+
+//smaller person stepping under another person
+/mob/living/proc/micro_step_under(var/mob/living/tmob)
+ if(istype(tmob) && istype(tmob, /datum/sprite_accessory/taur/naga))
+ to_chat(src,"You jump over [tmob]'s thick tail.")
+ to_chat(tmob,"[src] bounds over your tail.")
+ else
+ to_chat(src,"You run between [tmob]'s legs.")
+ to_chat(tmob,"[src] runs between your legs.")
+
+//Proc for scaling stamina damage on size difference
+/mob/living/proc/sizediffStamLoss(var/mob/living/tmob)
+ var/S = (get_effective_size()/tmob.get_effective_size()*25) //macro divided by micro, times 25
+ tmob.Knockdown(S) //final result in stamina knockdown
+
+//Proc for scaling brute damage on size difference
+/mob/living/proc/sizediffBruteloss(var/mob/living/tmob)
+ var/B = (get_effective_size()/tmob.get_effective_size()*2) //macro divided by micro, times 2
+ tmob.adjustBruteLoss(B) //final result in brute loss
+
+//Proc for instantly grabbing valid size difference. Code optimizations soon(TM)
+/*
+/mob/living/proc/sizeinteractioncheck(var/mob/living/tmob)
+ if(abs(get_effective_size()/tmob.get_effective_size())>=2.0 && get_effective_size()>tmob.get_effective_size())
+ return 0
+ else
+ return 1
+*/
+//Clothes coming off at different sizes, and health/speed/stam changes as well
diff --git a/hyperstation/code/modules/resize/sizechems.dm b/hyperstation/code/modules/resize/sizechems.dm
new file mode 100644
index 00000000..90deb236
--- /dev/null
+++ b/hyperstation/code/modules/resize/sizechems.dm
@@ -0,0 +1,40 @@
+//Size Chemicals, now with better and less cringy names.
+
+/datum/reagent/dahl/growthchem
+ name = "Prospacillin"
+ id = "growthchem"
+ 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
+
+/datum/reagent/dahl/growthchem/on_mob_add(mob/living/carbon/M)
+ log_game("SIZECODE: [M] ckey: [M.key] has ingested growthchem.")
+
+/datum/reagent/dahl/growthchem/on_mob_life(mob/living/carbon/M)
+ if(M.size_multiplier < RESIZE_MACRO)
+ M.resize(M.size_multiplier+0.01)
+
+ return
+
+/datum/reagent/dahl/shrinkchem
+ name = "Diminicillin"
+ id = "shrinkchem"
+ 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.25
+ can_synth = FALSE //SAME STORY AS ABOVE
+
+/datum/reagent/dahl/shrinkchem/on_mob_add(mob/living/carbon/M)
+ log_game("SIZECODE: [M] ckey: [M.key] has ingested shrinkchem.")
+
+/datum/reagent/dahl/shrinkchem/on_mob_life(mob/living/carbon/M)
+ if(M.size_multiplier > RESIZE_MICRO)
+ M.resize(M.size_multiplier-0.01)
+
+ return
+
diff --git a/hyperstation/code/modules/resize/sizegun.dm b/hyperstation/code/modules/resize/sizegun.dm
new file mode 100644
index 00000000..d1154838
--- /dev/null
+++ b/hyperstation/code/modules/resize/sizegun.dm
@@ -0,0 +1,86 @@
+/obj/item/projectile/sizelaser
+ name = "sizeray laser"
+ icon_state = "omnilaser"
+ hitsound = null
+ damage = 5
+ damage_type = STAMINA
+ flag = "laser"
+ pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
+
+/obj/item/projectile/sizelaser/shrinkray
+ icon_state="bluelaser"
+
+/obj/item/projectile/sizelaser/growthray
+ icon_state="laser"
+
+/obj/item/projectile/sizelaser/shrinkray/on_hit(var/atom/target, var/blocked = 0)
+ if(istype(target, /mob/living/carbon/human))
+ var/mob/living/M = target
+ switch(M.size_multiplier)
+ if(RESIZE_MACRO to INFINITY)
+ M.resize(RESIZE_HUGE)
+ if(RESIZE_HUGE to RESIZE_MACRO)
+ M.resize(RESIZE_BIG)
+ if(RESIZE_BIG to RESIZE_HUGE)
+ M.resize(RESIZE_NORMAL)
+ if(RESIZE_NORMAL to RESIZE_BIG)
+ M.resize(RESIZE_SMALL)
+ if(RESIZE_SMALL to RESIZE_NORMAL)
+ M.resize(RESIZE_TINY)
+ if(RESIZE_TINY to RESIZE_SMALL)
+ M.resize(RESIZE_MICRO)
+ if((0 - INFINITY) to RESIZE_NORMAL)
+ M.resize(RESIZE_MICRO)
+ M.update_transform()
+ return 1
+
+/obj/item/projectile/sizelaser/growthray/on_hit(var/atom/target, var/blocked = 0 )
+ if(istype(target, /mob/living/carbon/human))
+ var/mob/living/M = target
+ switch(M.size_multiplier)
+ if(RESIZE_HUGE to RESIZE_MACRO)
+ M.resize(RESIZE_MACRO)
+ if(RESIZE_BIG to RESIZE_HUGE)
+ M.resize(RESIZE_HUGE)
+ if(RESIZE_NORMAL to RESIZE_BIG)
+ M.resize(RESIZE_BIG)
+ if(RESIZE_SMALL to RESIZE_NORMAL)
+ M.resize(RESIZE_NORMAL)
+ if(RESIZE_TINY to RESIZE_SMALL)
+ M.resize(RESIZE_SMALL)
+ if(RESIZE_MICRO to RESIZE_TINY)
+ M.resize(RESIZE_TINY)
+ if((0 - INFINITY) to RESIZE_MICRO)
+ M.resize(RESIZE_MICRO)
+ M.update_transform()
+ return 1
+
+/obj/item/ammo_casing/energy/laser/growthray
+ projectile_type = /obj/item/projectile/sizelaser/growthray
+ select_name = "Growth"
+
+/obj/item/ammo_casing/energy/laser/shrinkray
+ projectile_type = /obj/item/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!"
+ item_state = null
+ ammo_type = list(/obj/item/ammo_casing/energy/laser/shrinkray, /obj/item/ammo_casing/energy/laser/growthray)
+ selfcharge = EGUN_SELFCHARGE
+ charge_delay = 5
+ ammo_x_offset = 2
+ clumsy_check = 1
+
+ attackby(obj/item/W, mob/user)
+ if(W==src)
+ if(icon_state=="bluetag")
+ icon_state="redtag"
+ ammo_type = list(/obj/item/ammo_casing/energy/laser/growthray)
+ else
+ icon_state="bluetag"
+ ammo_type = list(/obj/item/ammo_casing/energy/laser/shrinkray)
+ return ..()
diff --git a/icons/mob/animals_held.dmi b/icons/mob/animals_held.dmi
new file mode 100644
index 00000000..82a065d9
Binary files /dev/null and b/icons/mob/animals_held.dmi differ
diff --git a/icons/mob/animals_held_lh.dmi b/icons/mob/animals_held_lh.dmi
new file mode 100644
index 00000000..6c407c85
Binary files /dev/null and b/icons/mob/animals_held_lh.dmi differ
diff --git a/icons/mob/animals_held_rh.dmi b/icons/mob/animals_held_rh.dmi
new file mode 100644
index 00000000..322dad06
Binary files /dev/null and b/icons/mob/animals_held_rh.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 1344e502..ff3cd599 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -2882,6 +2882,9 @@
#include "hyperstation\code\mobs\werewolf.dm"
#include "hyperstation\code\modules\antagonists\werewolf\werewolf.dm"
#include "hyperstation\code\modules\crafting\recipes.dm"
+#include "hyperstation\code\modules\resize\holder_micro.dm"
+#include "hyperstation\code\modules\resize\resizing.dm"
+#include "hyperstation\code\modules\resize\sizegun.dm"
#include "hyperstation\code\obj\decal.dm"
#include "hyperstation\code\obj\fluff.dm"
#include "hyperstation\code\obj\kinkyclothes.dm"