From e7a1ec5ba2cecd52c8262ec5221ac1753a661ebb Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Sat, 28 Oct 2023 00:22:32 +0200 Subject: [PATCH] [MIRROR] Cuts the number of `apply_damage` copypaste procs from 3(.5) to 1, fixing a few bugs along the way [MDB IGNORE] (#24619) * Cuts the number of `apply_damage` copypaste procs from 3(.5) to 1, fixing a few bugs along the way * Update _species.dm * Update damage_procs.dm * Modular adjustments * Update mutant_species.dm * Update mutant_species.dm --------- Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com> --- .../signals/signals_mob/signals_mob_main.dm | 11 +- code/datums/components/explodable.dm | 5 +- code/datums/components/gunpoint.dm | 22 +- code/datums/components/pinata.dm | 2 +- code/datums/components/regenerator.dm | 2 +- code/datums/components/style/style.dm | 2 +- .../quirks/negative_quirks/glass_jaw.dm | 12 +- .../dna_infuser/organ_sets/roach_organs.dm | 72 ++++--- code/game/objects/items/grenades/flashbang.dm | 2 +- .../stacks/golem_food/golem_status_effects.dm | 2 +- .../antagonists/heretic/magic/shadow_cloak.dm | 2 +- .../components/avatar_connection.dm | 4 +- code/modules/bitrunning/server/util.dm | 8 +- .../equipment/monster_organs/brimdust_sac.dm | 2 +- .../living/basic/lavaland/goliath/goliath.dm | 4 +- .../modules/mob/living/carbon/damage_procs.dm | 99 ++++++--- .../mob/living/carbon/human/_species.dm | 118 +++------- .../mob/living/carbon/human/damage_procs.dm | 4 - .../mob/living/carbon/human/physiology.dm | 37 +++- .../carbon/human/species_types/flypeople.dm | 17 +- .../carbon/human/species_types/mothmen.dm | 17 +- .../carbon/human/species_types/vampire.dm | 14 +- code/modules/mob/living/damage_procs.dm | 203 +++++++++++++----- .../mob/living/silicon/damage_procs.dm | 14 -- .../mob/living/simple_animal/bot/medbot.dm | 4 +- .../crossbreeding/_status_effects.dm | 2 +- .../organs/internal/heart/heart_ethereal.dm | 2 +- .../surgery/organs/internal/lungs/_lungs.dm | 20 +- .../lewd_items/code/lewd_arousal/pain.dm | 5 +- .../modules/mutants/code/mutant_species.dm | 17 +- tgstation.dme | 1 - 31 files changed, 427 insertions(+), 299 deletions(-) delete mode 100644 code/modules/mob/living/carbon/human/damage_procs.dm diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm index 04cc044429e..b564a114b02 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -90,11 +90,16 @@ ///from base of mob/set_invis_see(): (new_invis, old_invis) #define COMSIG_MOB_SEE_INVIS_CHANGE "mob_see_invis_change" - -///from base of /mob/living/proc/apply_damage(): (damage, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) +/// from /mob/living/proc/apply_damage(): (list/damage_mods, damage, damagetype, def_zone, sharpness, attack_direction, attacking_item) +/// allows you to add multiplicative damage modifiers to the damage mods argument to adjust incoming damage +/// not sent if the apply damage call was forced +#define COMSIG_MOB_APPLY_DAMAGE_MODIFIERS "mob_apply_damage_modifiers" +/// from base of /mob/living/proc/apply_damage(): (damage, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) #define COMSIG_MOB_APPLY_DAMAGE "mob_apply_damage" -///from /mob/living/proc/apply_damage(), works like above but after the damage is actually inflicted: (damage, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) +/// from /mob/living/proc/apply_damage(): (damage, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) +/// works like above but after the damage is actually inflicted #define COMSIG_MOB_AFTER_APPLY_DAMAGE "mob_after_apply_damage" + ///from base of /mob/living/attack_alien(): (user) #define COMSIG_MOB_ATTACK_ALIEN "mob_attack_alien" ///from base of /mob/throw_item(): (atom/target) diff --git a/code/datums/components/explodable.dm b/code/datums/components/explodable.dm index 7ebb112d305..3093c995ced 100644 --- a/code/datums/components/explodable.dm +++ b/code/datums/components/explodable.dm @@ -91,13 +91,16 @@ detonate() ///Called when you attack a specific body part of the thing this is equipped on. Useful for exploding pants. -/datum/component/explodable/proc/explodable_attack_zone(datum/source, damage, damagetype, def_zone) +/datum/component/explodable/proc/explodable_attack_zone(datum/source, damage, damagetype, def_zone, ...) SIGNAL_HANDLER if(!def_zone) return if(damagetype != BURN) //Don't bother if it's not fire. return + if(isbodypart(def_zone)) + var/obj/item/bodypart/hitting = def_zone + def_zone = hitting.body_zone if(!is_hitting_zone(def_zone)) //You didn't hit us! ha! return detonate() diff --git a/code/datums/components/gunpoint.dm b/code/datums/components/gunpoint.dm index 8898795c6f9..c248b4f18c0 100644 --- a/code/datums/components/gunpoint.dm +++ b/code/datums/components/gunpoint.dm @@ -172,25 +172,27 @@ qdel(src) ///If the shooter is hit by an attack, they have a 50% chance to flinch and fire. If it hit the arm holding the trigger, it's an 80% chance to fire instead -/datum/component/gunpoint/proc/flinch(attacker, damage, damagetype, def_zone) +/datum/component/gunpoint/proc/flinch(mob/living/source, damage_amount, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) SIGNAL_HANDLER - var/mob/living/shooter = parent - if(attacker == shooter) - return // somehow this wasn't checked for months but no one tried punching themselves to initiate the shot, amazing + if(!attack_direction) // No fliching from yourself + return var/flinch_chance = 50 - var/gun_hand = LEFT_HANDS + var/gun_hand = (source.get_held_index_of_item(weapon) % 2) ? BODY_ZONE_L_ARM : BODY_ZONE_R_ARM - if(shooter.held_items[RIGHT_HANDS] == weapon) - gun_hand = RIGHT_HANDS + if(isbodypart(def_zone)) + var/obj/item/bodypart/hitting = def_zone + def_zone = hitting.body_zone - if((def_zone == BODY_ZONE_L_ARM && gun_hand == LEFT_HANDS) || (def_zone == BODY_ZONE_R_ARM && gun_hand == RIGHT_HANDS)) + if(def_zone == gun_hand) flinch_chance = 80 if(prob(flinch_chance)) - shooter.visible_message(span_danger("[shooter] flinches!"), \ - span_danger("You flinch!")) + source.visible_message( + span_danger("[source] flinches!"), + span_danger("You flinch!"), + ) INVOKE_ASYNC(src, PROC_REF(trigger_reaction)) #undef GUNPOINT_DELAY_STAGE_2 diff --git a/code/datums/components/pinata.dm b/code/datums/components/pinata.dm index 8f6866c5d94..1056200e3e2 100644 --- a/code/datums/components/pinata.dm +++ b/code/datums/components/pinata.dm @@ -33,7 +33,7 @@ return return COMPONENT_INCOMPATIBLE -/datum/component/pinata/proc/damage_inflicted(obj/target, damage, damage_type) +/datum/component/pinata/proc/damage_inflicted(obj/target, damage, damage_type, ...) SIGNAL_HANDLER if(damage < minimum_damage || damage_type == STAMINA || damage_type == OXY) return diff --git a/code/datums/components/regenerator.dm b/code/datums/components/regenerator.dm index 42d0a0f636c..b9886764565 100644 --- a/code/datums/components/regenerator.dm +++ b/code/datums/components/regenerator.dm @@ -66,7 +66,7 @@ deltimer(regeneration_start_timer) /// When you take damage, reset the cooldown and start processing -/datum/component/regenerator/proc/on_take_damage(datum/source, damage, damagetype) +/datum/component/regenerator/proc/on_take_damage(datum/source, damage, damagetype, ...) SIGNAL_HANDLER if (damagetype in ignore_damage_types) diff --git a/code/datums/components/style/style.dm b/code/datums/components/style/style.dm index b6b9770ec48..99fe652fad6 100644 --- a/code/datums/components/style/style.dm +++ b/code/datums/components/style/style.dm @@ -456,7 +456,7 @@ // Negative effects -/datum/component/style/proc/on_take_damage() +/datum/component/style/proc/on_take_damage(...) SIGNAL_HANDLER point_multiplier = round(max(point_multiplier - 0.3, 1), 0.1) diff --git a/code/datums/quirks/negative_quirks/glass_jaw.dm b/code/datums/quirks/negative_quirks/glass_jaw.dm index 33ad19add6d..567753f6fee 100644 --- a/code/datums/quirks/negative_quirks/glass_jaw.dm +++ b/code/datums/quirks/negative_quirks/glass_jaw.dm @@ -34,14 +34,16 @@ /datum/quirk/glass_jaw/proc/punch_out(mob/living/carbon/source, damage, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) SIGNAL_HANDLER - if((damagetype != BRUTE) || (def_zone != BODY_ZONE_HEAD)) + + if(isbodypart(def_zone)) + var/obj/item/bodypart/hitting = def_zone + def_zone = hitting.body_zone + if(damagetype != BRUTE || def_zone != BODY_ZONE_HEAD) return - var/actual_damage = damage - (damage * blocked/100) - //only roll for knockouts at 5 damage or more - if(actual_damage < 5) + if(damage < 5) return //blunt items are more likely to knock out, but sharp ones are still capable of doing it - if(prob(CEILING(actual_damage * (sharpness & (SHARP_EDGED|SHARP_POINTY) ? 0.65 : 1), 1))) + if(prob(CEILING(damage * (sharpness & (SHARP_EDGED|SHARP_POINTY) ? 0.65 : 1), 1))) //don't display the message if little mac is already KO'd if(!source.IsUnconscious()) source.visible_message( diff --git a/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm b/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm index 4aa96728358..3c2d461e08c 100644 --- a/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm +++ b/code/game/machinery/dna_infuser/organ_sets/roach_organs.dm @@ -56,11 +56,11 @@ greyscale_config = /datum/greyscale_config/mutant_organ greyscale_colors = ROACH_COLORS - /// Timer ID for resetting the damage resistance applied from attacks from behind - var/defense_timerid /// Bodypart overlay applied to the chest the heart is in var/datum/bodypart_overlay/simple/roach_shell/roach_shell + COOLDOWN_DECLARE(harden_effect_cd) + /obj/item/organ/internal/heart/roach/Initialize(mapload) . = ..() AddElement(/datum/element/noticable_organ, "has hardened, somewhat translucent skin.") @@ -78,7 +78,8 @@ var/mob/living/carbon/human/human_owner = organ_owner - RegisterSignal(human_owner, COMSIG_MOB_APPLY_DAMAGE, PROC_REF(modify_damage)) + RegisterSignal(human_owner, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS, PROC_REF(modify_damage)) + RegisterSignal(human_owner, COMSIG_MOB_AFTER_APPLY_DAMAGE, PROC_REF(do_block_effect)) human_owner.physiology.knockdown_mod *= 3 var/obj/item/bodypart/chest/chest = human_owner.get_bodypart(BODY_ZONE_CHEST) @@ -92,50 +93,55 @@ var/mob/living/carbon/human/human_owner = organ_owner - UnregisterSignal(human_owner, COMSIG_MOB_APPLY_DAMAGE) + UnregisterSignal(human_owner, list(COMSIG_MOB_APPLY_DAMAGE_MODIFIERS, COMSIG_MOB_AFTER_APPLY_DAMAGE)) human_owner.physiology.knockdown_mod /= 3 - if(defense_timerid) - reset_damage(human_owner) - var/obj/item/bodypart/chest/chest = human_owner.get_bodypart(BODY_ZONE_CHEST) chest.remove_bodypart_overlay(roach_shell) human_owner.update_body_parts() /** - * Signal proc for [COMSIG_MOB_APPLY_DAMAGE] + * Signal proc for [COMSIG_MOB_APPLY_DAMAGE_MODIFIERS] * - * Being hit with brute damage in the back will impart a large damage resistance bonus for a very short period. + * Adds a 0.5 modifier to attacks from the back */ -/obj/item/organ/internal/heart/roach/proc/modify_damage(datum/source, damage, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, obj/item/attacking_item) +/obj/item/organ/internal/heart/roach/proc/modify_damage(mob/living/carbon/human/source, list/damage_mods, damage_amount, damagetype, def_zone, sharpness, attack_direction, obj/item/attacking_item) SIGNAL_HANDLER - if(!ishuman(owner) || !attack_direction || damagetype != BRUTE || owner.stat >= UNCONSCIOUS) + if(!is_blocking(source, damage_amount, damagetype, attack_direction)) return - var/mob/living/carbon/human/human_owner = owner + damage_mods += 0.5 + +/** + * Signal proc for [COMSIG_MOB_AFTER_APPLY_DAMAGE] + * + * Does a special effect if we blocked damage with our back + */ +/obj/item/organ/internal/heart/roach/proc/do_block_effect(mob/living/carbon/human/source, damage_dealt, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, obj/item/attacking_item) + SIGNAL_HANDLER + + if(!is_blocking(source, damage_dealt, damagetype, attack_direction)) + return + + if(COOLDOWN_FINISHED(src, harden_effect_cd)) + source.visible_message(span_warning("[source]'s back hardens against the blow!")) + playsound(source, 'sound/effects/constructform.ogg', 25, vary = TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE) + + COOLDOWN_START(src, harden_effect_cd, 5 SECONDS) // Cooldown resets EVERY time we get hit + +/// Checks if the passed mob is in a valid state to be blocking damage with the roach shell +/obj/item/organ/internal/heart/roach/proc/is_blocking(mob/living/carbon/human/blocker, damage_amount, damagetype, attack_direction) + if(damage_amount < 5 || damagetype != BRUTE || !attack_direction) + return + if(!ishuman(blocker) || blocker.stat >= UNCONSCIOUS) + return FALSE // No tactical spinning - if(human_owner.flags_1 & IS_SPINNING_1) - return - - // If we're lying down, or were attacked from the back, we get armor. - var/should_armor_up = (human_owner.body_position == LYING_DOWN) || (human_owner.dir & attack_direction) - if(!should_armor_up) - return - - // Take 50% less damage from attack behind us - if(!defense_timerid) - human_owner.physiology.brute_mod /= 2 - human_owner.visible_message(span_warning("[human_owner]'s back hardens against the blow!")) - playsound(human_owner, 'sound/effects/constructform.ogg', 25, vary = TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE) - - defense_timerid = addtimer(CALLBACK(src, PROC_REF(reset_damage), owner), 5 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE) - -/obj/item/organ/internal/heart/roach/proc/reset_damage(mob/living/carbon/human/human_owner) - defense_timerid = null - if(!QDELETED(human_owner)) - human_owner.physiology.brute_mod *= 2 - human_owner.visible_message(span_warning("[human_owner]'s back softens again.")) + if(blocker.flags_1 & IS_SPINNING_1) + return FALSE + if(blocker.body_position == LYING_DOWN || (blocker.dir & attack_direction)) + return TRUE + return FALSE // Simple overlay so we can add a roach shell to guys with roach hearts /datum/bodypart_overlay/simple/roach_shell diff --git a/code/game/objects/items/grenades/flashbang.dm b/code/game/objects/items/grenades/flashbang.dm index c66e6b396e4..a73b0b02500 100644 --- a/code/game/objects/items/grenades/flashbang.dm +++ b/code/game/objects/items/grenades/flashbang.dm @@ -112,7 +112,7 @@ living_mob.Paralyze(20) living_mob.Knockdown(200) living_mob.soundbang_act(1, 200, 10, 15) - if(living_mob.apply_damages(10, 10)) + if(living_mob.apply_damages(brute = 10, burn = 10)) to_chat(living_mob, span_userdanger("The blast from \the [src] bruises and burns you!")) // only checking if they're on top of the tile, cause being one tile over will be its own punishment diff --git a/code/game/objects/items/stacks/golem_food/golem_status_effects.dm b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm index e52c5f8034c..26b5a4439ea 100644 --- a/code/game/objects/items/stacks/golem_food/golem_status_effects.dm +++ b/code/game/objects/items/stacks/golem_food/golem_status_effects.dm @@ -190,7 +190,7 @@ return ..() /// When we take fire damage (or... technically also cold damage, we don't differentiate), zap a nearby APC -/datum/status_effect/golem/plasma/proc/on_burned(datum/source, damage, damagetype) +/datum/status_effect/golem/plasma/proc/on_burned(datum/source, damage, damagetype, ...) SIGNAL_HANDLER if(damagetype != BURN) return diff --git a/code/modules/antagonists/heretic/magic/shadow_cloak.dm b/code/modules/antagonists/heretic/magic/shadow_cloak.dm index 63cb3d371fd..ef135441c36 100644 --- a/code/modules/antagonists/heretic/magic/shadow_cloak.dm +++ b/code/modules/antagonists/heretic/magic/shadow_cloak.dm @@ -190,7 +190,7 @@ qdel(src) /// Signal proc for [COMSIG_MOB_APPLY_DAMAGE], being damaged past a threshold will roll a chance to stop the effect -/datum/status_effect/shadow_cloak/proc/on_damaged(datum/source, damage, damagetype) +/datum/status_effect/shadow_cloak/proc/on_damaged(datum/source, damage, damagetype, ...) SIGNAL_HANDLER // Stam damage is generally bursty, so we'll half it diff --git a/code/modules/bitrunning/components/avatar_connection.dm b/code/modules/bitrunning/components/avatar_connection.dm index 57d75d3f89e..b50d374867a 100644 --- a/code/modules/bitrunning/components/avatar_connection.dm +++ b/code/modules/bitrunning/components/avatar_connection.dm @@ -108,7 +108,7 @@ ) /// Transfers damage from the avatar to the old_body -/datum/component/avatar_connection/proc/on_linked_damage(datum/source, damage, damage_type, def_zone, blocked, forced) +/datum/component/avatar_connection/proc/on_linked_damage(datum/source, damage, damage_type, def_zone, blocked, ...) SIGNAL_HANDLER var/mob/living/carbon/old_body = old_body_ref?.resolve() @@ -123,7 +123,7 @@ if(damage > 30 && prob(30)) INVOKE_ASYNC(old_body, TYPE_PROC_REF(/mob/living, emote), "scream") - old_body.apply_damage(damage, damage_type, def_zone, blocked, forced, wound_bonus = CANT_WOUND) + old_body.apply_damage(damage, damage_type, def_zone, blocked, wound_bonus = CANT_WOUND) if(old_body.stat > SOFT_CRIT) // KO! full_avatar_disconnect(forced = TRUE) diff --git a/code/modules/bitrunning/server/util.dm b/code/modules/bitrunning/server/util.dm index f4dbada9ef6..9570fd43915 100644 --- a/code/modules/bitrunning/server/util.dm +++ b/code/modules/bitrunning/server/util.dm @@ -58,10 +58,10 @@ "health" = creature.health, "name" = creature.name, "pilot" = pilot, - "brute" = creature.get_current_damage_of_type(BRUTE), - "burn" = creature.get_current_damage_of_type(BURN), - "tox" = creature.get_current_damage_of_type(TOX), - "oxy" = creature.get_current_damage_of_type(OXY), + "brute" = creature.getBruteLoss(), + "burn" = creature.getFireLoss(), + "tox" = creature.getToxLoss(), + "oxy" = creature.getOxyLoss(), )) return hosted_avatars diff --git a/code/modules/mining/equipment/monster_organs/brimdust_sac.dm b/code/modules/mining/equipment/monster_organs/brimdust_sac.dm index dc6539ff336..a77e526a9d1 100644 --- a/code/modules/mining/equipment/monster_organs/brimdust_sac.dm +++ b/code/modules/mining/equipment/monster_organs/brimdust_sac.dm @@ -141,7 +141,7 @@ return COMPONENT_CLEANED /// When you take brute damage, schedule an explosion -/datum/status_effect/stacking/brimdust_coating/proc/on_take_damage(datum/source, damage, damagetype) +/datum/status_effect/stacking/brimdust_coating/proc/on_take_damage(datum/source, damage, damagetype, ...) SIGNAL_HANDLER if(damagetype != BRUTE) return diff --git a/code/modules/mob/living/basic/lavaland/goliath/goliath.dm b/code/modules/mob/living/basic/lavaland/goliath/goliath.dm index f5556cb15cd..6f57e1dec67 100644 --- a/code/modules/mob/living/basic/lavaland/goliath/goliath.dm +++ b/code/modules/mob/living/basic/lavaland/goliath/goliath.dm @@ -102,9 +102,7 @@ // Goliaths can summon tentacles more frequently as they take damage, scary. /mob/living/basic/mining/goliath/apply_damage(damage, damagetype, def_zone, blocked, forced, spread_damage, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) . = ..() - if (!.) - return - if (damage <= 0) + if (. <= 0) return if (tentacles.cooldown_time > 1 SECONDS) tentacles.cooldown_time -= 1 SECONDS diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index 040bf76a3db..6ecc62b0498 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -1,44 +1,79 @@ -/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = 0, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, attacking_item) - SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMAGE, damage, damagetype, def_zone) - var/hit_percent = (100-blocked)/100 - if(!damage || (!forced && hit_percent <= 0)) - return 0 +/mob/living/carbon/apply_damage( + damage = 0, + damagetype = BRUTE, + def_zone = null, + blocked = 0, + forced = FALSE, + spread_damage = FALSE, + wound_bonus = 0, + bare_wound_bonus = 0, + sharpness = NONE, + attack_direction = null, + attacking_item, +) + // Spread damage should always have def zone be null + if(spread_damage) + def_zone = null - var/obj/item/bodypart/BP = null - if(!spread_damage) - if(isbodypart(def_zone)) //we specified a bodypart object - BP = def_zone - else - if(!def_zone) - def_zone = get_random_valid_zone(def_zone) - BP = get_bodypart(check_zone(def_zone)) - if(!BP) - BP = bodyparts[1] + // Otherwise if def zone is null, we'll get a random bodypart / zone to hit. + // ALso we'll automatically covnert string def zones into bodyparts to pass into parent call. + else if(!isbodypart(def_zone)) + var/random_zone = check_zone(def_zone || get_random_valid_zone(def_zone)) + def_zone = get_bodypart(random_zone) || bodyparts[1] + + . = ..() + // Taking brute or burn to bodyparts gives a damage flash + if(def_zone && (damagetype == BRUTE || damagetype == BURN)) + damageoverlaytemp += . + + return . + +/mob/living/carbon/human/apply_damage( + damage = 0, + damagetype = BRUTE, + def_zone = null, + blocked = 0, + forced = FALSE, + spread_damage = FALSE, + wound_bonus = 0, + bare_wound_bonus = 0, + sharpness = NONE, + attack_direction = null, + attacking_item, +) + + // Add relevant DR modifiers into blocked value to pass to parent + blocked += physiology?.damage_resistance + blocked += dna?.species?.damage_modifier + return ..() + +/mob/living/carbon/human/get_incoming_damage_modifier( + damage = 0, + damagetype = BRUTE, + def_zone = null, + sharpness = NONE, + attack_direction = null, + attacking_item, +) + var/final_mod = ..() - var/damage_amount = forced ? damage : damage * hit_percent switch(damagetype) if(BRUTE) - if(BP) - if(BP.receive_damage(damage_amount, 0, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness, attack_direction = attack_direction)) - update_damage_overlays() - else //no bodypart, we deal damage with a more general method. - adjustBruteLoss(damage_amount, forced = forced) + final_mod *= physiology.brute_mod if(BURN) - if(BP) - if(BP.receive_damage(0, damage_amount, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness, attack_direction = attack_direction)) - update_damage_overlays() - else - adjustFireLoss(damage_amount, forced = forced) + final_mod *= physiology.burn_mod if(TOX) - adjustToxLoss(damage_amount, forced = forced) + final_mod *= physiology.tox_mod if(OXY) - adjustOxyLoss(damage_amount, forced = forced) + final_mod *= physiology.oxy_mod if(CLONE) - adjustCloneLoss(damage_amount, forced = forced) + final_mod *= physiology.clone_mod if(STAMINA) - adjustStaminaLoss(damage_amount, forced = forced) - SEND_SIGNAL(src, COMSIG_MOB_AFTER_APPLY_DAMAGE, damage, damagetype, def_zone) - return TRUE + final_mod *= physiology.stamina_mod + if(BRAIN) + final_mod *= physiology.brain_mod + + return final_mod //These procs fetch a cumulative total damage from all bodyparts /mob/living/carbon/getBruteLoss() diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index d92dde594dd..f7e9526b299 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -104,10 +104,8 @@ GLOBAL_LIST_EMPTY(features_by_species) ///Replaces default appendix with a different organ. var/obj/item/organ/internal/appendix/mutantappendix = /obj/item/organ/internal/appendix - /** - * Percentage modifier for overall defense of the race, or less defense, if it's negative - * THIS MODIFIES ALL DAMAGE TYPES. - **/ + /// Flat modifier on all damage taken via [apply_damage][/mob/living/proc/apply_damage] (so being punched, shot, etc.) + /// IE: 10 = 10% less damage taken. var/damage_modifier = 0 ///multiplier for damage from cold temperature var/coldmod = 1 @@ -1072,9 +1070,6 @@ GLOBAL_LIST_EMPTY(features_by_species) affected.log_message("has started overdosing on [chem.name] at [chem.volume] units.", LOG_GAME) return SEND_SIGNAL(affected, COMSIG_SPECIES_HANDLE_CHEMICAL, chem, seconds_per_tick, times_fired) -/datum/species/proc/check_species_weakness(obj/item, mob/living/attacker) - return 1 //This is not a boolean, it's the multiplier for the damage that the user takes from the item. The force of the item is multiplied by this value - /** * Equip the outfit required for life. Replaces items currently worn. */ @@ -1306,30 +1301,36 @@ GLOBAL_LIST_EMPTY(features_by_species) span_userdanger("You block [weapon]!")) return FALSE - var/hit_area - if(!affecting) //Something went wrong. Maybe the limb is missing? - affecting = human.bodyparts[1] - - hit_area = affecting.plaintext_zone - var/def_zone = affecting.body_zone - - var/armor_block = human.run_armor_check(affecting, MELEE, span_notice("Your armor has protected your [hit_area]!"), span_warning("Your armor has softened a hit to your [hit_area]!"),weapon.armour_penetration, weak_against_armour = weapon.weak_against_armour) - armor_block = min(ARMOR_MAX_BLOCK, armor_block) //cap damage reduction at 90% - var/Iwound_bonus = weapon.wound_bonus + affecting ||= human.bodyparts[1] //Something went wrong. Maybe the limb is missing? + var/hit_area = affecting.plaintext_zone + var/armor_block = min(human.run_armor_check( + def_zone = affecting, + attack_flag = MELEE, + absorb_text = span_notice("Your armor has protected your [hit_area]!"), + soften_text = span_warning("Your armor has softened a hit to your [hit_area]!"), + armour_penetration = weapon.armour_penetration, + weak_against_armour = weapon.weak_against_armour, + ), ARMOR_MAX_BLOCK) //cap damage reduction at 90% + var/modified_wound_bonus = weapon.wound_bonus // this way, you can't wound with a surgical tool on help intent if they have a surgery active and are lying down, so a misclick with a circular saw on the wrong limb doesn't bleed them dry (they still get hit tho) if((weapon.item_flags & SURGICAL_TOOL) && !user.combat_mode && human.body_position == LYING_DOWN && (LAZYLEN(human.surgeries) > 0)) - Iwound_bonus = CANT_WOUND - - var/weakness = check_species_weakness(weapon, user) + modified_wound_bonus = CANT_WOUND human.send_item_attack_message(weapon, user, hit_area, affecting) + var/damage_dealt = human.apply_damage( + damage = weapon.force, + damagetype = weapon.damtype, + def_zone = affecting, + blocked = armor_block, + wound_bonus = modified_wound_bonus, + bare_wound_bonus = weapon.bare_wound_bonus, + sharpness = weapon.get_sharpness(), + attack_direction = get_dir(user, human), + attacking_item = weapon, + ) - - var/attack_direction = get_dir(user, human) - apply_damage(weapon.force * weakness, weapon.damtype, def_zone, armor_block, human, wound_bonus = Iwound_bonus, bare_wound_bonus = weapon.bare_wound_bonus, sharpness = weapon.get_sharpness(), attack_direction = attack_direction, attacking_item = weapon) - - if(!weapon.force) + if(damage_dealt <= 0) return FALSE //item force is zero var/bloody = FALSE if(weapon.damtype != BRUTE) @@ -1399,61 +1400,6 @@ GLOBAL_LIST_EMPTY(features_by_species) return TRUE -/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, attacking_item) - SEND_SIGNAL(H, COMSIG_MOB_APPLY_DAMAGE, damage, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) - var/hit_percent = (100-(damage_modifier+blocked))/100 - hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100 - if(!damage || (!forced && hit_percent <= 0)) - return 0 - - var/obj/item/bodypart/BP = null - if(!spread_damage) - if(isbodypart(def_zone)) - BP = def_zone - else - if(!def_zone) - def_zone = H.get_random_valid_zone(def_zone) - BP = H.get_bodypart(check_zone(def_zone)) - if(!BP) - BP = H.bodyparts[1] - - switch(damagetype) - if(BRUTE) - H.damageoverlaytemp = 20 - var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.brute_mod - if(BP) - if(BP.receive_damage(damage_amount, 0, forced = forced, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness, attack_direction = attack_direction, damage_source = attacking_item)) - H.update_damage_overlays() - else//no bodypart, we deal damage with a more general method. - H.adjustBruteLoss(damage_amount, forced = forced) - INVOKE_ASYNC(H, TYPE_PROC_REF(/mob/living/carbon/human, adjust_pain), damage_amount) // SKYRAT EDIT ADDITION - ERP Pain - if(BURN) - H.damageoverlaytemp = 20 - var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.burn_mod - if(BP) - if(BP.receive_damage(0, damage_amount, forced = forced, wound_bonus = wound_bonus, bare_wound_bonus = bare_wound_bonus, sharpness = sharpness, attack_direction = attack_direction, damage_source = attacking_item)) - H.update_damage_overlays() - else - H.adjustFireLoss(damage_amount, forced = forced) - INVOKE_ASYNC(H, TYPE_PROC_REF(/mob/living/carbon/human, adjust_pain), damage_amount) // SKYRAT EDIT ADDITION - ERP Pain - if(TOX) - var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.tox_mod - H.adjustToxLoss(damage_amount, forced = forced) - if(OXY) - var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.oxy_mod - H.adjustOxyLoss(damage_amount, forced = forced) - if(CLONE) - var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.clone_mod - H.adjustCloneLoss(damage_amount, forced = forced) - if(STAMINA) - var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.stamina_mod - H.adjustStaminaLoss(damage_amount, forced = forced) - if(BRAIN) - var/damage_amount = forced ? damage : damage * hit_percent * H.physiology.brain_mod - H.adjustOrganLoss(ORGAN_SLOT_BRAIN, damage_amount) - SEND_SIGNAL(H, COMSIG_MOB_AFTER_APPLY_DAMAGE, damage, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) - return TRUE - ////////////////////////// // ENVIRONMENT HANDLERS // ////////////////////////// @@ -1741,11 +1687,12 @@ GLOBAL_LIST_EMPTY(features_by_species) switch(adjusted_pressure) // Very high pressure, show an alert and take damage if(HAZARD_HIGH_PRESSURE to INFINITY) - if(!HAS_TRAIT(H, TRAIT_RESISTHIGHPRESSURE)) - H.adjustBruteLoss(min(((adjusted_pressure / HAZARD_HIGH_PRESSURE) - 1) * PRESSURE_DAMAGE_COEFFICIENT, MAX_HIGH_PRESSURE_DAMAGE) * H.physiology.pressure_mod * seconds_per_tick, required_bodytype = BODYTYPE_ORGANIC) - H.throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/highpressure, 2) - else + if(HAS_TRAIT(H, TRAIT_RESISTHIGHPRESSURE)) H.clear_alert(ALERT_PRESSURE) + else + var/pressure_damage = min(((adjusted_pressure / HAZARD_HIGH_PRESSURE) - 1) * PRESSURE_DAMAGE_COEFFICIENT, MAX_HIGH_PRESSURE_DAMAGE) * H.physiology.pressure_mod * H.physiology.brute_mod * seconds_per_tick + H.adjustBruteLoss(pressure_damage, required_bodytype = BODYTYPE_ORGANIC) + H.throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/highpressure, 2) // High pressure, show an alert if(WARNING_HIGH_PRESSURE to HAZARD_HIGH_PRESSURE) @@ -1769,7 +1716,8 @@ GLOBAL_LIST_EMPTY(features_by_species) if(HAS_TRAIT(H, TRAIT_RESISTLOWPRESSURE)) H.clear_alert(ALERT_PRESSURE) else - H.adjustBruteLoss(LOW_PRESSURE_DAMAGE * H.physiology.pressure_mod * seconds_per_tick, required_bodytype = BODYTYPE_ORGANIC) + var/pressure_damage = LOW_PRESSURE_DAMAGE * H.physiology.pressure_mod * H.physiology.brute_mod * seconds_per_tick + H.adjustBruteLoss(pressure_damage, required_bodytype = BODYTYPE_ORGANIC) H.throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/lowpressure, 2) diff --git a/code/modules/mob/living/carbon/human/damage_procs.dm b/code/modules/mob/living/carbon/human/damage_procs.dm deleted file mode 100644 index d4fc0b40365..00000000000 --- a/code/modules/mob/living/carbon/human/damage_procs.dm +++ /dev/null @@ -1,4 +0,0 @@ - -/// depending on the species, it will run the corresponding apply_damage code there -/mob/living/carbon/human/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, attacking_item) - return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced, spread_damage, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) diff --git a/code/modules/mob/living/carbon/human/physiology.dm b/code/modules/mob/living/carbon/human/physiology.dm index bfd3dc8d73c..398f8d0c5e9 100644 --- a/code/modules/mob/living/carbon/human/physiology.dm +++ b/code/modules/mob/living/carbon/human/physiology.dm @@ -1,18 +1,33 @@ //Stores several modifiers in a way that isn't cleared by changing species /datum/physiology - var/brute_mod = 1 // % of brute damage taken from all sources - var/burn_mod = 1 // % of burn damage taken from all sources - var/tox_mod = 1 // % of toxin damage taken from all sources - var/oxy_mod = 1 // % of oxygen damage taken from all sources - var/clone_mod = 1 // % of clone damage taken from all sources - var/stamina_mod = 1 // % of stamina damage taken from all sources - var/brain_mod = 1 // % of brain damage taken from all sources + /// Multiplier to brute damage received. + /// IE: A brute mod of 0.9 = 10% less brute damage. + /// Only applies to damage dealt via [apply_damage][/mob/living/proc/apply_damage] unless factored in manually. + var/brute_mod = 1 + /// Multiplier to burn damage received + var/burn_mod = 1 + /// Multiplier to toxin damage received + var/tox_mod = 1 + /// Multiplier to oxygen damage received + var/oxy_mod = 1 + /// Multiplier to clone damage received + var/clone_mod = 1 + /// Multiplier to stamina damage received + var/stamina_mod = 1 + /// Multiplier to brain damage received + var/brain_mod = 1 - var/pressure_mod = 1 // % of brute damage taken from low or high pressure (stacks with brute_mod) - var/heat_mod = 1 // % of burn damage taken from heat (stacks with burn_mod) - var/cold_mod = 1 // % of burn damage taken from cold (stacks with burn_mod) + /// Multiplier to damage taken from high / low pressure exposure, stacking with the brute modifier + var/pressure_mod = 1 + /// Multiplier to damage taken from high temperature exposure, stacking with the burn modifier + var/heat_mod = 1 + /// Multiplier to damage taken from low temperature exposure, stacking with the toxin modifier + var/cold_mod = 1 - var/damage_resistance = 0 // %damage reduction from all sources + /// Flat damage reduction from taking damage + /// Unlike the other modifiers, this is not a multiplier. + /// IE: DR of 10 = 10% less damage. + var/damage_resistance = 0 var/siemens_coeff = 1 // resistance to shocks diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm index c36252bbcb2..c2c73becdec 100644 --- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm @@ -32,10 +32,19 @@ BODY_ZONE_CHEST = /obj/item/bodypart/chest/fly, ) -/datum/species/fly/check_species_weakness(obj/item/weapon, mob/living/attacker) - if(istype(weapon, /obj/item/melee/flyswatter)) - return 30 //Flyswatters deal 30x damage to flypeople. - return 1 +/datum/species/fly/on_species_gain(mob/living/carbon/human/human_who_gained_species, datum/species/old_species, pref_load) + . = ..() + RegisterSignal(human_who_gained_species, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS, PROC_REF(damage_weakness)) + +/datum/species/fly/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) + . = ..() + UnregisterSignal(C, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS) + +/datum/species/fly/proc/damage_weakness(datum/source, list/damage_mods, damage_amount, damagetype, def_zone, sharpness, attack_direction, obj/item/attacking_item) + SIGNAL_HANDLER + + if(istype(attacking_item, /obj/item/melee/flyswatter)) + damage_mods += 30 // Yes, a 30x damage modifier /datum/species/fly/get_physical_attributes() return "These hideous creatures suffer from pesticide immensely, eat waste, and are incredibly vulnerable to bright lights. They do have wings though." diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index adb5ffa62aa..d8d49f7958f 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -47,10 +47,19 @@ return randname -/datum/species/moth/check_species_weakness(obj/item/weapon, mob/living/attacker) - if(istype(weapon, /obj/item/melee/flyswatter)) - return 10 //flyswatters deal 10x damage to moths - return 1 +/datum/species/moth/on_species_gain(mob/living/carbon/human/human_who_gained_species, datum/species/old_species, pref_load) + . = ..() + RegisterSignal(human_who_gained_species, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS, PROC_REF(damage_weakness)) + +/datum/species/moth/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) + . = ..() + UnregisterSignal(C, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS) + +/datum/species/moth/proc/damage_weakness(datum/source, list/damage_mods, damage_amount, damagetype, def_zone, sharpness, attack_direction, obj/item/attacking_item) + SIGNAL_HANDLER + + if(istype(attacking_item, /obj/item/melee/flyswatter)) + damage_mods += 10 // Yes, a 10x damage modifier /datum/species/moth/randomize_features(mob/living/carbon/human/human_mob) human_mob.dna.features["moth_markings"] = pick(GLOB.moth_wings_list) diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index c07f0478c03..4c2f1ffa708 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -40,6 +40,11 @@ new_vampire.skin_tone = "albino" new_vampire.update_body(0) new_vampire.set_safe_hunger_level() + RegisterSignal(new_vampire, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS, PROC_REF(damage_weakness)) + +/datum/species/vampire/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) + . = ..() + UnregisterSignal(C, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS) /datum/species/vampire/spec_life(mob/living/carbon/human/vampire, seconds_per_tick, times_fired) . = ..() @@ -64,10 +69,11 @@ vampire.adjust_fire_stacks(3 * seconds_per_tick) vampire.ignite_mob() -/datum/species/vampire/check_species_weakness(obj/item/weapon, mob/living/attacker) - if(istype(weapon, /obj/item/nullrod/whip)) - return 2 //Whips deal 2x damage to vampires. Vampire killer. - return 1 +/datum/species/vampire/proc/damage_weakness(datum/source, list/damage_mods, damage_amount, damagetype, def_zone, sharpness, attack_direction, obj/item/attacking_item) + SIGNAL_HANDLER + + if(istype(attacking_item, /obj/item/nullrod/whip)) + damage_mods += 2 /datum/species/vampire/get_physical_attributes() return "Vampires are afflicted with the Thirst, needing to sate it by draining the blood out of another living creature. However, they do not need to breathe or eat normally. \ diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index c92262733c1..41eb7bb06f4 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -1,58 +1,149 @@ /** - * Applies damage to this mob + * Applies damage to this mob. * * Sends [COMSIG_MOB_APPLY_DAMAGE] * * Arguuments: - * * damage - amount of damage - * * damagetype - one of [BRUTE], [BURN], [TOX], [OXY], [CLONE], [STAMINA] - * * def_zone - zone that is being hit if any - * * blocked - armor value applied - * * forced - bypass hit percentage - * * spread_damage - used in overrides + * * damage - Amount of damage + * * damagetype - What type of damage to do. one of [BRUTE], [BURN], [TOX], [OXY], [CLONE], [STAMINA], [BRAIN]. + * * def_zone - What body zone is being hit. Or a reference to what bodypart is being hit. + * * blocked - Percent modifier to damage. 100 = 100% less damage dealt, 50% = 50% less damage dealt. + * * forced - "Force" exactly the damage dealt. This means it skips damage modifier from blocked. + * * spread_damage - For carbons, spreads the damage across all bodyparts rather than just the targeted zone. + * * wound_bonus - Bonus modifier for wound chance. + * * bare_wound_bonus - Bonus modifier for wound chance on bare skin. + * * sharpness - Sharpness of the weapon. + * * attack_direction - Direction of the attack from the attacker to [src]. + * * attacking_item - Item that is attacking [src]. * - * Returns TRUE if damage applied + * Returns the amount of damage dealt. */ -/mob/living/proc/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, attacking_item) - SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMAGE, damage, damagetype, def_zone) - var/hit_percent = (100-blocked)/100 - if(!damage || (!forced && hit_percent <= 0)) - return FALSE - var/damage_amount = forced ? damage : damage * hit_percent - switch(damagetype) - if(BRUTE) - adjustBruteLoss(damage_amount, forced = forced) - if(BURN) - adjustFireLoss(damage_amount, forced = forced) - if(TOX) - adjustToxLoss(damage_amount, forced = forced) - if(OXY) - adjustOxyLoss(damage_amount, forced = forced) - if(CLONE) - adjustCloneLoss(damage_amount, forced = forced) - if(STAMINA) - adjustStaminaLoss(damage_amount, forced = forced) - SEND_SIGNAL(src, COMSIG_MOB_AFTER_APPLY_DAMAGE, damage, damagetype, def_zone) - return TRUE +/mob/living/proc/apply_damage( + damage = 0, + damagetype = BRUTE, + def_zone = null, + blocked = 0, + forced = FALSE, + spread_damage = FALSE, + wound_bonus = 0, + bare_wound_bonus = 0, + sharpness = NONE, + attack_direction = null, + attacking_item, +) + SHOULD_CALL_PARENT(TRUE) + var/damage_amount = damage + if(!forced) + damage_amount *= ((100 - blocked) / 100) + damage_amount *= get_incoming_damage_modifier(damage_amount, damagetype, def_zone, sharpness, attack_direction, attacking_item) + if(damage_amount <= 0) + return 0 -///like [apply_damage][/mob/living/proc/apply_damage] except it always uses the damage procs -/mob/living/proc/apply_damage_type(damage = 0, damagetype = BRUTE) + SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMAGE, damage_amount, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) + + var/damage_dealt = 0 switch(damagetype) if(BRUTE) - return adjustBruteLoss(damage) + if(isbodypart(def_zone)) + var/obj/item/bodypart/actual_hit = def_zone + var/delta = actual_hit.get_damage() + if(actual_hit.receive_damage( + brute = damage_amount, + burn = 0, + forced = forced, + wound_bonus = wound_bonus, + bare_wound_bonus = bare_wound_bonus, + sharpness = sharpness, + attack_direction = attack_direction, + damage_source = attacking_item, + )) + update_damage_overlays() + damage_dealt = actual_hit.get_damage() - delta // Unfortunately bodypart receive_damage doesn't return damage dealt so we do it manually + else + damage_dealt = adjustBruteLoss(damage_amount, forced = forced) + INVOKE_ASYNC(src, TYPE_PROC_REF(/mob/living, adjust_pain), damage_amount) // SKYRAT EDIT ADDITION - ERP Pain if(BURN) - return adjustFireLoss(damage) + if(isbodypart(def_zone)) + var/obj/item/bodypart/actual_hit = def_zone + var/delta = actual_hit.get_damage() + if(actual_hit.receive_damage( + brute = 0, + burn = damage_amount, + forced = forced, + wound_bonus = wound_bonus, + bare_wound_bonus = bare_wound_bonus, + sharpness = sharpness, + attack_direction = attack_direction, + damage_source = attacking_item, + )) + update_damage_overlays() + damage_dealt = delta - actual_hit.get_damage() // See above + else + damage_dealt = adjustFireLoss(damage_amount, forced = forced) + INVOKE_ASYNC(src, TYPE_PROC_REF(/mob/living, adjust_pain), damage_amount) // SKYRAT EDIT ADDITION - ERP Pain if(TOX) - return adjustToxLoss(damage) + damage_dealt = adjustToxLoss(damage_amount, forced = forced) if(OXY) - return adjustOxyLoss(damage) + damage_dealt = adjustOxyLoss(damage_amount, forced = forced) if(CLONE) - return adjustCloneLoss(damage) + damage_dealt = adjustCloneLoss(damage_amount, forced = forced) if(STAMINA) - return adjustStaminaLoss(damage) + damage_dealt = adjustStaminaLoss(damage_amount, forced = forced) + if(BRAIN) + damage_dealt = adjustOrganLoss(ORGAN_SLOT_BRAIN, damage_amount) + + SEND_SIGNAL(src, COMSIG_MOB_AFTER_APPLY_DAMAGE, damage_dealt, damagetype, def_zone, blocked, wound_bonus, bare_wound_bonus, sharpness, attack_direction, attacking_item) + return damage_dealt + +/** + * Used in tandem with [/mob/living/proc/apply_damage] to calculate modifier applied into incoming damage + */ +/mob/living/proc/get_incoming_damage_modifier( + damage = 0, + damagetype = BRUTE, + def_zone = null, + sharpness = NONE, + attack_direction = null, + attacking_item, +) + SHOULD_CALL_PARENT(TRUE) + SHOULD_BE_PURE(TRUE) + + var/list/damage_mods = list() + SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMAGE_MODIFIERS, damage_mods, damage, damagetype, def_zone, sharpness, attack_direction, attacking_item) + + var/final_mod = 1 + for(var/new_mod in damage_mods) + final_mod *= new_mod + return final_mod + +/** + * Simply a wrapper for calling mob adjustXLoss() procs to heal a certain damage type, + * when you don't know what damage type you're healing exactly. + */ +/mob/living/proc/heal_damage_type(heal_amount = 0, damagetype = BRUTE) + heal_amount = abs(heal_amount) * -1 + + switch(damagetype) + if(BRUTE) + return adjustBruteLoss(heal_amount) + if(BURN) + return adjustFireLoss(heal_amount) + if(TOX) + return adjustToxLoss(heal_amount) + if(OXY) + return adjustOxyLoss(heal_amount) + if(CLONE) + return adjustCloneLoss(heal_amount) + if(STAMINA) + return adjustStaminaLoss(heal_amount) /// return the damage amount for the type given +/** + * Simply a wrapper for calling mob getXLoss() procs to get a certain damage type, + * when you don't know what damage type you're getting exactly. + */ /mob/living/proc/get_current_damage_of_type(damagetype = BRUTE) switch(damagetype) if(BRUTE) @@ -72,26 +163,34 @@ /mob/living/proc/get_total_damage(precision = DAMAGE_PRECISION) return round(getBruteLoss() + getFireLoss() + getToxLoss() + getOxyLoss() + getCloneLoss(), precision) -/// applies multiple damages at once via [/mob/living/proc/apply_damage] -/mob/living/proc/apply_damages(brute = 0, burn = 0, tox = 0, oxy = 0, clone = 0, def_zone = null, blocked = FALSE, stamina = 0, brain = 0) - if(blocked >= 100) - return 0 +/// Applies multiple damages at once via [apply_damage][/mob/living/proc/apply_damage] +/mob/living/proc/apply_damages( + brute = 0, + burn = 0, + tox = 0, + oxy = 0, + clone = 0, + def_zone = null, + blocked = 0, + stamina = 0, + brain = 0, +) + var/total_damage = 0 if(brute) - apply_damage(brute, BRUTE, def_zone, blocked) + total_damage += apply_damage(brute, BRUTE, def_zone, blocked) if(burn) - apply_damage(burn, BURN, def_zone, blocked) + total_damage += apply_damage(burn, BURN, def_zone, blocked) if(tox) - apply_damage(tox, TOX, def_zone, blocked) + total_damage += apply_damage(tox, TOX, def_zone, blocked) if(oxy) - apply_damage(oxy, OXY, def_zone, blocked) + total_damage += apply_damage(oxy, OXY, def_zone, blocked) if(clone) - apply_damage(clone, CLONE, def_zone, blocked) + total_damage += apply_damage(clone, CLONE, def_zone, blocked) if(stamina) - apply_damage(stamina, STAMINA, def_zone, blocked) + total_damage += apply_damage(stamina, STAMINA, def_zone, blocked) if(brain) - apply_damage(brain, BRAIN, def_zone, blocked) - return 1 - + total_damage += apply_damage(brain, BRAIN, def_zone, blocked) + return total_damage /// applies various common status effects or common hardcoded mob effects /mob/living/proc/apply_effect(effect = 0,effecttype = EFFECT_STUN, blocked = 0) @@ -432,11 +531,11 @@ ///heal up to amount damage, in a given order /mob/living/proc/heal_ordered_damage(amount, list/damage_types) - . = FALSE //we'll return the amount of damage healed + . = 0 //we'll return the amount of damage healed for(var/damagetype in damage_types) var/amount_to_heal = min(abs(amount), get_current_damage_of_type(damagetype)) //heal only up to the amount of damage we have if(amount_to_heal) - . += apply_damage_type(-amount_to_heal, damagetype) + . += heal_damage_type(amount_to_heal, damagetype) amount -= amount_to_heal //remove what we healed from our current amount if(!amount) break diff --git a/code/modules/mob/living/silicon/damage_procs.dm b/code/modules/mob/living/silicon/damage_procs.dm index 4fe6e688632..16f6b8abb42 100644 --- a/code/modules/mob/living/silicon/damage_procs.dm +++ b/code/modules/mob/living/silicon/damage_procs.dm @@ -1,17 +1,3 @@ - -/mob/living/silicon/apply_damage(damage = 0, damagetype = BRUTE, def_zone = null, blocked = 0, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, attacking_item) - var/hit_percent = (100-blocked)/100 - if((!damage || (!forced && hit_percent <= 0))) - return 0 - var/damage_amount = forced ? damage : damage * hit_percent - switch(damagetype) - if(BRUTE) - adjustBruteLoss(damage_amount, forced = forced) - if(BURN) - adjustFireLoss(damage_amount, forced = forced) - return 1 - - /mob/living/silicon/apply_effect(effect = 0,effecttype = EFFECT_STUN, blocked = FALSE) return FALSE //The only effect that can hit them atm is flashes and they still directly edit so this works for now. (This was written in at least 2016. Help) diff --git a/code/modules/mob/living/simple_animal/bot/medbot.dm b/code/modules/mob/living/simple_animal/bot/medbot.dm index acdf21c9fc8..33fa7baab7a 100644 --- a/code/modules/mob/living/simple_animal/bot/medbot.dm +++ b/code/modules/mob/living/simple_animal/bot/medbot.dm @@ -658,10 +658,10 @@ healies *= 1.1 if(bot_cover_flags & BOT_COVER_EMAGGED) patient.reagents.add_reagent(/datum/reagent/toxin/chloralhydrate, 5) - patient.apply_damage_type((healies*1),treatment_method) + patient.apply_damage((healies * 1), treatment_method, spread_damage = TRUE) log_combat(src, patient, "pretended to tend wounds on", "internal tools", "([uppertext(treatment_method)]) (EMAGGED)") else - patient.apply_damage_type((healies*-1),treatment_method) //don't need to check treatment_method since we know by this point that they were actually damaged. + patient.heal_damage_type((healies * 1), treatment_method) //don't need to check treatment_method since we know by this point that they were actually damaged. log_combat(src, patient, "tended the wounds of", "internal tools", "([uppertext(treatment_method)])") C.visible_message(span_notice("[src] tends the wounds of [patient]!"), \ "[span_green("[src] tends your wounds!")]") diff --git a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm index 6d4d6a7b272..04d37c62b7c 100644 --- a/code/modules/research/xenobiology/crossbreeding/_status_effects.dm +++ b/code/modules/research/xenobiology/crossbreeding/_status_effects.dm @@ -995,7 +995,7 @@ healing_types += CLONE if(length(healing_types)) - owner.apply_damage_type(-heal_amount, damagetype = pick(healing_types)) + owner.heal_damage_type(heal_amount, damagetype = pick(healing_types)) owner.adjust_nutrition(3) drained.apply_damage(heal_amount * DRAIN_DAMAGE_MULTIPLIER, damagetype = BRUTE, spread_damage = TRUE) diff --git a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm index bb0b30ddd62..8ad9301fe74 100644 --- a/code/modules/surgery/organs/internal/heart/heart_ethereal.dm +++ b/code/modules/surgery/organs/internal/heart/heart_ethereal.dm @@ -139,7 +139,7 @@ return ///Lets you stop the process with enough brute damage -/obj/item/organ/internal/heart/ethereal/proc/on_take_damage(datum/source, damage, damagetype, def_zone) +/obj/item/organ/internal/heart/ethereal/proc/on_take_damage(datum/source, damage, damagetype, def_zone, ...) SIGNAL_HANDLER if(damagetype != BRUTE) return diff --git a/code/modules/surgery/organs/internal/lungs/_lungs.dm b/code/modules/surgery/organs/internal/lungs/_lungs.dm index faf67a4596f..2e99f70d989 100644 --- a/code/modules/surgery/organs/internal/lungs/_lungs.dm +++ b/code/modules/surgery/organs/internal/lungs/_lungs.dm @@ -264,7 +264,7 @@ return var/ratio = (breath.gases[/datum/gas/oxygen][MOLES] / safe_oxygen_max) * 10 - breather.apply_damage_type(clamp(ratio, oxy_breath_dam_min, oxy_breath_dam_max), oxy_damage_type) + breather.apply_damage(clamp(ratio, oxy_breath_dam_min, oxy_breath_dam_max), oxy_damage_type, spread_damage = TRUE) breather.throw_alert(ALERT_TOO_MUCH_OXYGEN, /atom/movable/screen/alert/too_much_oxy) /// Handles NOT having too much o2. only relevant if safe_oxygen_max has a value @@ -320,10 +320,10 @@ breather.throw_alert(ALERT_TOO_MUCH_CO2, /atom/movable/screen/alert/too_much_co2) breather.Unconscious(6 SECONDS) // Lets hurt em a little, let them know we mean business. - breather.apply_damage_type(3, co2_damage_type) + breather.apply_damage(3, co2_damage_type, spread_damage = TRUE) // They've been in here 30s now, start to kill them for their own good! if((world.time - breather.co2overloadtime) > 30 SECONDS) - breather.apply_damage_type(8, co2_damage_type) + breather.apply_damage(8, co2_damage_type, spread_damage = TRUE) /// Handles NOT having too much co2. only relevant if safe_co2_max has a value /obj/item/organ/internal/lungs/proc/safe_co2(mob/living/carbon/breather, datum/gas_mixture/breath, old_co2_pp) @@ -364,7 +364,7 @@ breather.throw_alert(ALERT_TOO_MUCH_PLASMA, /atom/movable/screen/alert/too_much_plas) var/ratio = (breath.gases[/datum/gas/plasma][MOLES] / safe_plasma_max) * 10 - breather.apply_damage_type(clamp(ratio, plas_breath_dam_min, plas_breath_dam_max), plas_damage_type) + breather.apply_damage(clamp(ratio, plas_breath_dam_min, plas_breath_dam_max), plas_damage_type, spread_damage = TRUE) /// Resets plasma side effects /obj/item/organ/internal/lungs/proc/safe_plasma(mob/living/carbon/breather, datum/gas_mixture/breath, old_plasma_pp) @@ -754,11 +754,11 @@ if(!HAS_TRAIT(breather, TRAIT_RESISTCOLD)) // COLD DAMAGE var/cold_modifier = breather.dna.species.coldmod if(breath_temperature < cold_level_3_threshold) - breather.apply_damage_type(cold_level_3_damage*cold_modifier, cold_damage_type) + breather.apply_damage(cold_level_3_damage*cold_modifier, cold_damage_type, spread_damage = TRUE) if(breath_temperature > cold_level_3_threshold && breath_temperature < cold_level_2_threshold) - breather.apply_damage_type(cold_level_2_damage*cold_modifier, cold_damage_type) + breather.apply_damage(cold_level_2_damage*cold_modifier, cold_damage_type, spread_damage = TRUE) if(breath_temperature > cold_level_2_threshold && breath_temperature < cold_level_1_threshold) - breather.apply_damage_type(cold_level_1_damage*cold_modifier, cold_damage_type) + breather.apply_damage(cold_level_1_damage*cold_modifier, cold_damage_type, spread_damage = TRUE) if(breath_temperature < cold_level_1_threshold) if(prob(20)) to_chat(breather, span_warning("You feel [cold_message] in your [name]!")) @@ -766,11 +766,11 @@ if(!HAS_TRAIT(breather, TRAIT_RESISTHEAT)) // HEAT DAMAGE var/heat_modifier = breather.dna.species.heatmod if(breath_temperature > heat_level_1_threshold && breath_temperature < heat_level_2_threshold) - breather.apply_damage_type(heat_level_1_damage*heat_modifier, heat_damage_type) + breather.apply_damage(heat_level_1_damage*heat_modifier, heat_damage_type, spread_damage = TRUE) if(breath_temperature > heat_level_2_threshold && breath_temperature < heat_level_3_threshold) - breather.apply_damage_type(heat_level_2_damage*heat_modifier, heat_damage_type) + breather.apply_damage(heat_level_2_damage*heat_modifier, heat_damage_type, spread_damage = TRUE) if(breath_temperature > heat_level_3_threshold) - breather.apply_damage_type(heat_level_3_damage*heat_modifier, heat_damage_type) + breather.apply_damage(heat_level_3_damage*heat_modifier, heat_damage_type, spread_damage = TRUE) if(breath_temperature > heat_level_1_threshold) if(prob(20)) to_chat(breather, span_warning("You feel [hot_message] in your [name]!")) diff --git a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_arousal/pain.dm b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_arousal/pain.dm index 072de283139..e0d14bf01a2 100644 --- a/modular_skyrat/modules/modular_items/lewd_items/code/lewd_arousal/pain.dm +++ b/modular_skyrat/modules/modular_items/lewd_items/code/lewd_arousal/pain.dm @@ -2,7 +2,10 @@ /// Adds or removes pain, this should be used instead of the modifying the var, due to quirk logic. /// Makes the human scream and shiver when pain hits the soft limit, provided autoemote is enabled. -/mob/living/carbon/human/proc/adjust_pain(change_amount = 0) +/mob/living/proc/adjust_pain(change_amount = 0) + return + +/mob/living/carbon/human/adjust_pain(change_amount = 0) if(stat >= DEAD || !client?.prefs?.read_preference(/datum/preference/toggle/erp)) return diff --git a/modular_skyrat/modules/mutants/code/mutant_species.dm b/modular_skyrat/modules/mutants/code/mutant_species.dm index 86666198508..d61e0367421 100644 --- a/modular_skyrat/modules/mutants/code/mutant_species.dm +++ b/modular_skyrat/modules/mutants/code/mutant_species.dm @@ -74,9 +74,14 @@ /// The cooldown before the mutant can start regenerating COOLDOWN_DECLARE(regen_cooldown) -/datum/species/mutant/infectious/on_species_gain(mob/living/carbon/C, datum/species/old_species) +/datum/species/mutant/infectious/on_species_gain(mob/living/carbon/human/human_who_gained_species, datum/species/old_species, pref_load) . = ..() - C.AddComponent(/datum/component/mutant_hands, mutant_hand_path = hands_to_give) + human_who_gained_species.AddComponent(/datum/component/mutant_hands, mutant_hand_path = hands_to_give) + RegisterSignal(human_who_gained_species, COMSIG_MOB_AFTER_APPLY_DAMAGE, PROC_REF(queue_regeneration)) + +/datum/species/mutant/infectious/on_species_loss(mob/living/carbon/human/human_who_lost_species, datum/species/new_species, pref_load) + . = ..() + UnregisterSignal(human_who_lost_species, COMSIG_MOB_AFTER_APPLY_DAMAGE) /obj/item/bodypart/leg/left/mutant_zombie/infectious speed_modifier = 0.5 @@ -137,9 +142,11 @@ /datum/species/mutant/infectious/spec_stun(mob/living/carbon/human/H,amount) . = min(20, amount) -/datum/species/mutant/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = NONE, attack_direction = null, attacking_item) - . = ..() - if(.) +/// Start the cooldown to regenerate - 5 seconds after taking damage +/datum/species/mutant/infectious/proc/queue_regeneration() + SIGNAL_HANDLER + + if(COOLDOWN_FINISHED(src, regen_cooldown)) COOLDOWN_START(src, regen_cooldown, REGENERATION_DELAY) /datum/species/mutant/infectious/spec_life(mob/living/carbon/carbon_mob, seconds_per_tick, times_fired) diff --git a/tgstation.dme b/tgstation.dme index 42a20910290..5b809f546d7 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -4732,7 +4732,6 @@ #include "code\modules\mob\living\carbon\alien\special\alien_embryo.dm" #include "code\modules\mob\living\carbon\alien\special\facehugger.dm" #include "code\modules\mob\living\carbon\human\_species.dm" -#include "code\modules\mob\living\carbon\human\damage_procs.dm" #include "code\modules\mob\living\carbon\human\death.dm" #include "code\modules\mob\living\carbon\human\dummy.dm" #include "code\modules\mob\living\carbon\human\emote.dm"