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"