From 2bcbb36ab9adb7d91c4c55df992ae79add76a893 Mon Sep 17 00:00:00 2001 From: SkyratBot <59378654+SkyratBot@users.noreply.github.com> Date: Tue, 5 Sep 2023 19:24:22 +0200 Subject: [PATCH] [MIRROR] [TEST-MERGE FIRST] Allows all limbs to be dismembered and significantly refactors wounds [MDB IGNORE] (#23407) * [TEST-MERGE FIRST] Allows all limbs to be dismembered and significantly refactors wounds * ah fuck it * test * edaawdawd * Revert "edaawdawd" This reverts commit 47be710fe61a1f4ca79212b29b3e88bf05ec9a3a. * nothing but sheer hatred * freaawd * dzfxg * Fixing some diffs here while we are at it. * These are deprecated and should be removed --------- Co-authored-by: nikothedude <59709059+nikothedude@users.noreply.github.com> Co-authored-by: nikothedude Co-authored-by: Giz <13398309+vinylspiders@users.noreply.github.com> --- code/__DEFINES/dcs/signals/signals_reagent.dm | 2 + code/__DEFINES/wounds.dm | 115 ++- code/__DEFINES/~skyrat_defines/combat.dm | 12 +- code/__DEFINES/~skyrat_defines/wounds.dm | 5 + code/datums/components/butchering.dm | 5 +- code/datums/components/embedded.dm | 2 +- code/datums/elements/kneecapping.dm | 4 +- code/datums/mutations/hulk.dm | 6 +- code/datums/status_effects/debuffs/choke.dm | 2 +- code/datums/status_effects/debuffs/cursed.dm | 4 +- code/datums/status_effects/wound_effects.dm | 30 +- code/datums/wounds/_wound_static_data.dm | 136 +++ code/datums/wounds/_wounds.dm | 211 ++-- code/datums/wounds/blunt.dm | 4 + code/datums/wounds/bones.dm | 199 ++-- code/datums/wounds/burns.dm | 105 +- code/datums/wounds/loss.dm | 71 +- code/datums/wounds/pierce.dm | 95 +- code/datums/wounds/scars/_scars.dm | 57 +- code/datums/wounds/scars/_static_scar_data.dm | 20 + code/datums/wounds/slash.dm | 148 ++- code/game/atoms.dm | 1 + code/game/machinery/iv_drip.dm | 2 +- code/game/objects/items/devices/flashlight.dm | 2 +- code/game/objects/items/stacks/medical.dm | 4 +- code/game/objects/items/teleportation.dm | 3 +- code/modules/admin/smites/bloodless.dm | 6 +- code/modules/admin/smites/boneless.dm | 10 +- .../heretic/knowledge/flesh_lore.dm | 2 +- .../antagonists/heretic/magic/blood_cleave.dm | 6 +- .../heretic/status_effects/mark_effects.dm | 2 +- .../traitor/objectives/eyesnatching.dm | 4 +- .../mapfluff/ruins/spaceruin_code/meateor.dm | 2 +- code/modules/mob/living/carbon/carbon.dm | 15 +- .../mob/living/carbon/carbon_defense.dm | 4 +- .../mob/living/carbon/carbon_defines.dm | 3 + code/modules/mob/living/carbon/examine.dm | 2 +- .../mob/living/carbon/human/_species.dm | 10 +- .../mob/living/carbon/human/human_defense.dm | 6 +- .../mob/living/carbon/human/human_helpers.dm | 6 +- .../carbon/human/species_types/abductors.dm | 2 + .../carbon/human/species_types/golems.dm | 3 +- .../human/species_types/shadowpeople.dm | 2 + code/modules/mob/living/life.dm | 4 +- code/modules/paperwork/paper_cutter.dm | 2 +- .../religion/festival/instrument_rites.dm | 2 +- .../religion/sparring/sparring_datum.dm | 2 +- .../spells/spell_types/touch/scream_for_me.dm | 4 +- code/modules/surgery/bodyparts/_bodyparts.dm | 184 ++-- .../surgery/bodyparts/dismemberment.dm | 52 +- code/modules/surgery/bodyparts/head.dm | 7 +- code/modules/surgery/bodyparts/parts.dm | 4 + .../surgery/bodyparts/robot_bodyparts.dm | 28 + .../bodyparts/species_parts/misc_bodyparts.dm | 80 +- .../species_parts/plasmaman_bodyparts.dm | 8 +- code/modules/surgery/bodyparts/wounds.dm | 114 ++- code/modules/surgery/bone_mending.dm | 4 +- code/modules/surgery/burn_dressing.dm | 16 +- code/modules/surgery/repair_puncture.dm | 12 +- code/modules/unit_tests/medical_wounds.dm | 22 +- code/modules/vehicles/cars/clowncar.dm | 4 +- code/modules/vending/_vending.dm | 8 +- .../code/roundstartslime_bodyparts.dm | 12 +- .../contractor/code/datums/contract.dm | 4 +- .../modules/customization/readme.md | 2 - .../modules/hev_suit/code/hev_suit.dm | 67 +- .../modules/medical/code/bodypart.dm | 11 - .../modules/medical/code/bodypart_aid.dm | 227 ----- .../modules/medical/code/carbon_examine.dm | 6 +- .../medical/code/carbon_update_icons.dm | 14 +- .../code/{carbon_defense.dm => grasp.dm} | 0 .../modules/medical/code/medical_stacks.dm | 65 -- .../modules/medical/code/wounds/bleed.dm | 19 + .../modules/medical/code/wounds/bones.dm | 455 --------- .../modules/medical/code/wounds/burns.dm | 311 ------ .../modules/medical/code/wounds/medical.dm | 147 +++ .../modules/medical/code/wounds/muscle.dm | 91 +- .../modules/medical/code/wounds/pierce.dm | 198 ---- .../modules/medical/code/wounds/slash.dm | 324 ------- .../modules/mutants/code/mutant_component.dm | 2 +- .../robohand/code/bodypart_autosurgeon.dm | 1 - sound/attributions.txt | 1 - tgstation.dme | 15 +- .../flakyTestPayloads/monkey_business.txt | 912 +++++++++--------- 84 files changed, 1974 insertions(+), 2797 deletions(-) create mode 100644 code/__DEFINES/~skyrat_defines/wounds.dm create mode 100644 code/datums/wounds/_wound_static_data.dm create mode 100644 code/datums/wounds/blunt.dm create mode 100644 code/datums/wounds/scars/_static_scar_data.dm delete mode 100644 modular_skyrat/modules/medical/code/bodypart.dm delete mode 100644 modular_skyrat/modules/medical/code/bodypart_aid.dm rename modular_skyrat/modules/medical/code/{carbon_defense.dm => grasp.dm} (100%) delete mode 100644 modular_skyrat/modules/medical/code/medical_stacks.dm create mode 100644 modular_skyrat/modules/medical/code/wounds/bleed.dm delete mode 100644 modular_skyrat/modules/medical/code/wounds/bones.dm delete mode 100644 modular_skyrat/modules/medical/code/wounds/burns.dm create mode 100644 modular_skyrat/modules/medical/code/wounds/medical.dm delete mode 100644 modular_skyrat/modules/medical/code/wounds/pierce.dm delete mode 100644 modular_skyrat/modules/medical/code/wounds/slash.dm diff --git a/code/__DEFINES/dcs/signals/signals_reagent.dm b/code/__DEFINES/dcs/signals/signals_reagent.dm index 00fdddc6c9e..a73d59a234c 100644 --- a/code/__DEFINES/dcs/signals/signals_reagent.dm +++ b/code/__DEFINES/dcs/signals/signals_reagent.dm @@ -6,6 +6,8 @@ #define COMSIG_ATOM_EXPOSE_REAGENTS "atom_expose_reagents" /// Prevents the atom from being exposed to reagents if returned on [COMSIG_ATOM_EXPOSE_REAGENTS] #define COMPONENT_NO_EXPOSE_REAGENTS (1<<0) +///from base of atom/expose_reagents(): (/list, /datum/reagents, methods, volume_modifier, show_message) +#define COMSIG_ATOM_AFTER_EXPOSE_REAGENTS "atom_after_expose_reagents" ///from base of [/datum/reagent/proc/expose_atom]: (/datum/reagent, reac_volume) #define COMSIG_ATOM_EXPOSE_REAGENT "atom_expose_reagent" ///from base of [/datum/reagent/proc/expose_atom]: (/atom, reac_volume) diff --git a/code/__DEFINES/wounds.dm b/code/__DEFINES/wounds.dm index 0a020b2b5a8..5529ee1f0c6 100644 --- a/code/__DEFINES/wounds.dm +++ b/code/__DEFINES/wounds.dm @@ -32,11 +32,6 @@ #define WOUND_PIERCE 3 /// any concentrated burn attack (lasers really). rolls for burning wounds #define WOUND_BURN 4 -//SKYRAT EDIT ADDITION BEGIN - MEDICAL -/// any brute attacks, rolled on a chance -#define WOUND_MUSCLE 5 -//SKYRAT EDIT ADDITION END - // ~determination second wind defines // How much determination reagent to add each time someone gains a new wound in [/datum/wound/proc/second_wind] @@ -50,36 +45,57 @@ /// While someone has determination in their system, their bleed rate is slightly reduced #define WOUND_DETERMINATION_BLEED_MOD 0.85 -// ~wound global lists -// list in order of highest severity to lowest -GLOBAL_LIST_INIT(global_wound_types, list( - WOUND_BLUNT = list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate), - WOUND_SLASH = list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate), - WOUND_PIERCE = list(/datum/wound/pierce/critical, /datum/wound/pierce/severe, /datum/wound/pierce/moderate), - WOUND_BURN = list(/datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate), - WOUND_MUSCLE = list(/datum/wound/muscle/severe, /datum/wound/muscle/moderate), /* SKYRAT EDIT ADD */ -)) - -// every single type of wound that can be rolled naturally, in case you need to pull a random one -GLOBAL_LIST_INIT(global_all_wound_types, list( - /datum/wound/blunt/critical, - /datum/wound/blunt/severe, - /datum/wound/blunt/moderate, - /datum/wound/slash/critical, - /datum/wound/slash/severe, - /datum/wound/slash/moderate, - /datum/wound/pierce/critical, - /datum/wound/pierce/severe, - /datum/wound/pierce/moderate, - /datum/wound/burn/critical, - /datum/wound/burn/severe, - /datum/wound/burn/moderate, - /* SKYRAT EDIT ADD START */ - /datum/wound/muscle/severe, - /datum/wound/muscle/moderate, - /* SKYRAT EDIT ADD END */ +// ~biology defines +// What kind of biology a limb has, and what wounds it can suffer +/// Has absolutely fucking nothing, no wounds +#define BIO_INORGANIC NONE +/// Has bone - allows the victim to suffer T2-T3 bone blunt wounds +#define BIO_BONE (1<<0) +/// Has flesh - allows the victim to suffer fleshy slash pierce and burn wounds +#define BIO_FLESH (1<<1) +/// Self explanatory +#define BIO_FLESH_BONE (BIO_BONE | BIO_FLESH) +/// Has metal - allows the victim to suffer robotic blunt and burn wounds +#define BIO_METAL (1<<2) +/// Is wired internally - allows the victim to suffer electrical wounds (robotic T1-T3 slash/pierce) +#define BIO_WIRED (1<<3) +/// Robotic: shit like cyborg limbs, mostly +#define BIO_ROBOTIC (BIO_METAL|BIO_WIRED) +/// Has bloodflow - can suffer bleeding wounds and can bleed +#define BIO_BLOODED (1<<4) +/// Is connected by a joint - can suffer T1 bone blunt wounds (dislocation) +#define BIO_JOINTED (1<<5) +/// Standard humanoid - can suffer all flesh wounds, such as: T1-3 slash/pierce/burn/blunt. Can also bleed +#define BIO_STANDARD (BIO_FLESH_BONE|BIO_BLOODED) + +// "Where" a specific "bio" feature is within a given limb +// Exterior is hard shit, the last line, shit lines bones +// Interior is soft shit, targetted by slashes and pierces (usually), protects exterior +// Yes, it makes no sense +/// The given biostate is on the "exterior" of the limb - hard shit, protected by interior +#define BIO_EXTERIOR (1<<0) +/// The given biostate is on the "exterior" of the limb - soft shit, protects exterior +#define BIO_INTERIOR (1<<1) +#define BIO_EXTERIOR_AND_INTERIOR (BIO_EXTERIOR|BIO_INTERIOR) + +GLOBAL_LIST_INIT(bio_state_states, list( + "[BIO_WIRED]" = BIO_INTERIOR, + "[BIO_METAL]" = BIO_EXTERIOR, + "[BIO_FLESH]" = BIO_INTERIOR, + "[BIO_BONE]" = BIO_EXTERIOR, )) +// Wound series +// A "wound series" is just a family of wounds that logically follow eachother +// Multiple wounds in a single series cannot be on a limb - the highest severity will always be prioritized, and lower ones will be skipped +/// T1-T3 Bleeding slash wounds. Requires flesh. Can cause bleeding, but doesn't require it. From: slash.dm +#define WOUND_SERIES_FLESH_SLASH_BLEED 1 +/// T1-T3 Basic blunt wounds. T1 requires jointed, but 2-3 require bone. From: bone.dm +#define WOUND_SERIES_BONE_BLUNT_BASIC 2 +/// T1-T3 Basic burn wounds. Requires flesh. From: burns.dm +#define WOUND_SERIES_FLESH_BURN_BASIC 3 +/// T1-3 Bleeding puncture wounds. Requires flesh. Can cause bleeding, but doesn't require it. From: pierce.dm +#define WOUND_SERIES_FLESH_PUNCTURE_BLEED 4 // ~burn wound infection defines // Thresholds for infection for burn wounds, once infestation hits each threshold, things get steadily worse @@ -116,34 +132,13 @@ GLOBAL_LIST_INIT(global_all_wound_types, list( #define BODYPART_MANGLED_FLESH (1<<1) #define BODYPART_MANGLED_BOTH (BODYPART_MANGLED_BONE | BODYPART_MANGLED_FLESH) - -// ~biology defines -// What kind of biology a limb has, and what wounds it can suffer -/// golems and androids, cannot suffer any wounds -#define BIO_INORGANIC NONE -/// skeletons and plasmemes, can only suffer bone wounds, only needs mangled bone to be able to dismember -#define BIO_BONE (1<<0) -/// nothing right now, maybe slimepeople in the future, can only suffer slashing, piercing, and burn wounds -#define BIO_FLESH (1<<1) -/// standard humanoids, can suffer all wounds, needs mangled bone and flesh to dismember. conveniently, what you get when you combine BIO_BONE and BIO_FLESH -#define BIO_FLESH_BONE (BIO_BONE | BIO_FLESH) - - // ~wound flag defines -/// If this wound requires having the BIO_FLESH biological_state on the limb -#define FLESH_WOUND (1<<0) -/// If this wound requires having the BIO_BONE biological_state on the limb -#define BONE_WOUND (1<<1) /// If having this wound counts as mangled flesh for dismemberment -#define MANGLES_FLESH (1<<2) +#define MANGLES_FLESH (1<<0) /// If having this wound counts as mangled bone for dismemberment -#define MANGLES_BONE (1<<3) +#define MANGLES_BONE (1<<1) /// If this wound marks the limb as being allowed to have gauze applied -#define ACCEPTS_GAUZE (1<<4) -//SKYRAT EDIT ADDITION BEGIN - MEDICAL -/// If this wound marks the limb as being allowed to have gauze applied as a splint -#define ACCEPTS_SPLINT (1<<5) -//SKYRAT EDIT ADDITION END +#define ACCEPTS_GAUZE (1<<2) // ~scar persistence defines // The following are the order placements for persistent scar save formats @@ -161,11 +156,13 @@ GLOBAL_LIST_INIT(global_all_wound_types, list( #define SCAR_SAVE_BIOLOGY 6 /// Which character slot this was saved to #define SCAR_SAVE_CHAR_SLOT 7 +/// if the scar will check for any or all biostates on the limb (defaults to FALSE, so all) +#define SCAR_SAVE_CHECK_ANY_BIO 8 ///how many fields we save for each scar (so the number of above fields) -#define SCAR_SAVE_LENGTH 7 +#define SCAR_SAVE_LENGTH 8 /// saved scars with a version lower than this will be discarded, increment when you update the persistent scarring format in a way that invalidates previous saved scars (new fields, reordering, etc) -#define SCAR_CURRENT_VERSION 3 +#define SCAR_CURRENT_VERSION 4 /// how many scar slots, per character slot, we have to cycle through for persistent scarring, if enabled in character prefs #define PERSISTENT_SCAR_SLOTS 3 diff --git a/code/__DEFINES/~skyrat_defines/combat.dm b/code/__DEFINES/~skyrat_defines/combat.dm index 6ce9519992c..54659715cc3 100644 --- a/code/__DEFINES/~skyrat_defines/combat.dm +++ b/code/__DEFINES/~skyrat_defines/combat.dm @@ -173,6 +173,16 @@ /// Attempts to perform a limb dislocation, with the user violently twisting one of target's limbs (as passed in). Only useful for extremities, because only extremities can eat dislocations. /datum/species/proc/try_dislocate(mob/living/carbon/human/user, mob/living/carbon/human/target, obj/item/bodypart/affecting) + var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[/datum/wound/blunt/bone/moderate] + if (!pregen_data) + stack_trace("/datum/wound/blunt/bone/moderate has no pregen data!") + return FALSE // shouldnt happen but sanity + + if (!pregen_data.can_be_applied_to(affecting, random_roll = FALSE)) + if (!(affecting.biological_state & BIO_JOINTED)) + to_chat(user, span_warning("[target]'s [affecting.plaintext_zone] has no joint to dislocate!")) + return FALSE + user.changeNext_move(4 SECONDS) target.visible_message(span_danger("[user.name] twists [target.name]'s [affecting.name] violently!"), \ span_userdanger("[user.name] twists your [affecting.name] violently!"), ignored_mobs=user) @@ -182,7 +192,7 @@ target.visible_message(span_danger("[user.name] dislocates [target.name]'s [affecting.name]!"), \ span_userdanger("[user.name] dislocates your [affecting.name]!"), ignored_mobs=user) to_chat(user, span_danger("You dislocate [target.name]'s [affecting.name]!")) - affecting.force_wound_upwards(/datum/wound/blunt/moderate) + affecting.force_wound_upwards(/datum/wound/blunt/bone/moderate) log_combat(user, target, "dislocates", "the [affecting.name]") return TRUE diff --git a/code/__DEFINES/~skyrat_defines/wounds.dm b/code/__DEFINES/~skyrat_defines/wounds.dm new file mode 100644 index 00000000000..4c29cd6a642 --- /dev/null +++ b/code/__DEFINES/~skyrat_defines/wounds.dm @@ -0,0 +1,5 @@ +/// See muscle.dm +#define WOUND_SERIES_MUSCLE_DAMAGE 10000 // We use a super high number as realistically speaking TG will never increment to this amount of wound series + +/// If this wound, when bandaged, will cause a splint overlay to generate rather than a bandage overlay. +#define SPLINT_OVERLAY (1<<200) // we use a big number since tg realistically wouldnt go to it diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm index 6aa4555f3aa..3a360c012f6 100644 --- a/code/datums/components/butchering.dm +++ b/code/datums/components/butchering.dm @@ -92,8 +92,9 @@ H.apply_damage(source.force, BRUTE, BODY_ZONE_HEAD, wound_bonus=CANT_WOUND) // easy tiger, we'll get to that in a sec var/obj/item/bodypart/slit_throat = H.get_bodypart(BODY_ZONE_HEAD) if(slit_throat) - var/datum/wound/slash/critical/screaming_through_a_slit_throat = new - screaming_through_a_slit_throat.apply_wound(slit_throat, wound_source = "throat slit") + var/datum/wound/slash/flesh/critical/screaming_through_a_slit_throat = new + if (!screaming_through_a_slit_throat.apply_wound(slit_throat, wound_source = "throat slit")) + qdel(screaming_through_a_slit_throat) H.apply_status_effect(/datum/status_effect/neck_slice) /** diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm index 8abb32e0e53..433784e845e 100644 --- a/code/datums/components/embedded.dm +++ b/code/datums/components/embedded.dm @@ -303,7 +303,7 @@ return var/damage = weapon.w_class * remove_pain_mult limb.receive_damage(brute=(1-pain_stam_pct) * damage * 1.5, sharpness=SHARP_EDGED) // Performs exit wounds and flings the user to the caster if nearby - limb.force_wound_upwards(/datum/wound/pierce/moderate) + limb.force_wound_upwards(/datum/wound/pierce/bleed/moderate) victim.adjustStaminaLoss(pain_stam_pct * damage) playsound(get_turf(victim), 'sound/effects/wounds/blood2.ogg', 50, TRUE) diff --git a/code/datums/elements/kneecapping.dm b/code/datums/elements/kneecapping.dm index f652a196323..217c11d4361 100644 --- a/code/datums/elements/kneecapping.dm +++ b/code/datums/elements/kneecapping.dm @@ -80,8 +80,8 @@ if(do_after(attacker, 3 SECONDS, target, interaction_key = weapon)) attacker.visible_message(span_warning("[attacker] swings [attacker.p_their()] [weapon] at [target]'s kneecaps!"), span_danger("You swing \the [weapon] at [target]'s kneecaps!")) - var/datum/wound/blunt/severe/severe_wound_type = /datum/wound/blunt/severe - var/datum/wound/blunt/critical/critical_wound_type = /datum/wound/blunt/critical + var/datum/wound/blunt/bone/severe/severe_wound_type = /datum/wound/blunt/bone/severe + var/datum/wound/blunt/bone/critical/critical_wound_type = /datum/wound/blunt/bone/critical leg.receive_damage(brute = weapon.force, wound_bonus = rand(initial(severe_wound_type.threshold_minimum), initial(critical_wound_type.threshold_minimum) + 10), damage_source = "kneecapping") target.emote("scream") log_combat(attacker, target, "broke the kneecaps of", weapon) diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm index 0de7daa6589..28b88c246e3 100644 --- a/code/datums/mutations/hulk.dm +++ b/code/datums/mutations/hulk.dm @@ -65,11 +65,11 @@ /datum/mutation/human/hulk/proc/break_an_arm(obj/item/bodypart/arm) switch(arm.brute_dam) if(45 to 50) - arm.force_wound_upwards(/datum/wound/blunt/critical, wound_source = "hulk smashing") + arm.force_wound_upwards(/datum/wound/blunt/bone/critical, wound_source = "hulk smashing") if(41 to 45) - arm.force_wound_upwards(/datum/wound/blunt/severe, wound_source = "hulk smashing") + arm.force_wound_upwards(/datum/wound/blunt/bone/severe, wound_source = "hulk smashing") if(35 to 41) - arm.force_wound_upwards(/datum/wound/blunt/moderate, wound_source = "hulk smashing") + arm.force_wound_upwards(/datum/wound/blunt/bone/moderate, wound_source = "hulk smashing") /datum/mutation/human/hulk/on_life(seconds_per_tick, times_fired) if(owner.health < owner.crit_threshold) diff --git a/code/datums/status_effects/debuffs/choke.dm b/code/datums/status_effects/debuffs/choke.dm index 4fb668b5fe0..f626cb52be5 100644 --- a/code/datums/status_effects/debuffs/choke.dm +++ b/code/datums/status_effects/debuffs/choke.dm @@ -216,7 +216,7 @@ var/mob/living/carbon/carbon_victim = victim var/obj/item/bodypart/chest = carbon_victim.get_bodypart(BODY_ZONE_CHEST) if(chest) - chest.force_wound_upwards(/datum/wound/blunt/severe, wound_source = "human force to the chest") + chest.force_wound_upwards(/datum/wound/blunt/bone/severe, wound_source = "human force to the chest") playsound(owner, 'sound/creatures/crack_vomit.ogg', 120, extrarange = 5, falloff_exponent = 4) vomit_up() diff --git a/code/datums/status_effects/debuffs/cursed.dm b/code/datums/status_effects/debuffs/cursed.dm index 20afa8a7ea6..285fb86348e 100644 --- a/code/datums/status_effects/debuffs/cursed.dm +++ b/code/datums/status_effects/debuffs/cursed.dm @@ -66,7 +66,7 @@ playsound(human_owner, SFX_SEAR, 50, TRUE) var/obj/item/bodypart/affecting = human_owner.get_active_hand() branded_hand = affecting - affecting.force_wound_upwards(/datum/wound/burn/severe/cursed_brand, wound_source = "curse of the slot machine") + affecting.force_wound_upwards(/datum/wound/burn/flesh/severe/cursed_brand, wound_source = "curse of the slot machine") messages += span_boldwarning("Your hand burns, and you quickly let go of the lever! You feel a little sick as the nerves deaden in your hand...") messages += span_boldwarning("Some smoke appears to be coming out of your hand now, but it's not too bad...") @@ -116,7 +116,7 @@ SIGNAL_HANDLER if(!isnull(branded_hand)) - var/datum/wound/brand = branded_hand.get_wound_type(/datum/wound/burn/severe/cursed_brand) + var/datum/wound/brand = branded_hand.get_wound_type(/datum/wound/burn/flesh/severe/cursed_brand) brand?.remove_wound() owner.visible_message( diff --git a/code/datums/status_effects/wound_effects.dm b/code/datums/status_effects/wound_effects.dm index dfee1c2ee2c..5da74ef7722 100644 --- a/code/datums/status_effects/wound_effects.dm +++ b/code/datums/status_effects/wound_effects.dm @@ -167,20 +167,20 @@ // bones -/datum/status_effect/wound/blunt +/datum/status_effect/wound/blunt/bone -/datum/status_effect/wound/blunt/on_apply() +/datum/status_effect/wound/blunt/bone/on_apply() . = ..() RegisterSignal(owner, COMSIG_MOB_SWAP_HANDS, PROC_REF(on_swap_hands)) on_swap_hands() -/datum/status_effect/wound/blunt/on_remove() +/datum/status_effect/wound/blunt/bone/on_remove() . = ..() UnregisterSignal(owner, COMSIG_MOB_SWAP_HANDS) var/mob/living/carbon/wound_owner = owner wound_owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/blunt_wound) -/datum/status_effect/wound/blunt/proc/on_swap_hands() +/datum/status_effect/wound/blunt/bone/proc/on_swap_hands() SIGNAL_HANDLER var/mob/living/carbon/wound_owner = owner @@ -189,7 +189,7 @@ else wound_owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/blunt_wound) -/datum/status_effect/wound/blunt/nextmove_modifier() +/datum/status_effect/wound/blunt/bone/nextmove_modifier() var/mob/living/carbon/C = owner if(C.get_active_hand() == linked_limb) @@ -198,18 +198,20 @@ return 1 // blunt -/datum/status_effect/wound/blunt/moderate +/datum/status_effect/wound/blunt/bone/moderate id = "disjoint" -/datum/status_effect/wound/blunt/severe +/datum/status_effect/wound/blunt/bone/severe id = "hairline" -/datum/status_effect/wound/blunt/critical +/datum/status_effect/wound/blunt/bone/critical id = "compound" + // slash -/datum/status_effect/wound/slash/moderate + +/datum/status_effect/wound/slash/flesh/moderate id = "abrasion" -/datum/status_effect/wound/slash/severe +/datum/status_effect/wound/slash/flesh/severe id = "laceration" -/datum/status_effect/wound/slash/critical +/datum/status_effect/wound/slash/flesh/critical id = "avulsion" // pierce /datum/status_effect/wound/pierce/moderate @@ -219,9 +221,9 @@ /datum/status_effect/wound/pierce/critical id = "rupture" // burns -/datum/status_effect/wound/burn/moderate +/datum/status_effect/wound/burn/flesh/moderate id = "seconddeg" -/datum/status_effect/wound/burn/severe +/datum/status_effect/wound/burn/flesh/severe id = "thirddeg" -/datum/status_effect/wound/burn/critical +/datum/status_effect/wound/burn/flesh/critical id = "fourthdeg" diff --git a/code/datums/wounds/_wound_static_data.dm b/code/datums/wounds/_wound_static_data.dm new file mode 100644 index 00000000000..4d28e80a910 --- /dev/null +++ b/code/datums/wounds/_wound_static_data.dm @@ -0,0 +1,136 @@ +// This datum is merely a singleton instance that allows for custom "can be applied" behaviors without instantiating a wound instance. +// For example: You can make a pregen_data subtype for your wound that overrides can_be_applied_to to only apply to specifically slimeperson limbs. +// Without this, youre stuck with very static initial variables. + +GLOBAL_LIST_INIT_TYPED(all_wound_pregen_data, /datum/wound_pregen_data, generate_wound_static_data()) + +/proc/generate_wound_static_data() + RETURN_TYPE(/list/datum/wound_pregen_data) + + var/list/datum/wound_pregen_data/data = list() + + for (var/datum/wound_pregen_data/path as anything in typecacheof(path = /datum/wound_pregen_data, ignore_root_path = TRUE)) + if (initial(path.abstract)) + continue + + if (!isnull(data[initial(path.wound_path_to_generate)])) + stack_trace("pre-existing pregen data for [initial(path.wound_path_to_generate)] when [path] was being considered: [data[initial(path.wound_path_to_generate)]]. \ + this is definitely a bug, and is probably because one of the two pregen data have the wrong wound typepath defined. [path] will not be instantiated") + + continue + + var/datum/wound_pregen_data/pregen_data = new path + data[pregen_data.wound_path_to_generate] = pregen_data + + return data + +/// A singleton datum that holds pre-gen and static data about a wound. Each wound datum should have a corresponding wound_pregen_data. +/datum/wound_pregen_data + /// The typepath of the wound we will be handling and storing data of. NECESSARY IF THIS IS A NON-ABSTRACT TYPE! + var/datum/wound/wound_path_to_generate + + /// Will this be instantiated? + var/abstract = FALSE + + /// If true, our wound can be selected in ordinary wound rolling. If this is set to false, our wound can only be directly instantiated by use of specific typepath. + var/can_be_randomly_generated = TRUE + + /// A list of biostates a limb must have to receive our wound, in wounds.dm. + var/required_limb_biostate + /// If false, we will check if the limb has all of our required biostates instead of just any. + var/check_for_any = FALSE + + /// If false, we will iterate through wounds on a given limb, and if any match our type, we wont add our wound. + var/duplicates_allowed = FALSE + + /// If we require BIO_BLOODED, we will not add our wound if this is true and the limb cannot bleed. + var/ignore_cannot_bleed = TRUE // a lot of bleed wounds should still be applied for purposes of mangling flesh + + /// A list of bodyzones we are applicable to. + var/list/viable_zones = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + +/datum/wound_pregen_data/New() + . = ..() + + if (!abstract) + if (required_limb_biostate == null) + stack_trace("required_limb_biostate null - please set it! occured on: [src.type]") + if (wound_path_to_generate == null) + stack_trace("wound_path_to_generate null - please set it! occured on: [src.type]") + +// this proc is the primary reason this datum exists - a singleton instance so we can always run this proc even without the wound existing +/** + * Args: + * * obj/item/bodypart/limb: The limb we are considering. + * * wound_type: The type of the "wound acquisition attempt". Example: A slashing attack cannot proc a blunt wound, so wound_type = WOUND_SLASH would + * fail if we expect WOUND_BLUNT. Defaults to the wound type we expect. + * * datum/wound/old_wound: If we would replace a wound, this would be said wound. Nullable. + * * random_roll = FALSE: If this is in the context of a random wound generation, and this wound wasn't specifically checked. + * + * Returns: + * FALSE if the limb cannot be wounded, if wound_type is not ours, if we have a higher severity wound already in our series, + * if we have a biotype mismatch, if the limb isnt in a viable zone, or if theres any duplicate wound types. + * TRUE otherwise. + */ +/datum/wound_pregen_data/proc/can_be_applied_to(obj/item/bodypart/limb, wound_type = initial(wound_path_to_generate.wound_type), datum/wound/old_wound, random_roll = FALSE) + SHOULD_BE_PURE(TRUE) + + if (!istype(limb) || !limb.owner) + return FALSE + + if (random_roll && !can_be_randomly_generated) + return FALSE + + if (HAS_TRAIT(limb.owner, TRAIT_NEVER_WOUNDED) || (limb.owner.status_flags & GODMODE)) + return FALSE + + if (wound_type != initial(wound_path_to_generate.wound_type)) + return + else + for (var/datum/wound/preexisting_wound as anything in limb.wounds) + if (preexisting_wound.wound_series == initial(wound_path_to_generate.wound_series)) + if (preexisting_wound.severity >= initial(wound_path_to_generate.severity)) + return FALSE + + if (!ignore_cannot_bleed && ((required_limb_biostate & BIO_BLOODED) && !limb.can_bleed())) + return FALSE + + if (!biostate_valid(limb.biological_state)) + return FALSE + + if (!(limb.body_zone in viable_zones)) + return FALSE + + // we accept promotions and demotions, but no point in redundancy. This should have already been checked wherever the wound was rolled and applied for (see: bodypart damage code), but we do an extra check + // in case we ever directly add wounds + if (!duplicates_allowed) + for (var/datum/wound/preexisting_wound as anything in limb.wounds) + if (preexisting_wound.type == wound_path_to_generate && (preexisting_wound != old_wound)) + return FALSE + return TRUE + +/// Returns true if we have the given biostates, or any biostate in it if check_for_any is true. False otherwise. +/datum/wound_pregen_data/proc/biostate_valid(biostate) + if (check_for_any) + if (!(biostate & required_limb_biostate)) + return FALSE + else if (!((biostate & required_limb_biostate) == required_limb_biostate)) // check for all + return FALSE + + return TRUE + +/// Returns a new instance of our wound datum. +/datum/wound_pregen_data/proc/generate_instance(obj/item/bodypart/limb, ...) + RETURN_TYPE(/datum/wound) + + return new wound_path_to_generate + +/datum/wound_pregen_data/Destroy(force, ...) + stack_trace("[src], a singleton wound pregen data instance, was destroyed! This should not happen!") + + if (!force) + return + + . = ..() + + GLOB.all_wound_pregen_data[wound_path_to_generate] = new src.type //recover diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm index 33686d6bc24..11f2dc6a63d 100644 --- a/code/datums/wounds/_wounds.dm +++ b/code/datums/wounds/_wounds.dm @@ -14,6 +14,8 @@ deciding what specific wound will be applied. I'd like to have a few different types of wounds for at least some of the choices, but I'm just doing rough generals for now. Expect polishing */ +#define WOUND_CRITICAL_BLUNT_DISMEMBER_BONUS 15 + /datum/wound /// What it's named var/name = "Wound" @@ -24,23 +26,31 @@ /// What the limb looks like on a cursory examine var/examine_desc = "is badly hurt" + /// If this wound can generate a scar. + var/can_scar = TRUE + + /// The file we take our scar descriptions from. + var/scar_file + /// needed for "your arm has a compound fracture" vs "your arm has some third degree burns" var/a_or_from = "a" /// The visible message when this happens var/occur_text = "" /// This sound will be played upon the wound being applied var/sound_effect + /// The volume of [sound_effect] + var/sound_volume = 70 /// Either WOUND_SEVERITY_TRIVIAL (meme wounds like stubbed toe), WOUND_SEVERITY_MODERATE, WOUND_SEVERITY_SEVERE, or WOUND_SEVERITY_CRITICAL (or maybe WOUND_SEVERITY_LOSS) var/severity = WOUND_SEVERITY_MODERATE - /// The list of wounds it belongs in, WOUND_LIST_BLUNT, WOUND_LIST_SLASH, or WOUND_LIST_BURN + /// The type of attack that can generate this wound. E.g. WOUND_SLASH = A sword can cause us, or WOUND_BLUNT = a hammer can cause us/a sword attacking mangled flesh. var/wound_type + /// The series of wounds this is in. See wounds.dm (the defines file) for a more detailed explanation - but tldr is that no 2 wounds of the same series can be on a limb. + var/wound_series - /// What body zones can we affect - var/list/viable_zones = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) /// Who owns the body part that we're wounding var/mob/living/carbon/victim = null - /// The bodypart we're parented to + /// The bodypart we're parented to. Not guaranteed to be non-null, especially after/during removal or if we haven't been applied var/obj/item/bodypart/limb = null /// Specific items such as bandages or sutures that can try directly treating this wound @@ -90,14 +100,13 @@ var/wound_source /// What flags apply to this wound - var/wound_flags = (FLESH_WOUND | BONE_WOUND | ACCEPTS_GAUZE) + var/wound_flags = (ACCEPTS_GAUZE) /datum/wound/Destroy() if(attached_surgery) QDEL_NULL(attached_surgery) - remove_wound() - set_limb(null) - victim = null + if (limb) + remove_wound() return ..() // Applied into wounds when they're scanned with the wound analyzer, halves time to treat them manually. @@ -118,22 +127,10 @@ * * wound_source: The source of the wound, such as a weapon. */ /datum/wound/proc/apply_wound(obj/item/bodypart/L, silent = FALSE, datum/wound/old_wound = null, smited = FALSE, attack_direction = null, wound_source = "Unknown") - if(!istype(L) || !L.owner || !(L.body_zone in viable_zones) || !IS_ORGANIC_LIMB(L) || HAS_TRAIT(L.owner, TRAIT_NEVER_WOUNDED) || (L.owner.status_flags & GODMODE)) - qdel(src) - return - // Checks for biological state, to ensure only valid wounds are applied on the limb - if(((wound_flags & BONE_WOUND) && !(L.biological_state & BIO_BONE)) || ((wound_flags & FLESH_WOUND) && !(L.biological_state & BIO_FLESH))) + if (!can_be_applied_to(L, old_wound)) qdel(src) - return - - // we accept promotions and demotions, but no point in redundancy. This should have already been checked wherever the wound was rolled and applied for (see: bodypart damage code), but we do an extra check - // in case we ever directly add wounds - for(var/i in L.wounds) - var/datum/wound/preexisting_wound = i - if((preexisting_wound.type == type) && (preexisting_wound != old_wound)) - qdel(src) - return + return FALSE if(isitem(wound_source)) var/obj/item/wound_item = wound_source @@ -171,12 +168,35 @@ victim.visible_message(msg, span_userdanger("Your [limb.plaintext_zone] [occur_text]!"), vision_distance = vis_dist) if(sound_effect) - playsound(L.owner, sound_effect, 70 + 20 * severity, TRUE) + playsound(L.owner, sound_effect, sound_volume + (20 * severity), TRUE) wound_injury(old_wound, attack_direction = attack_direction) if(!demoted) second_wind() + return TRUE + +/// Returns TRUE if we can be applied to the limb. +/datum/wound/proc/can_be_applied_to(obj/item/bodypart/L, datum/wound/old_wound) + var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[type] + + // We assume we aren't being randomly applied - we have no reason to believe we are + // And, besides, if we were, you could just as easily check our pregen data rather than run this proc + // Generally speaking this proc is called in apply_wound, which is called when the caller is already confidant in its ability to be applied + return pregen_data.can_be_applied_to(L, wound_type, old_wound) + +/// Returns the zones we can be applied to. +/datum/wound/proc/get_viable_zones() + var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[type] + + return pregen_data.viable_zones + +/// Returns the biostate we require to be applied. +/datum/wound/proc/get_required_biostate() + var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[type] + + return pregen_data.required_limb_biostate + // Updates descriptive texts for the wound, in case it can get altered for whatever reason /datum/wound/proc/update_descriptions() return @@ -201,14 +221,16 @@ /datum/wound/proc/remove_wound(ignore_limb, replaced = FALSE) //TODO: have better way to tell if we're getting removed without replacement (full heal) scar stuff set_disabling(FALSE) - if(limb && !already_scarred && !replaced) + if(limb && can_scar && !already_scarred && !replaced) already_scarred = TRUE var/datum/scar/new_scar = new new_scar.generate(limb, src) - remove_wound_from_victim() + + null_victim() // we use the proc here because some behaviors may depend on changing victim to some new value + if(limb && !ignore_limb) - LAZYREMOVE(limb.wounds, src) - limb.update_wounds(replaced) + set_limb(null, replaced) // since we're removing limb's ref to us, we should do the same + // if you want to keep the ref, do it externally, theres no reason for us to remember it /datum/wound/proc/remove_wound_from_victim() if(!victim) @@ -221,17 +243,15 @@ /** * replace_wound() is used when you want to replace the current wound with a new wound, presumably of the same category, just of a different severity (either up or down counts) * - * This proc actually instantiates the new wound based off the specific type path passed, then returns the new instantiated wound datum. - * * Arguments: - * * new_type- The TYPE PATH of the wound you want to replace this, like /datum/wound/slash/severe + * * new_wound- The wound instance you want to replace this * * smited- If this is a smite, we don't care about this wound for stat tracking purposes (not yet implemented) */ -/datum/wound/proc/replace_wound(new_type, smited = FALSE, attack_direction = attack_direction) - var/datum/wound/new_wound = new new_type +/datum/wound/proc/replace_wound(datum/wound/new_wound, smited = FALSE, attack_direction = attack_direction) already_scarred = TRUE + var/obj/item/bodypart/cached_limb = limb // remove_wound() nulls limb so we have to track it locally remove_wound(replaced=TRUE) - new_wound.apply_wound(limb, old_wound = src, smited = smited, attack_direction = attack_direction, wound_source = wound_source) + new_wound.apply_wound(cached_limb, old_wound = src, smited = smited, attack_direction = attack_direction, wound_source = wound_source) . = new_wound qdel(src) @@ -239,24 +259,28 @@ /datum/wound/proc/wound_injury(datum/wound/old_wound = null, attack_direction = null) return - /// Proc called to change the variable `limb` and react to the event. -/datum/wound/proc/set_limb(new_value) +/datum/wound/proc/set_limb(obj/item/bodypart/new_value, replaced = FALSE) if(limb == new_value) return FALSE //Limb can either be a reference to something or `null`. Returning the number variable makes it clear no change was made. . = limb - if(limb) + if(limb) // if we're nulling limb, we're basically detaching from it, so we should remove ourselves in that case UnregisterSignal(limb, COMSIG_QDELETING) + LAZYREMOVE(limb.wounds, src) + limb.update_wounds(replaced) + if (disabling) + limb.remove_traits(list(TRAIT_PARALYSIS, TRAIT_DISABLED_BY_WOUND), REF(src)) + limb = new_value - RegisterSignal(new_value, COMSIG_QDELETING, PROC_REF(source_died)) - if(. && disabling) - var/obj/item/bodypart/old_limb = . - old_limb.remove_traits(list(TRAIT_PARALYSIS, TRAIT_DISABLED_BY_WOUND), REF(src)) + + // POST-CHANGE + + if (limb) + RegisterSignal(limb, COMSIG_QDELETING, PROC_REF(source_died)) if(limb) if(disabling) limb.add_traits(list(TRAIT_PARALYSIS, TRAIT_DISABLED_BY_WOUND), REF(src)) - /// Proc called to change the variable `disabling` and react to the event. /datum/wound/proc/set_disabling(new_value) if(disabling == new_value) @@ -304,25 +328,7 @@ if(I.force && tendee.combat_mode) return FALSE - var/allowed = FALSE - - // check if we have a valid treatable tool - if(I.tool_behaviour == treatable_tool) - allowed = TRUE - else if(treatable_tool == TOOL_CAUTERY && I.get_temperature() && user == victim) // allow improvised cauterization on yourself without an aggro grab - allowed = TRUE - // failing that, see if we're aggro grabbing them and if we have an item that works for aggro grabs only - else if(user.pulling == victim && user.grab_state >= GRAB_AGGRESSIVE && check_grab_treatments(I, user)) - allowed = TRUE - // failing THAT, we check if we have a generally allowed item - else - for(var/allowed_type in treatable_by) - if(istype(I, allowed_type)) - allowed = TRUE - break - - // if none of those apply, we return false to avoid interrupting - if(!allowed) + if(!item_can_treat(I, user)) return FALSE // now that we've determined we have a valid attempt at treating, we can stomp on their dreams if we're already interacting with the patient or if their part is obscured @@ -338,8 +344,22 @@ return TRUE // lastly, treat them - treat(I, user) - return TRUE + return treat(I, user) // we allow treat to return a value so it can control if the item does its normal interaction or not + +/// Returns TRUE if the item can be used to treat our wounds. Hooks into treat() - only things that return TRUE here may be used there. +/datum/wound/proc/item_can_treat(obj/item/potential_treater, mob/user) + // check if we have a valid treatable tool + if(potential_treater.tool_behaviour == treatable_tool) + return TRUE + if(treatable_tool == TOOL_CAUTERY && potential_treater.get_temperature() && user == victim) // allow improvised cauterization on yourself without an aggro grab + return TRUE + // failing that, see if we're aggro grabbing them and if we have an item that works for aggro grabs only + if(user.pulling == victim && user.grab_state >= GRAB_AGGRESSIVE && check_grab_treatments(potential_treater, user)) + return TRUE + // failing THAT, we check if we have a generally allowed item + for(var/allowed_type in treatable_by) + if(istype(potential_treater, allowed_type)) + return TRUE /// Return TRUE if we have an item that can only be used while aggro grabbed (unhanded aggro grab treatments go in [/datum/wound/proc/try_handling]). Treatment is still is handled in [/datum/wound/proc/treat] /datum/wound/proc/check_grab_treatments(obj/item/I, mob/user) @@ -361,8 +381,8 @@ /datum/wound/proc/still_exists() return (!QDELETED(src) && limb) -/// When our parent bodypart is hurt -/datum/wound/proc/receive_damage(wounding_type, wounding_dmg, wound_bonus, attack_direction) +/// When our parent bodypart is hurt. +/datum/wound/proc/receive_damage(wounding_type, wounding_dmg, wound_bonus, attack_direction, damage_source) return /// Called from cryoxadone and pyroxadone when they're proc'ing. Wounds will slowly be fixed separately from other methods when these are in effect. crappy name but eh @@ -427,9 +447,43 @@ return . /datum/wound/proc/get_wound_description(mob/user) - . = "[victim.p_Their()] [limb.plaintext_zone] [examine_desc]" - . = severity <= WOUND_SEVERITY_MODERATE ? "[.]." : "[.]!" - return . + var/desc + + if ((wound_flags & ACCEPTS_GAUZE) && limb.current_gauze) + var/sling_condition = get_gauze_condition() + desc = "[victim.p_Their()] [limb.plaintext_zone] is [sling_condition] fastened in a sling of [limb.current_gauze.name]" + else + desc = "[victim.p_Their()] [limb.plaintext_zone] [examine_desc]" + + desc = modify_desc_before_span(desc, user) + + return get_desc_intensity(desc) + +/// A hook proc used to modify desc before it is spanned via [get_desc_intensity]. Useful for inserting spans yourself. +/datum/wound/proc/modify_desc_before_span(desc, mob/user) + return desc + +/datum/wound/proc/get_gauze_condition() + SHOULD_BE_PURE(TRUE) + if (!limb.current_gauze) + return null + + switch(limb.current_gauze.absorption_capacity) + if(0 to 1.25) + return "just barely" + if(1.25 to 2.75) + return "loosely" + if(2.75 to 4) + return "mostly" + if(4 to INFINITY) + return "tightly" + +/// Spans [desc] based on our severity. +/datum/wound/proc/get_desc_intensity(desc) + SHOULD_BE_PURE(TRUE) + if (severity > WOUND_SEVERITY_MODERATE) + return span_bold("[desc]!") + return "[desc]." /datum/wound/proc/get_scanner_description(mob/user) return "Type: [name]\nSeverity: [severity_text()]\nDescription: [desc]\nRecommended Treatment: [treat_text]" @@ -445,7 +499,30 @@ if(WOUND_SEVERITY_CRITICAL) return "Critical" + +/// Returns TRUE if our limb is the head or chest, FALSE otherwise. +/// Essential in the sense of "we cannot live without it". +/datum/wound/proc/limb_essential() + return (limb.body_zone == BODY_ZONE_HEAD || limb.body_zone == BODY_ZONE_CHEST) + +/// Getter proc for our scar_keyword, in case we might have some custom scar gen logic. +/datum/wound/proc/get_scar_keyword(obj/item/bodypart/scarred_limb, add_to_scars) + return scar_keyword + +/// Getter proc for our scar_file, in case we might have some custom scar gen logic. +/datum/wound/proc/get_scar_file(obj/item/bodypart/scarred_limb, add_to_scars) + return scar_file + /// Returns what string is displayed when a limb that has sustained this wound is examined /// (This is examining the LIMB ITSELF, when it's not attached to someone.) /datum/wound/proc/get_limb_examine_description() return + +/// Gets the flat percentage chance increment of a dismember occuring, if a dismember is attempted (requires mangled flesh and bone). returning 15 = +15%. +/datum/wound/proc/get_dismember_chance_bonus(existing_chance) + SHOULD_BE_PURE(TRUE) + + if (wound_type == WOUND_BLUNT && severity >= WOUND_SEVERITY_CRITICAL) + return WOUND_CRITICAL_BLUNT_DISMEMBER_BONUS // we only require mangled bone (T2 blunt), but if there's a critical blunt, we'll add 15% more + +#undef WOUND_CRITICAL_BLUNT_DISMEMBER_BONUS diff --git a/code/datums/wounds/blunt.dm b/code/datums/wounds/blunt.dm new file mode 100644 index 00000000000..8a9c34e163d --- /dev/null +++ b/code/datums/wounds/blunt.dm @@ -0,0 +1,4 @@ +/datum/wound/blunt + name = "Blunt Wound" + sound_effect = 'sound/effects/wounds/crack1.ogg' + wound_type = WOUND_BLUNT diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index aa6cad87ed8..eed0fb1d883 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -1,16 +1,17 @@ -//SKYRAT EDIT REMOVAL - MOVED - MEDICINE -/* - /* Blunt/Bone wounds */ // TODO: well, a lot really, but i'd kill to get overlays and a bonebreaking effect like Blitz: The League, similar to electric shock skeletons -/datum/wound/blunt +/datum/wound_pregen_data/bone + abstract = TRUE + required_limb_biostate = BIO_BONE + +/datum/wound/blunt/bone name = "Blunt (Bone) Wound" - sound_effect = 'sound/effects/wounds/crack1.ogg' - wound_type = WOUND_BLUNT - wound_flags = (BONE_WOUND | ACCEPTS_GAUZE) + wound_flags = (ACCEPTS_GAUZE | SPLINT_OVERLAY) // SKYRAT EDIT: MEDICAL -- Makes bone wounds have a splint overlay + + scar_file = BONE_SCAR_FILE /// Have we been bone gel'd? var/gelled @@ -31,19 +32,18 @@ /// If this is a chest wound and this is set, we have this chance to cough up blood when hit in the chest var/internal_bleeding_chance = 0 + wound_series = WOUND_SERIES_BONE_BLUNT_BASIC + /* Overwriting of base procs */ -/datum/wound/blunt/wound_injury(datum/wound/old_wound = null, attack_direction = null) +/datum/wound/blunt/bone/wound_injury(datum/wound/old_wound = null, attack_direction = null) // hook into gaining/losing gauze so crit bone wounds can re-enable/disable depending if they're slung or not - RegisterSignals(limb, list(COMSIG_BODYPART_GAUZED, COMSIG_BODYPART_GAUZE_DESTROYED), PROC_REF(update_inefficiencies)) - if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group) processes = TRUE active_trauma = victim.gain_trauma_type(brain_trauma_group, TRAUMA_RESILIENCE_WOUND) next_trauma_cycle = world.time + (rand(100-WOUND_BONE_HEAD_TIME_VARIANCE, 100+WOUND_BONE_HEAD_TIME_VARIANCE) * 0.01 * trauma_cycle_cooldown) - RegisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand)) if(limb.held_index && victim.get_item_for_held_index(limb.held_index) && (disabling || prob(30 * severity))) var/obj/item/I = victim.get_item_for_held_index(limb.held_index) if(istype(I, /obj/item/offhand)) @@ -53,19 +53,37 @@ victim.visible_message(span_danger("[victim] drops [I] in shock!"), span_warning("The force on your [limb.plaintext_zone] causes you to drop [I]!"), vision_distance=COMBAT_MESSAGE_RANGE) update_inefficiencies() + return ..() -/datum/wound/blunt/remove_wound(ignore_limb, replaced) +/datum/wound/blunt/bone/set_victim(new_victim) + + if (victim) + UnregisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + if (new_victim) + RegisterSignal(new_victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand)) + + return ..() + +/datum/wound/blunt/bone/set_limb(obj/item/bodypart/new_value) + if (limb) + UnregisterSignal(limb, list(COMSIG_BODYPART_GAUZED, COMSIG_BODYPART_GAUZE_DESTROYED)) + if (new_value) + RegisterSignals(new_value, list(COMSIG_BODYPART_GAUZED, COMSIG_BODYPART_GAUZE_DESTROYED), PROC_REF(update_inefficiencies)) + + return ..() + +/datum/wound/blunt/bone/remove_wound(ignore_limb, replaced) limp_slowdown = 0 limp_chance = 0 QDEL_NULL(active_trauma) - if(limb) - UnregisterSignal(limb, list(COMSIG_BODYPART_GAUZED, COMSIG_BODYPART_GAUZE_DESTROYED)) - if(victim) - UnregisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) return ..() -/datum/wound/blunt/handle_process(seconds_per_tick, times_fired) +/datum/wound/blunt/bone/handle_process(seconds_per_tick, times_fired) . = ..() + + if (!victim || IS_IN_STASIS(victim)) + return + if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group && world.time > next_trauma_cycle) if(active_trauma) QDEL_NULL(active_trauma) @@ -98,7 +116,7 @@ remove_wound() /// If we're a human who's punching something with a broken arm, we might hurt ourselves doing so -/datum/wound/blunt/proc/attack_with_hurt_hand(mob/M, atom/target, proximity) +/datum/wound/blunt/bone/proc/attack_with_hurt_hand(mob/M, atom/target, proximity) SIGNAL_HANDLER if(victim.get_active_hand() != limb || !victim.combat_mode || !ismob(target) || severity <= WOUND_SEVERITY_MODERATE) @@ -119,7 +137,7 @@ return COMPONENT_CANCEL_ATTACK_CHAIN -/datum/wound/blunt/receive_damage(wounding_type, wounding_dmg, wound_bonus) +/datum/wound/blunt/bone/receive_damage(wounding_type, wounding_dmg, wound_bonus) if(!victim || wounding_dmg < WOUND_MINIMUM_DAMAGE) return if(ishuman(victim)) @@ -145,45 +163,23 @@ new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir) victim.add_splatter_floor(get_step(victim.loc, victim.dir)) +/datum/wound/blunt/bone/modify_desc_before_span(desc) + . = ..() -/datum/wound/blunt/get_wound_description(mob/user) - if(!limb.current_gauze && !gelled && !taped) - return ..() - - var/list/msg = list() - if(!limb.current_gauze) - msg += "[victim.p_Their()] [limb.plaintext_zone] [examine_desc]" - else - var/sling_condition = "" - // how much life we have left in these bandages - switch(limb.current_gauze.absorption_capacity) - if(0 to 1.25) - sling_condition = "just barely" - if(1.25 to 2.75) - sling_condition = "loosely" - if(2.75 to 4) - sling_condition = "mostly" - if(4 to INFINITY) - sling_condition = "tightly" - - msg += "[victim.p_Their()] [limb.plaintext_zone] is [sling_condition] fastened in a sling of [limb.current_gauze.name]" - - if(taped) - msg += ", [span_notice("and appears to be reforming itself under some surgical tape!")]" - else if(gelled) - msg += ", [span_notice("with fizzing flecks of blue bone gel sparking off the bone!")]" - else - msg += "!" - return "[msg.Join()]" + if (!limb.current_gauze) + if(taped) + . += ", [span_notice("and appears to be reforming itself under some surgical tape!")]" + else if(gelled) + . += ", [span_notice("with fizzing flecks of blue bone gel sparking off the bone!")]" /datum/wound/blunt/get_limb_examine_description() return span_warning("The bones in this limb appear badly cracked.") /* - New common procs for /datum/wound/blunt/ + New common procs for /datum/wound/blunt/bone/ */ -/datum/wound/blunt/proc/update_inefficiencies() +/datum/wound/blunt/bone/proc/update_inefficiencies() SIGNAL_HANDLER if(limb.body_zone in list(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) @@ -205,42 +201,60 @@ limb.update_wounds() +/datum/wound/blunt/bone/get_scar_file(obj/item/bodypart/scarred_limb, add_to_scars) + if (scarred_limb.biological_state & BIO_BONE && (!(scarred_limb.biological_state & BIO_FLESH))) // only bone + return BONE_SCAR_FILE + else if (scarred_limb.biological_state & BIO_FLESH && (!(scarred_limb.biological_state & BIO_BONE))) + return FLESH_SCAR_FILE + + return ..() + /// Joint Dislocation (Moderate Blunt) -/datum/wound/blunt/moderate +/datum/wound/blunt/bone/moderate name = "Joint Dislocation" - desc = "Patient's bone has been unset from socket, causing pain and reduced motor function." + desc = "Patient's limb has been unset from socket, causing pain and reduced motor function." treat_text = "Recommended application of bonesetter to affected limb, though manual relocation by applying an aggressive grab to the patient and helpfully interacting with afflicted limb may suffice." examine_desc = "is awkwardly janked out of place" occur_text = "janks violently and becomes unseated" severity = WOUND_SEVERITY_MODERATE - viable_zones = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) interaction_efficiency_penalty = 1.3 limp_slowdown = 3 limp_chance = 50 threshold_minimum = 35 threshold_penalty = 15 treatable_tool = TOOL_BONESET - wound_flags = (BONE_WOUND) - status_effect_type = /datum/status_effect/wound/blunt/moderate + status_effect_type = /datum/status_effect/wound/blunt/bone/moderate scar_keyword = "bluntmoderate" -/datum/wound/blunt/moderate/Destroy() +/datum/wound_pregen_data/bone/dislocate + abstract = FALSE + + wound_path_to_generate = /datum/wound/blunt/bone/moderate + + required_limb_biostate = BIO_JOINTED + +/datum/wound/blunt/bone/moderate/Destroy() if(victim) UnregisterSignal(victim, COMSIG_LIVING_DOORCRUSHED) return ..() -/datum/wound/blunt/moderate/wound_injury(datum/wound/old_wound, attack_direction = null) - . = ..() - RegisterSignal(victim, COMSIG_LIVING_DOORCRUSHED, PROC_REF(door_crush)) +/datum/wound/blunt/bone/moderate/set_victim(new_victim) + + if (victim) + UnregisterSignal(victim, COMSIG_LIVING_DOORCRUSHED) + if (new_victim) + RegisterSignal(new_victim, COMSIG_LIVING_DOORCRUSHED, PROC_REF(door_crush)) + + return ..() /// Getting smushed in an airlock/firelock is a last-ditch attempt to try relocating your limb -/datum/wound/blunt/moderate/proc/door_crush() +/datum/wound/blunt/bone/moderate/proc/door_crush() SIGNAL_HANDLER if(prob(40)) victim.visible_message(span_danger("[victim]'s dislocated [limb.plaintext_zone] pops back into place!"), span_userdanger("Your dislocated [limb.plaintext_zone] pops back into place! Ow!")) remove_wound() -/datum/wound/blunt/moderate/try_handling(mob/living/carbon/human/user) +/datum/wound/blunt/bone/moderate/try_handling(mob/living/carbon/human/user) if(user.pulling != victim || user.zone_selected != limb.body_zone) return FALSE @@ -258,7 +272,7 @@ return TRUE /// If someone is snapping our dislocated joint back into place by hand with an aggro grab and help intent -/datum/wound/blunt/moderate/proc/chiropractice(mob/living/carbon/human/user) +/datum/wound/blunt/bone/moderate/proc/chiropractice(mob/living/carbon/human/user) var/time = base_treat_time if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) @@ -277,7 +291,7 @@ chiropractice(user) /// If someone is snapping our dislocated joint into a fracture by hand with an aggro grab and harm or disarm intent -/datum/wound/blunt/moderate/proc/malpractice(mob/living/carbon/human/user) +/datum/wound/blunt/bone/moderate/proc/malpractice(mob/living/carbon/human/user) var/time = base_treat_time if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) @@ -295,7 +309,7 @@ malpractice(user) -/datum/wound/blunt/moderate/treat(obj/item/I, mob/user) +/datum/wound/blunt/bone/moderate/treat(obj/item/I, mob/user) var/scanned = HAS_TRAIT(src, TRAIT_WOUND_SCANNED) var/self_penalty_mult = user == victim ? 1.5 : 1 var/scanned_mult = scanned ? 0.5 : 1 @@ -324,7 +338,7 @@ Severe (Hairline Fracture) */ -/datum/wound/blunt/severe +/datum/wound/blunt/bone/severe name = "Hairline Fracture" desc = "Patient's bone has suffered a crack in the foundation, causing serious pain and reduced limb functionality." treat_text = "Recommended light surgical application of bone gel, though a sling of medical gauze will prevent worsening situation." @@ -338,16 +352,21 @@ threshold_minimum = 60 threshold_penalty = 30 treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/bone_gel) - status_effect_type = /datum/status_effect/wound/blunt/severe + status_effect_type = /datum/status_effect/wound/blunt/bone/severe scar_keyword = "bluntsevere" brain_trauma_group = BRAIN_TRAUMA_MILD trauma_cycle_cooldown = 1.5 MINUTES internal_bleeding_chance = 40 - wound_flags = (BONE_WOUND | ACCEPTS_GAUZE | MANGLES_BONE) + wound_flags = (ACCEPTS_GAUZE | MANGLES_BONE | SPLINT_OVERLAY) // SKYRAT EDIT - MEDICAL (SPLINT_OVERLAY) regen_ticks_needed = 120 // ticks every 2 seconds, 240 seconds, so roughly 4 minutes default +/datum/wound_pregen_data/bone/hairline + abstract = FALSE + + wound_path_to_generate = /datum/wound/blunt/bone/severe + /// Compound Fracture (Critical Blunt) -/datum/wound/blunt/critical +/datum/wound/blunt/bone/critical name = "Compound Fracture" desc = "Patient's bones have suffered multiple gruesome fractures, causing significant pain and near uselessness of limb." treat_text = "Immediate binding of affected limb, followed by surgical intervention ASAP." @@ -363,36 +382,40 @@ threshold_penalty = 50 disabling = TRUE treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/bone_gel) - status_effect_type = /datum/status_effect/wound/blunt/critical + status_effect_type = /datum/status_effect/wound/blunt/bone/critical scar_keyword = "bluntcritical" brain_trauma_group = BRAIN_TRAUMA_SEVERE trauma_cycle_cooldown = 2.5 MINUTES internal_bleeding_chance = 60 - wound_flags = (BONE_WOUND | ACCEPTS_GAUZE | MANGLES_BONE) + wound_flags = (ACCEPTS_GAUZE | MANGLES_BONE | SPLINT_OVERLAY) // SKYRAT EDIT - MEDICAL (SPLINT_OVERLAY) regen_ticks_needed = 240 // ticks every 2 seconds, 480 seconds, so roughly 8 minutes default +/datum/wound_pregen_data/bone/compound + abstract = FALSE + + wound_path_to_generate = /datum/wound/blunt/bone/critical + // doesn't make much sense for "a" bone to stick out of your head -/datum/wound/blunt/critical/apply_wound(obj/item/bodypart/L, silent = FALSE, datum/wound/old_wound = null, smited = FALSE, attack_direction = null, wound_source = "Unknown") +/datum/wound/blunt/bone/critical/apply_wound(obj/item/bodypart/L, silent = FALSE, datum/wound/old_wound = null, smited = FALSE, attack_direction = null, wound_source = "Unknown") if(L.body_zone == BODY_ZONE_HEAD) occur_text = "splits open, exposing a bare, cracked skull through the flesh and blood" examine_desc = "has an unsettling indent, with bits of skull poking out" . = ..() /// if someone is using bone gel on our wound -/datum/wound/blunt/proc/gel(obj/item/stack/medical/bone_gel/I, mob/user) +/datum/wound/blunt/bone/proc/gel(obj/item/stack/medical/bone_gel/I, mob/user) // skellies get treated nicer with bone gel since their "reattach dismembered limbs by hand" ability sucks when it's still critically wounded if((limb.biological_state & BIO_BONE) && !(limb.biological_state & BIO_FLESH)) - skelly_gel(I, user) - return + return skelly_gel(I, user) if(gelled) to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [limb.plaintext_zone] is already coated with bone gel!")) - return + return TRUE user.visible_message(span_danger("[user] begins hastily applying [I] to [victim]'s' [limb.plaintext_zone]..."), span_warning("You begin hastily applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone], disregarding the warning label...")) if(!do_after(user, base_treat_time * 1.5 * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, PROC_REF(still_exists)))) - return + return TRUE I.use(1) victim.emote("scream") @@ -415,15 +438,16 @@ if(prob(25 + (20 * (severity - 2)) - painkiller_bonus)) // 25%/45% chance to fail self-applying with severe and critical wounds, modded by painkillers victim.visible_message(span_danger("[victim] fails to finish applying [I] to [victim.p_their()] [limb.plaintext_zone], passing out from the pain!"), span_notice("You pass out from the pain of applying [I] to your [limb.plaintext_zone] before you can finish!")) victim.AdjustUnconscious(5 SECONDS) - return + return TRUE victim.visible_message(span_notice("[victim] finishes applying [I] to [victim.p_their()] [limb.plaintext_zone], grimacing from the pain!"), span_notice("You finish applying [I] to your [limb.plaintext_zone], and your bones explode in pain!")) limb.receive_damage(25, wound_bonus=CANT_WOUND) victim.adjustStaminaLoss(100) gelled = TRUE + return TRUE /// skellies are less averse to bone gel, since they're literally all bone -/datum/wound/blunt/proc/skelly_gel(obj/item/stack/medical/bone_gel/I, mob/user) +/datum/wound/blunt/bone/proc/skelly_gel(obj/item/stack/medical/bone_gel/I, mob/user) if(gelled) to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [limb.plaintext_zone] is already coated with bone gel!")) return @@ -442,20 +466,21 @@ gelled = TRUE processes = TRUE + return TRUE /// if someone is using surgical tape on our wound -/datum/wound/blunt/proc/tape(obj/item/stack/sticky_tape/surgical/I, mob/user) +/datum/wound/blunt/bone/proc/tape(obj/item/stack/sticky_tape/surgical/I, mob/user) if(!gelled) to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [limb.plaintext_zone] must be coated with bone gel to perform this emergency operation!")) - return + return TRUE if(taped) to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [limb.plaintext_zone] is already wrapped in [I.name] and reforming!")) - return + return TRUE user.visible_message(span_danger("[user] begins applying [I] to [victim]'s' [limb.plaintext_zone]..."), span_warning("You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone]...")) if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, PROC_REF(still_exists)))) - return + return TRUE if(victim == user) regen_ticks_needed *= 1.5 @@ -469,14 +494,15 @@ taped = TRUE processes = TRUE + return TRUE -/datum/wound/blunt/treat(obj/item/I, mob/user) +/datum/wound/blunt/bone/treat(obj/item/I, mob/user) if(istype(I, /obj/item/stack/medical/bone_gel)) - gel(I, user) + return gel(I, user) else if(istype(I, /obj/item/stack/sticky_tape/surgical)) - tape(I, user) + return tape(I, user) -/datum/wound/blunt/get_scanner_description(mob/user) +/datum/wound/blunt/bone/get_scanner_description(mob/user) . = ..() . += "
" @@ -500,4 +526,3 @@ else if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume) . += "Ribcage Trauma Detected: Further trauma to chest is likely to worsen internal bleeding until bone is repaired." . += "
" -*/ diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm index d3e7221d8f3..7ef1cd68268 100644 --- a/code/datums/wounds/burns.dm +++ b/code/datums/wounds/burns.dm @@ -1,6 +1,3 @@ -//SKYRAT EDIT REMOVAL - MOVED - MEDICINE -/* - /* Burn wounds */ @@ -10,9 +7,17 @@ name = "Burn Wound" a_or_from = "from" wound_type = WOUND_BURN - processes = TRUE sound_effect = 'sound/effects/wounds/sizzle1.ogg' - wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE) + +/datum/wound/burn/flesh + name = "Burn (Flesh) Wound" + a_or_from = "from" + wound_type = WOUND_BURN + processes = TRUE + + scar_file = FLESH_SCAR_FILE + + wound_series = WOUND_SERIES_FLESH_BURN_BASIC treatable_by = list(/obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) // sterilizer and alcohol will require reagent treatments, coming soon @@ -33,8 +38,11 @@ /// Once we reach infestation beyond WOUND_INFESTATION_SEPSIS, we get this many warnings before the limb is completely paralyzed (you'd have to ignore a really bad burn for a really long time for this to happen) var/strikes_to_lose_limb = 3 +/datum/wound/burn/flesh/handle_process(seconds_per_tick, times_fired) + + if (!victim || IS_IN_STASIS(victim)) + return -/datum/wound/burn/handle_process(seconds_per_tick, times_fired) . = ..() if(strikes_to_lose_limb == 0) // we've already hit sepsis, nothing more to do victim.adjustToxLoss(0.25 * seconds_per_tick) @@ -130,7 +138,7 @@ var/datum/brain_trauma/severe/paralysis/sepsis = new (limb.body_zone) victim.gain_trauma(sepsis) -/datum/wound/burn/get_wound_description(mob/user) +/datum/wound/burn/flesh/get_wound_description(mob/user) if(strikes_to_lose_limb <= 0) return span_deadsay("[victim.p_Their()] [limb.plaintext_zone] has locked up completely and is non-functional.") @@ -163,7 +171,7 @@ return "[condition.Join()]" -/datum/wound/burn/get_scanner_description(mob/user) +/datum/wound/burn/flesh/get_scanner_description(mob/user) if(strikes_to_lose_limb <= 0) // Unclear if it can go below 0, best to not take the chance var/oopsie = "Type: [name]\nSeverity: [severity_text()]" oopsie += "
Infection Level: [span_deadsay("The body part has suffered complete sepsis and must be removed. Amputate or augment limb immediately, or place the patient in a cryotube.")]
" @@ -196,12 +204,12 @@ */ /// if someone is using ointment or mesh on our burns -/datum/wound/burn/proc/ointmentmesh(obj/item/stack/medical/I, mob/user) +/datum/wound/burn/flesh/proc/ointmentmesh(obj/item/stack/medical/I, mob/user) user.visible_message(span_notice("[user] begins applying [I] to [victim]'s [limb.plaintext_zone]..."), span_notice("You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone]...")) if (I.amount <= 0) - return + return TRUE if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), extra_checks = CALLBACK(src, PROC_REF(still_exists)))) - return + return TRUE limb.heal_damage(I.heal_brute, I.heal_burn) user.visible_message(span_green("[user] applies [I] to [victim]."), span_green("You apply [I] to [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone].")) @@ -211,36 +219,38 @@ if((infestation <= 0 || sanitization >= infestation) && (flesh_damage <= 0 || flesh_healing > flesh_damage)) to_chat(user, span_notice("You've done all you can with [I], now you must wait for the flesh on [victim]'s [limb.plaintext_zone] to recover.")) + return TRUE else - try_treating(I, user) + return try_treating(I, user) /// Paramedic UV penlights -/datum/wound/burn/proc/uv(obj/item/flashlight/pen/paramedic/I, mob/user) +/datum/wound/burn/flesh/proc/uv(obj/item/flashlight/pen/paramedic/I, mob/user) if(!COOLDOWN_FINISHED(I, uv_cooldown)) to_chat(user, span_notice("[I] is still recharging!")) - return + return TRUE if(infestation <= 0 || infestation < sanitization) to_chat(user, span_notice("There's no infection to treat on [victim]'s [limb.plaintext_zone]!")) - return + return TRUE user.visible_message(span_notice("[user] flashes the burns on [victim]'s [limb] with [I]."), span_notice("You flash the burns on [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]."), vision_distance=COMBAT_MESSAGE_RANGE) sanitization += I.uv_power COOLDOWN_START(I, uv_cooldown, I.uv_cooldown_length) + return TRUE -/datum/wound/burn/treat(obj/item/I, mob/user) +/datum/wound/burn/flesh/treat(obj/item/I, mob/user) if(istype(I, /obj/item/stack/medical/ointment)) - ointmentmesh(I, user) + return ointmentmesh(I, user) else if(istype(I, /obj/item/stack/medical/mesh)) var/obj/item/stack/medical/mesh/mesh_check = I if(!mesh_check.is_open) to_chat(user, span_warning("You need to open [mesh_check] first.")) return - ointmentmesh(mesh_check, user) + return ointmentmesh(mesh_check, user) else if(istype(I, /obj/item/flashlight/pen/paramedic)) - uv(I, user) + return uv(I, user) // people complained about burns not healing on stasis beds, so in addition to checking if it's cured, they also get the special ability to very slowly heal on stasis beds if they have the healing effects stored -/datum/wound/burn/on_stasis(seconds_per_tick, times_fired) +/datum/wound/burn/flesh/on_stasis(seconds_per_tick, times_fired) . = ..() if(strikes_to_lose_limb == 0) // we've already hit sepsis, nothing more to do if(SPT_PROB(0.5, seconds_per_tick)) @@ -255,14 +265,19 @@ if(sanitization > 0) infestation = max(infestation - (0.1 * WOUND_BURN_SANITIZATION_RATE * seconds_per_tick), 0) -/datum/wound/burn/on_synthflesh(amount) +/datum/wound/burn/flesh/on_synthflesh(amount) flesh_healing += amount * 0.5 // 20u patch will heal 10 flesh standard +/datum/wound_pregen_data/flesh_burn + abstract = TRUE + + required_limb_biostate = BIO_FLESH + /datum/wound/burn/get_limb_examine_description() return span_warning("The flesh on this limb appears badly cooked.") // we don't even care about first degree burns, straight to second -/datum/wound/burn/moderate +/datum/wound/burn/flesh/moderate name = "Second Degree Burns" desc = "Patient is suffering considerable burns with mild skin penetration, weakening limb integrity and increased burning sensations." treat_text = "Recommended application of topical ointment or regenerative mesh to affected region." @@ -272,11 +287,16 @@ damage_mulitplier_penalty = 1.1 threshold_minimum = 40 threshold_penalty = 30 // burns cause significant decrease in limb integrity compared to other wounds - status_effect_type = /datum/status_effect/wound/burn/moderate + status_effect_type = /datum/status_effect/wound/burn/flesh/moderate flesh_damage = 5 scar_keyword = "burnmoderate" -/datum/wound/burn/severe +/datum/wound_pregen_data/flesh_burn/second_degree + abstract = FALSE + + wound_path_to_generate = /datum/wound/burn/flesh/moderate + +/datum/wound/burn/flesh/severe name = "Third Degree Burns" desc = "Patient is suffering extreme burns with full skin penetration, creating serious risk of infection and greatly reduced limb integrity." treat_text = "Recommended immediate disinfection and excision of any infected skin, followed by bandaging and ointment. If the limb has locked up, it must be amputated, augmented or treated with cryogenics." @@ -286,13 +306,18 @@ damage_mulitplier_penalty = 1.2 threshold_minimum = 80 threshold_penalty = 40 - status_effect_type = /datum/status_effect/wound/burn/severe + status_effect_type = /datum/status_effect/wound/burn/flesh/severe treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) infestation_rate = 0.07 // appx 9 minutes to reach sepsis without any treatment flesh_damage = 12.5 scar_keyword = "burnsevere" -/datum/wound/burn/critical +/datum/wound_pregen_data/flesh_burn/third_degree + abstract = FALSE + + wound_path_to_generate = /datum/wound/burn/flesh/severe + +/datum/wound/burn/flesh/critical name = "Catastrophic Burns" desc = "Patient is suffering near complete loss of tissue and significantly charred muscle and bone, creating life-threatening risk of infection and negligible limb integrity." treat_text = "Immediate surgical debriding of any infected skin, followed by potent tissue regeneration formula and bandaging. If the limb has locked up, it must be amputated, augmented or treated with cryogenics." @@ -303,26 +328,42 @@ sound_effect = 'sound/effects/wounds/sizzle2.ogg' threshold_minimum = 140 threshold_penalty = 80 - status_effect_type = /datum/status_effect/wound/burn/critical + status_effect_type = /datum/status_effect/wound/burn/flesh/critical treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) infestation_rate = 0.075 // appx 4.33 minutes to reach sepsis without any treatment flesh_damage = 20 scar_keyword = "burncritical" +/datum/wound_pregen_data/flesh_burn/fourth_degree + abstract = FALSE + + wound_path_to_generate = /datum/wound/burn/flesh/critical + ///special severe wound caused by sparring interference or other god related punishments. -/datum/wound/burn/severe/brand +/datum/wound/burn/flesh/severe/brand name = "Holy Brand" desc = "Patient is suffering extreme burns from a strange brand marking, creating serious risk of infection and greatly reduced limb integrity." examine_desc = "appears to have holy symbols painfully branded into their flesh, leaving severe burns." occur_text = "chars rapidly into a strange pattern of holy symbols, burned into the flesh." +/datum/wound_pregen_data/flesh_burn/holy + abstract = FALSE + can_be_randomly_generated = FALSE + + wound_path_to_generate = /datum/wound/burn/flesh/severe/brand /// special severe wound caused by the cursed slot machine. -/datum/wound/burn/severe/cursed_brand + +/datum/wound/burn/flesh/severe/cursed_brand name = "Ancient Brand" - desc = "Patient is suffering extreme burns with oddly ornate brand markings, creating serious risk of infection and greatly reduced limb integrity." + desc = "Patient is suffering extreme burns with oddly ornate brand markings, creating serious risk of infection and greatly reduced limb integrity." examine_desc = "appears to have ornate symbols painfully branded into their flesh, leaving severe burns" occur_text = "chars rapidly into a pattern that can only be described as an agglomeration of several financial symbols, burned into the flesh" -/datum/wound/burn/severe/cursed_brand/get_limb_examine_description() +/datum/wound/burn/flesh/severe/cursed_brand/get_limb_examine_description() return span_warning("The flesh on this limb has several ornate symbols burned into it, with pitting throughout.") -*/ + +/datum/wound_pregen_data/flesh_burn/cursed_brand + abstract = FALSE + can_be_randomly_generated = FALSE + + wound_path_to_generate = /datum/wound/burn/flesh/severe/cursed_brand diff --git a/code/datums/wounds/loss.dm b/code/datums/wounds/loss.dm index 66dddc99e1d..d396b3a469f 100644 --- a/code/datums/wounds/loss.dm +++ b/code/datums/wounds/loss.dm @@ -1,3 +1,9 @@ +/datum/wound_pregen_data/loss + abstract = FALSE + + wound_path_to_generate = /datum/wound/loss + required_limb_biostate = NONE + check_for_any = TRUE /datum/wound/loss name = "Dismemberment Wound" @@ -11,9 +17,12 @@ wound_flags = null already_scarred = TRUE // We manually assign scars for dismembers through endround missing limbs and aheals + /// The wound_type of the attack that caused us. Used to generate the description of our scar. Currently unused, but primarily exists in case non-biological wounds are added. + var/loss_wound_type + /// Our special proc for our special dismembering, the wounding type only matters for what text we have -/datum/wound/loss/proc/apply_dismember(obj/item/bodypart/dismembered_part, wounding_type=WOUND_SLASH, outright = FALSE, attack_direction) - if(!istype(dismembered_part) || !dismembered_part.owner || !(dismembered_part.body_zone in viable_zones) || isalien(dismembered_part.owner) || !dismembered_part.can_dismember()) +/datum/wound/loss/proc/apply_dismember(obj/item/bodypart/dismembered_part, wounding_type = WOUND_SLASH, outright = FALSE, attack_direction) + if(!istype(dismembered_part) || !dismembered_part.owner || !(dismembered_part.body_zone in get_viable_zones()) || isalien(dismembered_part.owner) || !dismembered_part.can_dismember()) qdel(src) return @@ -23,7 +32,28 @@ if(dismembered_part.body_zone == BODY_ZONE_CHEST) occur_text = "is split open, causing [victim.p_their()] internal organs to spill out!" self_msg = "is split open, causing your internal organs to spill out!" - else if(outright) + else + occur_text = dismembered_part.get_dismember_message(wounding_type, outright) + + var/msg = span_bolddanger("[victim]'s [dismembered_part.plaintext_zone] [occur_text]") + + victim.visible_message(msg, span_userdanger("Your [dismembered_part.plaintext_zone] [self_msg ? self_msg : occur_text]")) + + loss_wound_type = wounding_type + + set_limb(dismembered_part) + second_wind() + log_wound(victim, src) + if(dismembered_part.can_bleed() && wounding_type != WOUND_BURN && victim.blood_volume) + victim.spray_blood(attack_direction, severity) + dismembered_part.dismember(wounding_type == WOUND_BURN ? BURN : BRUTE, wound_type = wounding_type) + qdel(src) + return TRUE + +/obj/item/bodypart/proc/get_dismember_message(wounding_type, outright) + var/occur_text + + if(outright) switch(wounding_type) if(WOUND_BLUNT) occur_text = "is outright smashed to a gross pulp, severing it completely!" @@ -34,25 +64,34 @@ if(WOUND_BURN) occur_text = "is outright incinerated, falling to dust!" else + var/bone_text + if (biological_state & BIO_BONE) + bone_text = "bone" + else if (biological_state & BIO_METAL) + bone_text = "metal" + + var/tissue_text + if (biological_state & BIO_FLESH) + tissue_text = "flesh" + else if (biological_state & BIO_WIRED) + tissue_text = "wire" + switch(wounding_type) if(WOUND_BLUNT) - occur_text = "is shattered through the last bone holding it together, severing it completely!" + occur_text = "is shattered through the last [bone_text] holding it together, severing it completely!" if(WOUND_SLASH) - occur_text = "is slashed through the last tissue holding it together, severing it completely!" + occur_text = "is slashed through the last [tissue_text] holding it together, severing it completely!" if(WOUND_PIERCE) - occur_text = "is pierced through the last tissue holding it together, severing it completely!" + occur_text = "is pierced through the last [tissue_text] holding it together, severing it completely!" if(WOUND_BURN) occur_text = "is completely incinerated, falling to dust!" - var/msg = span_bolddanger("[victim]'s [dismembered_part.plaintext_zone] [occur_text]") + return occur_text - victim.visible_message(msg, span_userdanger("Your [dismembered_part.plaintext_zone] [self_msg ? self_msg : occur_text]")) +/datum/wound/loss/get_scar_file(obj/item/bodypart/scarred_limb, add_to_scars) + if (scarred_limb.biological_state & BIO_FLESH) + return FLESH_SCAR_FILE + if (scarred_limb.biological_state & BIO_BONE) + return BONE_SCAR_FILE - set_limb(dismembered_part) - second_wind() - log_wound(victim, src) - if(wounding_type != WOUND_BURN && victim.blood_volume) - victim.spray_blood(attack_direction, severity) - dismembered_part.dismember(wounding_type == WOUND_BURN ? BURN : BRUTE) - qdel(src) - return TRUE + return ..() diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm index 0f49496c91b..72dac45a877 100644 --- a/code/datums/wounds/pierce.dm +++ b/code/datums/wounds/pierce.dm @@ -1,19 +1,22 @@ -//SKYRAT EDIT REMOVAL - MOVED - MEDICINE -/* - /* Piercing wounds */ - /datum/wound/pierce + wound_type = WOUND_PIERCE + +/datum/wound/pierce/bleed name = "Piercing Wound" sound_effect = 'sound/weapons/slice.ogg' processes = TRUE - wound_type = WOUND_PIERCE treatable_by = list(/obj/item/stack/medical/suture) treatable_tool = TOOL_CAUTERY base_treat_time = 3 SECONDS - wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE) + wound_flags = (ACCEPTS_GAUZE) + + wound_series = WOUND_SERIES_FLESH_SLASH_BLEED + + scar_file = FLESH_SCAR_FILE + /// How much blood we start losing when this wound is first applied var/initial_flow @@ -25,12 +28,14 @@ /// If we let off blood when hit, the max blood lost is this * the incoming damage var/internal_bleeding_coefficient -/datum/wound/pierce/wound_injury(datum/wound/old_wound = null, attack_direction = null) +/datum/wound/pierce/bleed/wound_injury(datum/wound/old_wound = null, attack_direction = null) set_blood_flow(initial_flow) if(!no_bleeding && attack_direction && victim.blood_volume > BLOOD_VOLUME_OKAY) victim.spray_blood(attack_direction, severity) -/datum/wound/pierce/receive_damage(wounding_type, wounding_dmg, wound_bonus) + return ..() + +/datum/wound/pierce/bleed/receive_damage(wounding_type, wounding_dmg, wound_bonus) if(victim.stat == DEAD || (wounding_dmg < 5) || no_bleeding || !victim.blood_volume || !prob(internal_bleeding_chance + wounding_dmg)) return if(limb.current_gauze?.splint_factor) @@ -52,7 +57,7 @@ new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir) victim.add_splatter_floor(get_step(victim.loc, victim.dir)) -/datum/wound/pierce/get_bleed_rate_of_change() +/datum/wound/pierce/bleed/get_bleed_rate_of_change() //basically if a species doesn't bleed, the wound is stagnant and will not heal on it's own (nor get worse) if(no_bleeding) return BLOOD_FLOW_STEADY @@ -62,7 +67,10 @@ return BLOOD_FLOW_DECREASING return BLOOD_FLOW_STEADY -/datum/wound/pierce/handle_process(seconds_per_tick, times_fired) +/datum/wound/pierce/bleed/handle_process(seconds_per_tick, times_fired) + if (!victim || IS_IN_STASIS(victim)) + return + set_blood_flow(min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW)) if(!no_bleeding) @@ -81,31 +89,33 @@ if(blood_flow <= 0) qdel(src) -/datum/wound/pierce/on_stasis(seconds_per_tick, times_fired) +/datum/wound/pierce/bleed/on_stasis(seconds_per_tick, times_fired) . = ..() if(blood_flow <= 0) qdel(src) -/datum/wound/pierce/check_grab_treatments(obj/item/I, mob/user) +/datum/wound/pierce/bleed/check_grab_treatments(obj/item/I, mob/user) if(I.get_temperature()) // if we're using something hot but not a cautery, we need to be aggro grabbing them first, so we don't try treating someone we're eswording return TRUE -/datum/wound/pierce/treat(obj/item/I, mob/user) +/datum/wound/pierce/bleed/treat(obj/item/I, mob/user) if(istype(I, /obj/item/stack/medical/suture)) - suture(I, user) + return suture(I, user) else if(I.tool_behaviour == TOOL_CAUTERY || I.get_temperature()) - tool_cauterize(I, user) + return tool_cauterize(I, user) -/datum/wound/pierce/on_xadone(power) +/datum/wound/pierce/bleed/on_xadone(power) . = ..() - adjust_blood_flow(-0.03 * power) // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort -/datum/wound/pierce/on_synthflesh(power) + if (limb) // parent can cause us to be removed, so its reasonable to check if we're still applied + adjust_blood_flow(-0.03 * power) // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort + +/datum/wound/pierce/bleed/on_synthflesh(power) . = ..() adjust_blood_flow(-0.025 * power) // 20u * 0.05 = -1 blood flow, less than with slashes but still good considering smaller bleed rates /// If someone is using a suture to close this puncture -/datum/wound/pierce/proc/suture(obj/item/stack/medical/suture/I, mob/user) +/datum/wound/pierce/bleed/proc/suture(obj/item/stack/medical/suture/I, mob/user) var/self_penalty_mult = (user == victim ? 1.4 : 1) var/treatment_delay = base_treat_time * self_penalty_mult @@ -116,7 +126,7 @@ user.visible_message(span_notice("[user] begins stitching [victim]'s [limb.plaintext_zone] with [I]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]...")) if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) - return + return TRUE var/bleeding_wording = (no_bleeding ? "holes" : "bleeding") user.visible_message(span_green("[user] stitches up some of the [bleeding_wording] on [victim]."), span_green("You stitch up some of the [bleeding_wording] on [user == victim ? "yourself" : "[victim]"].")) var/blood_sutured = I.stop_bleeding / self_penalty_mult @@ -125,12 +135,13 @@ I.use(1) if(blood_flow > 0) - try_treating(I, user) + return try_treating(I, user) else to_chat(user, span_green("You successfully close the hole in [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone].")) + return TRUE /// If someone is using either a cautery tool or something with heat to cauterize this pierce -/datum/wound/pierce/proc/tool_cauterize(obj/item/I, mob/user) +/datum/wound/pierce/bleed/proc/tool_cauterize(obj/item/I, mob/user) var/improv_penalty_mult = (I.tool_behaviour == TOOL_CAUTERY ? 1 : 1.25) // 25% longer and less effective if you don't use a real cautery var/self_penalty_mult = (user == victim ? 1.5 : 1) // 50% longer and less effective if you do it to yourself @@ -144,7 +155,7 @@ user.visible_message(span_danger("[user] begins cauterizing [victim]'s [limb.plaintext_zone] with [I]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]...")) if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) - return + return TRUE var/bleeding_wording = (no_bleeding ? "holes" : "bleeding") user.visible_message(span_green("[user] cauterizes some of the [bleeding_wording] on [victim]."), span_green("You cauterize some of the [bleeding_wording] on [victim].")) @@ -155,13 +166,19 @@ adjust_blood_flow(-blood_cauterized) if(blood_flow > 0) - try_treating(I, user) + return try_treating(I, user) + return TRUE + +/datum/wound_pregen_data/flesh_pierce + abstract = TRUE + + required_limb_biostate = (BIO_FLESH) /datum/wound/pierce/get_limb_examine_description() return span_warning("The flesh on this limb appears badly perforated.") -/datum/wound/pierce/moderate - name = "Minor Breakage" +/datum/wound/pierce/bleed/moderate + name = "Minor Skin Breakage" desc = "Patient's skin has been broken open, causing severe bruising and minor internal bleeding in affected area." treat_text = "Treat affected site with bandaging or exposure to extreme cold. In dire cases, brief exposure to vacuum may suffice." // space is cold in ss13, so it's like an ice pack! examine_desc = "has a small, circular hole, gently bleeding" @@ -177,12 +194,17 @@ status_effect_type = /datum/status_effect/wound/pierce/moderate scar_keyword = "piercemoderate" -/datum/wound/pierce/moderate/update_descriptions() +/datum/wound_pregen_data/flesh_pierce/breakage + abstract = FALSE + + wound_path_to_generate = /datum/wound/pierce/bleed/moderate + +/datum/wound/pierce/bleed/moderate/update_descriptions() if(no_bleeding) examine_desc = "has a small, circular hole" occur_text = "splits a small hole open" -/datum/wound/pierce/severe +/datum/wound/pierce/bleed/severe name = "Open Puncture" desc = "Patient's internal tissue is penetrated, causing sizeable internal bleeding and reduced limb stability." treat_text = "Repair punctures in skin by suture or cautery, extreme cold may also work." @@ -199,11 +221,16 @@ status_effect_type = /datum/status_effect/wound/pierce/severe scar_keyword = "piercesevere" -/datum/wound/pierce/severe/update_descriptions() +/datum/wound_pregen_data/flesh_pierce/open_puncture + abstract = FALSE + + wound_path_to_generate = /datum/wound/pierce/bleed/severe + +/datum/wound/pierce/bleed/severe/update_descriptions() if(no_bleeding) occur_text = "tears a hole open" -/datum/wound/pierce/critical +/datum/wound/pierce/bleed/critical name = "Ruptured Cavity" desc = "Patient's internal tissue and circulatory system is shredded, causing significant internal bleeding and damage to internal organs." treat_text = "Surgical repair of puncture wound, followed by supervised resanguination." @@ -219,5 +246,9 @@ threshold_penalty = 50 status_effect_type = /datum/status_effect/wound/pierce/critical scar_keyword = "piercecritical" - wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE | MANGLES_FLESH) -*/ + wound_flags = (ACCEPTS_GAUZE | MANGLES_FLESH) + +/datum/wound_pregen_data/flesh_pierce/cavity + abstract = FALSE + + wound_path_to_generate = /datum/wound/pierce/bleed/critical diff --git a/code/datums/wounds/scars/_scars.dm b/code/datums/wounds/scars/_scars.dm index db6275ea62b..bf33af3fefc 100644 --- a/code/datums/wounds/scars/_scars.dm +++ b/code/datums/wounds/scars/_scars.dm @@ -22,11 +22,14 @@ var/visibility = 2 /// Whether this scar can actually be covered up by clothing var/coverable = TRUE - /// Obviously, scars that describe damaged flesh wouldn't apply to a skeleton (in some cases like bone wounds, there can be different descriptions for skeletons and fleshy humanoids) - var/biology = BIO_FLESH_BONE /// If we're a persistent scar or may become one, we go in this character slot var/persistent_character_slot = 0 + /// The biostates we require from a limb to give them our scar. + var/required_limb_biostate + /// If false, we will only check to see if a limb has ALL our biostates, instead of just any. + var/check_any_biostates + /datum/scar/Destroy(force, ...) if(limb) LAZYREMOVE(limb.scars, src) @@ -47,6 +50,19 @@ * * add_to_scars- Should always be TRUE unless you're just storing a scar for later usage, like how cuts want to store a scar for the highest severity of cut, rather than the severity when the wound is fully healed (probably demoted to moderate) */ /datum/scar/proc/generate(obj/item/bodypart/BP, datum/wound/W, add_to_scars=TRUE) + + if (!W.can_scar) + qdel(src) + return + + var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[W.type] + if (!pregen_data) + qdel(src) + return + + required_limb_biostate = pregen_data.required_limb_biostate + check_any_biostates = pregen_data.check_for_any + limb = BP RegisterSignal(limb, COMSIG_QDELETING, PROC_REF(limb_gone)) @@ -59,12 +75,13 @@ if(victim) LAZYADD(victim.all_scars, src) - biology = limb?.biological_state || BIO_FLESH_BONE + var/scar_file = W.get_scar_file(BP, add_to_scars) + var/scar_keyword = W.get_scar_keyword(BP, add_to_scars) + if (!scar_file || !scar_keyword) + qdel(src) + return - if((biology & BIO_BONE) && !(biology & BIO_FLESH)) - description = pick_list(BONE_SCAR_FILE, W.scar_keyword) || "general disfigurement" - else // no specific support for flesh w/o bone scars since it's not really useful - description = pick_list(FLESH_SCAR_FILE, W.scar_keyword) || "general disfigurement" + description = pick_list(W.get_scar_file(BP, add_to_scars), W.get_scar_keyword(BP, add_to_scars)) || "general disfigurement" precise_location = pick_list_replacements(SCAR_LOC_FILE, limb.body_zone) switch(W.severity) @@ -86,22 +103,28 @@ LAZYADD(victim.all_scars, src) /// Used to "load" a persistent scar -/datum/scar/proc/load(obj/item/bodypart/BP, version, description, specific_location, severity=WOUND_SEVERITY_SEVERE, biology=BIO_FLESH_BONE, char_slot) - if(!IS_ORGANIC_LIMB(BP)) +/datum/scar/proc/load(obj/item/bodypart/BP, version, description, specific_location, severity = WOUND_SEVERITY_SEVERE, required_limb_biostate = BIO_STANDARD, char_slot, check_any_biostates = FALSE) + if(!BP.scarrable) qdel(src) return limb = BP RegisterSignal(limb, COMSIG_QDELETING, PROC_REF(limb_gone)) - if(limb.owner) - victim = limb.owner - if(limb.biological_state != biology) + if (isnull(check_any_biostates)) // so we dont break old scars. NOTE: REMOVE AFTER VERSION NUMBER MOVES PAST 3 + check_any_biostates = FALSE + if (check_any_biostates) + if (!(limb.biological_state & required_limb_biostate)) qdel(src) return + else if (!((limb.biological_state & required_limb_biostate) == required_limb_biostate)) // check for all + qdel(src) + return + if(limb.owner) + victim = limb.owner LAZYADD(victim.all_scars, src) src.severity = severity - src.biology = biology + src.required_limb_biostate = required_limb_biostate persistent_character_slot = char_slot LAZYADD(limb.scars, src) @@ -163,9 +186,9 @@ /// Used to format a scar to save for either persistent scars, or for changeling disguises /datum/scar/proc/format() - return "[SCAR_CURRENT_VERSION]|[limb.body_zone]|[description]|[precise_location]|[severity]|[biology]|[persistent_character_slot]" + return "[SCAR_CURRENT_VERSION]|[limb.body_zone]|[description]|[precise_location]|[severity]|[required_limb_biostate]|[persistent_character_slot]|[check_any_biostates]" /// Used to format a scar to save in preferences for persistent scars -/datum/scar/proc/format_amputated(body_zone) - description = pick_list(FLESH_SCAR_FILE, "dismember") - return "[SCAR_CURRENT_VERSION]|[body_zone]|[description]|amputated|[WOUND_SEVERITY_LOSS]|[BIO_FLESH_BONE]|[persistent_character_slot]" +/datum/scar/proc/format_amputated(body_zone, scar_file = FLESH_SCAR_FILE) + description = pick_list(scar_file, "dismember") + return "[SCAR_CURRENT_VERSION]|[body_zone]|[description]|amputated|[WOUND_SEVERITY_LOSS]|[required_limb_biostate]|[persistent_character_slot]|[check_any_biostates]" diff --git a/code/datums/wounds/scars/_static_scar_data.dm b/code/datums/wounds/scars/_static_scar_data.dm new file mode 100644 index 00000000000..942dcffff9c --- /dev/null +++ b/code/datums/wounds/scars/_static_scar_data.dm @@ -0,0 +1,20 @@ +GLOBAL_LIST_INIT_TYPED(all_static_scar_data, /datum/static_scar_data, generate_static_scar_data()) + +/proc/generate_static_scar_data() + RETURN_TYPE(/list/datum/static_scar_data) + + var/list/datum/wound_pregen_data/data = list() + + for (var/datum/wound_pregen_data/path as anything in typecacheof(path = /datum/static_scar_data, ignore_root_path = TRUE)) + if (initial(path.abstract)) + continue + + var/datum/wound_pregen_data/pregen_data = new path + data[pregen_data.wound_path_to_generate] = pregen_data + + return data + +/datum/static_scar_data + var/abstract = FALSE + + diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm index 97fb744d3b3..e8165368952 100644 --- a/code/datums/wounds/slash.dm +++ b/code/datums/wounds/slash.dm @@ -1,5 +1,3 @@ -//SKYRAT EDIT REMOVAL - MOVED - MEDICINE -/* /* Slashing wounds @@ -8,13 +6,26 @@ /datum/wound/slash name = "Slashing (Cut) Wound" sound_effect = 'sound/weapons/slice.ogg' + wound_type = WOUND_SLASH + +/datum/wound_pregen_data/flesh_slash + abstract = TRUE + + required_limb_biostate = BIO_FLESH + +/datum/wound/slash/flesh + name = "Slashing (Cut) Flesh Wound" processes = TRUE wound_type = WOUND_SLASH treatable_by = list(/obj/item/stack/medical/suture) treatable_by_grabbed = list(/obj/item/gun/energy/laser) treatable_tool = TOOL_CAUTERY base_treat_time = 3 SECONDS - wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE) + wound_flags = (ACCEPTS_GAUZE) + + scar_file = FLESH_SCAR_FILE + + wound_series = WOUND_SERIES_FLESH_SLASH_BLEED /// How much blood we start losing when this wound is first applied var/initial_flow @@ -32,7 +43,7 @@ /// A bad system I'm using to track the worst scar we earned (since we can demote, we want the biggest our wound has been, not what it was when it was cured (probably moderate)) var/datum/scar/highest_scar -/datum/wound/slash/wound_injury(datum/wound/slash/old_wound = null, attack_direction = null) +/datum/wound/slash/flesh/wound_injury(datum/wound/slash/flesh/old_wound = null, attack_direction = null) if(old_wound) set_blood_flow(max(old_wound.blood_flow, initial_flow)) if(old_wound.severity > severity && old_wound.highest_scar) @@ -48,24 +59,26 @@ set_highest_scar(new_scar) new_scar.generate(limb, src, add_to_scars=FALSE) -/datum/wound/slash/proc/set_highest_scar(datum/scar/new_scar) + return ..() + +/datum/wound/slash/flesh/proc/set_highest_scar(datum/scar/new_scar) if(highest_scar) UnregisterSignal(highest_scar, COMSIG_QDELETING) if(new_scar) RegisterSignal(new_scar, COMSIG_QDELETING, PROC_REF(clear_highest_scar)) highest_scar = new_scar -/datum/wound/slash/proc/clear_highest_scar(datum/source) +/datum/wound/slash/flesh/proc/clear_highest_scar(datum/source) SIGNAL_HANDLER set_highest_scar(null) -/datum/wound/slash/remove_wound(ignore_limb, replaced) +/datum/wound/slash/flesh/remove_wound(ignore_limb, replaced) if(!replaced && highest_scar) already_scarred = TRUE highest_scar.lazy_attach(limb) return ..() -/datum/wound/slash/get_wound_description(mob/user) +/datum/wound/slash/flesh/get_wound_description(mob/user) if(!limb.current_gauze) return ..() @@ -84,11 +97,16 @@ return "[msg.Join()]" -/datum/wound/slash/receive_damage(wounding_type, wounding_dmg, wound_bonus) +/datum/wound/slash/flesh/receive_damage(wounding_type, wounding_dmg, wound_bonus) + if (!victim) // if we are dismembered, we can still take damage, its fine to check here + return + if(victim.stat != DEAD && wound_bonus != CANT_WOUND && wounding_type == WOUND_SLASH) // can't stab dead bodies to make it bleed faster this way adjust_blood_flow(WOUND_SLASH_DAMAGE_FLOW_COEFF * wounding_dmg) -/datum/wound/slash/drag_bleed_amount() + return ..() + +/datum/wound/slash/flesh/drag_bleed_amount() // say we have 3 severe cuts with 3 blood flow each, pretty reasonable // compare with being at 100 brute damage before, where you bled (brute/100 * 2), = 2 blood per tile var/bleed_amt = min(blood_flow * 0.1, 1) // 3 * 3 * 0.1 = 0.9 blood total, less than before! the share here is .3 blood of course. @@ -99,7 +117,7 @@ return bleed_amt -/datum/wound/slash/get_bleed_rate_of_change() +/datum/wound/slash/flesh/get_bleed_rate_of_change() //basically if a species doesn't bleed, the wound is stagnant and will not heal on it's own (nor get worse) if(no_bleeding) return BLOOD_FLOW_STEADY @@ -110,7 +128,11 @@ if(clot_rate < 0) return BLOOD_FLOW_INCREASING -/datum/wound/slash/handle_process(seconds_per_tick, times_fired) +/datum/wound/slash/flesh/handle_process(seconds_per_tick, times_fired) + + if (!victim || IS_IN_STASIS(victim)) + return + // in case the victim has the NOBLOOD trait, the wound will simply not clot on it's own if(!no_bleeding) set_blood_flow(min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW)) @@ -133,36 +155,36 @@ if(blood_flow < minimum_flow) if(demotes_to) - replace_wound(demotes_to) + replace_wound(new demotes_to) else to_chat(victim, span_green("The cut on your [limb.plaintext_zone] has [no_bleeding ? "healed up" : "stopped bleeding"]!")) qdel(src) -/datum/wound/slash/on_stasis(seconds_per_tick, times_fired) +/datum/wound/slash/flesh/on_stasis(seconds_per_tick, times_fired) if(blood_flow >= minimum_flow) return if(demotes_to) - replace_wound(demotes_to) + replace_wound(new demotes_to) return qdel(src) /* BEWARE, THE BELOW NONSENSE IS MADNESS. bones.dm looks more like what I have in mind and is sufficiently clean, don't pay attention to this messiness */ -/datum/wound/slash/check_grab_treatments(obj/item/I, mob/user) +/datum/wound/slash/flesh/check_grab_treatments(obj/item/I, mob/user) if(istype(I, /obj/item/gun/energy/laser)) return TRUE if(I.get_temperature()) // if we're using something hot but not a cautery, we need to be aggro grabbing them first, so we don't try treating someone we're eswording return TRUE -/datum/wound/slash/treat(obj/item/I, mob/user) +/datum/wound/slash/flesh/treat(obj/item/I, mob/user) if(istype(I, /obj/item/gun/energy/laser)) - las_cauterize(I, user) + return las_cauterize(I, user) else if(I.tool_behaviour == TOOL_CAUTERY || I.get_temperature()) - tool_cauterize(I, user) + return tool_cauterize(I, user) else if(istype(I, /obj/item/stack/medical/suture)) - suture(I, user) + return suture(I, user) -/datum/wound/slash/try_handling(mob/living/carbon/human/user) +/datum/wound/slash/flesh/try_handling(mob/living/carbon/human/user) if(user.pulling != victim || user.zone_selected != limb.body_zone || !isfelinid(user) || !victim.try_inject(user, injection_flags = INJECT_TRY_SHOW_ERROR_MESSAGE)) return FALSE if(DOING_INTERACTION_WITH_TARGET(user, victim)) @@ -179,7 +201,7 @@ return TRUE /// if a felinid is licking this cut to reduce bleeding -/datum/wound/slash/proc/lick_wounds(mob/living/carbon/human/user) +/datum/wound/slash/flesh/proc/lick_wounds(mob/living/carbon/human/user) // transmission is one way patient -> felinid since google said cat saliva is antiseptic or whatever, and also because felinids are already risking getting beaten for this even without people suspecting they're spreading a deathvirus for(var/i in victim.diseases) var/datum/disease/iter_disease = i @@ -201,16 +223,18 @@ else if(demotes_to) to_chat(user, span_green("You successfully lower the severity of [victim]'s cuts.")) -/datum/wound/slash/on_xadone(power) +/datum/wound/slash/flesh/on_xadone(power) . = ..() - adjust_blood_flow(-0.03 * power) // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort -/datum/wound/slash/on_synthflesh(power) + if (limb) // parent can cause us to be removed, so its reasonable to check if we're still applied + adjust_blood_flow(-0.03 * power) // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort + +/datum/wound/slash/flesh/on_synthflesh(power) . = ..() adjust_blood_flow(-0.075 * power) // 20u * 0.075 = -1.5 blood flow, pretty good for how little effort it is /// If someone's putting a laser gun up to our cut to cauterize it -/datum/wound/slash/proc/las_cauterize(obj/item/gun/energy/laser/lasgun, mob/user) +/datum/wound/slash/flesh/proc/las_cauterize(obj/item/gun/energy/laser/lasgun, mob/user) var/self_penalty_mult = (user == victim ? 1.25 : 1) user.visible_message(span_warning("[user] begins aiming [lasgun] directly at [victim]'s [limb.plaintext_zone]..."), span_userdanger("You begin aiming [lasgun] directly at [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone]...")) if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) @@ -223,9 +247,10 @@ victim.emote("scream") adjust_blood_flow(-1 * (damage / (5 * self_penalty_mult))) // 20 / 5 = 4 bloodflow removed, p good victim.visible_message(span_warning("The cuts on [victim]'s [limb.plaintext_zone] scar over!")) + return TRUE /// If someone is using either a cautery tool or something with heat to cauterize this cut -/datum/wound/slash/proc/tool_cauterize(obj/item/I, mob/user) +/datum/wound/slash/flesh/proc/tool_cauterize(obj/item/I, mob/user) var/improv_penalty_mult = (I.tool_behaviour == TOOL_CAUTERY ? 1 : 1.25) // 25% longer and less effective if you don't use a real cautery var/self_penalty_mult = (user == victim ? 1.5 : 1) // 50% longer and less effective if you do it to yourself @@ -248,12 +273,14 @@ adjust_blood_flow(-blood_cauterized) if(blood_flow > minimum_flow) - try_treating(I, user) + return try_treating(I, user) else if(demotes_to) to_chat(user, span_green("You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.")) + return TRUE + return FALSE /// If someone is using a suture to close this cut -/datum/wound/slash/proc/suture(obj/item/stack/medical/suture/I, mob/user) +/datum/wound/slash/flesh/proc/suture(obj/item/stack/medical/suture/I, mob/user) var/self_penalty_mult = (user == victim ? 1.4 : 1) var/treatment_delay = base_treat_time * self_penalty_mult @@ -264,7 +291,7 @@ user.visible_message(span_notice("[user] begins stitching [victim]'s [limb.plaintext_zone] with [I]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.plaintext_zone] with [I]...")) if(!do_after(user, treatment_delay, target = victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) - return + return TRUE var/bleeding_wording = (no_bleeding ? "cuts" : "bleeding") user.visible_message(span_green("[user] stitches up some of the [bleeding_wording] on [victim]."), span_green("You stitch up some of the [bleeding_wording] on [user == victim ? "yourself" : "[victim]"].")) var/blood_sutured = I.stop_bleeding / self_penalty_mult @@ -273,14 +300,16 @@ I.use(1) if(blood_flow > minimum_flow) - try_treating(I, user) + return try_treating(I, user) else if(demotes_to) to_chat(user, span_green("You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.")) + return TRUE + return TRUE /datum/wound/slash/get_limb_examine_description() return span_warning("The flesh on this limb appears badly lacerated.") -/datum/wound/slash/moderate +/datum/wound/slash/flesh/moderate name = "Rough Abrasion" desc = "Patient's skin has been badly scraped, generating moderate blood loss." treat_text = "Application of clean bandages or first-aid grade sutures, followed by food and rest." @@ -293,14 +322,19 @@ clot_rate = 0.05 threshold_minimum = 20 threshold_penalty = 10 - status_effect_type = /datum/status_effect/wound/slash/moderate + status_effect_type = /datum/status_effect/wound/slash/flesh/moderate scar_keyword = "slashmoderate" -/datum/wound/slash/moderate/update_descriptions() +/datum/wound/slash/flesh/moderate/update_descriptions() if(no_bleeding) occur_text = "is cut open" -/datum/wound/slash/severe +/datum/wound_pregen_data/flesh_slash/abrasion + abstract = FALSE + + wound_path_to_generate = /datum/wound/slash/flesh/moderate + +/datum/wound/slash/flesh/severe name = "Open Laceration" desc = "Patient's skin is ripped clean open, allowing significant blood loss." treat_text = "Speedy application of first-aid grade sutures and clean bandages, followed by vitals monitoring to ensure recovery." @@ -313,22 +347,25 @@ clot_rate = 0.03 threshold_minimum = 50 threshold_penalty = 25 - demotes_to = /datum/wound/slash/moderate - status_effect_type = /datum/status_effect/wound/slash/severe + demotes_to = /datum/wound/slash/flesh/moderate + status_effect_type = /datum/status_effect/wound/slash/flesh/severe scar_keyword = "slashsevere" -/datum/wound/slash/severe/update_descriptions() +/datum/wound_pregen_data/flesh_slash/laceration + abstract = FALSE + + wound_path_to_generate = /datum/wound/slash/flesh/severe + +/datum/wound/slash/flesh/severe/update_descriptions() if(no_bleeding) occur_text = "is ripped open" -/datum/wound/slash/critical +/datum/wound/slash/flesh/critical name = "Weeping Avulsion" desc = "Patient's skin is completely torn open, along with significant loss of tissue. Extreme blood loss will lead to quick death without intervention." treat_text = "Immediate bandaging and either suturing or cauterization, followed by supervised resanguination." examine_desc = "is carved down to the bone, spraying blood wildly" - examine_desc = "is carved down to the bone" occur_text = "is torn open, spraying blood wildly" - occur_text = "is torn open" sound_effect = 'sound/effects/wounds/blood3.ogg' severity = WOUND_SEVERITY_CRITICAL initial_flow = 4 @@ -336,25 +373,40 @@ clot_rate = -0.015 // critical cuts actively get worse instead of better threshold_minimum = 80 threshold_penalty = 40 - demotes_to = /datum/wound/slash/severe - status_effect_type = /datum/status_effect/wound/slash/critical + demotes_to = /datum/wound/slash/flesh/severe + status_effect_type = /datum/status_effect/wound/slash/flesh/critical scar_keyword = "slashcritical" - wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE | MANGLES_FLESH) + wound_flags = (ACCEPTS_GAUZE | MANGLES_FLESH) -/datum/wound/slash/moderate/many_cuts +/datum/wound_pregen_data/flesh_slash/avulsion + abstract = FALSE + + wound_path_to_generate = /datum/wound/slash/flesh/critical + +/datum/wound/slash/flesh/moderate/many_cuts name = "Numerous Small Slashes" desc = "Patient's skin has numerous small slashes and cuts, generating moderate blood loss." examine_desc = "has a ton of small cuts" occur_text = "is cut numerous times, leaving many small slashes." +/datum/wound_pregen_data/flesh_slash/cuts + abstract = FALSE + can_be_randomly_generated = FALSE + + wound_path_to_generate = /datum/wound/slash/flesh/moderate/many_cuts + // Subtype for cleave (heretic spell) -/datum/wound/slash/critical/cleave +/datum/wound/slash/flesh/critical/cleave name = "Burning Avulsion" examine_desc = "is ruptured, spraying blood wildly" clot_rate = 0.01 -/datum/wound/slash/critical/cleave/update_descriptions() +/datum/wound/slash/flesh/critical/cleave/update_descriptions() if(no_bleeding) occur_text = "is ruptured" -*/ +/datum/wound_pregen_data/flesh_slash/cleave + abstract = FALSE + can_be_randomly_generated = FALSE + + wound_path_to_generate = /datum/wound/slash/flesh/critical/cleave diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 87250df486e..29c5ea6e4df 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -541,6 +541,7 @@ SEND_SIGNAL(source, COMSIG_REAGENTS_EXPOSE_ATOM, src, reagents, methods, volume_modifier, show_message) for(var/datum/reagent/current_reagent as anything in reagents) . |= current_reagent.expose_atom(src, reagents[current_reagent]) + SEND_SIGNAL(src, COMSIG_ATOM_AFTER_EXPOSE_REAGENTS, reagents, source, methods, volume_modifier, show_message) /// Are you allowed to drop this atom /atom/proc/AllowDrop() diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm index 10c19336119..816814b1bcf 100644 --- a/code/game/machinery/iv_drip.dm +++ b/code/game/machinery/iv_drip.dm @@ -248,7 +248,7 @@ var/list/arm_zones = shuffle(list(BODY_ZONE_R_ARM, BODY_ZONE_L_ARM)) var/obj/item/bodypart/chosen_limb = attached_mob.get_bodypart(arm_zones[1]) || attached_mob.get_bodypart(arm_zones[2]) || attached_mob.get_bodypart(BODY_ZONE_CHEST) chosen_limb.receive_damage(3) - chosen_limb.force_wound_upwards(/datum/wound/pierce/moderate, wound_source = "IV needle") + chosen_limb.force_wound_upwards(/datum/wound/pierce/bleed/moderate, wound_source = "IV needle") else visible_message(span_warning("[attached] is detached from [src].")) detach_iv() diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index 447ebb87d03..14fc91ea7d0 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -286,7 +286,7 @@ holo_cooldown = world.time + 10 SECONDS return -// see: [/datum/wound/burn/proc/uv()] +// see: [/datum/wound/burn/flesh/proc/uv()] /obj/item/flashlight/pen/paramedic name = "paramedic penlight" desc = "A high-powered UV penlight intended to help stave off infection in the field on serious burned patients. Probably really bad to look into." diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index 7bfb330d271..d071e3465af 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -434,9 +434,9 @@ patient.emote("scream") for(var/i in patient.bodyparts) var/obj/item/bodypart/bone = i - var/datum/wound/blunt/severe/oof_ouch = new + var/datum/wound/blunt/bone/severe/oof_ouch = new oof_ouch.apply_wound(bone, wound_source = "bone gel") - var/datum/wound/blunt/critical/oof_OUCH = new + var/datum/wound/blunt/bone/critical/oof_OUCH = new oof_OUCH.apply_wound(bone, wound_source = "bone gel") for(var/i in patient.bodyparts) diff --git a/code/game/objects/items/teleportation.dm b/code/game/objects/items/teleportation.dm index deede6ea83b..533fc755fa1 100644 --- a/code/game/objects/items/teleportation.dm +++ b/code/game/objects/items/teleportation.dm @@ -465,7 +465,8 @@ new /obj/effect/temp_visual/teleport_abductor/syndi_teleporter(mobloc) new /obj/effect/temp_visual/teleport_abductor/syndi_teleporter(emergency_destination) balloon_alert(user, "emergency teleport triggered!") - make_bloods(mobloc, emergency_destination, user) + if (!HAS_TRAIT(user, TRAIT_NOBLOOD)) + make_bloods(mobloc, emergency_destination, user) playsound(mobloc, SFX_SPARKS, 50, 1, SHORT_RANGE_SOUND_EXTRARANGE) playsound(emergency_destination, 'sound/effects/phasein.ogg', 25, 1, SHORT_RANGE_SOUND_EXTRARANGE) playsound(emergency_destination, SFX_SPARKS, 50, 1, SHORT_RANGE_SOUND_EXTRARANGE) diff --git a/code/modules/admin/smites/bloodless.dm b/code/modules/admin/smites/bloodless.dm index f42711c0f74..db68a1cd3a2 100644 --- a/code/modules/admin/smites/bloodless.dm +++ b/code/modules/admin/smites/bloodless.dm @@ -10,9 +10,9 @@ var/mob/living/carbon/carbon_target = target for(var/_limb in carbon_target.bodyparts) var/obj/item/bodypart/limb = _limb - var/type_wound = pick(list(/datum/wound/slash/severe, /datum/wound/slash/moderate)) + var/type_wound = pick(list(/datum/wound/slash/flesh/severe, /datum/wound/slash/flesh/moderate)) limb.force_wound_upwards(type_wound, smited = TRUE) - type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate)) + type_wound = pick(list(/datum/wound/slash/flesh/critical, /datum/wound/slash/flesh/severe, /datum/wound/slash/flesh/moderate)) limb.force_wound_upwards(type_wound, smited = TRUE) - type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe)) + type_wound = pick(list(/datum/wound/slash/flesh/critical, /datum/wound/slash/flesh/severe)) limb.force_wound_upwards(type_wound, smited = TRUE) diff --git a/code/modules/admin/smites/boneless.dm b/code/modules/admin/smites/boneless.dm index 09361cf75cb..5d859669a68 100644 --- a/code/modules/admin/smites/boneless.dm +++ b/code/modules/admin/smites/boneless.dm @@ -12,10 +12,10 @@ var/mob/living/carbon/carbon_target = target for(var/obj/item/bodypart/limb as anything in carbon_target.bodyparts) var/type_wound = pick(list( - /datum/wound/blunt/critical, - /datum/wound/blunt/severe, - /datum/wound/blunt/critical, - /datum/wound/blunt/severe, - /datum/wound/blunt/moderate, + /datum/wound/blunt/bone/critical, + /datum/wound/blunt/bone/severe, + /datum/wound/blunt/bone/critical, + /datum/wound/blunt/bone/severe, + /datum/wound/blunt/bone/moderate, )) limb.force_wound_upwards(type_wound, smited = TRUE) diff --git a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm index a2e234f3ab8..26395396c06 100644 --- a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm @@ -269,7 +269,7 @@ var/mob/living/carbon/carbon_target = target var/obj/item/bodypart/bodypart = pick(carbon_target.bodyparts) - var/datum/wound/slash/severe/crit_wound = new() + var/datum/wound/slash/flesh/severe/crit_wound = new() crit_wound.apply_wound(bodypart, attack_direction = get_dir(source, target)) /datum/heretic_knowledge/summon/stalker diff --git a/code/modules/antagonists/heretic/magic/blood_cleave.dm b/code/modules/antagonists/heretic/magic/blood_cleave.dm index eca27e55566..d5317f23e34 100644 --- a/code/modules/antagonists/heretic/magic/blood_cleave.dm +++ b/code/modules/antagonists/heretic/magic/blood_cleave.dm @@ -19,7 +19,7 @@ /// The radius of the cleave effect var/cleave_radius = 1 /// What type of wound we apply - var/wound_type = /datum/wound/slash/critical/cleave + var/wound_type = /datum/wound/slash/flesh/critical/cleave /datum/action/cooldown/spell/pointed/cleave/is_valid_target(atom/cast_on) return ..() && ishuman(cast_on) @@ -45,7 +45,7 @@ ) var/obj/item/bodypart/bodypart = pick(victim.bodyparts) - var/datum/wound/slash/crit_wound = new wound_type() + var/datum/wound/slash/flesh/crit_wound = new wound_type() crit_wound.apply_wound(bodypart) victim.apply_damage(20, BURN, wound_bonus = CANT_WOUND) @@ -56,7 +56,7 @@ /datum/action/cooldown/spell/pointed/cleave/long name = "Lesser Cleave" cooldown_time = 60 SECONDS - wound_type = /datum/wound/slash/severe + wound_type = /datum/wound/slash/flesh/severe /obj/effect/temp_visual/cleave icon = 'icons/effects/eldritch.dmi' diff --git a/code/modules/antagonists/heretic/status_effects/mark_effects.dm b/code/modules/antagonists/heretic/status_effects/mark_effects.dm index 83a7e7accff..c454ebdc462 100644 --- a/code/modules/antagonists/heretic/status_effects/mark_effects.dm +++ b/code/modules/antagonists/heretic/status_effects/mark_effects.dm @@ -61,7 +61,7 @@ if(ishuman(owner)) var/mob/living/carbon/human/human_owner = owner var/obj/item/bodypart/bodypart = pick(human_owner.bodyparts) - var/datum/wound/slash/severe/crit_wound = new() + var/datum/wound/slash/flesh/severe/crit_wound = new() crit_wound.apply_wound(bodypart) return ..() diff --git a/code/modules/antagonists/traitor/objectives/eyesnatching.dm b/code/modules/antagonists/traitor/objectives/eyesnatching.dm index 49c53180b39..d912be2384a 100644 --- a/code/modules/antagonists/traitor/objectives/eyesnatching.dm +++ b/code/modules/antagonists/traitor/objectives/eyesnatching.dm @@ -179,8 +179,8 @@ if(!do_after(user, eye_snatch_enthusiasm, target = target, extra_checks = CALLBACK(src, PROC_REF(eyeballs_exist), eyeballies, head, target))) return - var/datum/wound/blunt/severe/severe_wound_type = /datum/wound/blunt/severe - var/datum/wound/blunt/critical/critical_wound_type = /datum/wound/blunt/critical + var/datum/wound/blunt/bone/severe/severe_wound_type = /datum/wound/blunt/bone/severe + var/datum/wound/blunt/bone/critical/critical_wound_type = /datum/wound/blunt/bone/critical target.apply_damage(20, BRUTE, BODY_ZONE_HEAD, wound_bonus = rand(initial(severe_wound_type.threshold_minimum), initial(critical_wound_type.threshold_minimum) + 10), attacking_item = src) target.visible_message( span_danger("[src] pierces through [target]'s skull, horribly mutilating their eyes!"), diff --git a/code/modules/mapfluff/ruins/spaceruin_code/meateor.dm b/code/modules/mapfluff/ruins/spaceruin_code/meateor.dm index 8af5d4e5a9d..ca2b6ec39c9 100644 --- a/code/modules/mapfluff/ruins/spaceruin_code/meateor.dm +++ b/code/modules/mapfluff/ruins/spaceruin_code/meateor.dm @@ -13,7 +13,7 @@ /obj/effect/mob_spawn/corpse/human/tigercultist/perforated/special(mob/living/carbon/human/spawned_human) . = ..() - var/datum/wound/pierce/critical/exit_hole = new() + var/datum/wound/pierce/bleed/critical/exit_hole = new() exit_hole.apply_wound(spawned_human.get_bodypart(BODY_ZONE_CHEST)) /// A fun drink enjoyed by the tiger cooperative, might corrode your brain if you drink the whole bottle diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 2ddb20b8b4e..36399dbc71d 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1268,12 +1268,17 @@ else wound_type = forced_type else - wound_type = pick(GLOB.global_all_wound_types) + for (var/datum/wound/path as anything in shuffle(GLOB.all_wound_pregen_data)) + var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[path] + if (pregen_data.can_be_applied_to(scar_part, random_roll = TRUE)) + wound_type = path + break - var/datum/wound/phantom_wound = new wound_type - scaries.generate(scar_part, phantom_wound) - scaries.fake = TRUE - QDEL_NULL(phantom_wound) + if (wound_type) // can feasibly happen, if its an inorganic limb/cant be wounded/scarred + var/datum/wound/phantom_wound = new wound_type + scaries.generate(scar_part, phantom_wound) + scaries.fake = TRUE + QDEL_NULL(phantom_wound) /mob/living/carbon/is_face_visible() return !(wear_mask?.flags_inv & HIDEFACE) && !(head?.flags_inv & HIDEFACE) diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 4a4dbeeec70..3ab34e70230 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -775,7 +775,6 @@ return ..() var/obj/item/bodypart/grasped_part = get_bodypart(zone_selected) - //SKYRAT EDIT CHANGE BEGIN - MEDICAL /* if(!grasped_part?.get_modified_bleed_rate()) return @@ -795,9 +794,8 @@ QDEL_NULL(grasp) return grasp.grasp_limb(grasped_part) - */ + */ // SKYRAT EDIT REMOVAL - MODULARIZED INTO grasp.dm's self_grasp_bleeding_limb !! IF THIS PROC IS UPDATED, PUT IT IN THERE !! self_grasp_bleeding_limb(grasped_part, supress_message) - //SKYRAT EDIT CHANGE END /// an abstract item representing you holding your own limb to staunch the bleeding, see [/mob/living/carbon/proc/grabbedby] will probably need to find somewhere else to put this. /obj/item/hand_item/self_grasp diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm index 16b5b478af0..ec44dcec13e 100644 --- a/code/modules/mob/living/carbon/carbon_defines.dm +++ b/code/modules/mob/living/carbon/carbon_defines.dm @@ -104,6 +104,9 @@ /// All of the scars a carbon has afflicted throughout their limbs var/list/all_scars + /// Assoc list of BODY_ZONE -> WOUND_TYPE. Set when a limb is dismembered, unset when one is attached. Used for determining what scar to add when it comes time to generate them. + var/list/body_zone_dismembered_by + /// Simple modifier for whether this mob can handle greater or lesser skillchip complexity. See /datum/mutation/human/biotechcompat/ for example. var/skillchip_complexity_modifier = 0 diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm index 3d1e08f8151..75a31925c33 100644 --- a/code/modules/mob/living/carbon/examine.dm +++ b/code/modules/mob/living/carbon/examine.dm @@ -154,7 +154,7 @@ SEND_SIGNAL(src, COMSIG_ATOM_EXAMINE, user, .) -//SKYRAT EDIT REMOVAL - MOVED - MEDICAL +//SKYRAT EDIT REMOVAL - MOVED - MEDICAL - carbon_examine.dm /* /mob/living/carbon/examine_more(mob/user) . = ..() diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index a77156dddfa..eb4bb54ea80 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -1327,7 +1327,7 @@ GLOBAL_LIST_EMPTY(features_by_species) if(!(prob(25 + (weapon.force * 2)))) return TRUE - if(IS_ORGANIC_LIMB(affecting)) + if(affecting.can_bleed()) weapon.add_mob_blood(human) //Make the weapon bloody, not the person. if(prob(weapon.force * 2)) //blood spatter! bloody = TRUE @@ -1706,19 +1706,19 @@ GLOBAL_LIST_EMPTY(features_by_species) // Lets pick a random body part and check for an existing burn var/obj/item/bodypart/bodypart = pick(humi.bodyparts) - var/datum/wound/burn/existing_burn = locate(/datum/wound/burn) in bodypart.wounds + var/datum/wound/burn/flesh/existing_burn = locate(/datum/wound/burn) in bodypart.wounds // If we have an existing burn try to upgrade it if(existing_burn) switch(existing_burn.severity) if(WOUND_SEVERITY_MODERATE) if(humi.bodytemperature > BODYTEMP_HEAT_WOUND_LIMIT + 400) // 800k - bodypart.force_wound_upwards(/datum/wound/burn/severe, wound_source = "hot temperatures") + bodypart.force_wound_upwards(/datum/wound/burn/flesh/severe, wound_source = "hot temperatures") if(WOUND_SEVERITY_SEVERE) if(humi.bodytemperature > BODYTEMP_HEAT_WOUND_LIMIT + 2800) // 3200k - bodypart.force_wound_upwards(/datum/wound/burn/critical, wound_source = "hot temperatures") + bodypart.force_wound_upwards(/datum/wound/burn/flesh/critical, wound_source = "hot temperatures") else // If we have no burn apply the lowest level burn - bodypart.force_wound_upwards(/datum/wound/burn/moderate, wound_source = "hot temperatures") + bodypart.force_wound_upwards(/datum/wound/burn/flesh/moderate, wound_source = "hot temperatures") // always take some burn damage var/burn_damage = HEAT_DAMAGE_LEVEL_1 diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index b8d21e60daa..1475d61ed38 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -705,11 +705,7 @@ //SKYRAT EDIT ADDITION BEGIN - MEDICAL if(body_part.current_gauze) - var/datum/bodypart_aid/current_gauze = body_part.current_gauze - combined_msg += "\t [span_notice("Your [body_part.name] is [current_gauze.desc_prefix] with [current_gauze.get_description()].")]" - if(body_part.current_splint) - var/datum/bodypart_aid/current_splint = body_part.current_splint - combined_msg += "\t [span_notice("Your [body_part.name] is [current_splint.desc_prefix] with [current_splint.get_description()].")]" + combined_msg += "\t [span_notice("Your [body_part.name] is [body_part.current_gauze.get_gauze_usage_prefix()] with [body_part.current_gauze.get_gauze_description()].")]" //SKYRAT EDIT END for(var/t in missing) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 41273946aa5..818ca1cf860 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -169,13 +169,15 @@ if(LAZYLEN(scar_data) != SCAR_SAVE_LENGTH) return // invalid, should delete var/version = text2num(scar_data[SCAR_SAVE_VERS]) - if(!version || version < SCAR_CURRENT_VERSION) // get rid of old scars + if(!version || version != SCAR_CURRENT_VERSION) // get rid of scars using a incompatable version return if(specified_char_index && (mind?.original_character_slot_index != specified_char_index)) return + if (isnull(text2num(scar_data[SCAR_SAVE_BIOLOGY]))) + return var/obj/item/bodypart/the_part = get_bodypart("[scar_data[SCAR_SAVE_ZONE]]") var/datum/scar/scaries = new - return scaries.load(the_part, scar_data[SCAR_SAVE_VERS], scar_data[SCAR_SAVE_DESC], scar_data[SCAR_SAVE_PRECISE_LOCATION], text2num(scar_data[SCAR_SAVE_SEVERITY]), text2num(scar_data[SCAR_SAVE_BIOLOGY]), text2num(scar_data[SCAR_SAVE_CHAR_SLOT])) + return scaries.load(the_part, scar_data[SCAR_SAVE_VERS], scar_data[SCAR_SAVE_DESC], scar_data[SCAR_SAVE_PRECISE_LOCATION], text2num(scar_data[SCAR_SAVE_SEVERITY]), text2num(scar_data[SCAR_SAVE_BIOLOGY]), text2num(scar_data[SCAR_SAVE_CHAR_SLOT]), text2num(scar_data[SCAR_SAVE_CHECK_ANY_BIO])) /// Read all the scars we have for the designated character/scar slots, verify they're good/dump them if they're old/wrong format, create them on the user, and write the scars that passed muster back to the file /mob/living/carbon/human/proc/load_persistent_scars() diff --git a/code/modules/mob/living/carbon/human/species_types/abductors.dm b/code/modules/mob/living/carbon/human/species_types/abductors.dm index ed9eb3c1094..58a46da81a4 100644 --- a/code/modules/mob/living/carbon/human/species_types/abductors.dm +++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm @@ -9,6 +9,8 @@ TRAIT_VIRUSIMMUNE, TRAIT_NOBLOOD, TRAIT_CHUNKYFINGERS_IGNORE_BATON, + TRAIT_NODISMEMBER, + TRAIT_NEVER_WOUNDED ) mutanttongue = /obj/item/organ/internal/tongue/abductor mutantstomach = null diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index cf16c236605..3f5f46edf6c 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -7,7 +7,6 @@ TRAIT_GENELESS, TRAIT_LAVA_IMMUNE, TRAIT_NOBREATH, - TRAIT_NODISMEMBER, TRAIT_NOBLOOD, TRAIT_NOFIRE, TRAIT_PIERCEIMMUNE, @@ -15,6 +14,8 @@ TRAIT_NO_DNA_COPY, TRAIT_NO_TRANSFORMATION_STING, TRAIT_NO_AUGMENTS, + TRAIT_NODISMEMBER, + TRAIT_NEVER_WOUNDED ) mutantheart = null mutantlungs = null diff --git a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm index d7b8fdf34db..a8b1be203a3 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -10,6 +10,8 @@ TRAIT_RADIMMUNE, TRAIT_VIRUSIMMUNE, TRAIT_NOBLOOD, + TRAIT_NODISMEMBER, + TRAIT_NEVER_WOUNDED ) inherent_factions = list(FACTION_FAITHLESS) changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index c2e46d697cd..cea0d00fc21 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -49,8 +49,6 @@ handle_diseases(seconds_per_tick, times_fired)// DEAD check is in the proc itself; we want it to spread even if the mob is dead, but to handle its disease-y properties only if you're not. - handle_wounds(seconds_per_tick, times_fired) - if (QDELETED(src)) // diseases can qdel the mob via transformations return @@ -65,6 +63,8 @@ handle_gravity(seconds_per_tick, times_fired) + handle_wounds(seconds_per_tick, times_fired) + if(machine) machine.check_eye(src) diff --git a/code/modules/paperwork/paper_cutter.dm b/code/modules/paperwork/paper_cutter.dm index 0dddb90c1db..31cbe153f9e 100644 --- a/code/modules/paperwork/paper_cutter.dm +++ b/code/modules/paperwork/paper_cutter.dm @@ -171,7 +171,7 @@ to_chat(user, span_userdanger("You neatly cut [stored_paper][clumsy ? "... and your finger in the process!" : "."]")) if(clumsy) var/obj/item/bodypart/finger = user.get_active_hand() - var/datum/wound/slash/moderate/papercut = new + var/datum/wound/slash/flesh/moderate/papercut = new papercut.apply_wound(finger, wound_source = "paper cut") stored_paper = null qdel(stored_paper) diff --git a/code/modules/religion/festival/instrument_rites.dm b/code/modules/religion/festival/instrument_rites.dm index 83b064a6398..a1c94c92425 100644 --- a/code/modules/religion/festival/instrument_rites.dm +++ b/code/modules/religion/festival/instrument_rites.dm @@ -90,7 +90,7 @@ /datum/religion_rites/song_tuner/pain/finish_effect(mob/living/carbon/human/listener, atom/song_source) var/obj/item/bodypart/sliced_limb = pick(listener.bodyparts) - sliced_limb.force_wound_upwards(/datum/wound/slash/moderate/many_cuts) + sliced_limb.force_wound_upwards(/datum/wound/slash/flesh/moderate/many_cuts) /datum/religion_rites/song_tuner/lullaby name = "Spiritual Lullaby" diff --git a/code/modules/religion/sparring/sparring_datum.dm b/code/modules/religion/sparring/sparring_datum.dm index f292293f90c..bfaa94d65a8 100644 --- a/code/modules/religion/sparring/sparring_datum.dm +++ b/code/modules/religion/sparring/sparring_datum.dm @@ -216,7 +216,7 @@ var/mob/living/carbon/human/branded = interfering to_chat(interfering, span_warning("[GLOB.deity] brands your flesh for interfering with [chaplain]'s sparring match!!")) var/obj/item/bodypart/branded_limb = pick(branded.bodyparts) - branded_limb.force_wound_upwards(/datum/wound/burn/severe/brand, wound_source = "divine intervention") + branded_limb.force_wound_upwards(/datum/wound/burn/flesh/severe/brand, wound_source = "divine intervention") branded.emote("scream") flubs-- diff --git a/code/modules/spells/spell_types/touch/scream_for_me.dm b/code/modules/spells/spell_types/touch/scream_for_me.dm index 941885e7577..e10bdaebcc5 100644 --- a/code/modules/spells/spell_types/touch/scream_for_me.dm +++ b/code/modules/spells/spell_types/touch/scream_for_me.dm @@ -21,7 +21,7 @@ span_userdanger("The spell bounces from [victim]'s skin back into your arm!"), ) var/obj/item/bodypart/to_wound = caster.get_holding_bodypart_of_item(hand) - to_wound.force_wound_upwards(/datum/wound/slash/critical) + to_wound.force_wound_upwards(/datum/wound/slash/flesh/critical) /datum/action/cooldown/spell/touch/scream_for_me/cast_on_hand_hit(obj/item/melee/touch_attack/hand, mob/living/victim, mob/living/carbon/caster) if(!ishuman(victim)) @@ -29,7 +29,7 @@ var/mob/living/carbon/human/human_victim = victim human_victim.emote("scream") for(var/obj/item/bodypart/to_wound as anything in human_victim.bodyparts) - to_wound.force_wound_upwards(/datum/wound/slash/critical) + to_wound.force_wound_upwards(/datum/wound/slash/flesh/critical) return TRUE /obj/item/melee/touch_attack/scream_for_me diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 2b85e7843ff..5967e3502dc 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -1,3 +1,6 @@ +#define AUGGED_LIMB_EMP_BRUTE_DAMAGE 3 +#define AUGGED_LIMB_EMP_BURN_DAMAGE 2 + /obj/item/bodypart name = "limb" desc = "Why is it detached..." @@ -22,14 +25,15 @@ /// DO NOT MODIFY DIRECTLY. Use set_owner() var/mob/living/carbon/owner + /// If this limb can be scarred. + var/scarrable = TRUE + /** * A bitfield of biological states, exclusively used to determine which wounds this limb will get, * as well as how easily it will happen. - * Set to BIO_FLESH_BONE because most species have both flesh and bone in their limbs. - * - * This currently has absolutely no meaning for robotic limbs. + * Set to BIO_STANDARD because most species have both flesh bone and blood in their limbs. */ - var/biological_state = BIO_FLESH_BONE + var/biological_state = BIO_STANDARD ///A bitfield of bodytypes for clothing, surgery, and misc information var/bodytype = BODYTYPE_HUMANOID | BODYTYPE_ORGANIC ///Defines when a bodypart should not be changed. Example: BP_BLOCK_CHANGE_SPECIES prevents the limb from being overwritten on species gain @@ -66,16 +70,14 @@ var/speed_modifier = 0 // Limb disabling variables + ///Whether it is possible for the limb to be disabled whatsoever. TRUE means that it is possible. + var/can_be_disabled = FALSE //Defaults to FALSE, as only human limbs can be disabled, and only the appendages. ///Controls if the limb is disabled. TRUE means it is disabled (similar to being removed, but still present for the sake of targeted interactions). var/bodypart_disabled = FALSE ///Handles limb disabling by damage. If 0 (0%), a limb can't be disabled via damage. If 1 (100%), it is disabled at max limb damage. Anything between is the percentage of damage against maximum limb damage needed to disable the limb. - //var/disabling_threshold_percentage = 0 //ORIGINAL - var/disabling_threshold_percentage = 1 //SKYRAT EDIT CHANGE - COMBAT - ///Whether it is possible for the limb to be disabled whatsoever. TRUE means that it is possible. - var/can_be_disabled = FALSE //Defaults to FALSE, as only human limbs can be disabled, and only the appendages. - - // Damage state variables + var/disabling_threshold_percentage = 1 //SKYRAT EDIT CHANGE - COMBAT - ORIGINAL : var/disabling_threshold_percentage = 0 + // Damage variables ///A mutiplication of the burn and brute damage that the limb's stored damage contributes to its attached mob's overall wellbeing. var/body_damage_coeff = 1 ///The current amount of brute damage the limb has @@ -152,20 +154,8 @@ var/cached_bleed_rate = 0 /// How much generic bleedstacks we have on this bodypart var/generic_bleedstacks - //SKYRAT EDIT CHANGE BEGIN - MEDICAL - /* /// If we have a gauze wrapping currently applied (not including splints) var/obj/item/stack/current_gauze - */ - /// If we have a gauze wrapping currently applied - var/datum/bodypart_aid/gauze/current_gauze - /// If we have a splint currently applied - var/datum/bodypart_aid/splint/current_splint - /// What icon do we use to render this limb? Ususally used by robotic limb augments. - var/rendered_bp_icon - /// Do we use an organic render for this robotic limb? - var/organic_render = TRUE - //SKYRAT EDIT CHANGE END /// If something is currently grasping this bodypart and trying to staunch bleeding (see [/obj/item/hand_item/self_grasp]) var/obj/item/hand_item/self_grasp/grasped_by @@ -200,6 +190,16 @@ /// List of the above datums which have actually been instantiated, managed automatically var/list/feature_offsets = list() + /// In the case we dont have dismemberable features, or literally cant get wounds, we will use this percent to determine when we can be dismembered. + /// Compared to our ABSOLUTE maximum. Stored in decimal; 0.8 = 80%. + var/hp_percent_to_dismemberable = 0.8 + /// If true, we will use [hp_percent_to_dismemberable] even if we are dismemberable via wounds. Useful for things with extreme wound resistance. + var/use_alternate_dismemberment_calc_even_if_mangleable = FALSE + /// If false, no wound that can be applied to us can mangle our flesh. Used for determining if we should use [hp_percent_to_dismemberable] instead of normal dismemberment. + var/any_existing_wound_can_mangle_our_flesh + /// If false, no wound that can be applied to us can mangle our bone. Used for determining if we should use [hp_percent_to_dismemberable] instead of normal dismemberment. + var/any_existing_wound_can_mangle_our_bone + /obj/item/bodypart/apply_fantasy_bonuses(bonus) . = ..() unarmed_damage_low = modify_fantasy_variable("unarmed_damage_low", unarmed_damage_low, bonus, minimum = 1) @@ -241,12 +241,6 @@ if(length(wounds)) stack_trace("[type] qdeleted with [length(wounds)] uncleared wounds") wounds.Cut() - //SKYRAT EDIT ADDITION BEGIN - MEDICAL - if(current_gauze) - qdel(current_gauze) - if(current_splint) - qdel(current_splint) - //SKYRAT EDIT ADDITION END if(length(external_organs)) for(var/obj/item/organ/external/external_organ as anything in external_organs) @@ -415,11 +409,7 @@ var/atom/drop_loc = drop_location() if(IS_ORGANIC_LIMB(src)) playsound(drop_loc, 'sound/misc/splort.ogg', 50, TRUE, -1) - //seep_gauze(9999) // destroy any existing gauze if any exists - if(current_gauze) - qdel(current_gauze) - if(current_splint) - qdel(current_splint) + seep_gauze(9999) // destroy any existing gauze if any exists for(var/obj/item/organ/bodypart_organ in get_organs()) bodypart_organ.transfer_to_limb(src, owner) for(var/obj/item/organ/external/external in external_organs) @@ -505,40 +495,75 @@ else if (sharpness & SHARP_POINTY) wounding_type = WOUND_PIERCE - if(owner) + if(owner) // i tried to modularize the below, but the modifications to wounding_dmg and wounding_type cant be extracted to a proc var/mangled_state = get_mangled_state() var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%) - //Handling for bone only/flesh only(none right now)/flesh and bone targets - switch(biological_state) - // if we're bone only, all cutting attacks go straight to the bone - if(BIO_BONE) - if(wounding_type == WOUND_SLASH) - wounding_type = WOUND_BLUNT - wounding_dmg *= (easy_dismember ? 1 : 0.6) - else if(wounding_type == WOUND_PIERCE) - wounding_type = WOUND_BLUNT - wounding_dmg *= (easy_dismember ? 1 : 0.75) - if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)) - return - // note that there's no handling for BIO_FLESH since we don't have any that are that right now (slimepeople maybe someday) - // standard humanoids - if(BIO_FLESH_BONE) - //SKYRAT EDIT ADDITION BEGIN - MEDICAL - //We do a body zone check here because muscles dont have any variants for head or chest, and rolling a muscle wound on them wound end up on a wasted wound roll - if(body_zone != BODY_ZONE_CHEST && body_zone != BODY_ZONE_HEAD && prob(35)) - wounding_type = WOUND_MUSCLE - //SKYRAT EDIT ADDITION END - // if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate - // So a big sharp weapon is still all you need to destroy a limb - if((mangled_state & BODYPART_MANGLED_FLESH) && !(mangled_state & BODYPART_MANGLED_BONE) && sharpness) - playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100) - if(wounding_type == WOUND_SLASH && !easy_dismember) - wounding_dmg *= 0.6 // edged weapons pass along 60% of their wounding damage to the bone since the power is spread out over a larger area - if(wounding_type == WOUND_PIERCE && !easy_dismember) - wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated - wounding_type = WOUND_BLUNT - else if((mangled_state & BODYPART_MANGLED_FLESH) && (mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)) + var/has_exterior = FALSE + var/has_interior = FALSE + + for (var/state as anything in GLOB.bio_state_states) + var/flag = text2num(state) + if (!(biological_state & flag)) + continue + + var/value = GLOB.bio_state_states[state] + if (value & BIO_EXTERIOR) + has_exterior = TRUE + if (value & BIO_INTERIOR) + has_interior = TRUE + + if (has_exterior && has_interior) + break + + // We put this here so we dont increase init time by doing this all at once on initialization + // Effectively, we "lazy load" + if (isnull(any_existing_wound_can_mangle_our_bone) || isnull(any_existing_wound_can_mangle_our_flesh)) + any_existing_wound_can_mangle_our_bone = FALSE + any_existing_wound_can_mangle_our_flesh = FALSE + for (var/datum/wound/wound_type as anything in GLOB.all_wound_pregen_data) + var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[wound_type] + if (!pregen_data.can_be_applied_to(src, random_roll = TRUE)) // we only consider randoms because non-randoms are usually really specific + continue + if (initial(pregen_data.wound_path_to_generate.wound_flags) & MANGLES_FLESH) + any_existing_wound_can_mangle_our_flesh = TRUE + if (initial(pregen_data.wound_path_to_generate.wound_flags) & MANGLES_BONE) + any_existing_wound_can_mangle_our_bone = TRUE + + if (any_existing_wound_can_mangle_our_bone && any_existing_wound_can_mangle_our_flesh) + break + + var/can_theoretically_be_dismembered = (any_existing_wound_can_mangle_our_bone || (any_existing_wound_can_mangle_our_flesh && !has_exterior)) + + var/exterior_ready_to_dismember = (!has_exterior || ((mangled_state & BODYPART_MANGLED_BONE) == BODYPART_MANGLED_BONE)) + var/interior_ready_to_dismember = (!has_interior || ((mangled_state & BODYPART_MANGLED_FLESH) == BODYPART_MANGLED_FLESH)) + + // if we're bone only, all cutting attacks go straight to the bone + if(has_exterior && interior_ready_to_dismember) + if(wounding_type == WOUND_SLASH) + wounding_type = WOUND_BLUNT + wounding_dmg *= (easy_dismember ? 1 : 0.6) + else if(wounding_type == WOUND_PIERCE) + wounding_type = WOUND_BLUNT + wounding_dmg *= (easy_dismember ? 1 : 0.75) + if(exterior_ready_to_dismember && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)) + return + else + // if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate + // So a big sharp weapon is still all you need to destroy a limb + if(has_exterior && interior_ready_to_dismember && !(mangled_state & BODYPART_MANGLED_BONE) && sharpness) + playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100) + if(wounding_type == WOUND_SLASH && !easy_dismember) + wounding_dmg *= 0.6 // edged weapons pass along 60% of their wounding damage to the bone since the power is spread out over a larger area + if(wounding_type == WOUND_PIERCE && !easy_dismember) + wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated + wounding_type = WOUND_BLUNT + else if(interior_ready_to_dismember && exterior_ready_to_dismember && try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)) + return + if (use_alternate_dismemberment_calc_even_if_mangleable || !can_theoretically_be_dismembered) + var/percent_to_total_max = (get_damage() / max_damage) + if (percent_to_total_max >= hp_percent_to_dismemberable) + if (try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus)) return // now we have our wounding_type and are ready to carry on with wounds and dealing the actual damage @@ -552,15 +577,14 @@ damaged_percent = DAMAGED_BODYPART_BONUS_WOUNDING_THRESHOLD wounding_dmg = min(DAMAGED_BODYPART_BONUS_WOUNDING_BONUS, wounding_dmg + (damaged_percent * DAMAGED_BODYPART_BONUS_WOUNDING_COEFF)) - if(current_gauze) - current_gauze.take_damage() - if(current_splint) - current_splint.take_damage() + if (istype(current_gauze, /obj/item/stack/medical/gauze)) + var/obj/item/stack/medical/gauze/our_gauze = current_gauze + our_gauze.get_hit() //SKYRAT EDIT ADDITION END - MEDICAL check_wounding(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus, attack_direction, damage_source = damage_source) for(var/datum/wound/iter_wound as anything in wounds) - iter_wound.receive_damage(wounding_type, wounding_dmg, wound_bonus) + iter_wound.receive_damage(wounding_type, wounding_dmg, wound_bonus, damage_source) /* // END WOUND HANDLING @@ -1162,7 +1186,7 @@ if(!owner) return - if(HAS_TRAIT(owner, TRAIT_NOBLOOD) || !IS_ORGANIC_LIMB(src)) + if(!can_bleed()) if(cached_bleed_rate != old_bleed_rate) update_part_wound_overlay() return @@ -1203,7 +1227,7 @@ /obj/item/bodypart/proc/update_part_wound_overlay() if(!owner) return FALSE - if(HAS_TRAIT(owner, TRAIT_NOBLOOD) || !IS_ORGANIC_LIMB(src)) + if(!can_bleed()) if(bleed_overlay_icon) bleed_overlay_icon = null owner.update_wound_overlays() @@ -1236,6 +1260,11 @@ #undef BLEED_OVERLAY_MED #undef BLEED_OVERLAY_GUSH +/obj/item/bodypart/proc/can_bleed() + SHOULD_BE_PURE(TRUE) + + return ((biological_state & BIO_BLOODED) && (!owner || !HAS_TRAIT(owner, TRAIT_NOBLOOD))) + /** * apply_gauze() is used to- well, apply gauze to a bodypart * @@ -1247,7 +1276,6 @@ * Arguments: * * gauze- Just the gauze stack we're taking a sheet from to apply here */ -/* SKYRAT EDIT REMOVAL /obj/item/bodypart/proc/apply_gauze(obj/item/stack/gauze) if(!istype(gauze) || !gauze.absorption_capacity) return @@ -1259,7 +1287,6 @@ gauze.use(1) if(newly_gauzed) SEND_SIGNAL(src, COMSIG_BODYPART_GAUZED, gauze) -*/ /** * seep_gauze() is for when a gauze wrapping absorbs blood or pus from wounds, lowering its absorption capacity. @@ -1269,7 +1296,6 @@ * Arguments: * * seep_amt - How much absorption capacity we're removing from our current bandages (think, how much blood or pus are we soaking up this tick?) */ -/* SKYRAT EDIT REMOVAL /obj/item/bodypart/proc/seep_gauze(seep_amt = 0) if(!current_gauze) return @@ -1278,7 +1304,6 @@ owner.visible_message(span_danger("\The [current_gauze.name] on [owner]'s [name] falls away in rags."), span_warning("\The [current_gauze.name] on your [name] falls away in rags."), vision_distance=COMBAT_MESSAGE_RANGE) QDEL_NULL(current_gauze) SEND_SIGNAL(src, COMSIG_BODYPART_GAUZE_DESTROYED) -*/ ///Loops through all of the bodypart's external organs and update's their color. /obj/item/bodypart/proc/recolor_external_organs() @@ -1328,14 +1353,17 @@ /obj/item/bodypart/emp_act(severity) . = ..() - if(. & EMP_PROTECT_WIRES || !(bodytype & BODYTYPE_ROBOTIC)) + if(. & EMP_PROTECT_WIRES || !IS_ROBOTIC_LIMB(src)) return FALSE owner.visible_message(span_danger("[owner]'s [src.name] seems to malfunction!")) + // with defines at the time of writing, this is 3 brute and 2 burn + // 3 + 2 = 5, with 6 limbs thats 30, on a heavy 60 + // 60 * 0.8 = 48 var/time_needed = 10 SECONDS - var/brute_damage = 2.5 // SKYRAT EDIT : Balances direct EMP damage for Brute - SR's synth values are multiplied 3x 2.5 * 1.3 * 1.3 - var/burn_damage = 2 // SKYRAT EDIT : Balances direct EMP damage for Burn - SR's synth values are multiplied 3x 2 * 1.3 * 1.3 + var/brute_damage = AUGGED_LIMB_EMP_BRUTE_DAMAGE + var/burn_damage = AUGGED_LIMB_EMP_BURN_DAMAGE if(severity == EMP_HEAVY) time_needed *= 2 brute_damage *= 1.3 // SKYRAT EDIT : Balance - Lowers total damage from ~125 Brute to ~30 diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index 850bfc7b9e7..22a325f1974 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -1,11 +1,11 @@ /obj/item/bodypart/proc/can_dismember(obj/item/item) - if(bodypart_flags & BODYPART_UNREMOVABLE) + if(bodypart_flags & BODYPART_UNREMOVABLE || (owner && HAS_TRAIT(owner, TRAIT_NODISMEMBER))) return FALSE return TRUE ///Remove target limb from it's owner, with side effects. -/obj/item/bodypart/proc/dismember(dam_type = BRUTE, silent=TRUE) +/obj/item/bodypart/proc/dismember(dam_type = BRUTE, silent=TRUE, wound_type) if(!owner || (bodypart_flags & BODYPART_UNREMOVABLE)) return FALSE var/mob/living/carbon/limb_owner = owner @@ -22,11 +22,15 @@ playsound(get_turf(limb_owner), 'sound/effects/dismember.ogg', 80, TRUE) limb_owner.add_mood_event("dismembered_[body_zone]", /datum/mood_event/dismembered, src) limb_owner.add_mob_memory(/datum/memory/was_dismembered, lost_limb = src) + + if (wound_type) + LAZYSET(limb_owner.body_zone_dismembered_by, body_zone, wound_type) + drop_limb() limb_owner.update_equipment_speed_mods() // Update in case speed affecting item unequipped by dismemberment var/turf/owner_location = limb_owner.loc - if(istype(owner_location)) + if(wound_type != WOUND_BURN && istype(owner_location) && can_bleed()) limb_owner.add_splatter_floor(owner_location) if(QDELETED(src)) //Could have dropped into lava/explosion/chasm/whatever @@ -34,8 +38,9 @@ if(dam_type == BURN) burn() return TRUE - add_mob_blood(limb_owner) - limb_owner.bleed(rand(20, 40)) + if (can_bleed()) + add_mob_blood(limb_owner) + limb_owner.bleed(rand(20, 40)) var/direction = pick(GLOB.cardinals) var/t_range = rand(2,max(throw_range/2, 2)) var/turf/target_turf = get_turf(src) @@ -47,10 +52,10 @@ if(new_turf.density) break throw_at(target_turf, throw_range, throw_speed) + return TRUE - -/obj/item/bodypart/chest/dismember() +/obj/item/bodypart/chest/dismember(dam_type = BRUTE, silent=TRUE, wound_type) if(!owner) return FALSE var/mob/living/carbon/chest_owner = owner @@ -59,7 +64,7 @@ if(HAS_TRAIT(chest_owner, TRAIT_NODISMEMBER)) return FALSE . = list() - if(isturf(chest_owner.loc)) + if(wound_type != WOUND_BURN && isturf(chest_owner.loc) && can_bleed()) chest_owner.add_splatter_floor(chest_owner.loc) playsound(get_turf(chest_owner), 'sound/misc/splort.ogg', 80, TRUE) for(var/obj/item/organ/organ as anything in chest_owner.organs) @@ -81,8 +86,6 @@ . += cavity_item cavity_item = null - - ///limb removal. The "special" argument is used for swapping a limb with a new one without the effects of losing a limb kicking in. /obj/item/bodypart/proc/drop_limb(special, dismembered) if(!owner) @@ -180,14 +183,17 @@ * * bare_wound_bonus: ditto above */ /obj/item/bodypart/proc/try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus) + if (!can_dismember()) + return + if(wounding_dmg < DISMEMBER_MINIMUM_DAMAGE) return var/base_chance = wounding_dmg base_chance += (get_damage() / max_damage * 50) // how much damage we dealt with this blow, + 50% of the damage percentage we already had on this bodypart - if(locate(/datum/wound/blunt/critical) in wounds) // we only require a severe bone break, but if there's a critical bone break, we'll add 15% more - base_chance += 15 + for (var/datum/wound/iterated_wound as anything in wounds) + base_chance += iterated_wound.get_dismember_chance_bonus(base_chance) if(prob(base_chance)) var/datum/wound/loss/dismembering = new @@ -328,6 +334,8 @@ set_owner(new_limb_owner) new_limb_owner.add_bodypart(src) + LAZYREMOVE(new_limb_owner.body_zone_dismembered_by, body_zone) + if(special) //non conventional limb attachment for(var/datum/surgery/attach_surgery as anything in new_limb_owner.surgeries) //if we had an ongoing surgery to attach a new limb, we stop it. var/surgery_zone = check_zone(attach_surgery.location) @@ -416,12 +424,15 @@ /mob/living/carbon/proc/regenerate_limbs(list/excluded_zones = list()) SEND_SIGNAL(src, COMSIG_CARBON_REGENERATE_LIMBS, excluded_zones) var/list/zone_list = list(BODY_ZONE_HEAD, BODY_ZONE_CHEST, BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, BODY_ZONE_R_LEG, BODY_ZONE_L_LEG) + + var/list/dismembered_by_copy = body_zone_dismembered_by?.Copy() + if(length(excluded_zones)) zone_list -= excluded_zones for(var/limb_zone in zone_list) - regenerate_limb(limb_zone) + regenerate_limb(limb_zone, dismembered_by_copy) -/mob/living/carbon/proc/regenerate_limb(limb_zone) +/mob/living/carbon/proc/regenerate_limb(limb_zone, list/dismembered_by_copy = body_zone_dismembered_by?.Copy()) var/obj/item/bodypart/limb if(get_bodypart(limb_zone)) return FALSE @@ -431,9 +442,16 @@ qdel(limb) return FALSE limb.update_limb(is_creating = TRUE) - var/datum/scar/scaries = new - var/datum/wound/loss/phantom_loss = new // stolen valor, really - scaries.generate(limb, phantom_loss) + if (LAZYLEN(dismembered_by_copy)) + var/datum/scar/scaries = new + var/datum/wound/loss/phantom_loss = new // stolen valor, really + phantom_loss.loss_wound_type = dismembered_by_copy?[limb_zone] + if (phantom_loss.loss_wound_type) + scaries.generate(limb, phantom_loss) + LAZYREMOVE(dismembered_by_copy, limb_zone) // in case we're using a passed list + else + qdel(scaries) + qdel(phantom_loss) //Copied from /datum/species/proc/on_species_gain() for(var/obj/item/organ/external/organ_path as anything in dna.species.external_organs) diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index 73e7d4207e5..30fb63a8034 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -191,9 +191,10 @@ /obj/item/bodypart/head/update_limb(dropping_limb, is_creating) . = ..() if(!isnull(owner)) - real_name = owner.real_name - if(HAS_TRAIT(owner, TRAIT_HUSK)) - real_name = "Unknown" + if(HAS_TRAIT(owner, TRAIT_HUSK)) + real_name = "Unknown" + else + real_name = owner.real_name update_hair_and_lips(dropping_limb, is_creating) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index cbe533de54d..d022e003f2f 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -114,6 +114,8 @@ /// Datum describing how to offset things held in the hands of this arm, the x offset IS functional here var/datum/worn_feature_offset/held_hand_offset + biological_state = (BIO_STANDARD|BIO_JOINTED) + /obj/item/bodypart/arm/Destroy() QDEL_NULL(worn_glove_offset) QDEL_NULL(held_hand_offset) @@ -344,6 +346,8 @@ /// Datum describing how to offset things worn on the foot of this leg, note that an x offset won't do anything here var/datum/worn_feature_offset/worn_foot_offset + biological_state = (BIO_STANDARD|BIO_JOINTED) + /obj/item/bodypart/leg/Destroy() QDEL_NULL(worn_foot_offset) return ..() diff --git a/code/modules/surgery/bodyparts/robot_bodyparts.dm b/code/modules/surgery/bodyparts/robot_bodyparts.dm index cd0ac286559..0382f4b048f 100644 --- a/code/modules/surgery/bodyparts/robot_bodyparts.dm +++ b/code/modules/surgery/bodyparts/robot_bodyparts.dm @@ -37,6 +37,8 @@ medium_burn_msg = ROBOTIC_MEDIUM_BURN_MSG heavy_burn_msg = ROBOTIC_HEAVY_BURN_MSG + biological_state = (BIO_ROBOTIC|BIO_JOINTED) + damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT, CLONE = DEFAULT_CLONE_EXAMINE_TEXT) disabling_threshold_percentage = 1 @@ -58,6 +60,7 @@ brute_modifier = 0.8 burn_modifier = 0.8 + disabling_threshold_percentage = 1 light_brute_msg = ROBOTIC_LIGHT_BRUTE_MSG @@ -68,6 +71,8 @@ medium_burn_msg = ROBOTIC_MEDIUM_BURN_MSG heavy_burn_msg = ROBOTIC_HEAVY_BURN_MSG + biological_state = (BIO_ROBOTIC|BIO_JOINTED) + damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT, CLONE = DEFAULT_CLONE_EXAMINE_TEXT) /obj/item/bodypart/leg/left/robot @@ -88,6 +93,7 @@ brute_modifier = 0.8 burn_modifier = 0.8 + disabling_threshold_percentage = 1 light_brute_msg = ROBOTIC_LIGHT_BRUTE_MSG @@ -98,6 +104,8 @@ medium_burn_msg = ROBOTIC_MEDIUM_BURN_MSG heavy_burn_msg = ROBOTIC_HEAVY_BURN_MSG + biological_state = (BIO_ROBOTIC|BIO_JOINTED) + damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT, CLONE = DEFAULT_CLONE_EXAMINE_TEXT) /obj/item/bodypart/leg/left/robot/emp_act(severity) @@ -127,6 +135,7 @@ brute_modifier = 0.8 burn_modifier = 0.8 + disabling_threshold_percentage = 1 light_brute_msg = ROBOTIC_LIGHT_BRUTE_MSG @@ -137,6 +146,8 @@ medium_burn_msg = ROBOTIC_MEDIUM_BURN_MSG heavy_burn_msg = ROBOTIC_HEAVY_BURN_MSG + biological_state = (BIO_ROBOTIC|BIO_JOINTED) + damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT, CLONE = DEFAULT_CLONE_EXAMINE_TEXT) /obj/item/bodypart/leg/right/robot/emp_act(severity) @@ -174,6 +185,8 @@ medium_burn_msg = ROBOTIC_MEDIUM_BURN_MSG heavy_burn_msg = ROBOTIC_HEAVY_BURN_MSG + biological_state = (BIO_ROBOTIC) + damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT, CLONE = DEFAULT_CLONE_EXAMINE_TEXT) var/wired = FALSE @@ -294,6 +307,8 @@ medium_burn_msg = ROBOTIC_MEDIUM_BURN_MSG heavy_burn_msg = ROBOTIC_HEAVY_BURN_MSG + biological_state = (BIO_ROBOTIC) + damage_examines = list(BRUTE = ROBOTIC_BRUTE_EXAMINE_TEXT, BURN = ROBOTIC_BURN_EXAMINE_TEXT, CLONE = DEFAULT_CLONE_EXAMINE_TEXT) head_flags = HEAD_EYESPRITES @@ -380,6 +395,11 @@ flash2?.forceMove(drop_loc) return ..() +// Prosthetics - Cheap, mediocre, and worse than organic limbs +// The fact they dont have a internal biotype means theyre a lot weaker defensively, +// since they skip slash and go right to blunt +// They are VERY easy to delimb as a result +// HP is also reduced just in case this isnt enough /obj/item/bodypart/arm/left/robot/surplus name = "surplus prosthetic left arm" @@ -390,6 +410,8 @@ brute_modifier = 1 max_damage = 20 + biological_state = (BIO_METAL|BIO_JOINTED) + /obj/item/bodypart/arm/right/robot/surplus name = "surplus prosthetic right arm" desc = "A skeletal, robotic limb. Outdated and fragile, but it's still better than nothing." @@ -399,6 +421,8 @@ brute_modifier = 1 max_damage = 20 + biological_state = (BIO_METAL|BIO_JOINTED) + /obj/item/bodypart/leg/left/robot/surplus name = "surplus prosthetic left leg" desc = "A skeletal, robotic limb. Outdated and fragile, but it's still better than nothing." @@ -408,6 +432,8 @@ burn_modifier = 1 max_damage = 20 + biological_state = (BIO_METAL|BIO_JOINTED) + /obj/item/bodypart/leg/right/robot/surplus name = "surplus prosthetic right leg" desc = "A skeletal, robotic limb. Outdated and fragile, but it's still better than nothing." @@ -417,6 +443,8 @@ burn_modifier = 1 max_damage = 20 + biological_state = (BIO_METAL|BIO_JOINTED) + #undef ROBOTIC_LIGHT_BRUTE_MSG #undef ROBOTIC_MEDIUM_BRUTE_MSG #undef ROBOTIC_HEAVY_BRUTE_MSG diff --git a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm index e57c014c02b..1126d1ee036 100644 --- a/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/misc_bodyparts.dm @@ -1,19 +1,19 @@ ///SNAIL /obj/item/bodypart/head/snail - biological_state = BIO_FLESH //SKYRAT EDIT - Roundstart Snails - Now invertebrates! + biological_state = (BIO_BLOODED|BIO_FLESH) //SKYRAT EDIT - Roundstart Snails - Now invertebrates! limb_id = SPECIES_SNAIL is_dimorphic = FALSE burn_modifier = 2 head_flags = HEAD_EYESPRITES|HEAD_DEBRAIN /obj/item/bodypart/chest/snail - biological_state = BIO_FLESH //SKYRAT EDIT - Roundstart Snails - Now invertebrates! + biological_state = (BIO_BLOODED|BIO_FLESH) //SKYRAT EDIT - Roundstart Snails - Now invertebrates! limb_id = SPECIES_SNAIL is_dimorphic = FALSE burn_modifier = 2 /obj/item/bodypart/arm/left/snail - biological_state = BIO_FLESH //SKYRAT EDIT - Roundstart Snails - Now invertebrates! + biological_state = (BIO_BLOODED|BIO_FLESH) //SKYRAT EDIT - Roundstart Snails - Now invertebrates! limb_id = SPECIES_SNAIL unarmed_attack_verb = "slap" unarmed_attack_effect = ATTACK_EFFECT_DISARM @@ -22,7 +22,7 @@ burn_modifier = 2 /obj/item/bodypart/arm/right/snail - biological_state = BIO_FLESH //SKYRAT EDIT - Roundstart Snails - Now invertebrates! + biological_state = (BIO_BLOODED|BIO_FLESH) //SKYRAT EDIT - Roundstart Snails - Now invertebrates! limb_id = SPECIES_SNAIL unarmed_attack_verb = "slap" unarmed_attack_effect = ATTACK_EFFECT_DISARM @@ -31,7 +31,7 @@ burn_modifier = 2 /obj/item/bodypart/leg/left/snail - biological_state = BIO_FLESH //SKYRAT EDIT - Roundstart Snails - Now invertebrates! + biological_state = (BIO_BLOODED|BIO_FLESH) //SKYRAT EDIT - Roundstart Snails - Now invertebrates! limb_id = SPECIES_SNAIL unarmed_damage_low = 1 //SKYRAT EDIT - Roundstart Snails - Lowest possible punch damage. if this is set to 0, punches will always miss. unarmed_damage_high = 5 //snails are soft and squishy //SKYRAT EDIT - Roundstart Snails - A Bit More Damage. - ORIGINAL: unarmed_damage_high = 0.5 //snails are soft and squishy @@ -39,7 +39,7 @@ // speed_modifier = 3 //disgustingly slow // SKYRAT EDIT - Moved the movespeed to the shell. /obj/item/bodypart/leg/right/snail - biological_state = BIO_FLESH //SKYRAT EDIT - Roundstart Snails - Now invertebrates! + biological_state = (BIO_BLOODED|BIO_FLESH) //SKYRAT EDIT - Roundstart Snails - Now invertebrates! limb_id = SPECIES_SNAIL unarmed_damage_low = 1 //SKYRAT EDIT - Roundstart Snails - Lowest possible punch damage. if this is set to 0, punches will always miss. unarmed_damage_high = 5 //snails are soft and squishy //SKYRAT EDIT - Roundstart Snails - A Bit More Damage. - ORIGINAL: unarmed_damage_high = 0.5 //snails are soft and squishy @@ -48,43 +48,37 @@ ///ABDUCTOR /obj/item/bodypart/head/abductor - biological_state = BIO_INORGANIC //i have no fucking clue why these mfs get no wounds but SURE limb_id = SPECIES_ABDUCTOR is_dimorphic = FALSE should_draw_greyscale = FALSE head_flags = NONE /obj/item/bodypart/chest/abductor - biological_state = BIO_INORGANIC limb_id = SPECIES_ABDUCTOR is_dimorphic = FALSE should_draw_greyscale = FALSE /obj/item/bodypart/arm/left/abductor - biological_state = BIO_INORGANIC limb_id = SPECIES_ABDUCTOR should_draw_greyscale = FALSE bodypart_traits = list(TRAIT_CHUNKYFINGERS) /obj/item/bodypart/arm/right/abductor - biological_state = BIO_INORGANIC limb_id = SPECIES_ABDUCTOR should_draw_greyscale = FALSE bodypart_traits = list(TRAIT_CHUNKYFINGERS) /obj/item/bodypart/leg/left/abductor - biological_state = BIO_INORGANIC limb_id = SPECIES_ABDUCTOR should_draw_greyscale = FALSE /obj/item/bodypart/leg/right/abductor - biological_state = BIO_INORGANIC limb_id = SPECIES_ABDUCTOR should_draw_greyscale = FALSE ///JELLY /obj/item/bodypart/head/jelly - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_JELLYPERSON is_dimorphic = TRUE dmg_overlay_type = null @@ -92,90 +86,90 @@ head_flags = HEAD_ALL_FEATURES /obj/item/bodypart/chest/jelly - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_JELLYPERSON is_dimorphic = TRUE dmg_overlay_type = null burn_modifier = 0.5 // = 1/2x generic burn damage /obj/item/bodypart/arm/left/jelly - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null burn_modifier = 0.5 // = 1/2x generic burn damage /obj/item/bodypart/arm/right/jelly - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null burn_modifier = 0.5 // = 1/2x generic burn damage /obj/item/bodypart/leg/left/jelly - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null burn_modifier = 0.5 // = 1/2x generic burn damage /obj/item/bodypart/leg/right/jelly - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_JELLYPERSON dmg_overlay_type = null burn_modifier = 0.5 // = 1/2x generic burn damage ///SLIME /obj/item/bodypart/head/slime - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_SLIMEPERSON is_dimorphic = FALSE head_flags = HEAD_ALL_FEATURES /obj/item/bodypart/chest/slime - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_SLIMEPERSON is_dimorphic = TRUE /obj/item/bodypart/arm/left/slime - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_SLIMEPERSON /obj/item/bodypart/arm/right/slime - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_SLIMEPERSON /obj/item/bodypart/leg/left/slime - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_SLIMEPERSON /obj/item/bodypart/leg/right/slime - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_SLIMEPERSON ///LUMINESCENT /obj/item/bodypart/head/luminescent - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_LUMINESCENT is_dimorphic = TRUE head_flags = HEAD_ALL_FEATURES /obj/item/bodypart/chest/luminescent - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED) limb_id = SPECIES_LUMINESCENT is_dimorphic = TRUE /obj/item/bodypart/arm/left/luminescent - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_LUMINESCENT /obj/item/bodypart/arm/right/luminescent - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_LUMINESCENT /obj/item/bodypart/leg/left/luminescent - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_LUMINESCENT /obj/item/bodypart/leg/right/luminescent - biological_state = BIO_INORGANIC + biological_state = (BIO_FLESH|BIO_BLOODED|BIO_JOINTED) limb_id = SPECIES_LUMINESCENT ///ZOMBIE @@ -282,7 +276,6 @@ ///SHADOW /obj/item/bodypart/head/shadow - biological_state = BIO_INORGANIC limb_id = SPECIES_SHADOW is_dimorphic = FALSE should_draw_greyscale = FALSE @@ -290,32 +283,27 @@ head_flags = NONE /obj/item/bodypart/chest/shadow - biological_state = BIO_INORGANIC limb_id = SPECIES_SHADOW is_dimorphic = FALSE should_draw_greyscale = FALSE burn_modifier = 1.5 /obj/item/bodypart/arm/left/shadow - biological_state = BIO_INORGANIC limb_id = SPECIES_SHADOW should_draw_greyscale = FALSE burn_modifier = 1.5 /obj/item/bodypart/arm/right/shadow - biological_state = BIO_INORGANIC limb_id = SPECIES_SHADOW should_draw_greyscale = FALSE burn_modifier = 1.5 /obj/item/bodypart/leg/left/shadow - biological_state = BIO_INORGANIC limb_id = SPECIES_SHADOW should_draw_greyscale = FALSE burn_modifier = 1.5 /obj/item/bodypart/leg/right/shadow - biological_state = BIO_INORGANIC limb_id = SPECIES_SHADOW should_draw_greyscale = FALSE burn_modifier = 1.5 @@ -343,25 +331,25 @@ dmg_overlay_type = null /obj/item/bodypart/arm/left/skeleton - biological_state = BIO_BONE + biological_state = (BIO_BONE|BIO_JOINTED) limb_id = SPECIES_SKELETON should_draw_greyscale = FALSE dmg_overlay_type = null /obj/item/bodypart/arm/right/skeleton - biological_state = BIO_BONE + biological_state = (BIO_BONE|BIO_JOINTED) limb_id = SPECIES_SKELETON should_draw_greyscale = FALSE dmg_overlay_type = null /obj/item/bodypart/leg/left/skeleton - biological_state = BIO_BONE + biological_state = (BIO_BONE|BIO_JOINTED) limb_id = SPECIES_SKELETON should_draw_greyscale = FALSE dmg_overlay_type = null /obj/item/bodypart/leg/right/skeleton - biological_state = BIO_BONE + biological_state = (BIO_BONE|BIO_JOINTED) limb_id = SPECIES_SKELETON should_draw_greyscale = FALSE dmg_overlay_type = null @@ -414,7 +402,7 @@ icon = 'icons/mob/human/species/golems.dmi' icon_static = 'icons/mob/human/species/golems.dmi' icon_state = "golem_head" - biological_state = BIO_INORGANIC + biological_state = BIO_BONE bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM is_dimorphic = FALSE @@ -451,7 +439,7 @@ icon = 'icons/mob/human/species/golems.dmi' icon_static = 'icons/mob/human/species/golems.dmi' icon_state = "golem_chest" - biological_state = BIO_INORGANIC + biological_state = BIO_BONE acceptable_bodytype = BODYTYPE_GOLEM bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM @@ -472,7 +460,7 @@ icon = 'icons/mob/human/species/golems.dmi' icon_static = 'icons/mob/human/species/golems.dmi' icon_state = "golem_l_arm" - biological_state = BIO_INORGANIC + biological_state = (BIO_BONE|BIO_JOINTED) bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM should_draw_greyscale = FALSE @@ -506,7 +494,7 @@ icon = 'icons/mob/human/species/golems.dmi' icon_static = 'icons/mob/human/species/golems.dmi' icon_state = "golem_r_arm" - biological_state = BIO_INORGANIC + biological_state = (BIO_BONE|BIO_JOINTED) bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM should_draw_greyscale = FALSE @@ -540,7 +528,7 @@ icon = 'icons/mob/human/species/golems.dmi' icon_static = 'icons/mob/human/species/golems.dmi' icon_state = "golem_l_leg" - biological_state = BIO_INORGANIC + biological_state = (BIO_BONE|BIO_JOINTED) bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM should_draw_greyscale = FALSE @@ -553,7 +541,7 @@ icon = 'icons/mob/human/species/golems.dmi' icon_static = 'icons/mob/human/species/golems.dmi' icon_state = "golem_r_leg" - biological_state = BIO_INORGANIC + biological_state = (BIO_BONE|BIO_JOINTED) bodytype = BODYTYPE_GOLEM | BODYTYPE_ORGANIC limb_id = SPECIES_GOLEM should_draw_greyscale = FALSE diff --git a/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm b/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm index 85eea7edba0..f478d522d56 100644 --- a/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm +++ b/code/modules/surgery/bodyparts/species_parts/plasmaman_bodyparts.dm @@ -27,7 +27,7 @@ icon = 'icons/mob/human/species/plasmaman/bodyparts.dmi' icon_state = "plasmaman_l_arm" icon_static = 'icons/mob/human/species/plasmaman/bodyparts.dmi' - biological_state = BIO_BONE + biological_state = (BIO_BONE|BIO_JOINTED) limb_id = SPECIES_PLASMAMAN should_draw_greyscale = FALSE dmg_overlay_type = null @@ -38,7 +38,7 @@ icon = 'icons/mob/human/species/plasmaman/bodyparts.dmi' icon_state = "plasmaman_r_arm" icon_static = 'icons/mob/human/species/plasmaman/bodyparts.dmi' - biological_state = BIO_BONE + biological_state = (BIO_BONE|BIO_JOINTED) limb_id = SPECIES_PLASMAMAN should_draw_greyscale = FALSE dmg_overlay_type = null @@ -49,7 +49,7 @@ icon = 'icons/mob/human/species/plasmaman/bodyparts.dmi' icon_state = "plasmaman_l_leg" icon_static = 'icons/mob/human/species/plasmaman/bodyparts.dmi' - biological_state = BIO_BONE + biological_state = (BIO_BONE|BIO_JOINTED) limb_id = SPECIES_PLASMAMAN should_draw_greyscale = FALSE dmg_overlay_type = null @@ -60,7 +60,7 @@ icon = 'icons/mob/human/species/plasmaman/bodyparts.dmi' icon_state = "plasmaman_r_leg" icon_static = 'icons/mob/human/species/plasmaman/bodyparts.dmi' - biological_state = BIO_BONE + biological_state = (BIO_BONE|BIO_JOINTED) limb_id = SPECIES_PLASMAMAN should_draw_greyscale = FALSE dmg_overlay_type = null diff --git a/code/modules/surgery/bodyparts/wounds.dm b/code/modules/surgery/bodyparts/wounds.dm index 1961993ec64..db1407953b6 100644 --- a/code/modules/surgery/bodyparts/wounds.dm +++ b/code/modules/surgery/bodyparts/wounds.dm @@ -8,40 +8,74 @@ var/mangled_state = get_mangled_state() var/easy_dismember = HAS_TRAIT(owner, TRAIT_EASYDISMEMBER) // if we have easydismember, we don't reduce damage when redirecting damage to different types (slashing weapons on mangled/skinless limbs attack at 100% instead of 50%) - if(wounding_type == WOUND_BLUNT && sharpness) - if(sharpness & SHARP_EDGED) - wounding_type = WOUND_SLASH - else if (sharpness & SHARP_POINTY) - wounding_type = WOUND_PIERCE + var/has_exterior = FALSE + var/has_interior = FALSE - //Handling for bone only/flesh only(none right now)/flesh and bone targets - switch(biological_state) - // if we're bone only, all cutting attacks go straight to the bone - if(BIO_BONE) - if(wounding_type == WOUND_SLASH) - wounding_type = WOUND_BLUNT - phantom_wounding_dmg *= (easy_dismember ? 1 : 0.6) - else if(wounding_type == WOUND_PIERCE) - wounding_type = WOUND_BLUNT - phantom_wounding_dmg *= (easy_dismember ? 1 : 0.75) - if((mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)) - return - // note that there's no handling for BIO_FLESH since we don't have any that are that right now (slimepeople maybe someday) - // standard humanoids - if(BIO_FLESH_BONE) - // if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate - // So a big sharp weapon is still all you need to destroy a limb - if((mangled_state & BODYPART_MANGLED_FLESH) && !(mangled_state & BODYPART_MANGLED_BONE) && sharpness) - playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100) - if(wounding_type == WOUND_SLASH && !easy_dismember) - phantom_wounding_dmg *= 0.6 // edged weapons pass along 60% of their wounding damage to the bone since the power is spread out over a larger area - if(wounding_type == WOUND_PIERCE && !easy_dismember) - phantom_wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated - wounding_type = WOUND_BLUNT - else if((mangled_state & BODYPART_MANGLED_FLESH) && (mangled_state & BODYPART_MANGLED_BONE) && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)) + for (var/state as anything in GLOB.bio_state_states) + var/flag = text2num(state) + if (!(biological_state & flag)) + continue + + var/value = GLOB.bio_state_states[state] + if (value & BIO_EXTERIOR) + has_exterior = TRUE + if (value & BIO_INTERIOR) + has_interior = TRUE + + if (has_exterior && has_interior) + break + + // We put this here so we dont increase init time by doing this all at once on initialization + // Effectively, we "lazy load" + if (isnull(any_existing_wound_can_mangle_our_bone) || isnull(any_existing_wound_can_mangle_our_flesh)) + any_existing_wound_can_mangle_our_bone = FALSE + any_existing_wound_can_mangle_our_flesh = FALSE + for (var/datum/wound/wound_type as anything in GLOB.all_wound_pregen_data) + var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[wound_type] + if (!pregen_data.can_be_applied_to(src, random_roll = TRUE)) // we only consider randoms because non-randoms are usually really specific + continue + if (initial(pregen_data.wound_path_to_generate.wound_flags) & MANGLES_FLESH) + any_existing_wound_can_mangle_our_flesh = TRUE + if (initial(pregen_data.wound_path_to_generate.wound_flags) & MANGLES_BONE) + any_existing_wound_can_mangle_our_bone = TRUE + + if (any_existing_wound_can_mangle_our_bone && any_existing_wound_can_mangle_our_flesh) + break + + var/can_theoretically_be_dismembered = (any_existing_wound_can_mangle_our_bone || (any_existing_wound_can_mangle_our_flesh && !has_exterior)) + + var/exterior_ready_to_dismember = (!has_exterior || ((mangled_state & BODYPART_MANGLED_BONE) == BODYPART_MANGLED_BONE)) + var/interior_ready_to_dismember = (!has_interior || ((mangled_state & BODYPART_MANGLED_FLESH) == BODYPART_MANGLED_FLESH)) + + // if we're bone only, all cutting attacks go straight to the bone + if(has_exterior && interior_ready_to_dismember) + if(wounding_type == WOUND_SLASH) + wounding_type = WOUND_BLUNT + phantom_wounding_dmg *= (easy_dismember ? 1 : 0.6) + else if(wounding_type == WOUND_PIERCE) + wounding_type = WOUND_BLUNT + phantom_wounding_dmg *= (easy_dismember ? 1 : 0.75) + if(exterior_ready_to_dismember && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)) + return + else + // if we've already mangled the skin (critical slash or piercing wound), then the bone is exposed, and we can damage it with sharp weapons at a reduced rate + // So a big sharp weapon is still all you need to destroy a limb + if(has_exterior && interior_ready_to_dismember && !(mangled_state & BODYPART_MANGLED_BONE) && sharpness) + playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100) + if(wounding_type == WOUND_SLASH && !easy_dismember) + phantom_wounding_dmg *= 0.6 // edged weapons pass along 60% of their wounding damage to the bone since the power is spread out over a larger area + if(wounding_type == WOUND_PIERCE && !easy_dismember) + phantom_wounding_dmg *= 0.75 // piercing weapons pass along 75% of their wounding damage to the bone since it's more concentrated + wounding_type = WOUND_BLUNT + else if(interior_ready_to_dismember && exterior_ready_to_dismember && try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)) + return + if (use_alternate_dismemberment_calc_even_if_mangleable || !can_theoretically_be_dismembered) + var/percent_to_total_max = (get_damage() / max_damage) + if (percent_to_total_max >= hp_percent_to_dismemberable) + if (try_dismember(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus)) return - check_wounding(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus) + return check_wounding(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus) /** * check_wounding() is where we handle rolling for, selecting, and applying a wound if we meet the criteria @@ -82,7 +116,11 @@ dismembering.apply_dismember(src, woundtype, outright = TRUE, attack_direction = attack_direction) return - var/list/wounds_checking = GLOB.global_wound_types[woundtype] + var/list/datum/wound/possible_wounds = list() + for (var/datum/wound/type as anything in GLOB.all_wound_pregen_data) + var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[type] + if (pregen_data.can_be_applied_to(src, woundtype, random_roll = TRUE)) + possible_wounds += type // quick re-check to see if bare_wound_bonus applies, for the benefit of log_wound(), see about getting the check from check_woundings_mods() somehow if(ishuman(owner)) var/mob/living/carbon/human/human_wearer = owner @@ -94,19 +132,19 @@ break //cycle through the wounds of the relevant category from the most severe down - for(var/datum/wound/possible_wound as anything in wounds_checking) + for(var/datum/wound/possible_wound as anything in possible_wounds) var/datum/wound/replaced_wound for(var/datum/wound/existing_wound as anything in wounds) - if(existing_wound.type in wounds_checking) + if(existing_wound.wound_series == initial(possible_wound.wound_series)) if(existing_wound.severity >= initial(possible_wound.severity)) return else - replaced_wound = existing_wound + replaced_wound = existing_wound // if we find something we keep iterating untilw e're done or we find we're outclassed by something in our series if(initial(possible_wound.threshold_minimum) < injury_roll) var/datum/wound/new_wound if(replaced_wound) - new_wound = replaced_wound.replace_wound(possible_wound, attack_direction = attack_direction) + new_wound = replaced_wound.replace_wound(new possible_wound, attack_direction = attack_direction) else new_wound = new possible_wound new_wound.apply_wound(src, attack_direction = attack_direction, wound_source = damage_source) @@ -119,9 +157,9 @@ var/datum/wound/potential_wound = specific_woundtype for(var/datum/wound/existing_wound as anything in wounds) - if(existing_wound.wound_type == initial(potential_wound.wound_type)) + if (existing_wound.wound_series == initial(potential_wound.wound_series)) if(existing_wound.severity < initial(potential_wound.severity)) // we only try if the existing one is inferior to the one we're trying to force - existing_wound.replace_wound(potential_wound, smited) + existing_wound.replace_wound(new potential_wound, smited) return var/datum/wound/new_wound = new potential_wound diff --git a/code/modules/surgery/bone_mending.dm b/code/modules/surgery/bone_mending.dm index 2396f49c322..48114fe6d04 100644 --- a/code/modules/surgery/bone_mending.dm +++ b/code/modules/surgery/bone_mending.dm @@ -5,7 +5,7 @@ /datum/surgery/repair_bone_hairline name = "Repair bone fracture (hairline)" surgery_flags = SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB | SURGERY_REQUIRES_REAL_LIMB - targetable_wound = /datum/wound/blunt/severe + targetable_wound = /datum/wound/blunt/bone/severe possible_locs = list( BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, @@ -31,7 +31,7 @@ /datum/surgery/repair_bone_compound name = "Repair Compound Fracture" surgery_flags = SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB | SURGERY_REQUIRES_REAL_LIMB - targetable_wound = /datum/wound/blunt/critical + targetable_wound = /datum/wound/blunt/bone/critical possible_locs = list( BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, diff --git a/code/modules/surgery/burn_dressing.dm b/code/modules/surgery/burn_dressing.dm index f448195d3ef..c22a8f4be97 100644 --- a/code/modules/surgery/burn_dressing.dm +++ b/code/modules/surgery/burn_dressing.dm @@ -5,7 +5,7 @@ /datum/surgery/debride name = "Debride burnt flesh" surgery_flags = SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB | SURGERY_REQUIRES_REAL_LIMB - targetable_wound = /datum/wound/burn + targetable_wound = /datum/wound/burn/flesh possible_locs = list( BODY_ZONE_R_ARM, BODY_ZONE_L_ARM, @@ -24,7 +24,7 @@ return FALSE if(..()) var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected) - var/datum/wound/burn/burn_wound = targeted_bodypart.get_wound_type(targetable_wound) + var/datum/wound/burn/flesh/burn_wound = targeted_bodypart.get_wound_type(targetable_wound) return(burn_wound && burn_wound.infestation > 0) //SURGERY STEPS @@ -48,7 +48,7 @@ var/infestation_removed = 4 /// To give the surgeon a heads up how much work they have ahead of them -/datum/surgery_step/debride/proc/get_progress(mob/user, mob/living/carbon/target, datum/wound/burn/burn_wound) +/datum/surgery_step/debride/proc/get_progress(mob/user, mob/living/carbon/target, datum/wound/burn/flesh/burn_wound) if(!burn_wound?.infestation || !infestation_removed) return var/estimated_remaining_steps = burn_wound.infestation / infestation_removed @@ -68,7 +68,7 @@ /datum/surgery_step/debride/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) if(surgery.operated_wound) - var/datum/wound/burn/burn_wound = surgery.operated_wound + var/datum/wound/burn/flesh/burn_wound = surgery.operated_wound if(burn_wound.infestation <= 0) to_chat(user, span_notice("[target]'s [parse_zone(user.zone_selected)] has no infected flesh to remove!")) surgery.status++ @@ -86,7 +86,7 @@ user.visible_message(span_notice("[user] looks for [target]'s [parse_zone(user.zone_selected)]."), span_notice("You look for [target]'s [parse_zone(user.zone_selected)]...")) /datum/surgery_step/debride/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) - var/datum/wound/burn/burn_wound = surgery.operated_wound + var/datum/wound/burn/flesh/burn_wound = surgery.operated_wound if(burn_wound) var/progress_text = get_progress(user, target, burn_wound) display_results( @@ -120,7 +120,7 @@ /datum/surgery_step/debride/initiate(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, try_to_fail = FALSE) if(!..()) return - var/datum/wound/burn/burn_wound = surgery.operated_wound + var/datum/wound/burn/flesh/burn_wound = surgery.operated_wound while(burn_wound && burn_wound.infestation > 0.25) if(!..()) break @@ -139,7 +139,7 @@ /datum/surgery_step/dress/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - var/datum/wound/burn/burn_wound = surgery.operated_wound + var/datum/wound/burn/flesh/burn_wound = surgery.operated_wound if(burn_wound) display_results( user, @@ -153,7 +153,7 @@ user.visible_message(span_notice("[user] looks for [target]'s [parse_zone(user.zone_selected)]."), span_notice("You look for [target]'s [parse_zone(user.zone_selected)]...")) /datum/surgery_step/dress/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) - var/datum/wound/burn/burn_wound = surgery.operated_wound + var/datum/wound/burn/flesh/burn_wound = surgery.operated_wound if(burn_wound) display_results( user, diff --git a/code/modules/surgery/repair_puncture.dm b/code/modules/surgery/repair_puncture.dm index 843336c258b..bb33c314689 100644 --- a/code/modules/surgery/repair_puncture.dm +++ b/code/modules/surgery/repair_puncture.dm @@ -9,7 +9,7 @@ /datum/surgery/repair_puncture name = "Repair puncture" surgery_flags = SURGERY_REQUIRE_RESTING | SURGERY_REQUIRE_LIMB | SURGERY_REQUIRES_REAL_LIMB - targetable_wound = /datum/wound/pierce + targetable_wound = /datum/wound/pierce/bleed target_mobtypes = list(/mob/living/carbon) possible_locs = list( BODY_ZONE_R_ARM, @@ -32,7 +32,7 @@ . = ..() if(.) var/obj/item/bodypart/targeted_bodypart = target.get_bodypart(user.zone_selected) - var/datum/wound/burn/pierce_wound = targeted_bodypart.get_wound_type(targetable_wound) + var/datum/wound/burn/flesh/pierce_wound = targeted_bodypart.get_wound_type(targetable_wound) return(pierce_wound && pierce_wound.blood_flow > 0) //SURGERY STEPS @@ -47,7 +47,7 @@ time = 3 SECONDS /datum/surgery_step/repair_innards/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - var/datum/wound/pierce/pierce_wound = surgery.operated_wound + var/datum/wound/pierce/bleed/pierce_wound = surgery.operated_wound if(!pierce_wound) user.visible_message(span_notice("[user] looks for [target]'s [parse_zone(user.zone_selected)]."), span_notice("You look for [target]'s [parse_zone(user.zone_selected)]...")) return @@ -67,7 +67,7 @@ display_pain(target, "You feel a horrible stabbing pain in your [parse_zone(user.zone_selected)]!") /datum/surgery_step/repair_innards/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) - var/datum/wound/pierce/pierce_wound = surgery.operated_wound + var/datum/wound/pierce/bleed/pierce_wound = surgery.operated_wound if(!pierce_wound) to_chat(user, span_warning("[target] has no puncture wound there!")) return ..() @@ -112,7 +112,7 @@ return TRUE /datum/surgery_step/seal_veins/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) - var/datum/wound/pierce/pierce_wound = surgery.operated_wound + var/datum/wound/pierce/bleed/pierce_wound = surgery.operated_wound if(!pierce_wound) user.visible_message(span_notice("[user] looks for [target]'s [parse_zone(user.zone_selected)]."), span_notice("You look for [target]'s [parse_zone(user.zone_selected)]...")) return @@ -126,7 +126,7 @@ display_pain(target, "You're being burned inside your [parse_zone(user.zone_selected)]!") /datum/surgery_step/seal_veins/success(mob/living/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) - var/datum/wound/pierce/pierce_wound = surgery.operated_wound + var/datum/wound/pierce/bleed/pierce_wound = surgery.operated_wound if(!pierce_wound) to_chat(user, span_warning("[target] has no puncture there!")) return ..() diff --git a/code/modules/unit_tests/medical_wounds.dm b/code/modules/unit_tests/medical_wounds.dm index 56c7a43104f..0838b2d18be 100644 --- a/code/modules/unit_tests/medical_wounds.dm +++ b/code/modules/unit_tests/medical_wounds.dm @@ -12,10 +12,10 @@ var/i = 1 var/list/iter_test_wound_list - for(iter_test_wound_list in list(list(/datum/wound/blunt/moderate, /datum/wound/blunt/severe, /datum/wound/blunt/critical),\ - list(/datum/wound/slash/moderate, /datum/wound/slash/severe, /datum/wound/slash/critical),\ - list(/datum/wound/pierce/moderate, /datum/wound/pierce/severe, /datum/wound/pierce/critical),\ - list(/datum/wound/burn/moderate, /datum/wound/burn/severe, /datum/wound/burn/critical))) + for(iter_test_wound_list in list(list(/datum/wound/blunt/bone/moderate, /datum/wound/blunt/bone/severe, /datum/wound/blunt/bone/critical),\ + list(/datum/wound/slash/flesh/moderate, /datum/wound/slash/flesh/severe, /datum/wound/slash/flesh/critical),\ + list(/datum/wound/pierce/bleed/moderate, /datum/wound/pierce/bleed/severe, /datum/wound/pierce/bleed/critical),\ + list(/datum/wound/burn/flesh/moderate, /datum/wound/burn/flesh/severe, /datum/wound/burn/flesh/critical))) TEST_ASSERT_EQUAL(length(victim.all_wounds), 0, "Patient is somehow wounded before test") var/datum/wound/iter_test_wound @@ -52,10 +52,10 @@ var/list/iter_test_wound_list tested_part.biological_state &= ~BIO_FLESH // take away the base limb's flesh (ouchie!) ((not actually ouchie, this just affects their wounds and dismemberment handling)) - for(iter_test_wound_list in list(list(/datum/wound/blunt/moderate, /datum/wound/blunt/severe, /datum/wound/blunt/critical),\ - list(/datum/wound/slash/moderate, /datum/wound/slash/severe, /datum/wound/slash/critical),\ - list(/datum/wound/pierce/moderate, /datum/wound/pierce/severe, /datum/wound/pierce/critical),\ - list(/datum/wound/burn/moderate, /datum/wound/burn/severe, /datum/wound/burn/critical))) + for(iter_test_wound_list in list(list(/datum/wound/blunt/bone/moderate, /datum/wound/blunt/bone/severe, /datum/wound/blunt/bone/critical),\ + list(/datum/wound/slash/flesh/moderate, /datum/wound/slash/flesh/severe, /datum/wound/slash/flesh/critical),\ + list(/datum/wound/pierce/bleed/moderate, /datum/wound/pierce/bleed/severe, /datum/wound/pierce/bleed/critical),\ + list(/datum/wound/burn/flesh/moderate, /datum/wound/burn/flesh/severe, /datum/wound/burn/flesh/critical))) TEST_ASSERT_EQUAL(length(victim.all_wounds), 0, "Patient is somehow wounded before test") var/datum/wound/iter_test_wound @@ -69,13 +69,15 @@ tested_part.receive_damage(0, WOUND_MINIMUM_DAMAGE, wound_bonus = threshold, sharpness=sharps[i]) // so if we just tried to deal a flesh wound, make sure we didn't actually suffer it. We may have suffered a bone wound instead, but we just want to make sure we don't have a flesh wound - if(initial(iter_test_wound.wound_flags) & FLESH_WOUND) + var/datum/wound_pregen_data/pregen_data = GLOB.all_wound_pregen_data[iter_test_wound] + if (pregen_data.required_limb_biostate & BIO_FLESH) if(!length(victim.all_wounds)) // not having a wound is good news continue else // we have to check that it's actually a bone wound and not the intended wound type TEST_ASSERT_EQUAL(length(victim.all_wounds), 1, "Patient has more than one wound when only one is expected. Severity: [initial(iter_test_wound.severity)]") var/datum/wound/actual_wound = victim.all_wounds[1] - TEST_ASSERT((actual_wound.wound_flags & ~FLESH_WOUND), "Limb has flesh wound despite no BIO_FLESH biological_state, expected either no wound or bone wound. Offending wound: [actual_wound]") + var/datum/wound_pregen_data/actual_pregen_data = GLOB.all_wound_pregen_data[actual_wound.type] + TEST_ASSERT((actual_pregen_data.required_limb_biostate & ~BIO_FLESH), "Limb has flesh wound despite no BIO_FLESH biological_state, expected either no wound or bone wound. Offending wound: [actual_wound]") threshold_penalty = actual_wound.threshold_penalty else // otherwise if it's a bone wound, check that we have it per usual TEST_ASSERT(length(victim.all_wounds), "Patient has no wounds when one wound is expected. Severity: [initial(iter_test_wound.severity)]") diff --git a/code/modules/vehicles/cars/clowncar.dm b/code/modules/vehicles/cars/clowncar.dm index 3fb6d37bd2c..f08e30a7554 100644 --- a/code/modules/vehicles/cars/clowncar.dm +++ b/code/modules/vehicles/cars/clowncar.dm @@ -122,8 +122,8 @@ continue for(var/obj/item/bodypart/head/head_to_wound as anything in carbon_occupant.bodyparts) var/type_wound = pick(list( - /datum/wound/blunt/moderate, - /datum/wound/blunt/severe, + /datum/wound/blunt/bone/moderate, + /datum/wound/blunt/bone/severe, )) head_to_wound.force_wound_upwards(type_wound, wound_source = src) carbon_occupant.playsound_local(src, 'sound/weapons/flash_ring.ogg', 50) diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm index c68d70f5164..298af4a7cf9 100644 --- a/code/modules/vending/_vending.dm +++ b/code/modules/vending/_vending.dm @@ -954,11 +954,13 @@ return FALSE var/mob/living/carbon/carbon_target = atom_target for(var/obj/item/bodypart/squish_part in carbon_target.bodyparts) - if(IS_ORGANIC_LIMB(squish_part)) - var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate)) - squish_part.force_wound_upwards(type_wound, wound_source = "crushed by [src]") + var/type_wound + if (squish_part.biological_state & BIO_BONE) + type_wound = pick(list(/datum/wound/blunt/bone/critical, /datum/wound/blunt/bone/severe, /datum/wound/blunt/bone/moderate)) else squish_part.receive_damage(brute=30) + if (type_wound) + squish_part.force_wound_upwards(type_wound, wound_source = "crushed by [src]") carbon_target.visible_message(span_danger("[carbon_target]'s body is maimed underneath the mass of [src]!"), span_userdanger("Your body is maimed underneath the mass of [src]!")) return TRUE if(CRUSH_CRIT_HEADGIB) // skull squish! diff --git a/modular_skyrat/modules/bodyparts/code/roundstartslime_bodyparts.dm b/modular_skyrat/modules/bodyparts/code/roundstartslime_bodyparts.dm index e5894249ac1..302d3488931 100644 --- a/modular_skyrat/modules/bodyparts/code/roundstartslime_bodyparts.dm +++ b/modular_skyrat/modules/bodyparts/code/roundstartslime_bodyparts.dm @@ -3,25 +3,25 @@ /obj/item/bodypart/head/slime/roundstart is_dimorphic = TRUE icon_greyscale = BODYPART_ICON_ROUNDSTARTSLIME - biological_state = BIO_FLESH + biological_state = (BIO_FLESH|BIO_BLOODED) /obj/item/bodypart/chest/slime/roundstart is_dimorphic = TRUE icon_greyscale = BODYPART_ICON_ROUNDSTARTSLIME - biological_state = BIO_FLESH + biological_state = (BIO_FLESH|BIO_BLOODED) /obj/item/bodypart/arm/left/slime/roundstart icon_greyscale = BODYPART_ICON_ROUNDSTARTSLIME - biological_state = BIO_FLESH + biological_state = (BIO_FLESH|BIO_BLOODED) /obj/item/bodypart/arm/right/slime/roundstart icon_greyscale = BODYPART_ICON_ROUNDSTARTSLIME - biological_state = BIO_FLESH + biological_state = (BIO_FLESH|BIO_BLOODED) /obj/item/bodypart/leg/left/slime/roundstart icon_greyscale = BODYPART_ICON_ROUNDSTARTSLIME - biological_state = BIO_FLESH + biological_state = (BIO_FLESH|BIO_BLOODED) /obj/item/bodypart/leg/right/slime/roundstart icon_greyscale = BODYPART_ICON_ROUNDSTARTSLIME - biological_state = BIO_FLESH + biological_state = (BIO_FLESH|BIO_BLOODED) diff --git a/modular_skyrat/modules/contractor/code/datums/contract.dm b/modular_skyrat/modules/contractor/code/datums/contract.dm index 087cb438dac..47e7906254d 100644 --- a/modular_skyrat/modules/contractor/code/datums/contract.dm +++ b/modular_skyrat/modules/contractor/code/datums/contract.dm @@ -213,8 +213,8 @@ for(var/i in 1 to 2) var/obj/item/bodypart/limb = target.get_bodypart(pick_n_take(parts_to_fuck_up)) - var/datum/wound/blunt/severe/severe_wound_type = /datum/wound/blunt/severe - var/datum/wound/blunt/critical/critical_wound_type = /datum/wound/blunt/critical + var/datum/wound/blunt/bone/severe/severe_wound_type = /datum/wound/blunt/bone/severe + var/datum/wound/blunt/bone/critical/critical_wound_type = /datum/wound/blunt/bone/critical limb.receive_damage(brute = WOUND_MINIMUM_DAMAGE, wound_bonus = rand(initial(severe_wound_type.threshold_minimum), initial(critical_wound_type.threshold_minimum) + 10)) target.update_damage_overlays() diff --git a/modular_skyrat/modules/customization/readme.md b/modular_skyrat/modules/customization/readme.md index af197a1baca..b488c032194 100644 --- a/modular_skyrat/modules/customization/readme.md +++ b/modular_skyrat/modules/customization/readme.md @@ -53,8 +53,6 @@ Re-writes how mutant bodyparts exist and how they're handled. Adds in a per limb ./code/_globalvars/lists/flavor_misc.dm > Removed accessory list defines .\code\datums\keybindings\living.dm > /datum/keybinding/living/look_up > from L to P -./code/modules/surgery/bodyparts/_bodyparts.dm > var/rendered_bp_icon - ./code/__DEFINES/~skyrat_defines/DNA.dm > A TON of defines ./code/__DEFINES/~skyrat_defines/obj_flags.dm > Organ flags ./code/__DEFINES/~skyrat_defines/say.dm > MAX_FLAVOR_LEN diff --git a/modular_skyrat/modules/hev_suit/code/hev_suit.dm b/modular_skyrat/modules/hev_suit/code/hev_suit.dm index 87f7d7788ab..081b4a0853f 100644 --- a/modular_skyrat/modules/hev_suit/code/hev_suit.dm +++ b/modular_skyrat/modules/hev_suit/code/hev_suit.dm @@ -614,51 +614,30 @@ /obj/item/clothing/suit/space/hev_suit/proc/process_wound(carbon, wound, bodypart) SIGNAL_HANDLER - var/list/minor_fractures = list( - /datum/wound/blunt, - /datum/wound/blunt/moderate, - /datum/wound/muscle, - /datum/wound/muscle/moderate - ) - var/list/major_fractures = list( - /datum/wound/blunt/severe, - /datum/wound/blunt/critical, - /datum/wound/muscle/severe, - /datum/wound/loss - ) - var/list/minor_lacerations = list( - /datum/wound/burn, - /datum/wound/burn/moderate, - /datum/wound/pierce, - /datum/wound/pierce/moderate, - /datum/wound/slash, - /datum/wound/slash/moderate - ) - var/list/major_lacerations = list( - /datum/wound/burn/severe, - /datum/wound/burn/critical, - /datum/wound/pierce/severe, - /datum/wound/pierce/critical, - /datum/wound/slash/severe, - /datum/wound/slash/critical - ) + if (!istype(wound, /datum/wound)) + return - if(wound in minor_fractures) - send_hev_sound(minor_fracture_sound) - else if(wound in major_fractures) - send_hev_sound(major_fracture_sound) - else if(wound in minor_lacerations) - send_hev_sound(minor_lacerations_sound) - else if(wound in major_lacerations) - send_hev_sound(major_lacerations_sound) - else - var/sound2play = pick(list( - minor_fracture_sound, - major_fracture_sound, - minor_lacerations_sound, - major_lacerations_sound - )) - send_hev_sound(sound2play) + var/datum/wound/new_wound = wound + + var/sound_to_play + + var/wound_series = new_wound.wound_series + var/wound_type = new_wound.wound_type + var/wound_severity = new_wound.severity + + if (wound_type == WOUND_SLASH || wound_type == WOUND_PIERCE) + if (wound_severity >= WOUND_SEVERITY_SEVERE) + sound_to_play = major_lacerations_sound + else + sound_to_play = minor_lacerations_sound + else if (wound_type == WOUND_BLUNT || wound_series == WOUND_SERIES_MUSCLE_DAMAGE) + if (wound_severity >= WOUND_SEVERITY_SEVERE) + sound_to_play = major_fracture_sound + else + sound_to_play = minor_fracture_sound + + if (sound_to_play) + send_hev_sound(sound_to_play) /obj/item/clothing/suit/space/hev_suit/proc/process_acid() SIGNAL_HANDLER diff --git a/modular_skyrat/modules/medical/code/bodypart.dm b/modular_skyrat/modules/medical/code/bodypart.dm deleted file mode 100644 index 60a695f59ef..00000000000 --- a/modular_skyrat/modules/medical/code/bodypart.dm +++ /dev/null @@ -1,11 +0,0 @@ -/obj/item/bodypart/proc/apply_gauze(obj/item/stack/medical/gauze/new_gauze) - if(!istype(new_gauze) || current_gauze) - return - current_gauze = new new_gauze.gauze_type(src) - new_gauze.use(1) - -/obj/item/bodypart/proc/apply_splint(obj/item/stack/medical/gauze/new_splint) - if(!istype(new_splint) || current_splint) - return - current_splint = new new_splint.splint_type(src) - new_splint.use(1) diff --git a/modular_skyrat/modules/medical/code/bodypart_aid.dm b/modular_skyrat/modules/medical/code/bodypart_aid.dm deleted file mode 100644 index e5b3b13ceaa..00000000000 --- a/modular_skyrat/modules/medical/code/bodypart_aid.dm +++ /dev/null @@ -1,227 +0,0 @@ -#define SELF_AID_REMOVE_DELAY (5 SECONDS) -#define OTHER_AID_REMOVE_DELAY (2 SECONDS) - -/datum/bodypart_aid - var/name - /// Keeping track of how damaged our aid is from external things, such as hits, it will break when it reaches 0 - var/integrity = 2 - /// To which bodypart we're attached to - var/obj/item/bodypart/bodypart - /// Which item do we get when we rip this off, while its in pristine condition - var/stack_to_drop - /// Suffix for our used overlay. The suffix is the bodypart zone, and "_digitigrade" for some legs. If this is null then it wont make an overlay. Gauzes are rendered before splints - var/overlay_prefix - /// Bodypart is [this_prefix] with get_description() - var/desc_prefix - -/datum/bodypart_aid/Topic(href, href_list) - . = ..() - if(href_list["remove"]) - if(!bodypart.owner) - return - if(!iscarbon(usr)) - return - if(!in_range(usr, bodypart.owner)) - return - var/mob/living/carbon/C = usr - var/self = (C == bodypart.owner) - C.visible_message(span_notice("[C] begins removing [name] from [self ? "[bodypart.owner.p_Their()]" : "[bodypart.owner]'s" ] [bodypart.name]..."), span_notice("You begin to remove [name] from [self ? "your" : "[bodypart.owner]'s"] [bodypart.name]...")) - if(!do_after(C, (self ? SELF_AID_REMOVE_DELAY : OTHER_AID_REMOVE_DELAY), target=bodypart.owner)) - return - if(QDELETED(src)) - return - C.visible_message(span_notice("[C] removes [name] from [self ? "[bodypart.owner.p_Their()]" : "[bodypart.owner]'s" ] [bodypart.name]."), span_notice("You remove [name] from [self ? "your" : "[bodypart.owner]'s" ] [bodypart.name].")) - var/obj/item/gotten = rip_off() - if(gotten && !C.put_in_hands(gotten)) - gotten.forceMove(get_turf(C)) - -/datum/bodypart_aid/New(obj/item/bodypart/BP) - //'bodypart == BP' is set in subtypes to ensure some proper signals and behaviours - if(overlay_prefix && bodypart.owner) - bodypart.owner.update_bandage_overlays() - -/datum/bodypart_aid/Destroy() - if(overlay_prefix && bodypart.owner) - bodypart.owner.update_bandage_overlays() - bodypart = null - ..() - -/** - * take_damage() called when the bandage gets damaged - * - * This proc will subtract integrity and delete the bandage with a to_chat message to whoever was bandaged - * - */ - -/datum/bodypart_aid/proc/take_damage() - integrity-- - if(integrity <= 0) - if(bodypart.owner) - to_chat(bodypart.owner, span_warning("The [name] on your [bodypart.name] tears and falls off!")) - qdel(src) - -/** - * rip_off() called when someone rips it off - * - * It will return the bandage if it's considered pristine - * - */ - -/datum/bodypart_aid/proc/rip_off() - if(is_pristine()) - . = new stack_to_drop(null, 1) - qdel(src) - -/** - * get_description() called by examine procs - * - * It will returns a description of the bandage - * - */ - -/datum/bodypart_aid/proc/get_description() - return "[name]" - -/** - * is_pristine() called by rip_off() - * - * Used to determine whether the bandage can be re-used and won't qdel itself - * - */ - -/datum/bodypart_aid/proc/is_pristine() - return (integrity == initial(integrity)) - -/datum/bodypart_aid/splint - name = "splint" - overlay_prefix = "splint" - desc_prefix = "fastened" - stack_to_drop = /obj/item/stack/medical/gauze - /// How effective are we in keeping the bodypart rigid - var/splint_factor = 0.3 - /// Whether the splint prevents the limb from being disabled, with a ruptured tendon or a shattered bone - var/helps_disabled = TRUE - /// Total condition of our splint, the more we use it the more it gets looser - var/sling_condition = 5 - -/datum/bodypart_aid/splint/get_description() - var/desc - switch(sling_condition) - if(0 to 1.25) - desc = "barely holding" - if(1.25 to 2.75) - desc = "loose" - if(2.75 to 4) - desc = "rigid" - if(4 to INFINITY) - desc = "tight" - desc += " [name]" - return desc - -/datum/bodypart_aid/splint/Destroy() - SEND_SIGNAL(bodypart, COMSIG_BODYPART_SPLINT_DESTROYED) - bodypart.current_splint = null - return ..() - -/datum/bodypart_aid/splint/New(obj/item/bodypart/BP) - bodypart = BP - BP.current_splint = src - SEND_SIGNAL(BP, COMSIG_BODYPART_SPLINTED, src) - ..() - -/datum/bodypart_aid/splint/improvised - name = "improvised splint" - splint_factor = 0.6 - helps_disabled= FALSE - stack_to_drop = /obj/item/stack/medical/gauze/improvised - overlay_prefix = "splint_improv" - -/datum/bodypart_aid/gauze - name = "gauze" - stack_to_drop = /obj/item/stack/medical/gauze - overlay_prefix = "gauze" - desc_prefix = "bandaged" - /// How much more can we absorb - var/absorption_capacity = 5 - /// How fast do we absorb - var/absorption_rate = 0.12 - /// How much does the gauze help with keeping infections clean - var/sanitisation_factor = 0.4 - /// How much sanitisation we've got after we become fairly stained and worn - var/sanitisation_factor_stained = 0.8 - /// Is it blood stained? For description - var/blood_stained = FALSE - /// Is it pus stained? For description - var/pus_stained = FALSE - -/datum/bodypart_aid/gauze/get_description() - var/desc - switch(absorption_capacity) - if(-INFINITY to 0) - desc = "unusable" - if(0 to 1.25) - desc = "nearly ruined" - if(1.25 to 2.75) - desc = "badly worn" - if(2.75 to 4) - desc = "slightly used" - if(4 to INFINITY) - desc = "clean" - if(blood_stained) - desc += ", bloodied" - if(pus_stained) - desc += ", pus stained" - desc += " [name]" - return desc - -/datum/bodypart_aid/gauze/New(obj/item/bodypart/BP) - bodypart = BP - BP.current_gauze = src - SEND_SIGNAL(BP, COMSIG_BODYPART_GAUZED, src) - ..() - -/datum/bodypart_aid/gauze/Destroy() - SEND_SIGNAL(bodypart, COMSIG_BODYPART_GAUZE_DESTROYED) - bodypart.current_gauze = null - return ..() - -/datum/bodypart_aid/gauze/is_pristine() - . = ..() - if(.) - return (absorption_capacity == initial(absorption_capacity)) - -/** - * seep_gauze() is for when a gauze wrapping absorbs blood or pus from wounds, lowering its absorption capacity. - * - * The passed amount of seepage is deducted from the bandage's absorption capacity, and if we reach a negative absorption capacity, the bandage won't help our wounds. - * When the bandage is left with a low amount of absorption, it'll notify user and act worse as a sanitiser for infections - * Returns TRUE if the bandage absorbed anything, FALSE if it's fully stained. - * - * Arguments: - * * seep_amt - How much absorption capacity we're removing from our current bandages (think, how much blood or pus are we soaking up this tick?) - * * type - Is it blood or pus we're being stained with? GAUZE_STAIN_BLOOD, GAUZE_STAIN_PUS defines from wounds.dm - */ - -/datum/bodypart_aid/gauze/proc/seep_gauze(amount, type) - if(absorption_capacity > 0) - . = TRUE - absorption_capacity -= amount - else - return FALSE - //If our remaining absorption capacity is low, make so blood and pus stains show - if(absorption_capacity < 2) - sanitisation_factor = sanitisation_factor_stained - if(type == GAUZE_STAIN_BLOOD && !blood_stained) - blood_stained = TRUE - if(bodypart.owner) - to_chat(bodypart.owner, span_warning("The [name] on your [bodypart.name] [pick(list("pools", "trickles", "seeps"))] with blood.")) - else if(type == GAUZE_STAIN_PUS && !pus_stained) - pus_stained = TRUE - if(bodypart.owner) - to_chat(bodypart.owner, span_warning("The [name] on your [bodypart.name] [pick(list("pools", "trickles", "seeps"))] with pus.")) - -/datum/bodypart_aid/gauze/improvised - name = "improvised gauze" - stack_to_drop = /obj/item/stack/medical/gauze/improvised - absorption_rate = 0.09 - absorption_capacity = 3 diff --git a/modular_skyrat/modules/medical/code/carbon_examine.dm b/modular_skyrat/modules/medical/code/carbon_examine.dm index aab30138184..e86ed9f9267 100644 --- a/modular_skyrat/modules/medical/code/carbon_examine.dm +++ b/modular_skyrat/modules/medical/code/carbon_examine.dm @@ -49,11 +49,7 @@ if(WOUND_SEVERITY_CRITICAL) msg += "\t[t_His] [LB.name] is suffering [W.a_or_from] [W.get_topic_name(user)]!!" if(LB.current_gauze) - var/datum/bodypart_aid/current_gauze = LB.current_gauze - msg += "\t[t_His] [LB.name] is [current_gauze.desc_prefix] with [current_gauze.get_description()]." - if(LB.current_splint) - var/datum/bodypart_aid/current_splint = LB.current_splint - msg += "\t[t_His] [LB.name] is [current_splint.desc_prefix] with a [current_splint.get_description()]." + msg += "\t[t_His] [LB.name] is [LB.current_gauze.get_gauze_usage_prefix()] with [LB.current_gauze.get_gauze_description()]." if(!any_bodypart_damage) msg += "\t[t_He] [t_Has] no significantly damaged bodyparts." diff --git a/modular_skyrat/modules/medical/code/carbon_update_icons.dm b/modular_skyrat/modules/medical/code/carbon_update_icons.dm index 76167bbf6ea..0c3b4bb4f47 100644 --- a/modular_skyrat/modules/medical/code/carbon_update_icons.dm +++ b/modular_skyrat/modules/medical/code/carbon_update_icons.dm @@ -6,15 +6,9 @@ for(var/b in bodyparts) var/obj/item/bodypart/BP = b - if(BP.current_gauze && BP.current_gauze.overlay_prefix) - var/bp_suffix = BP.body_zone - if(BP.bodytype & BODYTYPE_DIGITIGRADE) - bp_suffix += "_digitigrade" - overlays.add_overlay("[BP.current_gauze.overlay_prefix]_[bp_suffix]") - if(BP.current_splint && BP.current_splint.overlay_prefix) - var/bp_suffix = BP.body_zone - if(BP.bodytype & BODYTYPE_DIGITIGRADE) - bp_suffix += "_digitigrade" - overlays.add_overlay("[BP.current_splint.overlay_prefix]_[bp_suffix]") + var/obj/item/stack/medical/gauze/our_gauze = BP.current_gauze + if (!our_gauze) + continue + overlays.add_overlay(our_gauze.get_overlay_prefix()) apply_overlay(BANDAGE_LAYER) diff --git a/modular_skyrat/modules/medical/code/carbon_defense.dm b/modular_skyrat/modules/medical/code/grasp.dm similarity index 100% rename from modular_skyrat/modules/medical/code/carbon_defense.dm rename to modular_skyrat/modules/medical/code/grasp.dm diff --git a/modular_skyrat/modules/medical/code/medical_stacks.dm b/modular_skyrat/modules/medical/code/medical_stacks.dm deleted file mode 100644 index 35b2ff1b1f9..00000000000 --- a/modular_skyrat/modules/medical/code/medical_stacks.dm +++ /dev/null @@ -1,65 +0,0 @@ -/obj/item/stack/medical/gauze - var/gauze_type = /datum/bodypart_aid/gauze - var/splint_type = /datum/bodypart_aid/splint - -/obj/item/stack/medical/gauze/improvised - gauze_type = /datum/bodypart_aid/gauze/improvised - splint_type = /datum/bodypart_aid/splint/improvised - -// gauze is only relevant for wounds, which are handled in the wounds themselves -/obj/item/stack/medical/gauze/try_heal(mob/living/patient, mob/user, silent) - - var/treatment_delay = (user == patient ? self_delay : other_delay) - - var/obj/item/bodypart/limb = patient.get_bodypart(check_zone(user.zone_selected)) - if(!limb) - patient.balloon_alert(user, "missing limb!") - return - if(!LAZYLEN(limb.wounds)) - patient.balloon_alert(user, "no wounds!") // good problem to have imo - return - - var/gauzeable_wound = FALSE - var/splintable_wound = FALSE - var/datum/wound/woundies - for(var/i in limb.wounds) - woundies = i - if(woundies.wound_flags & (ACCEPTS_GAUZE | ACCEPTS_SPLINT)) - if(woundies.wound_flags & ACCEPTS_GAUZE) - gauzeable_wound = TRUE - continue - if(woundies.wound_flags & ACCEPTS_SPLINT) - splintable_wound = TRUE - continue - if(!gauzeable_wound && !splintable_wound) - patient.balloon_alert(user, "can't heal those!") - return - - if(limb.current_gauze && gauzeable_wound) - gauzeable_wound = FALSE - if(limb.current_splint && splintable_wound) - splintable_wound = FALSE - if(!gauzeable_wound && !splintable_wound) - balloon_alert(user, "already bandaged!") - return - - if(HAS_TRAIT(woundies, TRAIT_WOUND_SCANNED)) - treatment_delay *= 0.5 - if(user == patient) - user.visible_message(span_warning("[user] begins expertly [gauzeable_wound ? "wrapping the wounds on their [limb.plaintext_zone]" : "splinting their [limb.plaintext_zone]"] with [src]..."), span_notice("You keep in mind the indications from the holo-image about your injury, and expertly begin [gauzeable_wound ? "wrapping your wounds" : "splinting your [limb.plaintext_zone]"] with [src].")) - else - user.visible_message(span_warning("[user] begins expertly [gauzeable_wound ? "wrapping the wounds on [patient]'s [limb.plaintext_zone]" : "splinting [patient]'s [limb.plaintext_zone]"] with [src]..."), span_warning("You begin quickly [gauzeable_wound ? "wrapping the wounds on [patient]'s [limb.plaintext_zone]" : "splinting [patient]'s [limb.plaintext_zone]"] with [src], keeping the holo-image indications in mind...")) - else - user.visible_message(span_warning("[user] begins [gauzeable_wound ? "wrapping the wounds on [patient]'s [limb.plaintext_zone]" : "splinting [patient]'s [limb.plaintext_zone]"] with [src]..."), span_warning("You begin [gauzeable_wound ? "wrapping the wounds on" : "splinting"] [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone] with [src]...")) - - if(!do_after(user, treatment_delay, target = patient)) - return - - user.visible_message("[user] [gauzeable_wound ? "wraps the wounds on" : "splints"] [user == patient ? "[user.p_their()]" : "[patient]'s"] [limb.plaintext_zone] with [src].", "You [gauzeable_wound ? "wrap the wounds on" : "splint"] [user == patient ? "your" : "[patient]'s"] [limb.plaintext_zone].") - if(gauzeable_wound) - limb.apply_gauze(src) - return - if(splintable_wound) - limb.apply_splint(src) - return - diff --git a/modular_skyrat/modules/medical/code/wounds/bleed.dm b/modular_skyrat/modules/medical/code/wounds/bleed.dm new file mode 100644 index 00000000000..75d80d3b384 --- /dev/null +++ b/modular_skyrat/modules/medical/code/wounds/bleed.dm @@ -0,0 +1,19 @@ +/datum/wound/slash/flesh/show_wound_topic(mob/user) + return (user == victim && blood_flow) + +/datum/wound/slash/flesh/Topic(href, href_list) + . = ..() + if(href_list["wound_topic"]) + if(!usr == victim) + return + victim.self_grasp_bleeding_limb(limb) + +/datum/wound/pierce/bleed/show_wound_topic(mob/user) + return (user == victim && blood_flow) + +/datum/wound/slash/bleed/Topic(href, href_list) + . = ..() + if(href_list["wound_topic"]) + if(!usr == victim) + return + victim.self_grasp_bleeding_limb(limb) diff --git a/modular_skyrat/modules/medical/code/wounds/bones.dm b/modular_skyrat/modules/medical/code/wounds/bones.dm deleted file mode 100644 index 089e289e3d8..00000000000 --- a/modular_skyrat/modules/medical/code/wounds/bones.dm +++ /dev/null @@ -1,455 +0,0 @@ - -/* - Blunt/Bone wounds -*/ -// TODO: well, a lot really, but i'd kill to get overlays and a bonebreaking effect like Blitz: The League, similar to electric shock skeletons - -/datum/wound/blunt - name = "Blunt (Bone) Wound" - sound_effect = 'sound/effects/wounds/crack1.ogg' - wound_type = WOUND_BLUNT - wound_flags = (BONE_WOUND | ACCEPTS_SPLINT) - - /// Have we been taped? - var/taped - /// Have we been bone gel'd? - var/gelled - /// If we did the gel + surgical tape healing method for fractures, how many ticks does it take to heal by default - var/regen_ticks_needed - /// Our current counter for gel + surgical tape regeneration - var/regen_ticks_current - /// If we suffer severe head booboos, we can get brain traumas tied to them - var/datum/brain_trauma/active_trauma - /// What brain trauma group, if any, we can draw from for head wounds - var/brain_trauma_group - /// If we deal brain traumas, when is the next one due? - var/next_trauma_cycle - /// How long do we wait +/- 20% for the next trauma? - var/trauma_cycle_cooldown - /// If this is a chest wound and this is set, we have this chance to cough up blood when hit in the chest - var/internal_bleeding_chance = 0 - -/* - Overwriting of base procs -*/ -/datum/wound/blunt/wound_injury(datum/wound/old_wound = null, attack_direction) - // hook into gaining/losing gauze so crit bone wounds can re-enable/disable depending if they're slung or not - RegisterSignals(limb, list(COMSIG_BODYPART_SPLINTED, COMSIG_BODYPART_SPLINT_DESTROYED), PROC_REF(update_inefficiencies)) - - if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group) - processes = TRUE - active_trauma = victim.gain_trauma_type(brain_trauma_group, TRAUMA_RESILIENCE_WOUND) - next_trauma_cycle = world.time + (rand(100-WOUND_BONE_HEAD_TIME_VARIANCE, 100+WOUND_BONE_HEAD_TIME_VARIANCE) * 0.01 * trauma_cycle_cooldown) - - RegisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(attack_with_hurt_hand)) - if(limb.held_index && victim.get_item_for_held_index(limb.held_index) && (disabling || prob(30 * severity))) - var/obj/item/held_item = victim.get_item_for_held_index(limb.held_index) - if(istype(held_item, /obj/item/offhand)) - held_item = victim.get_inactive_held_item() - - if(held_item && victim.dropItemToGround(held_item)) - victim.visible_message(span_danger("[victim] drops [held_item] in shock!"), span_warning("The force on your [parse_zone(limb.body_zone)] causes you to drop [held_item]!"), vision_distance=COMBAT_MESSAGE_RANGE) - - update_inefficiencies() - -/datum/wound/blunt/remove_wound(ignore_limb, replaced) - limp_slowdown = 0 - QDEL_NULL(active_trauma) - if(limb) - UnregisterSignal(limb, list(COMSIG_BODYPART_GAUZED, COMSIG_BODYPART_GAUZE_DESTROYED)) - if(victim) - UnregisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) - return ..() - -/datum/wound/blunt/handle_process() - . = ..() - if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group && world.time > next_trauma_cycle) - if(active_trauma) - QDEL_NULL(active_trauma) - else - active_trauma = victim.gain_trauma_type(brain_trauma_group, TRAUMA_RESILIENCE_WOUND) - next_trauma_cycle = world.time + (rand(100-WOUND_BONE_HEAD_TIME_VARIANCE, 100+WOUND_BONE_HEAD_TIME_VARIANCE) * 0.01 * trauma_cycle_cooldown) - - if(!gelled || !taped) - return - - regen_ticks_current++ - if(victim.body_position == LYING_DOWN) - if(prob(50)) - regen_ticks_current += 0.5 - if(victim.IsSleeping() && prob(50)) - regen_ticks_current += 0.5 - - if(prob(severity * 3)) - victim.take_bodypart_damage(rand(1, severity * 2), wound_bonus = CANT_WOUND) - victim.adjustStaminaLoss(rand(2, severity * 2.5)) - if(prob(33)) - to_chat(victim, span_danger("You feel a sharp pain in your body as your bones are reforming!")) - - if(regen_ticks_current > regen_ticks_needed) - if(!victim || !limb) - qdel(src) - return - to_chat(victim, span_green("Your [parse_zone(limb.body_zone)] has recovered from your fracture!")) - remove_wound() - -/// If we're a human who's punching something with a broken arm, we might hurt ourselves doing so -/datum/wound/blunt/proc/attack_with_hurt_hand(mob/M, atom/target, proximity) - SIGNAL_HANDLER - - if(victim.get_active_hand() != limb || !victim.combat_mode || !ismob(target) || severity <= WOUND_SEVERITY_MODERATE) - return - - // With a severe or critical wound, you have a 15% or 30% chance to proc pain on hit - if(prob((severity - 1) * 15)) - // And you have a 70% or 50% chance to actually land the blow, respectively - if(prob(70 - 20 * (severity - 1))) - to_chat(victim, span_userdanger("The fracture in your [parse_zone(limb.body_zone)] shoots with pain as you strike [target]!")) - limb.receive_damage(brute=rand(1,5)) - else - victim.visible_message(span_danger("[victim] weakly strikes [target] with [victim.p_their()] broken [parse_zone(limb.body_zone)], recoiling from pain!"), \ - span_userdanger("You fail to strike [target] as the fracture in your [parse_zone(limb.body_zone)] lights up in unbearable pain!"), vision_distance=COMBAT_MESSAGE_RANGE) - INVOKE_ASYNC(victim, TYPE_PROC_REF(/mob, emote), "scream") - victim.Stun(0.5 SECONDS) - limb.receive_damage(brute=rand(3,7)) - return COMPONENT_CANCEL_ATTACK_CHAIN - - -/datum/wound/blunt/receive_damage(wounding_type, wounding_dmg, wound_bonus) - if(!victim || wounding_dmg < WOUND_MINIMUM_DAMAGE) - return - if(ishuman(victim)) - var/mob/living/carbon/human/human_victim = victim - if(HAS_TRAIT(human_victim, TRAIT_NOBLOOD)) - return - - if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume && prob(internal_bleeding_chance + wounding_dmg)) - var/blood_bled = rand(1, wounding_dmg * (severity == WOUND_SEVERITY_CRITICAL ? 2 : 1.5)) // 12 brute toolbox can cause up to 18/24 bleeding with a severe/critical chest wound - switch(blood_bled) - if(1 to 6) - victim.bleed(blood_bled, TRUE) - if(7 to 13) - victim.visible_message(span_smalldanger("A thin stream of blood drips from [victim]'s mouth from the blow to [victim.p_their()] chest."), span_danger("You cough up a bit of blood from the blow to your chest."), vision_distance=COMBAT_MESSAGE_RANGE) - victim.bleed(blood_bled, TRUE) - if(14 to 19) - victim.visible_message(span_smalldanger("Blood spews out of [victim]'s mouth from the blow to [victim.p_their()] chest!"), span_danger("You spit out a string of blood from the blow to your chest!"), vision_distance=COMBAT_MESSAGE_RANGE) - new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir) - victim.bleed(blood_bled) - if(20 to INFINITY) - victim.visible_message(span_danger("Blood spurts out of [victim]'s mouth from the blow to [victim.p_their()] chest!"), span_danger("You choke up on a spray of blood from the blow to your chest!"), vision_distance=COMBAT_MESSAGE_RANGE) - victim.bleed(blood_bled) - new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir) - victim.add_splatter_floor(get_step(victim.loc, victim.dir)) - - -/datum/wound/blunt/get_examine_description(mob/user) - if(!limb.current_splint && !gelled && !taped) - return ..() - - var/list/msg = list() - if(!limb.current_splint) - msg += "[victim.p_their(TRUE)] [parse_zone(limb.body_zone)] [examine_desc]" - else - var/sling_condition = "" - // how much life we have left in these bandages - switch(limb.current_splint.sling_condition) - if(0 to 1.25) - sling_condition = "just barely" - if(1.25 to 2.75) - sling_condition = "loosely" - if(2.75 to 4) - sling_condition = "mostly" - if(4 to INFINITY) - sling_condition = "tightly" - - msg += "[victim.p_their(TRUE)] [parse_zone(limb.body_zone)] is [sling_condition] fastened with a [limb.current_splint.name]" - - if(taped) - msg += ", and appears to be reforming itself under some surgical tape!" - else if(gelled) - msg += ", with fizzing flecks of blue bone gel sparking off the bone!" - else - msg += "!" - return "[msg.Join()]" - -/* - New common procs for /datum/wound/blunt/ -*/ - -/datum/wound/blunt/proc/update_inefficiencies() - SIGNAL_HANDLER - if(limb.body_zone in list(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) - if(limb.current_splint) - limp_slowdown = initial(limp_slowdown) * limb.current_splint.splint_factor - else - limp_slowdown = initial(limp_slowdown) - victim.apply_status_effect(/datum/status_effect/limp) - else if(limb.body_zone in list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) - if(limb.current_splint) - interaction_efficiency_penalty = 1 + ((interaction_efficiency_penalty - 1) * limb.current_splint.splint_factor) - else - interaction_efficiency_penalty = interaction_efficiency_penalty - - if(initial(disabling)) - set_disabling(!(limb.current_splint && limb.current_splint.helps_disabled)) - - limb.update_wounds() - -/// Joint Dislocation (Moderate Blunt) -/datum/wound/blunt/moderate - name = "Joint Dislocation" - desc = "Patient's bone has been unset from socket, causing pain and reduced motor function." - treat_text = "Recommended application of bonesetter to affected limb, though manual relocation by applying an aggressive grab to the patient and helpfully interacting with afflicted limb may suffice." - examine_desc = "is awkwardly jammed out of place" - occur_text = "jerks violently and becomes unseated" - severity = WOUND_SEVERITY_MODERATE - viable_zones = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) - interaction_efficiency_penalty = 1.5 - limp_slowdown = 3 - threshold_minimum = 35 - threshold_penalty = 15 - treatable_tool = TOOL_BONESET - wound_flags = (BONE_WOUND) - status_effect_type = /datum/status_effect/wound/blunt/moderate - scar_keyword = "bluntmoderate" - -/datum/wound/blunt/moderate/Destroy() - if(victim) - UnregisterSignal(victim, COMSIG_LIVING_DOORCRUSHED) - return ..() - -/datum/wound/blunt/moderate/wound_injury(datum/wound/old_wound, attack_direction) - . = ..() - RegisterSignal(victim, COMSIG_LIVING_DOORCRUSHED, PROC_REF(door_crush)) - -/// Getting smushed in an airlock/firelock is a last-ditch attempt to try relocating your limb -/datum/wound/blunt/moderate/proc/door_crush() - SIGNAL_HANDLER - if(prob(33)) - victim.visible_message(span_danger("[victim]'s dislocated [parse_zone(limb.body_zone)] pops back into place!"), span_userdanger("Your dislocated [parse_zone(limb.body_zone)] pops back into place! Ow!")) - remove_wound() - -/datum/wound/blunt/moderate/try_handling(mob/living/carbon/human/user) - if(user.pulling != victim || user.zone_selected != limb.body_zone) - return FALSE - - if(user.grab_state == GRAB_PASSIVE) - to_chat(user, span_warning("You must have [victim] in an aggressive grab to manipulate [victim.p_their()] [lowertext(name)]!")) - return TRUE - - if(user.grab_state >= GRAB_AGGRESSIVE) - user.visible_message(span_danger("[user] begins twisting and straining [victim]'s dislocated [parse_zone(limb.body_zone)]!"), span_notice("You begin twisting and straining [victim]'s dislocated [parse_zone(limb.body_zone)]..."), ignored_mobs=victim) - to_chat(victim, span_userdanger("[user] begins twisting and straining your dislocated [parse_zone(limb.body_zone)]!")) - if(!user.combat_mode) - chiropractice(user) - else - malpractice(user) - return TRUE - -/// If someone is snapping our dislocated joint back into place by hand with an aggro grab and help intent -/datum/wound/blunt/moderate/proc/chiropractice(mob/living/carbon/human/user) - var/time = base_treat_time - - if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) - return - - if(prob(65)) - user.visible_message(span_danger("[user] snaps [victim]'s dislocated [parse_zone(limb.body_zone)] back into place!"), span_notice("You snap [victim]'s dislocated [parse_zone(limb.body_zone)] back into place!"), ignored_mobs=victim) - to_chat(victim, span_userdanger("[user] snaps your dislocated [parse_zone(limb.body_zone)] back into place!")) - victim.emote("scream") - limb.receive_damage(brute=20, wound_bonus=CANT_WOUND) - qdel(src) - else - user.visible_message(span_danger("[user] wrenches [victim]'s dislocated [parse_zone(limb.body_zone)] around painfully!"), span_danger("You wrench [victim]'s dislocated [parse_zone(limb.body_zone)] around painfully!"), ignored_mobs=victim) - to_chat(victim, span_userdanger("[user] wrenches your dislocated [parse_zone(limb.body_zone)] around painfully!")) - limb.receive_damage(brute=10, wound_bonus=CANT_WOUND) - chiropractice(user) - -/// If someone is snapping our dislocated joint into a fracture by hand with an aggro grab and harm or disarm intent -/datum/wound/blunt/moderate/proc/malpractice(mob/living/carbon/human/user) - var/time = base_treat_time - - if(!do_after(user, time, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) - return - - if(prob(65)) - user.visible_message(span_danger("[user] snaps [victim]'s dislocated [parse_zone(limb.body_zone)] with a sickening crack!"), span_danger("You snap [victim]'s dislocated [parse_zone(limb.body_zone)] with a sickening crack!"), ignored_mobs=victim) - to_chat(victim, span_userdanger("[user] snaps your dislocated [parse_zone(limb.body_zone)] with a sickening crack!")) - victim.emote("scream") - limb.receive_damage(brute=25, wound_bonus=30) - else - user.visible_message(span_danger("[user] wrenches [victim]'s dislocated [parse_zone(limb.body_zone)] around painfully!"), span_danger("You wrench [victim]'s dislocated [parse_zone(limb.body_zone)] around painfully!"), ignored_mobs=victim) - to_chat(victim, span_userdanger("[user] wrenches your dislocated [parse_zone(limb.body_zone)] around painfully!")) - limb.receive_damage(brute=10, wound_bonus=CANT_WOUND) - malpractice(user) - - -/datum/wound/blunt/moderate/treat(obj/item/I, mob/user) - if(victim == user) - victim.visible_message(span_danger("[user] begins resetting [victim.p_their()] [parse_zone(limb.body_zone)] with [I]."), span_warning("You begin resetting your [parse_zone(limb.body_zone)] with [I]...")) - else - user.visible_message(span_danger("[user] begins resetting [victim]'s [parse_zone(limb.body_zone)] with [I]."), span_notice("You begin resetting [victim]'s [parse_zone(limb.body_zone)] with [I]...")) - - if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, PROC_REF(still_exists)))) - return - - if(victim == user) - limb.receive_damage(brute=15, wound_bonus=CANT_WOUND) - victim.visible_message(span_danger("[user] finishes resetting [victim.p_their()] [parse_zone(limb.body_zone)]!"), span_userdanger("You reset your [parse_zone(limb.body_zone)]!")) - else - limb.receive_damage(brute=10, wound_bonus=CANT_WOUND) - user.visible_message(span_danger("[user] finishes resetting [victim]'s [parse_zone(limb.body_zone)]!"), span_nicegreen("You finish resetting [victim]'s [parse_zone(limb.body_zone)]!"), victim) - to_chat(victim, span_userdanger("[user] resets your [parse_zone(limb.body_zone)]!")) - - victim.emote("scream") - qdel(src) - -/* - Severe (Hairline Fracture) -*/ - -/datum/wound/blunt/severe - name = "Hairline Fracture" - desc = "Patient's bone has suffered a crack in the foundation, causing serious pain and reduced limb functionality." - treat_text = "Recommended light surgical application of bone gel, though a sling of medical gauze will prevent worsening situation." - examine_desc = "appears grotesquely swollen, its attachment weakened" - occur_text = "sprays chips of bone and develops a nasty looking bruise" - - severity = WOUND_SEVERITY_SEVERE - interaction_efficiency_penalty = 2 - limp_slowdown = 6 - threshold_minimum = 60 - threshold_penalty = 30 - treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/bone_gel) - status_effect_type = /datum/status_effect/wound/blunt/severe - scar_keyword = "bluntsevere" - brain_trauma_group = BRAIN_TRAUMA_MILD - trauma_cycle_cooldown = 1.5 MINUTES - internal_bleeding_chance = 40 - wound_flags = (BONE_WOUND | ACCEPTS_SPLINT | MANGLES_BONE) - regen_ticks_needed = 120 // ticks every 2 seconds, 240 seconds, so roughly 4 minutes default - -/// Compound Fracture (Critical Blunt) -/datum/wound/blunt/critical - name = "Compound Fracture" - desc = "Patient's bones have suffered multiple gruesome fractures, causing significant pain and near uselessness of limb." - treat_text = "Immediate binding of affected limb, followed by surgical intervention ASAP." - examine_desc = "is mangled and pulped, seemingly held together by tissue alone" - occur_text = "cracks apart, exposing broken bones to open air" - - severity = WOUND_SEVERITY_CRITICAL - interaction_efficiency_penalty = 4 - limp_slowdown = 9 - sound_effect = 'sound/effects/wounds/crack2.ogg' - threshold_minimum = 115 - threshold_penalty = 50 - disabling = TRUE - treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/bone_gel) - status_effect_type = /datum/status_effect/wound/blunt/critical - scar_keyword = "bluntcritical" - brain_trauma_group = BRAIN_TRAUMA_SEVERE - trauma_cycle_cooldown = 2.5 MINUTES - internal_bleeding_chance = 60 - wound_flags = (BONE_WOUND | ACCEPTS_SPLINT | MANGLES_BONE) - regen_ticks_needed = 240 // ticks every 2 seconds, 480 seconds, so roughly 8 minutes default - -// doesn't make much sense for "a" bone to stick out of your head -/datum/wound/blunt/critical/apply_wound(obj/item/bodypart/L, silent = FALSE, datum/wound/old_wound = null, smited = FALSE, attack_direction = null, wound_source = "Unknown") - if(L.body_zone == BODY_ZONE_HEAD) - occur_text = "splits open, exposing a bare, cracked skull through the flesh and blood" - examine_desc = "has an unsettling indent, with bits of skull poking out" - . = ..() - -/// if someone is using bone gel on our wound -/datum/wound/blunt/proc/gel(obj/item/stack/medical/bone_gel/gel, mob/user) - if(gelled) - to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [parse_zone(limb.body_zone)] is already coated with bone gel!")) - return - - user.visible_message(span_danger("[user] begins hastily applying [gel] to [victim]'s' [parse_zone(limb.body_zone)]..."), span_warning("You begin hastily applying [gel] to [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)], disregarding the warning label...")) - - if(!do_after(user, base_treat_time * 1.5 * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, PROC_REF(still_exists)))) - return - - gel.use(1) - victim.emote("scream") - if(user != victim) - user.visible_message(span_notice("[user] finishes applying [gel] to [victim]'s [parse_zone(limb.body_zone)], emitting a fizzing noise!"), span_notice("You finish applying [gel] to [victim]'s [parse_zone(limb.body_zone)]!"), ignored_mobs=victim) - to_chat(victim, span_userdanger("[user] finishes applying [gel] to your [parse_zone(limb.body_zone)], and you can feel the bones exploding with pain as they begin melting and reforming!")) - else - var/painkiller_bonus = 0 - if(victim.get_drunk_amount() > 10) - painkiller_bonus += 10 - if(victim.reagents.has_reagent(/datum/reagent/medicine/morphine)) - painkiller_bonus += 20 - if(victim.reagents.has_reagent(/datum/reagent/determination)) - painkiller_bonus += 10 - if(victim.reagents.has_reagent(/datum/reagent/consumable/ethanol/painkiller)) - painkiller_bonus += 5 - if(victim.reagents.has_reagent(/datum/reagent/medicine/mine_salve)) - painkiller_bonus += 20 - - if(prob(25 + (20 * (severity - 2)) - painkiller_bonus)) // 25%/45% chance to fail self-applying with severe and critical wounds, modded by painkillers - victim.visible_message(span_danger("[victim] fails to finish applying [gel] to [victim.p_their()] [parse_zone(limb.body_zone)], passing out from the pain!"), span_notice("You pass out from the pain of applying [gel] to your [parse_zone(limb.body_zone)] before you can finish!")) - victim.AdjustUnconscious(5 SECONDS) - return - victim.visible_message(span_notice("[victim] finishes applying [gel] to [victim.p_their()] [parse_zone(limb.body_zone)], grimacing from the pain!"), span_notice("You finish applying [gel] to your [parse_zone(limb.body_zone)], and your bones explode in pain!")) - - limb.receive_damage(25, wound_bonus=CANT_WOUND) - victim.adjustStaminaLoss(100) - if(!gelled) - gelled = TRUE - -/// if someone is using surgical tape on our wound -/datum/wound/blunt/proc/tape(obj/item/stack/sticky_tape/surgical/tape, mob/user) - if(!gelled) - to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [parse_zone(limb.body_zone)] must be coated with bone gel to perform this emergency operation!")) - return - if(taped) - to_chat(user, span_warning("[user == victim ? "Your" : "[victim]'s"] [parse_zone(limb.body_zone)] is already wrapped in [tape.name] and reforming!")) - return - - user.visible_message(span_danger("[user] begins applying [tape] to [victim]'s' [parse_zone(limb.body_zone)]..."), span_warning("You begin applying [tape] to [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)]...")) - - if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, PROC_REF(still_exists)))) - return - - if(victim == user) - regen_ticks_needed *= 1.5 - - tape.use(1) - if(user != victim) - user.visible_message(span_notice("[user] finishes applying [tape] to [victim]'s [parse_zone(limb.body_zone)], emitting a fizzing noise!"), span_notice("You finish applying [tape] to [victim]'s [parse_zone(limb.body_zone)]!"), ignored_mobs=victim) - to_chat(victim, span_green("[user] finishes applying [tape] to your [parse_zone(limb.body_zone)], you immediately begin to feel your bones start to reform!")) - else - victim.visible_message(span_notice("[victim] finishes applying [tape] to [victim.p_their()] [parse_zone(limb.body_zone)], !"), span_green("You finish applying [tape] to your [parse_zone(limb.body_zone)], and you immediately begin to feel your bones start to reform!")) - - taped = TRUE - processes = TRUE - -/datum/wound/blunt/treat(obj/item/used_item, mob/user) - if(istype(used_item, /obj/item/stack/medical/bone_gel)) - gel(used_item, user) - else if(istype(used_item, /obj/item/stack/sticky_tape/surgical)) - tape(used_item, user) - -/datum/wound/blunt/get_scanner_description(mob/user) - . = ..() - - . += "
" - - if(!gelled) - . += "Alternative Treatment: Apply bone gel directly to injured limb, then apply surgical tape to begin bone regeneration. This is both excruciatingly painful and slow, and only recommended in dire circumstances.\n" - else if(!taped) - . += span_notice("Continue Alternative Treatment: Apply surgical tape directly to injured limb to begin bone regeneration. Note, this is both excruciatingly painful and slow, though sleep or laying down will speed recovery.\n") - else - . += span_notice("Note: Bone regeneration in effect. Bone is [round(regen_ticks_current*100/regen_ticks_needed)]% regenerated.\n") - - if(limb.body_zone == BODY_ZONE_HEAD) - . += "Cranial Trauma Detected: Patient will suffer random bouts of [severity == WOUND_SEVERITY_SEVERE ? "mild" : "severe"] brain traumas until bone is repaired." - else if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume) - . += "Ribcage Trauma Detected: Further trauma to chest is likely to worsen internal bleeding until bone is repaired." - . += "
" - -/datum/wound/blunt/get_limb_examine_description() - return span_warning("The bones in this limb appear badly cracked.") diff --git a/modular_skyrat/modules/medical/code/wounds/burns.dm b/modular_skyrat/modules/medical/code/wounds/burns.dm deleted file mode 100644 index 45eb0f2b7dc..00000000000 --- a/modular_skyrat/modules/medical/code/wounds/burns.dm +++ /dev/null @@ -1,311 +0,0 @@ - -/* - Burn wounds -*/ - -// TODO: well, a lot really, but specifically I want to add potential fusing of clothing/equipment on the affected area, and limb infections, though those may go in body part code -/datum/wound/burn - name = "Burn Wound" - a_or_from = "from" - wound_type = WOUND_BURN - processes = TRUE - sound_effect = 'sound/effects/wounds/sizzle1.ogg' - wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE) - - treatable_by = list(/obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) // sterilizer and alcohol will require reagent treatments, coming soon - - // Flesh damage vars - /// How much damage to our flesh we currently have. Once both this and infestation reach 0, the wound is considered healed - var/flesh_damage = 5 - /// Our current counter for how much flesh regeneration we have stacked from regenerative mesh/synthflesh/whatever, decrements each tick and lowers flesh_damage - var/flesh_healing = 0 - - // Infestation vars (only for severe and critical) - /// How quickly infection breeds on this burn if we don't have disinfectant - var/infestation_rate = 0 - /// Our current level of infection - var/infestation = 0 - /// Our current level of sanitization/anti-infection, from disinfectants/alcohol/UV lights. While positive, totally pauses and slowly reverses infestation effects each tick - var/sanitization = 0 - - /// Once we reach infestation beyond WOUND_INFESTATION_SEPSIS, we get this many warnings before the limb is completely paralyzed (you'd have to ignore a really bad burn for a really long time for this to happen) - var/strikes_to_lose_limb = 3 - - -/datum/wound/burn/handle_process() - . = ..() - if(strikes_to_lose_limb == 0) // we've already hit sepsis, nothing more to do - victim.adjustToxLoss(0.5) - if(prob(1)) - victim.visible_message(span_danger("The infection on the remnants of [victim]'s [parse_zone(limb.body_zone)] shift and bubble nauseatingly!"), span_warning("You can feel the infection on the remnants of your [parse_zone(limb.body_zone)] coursing through your veins!"), vision_distance = COMBAT_MESSAGE_RANGE) - return - - if(victim.reagents) - if(victim.reagents.has_reagent(/datum/reagent/medicine/spaceacillin)) - sanitization += 0.9 - if(victim.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine)) - sanitization += 0.9 - if(victim.reagents.has_reagent(/datum/reagent/medicine/mine_salve)) - sanitization += 0.3 - flesh_healing += 0.5 - - var/bandage_factor = 1 // good bandages multiply the length of flesh healing - if(limb.current_gauze && limb.current_gauze.seep_gauze(WOUND_BURN_SANITIZATION_RATE, GAUZE_STAIN_PUS)) - bandage_factor = limb.current_gauze.sanitisation_factor - - - // if we have little/no infection, the limb doesn't have much burn damage, and our nutrition is good, heal some flesh - if(infestation <= WOUND_INFECTION_MODERATE && (limb.burn_dam < 5) && (victim.nutrition >= NUTRITION_LEVEL_FED)) - flesh_healing += 0.2 - - if(flesh_healing > 0) - flesh_damage = max(0, flesh_damage - 0.5) - flesh_healing = max(0, flesh_healing - (0.5 * bandage_factor)) // good bandages multiply the length of flesh healing - - // here's the check to see if we're cleared up - if((flesh_damage <= 0) && (infestation <= 1)) - to_chat(victim, span_green("The burns on your [parse_zone(limb.body_zone)] have cleared up!")) - qdel(src) - return - - // sanitization is checked after the clearing check but before the actual ill-effects, because we freeze the effects of infection while we have sanitization - if(sanitization > 0) - infestation = max(0, infestation - WOUND_BURN_SANITIZATION_RATE) - sanitization = max(0, sanitization - (WOUND_BURN_SANITIZATION_RATE * bandage_factor)) - return - - infestation += infestation_rate - - switch(infestation) - if(0 to WOUND_INFECTION_MODERATE) - if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE) - if(prob(30)) - victim.adjustToxLoss(0.2) - if(prob(6)) - to_chat(victim, span_warning("The blisters on your [parse_zone(limb.body_zone)] ooze a strange pus...")) - if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL) - if(!disabling && prob(2)) - to_chat(victim, span_warning("Your [parse_zone(limb.body_zone)] completely locks up, as you struggle for control against the infection!")) - set_disabling(TRUE) - else if(disabling && prob(8)) - to_chat(victim, span_notice("You regain sensation in your [parse_zone(limb.body_zone)], but it's still in terrible shape!")) - set_disabling(FALSE) - else if(prob(20)) - victim.adjustToxLoss(0.5) - if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC) - if(!disabling && prob(3)) - to_chat(victim, span_warning("You suddenly lose all sensation of the festering infection in your [parse_zone(limb.body_zone)]!")) - set_disabling(TRUE) - else if(disabling && prob(3)) - to_chat(victim, span_notice("You can barely feel your [parse_zone(limb.body_zone)] again, and you have to strain to retain motor control!")) - set_disabling(FALSE) - else if(prob(1)) - to_chat(victim, span_warning("You contemplate life without your [parse_zone(limb.body_zone)]...")) - victim.adjustToxLoss(0.75) - else if(prob(4)) - victim.adjustToxLoss(1) - if(WOUND_INFECTION_SEPTIC to INFINITY) - if(prob(infestation)) - switch(strikes_to_lose_limb) - if(3 to INFINITY) - to_chat(victim, span_deadsay("The skin on your [parse_zone(limb.body_zone)] is literally dripping off, you feel awful!")) - if(2) - to_chat(victim, span_deadsay("The infection in your [parse_zone(limb.body_zone)] is literally dripping off, you feel horrible!")) - if(1) - to_chat(victim, span_deadsay("Infection has just about completely claimed your [parse_zone(limb.body_zone)]!")) - if(0) - to_chat(victim, span_deadsay("The last of the nerve endings in your [parse_zone(limb.body_zone)] wither away, as the infection completely paralyzes your joint connector.")) - threshold_penalty = 120 // piss easy to destroy - var/datum/brain_trauma/severe/paralysis/sepsis = new (limb.body_zone) - victim.gain_trauma(sepsis) - strikes_to_lose_limb-- - -/datum/wound/burn/get_examine_description(mob/user) - if(strikes_to_lose_limb <= 0) - return span_deadsay("[victim.p_Their()] [parse_zone(limb.body_zone)] has locked up completely and is non-functional. Amputate or augment limb immediately, or place the patient in a cryotube.") - - var/list/condition = list("[victim.p_Their()] [parse_zone(limb.body_zone)] [examine_desc]") - if(limb.current_gauze) - var/bandage_condition - switch(limb.current_gauze.absorption_capacity) - if(0 to 1.25) - bandage_condition = "nearly ruined" - if(1.25 to 2.75) - bandage_condition = "badly worn" - if(2.75 to 4) - bandage_condition = "slightly pus-stained" - if(4 to INFINITY) - bandage_condition = "clean" - - condition += " underneath a dressing of [bandage_condition] [limb.current_gauze.name]" - else - switch(infestation) - if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE) - condition += ", with small spots of discoloration along the nearby veins!" - if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL) - condition += ", with growing clouds of infection." - if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC) - condition += ", with streaks of rotten, pulsating infection!" - if(WOUND_INFECTION_SEPTIC to INFINITY) - return span_deadsay("[victim.p_Their()] [parse_zone(limb.body_zone)] is a mess of charred skin and infected rot!") - else - condition += "!" - - return "[condition.Join()]" - -/datum/wound/burn/get_scanner_description(mob/user) - if(strikes_to_lose_limb == 0) - var/oopsie = "Type: [name]\nSeverity: [severity_text()]" - oopsie += "
Infection Level: The bodypart has suffered complete sepsis and must be removed. Amputate or augment limb immediately.
" - return oopsie - - . = ..() - . += "
" - - if(infestation <= sanitization && flesh_damage <= flesh_healing) - . += "No further treatment required: Burns will heal shortly." - else - switch(infestation) - if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE) - . += "Infection Level: Moderate\n" - if(WOUND_INFECTION_SEVERE to WOUND_INFECTION_CRITICAL) - . += "Infection Level: Severe\n" - if(WOUND_INFECTION_CRITICAL to WOUND_INFECTION_SEPTIC) - . += "Infection Level: CRITICAL\n" - if(WOUND_INFECTION_SEPTIC to INFINITY) - . += "Infection Level: LOSS IMMINENT\n" - if(infestation > sanitization) - . += "\tSurgical debridement, antibiotics/sterilizers, or regenerative mesh will rid infection. Paramedic UV penlights are also effective.\n" - - if(flesh_damage > 0) - . += "Flesh damage detected: Application of ointment, regenerative mesh, Synthflesh, or ingestion of \"Miner's Salve\" will repair damaged flesh. Good nutrition, rest, and keeping the wound clean can also slowly repair flesh.\n" - . += "
" - -/datum/wound/burn/get_limb_examine_description() - return span_warning("The flesh on this limb appears badly cooked.") - -/* - new burn common procs -*/ - -/// if someone is using ointment or mesh on our burns -/datum/wound/burn/proc/ointmentmesh(obj/item/stack/medical/treatment_item, mob/user) - user.visible_message(span_notice("[user] begins applying [treatment_item] to [victim]'s [parse_zone(limb.body_zone)]..."), span_notice("You begin applying [treatment_item] to [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)]...")) - if(!do_after(user, (user == victim ? treatment_item.self_delay : treatment_item.other_delay), extra_checks = CALLBACK(src, PROC_REF(still_exists)))) - return - - limb.heal_damage(treatment_item.heal_brute, treatment_item.heal_burn) - user.visible_message(span_green("[user] applies [treatment_item] to [victim]."), span_green("You apply [treatment_item] to [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)].")) - treatment_item.use(1) - sanitization += treatment_item.sanitization - flesh_healing += treatment_item.flesh_regeneration - - if((infestation <= 0 || sanitization >= infestation) && (flesh_damage <= 0 || flesh_healing > flesh_damage)) - to_chat(user, span_notice("You've done all you can with [treatment_item], now you must wait for the flesh on [victim]'s [parse_zone(limb.body_zone)] to recover.")) - else - try_treating(treatment_item, user) - -/// Paramedic UV penlights -/datum/wound/burn/proc/uv(obj/item/flashlight/pen/paramedic/penlight_used, mob/user) - if(!COOLDOWN_FINISHED(penlight_used, uv_cooldown)) - to_chat(user, span_notice("[penlight_used] is still recharging!")) - return - if(infestation <= 0 || infestation < sanitization) - to_chat(user, span_notice("There's no infection to treat on [victim]'s [parse_zone(limb.body_zone)]!")) - return - - user.visible_message(span_notice("[user] flashes the burns on [victim]'s [limb] with [penlight_used]."), span_notice("You flash the burns on [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)] with [penlight_used]."), vision_distance=COMBAT_MESSAGE_RANGE) - sanitization += penlight_used.uv_power - COOLDOWN_START(penlight_used, uv_cooldown, penlight_used.uv_cooldown_length) - -/datum/wound/burn/treat(obj/item/treatment_item, mob/user) - if(istype(treatment_item, /obj/item/stack/medical/ointment)) - ointmentmesh(treatment_item, user) - else if(istype(treatment_item, /obj/item/stack/medical/mesh)) - var/obj/item/stack/medical/mesh/mesh_check = treatment_item - if(!mesh_check.is_open) - to_chat(user, span_warning("You need to open [mesh_check] first.")) - return - ointmentmesh(mesh_check, user) - else if(istype(treatment_item, /obj/item/flashlight/pen/paramedic)) - uv(treatment_item, user) - -// people complained about burns not healing on stasis beds, so in addition to checking if it's cured, they also get the special ability to very slowly heal on stasis beds if they have the healing effects stored -/datum/wound/burn/on_stasis() - . = ..() - if(flesh_healing > 0) - flesh_damage = max(0, flesh_damage - 0.2) - if((flesh_damage <= 0) && (infestation <= WOUND_INFECTION_MODERATE)) - to_chat(victim, span_green("The burns on your [parse_zone(limb.body_zone)] have cleared up!")) - qdel(src) - return - if(sanitization > 0) - infestation = max(0, infestation - WOUND_BURN_SANITIZATION_RATE * 0.2) - -/datum/wound/burn/on_synthflesh(amount) - flesh_healing += amount * 0.5 // 20u patch will heal 10 flesh standard - -// we don't even care about first degree burns, straight to second -/datum/wound/burn/moderate - name = "Second Degree Burns" - desc = "Patient is suffering considerable burns with mild skin penetration, weakening limb integrity and increased burning sensations." - treat_text = "Recommended application of topical ointment or regenerative mesh to affected region." - examine_desc = "is badly burned and breaking out in blisters" - occur_text = "breaks out with violent red burns" - severity = WOUND_SEVERITY_MODERATE - damage_mulitplier_penalty = 1.1 - threshold_minimum = 40 - threshold_penalty = 30 // burns cause significant decrease in limb integrity compared to other wounds - status_effect_type = /datum/status_effect/wound/burn/moderate - flesh_damage = 5 - scar_keyword = "burnmoderate" - -/datum/wound/burn/severe - name = "Third Degree Burns" - desc = "Patient is suffering extreme burns with full skin penetration, creating serious risk of infection and greatly reduced limb integrity." - treat_text = "Recommended immediate disinfection and excision of any infected skin, followed by bandaging and ointment. If the limb has locked up, it must be amputated, augmented or treated with cryogenics." - examine_desc = "appears seriously charred, with aggressive red splotches" - occur_text = "chars rapidly, exposing ruined tissue and spreading angry red burns" - severity = WOUND_SEVERITY_SEVERE - damage_mulitplier_penalty = 1.2 - threshold_minimum = 80 - threshold_penalty = 40 - status_effect_type = /datum/status_effect/wound/burn/severe - treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) - infestation_rate = 0.05 // appx 13 minutes to reach sepsis without any treatment - flesh_damage = 12.5 - scar_keyword = "burnsevere" - -/datum/wound/burn/critical - name = "Catastrophic Burns" - desc = "Patient is suffering near complete loss of tissue and significantly charred muscle and bone, creating life-threatening risk of infection and negligible limb integrity." - treat_text = "Immediate surgical debriding of any infected skin, followed by potent tissue regeneration formula and bandaging. If the limb has locked up, it must be amputated, augmented or treated with cryogenics." - examine_desc = "is a ruined mess of blanched bone, melted fat, and charred tissue" - occur_text = "vaporizes as flesh, bone, and fat melt together in a horrifying mess" - severity = WOUND_SEVERITY_CRITICAL - damage_mulitplier_penalty = 1.3 - sound_effect = 'sound/effects/wounds/sizzle2.ogg' - threshold_minimum = 140 - threshold_penalty = 80 - status_effect_type = /datum/status_effect/wound/burn/critical - treatable_by = list(/obj/item/flashlight/pen/paramedic, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) - infestation_rate = 0.15 // appx 4.33 minutes to reach sepsis without any treatment - flesh_damage = 20 - scar_keyword = "burncritical" - -///special severe wound caused by sparring interference or other god related punishments. -/datum/wound/burn/severe/brand - name = "Holy Brand" - desc = "Patient is suffering extreme burns from a strange brand marking, creating serious risk of infection and greatly reduced limb integrity." - examine_desc = "appears to have holy symbols painfully branded into their flesh, leaving severe burns." - occur_text = "chars rapidly into a strange pattern of holy symbols, burned into the flesh." - -/// special severe wound caused by the cursed slot machine. -/datum/wound/burn/severe/cursed_brand - name = "Ancient Brand" - desc = "Patient is suffering extreme burns with oddly ornate brand markings, creating serious risk of infection and greatly reduced limb integrity." - examine_desc = "appears to have ornate symbols painfully branded into their flesh, leaving severe burns" - occur_text = "chars rapidly into a pattern that can only be described as an agglomeration of several financial symbols, burned into the flesh" - -/datum/wound/burn/severe/cursed_brand/get_limb_examine_description() - return span_warning("The flesh on this limb has several ornate symbols burned into it, with pitting throughout.") diff --git a/modular_skyrat/modules/medical/code/wounds/medical.dm b/modular_skyrat/modules/medical/code/wounds/medical.dm new file mode 100644 index 00000000000..80662956e5f --- /dev/null +++ b/modular_skyrat/modules/medical/code/wounds/medical.dm @@ -0,0 +1,147 @@ +#define SELF_AID_REMOVE_DELAY 5 SECONDS +#define OTHER_AID_REMOVE_DELAY 2 SECONDS + +/obj/item/stack/medical/gauze + /// The amount of direct hits our limb can take before we fall off. + var/integrity = 2 + /// The bodypart we are attached to. Nullable if we aren't applied to anything. + var/obj/item/bodypart/bodypart + /// If we are splinting a limb, this is the overlay prefix we will use. + var/splint_prefix = "splint" + /// If we are bandaging a limb, this is the overlay prefix we will use. + var/gauze_prefix = "gauze" + /// If it is at all possible for us to splint a limb. + var/can_splint = TRUE + +/obj/item/bodypart/apply_gauze(obj/item/stack/gauze) + RegisterSignal(src, COMSIG_BODYPART_GAUZED, PROC_REF(got_gauzed)) + + . = ..() + + UnregisterSignal(src, COMSIG_BODYPART_GAUZED) + +/// Signal handler that allows us to modularly detect if we were applied to a limb or not. +/obj/item/bodypart/proc/got_gauzed(datum/signal_source, obj/item/stack/medical/gauze/new_gauze) + SIGNAL_HANDLER + + if (istype(current_gauze, /obj/item/stack/medical/gauze)) + var/obj/item/stack/medical/gauze/applied_gauze = current_gauze + applied_gauze.set_limb(src) // new_gauze isnt actually the gauze that was applied weirdly + +/obj/item/stack/medical/gauze/Destroy() + bodypart?.current_gauze = null + bodypart?.owner?.update_bandage_overlays() + set_limb(null) + return ..() + +/** + * rip_off() called when someone rips it off + * + * It will return the bandage if it's considered pristine + * + */ +/obj/item/stack/medical/gauze/proc/rip_off() + if (is_pristine()) + . = new src.type(null, 1) + bodypart?.owner?.update_bandage_overlays() + qdel(src) + +/// Returns either [splint_prefix] or [gauze_prefix] depending on if we are splinting or not. Suffixes it with a digitigrade flag if applicable for the limb. +/obj/item/stack/medical/gauze/proc/get_overlay_prefix() + var/splinting = is_splinting() + + var/prefix + if (splinting) + prefix = splint_prefix + else + prefix = gauze_prefix + + var/suffix = bodypart.body_zone + if(bodypart.bodytype & BODYTYPE_DIGITIGRADE) + suffix += "_digitigrade" + + return "[prefix]_[suffix]" + +/// Returns if we can splint, and if any wound on our bodypart gives a splint overlay. +/obj/item/stack/medical/gauze/proc/is_splinting() + SHOULD_BE_PURE(TRUE) + + if (!can_splint) + return FALSE + + for (var/datum/wound/iterated_wound as anything in bodypart.wounds) + if (iterated_wound.wound_flags & SPLINT_OVERLAY) + return TRUE + + return FALSE + +/** + * is_pristine() called by rip_off() + * + * Used to determine whether the bandage can be re-used and won't qdel itself + * + */ + +/obj/item/stack/medical/gauze/proc/is_pristine() + return (integrity == initial(integrity)) + +/** + * get_hit() called when the bandage gets damaged + * + * This proc will subtract integrity and delete the bandage with a to_chat message to whoever was bandaged + * + */ + +/obj/item/stack/medical/gauze/proc/get_hit() + integrity-- + if(integrity <= 0) + if(bodypart.owner) + to_chat(bodypart.owner, span_warning("The [name] on your [bodypart.name] tears and falls off!")) + qdel(src) + +/obj/item/stack/medical/gauze/Topic(href, href_list) + . = ..() + if(href_list["remove"]) + if(!bodypart.owner) + return + if(!iscarbon(usr)) + return + if(!in_range(usr, bodypart.owner)) + return + var/mob/living/carbon/C = usr + var/self = (C == bodypart.owner) + C.visible_message(span_notice("[C] begins removing [name] from [self ? "[bodypart.owner.p_Their()]" : "[bodypart.owner]'s" ] [bodypart.name]..."), span_notice("You begin to remove [name] from [self ? "your" : "[bodypart.owner]'s"] [bodypart.name]...")) + if(!do_after(C, (self ? SELF_AID_REMOVE_DELAY : OTHER_AID_REMOVE_DELAY), target=bodypart.owner)) + return + if(QDELETED(src)) + return + C.visible_message(span_notice("[C] removes [name] from [self ? "[bodypart.owner.p_Their()]" : "[bodypart.owner]'s" ] [bodypart.name]."), span_notice("You remove [name] from [self ? "your" : "[bodypart.owner]'s" ] [bodypart.name].")) + var/obj/item/gotten = rip_off() + if(gotten && !C.put_in_hands(gotten)) + gotten.forceMove(get_turf(C)) + +/// Sets bodypart to limb, and then updates owner's bandage overlays. Limb is nullable. +/obj/item/stack/medical/gauze/proc/set_limb(limb) + bodypart = limb + bodypart?.owner?.update_bandage_overlays() + +/// Returns the name of ourself when used in a "owner is [usage_prefix] by [name]" examine_more situation/ +/obj/item/stack/proc/get_gauze_description() + return "[name]" + +/// Returns the usage prefix of ourself when used in a "owner is [usage_prefix] by [name]" examine_more situation/ +/obj/item/stack/proc/get_gauze_usage_prefix() + return "bandaged" + +/obj/item/stack/medical/gauze/get_gauze_usage_prefix() + if (is_splinting()) + return "fastened" + else + return ..() + +/// Returns TRUE if we can generate an overlay, false otherwise. +/obj/item/stack/medical/gauze/proc/has_overlay() + return (!isnull(gauze_prefix) && !isnull(splint_prefix)) + +/obj/item/stack/medical/gauze/improvised + splint_prefix = "splint_improv" diff --git a/modular_skyrat/modules/medical/code/wounds/muscle.dm b/modular_skyrat/modules/medical/code/wounds/muscle.dm index 2090da83bb8..7c6b0e11b3b 100644 --- a/modular_skyrat/modules/medical/code/wounds/muscle.dm +++ b/modular_skyrat/modules/medical/code/wounds/muscle.dm @@ -6,15 +6,58 @@ /datum/wound/muscle name = "Muscle Wound" sound_effect = 'sound/effects/wounds/blood1.ogg' - wound_type = WOUND_MUSCLE - wound_flags = (FLESH_WOUND | ACCEPTS_SPLINT) - viable_zones = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + wound_type = WOUND_BLUNT + wound_flags = (ACCEPTS_GAUZE | SPLINT_OVERLAY) + + wound_series = WOUND_SERIES_MUSCLE_DAMAGE + processes = TRUE /// How much do we need to regen. Will regen faster if we're splinted and or laying down var/regen_ticks_needed /// Our current counter for healing var/regen_ticks_current = 0 +/datum/wound_pregen_data/muscle + abstract = TRUE + + viable_zones = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + required_limb_biostate = BIO_FLESH + +/datum/wound_pregen_data/muscle/can_be_applied_to(obj/item/bodypart/limb, wound_type, datum/wound/old_wound, random_roll) + if (!istype(limb) || !limb.owner) + return FALSE + + if (random_roll && !can_be_randomly_generated) + return FALSE + + if (HAS_TRAIT(limb.owner, TRAIT_NEVER_WOUNDED) || (limb.owner.status_flags & GODMODE)) + return FALSE + // THIS IS HIGHLY TEMPORARY A PROC WILL COME FROM UPSTREAM THAT SHOULD REPLACE THIS!! REPLACE IT!!!!!!!!!!!! REMOVE THE OVERRIDE 8/31/23 ~Niko + if (wound_type != (WOUND_BLUNT) && wound_type != (WOUND_SLASH) && wound_type != (WOUND_PIERCE)) + return FALSE + else + for (var/datum/wound/preexisting_wound as anything in limb.wounds) + if (preexisting_wound.wound_series == initial(wound_path_to_generate.wound_series)) + if (preexisting_wound.severity >= initial(wound_path_to_generate.severity)) + return FALSE + + if (!ignore_cannot_bleed && ((required_limb_biostate & BIO_BLOODED) && !limb.can_bleed())) + return FALSE + + if (!biostate_valid(limb.biological_state)) + return FALSE + + if (!(limb.body_zone in viable_zones)) + return FALSE + + // we accept promotions and demotions, but no point in redundancy. This should have already been checked wherever the wound was rolled and applied for (see: bodypart damage code), but we do an extra check + // in case we ever directly add wounds + if (!duplicates_allowed) + for (var/datum/wound/preexisting_wound as anything in limb.wounds) + if (preexisting_wound.type == wound_path_to_generate && (preexisting_wound != old_wound)) + return FALSE + return TRUE + /* Overwriting of base procs */ @@ -51,8 +94,8 @@ if(victim.IsSleeping()) regen_ticks_current += 0.5 - if(limb.current_splint) - regen_ticks_current += (1-limb.current_splint.splint_factor) + if(limb.current_gauze) + regen_ticks_current += (1-limb.current_gauze.splint_factor) if(regen_ticks_current > regen_ticks_needed) if(!victim || !limb) @@ -83,26 +126,26 @@ return COMPONENT_CANCEL_ATTACK_CHAIN /datum/wound/muscle/get_examine_description(mob/user) - if(!limb.current_splint) + if(!limb.current_gauze) return ..() var/list/msg = list() - if(!limb.current_splint) + if(!limb.current_gauze) msg += "[victim.p_Their()] [parse_zone(limb.body_zone)] [examine_desc]" else - var/sling_condition = "" + var/absorption_capacity = "" // how much life we have left in these bandages - switch(limb.current_splint.sling_condition) + switch(limb.current_gauze.absorption_capacity) if(0 to 1.25) - sling_condition = "just barely" + absorption_capacity = "just barely" if(1.25 to 2.75) - sling_condition = "loosely" + absorption_capacity = "loosely" if(2.75 to 4) - sling_condition = "mostly" + absorption_capacity = "mostly" if(4 to INFINITY) - sling_condition = "tightly" + absorption_capacity = "tightly" - msg += "[victim.p_Their()] [parse_zone(limb.body_zone)] is [sling_condition] fastened with a [limb.current_splint.name]!" + msg += "[victim.p_Their()] [parse_zone(limb.body_zone)] is [absorption_capacity] fastened with a [limb.current_gauze.name]!" return "[msg.Join()]" @@ -113,19 +156,19 @@ /datum/wound/muscle/proc/update_inefficiencies() SIGNAL_HANDLER if(limb.body_zone in list(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) - if(limb.current_splint) - limp_slowdown = initial(limp_slowdown) * limb.current_splint.splint_factor + if(limb.current_gauze) + limp_slowdown = initial(limp_slowdown) * limb.current_gauze.splint_factor else limp_slowdown = initial(limp_slowdown) victim.apply_status_effect(/datum/status_effect/limp) else if(limb.body_zone in list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) - if(limb.current_splint) - interaction_efficiency_penalty = 1 + ((interaction_efficiency_penalty - 1) * limb.current_splint.splint_factor) + if(limb.current_gauze) + interaction_efficiency_penalty = 1 + ((interaction_efficiency_penalty - 1) * limb.current_gauze.splint_factor) else interaction_efficiency_penalty = interaction_efficiency_penalty if(initial(disabling)) - if(limb.current_splint && limb.current_splint.helps_disabled) + if(limb.current_gauze) set_disabling(FALSE) else set_disabling(TRUE) @@ -147,6 +190,11 @@ status_effect_type = /datum/status_effect/wound/muscle/moderate regen_ticks_needed = 90 +/datum/wound_pregen_data/muscle/tear + abstract = FALSE + + wound_path_to_generate = /datum/wound/muscle/moderate + /* Severe (Ruptured Tendon) */ @@ -167,6 +215,11 @@ status_effect_type = /datum/status_effect/wound/muscle/severe regen_ticks_needed = 150 +/datum/wound_pregen_data/muscle/tendon + abstract = FALSE + + wound_path_to_generate = /datum/wound/muscle/severe + /datum/status_effect/wound/muscle /datum/status_effect/wound/muscle/on_apply() diff --git a/modular_skyrat/modules/medical/code/wounds/pierce.dm b/modular_skyrat/modules/medical/code/wounds/pierce.dm deleted file mode 100644 index c41855402d0..00000000000 --- a/modular_skyrat/modules/medical/code/wounds/pierce.dm +++ /dev/null @@ -1,198 +0,0 @@ - -/* - Piercing wounds -*/ - -/datum/wound/pierce - name = "Piercing Wound" - sound_effect = 'sound/weapons/slice.ogg' - processes = TRUE - wound_type = WOUND_PIERCE - treatable_by = list(/obj/item/stack/medical/suture) - treatable_tool = TOOL_CAUTERY - base_treat_time = 3 SECONDS - wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE) - - /// How much blood we start losing when this wound is first applied - var/initial_flow - /// If gauzed, what percent of the internal bleeding actually clots of the total absorption rate - var/gauzed_clot_rate - - /// When hit on this bodypart, we have this chance of losing some blood + the incoming damage - var/internal_bleeding_chance - /// If we let off blood when hit, the max blood lost is this * the incoming damage - var/internal_bleeding_coefficient - -/datum/wound/slash/show_wound_topic(mob/user) - return (user == victim && blood_flow) - -/datum/wound/slash/Topic(href, href_list) - . = ..() - if(href_list["wound_topic"]) - if(!usr == victim) - return - victim.self_grasp_bleeding_limb(limb) - -/datum/wound/pierce/wound_injury(datum/wound/old_wound, attack_direction) - set_blood_flow(initial_flow) - -/datum/wound/pierce/receive_damage(wounding_type, wounding_dmg, wound_bonus) - if(victim.stat == DEAD || wounding_dmg < 5) - return - if(victim.blood_volume && prob(internal_bleeding_chance + wounding_dmg)) - if(limb.current_splint && limb.current_splint.splint_factor) - wounding_dmg *= (1 - limb.current_splint.splint_factor) - var/blood_bled = rand(1, wounding_dmg * internal_bleeding_coefficient) // 12 brute toolbox can cause up to 15/18/21 bloodloss on mod/sev/crit - switch(blood_bled) - if(1 to 6) - victim.bleed(blood_bled, TRUE) - if(7 to 13) - victim.visible_message(span_smalldanger("Blood droplets fly from the hole in [victim]'s [parse_zone(limb.body_zone)]."), span_danger("You cough up a bit of blood from the blow to your [parse_zone(limb.body_zone)]."), vision_distance=COMBAT_MESSAGE_RANGE) - victim.bleed(blood_bled, TRUE) - if(14 to 19) - victim.visible_message(span_smalldanger("A small stream of blood spurts from the hole in [victim]'s [parse_zone(limb.body_zone)]!"), span_danger("You spit out a string of blood from the blow to your [parse_zone(limb.body_zone)]!"), vision_distance=COMBAT_MESSAGE_RANGE) - new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir) - victim.bleed(blood_bled) - if(20 to INFINITY) - victim.visible_message(span_danger("A spray of blood streams from the gash in [victim]'s [parse_zone(limb.body_zone)]!"), span_danger("You choke up on a spray of blood from the blow to your [parse_zone(limb.body_zone)]!"), vision_distance=COMBAT_MESSAGE_RANGE) - victim.bleed(blood_bled) - new /obj/effect/temp_visual/dir_setting/bloodsplatter(victim.loc, victim.dir) - victim.add_splatter_floor(get_step(victim.loc, victim.dir)) - -/datum/wound/pierce/get_bleed_rate_of_change() - if(HAS_TRAIT(victim, TRAIT_BLOODY_MESS)) - return BLOOD_FLOW_INCREASING - if(limb.current_gauze) - return BLOOD_FLOW_DECREASING - return BLOOD_FLOW_STEADY - -/datum/wound/pierce/handle_process() - set_blood_flow(min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW)) - - if(victim.bodytemperature < (BODYTEMP_NORMAL - 10)) - adjust_blood_flow(-0.2) - if(prob(5)) - to_chat(victim, span_notice("You feel the [lowertext(name)] in your [parse_zone(limb.body_zone)] firming up from the cold!")) - - if(HAS_TRAIT(victim, TRAIT_BLOODY_MESS)) - adjust_blood_flow(0.5) // old heparin used to just add +2 bleed stacks per tick, this adds 0.5 bleed flow to all open cuts which is probably even stronger as long as you can cut them first - - if(limb.current_gauze && limb.current_gauze.seep_gauze(limb.current_gauze.absorption_rate, GAUZE_STAIN_BLOOD)) - adjust_blood_flow(-(limb.current_gauze.absorption_rate * gauzed_clot_rate)) - - if(blood_flow <= 0) - qdel(src) - -/datum/wound/pierce/on_stasis() - . = ..() - if(blood_flow <= 0) - qdel(src) - -/datum/wound/pierce/check_grab_treatments(obj/item/I, mob/user) - if(I.get_temperature()) // if we're using something hot but not a cautery, we need to be aggro grabbing them first, so we don't try treating someone we're eswording - return TRUE - -/datum/wound/pierce/treat(obj/item/treatment_item, mob/user) - if(istype(treatment_item, /obj/item/stack/medical/suture)) - suture(treatment_item, user) - else if(treatment_item.tool_behaviour == TOOL_CAUTERY || treatment_item.get_temperature()) - tool_cauterize(treatment_item, user) - -/datum/wound/pierce/on_xadone(power) - . = ..() - adjust_blood_flow(-(0.03 * power)) // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort - -/datum/wound/pierce/on_synthflesh(power) - . = ..() - adjust_blood_flow(-(0.05 * power)) // 20u * 0.05 = -1 blood flow, less than with slashes but still good considering smaller bleed rates - -/// If someone is using a suture to close this puncture -/datum/wound/pierce/proc/suture(obj/item/stack/medical/suture/used_suture, mob/user) - var/self_penalty_mult = (user == victim ? 1.4 : 1) - user.visible_message(span_notice("[user] begins stitching [victim]'s [parse_zone(limb.body_zone)] with [used_suture]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)] with [used_suture]...")) - if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) - return - user.visible_message(span_green("[user] stitches up some of the bleeding on [victim]."), span_green("You stitch up some of the bleeding on [user == victim ? "yourself" : "[victim]"].")) - var/blood_sutured = used_suture.stop_bleeding / self_penalty_mult - adjust_blood_flow(-blood_sutured) - limb.heal_damage(used_suture.heal_brute, used_suture.heal_burn) - used_suture.use(1) - - if(blood_flow > 0) - try_treating(used_suture, user) - else - to_chat(user, span_green("You successfully close the hole in [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)].")) - -/// If someone is using either a cautery tool or something with heat to cauterize this pierce -/datum/wound/pierce/proc/tool_cauterize(obj/item/used_cautery, mob/user) - var/improv_penalty_mult = (used_cautery.tool_behaviour == TOOL_CAUTERY ? 1 : 1.25) // 25% longer and less effective if you don't use a real cautery - var/self_penalty_mult = (user == victim ? 1.5 : 1) // 50% longer and less effective if you do it to yourself - - user.visible_message(span_danger("[user] begins cauterizing [victim]'s [parse_zone(limb.body_zone)] with [used_cautery]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)] with [used_cautery]...")) - if(!do_after(user, base_treat_time * self_penalty_mult * improv_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) - return - - user.visible_message(span_green("[user] cauterizes some of the bleeding on [victim]."), span_green("You cauterize some of the bleeding on [victim].")) - limb.receive_damage(burn = 2 + severity, wound_bonus = CANT_WOUND) - if(prob(30)) - victim.emote("scream") - var/blood_cauterized = (0.6 / (self_penalty_mult * improv_penalty_mult)) - adjust_blood_flow(-blood_cauterized) - - if(blood_flow > 0) - try_treating(used_cautery, user) - -/datum/wound/pierce/moderate - name = "Minor Breakage" - desc = "Patient's skin has been broken open, causing severe bruising and minor internal bleeding in affected area." - treat_text = "Treat affected site with bandaging or exposure to extreme cold. In dire cases, brief exposure to vacuum may suffice." // space is cold in ss13, so it's like an ice pack! - examine_desc = "has a small, circular hole, gently bleeding" - occur_text = "spurts out a thin stream of blood" - sound_effect = 'sound/effects/wounds/pierce1.ogg' - severity = WOUND_SEVERITY_MODERATE - initial_flow = 1.5 - gauzed_clot_rate = 0.8 - internal_bleeding_chance = 30 - internal_bleeding_coefficient = 1.25 - threshold_minimum = 30 - threshold_penalty = 20 - status_effect_type = /datum/status_effect/wound/pierce/moderate - scar_keyword = "piercemoderate" - -/datum/wound/pierce/severe - name = "Open Puncture" - desc = "Patient's internal tissue is penetrated, causing sizeable internal bleeding and reduced limb stability." - treat_text = "Repair punctures in skin by suture or cautery, extreme cold may also work." - examine_desc = "is pierced clear through, with bits of tissue obscuring the open hole" - occur_text = "looses a violent spray of blood, revealing a pierced wound" - sound_effect = 'sound/effects/wounds/pierce2.ogg' - severity = WOUND_SEVERITY_SEVERE - initial_flow = 2.25 - gauzed_clot_rate = 0.6 - internal_bleeding_chance = 60 - internal_bleeding_coefficient = 1.5 - threshold_minimum = 50 - threshold_penalty = 35 - status_effect_type = /datum/status_effect/wound/pierce/severe - scar_keyword = "piercesevere" - -/datum/wound/pierce/critical - name = "Ruptured Cavity" - desc = "Patient's internal tissue and circulatory system is shredded, causing significant internal bleeding and damage to internal organs." - treat_text = "Surgical repair of puncture wound, followed by supervised resanguination." - examine_desc = "is ripped clear through, barely held together by exposed bone" - occur_text = "blasts apart, sending chunks of viscera flying in all directions" - sound_effect = 'sound/effects/wounds/pierce3.ogg' - severity = WOUND_SEVERITY_CRITICAL - initial_flow = 3 - gauzed_clot_rate = 0.4 - internal_bleeding_chance = 80 - internal_bleeding_coefficient = 1.75 - threshold_minimum = 100 - threshold_penalty = 50 - status_effect_type = /datum/status_effect/wound/pierce/critical - scar_keyword = "piercecritical" - wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE | MANGLES_FLESH) - -/datum/wound/pierce/get_limb_examine_description() - return span_warning("The flesh on this limb appears badly perforated.") diff --git a/modular_skyrat/modules/medical/code/wounds/slash.dm b/modular_skyrat/modules/medical/code/wounds/slash.dm deleted file mode 100644 index 345381ac503..00000000000 --- a/modular_skyrat/modules/medical/code/wounds/slash.dm +++ /dev/null @@ -1,324 +0,0 @@ - -/* - Slashing wounds -*/ - -/datum/wound/slash - name = "Slashing (Cut) Wound" - sound_effect = 'sound/weapons/slice.ogg' - processes = TRUE - wound_type = WOUND_SLASH - treatable_by = list(/obj/item/stack/medical/suture) - treatable_by_grabbed = list(/obj/item/gun/energy/laser) - treatable_tool = TOOL_CAUTERY - base_treat_time = 3 SECONDS - wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE) - - /// How much blood we start losing when this wound is first applied - var/initial_flow - /// When we have less than this amount of flow, either from treatment or clotting, we demote to a lower cut or are healed of the wound - var/minimum_flow - /// How much our blood_flow will naturally decrease per second, not only do larger cuts bleed more blood faster, they clot slower (higher number = clot quicker, negative = opening up) - var/clot_rate - - /// Once the blood flow drops below minimum_flow, we demote it to this type of wound. If there's none, we're all better - var/demotes_to - - /// The maximum flow we've had so far - var/highest_flow - - /// A bad system I'm using to track the worst scar we earned (since we can demote, we want the biggest our wound has been, not what it was when it was cured (probably moderate)) - var/datum/scar/highest_scar - -/datum/wound/slash/show_wound_topic(mob/user) - return (user == victim && blood_flow) - -/datum/wound/slash/Topic(href, href_list) - . = ..() - if(href_list["wound_topic"]) - if(!usr == victim) - return - victim.self_grasp_bleeding_limb(limb) - -/datum/wound/slash/wound_injury(datum/wound/slash/old_wound = null, attack_direction) - if(old_wound) - set_blood_flow(max(old_wound.blood_flow, initial_flow)) - if(old_wound.severity > severity && old_wound.highest_scar) - highest_scar = old_wound.highest_scar - old_wound.highest_scar = null - else - set_blood_flow(initial_flow) - if(attack_direction && victim.blood_volume > BLOOD_VOLUME_OKAY) - victim.spray_blood(attack_direction, severity) - - if(!highest_scar) - highest_scar = new - highest_scar.generate(limb, src, add_to_scars=FALSE) - -/datum/wound/slash/remove_wound(ignore_limb, replaced) - if(!replaced && highest_scar) - already_scarred = TRUE - highest_scar.lazy_attach(limb) - return ..() - -/datum/wound/slash/get_examine_description(mob/user) - if(!limb.current_gauze) - return ..() - - var/list/msg = list("The cuts on [victim.p_their()] [parse_zone(limb.body_zone)] are wrapped with ") - // how much life we have left in these bandages - switch(limb.current_gauze.absorption_capacity) - if(0 to 1.25) - msg += "nearly ruined" - if(1.25 to 2.75) - msg += "badly worn" - if(2.75 to 4) - msg += "slightly bloodied" - if(4 to INFINITY) - msg += "clean" - msg += " [limb.current_gauze.name]!" - - return "[msg.Join()]" - -/datum/wound/slash/receive_damage(wounding_type, wounding_dmg, wound_bonus) - if(victim.stat != DEAD && wound_bonus != CANT_WOUND && wounding_type == WOUND_SLASH) // can't stab dead bodies to make it bleed faster this way - adjust_blood_flow(WOUND_SLASH_DAMAGE_FLOW_COEFF * wounding_dmg) - -/datum/wound/slash/drag_bleed_amount() - // say we have 3 severe cuts with 3 blood flow each, pretty reasonable - // compare with being at 100 brute damage before, where you bled (brute/100 * 2), = 2 blood per tile - var/bleed_amt = min(blood_flow * 0.1, 1) // 3 * 3 * 0.1 = 0.9 blood total, less than before! the share here is .3 blood of course. - - if(limb.current_gauze && limb.current_gauze.seep_gauze(bleed_amt * 0.33, GAUZE_STAIN_BLOOD)) // gauze stops all bleeding from dragging on this limb, but wears the gauze out quicker - return 0 - - return bleed_amt - -/datum/wound/slash/get_bleed_rate_of_change() - if(HAS_TRAIT(victim, TRAIT_BLOODY_MESS)) - return BLOOD_FLOW_INCREASING - if(limb.current_gauze || clot_rate > 0) - return BLOOD_FLOW_DECREASING - if(clot_rate < 0) - return BLOOD_FLOW_INCREASING - -/datum/wound/slash/handle_process() - set_blood_flow(min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW)) - - if(HAS_TRAIT(victim, TRAIT_BLOODY_MESS)) - adjust_blood_flow(0.5) // old heparin used to just add +2 bleed stacks per tick, this adds 0.5 bleed flow to all open cuts which is probably even stronger as long as you can cut them first - - if(limb.current_gauze) - if(clot_rate > 0) - adjust_blood_flow(-clot_rate) - if(limb.current_gauze && limb.current_gauze.seep_gauze(limb.current_gauze.absorption_rate, GAUZE_STAIN_BLOOD)) - adjust_blood_flow(-limb.current_gauze.absorption_rate) - else - adjust_blood_flow(-clot_rate) - - if(blood_flow > highest_flow) - highest_flow = blood_flow - - if(blood_flow < minimum_flow) - if(demotes_to) - replace_wound(demotes_to) - else - to_chat(victim, span_green("The cut on your [parse_zone(limb.body_zone)] has stopped bleeding!")) - qdel(src) - - -/datum/wound/slash/on_stasis() - if(blood_flow >= minimum_flow) - return - if(demotes_to) - replace_wound(demotes_to) - return - qdel(src) - -/* BEWARE, THE BELOW NONSENSE IS MADNESS. bones.dm looks more like what I have in mind and is sufficiently clean, don't pay attention to this messiness */ - -/datum/wound/slash/check_grab_treatments(obj/item/treatment_item, mob/user) - if(istype(treatment_item, /obj/item/gun/energy/laser)) - return TRUE - if(treatment_item.get_temperature()) // if we're using something hot but not a cautery, we need to be aggro grabbing them first, so we don't try treating someone we're eswording - return TRUE - -/datum/wound/slash/treat(obj/item/treatment_item, mob/user) - if(istype(treatment_item, /obj/item/gun/energy/laser)) - las_cauterize(treatment_item, user) - else if(treatment_item.tool_behaviour == TOOL_CAUTERY || treatment_item.get_temperature()) - tool_cauterize(treatment_item, user) - else if(istype(treatment_item, /obj/item/stack/medical/suture)) - suture(treatment_item, user) - -/datum/wound/slash/try_handling(mob/living/carbon/human/user) - if(user.pulling != victim || user.zone_selected != limb.body_zone || !user.combat_mode || !isfelinid(user) || !victim.can_inject(user, TRUE)) - return FALSE - if(DOING_INTERACTION_WITH_TARGET(user, victim)) - to_chat(user, span_warning("You're already interacting with [victim]!")) - return - if(user.is_mouth_covered()) - to_chat(user, span_warning("Your mouth is covered, you can't lick [victim]'s wounds!")) - return - if(!user.get_organ_slot(ORGAN_SLOT_TONGUE)) - to_chat(user, span_warning("You can't lick wounds without a tongue!")) // f in chat - return - - lick_wounds(user) - return TRUE - -/// if a felinid is licking this cut to reduce bleeding -/datum/wound/slash/proc/lick_wounds(mob/living/carbon/human/user) - // transmission is one way patient -> felinid since google said cat saliva is antiseptic or whatever, and also because felinids are already risking getting beaten for this even without people suspecting they're spreading a deathvirus - for(var/i in victim.diseases) - var/datum/disease/iter_disease = i - if(iter_disease.spread_flags & (DISEASE_SPREAD_SPECIAL | DISEASE_SPREAD_NON_CONTAGIOUS)) - continue - user.ForceContractDisease(iter_disease) - - user.visible_message(span_notice("[user] begins licking the wounds on [victim]'s [parse_zone(limb.body_zone)]."), span_notice("You begin licking the wounds on [victim]'s [parse_zone(limb.body_zone)]..."), ignored_mobs=victim) - to_chat(victim, span_notice("[user] begins to lick the wounds on your [parse_zone(limb.body_zone)].")) - if(!do_after(user, base_treat_time, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) - return - - user.visible_message(span_notice("[user] licks the wounds on [victim]'s [parse_zone(limb.body_zone)]."), span_notice("You lick some of the wounds on [victim]'s [parse_zone(limb.body_zone)]"), ignored_mobs=victim) - to_chat(victim, span_green("[user] licks the wounds on your [parse_zone(limb.body_zone)]!")) - adjust_blood_flow(-0.5) - - if(blood_flow > minimum_flow) - try_handling(user) - else if(demotes_to) - to_chat(user, span_green("You successfully lower the severity of [victim]'s cuts.")) - -/datum/wound/slash/on_xadone(power) - . = ..() - adjust_blood_flow(-(0.03 * power)) // i think it's like a minimum of 3 power, so .09 blood_flow reduction per tick is pretty good for 0 effort - -/datum/wound/slash/on_synthflesh(power) - . = ..() - adjust_blood_flow(-(0.075 * power)) // 20u * 0.075 = -1.5 blood flow, pretty good for how little effort it is - -/// If someone's putting a laser gun up to our cut to cauterize it -/datum/wound/slash/proc/las_cauterize(obj/item/gun/energy/laser/lasgun, mob/user) - var/self_penalty_mult = (user == victim ? 1.25 : 1) - user.visible_message(span_warning("[user] begins aiming [lasgun] directly at [victim]'s [parse_zone(limb.body_zone)]..."), span_userdanger("You begin aiming [lasgun] directly at [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)]...")) - if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) - return - var/damage = lasgun.chambered.loaded_projectile.damage - lasgun.chambered.loaded_projectile.wound_bonus -= 30 - lasgun.chambered.loaded_projectile.damage *= self_penalty_mult - if(!lasgun.process_fire(victim, victim, TRUE, null, limb.body_zone)) - return - victim.emote("scream") - adjust_blood_flow(-1 * (damage / (5 * self_penalty_mult))) // 20 / 5 = 4 bloodflow removed, p good - victim.visible_message(span_warning("The cuts on [victim]'s [parse_zone(limb.body_zone)] scar over!")) - -/// If someone is using either a cautery tool or something with heat to cauterize this cut -/datum/wound/slash/proc/tool_cauterize(obj/item/used_cautery, mob/user) - var/improv_penalty_mult = (used_cautery.tool_behaviour == TOOL_CAUTERY ? 1 : 1.25) // 25% longer and less effective if you don't use a real cautery - var/self_penalty_mult = (user == victim ? 1.5 : 1) // 50% longer and less effective if you do it to yourself - - user.visible_message(span_danger("[user] begins cauterizing [victim]'s [parse_zone(limb.body_zone)] with [used_cautery]..."), span_warning("You begin cauterizing [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)] with [used_cautery]...")) - if(!do_after(user, base_treat_time * self_penalty_mult * improv_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) - return - - user.visible_message(span_green("[user] cauterizes some of the bleeding on [victim]."), span_green("You cauterize some of the bleeding on [victim].")) - limb.receive_damage(burn = 2 + severity, wound_bonus = CANT_WOUND) - if(prob(30)) - victim.emote("scream") - var/blood_cauterized = (0.6 / (self_penalty_mult * improv_penalty_mult)) - adjust_blood_flow(-blood_cauterized) - - if(blood_flow > minimum_flow) - try_treating(used_cautery, user) - else if(demotes_to) - to_chat(user, span_green("You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.")) - -/// If someone is using a suture to close this cut -/datum/wound/slash/proc/suture(obj/item/stack/medical/suture/used_suture, mob/user) - var/self_penalty_mult = (user == victim ? 1.4 : 1) - user.visible_message(span_notice("[user] begins stitching [victim]'s [parse_zone(limb.body_zone)] with [used_suture]..."), span_notice("You begin stitching [user == victim ? "your" : "[victim]'s"] [parse_zone(limb.body_zone)] with [used_suture]...")) - - if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, PROC_REF(still_exists)))) - return - user.visible_message(span_green("[user] stitches up some of the bleeding on [victim]."), span_green("You stitch up some of the bleeding on [user == victim ? "yourself" : "[victim]"].")) - var/blood_sutured = used_suture.stop_bleeding / self_penalty_mult - adjust_blood_flow(-blood_sutured) - limb.heal_damage(used_suture.heal_brute, used_suture.heal_burn) - used_suture.use(1) - - if(blood_flow > minimum_flow) - try_treating(used_suture, user) - else if(demotes_to) - to_chat(user, span_green("You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.")) - - -/datum/wound/slash/moderate - name = "Rough Abrasion" - desc = "Patient's skin has been badly scraped, generating moderate blood loss." - treat_text = "Application of clean bandages or first-aid grade sutures, followed by food and rest." - examine_desc = "has an open cut" - occur_text = "is cut open, slowly leaking blood" - sound_effect = 'sound/effects/wounds/blood1.ogg' - severity = WOUND_SEVERITY_MODERATE - initial_flow = 2 - minimum_flow = 0.5 - clot_rate = 0.05 - threshold_minimum = 20 - threshold_penalty = 10 - status_effect_type = /datum/status_effect/wound/slash/moderate - scar_keyword = "slashmoderate" - -/datum/wound/slash/severe - name = "Open Laceration" - desc = "Patient's skin is ripped clean open, allowing significant blood loss." - treat_text = "Speedy application of first-aid grade sutures and clean bandages, followed by vitals monitoring to ensure recovery." - examine_desc = "has a severe cut" - occur_text = "is ripped open, veins spurting blood" - sound_effect = 'sound/effects/wounds/blood2.ogg' - severity = WOUND_SEVERITY_SEVERE - initial_flow = 3.25 - minimum_flow = 2.75 - clot_rate = 0.03 - threshold_minimum = 50 - threshold_penalty = 25 - demotes_to = /datum/wound/slash/moderate - status_effect_type = /datum/status_effect/wound/slash/severe - scar_keyword = "slashsevere" - -/datum/wound/slash/critical - name = "Weeping Avulsion" - desc = "Patient's skin is completely torn open, along with significant loss of tissue. Extreme blood loss will lead to quick death without intervention." - treat_text = "Immediate bandaging and either suturing or cauterization, followed by supervised resanguination." - examine_desc = "is carved down to the bone, spraying blood wildly" - occur_text = "is torn open, spraying blood wildly" - sound_effect = 'sound/effects/wounds/blood3.ogg' - severity = WOUND_SEVERITY_CRITICAL - initial_flow = 4 - minimum_flow = 3.85 - clot_rate = -0.015 // critical cuts actively get worse instead of better - threshold_minimum = 80 - threshold_penalty = 40 - demotes_to = /datum/wound/slash/severe - status_effect_type = /datum/status_effect/wound/slash/critical - scar_keyword = "slashcritical" - wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE | MANGLES_FLESH) - -/datum/wound/slash/moderate/many_cuts - name = "Numerous Small Slashes" - desc = "Patient's skin has numerous small slashes and cuts, generating moderate blood loss." - examine_desc = "has a ton of small cuts" - occur_text = "is cut numerous times, leaving many small slashes." - -// Subtype for cleave (heretic spell) -/datum/wound/slash/critical/cleave - name = "Burning Avulsion" - examine_desc = "is ruptured, spraying blood wildly" - clot_rate = 0.01 - -/datum/wound/slash/critical/cleave/update_descriptions() - if(no_bleeding) - occur_text = "is ruptured" - -/datum/wound/slash/get_limb_examine_description() - return span_warning("The flesh on this limb appears badly lacerated.") diff --git a/modular_skyrat/modules/mutants/code/mutant_component.dm b/modular_skyrat/modules/mutants/code/mutant_component.dm index 99233cb2656..4e78065eb37 100644 --- a/modular_skyrat/modules/mutants/code/mutant_component.dm +++ b/modular_skyrat/modules/mutants/code/mutant_component.dm @@ -100,7 +100,7 @@ if(SPT_PROB(10, seconds_per_tick)) var/obj/item/bodypart/wound_area = host.get_bodypart(BODY_ZONE_CHEST) if(wound_area) - var/datum/wound/slash/moderate/rotting_wound = new + var/datum/wound/slash/flesh/moderate/rotting_wound = new rotting_wound.apply_wound(wound_area) host.emote(pick(list("cough", "sneeze", "scream"))) if(timer_id) diff --git a/modular_skyrat/modules/robohand/code/bodypart_autosurgeon.dm b/modular_skyrat/modules/robohand/code/bodypart_autosurgeon.dm index 61f1e618a2e..46de28831c2 100644 --- a/modular_skyrat/modules/robohand/code/bodypart_autosurgeon.dm +++ b/modular_skyrat/modules/robohand/code/bodypart_autosurgeon.dm @@ -91,4 +91,3 @@ /obj/item/autosurgeon/bodypart/r_arm_robotic/Initialize(mapload) . = ..() storedbodypart.icon = 'modular_skyrat/master_files/icons/mob/augmentation/hi2ipc.dmi' - storedbodypart.organic_render = FALSE diff --git a/sound/attributions.txt b/sound/attributions.txt index 97e5faa5913..09ac2bd5642 100644 --- a/sound/attributions.txt +++ b/sound/attributions.txt @@ -88,7 +88,6 @@ https://freesound.org/people/squareal/sounds/237375/ ding_short.ogg is from Natty23 (CC 4) https://freesound.org/people/Natty23/sounds/411747/ - jingle.ogg is from Zapsplat (https://www.zapsplat.com/license-type/standard-license/) https://www.zapsplat.com/sound-effect-category/sleigh-bells/ diff --git a/tgstation.dme b/tgstation.dme index eac0e377ae2..9811b1d7093 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -432,6 +432,7 @@ #include "code\__DEFINES\~skyrat_defines\turfs.dm" #include "code\__DEFINES\~skyrat_defines\vox_defines.dm" #include "code\__DEFINES\~skyrat_defines\vv.dm" +#include "code\__DEFINES\~skyrat_defines\wounds.dm" #include "code\__DEFINES\~skyrat_defines\_globalvars\bitfields.dm" #include "code\__DEFINES\~skyrat_defines\_globalvars\logging.dm" #include "code\__DEFINES\~skyrat_defines\_globalvars\lists\mapping.dm" @@ -1701,13 +1702,16 @@ #include "code\datums\wires\syndicatebomb.dm" #include "code\datums\wires\tesla_coil.dm" #include "code\datums\wires\vending.dm" +#include "code\datums\wounds\_wound_static_data.dm" #include "code\datums\wounds\_wounds.dm" +#include "code\datums\wounds\blunt.dm" #include "code\datums\wounds\bones.dm" #include "code\datums\wounds\burns.dm" #include "code\datums\wounds\loss.dm" #include "code\datums\wounds\pierce.dm" #include "code\datums\wounds\slash.dm" #include "code\datums\wounds\scars\_scars.dm" +#include "code\datums\wounds\scars\_static_scar_data.dm" #include "code\game\alternate_appearance.dm" #include "code\game\atom_defense.dm" #include "code\game\atoms.dm" @@ -6885,19 +6889,14 @@ #include "modular_skyrat\modules\marines\code\modsuit_modules.dm" #include "modular_skyrat\modules\marines\code\smartgun.dm" #include "modular_skyrat\modules\medical\code\anesthetic_machine.dm" -#include "modular_skyrat\modules\medical\code\bodypart.dm" -#include "modular_skyrat\modules\medical\code\bodypart_aid.dm" -#include "modular_skyrat\modules\medical\code\carbon_defense.dm" #include "modular_skyrat\modules\medical\code\carbon_examine.dm" #include "modular_skyrat\modules\medical\code\carbon_update_icons.dm" -#include "modular_skyrat\modules\medical\code\medical_stacks.dm" +#include "modular_skyrat\modules\medical\code\grasp.dm" #include "modular_skyrat\modules\medical\code\smartdarts.dm" #include "modular_skyrat\modules\medical\code\wounds\_wounds.dm" -#include "modular_skyrat\modules\medical\code\wounds\bones.dm" -#include "modular_skyrat\modules\medical\code\wounds\burns.dm" +#include "modular_skyrat\modules\medical\code\wounds\bleed.dm" +#include "modular_skyrat\modules\medical\code\wounds\medical.dm" #include "modular_skyrat\modules\medical\code\wounds\muscle.dm" -#include "modular_skyrat\modules\medical\code\wounds\pierce.dm" -#include "modular_skyrat\modules\medical\code\wounds\slash.dm" #include "modular_skyrat\modules\medical_designs\medical_designs.dm" #include "modular_skyrat\modules\medievalcrate_skyrat\code\vintageitems.dm" #include "modular_skyrat\modules\mentor\code\_globalvars.dm" diff --git a/tools/pull_request_hooks/tests/flakyTestPayloads/monkey_business.txt b/tools/pull_request_hooks/tests/flakyTestPayloads/monkey_business.txt index bc7cbc26924..a52375357a0 100644 --- a/tools/pull_request_hooks/tests/flakyTestPayloads/monkey_business.txt +++ b/tools/pull_request_hooks/tests/flakyTestPayloads/monkey_business.txt @@ -168,12 +168,12 @@ 2022-11-01T15:23:05.7999555Z hint: Using 'master' as the name for the initial branch. This default branch name 2022-11-01T15:23:05.8000657Z hint: is subject to change. To configure the initial branch name to use in all 2022-11-01T15:23:05.8001229Z hint: of your new repositories, which will suppress this warning, call: -2022-11-01T15:23:05.8001635Z hint: +2022-11-01T15:23:05.8001635Z hint: 2022-11-01T15:23:05.8002546Z hint: git config --global init.defaultBranch -2022-11-01T15:23:05.8003017Z hint: +2022-11-01T15:23:05.8003017Z hint: 2022-11-01T15:23:05.8003562Z hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and 2022-11-01T15:23:05.8004498Z hint: 'development'. The just-created branch can be renamed via this command: -2022-11-01T15:23:05.8006177Z hint: +2022-11-01T15:23:05.8006177Z hint: 2022-11-01T15:23:05.8006532Z hint: git branch -m 2022-11-01T15:23:05.8016074Z Initialized empty Git repository in /home/runner/work/tgstation/tgstation/.git/ 2022-11-01T15:23:05.8029083Z [command]/usr/bin/git remote add origin https://github.com/tgstation/tgstation @@ -190,213 +190,213 @@ 2022-11-01T15:23:05.9154264Z ##[endgroup] 2022-11-01T15:23:05.9155507Z ##[group]Fetching the repository 2022-11-01T15:23:05.9167693Z [command]/usr/bin/git -c protocol.version=2 fetch --no-tags --prune --progress --no-recurse-submodules --depth=1 origin +90d58213531368fd97e9955fe80b75ad69c20f24:refs/remotes/pull/70980/merge -2022-11-01T15:23:06.8635625Z remote: Enumerating objects: 12567, done. -2022-11-01T15:23:06.8636451Z remote: Counting objects: 0% (1/12567) -2022-11-01T15:23:06.8650219Z remote: Counting objects: 1% (126/12567) -2022-11-01T15:23:06.8660754Z remote: Counting objects: 2% (252/12567) -2022-11-01T15:23:06.8672560Z remote: Counting objects: 3% (378/12567) -2022-11-01T15:23:06.8672977Z remote: Counting objects: 4% (503/12567) -2022-11-01T15:23:06.8673376Z remote: Counting objects: 5% (629/12567) -2022-11-01T15:23:06.8675482Z remote: Counting objects: 6% (755/12567) -2022-11-01T15:23:06.8675791Z remote: Counting objects: 7% (880/12567) -2022-11-01T15:23:06.9160118Z remote: Counting objects: 8% (1006/12567) -2022-11-01T15:23:06.9160767Z remote: Counting objects: 9% (1132/12567) -2022-11-01T15:23:06.9161166Z remote: Counting objects: 10% (1257/12567) -2022-11-01T15:23:06.9161566Z remote: Counting objects: 11% (1383/12567) -2022-11-01T15:23:06.9161964Z remote: Counting objects: 12% (1509/12567) -2022-11-01T15:23:06.9162324Z remote: Counting objects: 13% (1634/12567) -2022-11-01T15:23:06.9162700Z remote: Counting objects: 14% (1760/12567) -2022-11-01T15:23:06.9163069Z remote: Counting objects: 15% (1886/12567) -2022-11-01T15:23:06.9163437Z remote: Counting objects: 16% (2011/12567) -2022-11-01T15:23:06.9163808Z remote: Counting objects: 17% (2137/12567) -2022-11-01T15:23:06.9164357Z remote: Counting objects: 18% (2263/12567) -2022-11-01T15:23:06.9165066Z remote: Counting objects: 19% (2388/12567) -2022-11-01T15:23:06.9165451Z remote: Counting objects: 20% (2514/12567) -2022-11-01T15:23:06.9165800Z remote: Counting objects: 21% (2640/12567) -2022-11-01T15:23:06.9166097Z remote: Counting objects: 22% (2765/12567) -2022-11-01T15:23:06.9166459Z remote: Counting objects: 23% (2891/12567) -2022-11-01T15:23:06.9166827Z remote: Counting objects: 24% (3017/12567) -2022-11-01T15:23:06.9167178Z remote: Counting objects: 25% (3142/12567) -2022-11-01T15:23:06.9167700Z remote: Counting objects: 26% (3268/12567) -2022-11-01T15:23:06.9168060Z remote: Counting objects: 27% (3394/12567) -2022-11-01T15:23:06.9168413Z remote: Counting objects: 28% (3519/12567) -2022-11-01T15:23:06.9168685Z remote: Counting objects: 29% (3645/12567) -2022-11-01T15:23:06.9169293Z remote: Counting objects: 30% (3771/12567) -2022-11-01T15:23:06.9169550Z remote: Counting objects: 31% (3896/12567) -2022-11-01T15:23:06.9169791Z remote: Counting objects: 32% (4022/12567) -2022-11-01T15:23:06.9170049Z remote: Counting objects: 33% (4148/12567) -2022-11-01T15:23:06.9170305Z remote: Counting objects: 34% (4273/12567) -2022-11-01T15:23:06.9170563Z remote: Counting objects: 35% (4399/12567) -2022-11-01T15:23:06.9170803Z remote: Counting objects: 36% (4525/12567) -2022-11-01T15:23:06.9171062Z remote: Counting objects: 37% (4650/12567) -2022-11-01T15:23:06.9171316Z remote: Counting objects: 38% (4776/12567) -2022-11-01T15:23:06.9171714Z remote: Counting objects: 39% (4902/12567) -2022-11-01T15:23:06.9171963Z remote: Counting objects: 40% (5027/12567) -2022-11-01T15:23:06.9172211Z remote: Counting objects: 41% (5153/12567) -2022-11-01T15:23:06.9172447Z remote: Counting objects: 42% (5279/12567) -2022-11-01T15:23:06.9172868Z remote: Counting objects: 43% (5404/12567) -2022-11-01T15:23:06.9173464Z remote: Counting objects: 44% (5530/12567) -2022-11-01T15:23:06.9173834Z remote: Counting objects: 45% (5656/12567) -2022-11-01T15:23:06.9174083Z remote: Counting objects: 46% (5781/12567) -2022-11-01T15:23:06.9174458Z remote: Counting objects: 47% (5907/12567) -2022-11-01T15:23:06.9174828Z remote: Counting objects: 48% (6033/12567) -2022-11-01T15:23:06.9175193Z remote: Counting objects: 49% (6158/12567) -2022-11-01T15:23:06.9175686Z remote: Counting objects: 50% (6284/12567) -2022-11-01T15:23:06.9176096Z remote: Counting objects: 51% (6410/12567) -2022-11-01T15:23:06.9176806Z remote: Counting objects: 52% (6535/12567) -2022-11-01T15:23:06.9177226Z remote: Counting objects: 53% (6661/12567) -2022-11-01T15:23:06.9383126Z remote: Counting objects: 54% (6787/12567) -2022-11-01T15:23:06.9383471Z remote: Counting objects: 55% (6912/12567) -2022-11-01T15:23:06.9383912Z remote: Counting objects: 56% (7038/12567) -2022-11-01T15:23:06.9384205Z remote: Counting objects: 57% (7164/12567) -2022-11-01T15:23:06.9384882Z remote: Counting objects: 58% (7289/12567) -2022-11-01T15:23:06.9385322Z remote: Counting objects: 59% (7415/12567) -2022-11-01T15:23:06.9385593Z remote: Counting objects: 60% (7541/12567) -2022-11-01T15:23:06.9386047Z remote: Counting objects: 61% (7666/12567) -2022-11-01T15:23:06.9386320Z remote: Counting objects: 62% (7792/12567) -2022-11-01T15:23:06.9386602Z remote: Counting objects: 63% (7918/12567) -2022-11-01T15:23:06.9387066Z remote: Counting objects: 64% (8043/12567) -2022-11-01T15:23:06.9387318Z remote: Counting objects: 65% (8169/12567) -2022-11-01T15:23:06.9387584Z remote: Counting objects: 66% (8295/12567) -2022-11-01T15:23:06.9387858Z remote: Counting objects: 67% (8420/12567) -2022-11-01T15:23:06.9388109Z remote: Counting objects: 68% (8546/12567) -2022-11-01T15:23:06.9388374Z remote: Counting objects: 69% (8672/12567) -2022-11-01T15:23:06.9388777Z remote: Counting objects: 70% (8797/12567) -2022-11-01T15:23:06.9389026Z remote: Counting objects: 71% (8923/12567) -2022-11-01T15:23:06.9389293Z remote: Counting objects: 72% (9049/12567) -2022-11-01T15:23:06.9389558Z remote: Counting objects: 73% (9174/12567) -2022-11-01T15:23:06.9389987Z remote: Counting objects: 74% (9300/12567) -2022-11-01T15:23:06.9390230Z remote: Counting objects: 75% (9426/12567) -2022-11-01T15:23:06.9390484Z remote: Counting objects: 76% (9551/12567) -2022-11-01T15:23:06.9390738Z remote: Counting objects: 77% (9677/12567) -2022-11-01T15:23:06.9390979Z remote: Counting objects: 78% (9803/12567) -2022-11-01T15:23:06.9391235Z remote: Counting objects: 79% (9928/12567) -2022-11-01T15:23:06.9391796Z remote: Counting objects: 80% (10054/12567) -2022-11-01T15:23:06.9392047Z remote: Counting objects: 81% (10180/12567) -2022-11-01T15:23:06.9392314Z remote: Counting objects: 82% (10305/12567) -2022-11-01T15:23:06.9392577Z remote: Counting objects: 83% (10431/12567) -2022-11-01T15:23:06.9392824Z remote: Counting objects: 84% (10557/12567) -2022-11-01T15:23:06.9393085Z remote: Counting objects: 85% (10682/12567) -2022-11-01T15:23:06.9394375Z remote: Counting objects: 86% (10808/12567) -2022-11-01T15:23:06.9394631Z remote: Counting objects: 87% (10934/12567) -2022-11-01T15:23:06.9394877Z remote: Counting objects: 88% (11059/12567) -2022-11-01T15:23:06.9395134Z remote: Counting objects: 89% (11185/12567) -2022-11-01T15:23:06.9395389Z remote: Counting objects: 90% (11311/12567) -2022-11-01T15:23:06.9395622Z remote: Counting objects: 91% (11436/12567) -2022-11-01T15:23:06.9395877Z remote: Counting objects: 92% (11562/12567) -2022-11-01T15:23:06.9396132Z remote: Counting objects: 93% (11688/12567) -2022-11-01T15:23:06.9396564Z remote: Counting objects: 94% (11813/12567) -2022-11-01T15:23:06.9396804Z remote: Counting objects: 95% (11939/12567) -2022-11-01T15:23:06.9397061Z remote: Counting objects: 96% (12065/12567) -2022-11-01T15:23:06.9397319Z remote: Counting objects: 97% (12190/12567) -2022-11-01T15:23:06.9397557Z remote: Counting objects: 98% (12316/12567) -2022-11-01T15:23:06.9397810Z remote: Counting objects: 99% (12442/12567) -2022-11-01T15:23:06.9398208Z remote: Counting objects: 100% (12567/12567) -2022-11-01T15:23:06.9398661Z remote: Counting objects: 100% (12567/12567), done. -2022-11-01T15:23:06.9398965Z remote: Compressing objects: 0% (1/10988) -2022-11-01T15:23:06.9399257Z remote: Compressing objects: 1% (110/10988) -2022-11-01T15:23:06.9439997Z remote: Compressing objects: 2% (220/10988) -2022-11-01T15:23:06.9561627Z remote: Compressing objects: 3% (330/10988) -2022-11-01T15:23:06.9680955Z remote: Compressing objects: 4% (440/10988) -2022-11-01T15:23:06.9723040Z remote: Compressing objects: 5% (550/10988) -2022-11-01T15:23:06.9876931Z remote: Compressing objects: 6% (660/10988) -2022-11-01T15:23:07.0170815Z remote: Compressing objects: 7% (770/10988) -2022-11-01T15:23:07.0504059Z remote: Compressing objects: 8% (880/10988) -2022-11-01T15:23:07.0836116Z remote: Compressing objects: 9% (989/10988) -2022-11-01T15:23:07.1460729Z remote: Compressing objects: 10% (1099/10988) -2022-11-01T15:23:07.6608683Z remote: Compressing objects: 11% (1209/10988) -2022-11-01T15:23:07.7588422Z remote: Compressing objects: 12% (1319/10988) -2022-11-01T15:23:07.9494647Z remote: Compressing objects: 13% (1429/10988) -2022-11-01T15:23:07.9527972Z remote: Compressing objects: 13% (1508/10988) -2022-11-01T15:23:07.9668498Z remote: Compressing objects: 14% (1539/10988) -2022-11-01T15:23:08.0219248Z remote: Compressing objects: 15% (1649/10988) -2022-11-01T15:23:08.0283852Z remote: Compressing objects: 16% (1759/10988) -2022-11-01T15:23:08.0452608Z remote: Compressing objects: 17% (1868/10988) -2022-11-01T15:23:08.0618448Z remote: Compressing objects: 18% (1978/10988) -2022-11-01T15:23:08.0889220Z remote: Compressing objects: 19% (2088/10988) -2022-11-01T15:23:08.1162946Z remote: Compressing objects: 20% (2198/10988) -2022-11-01T15:23:08.1247220Z remote: Compressing objects: 21% (2308/10988) -2022-11-01T15:23:08.1520626Z remote: Compressing objects: 22% (2418/10988) -2022-11-01T15:23:08.2139765Z remote: Compressing objects: 23% (2528/10988) -2022-11-01T15:23:08.2412924Z remote: Compressing objects: 24% (2638/10988) -2022-11-01T15:23:08.2597478Z remote: Compressing objects: 25% (2747/10988) -2022-11-01T15:23:08.2752211Z remote: Compressing objects: 26% (2857/10988) -2022-11-01T15:23:08.2966161Z remote: Compressing objects: 27% (2967/10988) -2022-11-01T15:23:08.3926822Z remote: Compressing objects: 28% (3077/10988) -2022-11-01T15:23:08.3927793Z remote: Compressing objects: 29% (3187/10988) -2022-11-01T15:23:08.4094739Z remote: Compressing objects: 30% (3297/10988) -2022-11-01T15:23:08.4338176Z remote: Compressing objects: 31% (3407/10988) -2022-11-01T15:23:08.4632502Z remote: Compressing objects: 32% (3517/10988) -2022-11-01T15:23:08.4940329Z remote: Compressing objects: 33% (3627/10988) -2022-11-01T15:23:08.5404129Z remote: Compressing objects: 34% (3736/10988) -2022-11-01T15:23:08.5814756Z remote: Compressing objects: 35% (3846/10988) -2022-11-01T15:23:08.6091092Z remote: Compressing objects: 36% (3956/10988) -2022-11-01T15:23:08.6446921Z remote: Compressing objects: 37% (4066/10988) -2022-11-01T15:23:08.6900873Z remote: Compressing objects: 38% (4176/10988) -2022-11-01T15:23:08.7213081Z remote: Compressing objects: 39% (4286/10988) -2022-11-01T15:23:08.7502723Z remote: Compressing objects: 40% (4396/10988) -2022-11-01T15:23:08.7869698Z remote: Compressing objects: 41% (4506/10988) -2022-11-01T15:23:08.8103626Z remote: Compressing objects: 42% (4615/10988) -2022-11-01T15:23:08.8451299Z remote: Compressing objects: 43% (4725/10988) -2022-11-01T15:23:08.8774688Z remote: Compressing objects: 44% (4835/10988) -2022-11-01T15:23:08.9003331Z remote: Compressing objects: 45% (4945/10988) -2022-11-01T15:23:08.9070180Z remote: Compressing objects: 45% (5034/10988) -2022-11-01T15:23:08.9344499Z remote: Compressing objects: 46% (5055/10988) -2022-11-01T15:23:08.9568190Z remote: Compressing objects: 47% (5165/10988) -2022-11-01T15:23:08.9805763Z remote: Compressing objects: 48% (5275/10988) -2022-11-01T15:23:09.0037568Z remote: Compressing objects: 49% (5385/10988) -2022-11-01T15:23:09.0301310Z remote: Compressing objects: 50% (5494/10988) -2022-11-01T15:23:09.0582321Z remote: Compressing objects: 51% (5604/10988) -2022-11-01T15:23:09.0808327Z remote: Compressing objects: 52% (5714/10988) -2022-11-01T15:23:09.1124129Z remote: Compressing objects: 53% (5824/10988) -2022-11-01T15:23:09.1387087Z remote: Compressing objects: 54% (5934/10988) -2022-11-01T15:23:09.1647455Z remote: Compressing objects: 55% (6044/10988) -2022-11-01T15:23:09.1915056Z remote: Compressing objects: 56% (6154/10988) -2022-11-01T15:23:09.2255320Z remote: Compressing objects: 57% (6264/10988) -2022-11-01T15:23:09.2457326Z remote: Compressing objects: 58% (6374/10988) -2022-11-01T15:23:09.2755910Z remote: Compressing objects: 59% (6483/10988) -2022-11-01T15:23:09.3017305Z remote: Compressing objects: 60% (6593/10988) -2022-11-01T15:23:09.3325069Z remote: Compressing objects: 61% (6703/10988) -2022-11-01T15:23:09.3546803Z remote: Compressing objects: 62% (6813/10988) -2022-11-01T15:23:09.3801684Z remote: Compressing objects: 63% (6923/10988) -2022-11-01T15:23:09.4067963Z remote: Compressing objects: 64% (7033/10988) -2022-11-01T15:23:09.5472387Z remote: Compressing objects: 65% (7143/10988) -2022-11-01T15:23:09.5473083Z remote: Compressing objects: 66% (7253/10988) -2022-11-01T15:23:09.5473536Z remote: Compressing objects: 67% (7362/10988) -2022-11-01T15:23:09.5473940Z remote: Compressing objects: 68% (7472/10988) -2022-11-01T15:23:09.5474375Z remote: Compressing objects: 69% (7582/10988) -2022-11-01T15:23:09.5474794Z remote: Compressing objects: 70% (7692/10988) -2022-11-01T15:23:09.5475212Z remote: Compressing objects: 71% (7802/10988) -2022-11-01T15:23:09.5475789Z remote: Compressing objects: 72% (7912/10988) -2022-11-01T15:23:09.5476209Z remote: Compressing objects: 73% (8022/10988) -2022-11-01T15:23:09.5477532Z remote: Compressing objects: 74% (8132/10988) -2022-11-01T15:23:09.5478233Z remote: Compressing objects: 75% (8241/10988) -2022-11-01T15:23:09.5478582Z remote: Compressing objects: 76% (8351/10988) -2022-11-01T15:23:09.5479163Z remote: Compressing objects: 77% (8461/10988) -2022-11-01T15:23:09.5479885Z remote: Compressing objects: 78% (8571/10988) -2022-11-01T15:23:09.5480434Z remote: Compressing objects: 79% (8681/10988) -2022-11-01T15:23:09.5480899Z remote: Compressing objects: 80% (8791/10988) -2022-11-01T15:23:09.5481594Z remote: Compressing objects: 81% (8901/10988) -2022-11-01T15:23:09.5482284Z remote: Compressing objects: 82% (9011/10988) -2022-11-01T15:23:09.5482865Z remote: Compressing objects: 83% (9121/10988) -2022-11-01T15:23:09.5483308Z remote: Compressing objects: 84% (9230/10988) -2022-11-01T15:23:09.5483685Z remote: Compressing objects: 85% (9340/10988) -2022-11-01T15:23:09.5484385Z remote: Compressing objects: 86% (9450/10988) -2022-11-01T15:23:09.5485582Z remote: Compressing objects: 87% (9560/10988) -2022-11-01T15:23:09.5486089Z remote: Compressing objects: 88% (9670/10988) -2022-11-01T15:23:09.5486597Z remote: Compressing objects: 89% (9780/10988) -2022-11-01T15:23:09.5487116Z remote: Compressing objects: 90% (9890/10988) -2022-11-01T15:23:09.5487742Z remote: Compressing objects: 91% (10000/10988) -2022-11-01T15:23:09.5488235Z remote: Compressing objects: 92% (10109/10988) -2022-11-01T15:23:09.5488673Z remote: Compressing objects: 93% (10219/10988) -2022-11-01T15:23:09.5489383Z remote: Compressing objects: 94% (10329/10988) -2022-11-01T15:23:09.5489745Z remote: Compressing objects: 95% (10439/10988) -2022-11-01T15:23:09.5490195Z remote: Compressing objects: 96% (10549/10988) -2022-11-01T15:23:09.5490745Z remote: Compressing objects: 97% (10659/10988) -2022-11-01T15:23:09.5491127Z remote: Compressing objects: 98% (10769/10988) -2022-11-01T15:23:09.5491596Z remote: Compressing objects: 99% (10879/10988) -2022-11-01T15:23:09.5492106Z remote: Compressing objects: 100% (10988/10988) -2022-11-01T15:23:09.5492683Z remote: Compressing objects: 100% (10988/10988), done. +2022-11-01T15:23:06.8635625Z remote: Enumerating objects: 12567, done. +2022-11-01T15:23:06.8636451Z remote: Counting objects: 0% (1/12567) +2022-11-01T15:23:06.8650219Z remote: Counting objects: 1% (126/12567) +2022-11-01T15:23:06.8660754Z remote: Counting objects: 2% (252/12567) +2022-11-01T15:23:06.8672560Z remote: Counting objects: 3% (378/12567) +2022-11-01T15:23:06.8672977Z remote: Counting objects: 4% (503/12567) +2022-11-01T15:23:06.8673376Z remote: Counting objects: 5% (629/12567) +2022-11-01T15:23:06.8675482Z remote: Counting objects: 6% (755/12567) +2022-11-01T15:23:06.8675791Z remote: Counting objects: 7% (880/12567) +2022-11-01T15:23:06.9160118Z remote: Counting objects: 8% (1006/12567) +2022-11-01T15:23:06.9160767Z remote: Counting objects: 9% (1132/12567) +2022-11-01T15:23:06.9161166Z remote: Counting objects: 10% (1257/12567) +2022-11-01T15:23:06.9161566Z remote: Counting objects: 11% (1383/12567) +2022-11-01T15:23:06.9161964Z remote: Counting objects: 12% (1509/12567) +2022-11-01T15:23:06.9162324Z remote: Counting objects: 13% (1634/12567) +2022-11-01T15:23:06.9162700Z remote: Counting objects: 14% (1760/12567) +2022-11-01T15:23:06.9163069Z remote: Counting objects: 15% (1886/12567) +2022-11-01T15:23:06.9163437Z remote: Counting objects: 16% (2011/12567) +2022-11-01T15:23:06.9163808Z remote: Counting objects: 17% (2137/12567) +2022-11-01T15:23:06.9164357Z remote: Counting objects: 18% (2263/12567) +2022-11-01T15:23:06.9165066Z remote: Counting objects: 19% (2388/12567) +2022-11-01T15:23:06.9165451Z remote: Counting objects: 20% (2514/12567) +2022-11-01T15:23:06.9165800Z remote: Counting objects: 21% (2640/12567) +2022-11-01T15:23:06.9166097Z remote: Counting objects: 22% (2765/12567) +2022-11-01T15:23:06.9166459Z remote: Counting objects: 23% (2891/12567) +2022-11-01T15:23:06.9166827Z remote: Counting objects: 24% (3017/12567) +2022-11-01T15:23:06.9167178Z remote: Counting objects: 25% (3142/12567) +2022-11-01T15:23:06.9167700Z remote: Counting objects: 26% (3268/12567) +2022-11-01T15:23:06.9168060Z remote: Counting objects: 27% (3394/12567) +2022-11-01T15:23:06.9168413Z remote: Counting objects: 28% (3519/12567) +2022-11-01T15:23:06.9168685Z remote: Counting objects: 29% (3645/12567) +2022-11-01T15:23:06.9169293Z remote: Counting objects: 30% (3771/12567) +2022-11-01T15:23:06.9169550Z remote: Counting objects: 31% (3896/12567) +2022-11-01T15:23:06.9169791Z remote: Counting objects: 32% (4022/12567) +2022-11-01T15:23:06.9170049Z remote: Counting objects: 33% (4148/12567) +2022-11-01T15:23:06.9170305Z remote: Counting objects: 34% (4273/12567) +2022-11-01T15:23:06.9170563Z remote: Counting objects: 35% (4399/12567) +2022-11-01T15:23:06.9170803Z remote: Counting objects: 36% (4525/12567) +2022-11-01T15:23:06.9171062Z remote: Counting objects: 37% (4650/12567) +2022-11-01T15:23:06.9171316Z remote: Counting objects: 38% (4776/12567) +2022-11-01T15:23:06.9171714Z remote: Counting objects: 39% (4902/12567) +2022-11-01T15:23:06.9171963Z remote: Counting objects: 40% (5027/12567) +2022-11-01T15:23:06.9172211Z remote: Counting objects: 41% (5153/12567) +2022-11-01T15:23:06.9172447Z remote: Counting objects: 42% (5279/12567) +2022-11-01T15:23:06.9172868Z remote: Counting objects: 43% (5404/12567) +2022-11-01T15:23:06.9173464Z remote: Counting objects: 44% (5530/12567) +2022-11-01T15:23:06.9173834Z remote: Counting objects: 45% (5656/12567) +2022-11-01T15:23:06.9174083Z remote: Counting objects: 46% (5781/12567) +2022-11-01T15:23:06.9174458Z remote: Counting objects: 47% (5907/12567) +2022-11-01T15:23:06.9174828Z remote: Counting objects: 48% (6033/12567) +2022-11-01T15:23:06.9175193Z remote: Counting objects: 49% (6158/12567) +2022-11-01T15:23:06.9175686Z remote: Counting objects: 50% (6284/12567) +2022-11-01T15:23:06.9176096Z remote: Counting objects: 51% (6410/12567) +2022-11-01T15:23:06.9176806Z remote: Counting objects: 52% (6535/12567) +2022-11-01T15:23:06.9177226Z remote: Counting objects: 53% (6661/12567) +2022-11-01T15:23:06.9383126Z remote: Counting objects: 54% (6787/12567) +2022-11-01T15:23:06.9383471Z remote: Counting objects: 55% (6912/12567) +2022-11-01T15:23:06.9383912Z remote: Counting objects: 56% (7038/12567) +2022-11-01T15:23:06.9384205Z remote: Counting objects: 57% (7164/12567) +2022-11-01T15:23:06.9384882Z remote: Counting objects: 58% (7289/12567) +2022-11-01T15:23:06.9385322Z remote: Counting objects: 59% (7415/12567) +2022-11-01T15:23:06.9385593Z remote: Counting objects: 60% (7541/12567) +2022-11-01T15:23:06.9386047Z remote: Counting objects: 61% (7666/12567) +2022-11-01T15:23:06.9386320Z remote: Counting objects: 62% (7792/12567) +2022-11-01T15:23:06.9386602Z remote: Counting objects: 63% (7918/12567) +2022-11-01T15:23:06.9387066Z remote: Counting objects: 64% (8043/12567) +2022-11-01T15:23:06.9387318Z remote: Counting objects: 65% (8169/12567) +2022-11-01T15:23:06.9387584Z remote: Counting objects: 66% (8295/12567) +2022-11-01T15:23:06.9387858Z remote: Counting objects: 67% (8420/12567) +2022-11-01T15:23:06.9388109Z remote: Counting objects: 68% (8546/12567) +2022-11-01T15:23:06.9388374Z remote: Counting objects: 69% (8672/12567) +2022-11-01T15:23:06.9388777Z remote: Counting objects: 70% (8797/12567) +2022-11-01T15:23:06.9389026Z remote: Counting objects: 71% (8923/12567) +2022-11-01T15:23:06.9389293Z remote: Counting objects: 72% (9049/12567) +2022-11-01T15:23:06.9389558Z remote: Counting objects: 73% (9174/12567) +2022-11-01T15:23:06.9389987Z remote: Counting objects: 74% (9300/12567) +2022-11-01T15:23:06.9390230Z remote: Counting objects: 75% (9426/12567) +2022-11-01T15:23:06.9390484Z remote: Counting objects: 76% (9551/12567) +2022-11-01T15:23:06.9390738Z remote: Counting objects: 77% (9677/12567) +2022-11-01T15:23:06.9390979Z remote: Counting objects: 78% (9803/12567) +2022-11-01T15:23:06.9391235Z remote: Counting objects: 79% (9928/12567) +2022-11-01T15:23:06.9391796Z remote: Counting objects: 80% (10054/12567) +2022-11-01T15:23:06.9392047Z remote: Counting objects: 81% (10180/12567) +2022-11-01T15:23:06.9392314Z remote: Counting objects: 82% (10305/12567) +2022-11-01T15:23:06.9392577Z remote: Counting objects: 83% (10431/12567) +2022-11-01T15:23:06.9392824Z remote: Counting objects: 84% (10557/12567) +2022-11-01T15:23:06.9393085Z remote: Counting objects: 85% (10682/12567) +2022-11-01T15:23:06.9394375Z remote: Counting objects: 86% (10808/12567) +2022-11-01T15:23:06.9394631Z remote: Counting objects: 87% (10934/12567) +2022-11-01T15:23:06.9394877Z remote: Counting objects: 88% (11059/12567) +2022-11-01T15:23:06.9395134Z remote: Counting objects: 89% (11185/12567) +2022-11-01T15:23:06.9395389Z remote: Counting objects: 90% (11311/12567) +2022-11-01T15:23:06.9395622Z remote: Counting objects: 91% (11436/12567) +2022-11-01T15:23:06.9395877Z remote: Counting objects: 92% (11562/12567) +2022-11-01T15:23:06.9396132Z remote: Counting objects: 93% (11688/12567) +2022-11-01T15:23:06.9396564Z remote: Counting objects: 94% (11813/12567) +2022-11-01T15:23:06.9396804Z remote: Counting objects: 95% (11939/12567) +2022-11-01T15:23:06.9397061Z remote: Counting objects: 96% (12065/12567) +2022-11-01T15:23:06.9397319Z remote: Counting objects: 97% (12190/12567) +2022-11-01T15:23:06.9397557Z remote: Counting objects: 98% (12316/12567) +2022-11-01T15:23:06.9397810Z remote: Counting objects: 99% (12442/12567) +2022-11-01T15:23:06.9398208Z remote: Counting objects: 100% (12567/12567) +2022-11-01T15:23:06.9398661Z remote: Counting objects: 100% (12567/12567), done. +2022-11-01T15:23:06.9398965Z remote: Compressing objects: 0% (1/10988) +2022-11-01T15:23:06.9399257Z remote: Compressing objects: 1% (110/10988) +2022-11-01T15:23:06.9439997Z remote: Compressing objects: 2% (220/10988) +2022-11-01T15:23:06.9561627Z remote: Compressing objects: 3% (330/10988) +2022-11-01T15:23:06.9680955Z remote: Compressing objects: 4% (440/10988) +2022-11-01T15:23:06.9723040Z remote: Compressing objects: 5% (550/10988) +2022-11-01T15:23:06.9876931Z remote: Compressing objects: 6% (660/10988) +2022-11-01T15:23:07.0170815Z remote: Compressing objects: 7% (770/10988) +2022-11-01T15:23:07.0504059Z remote: Compressing objects: 8% (880/10988) +2022-11-01T15:23:07.0836116Z remote: Compressing objects: 9% (989/10988) +2022-11-01T15:23:07.1460729Z remote: Compressing objects: 10% (1099/10988) +2022-11-01T15:23:07.6608683Z remote: Compressing objects: 11% (1209/10988) +2022-11-01T15:23:07.7588422Z remote: Compressing objects: 12% (1319/10988) +2022-11-01T15:23:07.9494647Z remote: Compressing objects: 13% (1429/10988) +2022-11-01T15:23:07.9527972Z remote: Compressing objects: 13% (1508/10988) +2022-11-01T15:23:07.9668498Z remote: Compressing objects: 14% (1539/10988) +2022-11-01T15:23:08.0219248Z remote: Compressing objects: 15% (1649/10988) +2022-11-01T15:23:08.0283852Z remote: Compressing objects: 16% (1759/10988) +2022-11-01T15:23:08.0452608Z remote: Compressing objects: 17% (1868/10988) +2022-11-01T15:23:08.0618448Z remote: Compressing objects: 18% (1978/10988) +2022-11-01T15:23:08.0889220Z remote: Compressing objects: 19% (2088/10988) +2022-11-01T15:23:08.1162946Z remote: Compressing objects: 20% (2198/10988) +2022-11-01T15:23:08.1247220Z remote: Compressing objects: 21% (2308/10988) +2022-11-01T15:23:08.1520626Z remote: Compressing objects: 22% (2418/10988) +2022-11-01T15:23:08.2139765Z remote: Compressing objects: 23% (2528/10988) +2022-11-01T15:23:08.2412924Z remote: Compressing objects: 24% (2638/10988) +2022-11-01T15:23:08.2597478Z remote: Compressing objects: 25% (2747/10988) +2022-11-01T15:23:08.2752211Z remote: Compressing objects: 26% (2857/10988) +2022-11-01T15:23:08.2966161Z remote: Compressing objects: 27% (2967/10988) +2022-11-01T15:23:08.3926822Z remote: Compressing objects: 28% (3077/10988) +2022-11-01T15:23:08.3927793Z remote: Compressing objects: 29% (3187/10988) +2022-11-01T15:23:08.4094739Z remote: Compressing objects: 30% (3297/10988) +2022-11-01T15:23:08.4338176Z remote: Compressing objects: 31% (3407/10988) +2022-11-01T15:23:08.4632502Z remote: Compressing objects: 32% (3517/10988) +2022-11-01T15:23:08.4940329Z remote: Compressing objects: 33% (3627/10988) +2022-11-01T15:23:08.5404129Z remote: Compressing objects: 34% (3736/10988) +2022-11-01T15:23:08.5814756Z remote: Compressing objects: 35% (3846/10988) +2022-11-01T15:23:08.6091092Z remote: Compressing objects: 36% (3956/10988) +2022-11-01T15:23:08.6446921Z remote: Compressing objects: 37% (4066/10988) +2022-11-01T15:23:08.6900873Z remote: Compressing objects: 38% (4176/10988) +2022-11-01T15:23:08.7213081Z remote: Compressing objects: 39% (4286/10988) +2022-11-01T15:23:08.7502723Z remote: Compressing objects: 40% (4396/10988) +2022-11-01T15:23:08.7869698Z remote: Compressing objects: 41% (4506/10988) +2022-11-01T15:23:08.8103626Z remote: Compressing objects: 42% (4615/10988) +2022-11-01T15:23:08.8451299Z remote: Compressing objects: 43% (4725/10988) +2022-11-01T15:23:08.8774688Z remote: Compressing objects: 44% (4835/10988) +2022-11-01T15:23:08.9003331Z remote: Compressing objects: 45% (4945/10988) +2022-11-01T15:23:08.9070180Z remote: Compressing objects: 45% (5034/10988) +2022-11-01T15:23:08.9344499Z remote: Compressing objects: 46% (5055/10988) +2022-11-01T15:23:08.9568190Z remote: Compressing objects: 47% (5165/10988) +2022-11-01T15:23:08.9805763Z remote: Compressing objects: 48% (5275/10988) +2022-11-01T15:23:09.0037568Z remote: Compressing objects: 49% (5385/10988) +2022-11-01T15:23:09.0301310Z remote: Compressing objects: 50% (5494/10988) +2022-11-01T15:23:09.0582321Z remote: Compressing objects: 51% (5604/10988) +2022-11-01T15:23:09.0808327Z remote: Compressing objects: 52% (5714/10988) +2022-11-01T15:23:09.1124129Z remote: Compressing objects: 53% (5824/10988) +2022-11-01T15:23:09.1387087Z remote: Compressing objects: 54% (5934/10988) +2022-11-01T15:23:09.1647455Z remote: Compressing objects: 55% (6044/10988) +2022-11-01T15:23:09.1915056Z remote: Compressing objects: 56% (6154/10988) +2022-11-01T15:23:09.2255320Z remote: Compressing objects: 57% (6264/10988) +2022-11-01T15:23:09.2457326Z remote: Compressing objects: 58% (6374/10988) +2022-11-01T15:23:09.2755910Z remote: Compressing objects: 59% (6483/10988) +2022-11-01T15:23:09.3017305Z remote: Compressing objects: 60% (6593/10988) +2022-11-01T15:23:09.3325069Z remote: Compressing objects: 61% (6703/10988) +2022-11-01T15:23:09.3546803Z remote: Compressing objects: 62% (6813/10988) +2022-11-01T15:23:09.3801684Z remote: Compressing objects: 63% (6923/10988) +2022-11-01T15:23:09.4067963Z remote: Compressing objects: 64% (7033/10988) +2022-11-01T15:23:09.5472387Z remote: Compressing objects: 65% (7143/10988) +2022-11-01T15:23:09.5473083Z remote: Compressing objects: 66% (7253/10988) +2022-11-01T15:23:09.5473536Z remote: Compressing objects: 67% (7362/10988) +2022-11-01T15:23:09.5473940Z remote: Compressing objects: 68% (7472/10988) +2022-11-01T15:23:09.5474375Z remote: Compressing objects: 69% (7582/10988) +2022-11-01T15:23:09.5474794Z remote: Compressing objects: 70% (7692/10988) +2022-11-01T15:23:09.5475212Z remote: Compressing objects: 71% (7802/10988) +2022-11-01T15:23:09.5475789Z remote: Compressing objects: 72% (7912/10988) +2022-11-01T15:23:09.5476209Z remote: Compressing objects: 73% (8022/10988) +2022-11-01T15:23:09.5477532Z remote: Compressing objects: 74% (8132/10988) +2022-11-01T15:23:09.5478233Z remote: Compressing objects: 75% (8241/10988) +2022-11-01T15:23:09.5478582Z remote: Compressing objects: 76% (8351/10988) +2022-11-01T15:23:09.5479163Z remote: Compressing objects: 77% (8461/10988) +2022-11-01T15:23:09.5479885Z remote: Compressing objects: 78% (8571/10988) +2022-11-01T15:23:09.5480434Z remote: Compressing objects: 79% (8681/10988) +2022-11-01T15:23:09.5480899Z remote: Compressing objects: 80% (8791/10988) +2022-11-01T15:23:09.5481594Z remote: Compressing objects: 81% (8901/10988) +2022-11-01T15:23:09.5482284Z remote: Compressing objects: 82% (9011/10988) +2022-11-01T15:23:09.5482865Z remote: Compressing objects: 83% (9121/10988) +2022-11-01T15:23:09.5483308Z remote: Compressing objects: 84% (9230/10988) +2022-11-01T15:23:09.5483685Z remote: Compressing objects: 85% (9340/10988) +2022-11-01T15:23:09.5484385Z remote: Compressing objects: 86% (9450/10988) +2022-11-01T15:23:09.5485582Z remote: Compressing objects: 87% (9560/10988) +2022-11-01T15:23:09.5486089Z remote: Compressing objects: 88% (9670/10988) +2022-11-01T15:23:09.5486597Z remote: Compressing objects: 89% (9780/10988) +2022-11-01T15:23:09.5487116Z remote: Compressing objects: 90% (9890/10988) +2022-11-01T15:23:09.5487742Z remote: Compressing objects: 91% (10000/10988) +2022-11-01T15:23:09.5488235Z remote: Compressing objects: 92% (10109/10988) +2022-11-01T15:23:09.5488673Z remote: Compressing objects: 93% (10219/10988) +2022-11-01T15:23:09.5489383Z remote: Compressing objects: 94% (10329/10988) +2022-11-01T15:23:09.5489745Z remote: Compressing objects: 95% (10439/10988) +2022-11-01T15:23:09.5490195Z remote: Compressing objects: 96% (10549/10988) +2022-11-01T15:23:09.5490745Z remote: Compressing objects: 97% (10659/10988) +2022-11-01T15:23:09.5491127Z remote: Compressing objects: 98% (10769/10988) +2022-11-01T15:23:09.5491596Z remote: Compressing objects: 99% (10879/10988) +2022-11-01T15:23:09.5492106Z remote: Compressing objects: 100% (10988/10988) +2022-11-01T15:23:09.5492683Z remote: Compressing objects: 100% (10988/10988), done. 2022-11-01T15:23:09.8456233Z Receiving objects: 0% (1/12567) 2022-11-01T15:23:10.1991946Z Receiving objects: 1% (126/12567) 2022-11-01T15:23:10.2129001Z Receiving objects: 2% (252/12567), 1.64 MiB | 3.13 MiB/s @@ -505,7 +505,7 @@ 2022-11-01T15:23:18.1101897Z Receiving objects: 97% (12190/12567), 131.07 MiB | 18.99 MiB/s 2022-11-01T15:23:18.1271902Z Receiving objects: 98% (12316/12567), 131.07 MiB | 18.99 MiB/s 2022-11-01T15:23:18.1310792Z Receiving objects: 99% (12442/12567), 131.07 MiB | 18.99 MiB/s -2022-11-01T15:23:18.1311930Z remote: Total 12567 (delta 1595), reused 7195 (delta 1446), pack-reused 0 +2022-11-01T15:23:18.1311930Z remote: Total 12567 (delta 1595), reused 7195 (delta 1446), pack-reused 0 2022-11-01T15:23:18.1338739Z Receiving objects: 100% (12567/12567), 131.07 MiB | 18.99 MiB/s 2022-11-01T15:23:18.1339954Z Receiving objects: 100% (12567/12567), 139.23 MiB | 16.22 MiB/s, done. 2022-11-01T15:23:18.1385156Z Resolving deltas: 0% (0/1595) @@ -657,22 +657,22 @@ 2022-11-01T15:23:20.3892548Z Updating files: 100% (11595/11595) 2022-11-01T15:23:20.3892853Z Updating files: 100% (11595/11595), done. 2022-11-01T15:23:20.4056043Z Note: switching to 'refs/remotes/pull/70980/merge'. -2022-11-01T15:23:20.4056307Z +2022-11-01T15:23:20.4056307Z 2022-11-01T15:23:20.4056668Z You are in 'detached HEAD' state. You can look around, make experimental 2022-11-01T15:23:20.4057485Z changes and commit them, and you can discard any commits you make in this 2022-11-01T15:23:20.4058470Z state without impacting any branches by switching back to a branch. -2022-11-01T15:23:20.4058838Z +2022-11-01T15:23:20.4058838Z 2022-11-01T15:23:20.4059084Z If you want to create a new branch to retain commits you create, you may 2022-11-01T15:23:20.4060410Z do so (now or later) by using -c with the switch command. Example: -2022-11-01T15:23:20.4060709Z +2022-11-01T15:23:20.4060709Z 2022-11-01T15:23:20.4061092Z git switch -c -2022-11-01T15:23:20.4061268Z +2022-11-01T15:23:20.4061268Z 2022-11-01T15:23:20.4061433Z Or undo this operation with: -2022-11-01T15:23:20.4061641Z +2022-11-01T15:23:20.4061641Z 2022-11-01T15:23:20.4061781Z git switch - -2022-11-01T15:23:20.4061964Z +2022-11-01T15:23:20.4061964Z 2022-11-01T15:23:20.4062222Z Turn off this advice by setting config variable advice.detachedHead to false -2022-11-01T15:23:20.4062504Z +2022-11-01T15:23:20.4062504Z 2022-11-01T15:23:20.4062736Z HEAD is now at 90d5821 Merge 1cb3ad143b2bd2b6467c31b7f52299c77448f1ee into 6ccb95a4ea337422d5d29cd85f5267e4c867ccff 2022-11-01T15:23:20.4116386Z ##[endgroup] 2022-11-01T15:23:20.4158288Z [command]/usr/bin/git log -1 --format='%H' @@ -707,9 +707,9 @@ 2022-11-01T15:23:29.0146860Z bash tools/ci/install_rust_g.sh 2022-11-01T15:23:29.0208114Z shell: /usr/bin/bash -e {0} 2022-11-01T15:23:29.0208371Z ##[endgroup] -2022-11-01T15:23:29.3467028Z +2022-11-01T15:23:29.3467028Z 2022-11-01T15:23:29.3467957Z WARNING: apt does not have a stable CLI interface. Use with caution in scripts. -2022-11-01T15:23:29.3470221Z +2022-11-01T15:23:29.3470221Z 2022-11-01T15:23:29.4665471Z Hit:1 http://azure.archive.ubuntu.com/ubuntu focal InRelease 2022-11-01T15:23:29.4669512Z Get:2 http://azure.archive.ubuntu.com/ubuntu focal-updates InRelease [114 kB] 2022-11-01T15:23:29.4687773Z Get:3 http://azure.archive.ubuntu.com/ubuntu focal-backports InRelease [108 kB] @@ -735,9 +735,9 @@ 2022-11-01T15:23:48.4655905Z Building dependency tree... 2022-11-01T15:23:48.4674811Z Reading state information... 2022-11-01T15:23:48.6158045Z 30 packages can be upgraded. Run 'apt list --upgradable' to see them. -2022-11-01T15:23:48.6289670Z +2022-11-01T15:23:48.6289670Z 2022-11-01T15:23:48.6290570Z WARNING: apt does not have a stable CLI interface. Use with caution in scripts. -2022-11-01T15:23:48.6290875Z +2022-11-01T15:23:48.6290875Z 2022-11-01T15:23:48.7009344Z Reading package lists... 2022-11-01T15:23:48.9786347Z Building dependency tree... 2022-11-01T15:23:48.9806498Z Reading state information... @@ -765,7 +765,7 @@ 2022-11-01T15:23:51.2386768Z Preconfiguring packages ... 2022-11-01T15:23:51.3495462Z Fetched 4528 kB in 1s (3176 kB/s) 2022-11-01T15:23:51.3919752Z Selecting previously unselected package gcc-11-base:i386. -2022-11-01T15:23:51.4344862Z (Reading database ... +2022-11-01T15:23:51.4344862Z (Reading database ... 2022-11-01T15:23:51.4345195Z (Reading database ... 5% 2022-11-01T15:23:51.4345492Z (Reading database ... 10% 2022-11-01T15:23:51.4346277Z (Reading database ... 15% @@ -852,98 +852,98 @@ 2022-11-01T15:24:20.0904985Z Setting up BYOND. 2022-11-01T15:24:20.1285049Z % Total % Received % Xferd Average Speed Time Time Time Current 2022-11-01T15:24:20.1288558Z Dload Upload Total Spent Left Speed -2022-11-01T15:24:20.1289906Z +2022-11-01T15:24:20.1289906Z 2022-11-01T15:24:20.2648629Z 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 2022-11-01T15:24:20.2651476Z 100 4021k 100 4021k 0 0 28.8M 0 --:--:-- --:--:-- --:--:-- 28.8M 2022-11-01T15:24:20.2868719Z Archive: byond.zip 2022-11-01T15:24:20.2869523Z creating: byond/ 2022-11-01T15:24:20.2872392Z creating: byond/key/ 2022-11-01T15:24:20.2872809Z creating: byond/web/ -2022-11-01T15:24:20.2873278Z inflating: byond/web/child.dms -2022-11-01T15:24:20.2873868Z inflating: byond/web/button.dms -2022-11-01T15:24:20.2874291Z inflating: byond/web/input.dms -2022-11-01T15:24:20.2874708Z inflating: byond/web/text.dms -2022-11-01T15:24:20.2990682Z inflating: byond/web/webclient.dart.js -2022-11-01T15:24:20.2991338Z inflating: byond/web/verbmenu.dms -2022-11-01T15:24:20.2992247Z inflating: byond/web/defaultSkin.dms -2022-11-01T15:24:20.2994907Z inflating: byond/web/hotbar.dms -2022-11-01T15:24:20.2995370Z inflating: byond/web/label.dms -2022-11-01T15:24:20.2997432Z inflating: byond/web/alert.dms -2022-11-01T15:24:20.3045767Z inflating: byond/web/message.dms -2022-11-01T15:24:20.3046084Z inflating: byond/web/drag.png -2022-11-01T15:24:20.3046357Z inflating: byond/web/map.dms -2022-11-01T15:24:20.3046639Z inflating: byond/web/splashlogo.png -2022-11-01T15:24:20.3046920Z inflating: byond/web/drop.png -2022-11-01T15:24:20.3109752Z inflating: byond/web/ext.js -2022-11-01T15:24:20.3110039Z inflating: byond/web/file.dms -2022-11-01T15:24:20.3110743Z inflating: byond/web/grid.dms -2022-11-01T15:24:20.3112568Z inflating: byond/web/bar.dms -2022-11-01T15:24:20.3116279Z inflating: byond/web/dpad.dms -2022-11-01T15:24:20.3117768Z inflating: byond/web/output.dms -2022-11-01T15:24:20.3118380Z inflating: byond/web/tab.dms -2022-11-01T15:24:20.3121184Z inflating: byond/web/info.dms -2022-11-01T15:24:20.3125342Z inflating: byond/web/color.dms -2022-11-01T15:24:20.3127736Z inflating: byond/web/gamepad.dms -2022-11-01T15:24:20.3129918Z inflating: byond/web/browser.dms -2022-11-01T15:24:20.3130867Z inflating: byond/web/status.dms -2022-11-01T15:24:20.3131904Z inflating: byond/web/any.dms -2022-11-01T15:24:20.3133198Z inflating: byond/web/pane.dms -2022-11-01T15:24:20.3134980Z inflating: byond/web/pop.dms -2022-11-01T15:24:20.3136094Z inflating: byond/license.txt -2022-11-01T15:24:20.3136925Z inflating: byond/legal.txt -2022-11-01T15:24:20.3138018Z inflating: byond/Makefile +2022-11-01T15:24:20.2873278Z inflating: byond/web/child.dms +2022-11-01T15:24:20.2873868Z inflating: byond/web/button.dms +2022-11-01T15:24:20.2874291Z inflating: byond/web/input.dms +2022-11-01T15:24:20.2874708Z inflating: byond/web/text.dms +2022-11-01T15:24:20.2990682Z inflating: byond/web/webclient.dart.js +2022-11-01T15:24:20.2991338Z inflating: byond/web/verbmenu.dms +2022-11-01T15:24:20.2992247Z inflating: byond/web/defaultSkin.dms +2022-11-01T15:24:20.2994907Z inflating: byond/web/hotbar.dms +2022-11-01T15:24:20.2995370Z inflating: byond/web/label.dms +2022-11-01T15:24:20.2997432Z inflating: byond/web/alert.dms +2022-11-01T15:24:20.3045767Z inflating: byond/web/message.dms +2022-11-01T15:24:20.3046084Z inflating: byond/web/drag.png +2022-11-01T15:24:20.3046357Z inflating: byond/web/map.dms +2022-11-01T15:24:20.3046639Z inflating: byond/web/splashlogo.png +2022-11-01T15:24:20.3046920Z inflating: byond/web/drop.png +2022-11-01T15:24:20.3109752Z inflating: byond/web/ext.js +2022-11-01T15:24:20.3110039Z inflating: byond/web/file.dms +2022-11-01T15:24:20.3110743Z inflating: byond/web/grid.dms +2022-11-01T15:24:20.3112568Z inflating: byond/web/bar.dms +2022-11-01T15:24:20.3116279Z inflating: byond/web/dpad.dms +2022-11-01T15:24:20.3117768Z inflating: byond/web/output.dms +2022-11-01T15:24:20.3118380Z inflating: byond/web/tab.dms +2022-11-01T15:24:20.3121184Z inflating: byond/web/info.dms +2022-11-01T15:24:20.3125342Z inflating: byond/web/color.dms +2022-11-01T15:24:20.3127736Z inflating: byond/web/gamepad.dms +2022-11-01T15:24:20.3129918Z inflating: byond/web/browser.dms +2022-11-01T15:24:20.3130867Z inflating: byond/web/status.dms +2022-11-01T15:24:20.3131904Z inflating: byond/web/any.dms +2022-11-01T15:24:20.3133198Z inflating: byond/web/pane.dms +2022-11-01T15:24:20.3134980Z inflating: byond/web/pop.dms +2022-11-01T15:24:20.3136094Z inflating: byond/license.txt +2022-11-01T15:24:20.3136925Z inflating: byond/legal.txt +2022-11-01T15:24:20.3138018Z inflating: byond/Makefile 2022-11-01T15:24:20.3138748Z creating: byond/man/ 2022-11-01T15:24:20.3140374Z creating: byond/man/man6/ -2022-11-01T15:24:20.3140865Z inflating: byond/man/man6/DreamDaemon.6 -2022-11-01T15:24:20.3142127Z inflating: byond/man/man6/DreamMaker.6 +2022-11-01T15:24:20.3140865Z inflating: byond/man/man6/DreamDaemon.6 +2022-11-01T15:24:20.3142127Z inflating: byond/man/man6/DreamMaker.6 2022-11-01T15:24:20.3149532Z creating: byond/lib/ 2022-11-01T15:24:20.3149763Z creating: byond/host/ -2022-11-01T15:24:20.3150009Z inflating: byond/host/readme.html -2022-11-01T15:24:20.3150561Z inflating: byond/host/readme-unix.txt +2022-11-01T15:24:20.3150009Z inflating: byond/host/readme.html +2022-11-01T15:24:20.3150561Z inflating: byond/host/readme-unix.txt 2022-11-01T15:24:20.3150816Z creating: byond/host/home/ 2022-11-01T15:24:20.3151052Z creating: byond/host/home/root/ 2022-11-01T15:24:20.3151304Z creating: byond/host/home/root/byond/ 2022-11-01T15:24:20.3151781Z creating: byond/host/home/root/byond/tools/ 2022-11-01T15:24:20.3152089Z creating: byond/host/home/root/byond/tools/root/ -2022-11-01T15:24:20.3153050Z inflating: byond/host/home/root/byond/tools/root/root.dmb +2022-11-01T15:24:20.3153050Z inflating: byond/host/home/root/byond/tools/root/root.dmb 2022-11-01T15:24:20.3154330Z creating: byond/host/shared/ 2022-11-01T15:24:20.3155440Z creating: byond/host/shared/byond/ 2022-11-01T15:24:20.3156763Z creating: byond/host/shared/byond/tools/ 2022-11-01T15:24:20.3157942Z creating: byond/host/shared/byond/tools/ftp/ -2022-11-01T15:24:20.3159544Z inflating: byond/host/shared/byond/tools/ftp/ftp.dmb +2022-11-01T15:24:20.3159544Z inflating: byond/host/shared/byond/tools/ftp/ftp.dmb 2022-11-01T15:24:20.3159981Z creating: byond/host/shared/byond/tools/admin/ -2022-11-01T15:24:20.3172339Z inflating: byond/host/shared/byond/tools/admin/admin.dmb +2022-11-01T15:24:20.3172339Z inflating: byond/host/shared/byond/tools/admin/admin.dmb 2022-11-01T15:24:20.3172798Z creating: byond/host/shared-web/ 2022-11-01T15:24:20.3173421Z creating: byond/host/shared-web/web/ 2022-11-01T15:24:20.3173784Z creating: byond/host/shared-web/web/tools/ 2022-11-01T15:24:20.3174165Z creating: byond/host/shared-web/web/tools/admin/ -2022-11-01T15:24:20.3176681Z inflating: byond/host/shared-web/web/tools/admin/index.dmb -2022-11-01T15:24:20.3186829Z inflating: byond/host/host.dmb -2022-11-01T15:24:20.3187123Z inflating: byond/host/host.start -2022-11-01T15:24:20.3188445Z inflating: byond/host/hostconf.orig -2022-11-01T15:24:20.3189903Z inflating: byond/host/hostconf.txt -2022-11-01T15:24:20.3191949Z inflating: byond/readme.txt +2022-11-01T15:24:20.3176681Z inflating: byond/host/shared-web/web/tools/admin/index.dmb +2022-11-01T15:24:20.3186829Z inflating: byond/host/host.dmb +2022-11-01T15:24:20.3187123Z inflating: byond/host/host.start +2022-11-01T15:24:20.3188445Z inflating: byond/host/hostconf.orig +2022-11-01T15:24:20.3189903Z inflating: byond/host/hostconf.txt +2022-11-01T15:24:20.3191949Z inflating: byond/readme.txt 2022-11-01T15:24:20.3192209Z creating: byond/bin/ -2022-11-01T15:24:20.3193769Z inflating: byond/bin/byondexec -2022-11-01T15:24:20.3195439Z inflating: byond/bin/DreamDownload -2022-11-01T15:24:20.3908232Z inflating: byond/bin/libbyond.so -2022-11-01T15:24:20.4069319Z inflating: byond/bin/libext.so -2022-11-01T15:24:20.4073220Z inflating: byond/bin/DreamDaemon -2022-11-01T15:24:20.4080176Z inflating: byond/bin/DreamMaker +2022-11-01T15:24:20.3193769Z inflating: byond/bin/byondexec +2022-11-01T15:24:20.3195439Z inflating: byond/bin/DreamDownload +2022-11-01T15:24:20.3908232Z inflating: byond/bin/libbyond.so +2022-11-01T15:24:20.4069319Z inflating: byond/bin/libext.so +2022-11-01T15:24:20.4073220Z inflating: byond/bin/DreamDaemon +2022-11-01T15:24:20.4080176Z inflating: byond/bin/DreamMaker 2022-11-01T15:24:20.4080431Z creating: byond/cfg/ -2022-11-01T15:24:20.4080676Z inflating: byond/cfg/release.txt +2022-11-01T15:24:20.4080676Z inflating: byond/cfg/release.txt 2022-11-01T15:24:20.4266638Z *************************** 2022-11-01T15:24:20.4273089Z Now run the following command: -2022-11-01T15:24:20.4285743Z +2022-11-01T15:24:20.4285743Z 2022-11-01T15:24:20.4296269Z source /home/runner/BYOND/byond/bin/byondsetup -2022-11-01T15:24:20.4307061Z +2022-11-01T15:24:20.4307061Z 2022-11-01T15:24:20.4314771Z If it generates errors, your shell is not compatible with 'sh', so you will 2022-11-01T15:24:20.4321421Z have to edit byondsetup and make it work with your shell. If the script works, you should be able to run DreamDaemon. -2022-11-01T15:24:20.4332109Z +2022-11-01T15:24:20.4332109Z 2022-11-01T15:24:20.4340024Z IMPORTANT: once you have the script working, you must add the above line 2022-11-01T15:24:20.4346843Z to your startup script. The name of your startup script depends on the 2022-11-01T15:24:20.4352983Z shell you use. Typical ones are .profile or .bash_profile. -2022-11-01T15:24:20.4363091Z +2022-11-01T15:24:20.4363091Z 2022-11-01T15:24:20.4371649Z Once everything is working, you can find out more about the software 2022-11-01T15:24:20.4381742Z by doing 'man DreamDaemon'. A host server has also been included 2022-11-01T15:24:20.4389897Z so edit host/hostconf.txt and boot up your world server! @@ -973,7 +973,7 @@ 2022-11-01T15:25:42.0446892Z Welcome BYOND! (5.0 Public Version 514.1588) 2022-11-01T15:26:04.0921674Z 865 global variables 2022-11-01T15:26:04.9224562Z World loaded at 15:26:04! -2022-11-01T15:26:04.9749013Z Running /tg/ revision: +2022-11-01T15:26:04.9749013Z Running /tg/ revision: 2022-11-01T15:26:04.9749563Z No commit information 2022-11-01T15:26:04.9837092Z Loading config file config.txt... 2022-11-01T15:26:04.9841145Z Loading config file maps.txt... @@ -1054,252 +1054,252 @@ 2022-11-01T15:28:07.7750369Z Initializations complete within 121.7 seconds! 2022-11-01T15:28:07.7824332Z Game start took 0s 2022-11-01T15:28:18.9688166Z ##[group]/datum/unit_test/log_mapping -2022-11-01T15:28:18.9688840Z +2022-11-01T15:28:18.9688840Z 2022-11-01T15:28:18.9691942Z PASS /datum/unit_test/log_mapping 0s 2022-11-01T15:28:18.9692629Z ##[endgroup] 2022-11-01T15:28:19.0858950Z ##[group]/datum/unit_test/ablative_hood_hud -2022-11-01T15:28:19.1163124Z +2022-11-01T15:28:19.1163124Z 2022-11-01T15:28:19.1164826Z PASS /datum/unit_test/ablative_hood_hud 0.1s 2022-11-01T15:28:19.1165814Z ##[endgroup] 2022-11-01T15:28:19.1391399Z ##[group]/datum/unit_test/ablative_hood_hud_with_helmet -2022-11-01T15:28:19.1679738Z +2022-11-01T15:28:19.1679738Z 2022-11-01T15:28:19.1680798Z PASS /datum/unit_test/ablative_hood_hud_with_helmet 0s 2022-11-01T15:28:19.1684214Z ##[endgroup] 2022-11-01T15:28:19.1915312Z ##[group]/datum/unit_test/achievements -2022-11-01T15:28:19.2020908Z +2022-11-01T15:28:19.2020908Z 2022-11-01T15:28:19.2021795Z PASS /datum/unit_test/achievements 0.1s 2022-11-01T15:28:19.2022783Z ##[endgroup] 2022-11-01T15:28:19.2454845Z ##[group]/datum/unit_test/anchored_mobs -2022-11-01T15:28:19.2456383Z +2022-11-01T15:28:19.2456383Z 2022-11-01T15:28:19.2457685Z PASS /datum/unit_test/anchored_mobs 0s 2022-11-01T15:28:19.2458601Z ##[endgroup] 2022-11-01T15:28:19.2632595Z ##[group]/datum/unit_test/anonymous_themes -2022-11-01T15:28:19.4123645Z +2022-11-01T15:28:19.4123645Z 2022-11-01T15:28:19.4125365Z PASS /datum/unit_test/anonymous_themes 0.2s 2022-11-01T15:28:19.4128592Z ##[endgroup] 2022-11-01T15:28:19.6372545Z ##[group]/datum/unit_test/autowiki -2022-11-01T15:28:21.1559221Z +2022-11-01T15:28:21.1559221Z 2022-11-01T15:28:21.1560055Z PASS /datum/unit_test/autowiki 1.5s 2022-11-01T15:28:21.1560742Z ##[endgroup] 2022-11-01T15:28:22.6418059Z ##[group]/datum/unit_test/autowiki_include_template -2022-11-01T15:28:22.6418298Z +2022-11-01T15:28:22.6418298Z 2022-11-01T15:28:22.6419112Z PASS /datum/unit_test/autowiki_include_template 0s 2022-11-01T15:28:22.6419629Z ##[endgroup] 2022-11-01T15:28:22.6592281Z ##[group]/datum/unit_test/barsigns_icon -2022-11-01T15:28:22.6850472Z +2022-11-01T15:28:22.6850472Z 2022-11-01T15:28:22.6851042Z PASS /datum/unit_test/barsigns_icon 0s 2022-11-01T15:28:22.6851783Z ##[endgroup] 2022-11-01T15:28:22.7025607Z ##[group]/datum/unit_test/barsigns_name -2022-11-01T15:28:22.7025827Z +2022-11-01T15:28:22.7025827Z 2022-11-01T15:28:22.7026411Z PASS /datum/unit_test/barsigns_name 0s 2022-11-01T15:28:22.7026869Z ##[endgroup] 2022-11-01T15:28:22.7196300Z ##[group]/datum/unit_test/bespoke_id -2022-11-01T15:28:22.7196495Z +2022-11-01T15:28:22.7196495Z 2022-11-01T15:28:22.7196933Z PASS /datum/unit_test/bespoke_id 0s 2022-11-01T15:28:22.7197373Z ##[endgroup] 2022-11-01T15:28:22.7528217Z ##[group]/datum/unit_test/binary_insert -2022-11-01T15:28:22.7528455Z +2022-11-01T15:28:22.7528455Z 2022-11-01T15:28:22.7528943Z PASS /datum/unit_test/binary_insert 0s 2022-11-01T15:28:22.7529444Z ##[endgroup] 2022-11-01T15:28:22.7720960Z ##[group]/datum/unit_test/bloody_footprints -2022-11-01T15:28:22.8157307Z +2022-11-01T15:28:22.8157307Z 2022-11-01T15:28:22.8158188Z PASS /datum/unit_test/bloody_footprints 0.1s 2022-11-01T15:28:22.8158909Z ##[endgroup] 2022-11-01T15:28:22.9653160Z ##[group]/datum/unit_test/breath_sanity -2022-11-01T15:28:23.0154449Z +2022-11-01T15:28:23.0154449Z 2022-11-01T15:28:23.0155311Z PASS /datum/unit_test/breath_sanity 0.1s 2022-11-01T15:28:23.0155975Z ##[endgroup] 2022-11-01T15:28:23.0421572Z ##[group]/datum/unit_test/breath_sanity_plasmamen -2022-11-01T15:28:23.0966156Z +2022-11-01T15:28:23.0966156Z 2022-11-01T15:28:23.0966990Z PASS /datum/unit_test/breath_sanity_plasmamen 0s 2022-11-01T15:28:23.0967848Z ##[endgroup] 2022-11-01T15:28:23.1238973Z ##[group]/datum/unit_test/breath_sanity_ashwalker -2022-11-01T15:28:23.1864867Z +2022-11-01T15:28:23.1864867Z 2022-11-01T15:28:23.1865526Z PASS /datum/unit_test/breath_sanity_ashwalker 0s 2022-11-01T15:28:23.1866107Z ##[endgroup] 2022-11-01T15:28:23.2143094Z ##[group]/datum/unit_test/cable_powernets -2022-11-01T15:28:23.2143293Z +2022-11-01T15:28:23.2143293Z 2022-11-01T15:28:23.2143753Z PASS /datum/unit_test/cable_powernets 0s 2022-11-01T15:28:23.2144353Z ##[endgroup] 2022-11-01T15:28:23.2296359Z ##[group]/datum/unit_test/card_mismatch -2022-11-01T15:28:23.2339244Z +2022-11-01T15:28:23.2339244Z 2022-11-01T15:28:23.2339785Z PASS /datum/unit_test/card_mismatch 0s 2022-11-01T15:28:23.2340711Z ##[endgroup] 2022-11-01T15:28:23.3389441Z ##[group]/datum/unit_test/chain_pull_through_space -2022-11-01T15:28:23.3417372Z +2022-11-01T15:28:23.3417372Z 2022-11-01T15:28:23.3428322Z PASS /datum/unit_test/chain_pull_through_space 0s 2022-11-01T15:28:23.3429414Z ##[endgroup] 2022-11-01T15:28:23.4797614Z ##[group]/datum/unit_test/chat_filter_sanity -2022-11-01T15:28:23.4802389Z +2022-11-01T15:28:23.4802389Z 2022-11-01T15:28:23.4803303Z PASS /datum/unit_test/chat_filter_sanity 0s 2022-11-01T15:28:23.4803804Z ##[endgroup] 2022-11-01T15:28:23.4985708Z ##[group]/datum/unit_test/circuit_component_category -2022-11-01T15:28:23.4985973Z +2022-11-01T15:28:23.4985973Z 2022-11-01T15:28:23.4986498Z PASS /datum/unit_test/circuit_component_category 0s 2022-11-01T15:28:23.4987054Z ##[endgroup] 2022-11-01T15:28:23.5170927Z ##[group]/datum/unit_test/closets -2022-11-01T15:28:25.4385541Z +2022-11-01T15:28:25.4385541Z 2022-11-01T15:28:25.4386681Z PASS /datum/unit_test/closets 1.9s 2022-11-01T15:28:25.4387368Z ##[endgroup] 2022-11-01T15:28:28.6598884Z ##[group]/datum/unit_test/harm_punch -2022-11-01T15:28:28.7131885Z +2022-11-01T15:28:28.7131885Z 2022-11-01T15:28:28.7132943Z PASS /datum/unit_test/harm_punch 0.1s 2022-11-01T15:28:28.7134837Z ##[endgroup] 2022-11-01T15:28:28.7421766Z ##[group]/datum/unit_test/harm_melee -2022-11-01T15:28:28.7933680Z +2022-11-01T15:28:28.7933680Z 2022-11-01T15:28:28.7934808Z PASS /datum/unit_test/harm_melee 0s 2022-11-01T15:28:28.7935540Z ##[endgroup] 2022-11-01T15:28:28.8380921Z ##[group]/datum/unit_test/harm_different_damage -2022-11-01T15:28:28.8975633Z +2022-11-01T15:28:28.8975633Z 2022-11-01T15:28:28.8976869Z PASS /datum/unit_test/harm_different_damage 0s 2022-11-01T15:28:28.8977671Z ##[endgroup] 2022-11-01T15:28:28.9761803Z ##[group]/datum/unit_test/attack_chain -2022-11-01T15:28:29.0318227Z +2022-11-01T15:28:29.0318227Z 2022-11-01T15:28:29.0319454Z PASS /datum/unit_test/attack_chain 0.1s 2022-11-01T15:28:29.0320200Z ##[endgroup] 2022-11-01T15:28:29.0662718Z ##[group]/datum/unit_test/disarm -2022-11-01T15:28:29.1273517Z +2022-11-01T15:28:29.1273517Z 2022-11-01T15:28:29.1275850Z PASS /datum/unit_test/disarm 0.1s 2022-11-01T15:28:29.1276795Z ##[endgroup] 2022-11-01T15:28:29.1606515Z ##[group]/datum/unit_test/component_duping -2022-11-01T15:28:29.1606753Z +2022-11-01T15:28:29.1606753Z 2022-11-01T15:28:29.1607266Z PASS /datum/unit_test/component_duping 0s 2022-11-01T15:28:29.1607745Z ##[endgroup] 2022-11-01T15:28:29.1774627Z ##[group]/datum/unit_test/confusion_symptom -2022-11-01T15:28:29.2032018Z +2022-11-01T15:28:29.2032018Z 2022-11-01T15:28:29.2033145Z PASS /datum/unit_test/confusion_symptom 0.1s 2022-11-01T15:28:29.2033987Z ##[endgroup] 2022-11-01T15:28:29.2246157Z ##[group]/datum/unit_test/connect_loc_basic -2022-11-01T15:28:29.2248367Z +2022-11-01T15:28:29.2248367Z 2022-11-01T15:28:29.2249487Z PASS /datum/unit_test/connect_loc_basic 0s 2022-11-01T15:28:29.2250109Z ##[endgroup] 2022-11-01T15:28:29.2416396Z ##[group]/datum/unit_test/connect_loc_change_turf -2022-11-01T15:28:29.2424538Z +2022-11-01T15:28:29.2424538Z 2022-11-01T15:28:29.2425333Z PASS /datum/unit_test/connect_loc_change_turf 0s 2022-11-01T15:28:29.2425972Z ##[endgroup] 2022-11-01T15:28:29.2592394Z ##[group]/datum/unit_test/connect_loc_multiple_on_turf -2022-11-01T15:28:29.2599395Z +2022-11-01T15:28:29.2599395Z 2022-11-01T15:28:29.2599862Z PASS /datum/unit_test/connect_loc_multiple_on_turf 0s 2022-11-01T15:28:29.2600716Z ##[endgroup] 2022-11-01T15:28:29.2917858Z ##[group]/datum/unit_test/crayon_naming -2022-11-01T15:28:29.2996631Z +2022-11-01T15:28:29.2996631Z 2022-11-01T15:28:29.2997310Z PASS /datum/unit_test/crayon_naming 0s 2022-11-01T15:28:29.2997930Z ##[endgroup] 2022-11-01T15:28:29.3177352Z ##[group]/datum/unit_test/dcs_get_id_from_arguments -2022-11-01T15:28:29.3178559Z +2022-11-01T15:28:29.3178559Z 2022-11-01T15:28:29.3182903Z PASS /datum/unit_test/dcs_get_id_from_arguments 0s 2022-11-01T15:28:29.3183682Z ##[endgroup] 2022-11-01T15:28:29.3371899Z ##[group]/datum/unit_test/designs -2022-11-01T15:28:29.3438160Z +2022-11-01T15:28:29.3438160Z 2022-11-01T15:28:29.3438713Z PASS /datum/unit_test/designs 0s 2022-11-01T15:28:29.3439280Z ##[endgroup] 2022-11-01T15:28:29.3630774Z ##[group]/datum/unit_test/dummy_spawn_species -2022-11-01T15:28:29.7865710Z +2022-11-01T15:28:29.7865710Z 2022-11-01T15:28:29.7866984Z PASS /datum/unit_test/dummy_spawn_species 0.4s 2022-11-01T15:28:29.7868408Z ##[endgroup] 2022-11-01T15:28:30.2064941Z ##[group]/datum/unit_test/dummy_spawn_outfit 2022-11-01T15:28:30.2287943Z Job type /datum/job/ai could not be retrieved from SSjob -2022-11-01T15:28:30.5729399Z +2022-11-01T15:28:30.5729399Z 2022-11-01T15:28:30.5730637Z PASS /datum/unit_test/dummy_spawn_outfit 0.3s 2022-11-01T15:28:30.5731452Z ##[endgroup] 2022-11-01T15:28:30.8929561Z ##[group]/datum/unit_test/dynamic_roundstart_ruleset_sanity -2022-11-01T15:28:30.8930214Z +2022-11-01T15:28:30.8930214Z 2022-11-01T15:28:30.8933249Z PASS /datum/unit_test/dynamic_roundstart_ruleset_sanity 0s 2022-11-01T15:28:30.8933929Z ##[endgroup] 2022-11-01T15:28:30.9093619Z ##[group]/datum/unit_test/dynamic_unique_antag_flags -2022-11-01T15:28:30.9094243Z +2022-11-01T15:28:30.9094243Z 2022-11-01T15:28:30.9097412Z PASS /datum/unit_test/dynamic_unique_antag_flags 0s 2022-11-01T15:28:30.9098086Z ##[endgroup] 2022-11-01T15:28:30.9259102Z ##[group]/datum/unit_test/egg_glands -2022-11-01T15:28:30.9738261Z +2022-11-01T15:28:30.9738261Z 2022-11-01T15:28:30.9739529Z PASS /datum/unit_test/egg_glands 0s 2022-11-01T15:28:30.9742814Z ##[endgroup] 2022-11-01T15:28:30.9910488Z ##[group]/datum/unit_test/emoting -2022-11-01T15:28:31.0191020Z +2022-11-01T15:28:31.0191020Z 2022-11-01T15:28:31.0192873Z PASS /datum/unit_test/emoting 0.1s 2022-11-01T15:28:31.0196009Z ##[endgroup] 2022-11-01T15:28:31.0470998Z ##[group]/datum/unit_test/food_edibility_check -2022-11-01T15:28:32.3907505Z +2022-11-01T15:28:32.3907505Z 2022-11-01T15:28:32.3908587Z PASS /datum/unit_test/food_edibility_check 1.3s 2022-11-01T15:28:32.3909262Z ##[endgroup] 2022-11-01T15:28:33.7158865Z ##[group]/datum/unit_test/atmospheric_gas_transfer -2022-11-01T15:28:33.7169071Z +2022-11-01T15:28:33.7169071Z 2022-11-01T15:28:33.7171453Z PASS /datum/unit_test/atmospheric_gas_transfer 0s 2022-11-01T15:28:33.7173553Z ##[endgroup] 2022-11-01T15:28:33.7346695Z ##[group]/datum/unit_test/get_turf_pixel -2022-11-01T15:28:33.7367134Z +2022-11-01T15:28:33.7367134Z 2022-11-01T15:28:33.7368982Z PASS /datum/unit_test/get_turf_pixel 0s 2022-11-01T15:28:33.7371248Z ##[endgroup] 2022-11-01T15:28:33.7556559Z ##[group]/datum/unit_test/greyscale_item_icon_states -2022-11-01T15:28:33.7624830Z +2022-11-01T15:28:33.7624830Z 2022-11-01T15:28:33.7626511Z PASS /datum/unit_test/greyscale_item_icon_states 0s 2022-11-01T15:28:33.7628685Z ##[endgroup] 2022-11-01T15:28:33.7811590Z ##[group]/datum/unit_test/greyscale_color_count -2022-11-01T15:28:33.7978824Z +2022-11-01T15:28:33.7978824Z 2022-11-01T15:28:33.7981042Z PASS /datum/unit_test/greyscale_color_count 0s 2022-11-01T15:28:33.7981873Z ##[endgroup] 2022-11-01T15:28:33.8551069Z ##[group]/datum/unit_test/hallucination_icons -2022-11-01T15:28:34.1090174Z +2022-11-01T15:28:34.1090174Z 2022-11-01T15:28:34.1096431Z PASS /datum/unit_test/hallucination_icons 0.3s 2022-11-01T15:28:34.1099789Z ##[endgroup] 2022-11-01T15:28:34.3281283Z ##[group]/datum/unit_test/heretic_knowledge -2022-11-01T15:28:34.3305016Z +2022-11-01T15:28:34.3305016Z 2022-11-01T15:28:34.3306029Z PASS /datum/unit_test/heretic_knowledge 0s 2022-11-01T15:28:34.3306904Z ##[endgroup] 2022-11-01T15:28:34.3483924Z ##[group]/datum/unit_test/heretic_main_paths -2022-11-01T15:28:34.3484902Z +2022-11-01T15:28:34.3484902Z 2022-11-01T15:28:34.3487952Z PASS /datum/unit_test/heretic_main_paths 0s 2022-11-01T15:28:34.3491126Z ##[endgroup] 2022-11-01T15:28:34.3668321Z ##[group]/datum/unit_test/heretic_rituals -2022-11-01T15:28:34.4513883Z +2022-11-01T15:28:34.4513883Z 2022-11-01T15:28:34.4515231Z PASS /datum/unit_test/heretic_rituals 0.1s 2022-11-01T15:28:34.4518615Z ##[endgroup] 2022-11-01T15:28:34.5255676Z ##[group]/datum/unit_test/hanukkah_2123 -2022-11-01T15:28:34.5256380Z +2022-11-01T15:28:34.5256380Z 2022-11-01T15:28:34.5258696Z PASS /datum/unit_test/hanukkah_2123 0s 2022-11-01T15:28:34.5306060Z ##[endgroup] 2022-11-01T15:28:34.5435626Z ##[group]/datum/unit_test/ramadan_2165 -2022-11-01T15:28:34.5435839Z +2022-11-01T15:28:34.5435839Z 2022-11-01T15:28:34.5436316Z PASS /datum/unit_test/ramadan_2165 0s 2022-11-01T15:28:34.5436790Z ##[endgroup] 2022-11-01T15:28:34.5758281Z ##[group]/datum/unit_test/thanksgiving_2020 -2022-11-01T15:28:34.5758510Z +2022-11-01T15:28:34.5758510Z 2022-11-01T15:28:34.5759790Z PASS /datum/unit_test/thanksgiving_2020 0s 2022-11-01T15:28:34.5760323Z ##[endgroup] 2022-11-01T15:28:34.5922636Z ##[group]/datum/unit_test/mother_3683 -2022-11-01T15:28:34.5923203Z +2022-11-01T15:28:34.5923203Z 2022-11-01T15:28:34.5923668Z PASS /datum/unit_test/mother_3683 0s 2022-11-01T15:28:34.5924152Z ##[endgroup] 2022-11-01T15:28:34.6258731Z ##[group]/datum/unit_test/hello_2020 -2022-11-01T15:28:34.6258967Z +2022-11-01T15:28:34.6258967Z 2022-11-01T15:28:34.6259461Z PASS /datum/unit_test/hello_2020 0s 2022-11-01T15:28:34.6260389Z ##[endgroup] 2022-11-01T15:28:34.6425516Z ##[group]/datum/unit_test/new_year_1983 -2022-11-01T15:28:34.6425720Z +2022-11-01T15:28:34.6425720Z 2022-11-01T15:28:34.6426174Z PASS /datum/unit_test/new_year_1983 0s 2022-11-01T15:28:34.6426620Z ##[endgroup] 2022-11-01T15:28:34.6759224Z ##[group]/datum/unit_test/moth_week_2020 -2022-11-01T15:28:34.6792170Z +2022-11-01T15:28:34.6792170Z 2022-11-01T15:28:34.6792723Z PASS /datum/unit_test/moth_week_2020 0s 2022-11-01T15:28:34.6793240Z ##[endgroup] 2022-11-01T15:28:34.6958289Z ##[group]/datum/unit_test/human_through_recycler -2022-11-01T15:28:34.7370291Z +2022-11-01T15:28:34.7370291Z 2022-11-01T15:28:34.7371226Z PASS /datum/unit_test/human_through_recycler 0.1s 2022-11-01T15:28:34.7372112Z ##[endgroup] 2022-11-01T15:28:34.8623820Z ##[group]/datum/unit_test/hydroponics_extractor_storage -2022-11-01T15:28:34.8996006Z +2022-11-01T15:28:34.8996006Z 2022-11-01T15:28:34.8996940Z PASS /datum/unit_test/hydroponics_extractor_storage 0s 2022-11-01T15:28:34.8997589Z ##[endgroup] 2022-11-01T15:28:34.9278188Z ##[group]/datum/unit_test/hydroponics_harvest -2022-11-01T15:28:35.0009791Z +2022-11-01T15:28:35.0009791Z 2022-11-01T15:28:35.0010716Z PASS /datum/unit_test/hydroponics_harvest 0.1s 2022-11-01T15:28:35.0012013Z ##[endgroup] 2022-11-01T15:28:35.0747162Z ##[group]/datum/unit_test/hydroponics_self_mutation -2022-11-01T15:28:35.1406271Z +2022-11-01T15:28:35.1406271Z 2022-11-01T15:28:35.1407332Z PASS /datum/unit_test/hydroponics_self_mutation 0.1s 2022-11-01T15:28:35.1408057Z ##[endgroup] 2022-11-01T15:28:35.2102485Z ##[group]/datum/unit_test/hydroponics_validate_genes -2022-11-01T15:28:35.2762621Z +2022-11-01T15:28:35.2762621Z 2022-11-01T15:28:35.2763561Z PASS /datum/unit_test/hydroponics_validate_genes 0s 2022-11-01T15:28:35.2764288Z ##[endgroup] 2022-11-01T15:28:35.3749912Z ##[group]/datum/unit_test/defined_inhand_icon_states @@ -1420,200 +1420,200 @@ 2022-11-01T15:28:36.6241586Z /obj/item/bonesetter does not have an inhand_icon_state value - Possible matching sprites for "bonesetter" found in: 'icons/mob/inhands/equipment/medical_lefthand.dmi' & 'icons/mob/inhands/equipment/medical_righthand.dmi' 2022-11-01T15:28:36.6242563Z /obj/item/blood_filter does not have an inhand_icon_state value - Possible matching sprites for "bloodfilter" found in: 'icons/mob/inhands/equipment/medical_lefthand.dmi' & 'icons/mob/inhands/equipment/medical_righthand.dmi' 2022-11-01T15:28:36.6243567Z /obj/item/mecha_ammo/flashbang does not have an inhand_icon_state value - Possible matching sprites for "flashbang" found in: 'icons/mob/inhands/equipment/security_righthand.dmi' & 'icons/mob/inhands/equipment/security_lefthand.dmi' -2022-11-01T15:28:36.6243984Z +2022-11-01T15:28:36.6243984Z 2022-11-01T15:28:36.6244251Z PASS /datum/unit_test/defined_inhand_icon_states 1.3s 2022-11-01T15:28:36.6245107Z ##[endgroup] 2022-11-01T15:28:38.3781123Z ##[group]/datum/unit_test/keybinding_init -2022-11-01T15:28:38.3781642Z +2022-11-01T15:28:38.3781642Z 2022-11-01T15:28:38.3782256Z PASS /datum/unit_test/keybinding_init 0s 2022-11-01T15:28:38.3782848Z ##[endgroup] 2022-11-01T15:28:38.3952800Z ##[group]/datum/unit_test/knockoff_component -2022-11-01T15:28:38.4583090Z +2022-11-01T15:28:38.4583090Z 2022-11-01T15:28:38.4584605Z PASS /datum/unit_test/knockoff_component 0.1s 2022-11-01T15:28:38.4585463Z ##[endgroup] 2022-11-01T15:28:38.5388034Z ##[group]/datum/unit_test/limbsanity -2022-11-01T15:28:38.6201426Z +2022-11-01T15:28:38.6201426Z 2022-11-01T15:28:38.6202784Z PASS /datum/unit_test/limbsanity 0.1s 2022-11-01T15:28:38.6203543Z ##[endgroup] 2022-11-01T15:28:38.6375016Z ##[group]/datum/unit_test/load_map_security 2022-11-01T15:28:38.6378905Z map directory not in whitelist: data/load_map_security_temp for map runtimestation -2022-11-01T15:28:38.6380282Z +2022-11-01T15:28:38.6380282Z 2022-11-01T15:28:38.6381773Z PASS /datum/unit_test/load_map_security 0s 2022-11-01T15:28:38.6382439Z ##[endgroup] 2022-11-01T15:28:38.6552883Z ##[group]/datum/unit_test/machine_disassembly -2022-11-01T15:28:38.6594171Z +2022-11-01T15:28:38.6594171Z 2022-11-01T15:28:38.6595097Z PASS /datum/unit_test/machine_disassembly 0s 2022-11-01T15:28:38.6595719Z ##[endgroup] 2022-11-01T15:28:38.6872178Z ##[group]/datum/unit_test/mecha_damage -2022-11-01T15:28:38.7397615Z +2022-11-01T15:28:38.7397615Z 2022-11-01T15:28:38.7398654Z PASS /datum/unit_test/mecha_damage 0.1s 2022-11-01T15:28:38.7399283Z ##[endgroup] 2022-11-01T15:28:38.7754903Z ##[group]/datum/unit_test/test_human_base -2022-11-01T15:28:38.8529341Z +2022-11-01T15:28:38.8529341Z 2022-11-01T15:28:38.8530478Z PASS /datum/unit_test/test_human_base 0.1s 2022-11-01T15:28:38.8531256Z ##[endgroup] 2022-11-01T15:28:38.9752946Z ##[group]/datum/unit_test/test_human_bone -2022-11-01T15:28:39.0547873Z +2022-11-01T15:28:39.0547873Z 2022-11-01T15:28:39.0550271Z PASS /datum/unit_test/test_human_bone 0.1s 2022-11-01T15:28:39.0551284Z ##[endgroup] 2022-11-01T15:28:39.1298729Z ##[group]/datum/unit_test/merge_type -2022-11-01T15:28:39.1300463Z +2022-11-01T15:28:39.1300463Z 2022-11-01T15:28:39.1301413Z PASS /datum/unit_test/merge_type 0s 2022-11-01T15:28:39.1302403Z ##[endgroup] 2022-11-01T15:28:39.1477365Z ##[group]/datum/unit_test/metabolization -2022-11-01T15:28:39.3901954Z +2022-11-01T15:28:39.3901954Z 2022-11-01T15:28:39.3903433Z PASS /datum/unit_test/metabolization 0.2s 2022-11-01T15:28:39.3906497Z ##[endgroup] 2022-11-01T15:28:39.7294447Z ##[group]/datum/unit_test/on_mob_end_metabolize -2022-11-01T15:28:39.7598821Z +2022-11-01T15:28:39.7598821Z 2022-11-01T15:28:39.7600420Z PASS /datum/unit_test/on_mob_end_metabolize 0s 2022-11-01T15:28:39.7649553Z ##[endgroup] 2022-11-01T15:28:39.7835943Z ##[group]/datum/unit_test/addictions -2022-11-01T15:28:39.8761920Z +2022-11-01T15:28:39.8761920Z 2022-11-01T15:28:39.8763025Z PASS /datum/unit_test/addictions 0.1s 2022-11-01T15:28:39.8764090Z ##[endgroup] 2022-11-01T15:28:39.9657360Z ##[group]/datum/unit_test/actions_moved_on_mind_transfer -2022-11-01T15:28:39.9971522Z +2022-11-01T15:28:39.9971522Z 2022-11-01T15:28:39.9972744Z PASS /datum/unit_test/actions_moved_on_mind_transfer 0s 2022-11-01T15:28:39.9974074Z ##[endgroup] 2022-11-01T15:28:40.0547546Z ##[group]/datum/unit_test/mob_faction -2022-11-01T15:28:44.4337194Z +2022-11-01T15:28:44.4337194Z 2022-11-01T15:28:44.4338995Z PASS /datum/unit_test/mob_faction 4.4s 2022-11-01T15:28:44.4343946Z ##[endgroup] 2022-11-01T15:28:50.4570438Z ##[group]/datum/unit_test/mob_spawn -2022-11-01T15:28:50.4788560Z +2022-11-01T15:28:50.4788560Z 2022-11-01T15:28:50.4789841Z PASS /datum/unit_test/mob_spawn 0s 2022-11-01T15:28:50.4791361Z ##[endgroup] 2022-11-01T15:28:50.6427929Z ##[group]/datum/unit_test/modsuit_checks -2022-11-01T15:28:50.8774698Z +2022-11-01T15:28:50.8774698Z 2022-11-01T15:28:50.8776366Z PASS /datum/unit_test/modsuit_checks 0.2s 2022-11-01T15:28:50.8777936Z ##[endgroup] 2022-11-01T15:28:51.1124046Z ##[group]/datum/unit_test/modular_map_loader -2022-11-01T15:28:51.1141260Z +2022-11-01T15:28:51.1141260Z 2022-11-01T15:28:51.1142098Z PASS /datum/unit_test/modular_map_loader 0s 2022-11-01T15:28:51.1142848Z ##[endgroup] 2022-11-01T15:28:51.1326741Z ##[group]/datum/unit_test/mouse_bite_cable -2022-11-01T15:28:51.1380480Z +2022-11-01T15:28:51.1380480Z 2022-11-01T15:28:51.1381073Z PASS /datum/unit_test/mouse_bite_cable 0s 2022-11-01T15:28:51.1381752Z ##[endgroup] 2022-11-01T15:28:51.1577018Z ##[group]/datum/unit_test/novaflower_burn -2022-11-01T15:28:51.2169264Z +2022-11-01T15:28:51.2169264Z 2022-11-01T15:28:51.2170162Z PASS /datum/unit_test/novaflower_burn 0.1s 2022-11-01T15:28:51.2170901Z ##[endgroup] 2022-11-01T15:28:51.2996852Z ##[group]/datum/unit_test/ntnetwork -2022-11-01T15:28:51.3019053Z +2022-11-01T15:28:51.3019053Z 2022-11-01T15:28:51.3019857Z PASS /datum/unit_test/ntnetwork 0.1s 2022-11-01T15:28:51.3020531Z ##[endgroup] 2022-11-01T15:28:51.3196087Z ##[group]/datum/unit_test/nuke_cinematic -2022-11-01T15:28:56.0755977Z +2022-11-01T15:28:56.0755977Z 2022-11-01T15:28:56.0763029Z PASS /datum/unit_test/nuke_cinematic 4.7s 2022-11-01T15:28:56.0764783Z ##[endgroup] 2022-11-01T15:28:56.3446321Z ##[group]/datum/unit_test/objectives_category -2022-11-01T15:28:56.3446835Z +2022-11-01T15:28:56.3446835Z 2022-11-01T15:28:56.3447470Z PASS /datum/unit_test/objectives_category 0s 2022-11-01T15:28:56.3448136Z ##[endgroup] 2022-11-01T15:28:56.3614737Z ##[group]/datum/unit_test/operating_table -2022-11-01T15:28:56.4176620Z +2022-11-01T15:28:56.4176620Z 2022-11-01T15:28:56.4177598Z PASS /datum/unit_test/operating_table 0.1s 2022-11-01T15:28:56.4178689Z ##[endgroup] 2022-11-01T15:28:56.4981266Z ##[group]/datum/unit_test/outfit_sanity -2022-11-01T15:29:06.6657414Z +2022-11-01T15:29:06.6657414Z 2022-11-01T15:29:06.6658439Z PASS /datum/unit_test/outfit_sanity 10.2s 2022-11-01T15:29:06.6659196Z ##[endgroup] 2022-11-01T15:29:16.7908070Z ##[group]/datum/unit_test/paintings -2022-11-01T15:29:16.8212273Z +2022-11-01T15:29:16.8212273Z 2022-11-01T15:29:16.8213346Z PASS /datum/unit_test/paintings 0.1s 2022-11-01T15:29:16.8214069Z ##[endgroup] 2022-11-01T15:29:16.8389425Z ##[group]/datum/unit_test/pills -2022-11-01T15:29:16.8676028Z +2022-11-01T15:29:16.8676028Z 2022-11-01T15:29:16.8677434Z PASS /datum/unit_test/pills 0s 2022-11-01T15:29:16.8678165Z ##[endgroup] 2022-11-01T15:29:16.9417567Z ##[group]/datum/unit_test/plane_double_transform -2022-11-01T15:29:16.9735002Z +2022-11-01T15:29:16.9735002Z 2022-11-01T15:29:16.9735721Z PASS /datum/unit_test/plane_double_transform 0s 2022-11-01T15:29:16.9736359Z ##[endgroup] 2022-11-01T15:29:17.0062562Z ##[group]/datum/unit_test/plane_dupe_detector -2022-11-01T15:29:17.0065142Z +2022-11-01T15:29:17.0065142Z 2022-11-01T15:29:17.0067978Z PASS /datum/unit_test/plane_dupe_detector 0s 2022-11-01T15:29:17.0071640Z ##[endgroup] 2022-11-01T15:29:17.0244509Z ##[group]/datum/unit_test/plantgrowth -2022-11-01T15:29:17.0776528Z +2022-11-01T15:29:17.0776528Z 2022-11-01T15:29:17.0779718Z PASS /datum/unit_test/plantgrowth 0s 2022-11-01T15:29:17.0781279Z ##[endgroup] 2022-11-01T15:29:17.0965505Z ##[group]/datum/unit_test/preference_species -2022-11-01T15:29:17.0966443Z +2022-11-01T15:29:17.0966443Z 2022-11-01T15:29:17.0969864Z PASS /datum/unit_test/preference_species 0s 2022-11-01T15:29:17.0973093Z ##[endgroup] 2022-11-01T15:29:17.1152354Z ##[group]/datum/unit_test/preferences_implement_everything -2022-11-01T15:29:23.4577951Z +2022-11-01T15:29:23.4577951Z 2022-11-01T15:29:23.4578850Z PASS /datum/unit_test/preferences_implement_everything 6.3s 2022-11-01T15:29:23.4579521Z ##[endgroup] 2022-11-01T15:29:29.7830207Z ##[group]/datum/unit_test/preferences_valid_savefile_key -2022-11-01T15:29:29.7830930Z +2022-11-01T15:29:29.7830930Z 2022-11-01T15:29:29.7833510Z PASS /datum/unit_test/preferences_valid_savefile_key 0s 2022-11-01T15:29:29.7834275Z ##[endgroup] 2022-11-01T15:29:29.8033816Z ##[group]/datum/unit_test/preferences_valid_main_feature_name -2022-11-01T15:29:29.8034550Z +2022-11-01T15:29:29.8034550Z 2022-11-01T15:29:29.8035744Z PASS /datum/unit_test/preferences_valid_main_feature_name 0s 2022-11-01T15:29:29.8089387Z ##[endgroup] 2022-11-01T15:29:29.8234720Z ##[group]/datum/unit_test/projectile_movetypes -2022-11-01T15:29:29.8234940Z +2022-11-01T15:29:29.8234940Z 2022-11-01T15:29:29.8235533Z PASS /datum/unit_test/projectile_movetypes 0s 2022-11-01T15:29:29.8236221Z ##[endgroup] 2022-11-01T15:29:29.8415787Z ##[group]/datum/unit_test/gun_go_bang -2022-11-01T15:29:29.9160628Z +2022-11-01T15:29:29.9160628Z 2022-11-01T15:29:29.9161545Z PASS /datum/unit_test/gun_go_bang 0.1s 2022-11-01T15:29:29.9162229Z ##[endgroup] 2022-11-01T15:29:30.0035502Z ##[group]/datum/unit_test/quirk_icons -2022-11-01T15:29:30.0035718Z +2022-11-01T15:29:30.0035718Z 2022-11-01T15:29:30.0036645Z PASS /datum/unit_test/quirk_icons 0s 2022-11-01T15:29:30.0037121Z ##[endgroup] 2022-11-01T15:29:30.0231538Z ##[group]/datum/unit_test/range_return -2022-11-01T15:29:30.0231750Z +2022-11-01T15:29:30.0231750Z 2022-11-01T15:29:30.0232212Z PASS /datum/unit_test/range_return 0s 2022-11-01T15:29:30.0232658Z ##[endgroup] 2022-11-01T15:29:30.0427797Z ##[group]/datum/unit_test/frame_stacking -2022-11-01T15:29:30.1020458Z +2022-11-01T15:29:30.1020458Z 2022-11-01T15:29:30.1021324Z PASS /datum/unit_test/frame_stacking 0.1s 2022-11-01T15:29:30.1022036Z ##[endgroup] 2022-11-01T15:29:30.1824738Z ##[group]/datum/unit_test/reagent_id_typos -2022-11-01T15:29:30.1842378Z +2022-11-01T15:29:30.1842378Z 2022-11-01T15:29:30.1842930Z PASS /datum/unit_test/reagent_id_typos 0s 2022-11-01T15:29:30.1843838Z ##[endgroup] 2022-11-01T15:29:30.2065945Z ##[group]/datum/unit_test/reagent_mob_expose -2022-11-01T15:29:30.2431485Z +2022-11-01T15:29:30.2431485Z 2022-11-01T15:29:30.2432396Z PASS /datum/unit_test/reagent_mob_expose 0s 2022-11-01T15:29:30.2433748Z ##[endgroup] 2022-11-01T15:29:30.2736664Z ##[group]/datum/unit_test/reagent_mob_procs -2022-11-01T15:29:30.3087817Z +2022-11-01T15:29:30.3087817Z 2022-11-01T15:29:30.3088677Z PASS /datum/unit_test/reagent_mob_procs 0.1s 2022-11-01T15:29:30.3089382Z ##[endgroup] 2022-11-01T15:29:30.3347974Z ##[group]/datum/unit_test/reagent_names -2022-11-01T15:29:31.2354819Z +2022-11-01T15:29:31.2354819Z 2022-11-01T15:29:31.2355678Z PASS /datum/unit_test/reagent_names 0.9s 2022-11-01T15:29:31.2356318Z ##[endgroup] 2022-11-01T15:29:32.1042828Z ##[group]/datum/unit_test/reagent_recipe_collisions -2022-11-01T15:29:32.5727294Z +2022-11-01T15:29:32.5727294Z 2022-11-01T15:29:32.5728917Z PASS /datum/unit_test/reagent_recipe_collisions 0.4s 2022-11-01T15:29:32.5730155Z ##[endgroup] 2022-11-01T15:29:32.9927755Z ##[group]/datum/unit_test/reagent_transfer -2022-11-01T15:29:32.9934109Z +2022-11-01T15:29:32.9934109Z 2022-11-01T15:29:32.9935981Z PASS /datum/unit_test/reagent_transfer 0s 2022-11-01T15:29:32.9936895Z ##[endgroup] 2022-11-01T15:29:33.0126783Z ##[group]/datum/unit_test/stop_drop_and_roll -2022-11-01T15:29:33.0390175Z +2022-11-01T15:29:33.0390175Z 2022-11-01T15:29:33.0391562Z PASS /datum/unit_test/stop_drop_and_roll 0s 2022-11-01T15:29:33.0394218Z ##[endgroup] 2022-11-01T15:29:33.0646804Z ##[group]/datum/unit_test/container_resist -2022-11-01T15:29:33.1054797Z +2022-11-01T15:29:33.1054797Z 2022-11-01T15:29:33.1056167Z PASS /datum/unit_test/container_resist 0.1s 2022-11-01T15:29:33.1057687Z ##[endgroup] 2022-11-01T15:29:33.1496944Z ##[group]/datum/unit_test/get_message_mods -2022-11-01T15:29:33.1778888Z +2022-11-01T15:29:33.1778888Z 2022-11-01T15:29:33.1780246Z PASS /datum/unit_test/get_message_mods 0s 2022-11-01T15:29:33.1781311Z ##[endgroup] 2022-11-01T15:29:33.2061026Z ##[group]/datum/unit_test/say_signal -2022-11-01T15:29:33.2078006Z +2022-11-01T15:29:33.2078006Z 2022-11-01T15:29:33.2079823Z PASS /datum/unit_test/say_signal 0s 2022-11-01T15:29:33.2083007Z ##[endgroup] 2022-11-01T15:29:33.2288010Z ##[group]/datum/unit_test/screenshot_antag_icons @@ -1647,12 +1647,12 @@ 2022-11-01T15:29:33.5122130Z screenshot_antag_icons_blobinfection was put in data/screenshots_new 2022-11-01T15:29:33.5146398Z screenshot_antag_icons_obsessed was put in data/screenshots_new 2022-11-01T15:29:33.5153740Z screenshot_antag_icons_malfaimidround was put in data/screenshots_new -2022-11-01T15:29:33.5154025Z +2022-11-01T15:29:33.5154025Z 2022-11-01T15:29:33.5154740Z PASS /datum/unit_test/screenshot_antag_icons 0.3s 2022-11-01T15:29:33.5155554Z ##[endgroup] 2022-11-01T15:29:33.7840161Z ##[group]/datum/unit_test/screenshot_basic 2022-11-01T15:29:33.7846135Z screenshot_basic_red was put in data/screenshots_new -2022-11-01T15:29:33.7850103Z +2022-11-01T15:29:33.7850103Z 2022-11-01T15:29:33.7851242Z PASS /datum/unit_test/screenshot_basic 0s 2022-11-01T15:29:33.7851736Z ##[endgroup] 2022-11-01T15:29:33.8047719Z ##[group]/datum/unit_test/screenshot_humanoids @@ -1709,112 +1709,112 @@ 2022-11-01T15:30:06.7544848Z screenshot_humanoids__datum_species_vampire was put in data/screenshots_new 2022-11-01T15:30:07.6424794Z screenshot_humanoids__datum_species_zombie was put in data/screenshots_new 2022-11-01T15:30:08.5972035Z screenshot_humanoids__datum_species_zombie_infectious was put in data/screenshots_new -2022-11-01T15:30:08.5972336Z +2022-11-01T15:30:08.5972336Z 2022-11-01T15:30:08.5972854Z PASS /datum/unit_test/screenshot_humanoids 34.7s 2022-11-01T15:30:08.5973526Z ##[endgroup] 2022-11-01T15:30:44.2099567Z ##[group]/datum/unit_test/screenshot_saturnx 2022-11-01T15:30:44.5011065Z screenshot_saturnx_invisibility was put in data/screenshots_new -2022-11-01T15:30:44.5011333Z +2022-11-01T15:30:44.5011333Z 2022-11-01T15:30:44.5012180Z PASS /datum/unit_test/screenshot_saturnx 0.3s 2022-11-01T15:30:44.5012769Z ##[endgroup] 2022-11-01T15:30:44.7785909Z ##[group]/datum/unit_test/security_officer_roundstart_distribution -2022-11-01T15:30:44.9017426Z +2022-11-01T15:30:44.9017426Z 2022-11-01T15:30:44.9018614Z PASS /datum/unit_test/security_officer_roundstart_distribution 0.2s 2022-11-01T15:30:44.9019313Z ##[endgroup] 2022-11-01T15:30:45.0427506Z ##[group]/datum/unit_test/security_officer_latejoin_distribution -2022-11-01T15:30:45.5391742Z +2022-11-01T15:30:45.5391742Z 2022-11-01T15:30:45.5392426Z PASS /datum/unit_test/security_officer_latejoin_distribution 0.5s 2022-11-01T15:30:45.5393125Z ##[endgroup] 2022-11-01T15:30:46.2210379Z ##[group]/datum/unit_test/security_levels -2022-11-01T15:30:46.2210589Z +2022-11-01T15:30:46.2210589Z 2022-11-01T15:30:46.2216058Z PASS /datum/unit_test/security_levels 0s 2022-11-01T15:30:46.2216555Z ##[endgroup] 2022-11-01T15:30:46.2399271Z ##[group]/datum/unit_test/servingtray -2022-11-01T15:30:46.2779259Z +2022-11-01T15:30:46.2779259Z 2022-11-01T15:30:46.2780125Z PASS /datum/unit_test/servingtray 0s 2022-11-01T15:30:46.2780972Z ##[endgroup] 2022-11-01T15:30:46.3048093Z ##[group]/datum/unit_test/simple_animal_freeze -2022-11-01T15:30:46.3059709Z +2022-11-01T15:30:46.3059709Z 2022-11-01T15:30:46.3060267Z PASS /datum/unit_test/simple_animal_freeze 0s 2022-11-01T15:30:46.3060938Z ##[endgroup] 2022-11-01T15:30:46.3241320Z ##[group]/datum/unit_test/siunit -2022-11-01T15:30:46.3241508Z +2022-11-01T15:30:46.3241508Z 2022-11-01T15:30:46.3241961Z PASS /datum/unit_test/siunit 0s 2022-11-01T15:30:46.3242362Z ##[endgroup] 2022-11-01T15:30:46.3753674Z ##[group]/datum/unit_test/slips -2022-11-01T15:30:46.4300467Z +2022-11-01T15:30:46.4300467Z 2022-11-01T15:30:46.4301480Z PASS /datum/unit_test/slips 0.1s 2022-11-01T15:30:46.4302301Z ##[endgroup] 2022-11-01T15:30:46.5100922Z ##[group]/datum/unit_test/spawn_humans -2022-11-01T15:30:51.5880046Z +2022-11-01T15:30:51.5880046Z 2022-11-01T15:30:51.5881071Z PASS /datum/unit_test/spawn_humans 5s 2022-11-01T15:30:51.5881789Z ##[endgroup] 2022-11-01T15:30:51.6350612Z ##[group]/datum/unit_test/spawn_mobs -2022-11-01T15:30:51.7210346Z +2022-11-01T15:30:51.7210346Z 2022-11-01T15:30:51.7211375Z PASS /datum/unit_test/spawn_mobs 0.1s 2022-11-01T15:30:51.7212072Z ##[endgroup] 2022-11-01T15:30:51.8820435Z ##[group]/datum/unit_test/species_change_clothing -2022-11-01T15:30:51.9839314Z +2022-11-01T15:30:51.9839314Z 2022-11-01T15:30:51.9840163Z PASS /datum/unit_test/species_change_clothing 0.1s 2022-11-01T15:30:51.9840797Z ##[endgroup] 2022-11-01T15:30:52.0595249Z ##[group]/datum/unit_test/species_change_organs -2022-11-01T15:30:52.1312087Z +2022-11-01T15:30:52.1312087Z 2022-11-01T15:30:52.1313114Z PASS /datum/unit_test/species_change_organs 0.1s 2022-11-01T15:30:52.1313735Z ##[endgroup] 2022-11-01T15:30:52.2788548Z ##[group]/datum/unit_test/species_config_sanity -2022-11-01T15:30:52.2788764Z +2022-11-01T15:30:52.2788764Z 2022-11-01T15:30:52.2789218Z PASS /datum/unit_test/species_config_sanity 0s 2022-11-01T15:30:52.2789672Z ##[endgroup] 2022-11-01T15:30:52.2965591Z ##[group]/datum/unit_test/species_unique_id -2022-11-01T15:30:52.2965794Z +2022-11-01T15:30:52.2965794Z 2022-11-01T15:30:52.2966648Z PASS /datum/unit_test/species_unique_id 0s 2022-11-01T15:30:52.2967087Z ##[endgroup] 2022-11-01T15:30:52.3145296Z ##[group]/datum/unit_test/species_whitelist_check -2022-11-01T15:30:52.3145500Z +2022-11-01T15:30:52.3145500Z 2022-11-01T15:30:52.3145979Z PASS /datum/unit_test/species_whitelist_check 0s 2022-11-01T15:30:52.3146421Z ##[endgroup] 2022-11-01T15:30:52.3319686Z ##[group]/datum/unit_test/spell_invocations -2022-11-01T15:30:52.3320202Z +2022-11-01T15:30:52.3320202Z 2022-11-01T15:30:52.3320653Z PASS /datum/unit_test/spell_invocations 0s 2022-11-01T15:30:52.3321098Z ##[endgroup] 2022-11-01T15:30:52.3490883Z ##[group]/datum/unit_test/mind_swap_spell -2022-11-01T15:30:52.4036851Z +2022-11-01T15:30:52.4036851Z 2022-11-01T15:30:52.4037676Z PASS /datum/unit_test/mind_swap_spell 0.1s 2022-11-01T15:30:52.4038275Z ##[endgroup] 2022-11-01T15:30:52.4828774Z ##[group]/datum/unit_test/spell_names -2022-11-01T15:30:52.4828988Z +2022-11-01T15:30:52.4828988Z 2022-11-01T15:30:52.4829550Z PASS /datum/unit_test/spell_names 0s 2022-11-01T15:30:52.4829982Z ##[endgroup] 2022-11-01T15:30:52.5000265Z ##[group]/datum/unit_test/shapeshift_spell_validity -2022-11-01T15:30:52.5004478Z +2022-11-01T15:30:52.5004478Z 2022-11-01T15:30:52.5005145Z PASS /datum/unit_test/shapeshift_spell_validity 0.1s 2022-11-01T15:30:52.5005621Z ##[endgroup] 2022-11-01T15:30:52.5165907Z ##[group]/datum/unit_test/shapeshift_spell -2022-11-01T15:30:52.8039754Z +2022-11-01T15:30:52.8039754Z 2022-11-01T15:30:52.8040573Z PASS /datum/unit_test/shapeshift_spell 0.3s 2022-11-01T15:30:52.8041200Z ##[endgroup] 2022-11-01T15:30:53.0783548Z ##[group]/datum/unit_test/shapeshift_holoparasites -2022-11-01T15:30:53.1126288Z +2022-11-01T15:30:53.1126288Z 2022-11-01T15:30:53.1127333Z PASS /datum/unit_test/shapeshift_holoparasites 0.1s 2022-11-01T15:30:53.1128391Z ##[endgroup] 2022-11-01T15:30:53.1559214Z ##[group]/datum/unit_test/spritesheets -2022-11-01T15:30:53.1593744Z +2022-11-01T15:30:53.1593744Z 2022-11-01T15:30:53.1596242Z PASS /datum/unit_test/spritesheets 0s 2022-11-01T15:30:53.1599434Z ##[endgroup] 2022-11-01T15:30:53.1775369Z ##[group]/datum/unit_test/stack_singular_name -2022-11-01T15:30:53.1777955Z +2022-11-01T15:30:53.1777955Z 2022-11-01T15:30:53.1780282Z PASS /datum/unit_test/stack_singular_name 0s 2022-11-01T15:30:53.1781032Z ##[endgroup] 2022-11-01T15:30:53.1978111Z ##[group]/datum/unit_test/stomach -2022-11-01T15:30:53.2306019Z +2022-11-01T15:30:53.2306019Z 2022-11-01T15:30:53.2308397Z PASS /datum/unit_test/stomach 0.1s 2022-11-01T15:30:53.2311132Z ##[endgroup] 2022-11-01T15:30:53.2563959Z ##[group]/datum/unit_test/strip_menu_ui_status -2022-11-01T15:30:53.3090477Z +2022-11-01T15:30:53.3090477Z 2022-11-01T15:30:53.3091739Z PASS /datum/unit_test/strip_menu_ui_status 0.1s 2022-11-01T15:30:53.3094850Z ##[endgroup] 2022-11-01T15:30:53.3492514Z ##[group]/datum/unit_test/subsystem_init -2022-11-01T15:30:53.3493184Z +2022-11-01T15:30:53.3493184Z 2022-11-01T15:30:53.3495636Z PASS /datum/unit_test/subsystem_init 0s 2022-11-01T15:30:53.3498157Z ##[endgroup] 2022-11-01T15:30:53.3664175Z ##[group]/datum/unit_test/suit_storage_icons @@ -2078,83 +2078,83 @@ 2022-11-01T15:30:55.7752422Z 258 - /obj/item/storage/lockbox/medal using invalid icon_state, "medalbox+l" 2022-11-01T15:30:55.7752898Z 259 - /obj/item/crowbar/red/caravan using invalid icon_state, "crowbar_caravan" 2022-11-01T15:30:55.7757058Z 260 - /obj/item/crowbar/drone using invalid icon_state, "crowbar_cyborg" -2022-11-01T15:30:55.7784906Z +2022-11-01T15:30:55.7784906Z 2022-11-01T15:30:55.7785304Z PASS /datum/unit_test/suit_storage_icons 2.4s 2022-11-01T15:30:55.7786128Z ##[endgroup] 2022-11-01T15:30:58.1989647Z ##[group]/datum/unit_test/amputation -2022-11-01T15:30:58.2542620Z +2022-11-01T15:30:58.2542620Z 2022-11-01T15:30:58.2543982Z PASS /datum/unit_test/amputation 0.1s 2022-11-01T15:30:58.2545007Z ##[endgroup] 2022-11-01T15:30:58.2861052Z ##[group]/datum/unit_test/brain_surgery -2022-11-01T15:30:58.3393398Z +2022-11-01T15:30:58.3393398Z 2022-11-01T15:30:58.3395072Z PASS /datum/unit_test/brain_surgery 0.1s 2022-11-01T15:30:58.3396351Z ##[endgroup] 2022-11-01T15:30:58.3713295Z ##[group]/datum/unit_test/head_transplant -2022-11-01T15:30:58.4648885Z +2022-11-01T15:30:58.4648885Z 2022-11-01T15:30:58.4650964Z PASS /datum/unit_test/head_transplant 0.1s 2022-11-01T15:30:58.4652113Z ##[endgroup] 2022-11-01T15:30:58.5529908Z ##[group]/datum/unit_test/multiple_surgeries -2022-11-01T15:30:58.6322272Z +2022-11-01T15:30:58.6322272Z 2022-11-01T15:30:58.6323733Z PASS /datum/unit_test/multiple_surgeries 0.1s 2022-11-01T15:30:58.6324863Z ##[endgroup] 2022-11-01T15:30:58.7192842Z ##[group]/datum/unit_test/start_tend_wounds -2022-11-01T15:30:58.7696686Z +2022-11-01T15:30:58.7696686Z 2022-11-01T15:30:58.7697933Z PASS /datum/unit_test/start_tend_wounds 0s 2022-11-01T15:30:58.7699007Z ##[endgroup] 2022-11-01T15:30:58.8006481Z ##[group]/datum/unit_test/tend_wounds -2022-11-01T15:30:58.9098267Z +2022-11-01T15:30:58.9098267Z 2022-11-01T15:30:58.9099817Z PASS /datum/unit_test/tend_wounds 0.1s 2022-11-01T15:30:58.9100900Z ##[endgroup] 2022-11-01T15:30:59.0574781Z ##[group]/datum/unit_test/auto_teleporter_linking -2022-11-01T15:30:59.0986969Z +2022-11-01T15:30:59.0986969Z 2022-11-01T15:30:59.0988029Z PASS /datum/unit_test/auto_teleporter_linking 0s 2022-11-01T15:30:59.0989210Z ##[endgroup] 2022-11-01T15:30:59.1397849Z ##[group]/datum/unit_test/tgui_create_message -2022-11-01T15:30:59.1398053Z +2022-11-01T15:30:59.1398053Z 2022-11-01T15:30:59.1398515Z PASS /datum/unit_test/tgui_create_message 0s 2022-11-01T15:30:59.1398931Z ##[endgroup] 2022-11-01T15:30:59.1585159Z ##[group]/datum/unit_test/timer_sanity -2022-11-01T15:30:59.1585371Z +2022-11-01T15:30:59.1585371Z 2022-11-01T15:30:59.1585837Z PASS /datum/unit_test/timer_sanity 0s 2022-11-01T15:30:59.1586293Z ##[endgroup] 2022-11-01T15:30:59.1763570Z ##[group]/datum/unit_test/traitor -2022-11-01T15:31:01.0798012Z +2022-11-01T15:31:01.0798012Z 2022-11-01T15:31:01.0799101Z PASS /datum/unit_test/traitor 1.9s 2022-11-01T15:31:01.0799858Z ##[endgroup] 2022-11-01T15:31:05.2187120Z ##[group]/datum/unit_test/verify_config_tags -2022-11-01T15:31:05.2190123Z +2022-11-01T15:31:05.2190123Z 2022-11-01T15:31:05.2191991Z PASS /datum/unit_test/verify_config_tags 0s 2022-11-01T15:31:05.2193777Z ##[endgroup] 2022-11-01T15:31:05.2366479Z ##[group]/datum/unit_test/wizard_loadout -2022-11-01T15:31:05.3463154Z +2022-11-01T15:31:05.3463154Z 2022-11-01T15:31:05.3463988Z PASS /datum/unit_test/wizard_loadout 0.1s 2022-11-01T15:31:05.3465519Z ##[endgroup] 2022-11-01T15:31:05.4918147Z ##[group]/datum/unit_test/find_reference_sanity -2022-11-01T15:31:05.4922156Z +2022-11-01T15:31:05.4922156Z 2022-11-01T15:31:05.4923183Z PASS /datum/unit_test/find_reference_sanity 0s 2022-11-01T15:31:05.4924120Z ##[endgroup] 2022-11-01T15:31:05.5122652Z ##[group]/datum/unit_test/find_reference_baseline -2022-11-01T15:31:05.5126059Z +2022-11-01T15:31:05.5126059Z 2022-11-01T15:31:05.5126875Z PASS /datum/unit_test/find_reference_baseline 0s 2022-11-01T15:31:05.5127655Z ##[endgroup] 2022-11-01T15:31:05.5361446Z ##[group]/datum/unit_test/find_reference_exotic -2022-11-01T15:31:05.5367626Z +2022-11-01T15:31:05.5367626Z 2022-11-01T15:31:05.5369228Z PASS /datum/unit_test/find_reference_exotic 0s 2022-11-01T15:31:05.5369940Z ##[endgroup] 2022-11-01T15:31:05.5551795Z ##[group]/datum/unit_test/find_reference_esoteric -2022-11-01T15:31:05.5558725Z +2022-11-01T15:31:05.5558725Z 2022-11-01T15:31:05.5559583Z PASS /datum/unit_test/find_reference_esoteric 0s 2022-11-01T15:31:05.5560670Z ##[endgroup] 2022-11-01T15:31:05.5737466Z ##[group]/datum/unit_test/find_reference_null_key_entry -2022-11-01T15:31:05.5741407Z +2022-11-01T15:31:05.5741407Z 2022-11-01T15:31:05.5742596Z PASS /datum/unit_test/find_reference_null_key_entry 0s 2022-11-01T15:31:05.5743489Z ##[endgroup] 2022-11-01T15:31:05.6053804Z ##[group]/datum/unit_test/find_reference_assoc_investigation -2022-11-01T15:31:05.6057935Z +2022-11-01T15:31:05.6057935Z 2022-11-01T15:31:05.6058863Z PASS /datum/unit_test/find_reference_assoc_investigation 0s 2022-11-01T15:31:05.6060051Z ##[endgroup] 2022-11-01T15:31:05.6233030Z ##[group]/datum/unit_test/find_reference_static_investigation -2022-11-01T15:31:05.8520469Z +2022-11-01T15:31:05.8520469Z 2022-11-01T15:31:05.8521954Z PASS /datum/unit_test/find_reference_static_investigation 0.2s 2022-11-01T15:31:05.8523118Z ##[endgroup] 2022-11-01T15:31:06.0724951Z ##[group]/datum/unit_test/monkey_business @@ -2166,8 +2166,8 @@ 2022-11-01T15:31:23.2325062Z /datum/forensics (/datum/forensics): New(the blood splatter (/obj/effect/decal/cleanable/blood/hitsplatter), null, null, /list (/list), null) 2022-11-01T15:31:23.2325582Z the blood splatter (/obj/effect/decal/cleanable/blood/hitsplatter): add blood DNA(/list (/list)) 2022-11-01T15:31:23.2326006Z Anthony Hayhurst (461) (/mob/living/carbon/human): spray blood(2, 1) -2022-11-01T15:31:23.2326395Z Rough Abrasion (/datum/wound/slash/moderate): wound injury(null, 2) -2022-11-01T15:31:23.2327172Z Rough Abrasion (/datum/wound/slash/moderate): apply wound(the monkey left leg (/obj/item/bodypart/l_leg/monkey), 0, null, 0, 2) +2022-11-01T15:31:23.2326395Z Rough Abrasion (/datum/wound/slash/flesh/moderate): wound injury(null, 2) +2022-11-01T15:31:23.2327172Z Rough Abrasion (/datum/wound/slash/flesh/moderate): apply wound(the monkey left leg (/obj/item/bodypart/l_leg/monkey), 0, null, 0, 2) 2022-11-01T15:31:23.2327747Z the monkey left leg (/obj/item/bodypart/l_leg/monkey): check wounding(2, 8, 5, 15, 2) 2022-11-01T15:31:23.2328155Z the monkey left leg (/obj/item/bodypart/l_leg/monkey): receive damage(8, 0, 0, 0, 1, null, 5, 15, 1, 2) 2022-11-01T15:31:23.2328594Z Monkey (/datum/species/monkey): apply damage(8, "brute", "l_leg", 0, Anthony Hayhurst (461) (/mob/living/carbon/human), 0, 0, 5, 15, 1, 2) @@ -2191,8 +2191,8 @@ /datum/forensics (/datum/forensics): New(the blood splatter (/obj/effect/decal/cleanable/blood/hitsplatter), null, null, /list (/list), null) the blood splatter (/obj/effect/decal/cleanable/blood/hitsplatter): add blood DNA(/list (/list)) Anthony Hayhurst (461) (/mob/living/carbon/human): spray blood(2, 1) - Rough Abrasion (/datum/wound/slash/moderate): wound injury(null, 2) - Rough Abrasion (/datum/wound/slash/moderate): apply wound(the monkey left leg (/obj/item/bodypart/l_leg/monkey), 0, null, 0, 2) + Rough Abrasion (/datum/wound/slash/flesh/moderate): wound injury(null, 2) + Rough Abrasion (/datum/wound/slash/flesh/moderate): apply wound(the monkey left leg (/obj/item/bodypart/l_leg/monkey), 0, null, 0, 2) the monkey left leg (/obj/item/bodypart/l_leg/monkey): check wounding(2, 8, 5, 15, 2) the monkey left leg (/obj/item/bodypart/l_leg/monkey): receive damage(8, 0, 0, 0, 1, null, 5, 15, 1, 2) Monkey (/datum/species/monkey): apply damage(8, "brute", "l_leg", 0, Anthony Hayhurst (461) (/mob/living/carbon/human), 0, 0, 5, 15, 1, 2) @@ -2217,8 +2217,8 @@ 2022-11-01T15:31:44.6333171Z /datum/forensics (/datum/forensics): New(the blood splatter (/obj/effect/decal/cleanable/blood/hitsplatter), null, null, /list (/list), null) 2022-11-01T15:31:44.6333653Z the blood splatter (/obj/effect/decal/cleanable/blood/hitsplatter): add blood DNA(/list (/list)) 2022-11-01T15:31:44.6334238Z Anthony Hayhurst (461) (/mob/living/carbon/human): spray blood(2, 1) -2022-11-01T15:31:44.6334605Z Rough Abrasion (/datum/wound/slash/moderate): wound injury(null, 2) -2022-11-01T15:31:44.6335055Z Rough Abrasion (/datum/wound/slash/moderate): apply wound(the monkey left leg (/obj/item/bodypart/l_leg/monkey), 0, null, 0, 2) +2022-11-01T15:31:44.6334605Z Rough Abrasion (/datum/wound/slash/flesh/moderate): wound injury(null, 2) +2022-11-01T15:31:44.6335055Z Rough Abrasion (/datum/wound/slash/flesh/moderate): apply wound(the monkey left leg (/obj/item/bodypart/l_leg/monkey), 0, null, 0, 2) 2022-11-01T15:31:44.6335679Z the monkey left leg (/obj/item/bodypart/l_leg/monkey): check wounding(2, 8, 5, 15, 2) 2022-11-01T15:31:44.6336429Z the monkey left leg (/obj/item/bodypart/l_leg/monkey): receive damage(8, 0, 0, 0, 1, null, 5, 15, 1, 2) 2022-11-01T15:31:44.6336913Z Monkey (/datum/species/monkey): apply damage(8, "brute", "l_leg", 0, Anthony Hayhurst (461) (/mob/living/carbon/human), 0, 0, 5, 15, 1, 2) @@ -2236,7 +2236,7 @@ 2022-11-01T15:31:44.6343234Z Master (/datum/controller/master): StartProcessing(0) at _forensics.dm:232 2022-11-01T15:31:44.6345243Z ##[error]FAIL /datum/unit_test/monkey_business 38.6s 2022-11-01T15:31:46.9833542Z ##[group]/datum/unit_test/create_and_destroy -2022-11-01T15:37:15.1785471Z +2022-11-01T15:37:15.1785471Z 2022-11-01T15:37:15.1787041Z PASS /datum/unit_test/create_and_destroy 328.2s 2022-11-01T15:37:15.1788074Z ##[endgroup] 2022-11-01T15:37:15.2115771Z Shutting down Chat subsystem... @@ -2377,12 +2377,12 @@ 2022-11-01T15:37:31.3325316Z Total size of all the files uploaded is 138917 bytes 2022-11-01T15:37:31.3326061Z File upload process has finished. Finalizing the artifact upload 2022-11-01T15:37:31.4289346Z Artifact has been finalized. All files have been successfully uploaded! -2022-11-01T15:37:31.4291368Z +2022-11-01T15:37:31.4291368Z 2022-11-01T15:37:31.4293992Z The raw size of all the files that were specified for upload is 139272 bytes 2022-11-01T15:37:31.4298141Z The size of all the files that were uploaded is 138917 bytes. This takes into account any gzip compression used to reduce the upload size, time and storage -2022-11-01T15:37:31.4301961Z -2022-11-01T15:37:31.4303707Z Note: The size of downloaded zips can differ significantly from the reported size. For more information see: https://github.com/actions/upload-artifact#zipped-artifact-downloads -2022-11-01T15:37:31.4304326Z +2022-11-01T15:37:31.4301961Z +2022-11-01T15:37:31.4303707Z Note: The size of downloaded zips can differ significantly from the reported size. For more information see: https://github.com/actions/upload-artifact#zipped-artifact-downloads +2022-11-01T15:37:31.4304326Z 2022-11-01T15:37:31.4305332Z Artifact test_artifacts_tramstation has been successfully uploaded! 2022-11-01T15:37:31.4451625Z Post job cleanup. 2022-11-01T15:37:31.5950708Z [command]/usr/bin/git version @@ -2436,12 +2436,12 @@ 2022-11-01T15:37:31.7590084Z 2022-11-01 15:22:42+00:00 [Note] [Entrypoint]: Starting temporary server 2022-11-01T15:37:31.7590409Z 2022-11-01 15:22:43+00:00 [Note] [Entrypoint]: Temporary server started. 2022-11-01T15:37:31.7590742Z '/var/lib/mysql/mysql.sock' -> '/var/run/mysqld/mysqld.sock' -2022-11-01T15:37:31.7590984Z +2022-11-01T15:37:31.7590984Z 2022-11-01T15:37:31.7591244Z 2022-11-01 15:22:46+00:00 [Note] [Entrypoint]: Stopping temporary server 2022-11-01T15:37:31.7591577Z 2022-11-01 15:22:47+00:00 [Note] [Entrypoint]: Temporary server stopped -2022-11-01T15:37:31.7592516Z +2022-11-01T15:37:31.7592516Z 2022-11-01T15:37:31.7592791Z 2022-11-01 15:22:47+00:00 [Note] [Entrypoint]: MySQL init process done. Ready for start up. -2022-11-01T15:37:31.7593063Z +2022-11-01T15:37:31.7593063Z 2022-11-01T15:37:31.7608136Z Stop and remove container: e281b5d836644f53b33d06a88663b086_mysqllatest_c6a68e 2022-11-01T15:37:31.7616365Z ##[command]/usr/bin/docker rm --force cd1d0f20f8f882176c274fb882d88cea0d4e9a7b2aebc33f1123c02f7b908aa1 2022-11-01T15:37:32.0241098Z cd1d0f20f8f882176c274fb882d88cea0d4e9a7b2aebc33f1123c02f7b908aa1