diff --git a/code/__DEFINES/traits/monkestation/declarations.dm b/code/__DEFINES/traits/monkestation/declarations.dm index e3e0abafd7a2..36cf8daf818a 100644 --- a/code/__DEFINES/traits/monkestation/declarations.dm +++ b/code/__DEFINES/traits/monkestation/declarations.dm @@ -79,6 +79,7 @@ // Traits given by quirks #define TRAIT_ANIME "anime" #define TRAIT_CAT "cat" +#define TRAIT_FEEBLE "feeble" #define TRAIT_GOURMAND "gourmand" #define TRAIT_HIDDEN_CLOWN "clown_disbelief" #define TRAIT_HIDDEN_IMAGE "generic-hidden-image" diff --git a/code/__DEFINES/~monkestation/blood_datums.dm b/code/__DEFINES/~monkestation/blood_datums.dm index e1f906a8b103..578257a11cd8 100644 --- a/code/__DEFINES/~monkestation/blood_datums.dm +++ b/code/__DEFINES/~monkestation/blood_datums.dm @@ -19,3 +19,6 @@ /// Updating a mob's movespeed when lacking limbs. (list/modifiers) #define COMSIG_LIVING_LIMBLESS_MOVESPEED_UPDATE "living_get_movespeed_modifiers" + +/// Updating a mob's movespeed when they have the feeble trait. (list/modifiers) +#define COMSIG_LIVING_FEEBLE_MOVESPEED_UPDATE "living_get_movespeed_modifiers_feeble" diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index 5bcbe9c52839..1a42f5915f77 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -228,6 +228,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_FAST_CLIMBER" = TRAIT_FAST_CLIMBER, "TRAIT_FAT" = TRAIT_FAT, "TRAIT_FEARLESS" = TRAIT_FEARLESS, + "TRAIT_FEEBLE" = TRAIT_FEEBLE, "TRAIT_FENCE_CLIMBER" = TRAIT_FENCE_CLIMBER, "TRAIT_FINGERPRINT_PASSTHROUGH" = TRAIT_FINGERPRINT_PASSTHROUGH, "TRAIT_FIXED_MUTANT_COLORS" = TRAIT_FIXED_MUTANT_COLORS, diff --git a/code/datums/components/riding/riding_vehicle.dm b/code/datums/components/riding/riding_vehicle.dm index 1d3979817a38..5954b5c7ca7a 100644 --- a/code/datums/components/riding/riding_vehicle.dm +++ b/code/datums/components/riding/riding_vehicle.dm @@ -214,7 +214,7 @@ COOLDOWN_START(src, message_cooldown, 0.75 SECONDS) return COMPONENT_DRIVER_BLOCK_MOVE return ..() - + /datum/component/riding/vehicle/speedbike vehicle_move_delay = 0 override_allow_spacemove = TRUE @@ -259,6 +259,10 @@ // special messaging for those without arms /datum/component/riding/vehicle/wheelchair/hand/driver_move(obj/vehicle/vehicle_parent, mob/living/user, direction) var/delay_multiplier = 4 // magic number from wheelchair code //MONKESTATION EDIT + //MONKESTATION EDIT START + if(HAS_TRAIT(user, TRAIT_FEEBLE)) + delay_multiplier *= 2 + //MONKESTATION EDIT END vehicle_move_delay = round(CONFIG_GET(number/movedelay/run_delay) * delay_multiplier) / clamp(user.usable_hands, 1, 2) return ..() diff --git a/code/datums/elements/climbable.dm b/code/datums/elements/climbable.dm index 89843e08a22c..ac9376d66080 100644 --- a/code/datums/elements/climbable.dm +++ b/code/datums/elements/climbable.dm @@ -67,10 +67,12 @@ adjusted_climb_time *= 0.25 //aliens are terrifyingly fast if(HAS_TRAIT(user, TRAIT_FREERUNNING)) //do you have any idea how fast I am??? adjusted_climb_time *= 0.8 - //monkestation edit - CYBERNETICS + //MONKESTATION EDIT START + if(HAS_TRAIT(user, TRAIT_FEEBLE)) //do you have any idea how slow I am??? + adjusted_climb_time *= 1.25 if(HAS_TRAIT(user,TRAIT_FAST_CLIMBER)) //How it feels to chew 5 gum adjusted_climb_time *= 0.3 - //monkestation edit - CYBERNETICS + //MONKESTATION EDIT END LAZYADDASSOCLIST(current_climbers, climbed_thing, user) if(do_after(user, adjusted_climb_time, climbed_thing, interaction_key = DOAFTER_SOURCE_CLIMBING)) // monkestation edit: add an interaction key if(QDELETED(climbed_thing)) //Checking if structure has been destroyed diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index ce041d62f677..ebde1138a80d 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1226,6 +1226,10 @@ if(istype(I, /obj/item/fireaxe) && !HAS_TRAIT(I, TRAIT_WIELDED)) //being fireaxe'd to_chat(user, span_warning("You need to be wielding [I] to do that!")) return + //MONKESTATION EDIT START + if(apply_feeble_delay(user, density ? "open" : "close")) + return FALSE + //MONKESTATION EDIT END INVOKE_ASYNC(src, density ? PROC_REF(open) : PROC_REF(close), BYPASS_DOOR_CHECKS) /obj/machinery/door/airlock/open(forced = DEFAULT_DOOR_CHECKS) diff --git a/code/game/objects/items/extinguisher.dm b/code/game/objects/items/extinguisher.dm index 7e49bfac09ff..85f2d10453b0 100644 --- a/code/game/objects/items/extinguisher.dm +++ b/code/game/objects/items/extinguisher.dm @@ -220,6 +220,11 @@ var/obj/B = user.buckled var/movementdirection = turn(direction,180) addtimer(CALLBACK(src, TYPE_PROC_REF(/obj/item/extinguisher, move_chair), B, movementdirection), 1) + //MONKESTATION EDIT START + else if(HAS_TRAIT(user, TRAIT_FEEBLE) && w_class > WEIGHT_CLASS_SMALL && prob(15) && isliving(user)) + if(!feeble_quirk_recoil(user, direction, FALSE)) + user.newtonian_move(turn(direction, 180)) + //MONKESTATION EDIT END else user.newtonian_move(turn(direction, 180)) diff --git a/code/game/objects/items/hand_items.dm b/code/game/objects/items/hand_items.dm index 225e6c5b8739..8f24ae13d876 100644 --- a/code/game/objects/items/hand_items.dm +++ b/code/game/objects/items/hand_items.dm @@ -225,6 +225,12 @@ user.do_attack_animation(slapped) var/slap_volume = 50 + //MONKESTATION EDIT START + var/feeble = HAS_TRAIT(slapped, TRAIT_FEEBLE) + var/no_harm = feeble && HAS_TRAIT(user, TRAIT_PACIFISM) && slapped != user + if(no_harm) + slap_volume *= 0.5 + //MONKESTATION EDIT END var/datum/status_effect/offering/kiss_check = slapped.has_status_effect(/datum/status_effect/offering) if(kiss_check && istype(kiss_check.offered_item, /obj/item/hand_item/kisser) && (user in kiss_check.possible_takers)) user.visible_message( @@ -268,11 +274,29 @@ ) else user.visible_message( - span_danger("[user] slaps [slapped]!"), - span_notice("You slap [slapped]!"), - span_hear("You hear a slap."), + //MONKESTATION EDIT START + // span_danger("[user] slaps [slapped]!"), - MONKESTATION EDIT ORIGINAL + // span_notice("You slap [slapped]!"), - MONKESTATION EDIT ORIGINAL + // span_hear("You hear a slap."), - MONKESTATION EDIT ORIGINAL + span_danger("[user] [no_harm?"gently ":""]slaps [slapped]!"), + span_notice("You [no_harm?"gently ":""]slap [slapped]!"), + span_hear("You hear a [no_harm?"light ":""]slap."), + //MONKESTATION EDIT END ) playsound(slapped, 'sound/weapons/slap.ogg', slap_volume, TRUE, -1) + //MONKESTATION EDIT START + if (feeble && !no_harm) + var/damage = 5 + var/attack_direction = get_dir(user, slapped) + var/obj/item/bodypart/affecting = slapped.get_bodypart(slapped.get_random_valid_zone(user.zone_selected)) + var/armor_block = slapped.run_armor_check(affecting, MELEE) + slapped.apply_damage(damage, BRUTE, affecting, armor_block, attack_direction = attack_direction) + + slapped.visible_message( + span_danger("[user] hurt [slapped]!"), + span_userdanger("[user]'s slap really hurt!"), + ) + //MONKESTATION EDIT END return /obj/item/hand_item/slapper/pre_attack_secondary(atom/target, mob/living/user, params) diff --git a/code/game/objects/items/robot/items/generic.dm b/code/game/objects/items/robot/items/generic.dm index aa09efcd517c..d3872ed7e02f 100644 --- a/code/game/objects/items/robot/items/generic.dm +++ b/code/game/objects/items/robot/items/generic.dm @@ -109,6 +109,10 @@ else user.visible_message(span_notice("[user] hugs [attacked_mob] to make [attacked_mob.p_them()] feel better!"), \ span_notice("You hug [attacked_mob] to make [attacked_mob.p_them()] feel better!")) + //MONKESTATION EDIT START + if(HAS_TRAIT(attacked_mob, TRAIT_FEEBLE)) + feeble_quirk_wound_chest(attacked_mob, hugger=user) + //MONKESTATION EDIT END if(attacked_mob.resting) attacked_mob.set_resting(FALSE, TRUE) else diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm index 076c79ccafb6..992e4373365e 100644 --- a/code/game/objects/structures/grille.dm +++ b/code/game/objects/structures/grille.dm @@ -190,6 +190,10 @@ if(shock(user, 100)) return tool.play_tool_sound(src, 100) + //MONKESTATION EDIT START + if(feeble_quirk_slow_interact(user, "cut", src)) + return + //MONKESTATION EDIT END deconstruct() return TOOL_ACT_TOOLTYPE_SUCCESS @@ -201,6 +205,10 @@ return FALSE if(!tool.use_tool(src, user, 0, volume=100)) return FALSE + //MONKESTATION EDIT START + if(feeble_quirk_slow_interact(user, "[anchored ? "unfasten" : "fasten"]", src)) + return + //MONKESTATION EDIT END set_anchored(!anchored) user.visible_message(span_notice("[user] [anchored ? "fastens" : "unfastens"] [src]."), \ span_notice("You [anchored ? "fasten [src] to" : "unfasten [src] from"] the floor.")) diff --git a/code/game/turfs/open/floor.dm b/code/game/turfs/open/floor.dm index 142a7aad9a5c..c8be9cd42153 100644 --- a/code/game/turfs/open/floor.dm +++ b/code/game/turfs/open/floor.dm @@ -194,6 +194,10 @@ /turf/open/floor/proc/pry_tile(obj/item/I, mob/user, silent = FALSE) I.play_tool_sound(src, 80) + //MONKESTATION EDIT START + if(feeble_quirk_slow_interact(user, "remove", src)) + return + //MONKESTATION EDIT END return remove_tile(user, silent) /turf/open/floor/proc/remove_tile(mob/user, silent = FALSE, make_tile = TRUE, force_plating) diff --git a/code/modules/food_and_drinks/machinery/microwave.dm b/code/modules/food_and_drinks/machinery/microwave.dm index 521af2e3618b..8896576c2e66 100644 --- a/code/modules/food_and_drinks/machinery/microwave.dm +++ b/code/modules/food_and_drinks/machinery/microwave.dm @@ -144,7 +144,20 @@ var/ingredient_count = 0 for (var/atom/movable/ingredient as anything in ingredients) + //MONKESTATION EDIT START + // quick hack to make any living mobs in the microwave be drawn lying down + // hopefully this wont't break anything + var/mob/living/L = ingredient + var/lying_angle + if(istype(L)) + lying_angle = L.get_lying_angle() + L.set_lying_angle(90) + //MONKESTATION EDIT END var/image/ingredient_overlay = image(ingredient, src) + //MONKESTATION EDIT START + if(istype(L)) + L.set_lying_angle(lying_angle) + //MONKESTATION EDIT END var/icon/ingredient_icon = icon(ingredient.icon, ingredient.icon_state) @@ -324,6 +337,11 @@ update_appearance() return + //MONKESTATION EDIT START + if (istype(O, /obj/item/riding_offhand)) + var/obj/item/riding_offhand/riding = O + return stuff_mob_in(riding.rider, user) + //MONKESTATION EDIT END return ..() /obj/machinery/microwave/attack_hand_secondary(mob/user, list/modifiers) diff --git a/code/modules/mob/emote.dm b/code/modules/mob/emote.dm index 80e97cb3c729..3cb764b9af12 100644 --- a/code/modules/mob/emote.dm +++ b/code/modules/mob/emote.dm @@ -20,6 +20,13 @@ act = copytext(act, 1, custom_param) act = lowertext(act) + + //MONKESTATION EDIT START + // not a fan of this but I don't think there's a less hacky way to do it without changing how emotes work + if (HAS_TRAIT(src, TRAIT_FEEBLE) && !intentional && (act in list("scream", "screech", "screams", "screeches"))) + act = pick("whimper", "cry") + //MONKESTATION EDIT END + var/list/key_emotes = GLOB.emote_list[act] if(!length(key_emotes)) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 16141c8a59a6..e665c4bf3ee8 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -146,6 +146,12 @@ var/turf/end_T = get_turf(target) if(start_T && end_T) log_combat(src, thrown_thing, "thrown", addition="grab from tile in [AREACOORD(start_T)] towards tile at [AREACOORD(end_T)]") + //MONKESTATION EDIT START + var/feeble = HAS_TRAIT(src, TRAIT_FEEBLE) + var/leg_aid = HAS_TRAIT(src, TRAIT_NO_LEG_AID) + if (feeble && !leg_aid && prob(buckled ? 45 : 15)) + return fumble_throw_item(target, thrown_thing) + //MONKESTATION EDIT START var/power_throw = 0 if(HAS_TRAIT(src, TRAIT_HULK)) power_throw++ @@ -155,6 +161,10 @@ power_throw++ if(neckgrab_throw) power_throw++ + //MONKESTATION EDIT START + if (feeble) + power_throw = 0 + //MONKESTATION EDIT END if(isitem(thrown_thing)) var/obj/item/thrown_item = thrown_thing if(thrown_item.throw_verb) @@ -164,7 +174,28 @@ log_message("has thrown [thrown_thing] [power_throw > 0 ? "really hard" : ""]", LOG_ATTACK) var/extra_throw_range = HAS_TRAIT(src, TRAIT_THROWINGARM) ? 2 : 0 newtonian_move(get_dir(target, src)) - thrown_thing.safe_throw_at(target, thrown_thing.throw_range + extra_throw_range, max(1,thrown_thing.throw_speed + power_throw), src, null, null, null, move_force) + //MONKESTATION EDIT START + var/total_throw_range = thrown_thing.throw_range + extra_throw_range + if (feeble) + total_throw_range = ceil(total_throw_range / (buckled ? 3 : 2)) + // thrown_thing.safe_throw_at(target, thrown_thing.throw_range + extra_throw_range, max(1,thrown_thing.throw_speed + power_throw), src, null, null, null, move_force) - MONKESTATION EDIT ORIGINAL + thrown_thing.safe_throw_at(target, total_throw_range, max(1,thrown_thing.throw_speed + power_throw), src, null, null, null, move_force) + if (!feeble || body_position == LYING_DOWN || buckled) + return + var/bulky = FALSE + var/obj/item/I = thrown_thing + if (istype(I)) + if (I.w_class > WEIGHT_CLASS_NORMAL || (thrown_thing.throwforce && !leg_aid)) + bulky = I.w_class > WEIGHT_CLASS_NORMAL + else + return + if (!bulky && prob(50)) + return + visible_message(span_danger("[src] looses [src.p_their()] balance."), \ + span_danger("You loose your balance.")) + Knockdown(2 SECONDS) + + //MONKESTATION EDIT END /mob/living/carbon/proc/canBeHandcuffed() return FALSE diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index ab3f27f479b1..8be5d9a8d0b6 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -336,7 +336,10 @@ //Don't hit people through windows, ok? if(!directional_blocked && SEND_SIGNAL(target_shove_turf, COMSIG_CARBON_DISARM_COLLIDE, src, target, shove_blocked) & COMSIG_CARBON_SHOVE_HANDLED) return - if(directional_blocked || shove_blocked) + //MONKESTATION EDIT START + // if(directional_blocked || shove_blocked) - MONKESTATION EDIT ORIGINAL + if(directional_blocked || shove_blocked || HAS_TRAIT(target, TRAIT_FEEBLE)) + //MONKESTATION EDIT END target.Knockdown(SHOVE_KNOCKDOWN_SOLID) target.visible_message(span_danger("[name] shoves [target.name], knocking [target.p_them()] down!"), span_userdanger("You're knocked down from a shove by [name]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, src) @@ -500,16 +503,30 @@ helper.add_mood_event("rippedtail", /datum/mood_event/rippedtail) else - if (helper.grab_state >= GRAB_AGGRESSIVE) + //MONKESTATION EDIT START + var/feeble = HAS_TRAIT(src, TRAIT_FEEBLE) + var/gently = feeble && HAS_TRAIT(helper, TRAIT_PACIFISM) ? "gently " : null + // if (helper.grab_state >= GRAB_AGGRESSIVE) - MONKESTATION EDIT ORIGINAL + if (helper.grab_state >= GRAB_AGGRESSIVE && !gently) + //MONKESTATION EDIT END helper.visible_message(span_notice("[helper] embraces [src] in a tight bear hug!"), \ null, span_hear("You hear the rustling of clothes."), DEFAULT_MESSAGE_RANGE, list(helper, src)) to_chat(helper, span_notice("You wrap [src] into a tight bear hug!")) to_chat(src, span_notice("[helper] squeezes you super tightly in a firm bear hug!")) else - helper.visible_message(span_notice("[helper] hugs [src] to make [p_them()] feel better!"), \ + //MONKESTATION EDIT START + // helper.visible_message(span_notice("[helper] [gently]hugs [src] to make [p_them()] feel better!"), \ - MONKESTATION EDIT ORIGINAL + // null, span_hear("You hear the rustling of clothes."), DEFAULT_MESSAGE_RANGE, list(helper, src)) - MONKESTATION EDIT ORIGINAL + // to_chat(helper, span_notice("You [gently]hug [src] to make [p_them()] feel better!")) - MONKESTATION EDIT ORIGINAL + // to_chat(src, span_notice("[helper] [gently]hugs you to make you feel better!")) - MONKESTATION EDIT ORIGINAL + helper.visible_message(span_notice("[helper] [gently]hugs [src] to make [p_them()] feel better!"), \ null, span_hear("You hear the rustling of clothes."), DEFAULT_MESSAGE_RANGE, list(helper, src)) - to_chat(helper, span_notice("You hug [src] to make [p_them()] feel better!")) - to_chat(src, span_notice("[helper] hugs you to make you feel better!")) + to_chat(helper, span_notice("You [gently]hug [src] to make [p_them()] feel better!")) + to_chat(src, span_notice("[helper] [gently]hugs you to make you feel better!")) + + if (feeble && !gently) + feeble_quirk_wound_chest(src, hugger=helper, force=helper.grab_state >= GRAB_AGGRESSIVE) + //MONKESTATION EDIT END // Warm them up with hugs share_bodytemperature(helper) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 6d4d19f8acbb..9adfdde9ee1d 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -1243,7 +1243,14 @@ GLOBAL_LIST_EMPTY(features_by_species) var/armor_block = target.run_armor_check(affecting, MELEE) - playsound(target.loc, attacking_bodypart.unarmed_attack_sound, 25, TRUE, -1) + //MONKESTATION EDIT START + var/feeble = HAS_TRAIT(user, TRAIT_FEEBLE) + if (feeble) + damage *= 0.5 + atk_verb = "weakly [atk_verb]" + // playsound(target.loc, attacking_bodypart.unarmed_attack_sound, 25, TRUE, -1) - MONKESTATION EDIT ORIGINAL + playsound(target.loc, attacking_bodypart.unarmed_attack_sound, feeble ? 10 : 25, TRUE, -1) + //MONKESTATION EDIT END target.visible_message(span_danger("[user] [atk_verb]ed [target]!"), \ span_userdanger("You're [atk_verb]ed by [user]!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, user) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index ceda4365d105..f04740aaddd7 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1086,6 +1086,12 @@ if(buckled || mob_negates_gravity()) return + //MONKESTATION EDIT START + if (pressure_difference > pressure_resistance && body_position != LYING_DOWN && HAS_TRAIT(src, TRAIT_FEEBLE)) + Paralyze(1 SECONDS) + Knockdown(4 SECONDS) + emote("scream", intentional=FALSE) + //MONKESTATION EDIT END if(client && client.move_delay >= world.time + world.tick_lag*2) pressure_resistance_prob_delta -= 30 diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 2594aaee786e..cd6a2fdbc9b5 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -206,6 +206,11 @@ visible_message(span_danger("[src] is hit by [thrown_item]!"), \ span_userdanger("You're hit by [thrown_item]!")) if(!thrown_item.throwforce) + //MONKESTATION EDIT START + if (HAS_TRAIT(src, TRAIT_FEEBLE) && body_position != LYING_DOWN && thrown_item.w_class > WEIGHT_CLASS_NORMAL && !buckled) + Knockdown(4 SECONDS) + emote("scream", intentional=FALSE) + //MONKESTATION EDIT END return var/armor = run_armor_check(zone, MELEE, "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].", thrown_item.armour_penetration, "", FALSE, thrown_item.weak_against_armour) apply_damage(thrown_item.throwforce, thrown_item.damtype, zone, armor, sharpness = thrown_item.get_sharpness(), wound_bonus = (nosell_hit * CANT_WOUND)) @@ -213,6 +218,11 @@ return if(body_position == LYING_DOWN) // physics says it's significantly harder to push someone by constantly chucking random furniture at them if they are down on the floor. hitpush = FALSE + //MONKESTATION EDIT START + else if (HAS_TRAIT(src, TRAIT_FEEBLE) && thrown_item.w_class > WEIGHT_CLASS_SMALL && !buckled) + Knockdown(4 SECONDS) + emote("scream", intentional=FALSE) + //MONKESTATION EDIT END return ..() playsound(loc, 'sound/weapons/genhit.ogg', 50, TRUE, -1) //Item sounds are handled in the item itself diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm index 0da524effa61..506b7dca423f 100644 --- a/code/modules/mob/living/living_movement.dm +++ b/code/modules/mob/living/living_movement.dm @@ -97,6 +97,11 @@ SEND_SIGNAL(src, COMSIG_LIVING_UPDATING_PULL_MOVESPEED) if(pulling) + //MONKESTATION EDIT START + if (HAS_TRAIT(src, TRAIT_FEEBLE)) + update_pull_movespeed_feeble() + return + //MONKESTATION EDIT END if(isliving(pulling)) var/mob/living/L = pulling if(!slowed_by_drag || L.body_position == STANDING_UP || L.buckled || grab_state >= GRAB_AGGRESSIVE) diff --git a/monkestation/code/datums/components/riding/riding_mob.dm b/monkestation/code/datums/components/riding/riding_mob.dm new file mode 100644 index 000000000000..80596de34e8e --- /dev/null +++ b/monkestation/code/datums/components/riding/riding_mob.dm @@ -0,0 +1,12 @@ +/datum/component/riding/creature/human/Initialize(mob/living/riding_mob, force = FALSE, ride_check_flags = NONE, potion_boost = FALSE) + . = ..() + var/mob/living/carbon/human/human_parent = parent + if (HAS_TRAIT(human_parent, TRAIT_FEEBLE)) + human_parent.Paralyze(1 SECONDS) + human_parent.Knockdown(4 SECONDS) + human_parent.emote("scream", intentional=FALSE) + human_parent.adjustBruteLoss(15) + human_parent.visible_message(span_danger("The weight of [riding_mob] is too much for [human_parent]!"), \ + span_userdanger("The weight of [riding_mob] is too much. You are crushed beneath [riding_mob.p_them()]!")) + playsound(human_parent.loc, 'sound/weapons/punch1.ogg', 35, TRUE, -1) + Unbuckle(riding_mob) diff --git a/monkestation/code/datums/quirks/negative_quirks.dm b/monkestation/code/datums/quirks/negative_quirks.dm index aa4eeb29a9a7..765d352622c7 100644 --- a/monkestation/code/datums/quirks/negative_quirks.dm +++ b/monkestation/code/datums/quirks/negative_quirks.dm @@ -240,3 +240,91 @@ */ /datum/quirk/tunnel_vision/remove() quirk_holder.remove_fov_trait("tunnel vision quirk") + +/datum/quirk/item_quirk/feeble + name = "Feeble" + desc = "All it takes is a strong gust of wind to knock you over, doing anything physical takes much longer and good luck using anything with recoil." + mob_trait = TRAIT_FEEBLE + value = -14 + icon = FA_ICON_PERSON_CANE + gain_text = span_danger("You feel really weak.") + lose_text = span_notice("You feel much less weak.") + medical_record_text = "Patient is suffering from poor dexterity and general physical strength." + mail_goodies = list(/obj/item/cane, /obj/item/cane/white, /obj/item/cane/crutch, /obj/item/cane/crutch/wood) + +/datum/quirk/item_quirk/feeble/add_unique(client/client_source) + give_item_to_holder(/obj/item/cane, list(LOCATION_HANDS = ITEM_SLOT_HANDS, LOCATION_BACKPACK = ITEM_SLOT_BACKPACK)) + +/datum/movespeed_modifier/feeble_quirk_ground + variable = TRUE + movetypes = GROUND + +/datum/movespeed_modifier/feeble_quirk_not_ground + multiplicative_slowdown = 1 + blacklisted_movetypes = GROUND + +/datum/actionspeed_modifier/feeble_quirk + multiplicative_slowdown = 2.2 + +/datum/quirk/item_quirk/feeble/add() + quirk_holder.add_movespeed_modifier(/datum/movespeed_modifier/feeble_quirk_not_ground) + quirk_holder.add_actionspeed_modifier(/datum/actionspeed_modifier/feeble_quirk) + feeble_quirk_update_slowdown(quirk_holder) + +/datum/quirk/item_quirk/feeble/remove() + quirk_holder.remove_movespeed_modifier(/datum/movespeed_modifier/feeble_quirk_ground) + quirk_holder.remove_movespeed_modifier(/datum/movespeed_modifier/feeble_quirk_not_ground) + quirk_holder.remove_actionspeed_modifier(/datum/actionspeed_modifier/feeble_quirk) + +/proc/feeble_quirk_update_slowdown(mob/living/target) + var/slowdown = 2.2 // Same slowdown as the walk intent + var/list/slowdown_mods = list() + SEND_SIGNAL(target, COMSIG_LIVING_FEEBLE_MOVESPEED_UPDATE, slowdown_mods) + for(var/num in slowdown_mods) + slowdown *= num + target.add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/feeble_quirk_ground, multiplicative_slowdown = slowdown) + +/proc/feeble_quirk_wound_chest(mob/living/carbon/target, hugger=null, force=FALSE) + if (!istype(target)) + return + var/obj/item/bodypart/chest = target.get_bodypart(BODY_ZONE_CHEST) + if (!force && !prob((locate(/datum/wound/blunt) in chest.wounds) ? 30 : 15)) + return + if (hugger) + to_chat(hugger, span_danger("You feel something break inside [target]!")) + if (locate(/datum/wound/blunt/bone/critical) in chest.wounds) + playsound(target, 'sound/effects/wounds/crack2.ogg', 70 + (20 * 3), TRUE) + else if (locate(/datum/wound/blunt/bone/severe) in chest.wounds) + chest.force_wound_upwards(/datum/wound/blunt/bone/critical) + else if (locate(/datum/wound/blunt/bone/rib_break) in chest.wounds) + chest.force_wound_upwards(/datum/wound/blunt/bone/severe) + else + chest.force_wound_upwards(/datum/wound/blunt/bone/rib_break) + chest.receive_damage(brute = 15) + +/proc/feeble_quirk_slow_interact(mob/living/carbon/user, action, atom) + if(!HAS_TRAIT(user, TRAIT_FEEBLE)) + return FALSE + user.visible_message(span_notice("[user] struggles to [action] [atom]."), \ + span_notice("You struggle to [action] [atom].")) + return !do_after(user, 2 SECONDS, target = atom) + +/proc/feeble_quirk_recoil(mob/living/user, direction, is_gunshot) + if (user.body_position == LYING_DOWN || user.buckled) + if (is_gunshot) + var/item = user.get_active_held_item() + user.dropItemToGround(item) + user.visible_message(span_danger("[item] flies out of [user]'s hand!"), \ + span_danger("The recoil makes [item] fly out of your hand!")) + return FALSE + user.Knockdown(4 SECONDS) + user.visible_message(span_danger("[user] looses [user.p_their()] balance!"), \ + span_danger("You loose your balance!")) + var/shove_dir = turn(direction, 180) + if (!is_gunshot && prob(0.01)) + user.safe_throw_at(get_edge_target_turf(user, shove_dir), 8, 3, user, spin=FALSE) + else + var/turf/target_shove_turf = get_step(user.loc, shove_dir) + var/turf/target_old_turf = user.loc + user.Move(target_shove_turf, shove_dir) + SEND_SIGNAL(target_shove_turf, COMSIG_CARBON_DISARM_COLLIDE, user, user, get_turf(user) == target_old_turf) diff --git a/monkestation/code/game/machinery/doors/airlock.dm b/monkestation/code/game/machinery/doors/airlock.dm new file mode 100644 index 000000000000..bbe8689824c6 --- /dev/null +++ b/monkestation/code/game/machinery/doors/airlock.dm @@ -0,0 +1,13 @@ +/obj/machinery/door/airlock/proc/apply_feeble_delay(mob/user, action) + if(!HAS_TRAIT(user, TRAIT_FEEBLE)) + return FALSE + if(!feeble_callback()) + return TRUE + user.visible_message(span_notice("[user] struggles to [action] the airlock."), \ + span_notice("You struggle to [action] the airlock.")) + return !do_after(user, 4 SECONDS, target = src, extra_checks = CALLBACK(src, TYPE_PROC_REF(/obj/machinery/door/airlock, feeble_callback))) + +/obj/machinery/door/airlock/proc/feeble_callback() + if( operating || welded || locked || seal ) + return FALSE + return TRUE diff --git a/monkestation/code/game/machinery/doors/firedoor.dm b/monkestation/code/game/machinery/doors/firedoor.dm new file mode 100644 index 000000000000..fa88a6b89ff4 --- /dev/null +++ b/monkestation/code/game/machinery/doors/firedoor.dm @@ -0,0 +1,23 @@ +/obj/machinery/door/firedoor/try_to_crowbar(obj/item/acting_object, mob/user) + if(apply_feeble_delay(user, density ? "open" : "close")) + return + . = ..() + +/obj/machinery/door/firedoor/try_to_crowbar_secondary(obj/item/acting_object, mob/user) + if(apply_feeble_delay(user, density ? "open" : "close")) + return + . = ..() + +/obj/machinery/door/firedoor/proc/apply_feeble_delay(mob/user, action) + if(!HAS_TRAIT(user, TRAIT_FEEBLE)) + return FALSE + if(!feeble_callback()) + return TRUE + user.visible_message(span_notice("[user] struggles to [action] the firelock."), \ + span_notice("You struggle to [action] the firelock.")) + return !do_after(user, 4 SECONDS, target = src, extra_checks = CALLBACK(src, TYPE_PROC_REF(/obj/machinery/door/firedoor, feeble_callback))) + +/obj/machinery/door/firedoor/proc/feeble_callback() + if(welded || operating) + return FALSE + return TRUE diff --git a/monkestation/code/modules/blood_datum/components/limbless_aid.dm b/monkestation/code/modules/blood_datum/components/limbless_aid.dm index 95e10c382c5b..f59c01e69b24 100644 --- a/monkestation/code/modules/blood_datum/components/limbless_aid.dm +++ b/monkestation/code/modules/blood_datum/components/limbless_aid.dm @@ -48,11 +48,14 @@ /datum/component/limbless_aid/proc/add_support(mob/living/user) ADD_TRAIT(user, TRAIT_NO_LEG_AID, "[REF(src)]_aid") RegisterSignal(user, COMSIG_LIVING_LIMBLESS_MOVESPEED_UPDATE, PROC_REF(modify_movespeed), override = TRUE) + RegisterSignal(user, COMSIG_LIVING_FEEBLE_MOVESPEED_UPDATE, PROC_REF(modify_movespeed_feeble), override = TRUE) RegisterSignal(user, COMSIG_CARBON_PAINED_STEP, PROC_REF(pain_step), override = TRUE) RegisterSignal(user, COMSIG_CARBON_LIMPING, PROC_REF(limp_check), override = TRUE) RegisterSignal(user, COMSIG_LIVING_RESIST, PROC_REF(self_brace), override = TRUE) user.update_limbless_locomotion() user.update_limbless_movespeed_mod() + if(HAS_TRAIT(user, TRAIT_FEEBLE)) + feeble_quirk_update_slowdown(user) /datum/component/limbless_aid/proc/on_drop(obj/item/source, mob/living/user) SIGNAL_HANDLER @@ -63,11 +66,14 @@ REMOVE_TRAIT(user, TRAIT_NO_LEG_AID, "[REF(src)]_aid") un_self_brace(user) UnregisterSignal(user, COMSIG_LIVING_LIMBLESS_MOVESPEED_UPDATE) + UnregisterSignal(user, COMSIG_LIVING_FEEBLE_MOVESPEED_UPDATE) UnregisterSignal(user, COMSIG_CARBON_PAINED_STEP) UnregisterSignal(user, COMSIG_CARBON_LIMPING) UnregisterSignal(user, COMSIG_LIVING_RESIST) user.update_limbless_locomotion() user.update_limbless_movespeed_mod() + if(HAS_TRAIT(user, TRAIT_FEEBLE)) + feeble_quirk_update_slowdown(user) /datum/component/limbless_aid/proc/modify_movespeed(mob/living/source, list/modifiers) SIGNAL_HANDLER @@ -76,6 +82,10 @@ if(isnull(leg) || leg.bodypart_disabled) modifiers += movespeed_mod +/datum/component/limbless_aid/proc/modify_movespeed_feeble(mob/living/source, list/modifiers) + SIGNAL_HANDLER + modifiers += movespeed_mod * 0.9 + /datum/component/limbless_aid/proc/pain_step(mob/living/source, obj/item/affected_leg, footstep_count) SIGNAL_HANDLER diff --git a/monkestation/code/modules/food_and_drinks/machinery/microwave.dm b/monkestation/code/modules/food_and_drinks/machinery/microwave.dm index c675a24cb5ae..e6b43708e59f 100644 --- a/monkestation/code/modules/food_and_drinks/machinery/microwave.dm +++ b/monkestation/code/modules/food_and_drinks/machinery/microwave.dm @@ -19,3 +19,56 @@ open() else update_appearance() + +/obj/machinery/microwave/loop(type, time, wait = max(12 - 2 * efficiency, 2), mob/cooker) + for(var/ingredient in ingredients) + if (isliving(ingredient)) + var/mob/living/occupant = ingredient + occupant.adjust_bodytemperature(12, 0, 473) + . = ..() + +// Shamelessly copied from code\modules\recycling\disposal\bin.dm +/obj/machinery/microwave/MouseDrop_T(mob/living/target, mob/living/user) + if(target.buckled || target.has_buckled_mobs()) + return + stuff_mob_in(target, user) + +// Shamelessly copied from code\modules\recycling\disposal\bin.dm +/obj/machinery/microwave/proc/stuff_mob_in(mob/living/target, mob/living/user) + if(!istype(target)) + return + if(user != target && HAS_TRAIT(user, TRAIT_PACIFISM)) + return + if(!HAS_TRAIT(target, TRAIT_FEEBLE)) + return + if(ingredients.len >= max_n_of_items) + balloon_alert(user, "it's full!") + return + if(!isturf(user.loc)) //No magically doing it from inside closets + return + if(user == target) + user.visible_message(span_warning("[user] starts climbing into [src]."), span_notice("You start climbing into [src]...")) + else + target.visible_message(span_danger("[user] starts putting [target] into [src]."), span_userdanger("[user] starts putting you into [src]!")) + if(do_after(user, 2 SECONDS, target)) + if (!loc) + return + target.forceMove(src) + if(user == target) + user.visible_message(span_warning("[user] climbs into [src]."), span_notice("You climb into [src].")) + . = TRUE + else + target.visible_message(span_danger("[user] places [target] in [src]."), span_userdanger("[user] places you in [src].")) + log_combat(user, target, "stuffed", addition="into [src]") + target.LAssailant = WEAKREF(user) + . = TRUE + ingredients += target + update_appearance() + +// Shamelessly copied from code\modules\recycling\disposal\bin.dm +/obj/machinery/microwave/relaymove(mob/living/user, direction) + eject(force=TRUE) + +// Shamelessly copied from code\modules\recycling\disposal\bin.dm +/obj/machinery/microwave/container_resist_act(mob/living/user) + eject(force=TRUE) diff --git a/monkestation/code/modules/mob/living/carbon/carbon.dm b/monkestation/code/modules/mob/living/carbon/carbon.dm index 56e2872596b3..bbdefb2c1bd8 100644 --- a/monkestation/code/modules/mob/living/carbon/carbon.dm +++ b/monkestation/code/modules/mob/living/carbon/carbon.dm @@ -2,3 +2,10 @@ if(HAS_MIND_TRAIT(src, TRAIT_UNCONVERTABLE)) return FALSE return ..() + +/mob/living/carbon/proc/fumble_throw_item(atom/target, atom/movable/thrown_thing) + visible_message(span_danger("[src] fumbles [thrown_thing]."), \ + span_danger("You fumble [thrown_thing].")) + log_message("has failed to throw [thrown_thing]", LOG_ATTACK) + thrown_thing.safe_throw_at(target, min(thrown_thing.throw_range, 1), 1, src, FALSE, null, null, move_force, gentle=TRUE) + return FALSE diff --git a/monkestation/code/modules/mob/living/emote.dm b/monkestation/code/modules/mob/living/emote.dm new file mode 100644 index 000000000000..91f59ec332c5 --- /dev/null +++ b/monkestation/code/modules/mob/living/emote.dm @@ -0,0 +1,4 @@ +/datum/emote/living/laugh/run_emote(mob/user, params, type_override, intentional = FALSE) + . = ..() + if (HAS_TRAIT(user, TRAIT_FEEBLE)) + feeble_quirk_wound_chest(user) diff --git a/monkestation/code/modules/mob/living/living.dm b/monkestation/code/modules/mob/living/living.dm new file mode 100644 index 000000000000..bfc769ee3f95 --- /dev/null +++ b/monkestation/code/modules/mob/living/living.dm @@ -0,0 +1,3 @@ +// This adds extra overhead to getting `lying_angle` directly but doing so upsets SpacemanDMM as it's set to protected +/mob/living/proc/get_lying_angle() + return lying_angle diff --git a/monkestation/code/modules/mob/living/living_movement.dm b/monkestation/code/modules/mob/living/living_movement.dm index a2efb7be0ec5..40ac7316ff42 100644 --- a/monkestation/code/modules/mob/living/living_movement.dm +++ b/monkestation/code/modules/mob/living/living_movement.dm @@ -2,3 +2,29 @@ if(SEND_SIGNAL(src, COMSIG_LIVING_CAN_ALLOW_THROUGH, mover, border_dir) & COMPONENT_LIVING_PASSABLE) return TRUE return ..() + +/mob/living/proc/update_pull_movespeed_feeble() + if(isliving(pulling)) + var/mob/living/L = pulling + if (!slowed_by_drag) + remove_movespeed_modifier(/datum/movespeed_modifier/bulky_drag) + return + if(L.body_position == STANDING_UP) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/bulky_drag, multiplicative_slowdown = PULL_PRONE_SLOWDOWN * 0.75) + return + if (L.buckled || grab_state >= GRAB_AGGRESSIVE) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/bulky_drag, multiplicative_slowdown = PULL_PRONE_SLOWDOWN * 1) + return + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/bulky_drag, multiplicative_slowdown = PULL_PRONE_SLOWDOWN * 3) + return + if(isobj(pulling)) + var/obj/structure/S = pulling + if(!slowed_by_drag || !S.drag_slowdown) + if (S.has_buckled_mobs()) + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/bulky_drag, multiplicative_slowdown = PULL_PRONE_SLOWDOWN * 0.75) + return + remove_movespeed_modifier(/datum/movespeed_modifier/bulky_drag) + return + add_or_update_variable_movespeed_modifier(/datum/movespeed_modifier/bulky_drag, multiplicative_slowdown = S.drag_slowdown * 3) + return + remove_movespeed_modifier(/datum/movespeed_modifier/bulky_drag) diff --git a/monkestation/code/modules/mob/mob_helpers.dm b/monkestation/code/modules/mob/mob_helpers.dm new file mode 100644 index 000000000000..f6d1efd2be3f --- /dev/null +++ b/monkestation/code/modules/mob/mob_helpers.dm @@ -0,0 +1,4 @@ +/mob/common_trait_examine() + . = ..() + if(HAS_TRAIT(src, TRAIT_FEEBLE)) + . += span_warning("[p_they(capitalized=TRUE)] look[p_s()] really weak.") diff --git a/monkestation/code/modules/possession/basic_additions.dm b/monkestation/code/modules/possession/basic_additions.dm index 252afc267e49..f10a7288d2e0 100644 --- a/monkestation/code/modules/possession/basic_additions.dm +++ b/monkestation/code/modules/possession/basic_additions.dm @@ -84,7 +84,10 @@ //Don't hit people through windows, ok? if(!directional_blocked && SEND_SIGNAL(target_shove_turf, COMSIG_CARBON_DISARM_COLLIDE, src, target, shove_blocked) & COMSIG_CARBON_SHOVE_HANDLED) return - if(directional_blocked || shove_blocked) + //MONKESTATION EDIT START + // if(directional_blocked || shove_blocked) - MONKESTATION EDIT ORIGINAL + if(directional_blocked || shove_blocked || HAS_TRAIT(target, TRAIT_FEEBLE)) + //MONKESTATION EDIT END target.Knockdown(SHOVE_KNOCKDOWN_SOLID) target.visible_message(span_danger("[name] shoves [target.name], knocking [target.p_them()] down!"), span_userdanger("You're knocked down from a shove by [name]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, src) diff --git a/monkestation/code/modules/projectiles/gun.dm b/monkestation/code/modules/projectiles/gun.dm new file mode 100644 index 000000000000..af8ab3dcfa26 --- /dev/null +++ b/monkestation/code/modules/projectiles/gun.dm @@ -0,0 +1,4 @@ +/obj/item/gun/shoot_live_shot(mob/living/user, pointblank = 0, atom/pbtarget = null, message = 1) + . = ..() + if(HAS_TRAIT(user, TRAIT_FEEBLE) && recoil && !tk_firing(user)) + feeble_quirk_recoil(user, get_dir(user, pbtarget), TRUE) diff --git a/tgstation.dme b/tgstation.dme index c2346e77e27e..d11278aac9ff 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -5866,6 +5866,7 @@ #include "monkestation\code\datums\components\turf_healing.dm" #include "monkestation\code\datums\components\uplink.dm" #include "monkestation\code\datums\components\wound_converter.dm" +#include "monkestation\code\datums\components\riding\riding_mob.dm" #include "monkestation\code\datums\diseases\advance\symptoms\clockwork.dm" #include "monkestation\code\datums\elements\area_locked.dm" #include "monkestation\code\datums\elements\basic_eating.dm" @@ -5916,6 +5917,8 @@ #include "monkestation\code\game\machinery\suit_storage_unit.dm" #include "monkestation\code\game\machinery\computer\cloning.dm" #include "monkestation\code\game\machinery\computer\orders\order_veggies.dm" +#include "monkestation\code\game\machinery\doors\airlock.dm" +#include "monkestation\code\game\machinery\doors\firedoor.dm" #include "monkestation\code\game\machinery\trains\train_cart.dm" #include "monkestation\code\game\machinery\trains\train_head.dm" #include "monkestation\code\game\machinery\trains\train_network.dm" @@ -7335,6 +7338,7 @@ #include "monkestation\code\modules\mob\login.dm" #include "monkestation\code\modules\mob\mob.dm" #include "monkestation\code\modules\mob\mob_defines.dm" +#include "monkestation\code\modules\mob\mob_helpers.dm" #include "monkestation\code\modules\mob\mob_say.dm" #include "monkestation\code\modules\mob\transform_procs.dm" #include "monkestation\code\modules\mob\dead\new_player\new_player.dm" @@ -7355,7 +7359,9 @@ #include "monkestation\code\modules\mob\dead\new_player\sprite_accessories\sock_color.dm" #include "monkestation\code\modules\mob\dead\new_player\sprite_accessories\tails.dm" #include "monkestation\code\modules\mob\dead\new_player\sprite_accessories\underwear.dm" +#include "monkestation\code\modules\mob\living\emote.dm" #include "monkestation\code\modules\mob\living\init_signals.dm" +#include "monkestation\code\modules\mob\living\living.dm" #include "monkestation\code\modules\mob\living\living_defines.dm" #include "monkestation\code\modules\mob\living\living_movement.dm" #include "monkestation\code\modules\mob\living\status_procs.dm" @@ -7610,6 +7616,7 @@ #include "monkestation\code\modules\power\singularity\particle_accelerator\particle_accelerator.dm" #include "monkestation\code\modules\power\singularity\particle_accelerator\particle_controller.dm" #include "monkestation\code\modules\power\singularity\particle_accelerator\particle_emitter.dm" +#include "monkestation\code\modules\projectiles\gun.dm" #include "monkestation\code\modules\projectiles\ammunition\_ammunition.dm" #include "monkestation\code\modules\projectiles\guns\ballistic\revolver.dm" #include "monkestation\code\modules\projectiles\guns\ballistic\ryanecorp_whispering_jester.dm"