diff --git a/code/game/objects/items/implants/implant_misc.dm b/code/game/objects/items/implants/implant_misc.dm index b353070df7b8..4254f214fee0 100644 --- a/code/game/objects/items/implants/implant_misc.dm +++ b/code/game/objects/items/implants/implant_misc.dm @@ -40,6 +40,7 @@ imp_in.SetParalyzed(0) imp_in.SetImmobilized(0) imp_in.adjustStaminaLoss(-75) + imp_in.clear_stamina_regen() // We already cleared our stamina, don't continue healing imp_in.set_resting(FALSE) imp_in.update_mobility() diff --git a/code/modules/antagonists/changeling/powers/adrenaline.dm b/code/modules/antagonists/changeling/powers/adrenaline.dm index 7d68312b8f4c..12dddd13140e 100644 --- a/code/modules/antagonists/changeling/powers/adrenaline.dm +++ b/code/modules/antagonists/changeling/powers/adrenaline.dm @@ -21,4 +21,5 @@ user.reagents.add_reagent(/datum/reagent/medicine/changelingadrenaline, 10) user.reagents.add_reagent(/datum/reagent/medicine/changelinghaste, 2) //For a really quick burst of speed user.adjustStaminaLoss(-75) + user.clear_stamina_regen() // We already cleared our stamina, don't continue healing return TRUE diff --git a/code/modules/antagonists/changeling/powers/strained_muscles.dm b/code/modules/antagonists/changeling/powers/strained_muscles.dm index 71cde7a5ab65..60fd653586df 100644 --- a/code/modules/antagonists/changeling/powers/strained_muscles.dm +++ b/code/modules/antagonists/changeling/powers/strained_muscles.dm @@ -42,12 +42,13 @@ stacks++ user.adjustStaminaLoss(stacks * 1.3) //At first the changeling may regenerate stamina fast enough to nullify fatigue, but it will stack + user.clear_stamina_regen() if(stacks == 11) //Warning message that the stacks are getting too high to_chat(user, span_warning("Our legs are really starting to hurt...")) sleep(4 SECONDS) - + //yogs start - removes speed buff when not active while(!active) user.remove_movespeed_modifier(MOVESPEED_ID_CHANGELING_MUSCLES) diff --git a/code/modules/antagonists/cult/runes.dm b/code/modules/antagonists/cult/runes.dm index 3ec2ad52d200..1d62c217154f 100644 --- a/code/modules/antagonists/cult/runes.dm +++ b/code/modules/antagonists/cult/runes.dm @@ -876,6 +876,7 @@ structure_check() searches for nearby cultist structures required for the invoca L.take_overall_damage(0, tick_damage*multiplier) //yogs: only burn damage since these like all runes can be placed and activated near freely if(is_servant_of_ratvar(L)) L.adjustStaminaLoss(tick_damage*multiplier*1.5) + L.clear_stamina_regen() //Rite of Spectral Manifestation: Summons a ghost on top of the rune as a cultist human with no items. User must stand on the rune at all times, and takes damage for each summoned ghost. /obj/effect/rune/manifest diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index b26069b08c47..06a6ba85244f 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -638,7 +638,7 @@ sight |= E.sight_flags if(!isnull(E.lighting_alpha)) lighting_alpha = E.lighting_alpha - + for(var/image/I in infra_images) if(client) client.images.Remove(I) @@ -1334,3 +1334,12 @@ our_splatter.blood_dna_info = get_blood_dna_list() var/turf/targ = get_ranged_target_turf(src, splatter_direction, splatter_strength) INVOKE_ASYNC(our_splatter, TYPE_PROC_REF(/obj/effect/decal/cleanable/blood/hitsplatter, fly_towards), targ, splatter_strength) + +/** + * Clears dynamic stamina regeneration on all limbs, typically used for continuous buildup like chems. + * + * Make sure it's used AFTER stamina damage is applied. + */ +/mob/living/carbon/clear_stamina_regen() + for(var/obj/item/bodypart/B in bodyparts) + B.stamina_cache = list() diff --git a/code/modules/mob/living/carbon/status_procs.dm b/code/modules/mob/living/carbon/status_procs.dm index fc4e2e24a953..d300115db56a 100644 --- a/code/modules/mob/living/carbon/status_procs.dm +++ b/code/modules/mob/living/carbon/status_procs.dm @@ -9,6 +9,7 @@ /mob/living/carbon/proc/enter_stamcrit() if(!(status_flags & CANKNOCKDOWN) || HAS_TRAIT(src, TRAIT_STUNIMMUNE)) return + clear_stamina_regen() // Can't passively regen out of stamcrit if(HAS_TRAIT_FROM(src, TRAIT_INCAPACITATED, STAMINA)) //Already in stamcrit return if(absorb_stun(0)) //continuous effect, so we don't want it to increment the stuns absorbed. diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 79935da5086a..32411d07a3f7 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -246,6 +246,9 @@ /mob/living/proc/setStaminaLoss(amount, updating_health = TRUE, forced = FALSE) return +/mob/living/proc/clear_stamina_regen() + return + // heal ONE external organ, organ gets randomly selected from damaged ones. /mob/living/proc/heal_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status) adjustBruteLoss(-brute, FALSE) //zero as argument for no instant health update diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm index 2666dd6db2d2..24d0c00d42f4 100644 --- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm @@ -1949,6 +1949,7 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/fanciulli/on_mob_metabolize(mob/living/M) if(M.health > 0) M.adjustStaminaLoss(20) + M.clear_stamina_regen() . = TRUE ..() @@ -1972,6 +1973,7 @@ All effects don't start immediately, but rather get worse over time; the rate is /datum/reagent/consumable/ethanol/branca_menta/on_mob_metabolize(mob/living/M) if(M.health > 0) M.adjustStaminaLoss(35) + M.clear_stamina_regen() . = TRUE ..() diff --git a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm index 2b1ddca8c90a..919f5e5dc776 100644 --- a/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/cat2_medicine_reagents.dm @@ -44,6 +44,7 @@ if(61 to 200) //you really can only go to 120 ooo_youaregettingsleepy = 2 M.adjustStaminaLoss(ooo_youaregettingsleepy * REM) + M.clear_stamina_regen() ..() . = TRUE @@ -55,6 +56,7 @@ to_chat(M,span_warning("You feel more tired than you usually do, perhaps if you rest your eyes for a bit...")) M.adjustStaminaLoss(-100, TRUE) M.Sleeping(10 SECONDS) + M.clear_stamina_regen() ..() . = TRUE @@ -156,6 +158,7 @@ /datum/reagent/medicine/c2/tirimol/on_mob_life(mob/living/carbon/human/M) M.adjustOxyLoss(-3 * REM) M.adjustStaminaLoss(2 * REM) + M.clear_stamina_regen() if(drowsycd && COOLDOWN_FINISHED(src, drowsycd)) M.adjust_drowsiness(20 SECONDS) COOLDOWN_START(src, drowsycd, 45 SECONDS) diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm index 714772b73545..95e0d12aa8c3 100644 --- a/code/modules/reagents/chemistry/reagents/food_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm @@ -343,6 +343,7 @@ M.emote("cough") M.adjustStaminaLoss(3) + M.clear_stamina_regen() ..() /datum/reagent/consumable/sodiumchloride diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 775bb016161e..9931b57c4fe2 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -1296,6 +1296,7 @@ if(prob(20)) M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1*REM, 50) M.adjustStaminaLoss(2.5*REM, 0) + M.clear_stamina_regen() ..() return TRUE @@ -1436,6 +1437,7 @@ if(41 to 80) M.adjustOxyLoss(0.1*REM, 0) M.adjustStaminaLoss(0.1*REM, 0) + M.clear_stamina_regen() M.adjust_jitter_up_to(1 SECONDS, 20 SECONDS) M.adjust_stutter_up_to(1 SECONDS, 20 SECONDS) M.adjust_dizzy(10) @@ -1449,10 +1451,12 @@ to_chat(M, "You feel too exhausted to continue!") // at this point you will eventually die unless you get charcoal M.adjustOxyLoss(0.1*REM, 0) M.adjustStaminaLoss(0.1*REM, 0) + M.clear_stamina_regen() if(82 to INFINITY) M.Sleeping(100, 0, TRUE) M.adjustOxyLoss(1.5*REM, 0) M.adjustStaminaLoss(1.5*REM, 0) + M.clear_stamina_regen() ..() return TRUE @@ -1897,4 +1901,3 @@ if(SEND_SIGNAL(M, COMSIG_HAS_NANITES)) SEND_SIGNAL(M, COMSIG_NANITE_ADJUST_VOLUME, nanite_reduction) return ..() - \ No newline at end of file diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index b81a2a1674ed..97c39c6462a9 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -635,7 +635,7 @@ color = "#5EFF3B" //RGB: 94, 255, 59 race = /datum/species/ethereal mutationtext = span_danger("The pain subsides. You feel... ecstatic.") - + /datum/reagent/mutationtoxin/preternis name = "Preternis Mutation Toxin" description = "A metallic precursor toxin." @@ -2081,6 +2081,7 @@ var/healthcomp = (100 - M.health) //DOES NOT ACCOUNT FOR ADMINBUS THINGS THAT MAKE YOU HAVE MORE THAN 200/210 HEALTH, OR SOMETHING OTHER THAN A HUMAN PROCESSING THIS. if(M.getStaminaLoss() < (45 - healthcomp)) //At 50 health you would have 200 - 150 health meaning 50 compensation. 60 - 50 = 10, so would only do 10-19 stamina.) M.adjustStaminaLoss(10) + M.clear_stamina_regen() if(prob(30)) to_chat(M, "You should sit down and take a rest...") ..() diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm index e158ded7cfc0..3af668423d77 100644 --- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm @@ -210,6 +210,7 @@ M.adjust_slurring(3 SECONDS) if(5 to 8) M.adjustStaminaLoss(40, 0) + M.clear_stamina_regen() if(9 to INFINITY) fakedeath_active = TRUE M.fakedeath(type) @@ -404,6 +405,7 @@ /datum/reagent/toxin/staminatoxin/on_mob_life(mob/living/carbon/M) M.adjustStaminaLoss(REM * data, 0) + M.clear_stamina_regen() data = max(data - 1, 3) ..() . = 1 @@ -676,6 +678,7 @@ if(current_cycle >= 10) M.Sleeping(40, 0) M.adjustStaminaLoss(10*REM, 0) + M.clear_stamina_regen() ..() return TRUE @@ -947,6 +950,7 @@ /datum/reagent/toxin/bonehurtingjuice/on_mob_life(mob/living/carbon/M) M.adjustStaminaLoss(7.5, 0) + M.clear_stamina_regen() if(HAS_TRAIT(M, TRAIT_CALCIUM_HEALER)) M.adjustBruteLoss(0.5, 0) if(prob(20)) @@ -1004,8 +1008,9 @@ /datum/reagent/toxin/ninjatoxin/on_mob_life(mob/living/carbon/M) M.adjustStaminaLoss(3) + M.clear_stamina_regen() ..() - + /datum/reagent/toxin/mushroom_powder name = "Mushroom Powder" description = "Finely ground polypore mushrooms, ready to be steeped in water to make mushroom tea." diff --git a/code/modules/research/nanites/nanite_programs/healing.dm b/code/modules/research/nanites/nanite_programs/healing.dm index b015d1695caa..b724fbc09006 100644 --- a/code/modules/research/nanites/nanite_programs/healing.dm +++ b/code/modules/research/nanites/nanite_programs/healing.dm @@ -28,6 +28,7 @@ host_mob.update_damage_overlays() if(C.getStaminaLoss() < 41) //Should just push you into the first slowdown stage before resetting after 10 seconds C.adjustStaminaLoss(1) //Annoying but not lethal, and won't stop stamina regen if you're over the limit + C.clear_stamina_regen() if(prob(5)) to_chat(C, "Your injuries itch and burn as they heal.") else @@ -185,10 +186,12 @@ host_mob.update_damage_overlays() if(C.getStaminaLoss() < 80) //Stops after hitting the second slowdown level. C.adjustStaminaLoss(5) //Hurts a lot more + C.clear_stamina_regen() else if(C.getBruteLoss() || C.getFireLoss()) //Prevents stamina regen if it's actively healing and you're over the limit. - C.adjustStaminaLoss(0.1) + C.adjustStaminaLoss(0.1) + C.clear_stamina_regen() if(prob(5)) - if(!C.getBruteLoss() && !C.getFireLoss()) + if(!C.getBruteLoss() && !C.getFireLoss()) to_chat(C, "You feel a searing pain across your body!")//Not actively healing, so nanites will start randomly replacing healthy tissue. Ouch! else to_chat(C, "Your wounds burn horribly as they heal!") diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 8b4cb90219c5..89b69f692bda 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -1,3 +1,4 @@ +#define STAMINA_REGENERATION_COEFFICIENT 0.65 // How effective stamina regeneration is, with 1 being 100% /obj/item/bodypart name = "limb" @@ -40,6 +41,8 @@ var/max_stamina_damage = 0 var/max_damage = 0 + var/stamina_cache = list() // Lists the times that we should clear stamina damage and for how much + var/brute_reduction = 0 //Subtracted to brute damage taken var/burn_reduction = 0 //Subtracted to burn damage taken @@ -201,9 +204,17 @@ return bodypart_organs //Return TRUE to get whatever mob this is in to update health. /obj/item/bodypart/proc/on_life(stam_regen) - if(stamina_dam > DAMAGE_PRECISION && stam_regen) //DO NOT update health here, it'll be done in the carbon's life. - heal_damage(0, 0, INFINITY, null, FALSE) - . |= BODYPART_LIFE_UPDATE_HEALTH + if(stamina_dam > DAMAGE_PRECISION) //DO NOT update health here, it'll be done in the carbon's life. + if(stam_regen) + heal_damage(0, 0, INFINITY, null, FALSE) + stamina_cache = list() + . |= BODYPART_LIFE_UPDATE_HEALTH + else + for(var/dam_instance in stamina_cache) + if(world.time > dam_instance["expiration"]) + heal_damage(0, 0, dam_instance["amount"] * STAMINA_REGENERATION_COEFFICIENT, null, FALSE) + stamina_cache -= list(dam_instance) + . |= BODYPART_LIFE_UPDATE_HEALTH //Applies brute and burn damage to the organ. Returns 1 if the damage-icon states changed at all. //Damage will not exceed max_damage using this proc @@ -316,6 +327,8 @@ owner.updatehealth() if(stamina > DAMAGE_PRECISION) owner.update_stamina() + if(!HAS_TRAIT_FROM(owner, TRAIT_INCAPACITATED, STAMINA)) + stamina_cache += list(list("expiration" = world.time + STAMINA_REGEN_BLOCK_TIME, "amount" = stamina)) owner.stam_regen_start_time = world.time + STAMINA_REGEN_BLOCK_TIME . = TRUE return update_bodypart_damage_state() || . @@ -382,7 +395,7 @@ if(HAS_TRAIT(owner, TRAIT_EASYDISMEMBER)) damage *= 1.1 - + // If we have an open surgery site here, wound more easily for(var/datum/surgery/S in owner.surgeries) if(S.operated_bodypart == src) @@ -465,7 +478,7 @@ if(H?.physiology?.armor?.wound)//if there is any innate wound armor (poly or genetics) armor_ablation += H.physiology.armor.getRating(WOUND) - + var/list/clothing = H.clothingonpart(src) for(var/c in clothing) var/obj/item/clothing/C = c diff --git a/yogstation/code/datums/martial/explosive_fist.dm b/yogstation/code/datums/martial/explosive_fist.dm index cf9b49b224e6..649da6e3e952 100644 --- a/yogstation/code/datums/martial/explosive_fist.dm +++ b/yogstation/code/datums/martial/explosive_fist.dm @@ -4,11 +4,11 @@ #define ALMOST_DETONATE_COMBO "PD" //Sets streak to "Q" #define PRE_DETONATE_COMBO "HH" //Sets streak to "P" -#define LIFEFORCE_TRADE_COMBO "MG" +#define LIFEFORCE_TRADE_COMBO "MG" #define ALMOST_LIFEFORCE_TRADE_COMBO "LD" //Sets streak to "M" #define PRE_LIFEFORCE_TRADE_COMBO "DG" //Sets streak to "L" -#define IMMOLATE_COMBO "JG" +#define IMMOLATE_COMBO "JG" #define ALMOST_IMMOLATE_COMBO "ID" //Sets streak to "J" #define PRE_IMMOLATE_COMBO "DH" //Sets strak to "I" @@ -64,13 +64,13 @@ if(!can_use(A)) return if(findtext(streak, EXPLOSIVE_DISARM_COMBO)) - streak = "" + streak = "" explosive_disarm(A,D) return TRUE if(findtext(streak, DETONATE_COMBO)) // End Detonate Chain streak = "" detonate(A,D) - return TRUE + return TRUE if(findtext(streak, ALMOST_DETONATE_COMBO)) streak = "Q" //Q comes after P almost_detonate(A,D) @@ -163,7 +163,7 @@ D.apply_damage(damage_to_deal + 10, STAMINA, selected_zone, armor_block) //Always does at least 10 D.visible_message(span_danger("[A] activates [D]!"), \ - span_userdanger("[A] activates you!")) + span_userdanger("[A] activates you!")) log_combat(A, D, "activates(Explosive Fist)") D.adjust_fire_stacks(4) @@ -261,11 +261,11 @@ var/obj/item/bodypart/affecting_p = A.get_bodypart(BODY_ZONE_HEAD) var/brute_block_p = A.run_armor_check(affecting_p, MELEE) var/burn_block_p = A.run_armor_check(affecting_p, BOMB) - A.apply_damage(5, BRUTE, BODY_ZONE_HEAD, brute_block_p) - A.apply_damage(5, BURN, BODY_ZONE_HEAD, burn_block_p) + A.apply_damage(5, BRUTE, BODY_ZONE_HEAD, brute_block_p) + A.apply_damage(5, BURN, BODY_ZONE_HEAD, burn_block_p) D.visible_message(span_danger("[A] headbutts [D]!"), \ - span_userdanger("[A] headbutts you!")) + span_userdanger("[A] headbutts you!")) log_combat(A, D, "headbutts(Explosive Fist)") streak = "" else @@ -274,7 +274,7 @@ if(!(A.pulling == D)) D.grabbedby(A, 1) D.visible_message(span_danger("[A] violently grabs [D]'s neck!"), \ - span_userdanger("[A] violently grabs your neck!")) + span_userdanger("[A] violently grabs your neck!")) log_combat(A, D, "grabs by the neck(Explosive Fist)") playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, TRUE, -1) streak = "" @@ -321,7 +321,7 @@ D.apply_damage(A.get_punchdamagehigh() * 2 + 6, BURN, selected_zone, armor_block) //20 burn (vs bomb armor) D.visible_message(span_danger("[A] burns [D]!"), \ - span_userdanger("[A] burns you!")) + span_userdanger("[A] burns you!")) log_combat(A, D, "burns(Explosive Fist)") return TRUE @@ -349,9 +349,9 @@ if(A.get_item_by_slot(ITEM_SLOT_HEAD)) //No helmets??? streak = "" return FALSE - else + else for(var/mob/living/target in view_or_range(2, A, "range")) - if(target == A) + if(target == A) continue target.adjustFireLoss(30) target.ignite_mob() @@ -361,7 +361,7 @@ var/obj/item/bodypart/hed = D.get_bodypart(BODY_ZONE_HEAD) var/armor_block = D.run_armor_check(hed, BOMB) D.apply_damage(A.get_punchdamagehigh() + 3, BURN, BODY_ZONE_HEAD, armor_block) //10 burn (vs bomb armor) - D.emote("scream") + D.emote("scream") D.blur_eyes(4) A.apply_damage(10, BURN, BODY_ZONE_CHEST, 0) //Take some unblockable damage since you're using your inner flame or something