From 8ca3958bcf6ff4ab38d54f69e1a075764be37af6 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Wed, 15 Jul 2020 16:23:37 +0100 Subject: [PATCH 01/91] woops dont let monkeys die --- code/game/objects/items/pet_carrier.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/items/pet_carrier.dm b/code/game/objects/items/pet_carrier.dm index a60aa02ce1..4affc99a4b 100644 --- a/code/game/objects/items/pet_carrier.dm +++ b/code/game/objects/items/pet_carrier.dm @@ -256,7 +256,7 @@ occupant_gas_supply[/datum/gas/oxygen] = 0.0064 //make sure it has some gas in so it isn't depressurized occupant_gas_supply.set_temperature(animal.minbodytemp) //simple animals only care about temperature/pressure when their turf isnt a location else - if(ishuman(occupant)) //humans require resistance to cold/heat and living in no air while inside, and lose this when outside + if(iscarbon(occupant)) //humans require resistance to cold/heat and living in no air while inside, and lose this when outside ADD_TRAIT(occupant, TRAIT_RESISTCOLD, "bluespace_container_cold_resist") ADD_TRAIT(occupant, TRAIT_RESISTHEAT, "bluespace_container_heat_resist") ADD_TRAIT(occupant, TRAIT_NOBREATH, "bluespace_container_no_breath") From c6de85bae4fd95993338d9cab3f84263f654712b Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 24 Jul 2020 15:24:02 +0100 Subject: [PATCH 02/91] yes i too like sec being blind --- code/datums/traits/negative.dm | 8 +++----- code/modules/jobs/job_types/head_of_security.dm | 2 +- code/modules/jobs/job_types/security_officer.dm | 2 +- code/modules/jobs/job_types/warden.dm | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) diff --git a/code/datums/traits/negative.dm b/code/datums/traits/negative.dm index 95e02c5a94..a27296e56f 100644 --- a/code/datums/traits/negative.dm +++ b/code/datums/traits/negative.dm @@ -14,7 +14,7 @@ if(NOBLOOD in H.dna.species.species_traits) //can't lose blood if your species doesn't have any return else - quirk_holder.blood_volume -= 0.275 + quirk_holder.blood_volume -= 0.2 /datum/quirk/depression name = "Depression" @@ -54,7 +54,7 @@ GLOBAL_LIST_EMPTY(family_heirlooms) if("Botanist") heirloom_type = pick(/obj/item/cultivator, /obj/item/reagent_containers/glass/bucket, /obj/item/storage/bag/plants, /obj/item/toy/plush/beeplushie) if("Medical Doctor") - heirloom_type = /obj/item/healthanalyzer/advanced + heirloom_type = /obj/item/healthanalyzer if("Paramedic") heirloom_type = pick(/obj/item/clothing/neck/stethoscope, /obj/item/bodybag) if("Station Engineer") @@ -337,10 +337,8 @@ GLOBAL_LIST_EMPTY(family_heirlooms) dumb_thing = FALSE //only once per life if(prob(1)) new/obj/item/reagent_containers/food/snacks/pastatomato(get_turf(H)) //now that's what I call spaghetti code + // small chance to make eye contact with inanimate objects/mindless mobs because of nerves - - - /datum/quirk/social_anxiety/proc/looks_at_floor(datum/source, atom/A) var/mob/living/mind_check = A if(prob(85) || (istype(mind_check) && mind_check.mind)) diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm index 69ed63a514..987ee4977a 100644 --- a/code/modules/jobs/job_types/head_of_security.dm +++ b/code/modules/jobs/job_types/head_of_security.dm @@ -31,7 +31,7 @@ paycheck_department = ACCOUNT_SEC display_order = JOB_DISPLAY_ORDER_HEAD_OF_SECURITY - blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/insanity) + blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/poor_aim, /datum/quirk/blindness, /datum/quirk/monophobia, /datum/quirk/insanity) threat = 3 /datum/outfit/job/hos diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm index bc6f6a94c7..601eadedad 100644 --- a/code/modules/jobs/job_types/security_officer.dm +++ b/code/modules/jobs/job_types/security_officer.dm @@ -23,7 +23,7 @@ mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) display_order = JOB_DISPLAY_ORDER_SECURITY_OFFICER - blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/nonviolent, /datum/quirk/paraplegic) + blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/poor_aim, /datum/quirk/blindness, /datum/quirk/monophobia) threat = 2 /datum/job/officer/get_access() diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm index 5762731f62..6527b2eceb 100644 --- a/code/modules/jobs/job_types/warden.dm +++ b/code/modules/jobs/job_types/warden.dm @@ -24,7 +24,7 @@ mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) display_order = JOB_DISPLAY_ORDER_WARDEN - blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/nonviolent, /datum/quirk/paraplegic) + blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/poor_aim, /datum/quirk/blindness, /datum/quirk/monophobia) threat = 2 /datum/job/warden/get_access() From a057ceaa2a82c33daae597271fa01d4acac10dd1 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 24 Jul 2020 15:31:02 +0100 Subject: [PATCH 03/91] i too like my secoffs to not have blood deficiency --- code/modules/jobs/job_types/head_of_security.dm | 2 +- code/modules/jobs/job_types/security_officer.dm | 2 +- code/modules/jobs/job_types/warden.dm | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm index 987ee4977a..9d870b069a 100644 --- a/code/modules/jobs/job_types/head_of_security.dm +++ b/code/modules/jobs/job_types/head_of_security.dm @@ -31,7 +31,7 @@ paycheck_department = ACCOUNT_SEC display_order = JOB_DISPLAY_ORDER_HEAD_OF_SECURITY - blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/poor_aim, /datum/quirk/blindness, /datum/quirk/monophobia, /datum/quirk/insanity) + blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/poor_aim, /datum/quirk/blindness, /datum/quirk/monophobia, /datum/quirk/insanity, /datum/quirk/blooddeficiency) threat = 3 /datum/outfit/job/hos diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm index 601eadedad..466131899d 100644 --- a/code/modules/jobs/job_types/security_officer.dm +++ b/code/modules/jobs/job_types/security_officer.dm @@ -23,7 +23,7 @@ mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) display_order = JOB_DISPLAY_ORDER_SECURITY_OFFICER - blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/poor_aim, /datum/quirk/blindness, /datum/quirk/monophobia) + blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/poor_aim, /datum/quirk/blindness, /datum/quirk/monophobia, /datum/quirk/blooddeficiency) threat = 2 /datum/job/officer/get_access() diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm index 6527b2eceb..8b36e995da 100644 --- a/code/modules/jobs/job_types/warden.dm +++ b/code/modules/jobs/job_types/warden.dm @@ -24,7 +24,7 @@ mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) display_order = JOB_DISPLAY_ORDER_WARDEN - blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/poor_aim, /datum/quirk/blindness, /datum/quirk/monophobia) + blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/poor_aim, /datum/quirk/blindness, /datum/quirk/monophobia, /datum/quirk/blooddeficiency) threat = 2 /datum/job/warden/get_access() From 7fb55a02a56844a11827dfb5bdf5334e4b6267e6 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 24 Jul 2020 22:34:22 +0100 Subject: [PATCH 04/91] section one --- code/__DEFINES/DNA.dm | 4 + code/__DEFINES/admin.dm | 1 + code/__DEFINES/combat.dm | 6 +- code/__DEFINES/dcs/signals.dm | 4 +- code/__DEFINES/is_helpers.dm | 8 - code/__DEFINES/misc.dm | 3 + code/__DEFINES/wounds.dm | 112 ++++++++-- code/_onclick/item_attack.dm | 4 +- code/controllers/subsystem/persistence.dm | 4 +- code/datums/components/butchering.dm | 2 +- code/datums/components/embedded.dm | 28 ++- code/datums/components/pellet_cloud.dm | 55 ++++- code/datums/elements/embed.dm | 38 ++-- code/datums/mutations/actions.dm | 2 +- code/datums/mutations/hulk.dm | 18 ++ code/datums/status_effects/debuffs.dm | 2 +- code/datums/status_effects/wound_effects.dm | 31 ++- code/datums/wounds/_scars.dm | 38 +++- code/datums/wounds/_wounds.dm | 51 +++-- code/datums/wounds/bones.dm | 185 +++++++--------- code/datums/wounds/burns.dm | 99 +++------ code/datums/wounds/loss.dm | 41 ++++ code/datums/wounds/pierce.dm | 170 ++++++++++++++ code/datums/wounds/{cuts.dm => slash.dm} | 208 ++++++++---------- .../game/gamemodes/clown_ops/clown_weapons.dm | 2 +- code/game/machinery/doors/door.dm | 3 +- code/game/objects/items.dm | 10 +- code/game/objects/items/chainsaw.dm | 6 +- code/game/objects/items/dualsaber.dm | 2 +- code/game/objects/items/fireaxe.dm | 5 +- code/game/objects/items/holy_weapons.dm | 18 +- code/game/objects/items/kitchen.dm | 7 +- code/game/objects/items/melee/energy.dm | 8 +- code/game/objects/items/melee/misc.dm | 6 +- code/game/objects/items/melee/transforming.dm | 2 +- code/game/objects/items/pitchfork.dm | 2 +- code/game/objects/items/sharpener.dm | 2 +- code/game/objects/items/shrapnel.dm | 29 +-- code/game/objects/items/spear.dm | 6 +- code/game/objects/items/stacks/medical.dm | 37 +++- .../game/objects/items/stacks/sheets/glass.dm | 2 +- code/game/objects/items/tools/weldingtool.dm | 2 + code/game/objects/items/toys.dm | 4 +- code/game/objects/items/weaponry.dm | 18 +- code/game/turfs/simulated/walls.dm | 37 +++- code/modules/admin/verbs/randomverbs.dm | 89 +++++++- .../bloodsucker/objects/bloodsucker_crypt.dm | 4 +- .../changeling/powers/mutations.dm | 2 +- .../changeling/powers/regenerate.dm | 4 +- .../clock_weapons/ratvarian_spear.dm | 2 +- code/modules/antagonists/cult/cult_items.dm | 6 +- .../antagonists/slaughter/slaughter.dm | 2 +- .../antagonists/wizard/equipment/artefact.dm | 2 +- code/modules/cargo/packs/goodies.dm | 6 + code/modules/cargo/packs/medical.dm | 15 ++ code/modules/client/preferences.dm | 2 +- code/modules/clothing/glasses/_glasses.dm | 8 +- code/modules/clothing/glasses/hud.dm | 4 +- code/modules/clothing/suits/armor.dm | 6 +- .../food_and_drinks/drinks/drinks/bottle.dm | 2 +- code/modules/food_and_drinks/food/snacks.dm | 16 +- .../browserassets/css/browserOutput.css | 8 +- code/modules/hydroponics/hydroitemdefines.dm | 2 +- .../mining/equipment/kinetic_crusher.dm | 2 +- code/modules/mining/equipment/mining_tools.dm | 4 +- .../mining/lavaland/necropolis_chests.dm | 4 +- code/modules/mob/living/bloodcrawl.dm | 4 +- code/modules/mob/living/carbon/carbon.dm | 39 ++-- .../mob/living/carbon/carbon_defense.dm | 51 ++++- .../modules/mob/living/carbon/damage_procs.dm | 4 +- code/modules/mob/living/carbon/examine.dm | 5 +- .../mob/living/carbon/human/damage_procs.dm | 2 +- .../mob/living/carbon/human/examine.dm | 25 ++- .../mob/living/carbon/human/human_helpers.dm | 24 +- .../mob/living/carbon/human/species.dm | 32 ++- .../carbon/human/species_types/abductors.dm | 2 +- .../carbon/human/species_types/angel.dm | 2 +- .../carbon/human/species_types/bugmen.dm | 2 +- .../carbon/human/species_types/dullahan.dm | 4 +- .../carbon/human/species_types/dwarves.dm | 2 +- .../carbon/human/species_types/flypeople.dm | 2 +- .../carbon/human/species_types/furrypeople.dm | 4 +- .../carbon/human/species_types/humans.dm | 2 +- .../living/carbon/human/species_types/ipc.dm | 2 +- .../carbon/human/species_types/jellypeople.dm | 2 +- .../human/species_types/lizardpeople.dm | 2 +- .../carbon/human/species_types/mushpeople.dm | 2 +- .../carbon/human/species_types/plasmamen.dm | 2 +- .../carbon/human/species_types/podpeople.dm | 2 +- .../human/species_types/shadowpeople.dm | 6 +- .../carbon/human/species_types/skeletons.dm | 2 +- .../carbon/human/species_types/synthliz.dm | 2 +- .../carbon/human/species_types/vampire.dm | 2 +- .../carbon/human/species_types/zombies.dm | 10 +- code/modules/mob/living/damage_procs.dm | 4 +- code/modules/mob/living/living.dm | 66 +++--- .../mob/living/silicon/damage_procs.dm | 2 +- .../mob/living/simple_animal/hostile/bear.dm | 2 +- .../living/simple_animal/hostile/syndicate.dm | 2 +- .../mob/living/simple_animal/simple_animal.dm | 2 +- code/modules/ninja/energy_katana.dm | 2 +- code/modules/paperwork/pen.dm | 4 +- .../projectiles/guns/energy/special.dm | 2 +- code/modules/projectiles/guns/magic/staff.dm | 2 +- code/modules/projectiles/projectile.dm | 2 +- .../modules/projectiles/projectile/bullets.dm | 2 +- .../projectile/bullets/revolver.dm | 2 +- .../projectiles/projectile/bullets/shotgun.dm | 6 +- .../chemistry/reagents/drink_reagents.dm | 3 + code/modules/surgery/bodyparts/_bodyparts.dm | 6 +- code/modules/surgery/bone_mending.dm | 4 +- code/modules/surgery/tools.dm | 10 +- code/modules/vending/_vending.dm | 4 +- code/modules/zombie/items.dm | 4 +- tgstation.dme | 1 - 115 files changed, 1202 insertions(+), 682 deletions(-) create mode 100644 code/datums/wounds/loss.dm create mode 100644 code/datums/wounds/pierce.dm rename code/datums/wounds/{cuts.dm => slash.dm} (60%) diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index d1c1d309cd..035563627f 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -144,6 +144,10 @@ #define WINGCOLOR 26 #define CAN_SCAR 27 // If this species can be scarred (fleshy) +/// Used for determining which wounds are applicable to this species. +#define HAS_FLESH 28 /// if we have flesh (can suffer slash/piercing/burn wounds, requires they don't have NOBLOOD) +#define HAS_BONE 29 /// if we have bones (can suffer bone wounds) + //organ slots #define ORGAN_SLOT_BRAIN "brain" #define ORGAN_SLOT_APPENDIX "appendix" diff --git a/code/__DEFINES/admin.dm b/code/__DEFINES/admin.dm index 0b2764c4a7..2dee6930c6 100644 --- a/code/__DEFINES/admin.dm +++ b/code/__DEFINES/admin.dm @@ -79,6 +79,7 @@ #define ADMIN_PUNISHMENT_SCARIFY "Scarify" #define ADMIN_PUNISHMENT_PICKLE "Pickle-ify" #define ADMIN_PUNISHMENT_FRY "Fry" +#define ADMIN_PUNISHMENT_PERFORATE ":B:erforate" #define AHELP_ACTIVE 1 #define AHELP_CLOSED 2 diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index dff52f4748..d4f0d94666 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -209,9 +209,9 @@ GLOBAL_LIST_INIT(shove_disarming_types, typecacheof(list( #define GUN_AIMING_TIME (2 SECONDS) //Object/Item sharpness -#define IS_BLUNT 0 -#define IS_SHARP 1 -#define IS_SHARP_ACCURATE 2 +#define SHARP_NONE 0 +#define SHARP_EDGED 1 +#define SHARP_POINTY 2 //His Grace. #define HIS_GRACE_SATIATED 0 //He hungers not. If bloodthirst is set to this, His Grace is asleep. diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 5b8a4d5fc3..7e1a83486d 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -356,8 +356,8 @@ #define COMSIG_PEN_ROTATED "pen_rotated" //called after rotation in /obj/item/pen/attack_self(): (rotation, mob/living/carbon/user) // /obj/item/projectile signals (sent to the firer) -#define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit" // from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle) -#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit" // from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle) +#define COMSIG_PROJECTILE_SELF_ON_HIT "projectile_self_on_hit" ///from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle, hit_limb) +#define COMSIG_PROJECTILE_ON_HIT "projectile_on_hit" ///from base of /obj/item/projectile/proc/on_hit(): (atom/movable/firer, atom/target, Angle, hit_limb) #define COMSIG_PROJECTILE_BEFORE_FIRE "projectile_before_fire" // from base of /obj/item/projectile/proc/fire(): (obj/item/projectile, atom/original_target) #define COMSIG_PROJECTILE_FIRE "projectile_fire" ///from the base of /obj/item/projectile/proc/fire(): () #define COMSIG_PROJECTILE_RANGE_OUT "projectile_range_out" // sent to targets during the process_hit proc of projectiles diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index a9d9bda00c..0065e0298c 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -202,14 +202,6 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list( #define isclothing(A) (istype(A, /obj/item/clothing)) -GLOBAL_LIST_INIT(pointed_types, typecacheof(list( - /obj/item/pen, - /obj/item/screwdriver, - /obj/item/reagent_containers/syringe, - /obj/item/kitchen/fork))) - -#define is_pointed(W) (is_type_in_typecache(W, GLOB.pointed_types)) - #define isbodypart(A) (istype(A, /obj/item/bodypart)) #define isprojectile(A) (istype(A, /obj/item/projectile)) diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index 071dab20b1..aaa63225d8 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -434,6 +434,9 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define ION_FILE "ion_laws.json" #define REDPILL_FILE "redpill.json" #define PIRATE_NAMES_FILE "pirates.json" +#define FLESH_SCAR_FILE "wounds/flesh_scar_desc.json" +#define BONE_SCAR_FILE "wounds/bone_scar_desc.json" +#define SCAR_LOC_FILE "wounds/scar_loc.json" //Fullscreen overlay resolution in tiles. diff --git a/code/__DEFINES/wounds.dm b/code/__DEFINES/wounds.dm index b993429961..c87e2f8bbd 100644 --- a/code/__DEFINES/wounds.dm +++ b/code/__DEFINES/wounds.dm @@ -1,43 +1,119 @@ + #define WOUND_DAMAGE_EXPONENT 1.4 +/// an attack must do this much damage after armor in order to roll for being a wound (incremental pressure damage need not apply) +#define WOUND_MINIMUM_DAMAGE 5 +/// an attack must do this much damage after armor in order to be eliigible to dismember a suitably mushed bodypart +#define DISMEMBER_MINIMUM_DAMAGE 10 +/// any damage dealt over this is ignored for damage rolls unless the target has the frail quirk (35^1.4=145) +#define WOUND_MAX_CONSIDERED_DAMAGE 35 + + #define WOUND_SEVERITY_TRIVIAL 0 // for jokey/meme wounds like stubbed toe, no standard messages/sounds or second winds #define WOUND_SEVERITY_MODERATE 1 #define WOUND_SEVERITY_SEVERE 2 #define WOUND_SEVERITY_CRITICAL 3 #define WOUND_SEVERITY_LOSS 4 // theoretical total limb loss, like dismemberment for cuts -#define WOUND_BRUTE 0 -#define WOUND_SHARP 1 -#define WOUND_BURN 2 +/// any brute weapon/attack that doesn't have sharpness. rolls for blunt bone wounds +#define WOUND_BLUNT 1 +/// any brute weapon/attack with sharpness = SHARP_EDGED. rolls for slash wounds +#define WOUND_SLASH 2 +/// any brute weapon/attack with sharpness = SHARP_POINTY. rolls for piercing wounds +#define WOUND_PIERCE 3 +/// any concentrated burn attack (lasers really). rolls for burning wounds +#define WOUND_BURN 4 // How much determination reagent to add each time someone gains a new wound in [/datum/wound/proc/second_wind()] #define WOUND_DETERMINATION_MODERATE 1 #define WOUND_DETERMINATION_SEVERE 2.5 #define WOUND_DETERMINATION_CRITICAL 5 +#define WOUND_DETERMINATION_LOSS 7.5 +/// the max amount of determination you can have #define WOUND_DETERMINATION_MAX 10 -// set wound_bonus on an item or attack to this to disable checking wounding for the attack +/// set wound_bonus on an item or attack to this to disable checking wounding for the attack #define CANT_WOUND -100 // list in order of highest severity to lowest -#define WOUND_LIST_BONE list(/datum/wound/brute/bone/critical, /datum/wound/brute/bone/severe, /datum/wound/brute/bone/moderate) -#define WOUND_LIST_CUT list(/datum/wound/brute/cut/loss, /datum/wound/brute/cut/critical, /datum/wound/brute/cut/severe, /datum/wound/brute/cut/moderate) -#define WOUND_LIST_BURN list(/datum/wound/burn/critical, /datum/wound/burn/severe, /datum/wound/burn/moderate) +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) + )) + +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)) // Thresholds for infection for burn wounds, once infestation hits each threshold, things get steadily worse -#define WOUND_INFECTION_MODERATE 4 // below this has no ill effects from infection -#define WOUND_INFECTION_SEVERE 8 // then below here, you ooze some pus and suffer minor tox damage, but nothing serious -#define WOUND_INFECTION_CRITICAL 12 // then below here, your limb occasionally locks up from damage and infection and briefly becomes disabled. Things are getting really bad -#define WOUND_INFECTION_SEPTIC 20 // below here, your skin is almost entirely falling off and your limb locks up more frequently. You are within a stone's throw of septic paralysis and losing the limb +/// below this has no ill effects from infection +#define WOUND_INFECTION_MODERATE 4 +/// then below here, you ooze some pus and suffer minor tox damage, but nothing serious +#define WOUND_INFECTION_SEVERE 8 +/// then below here, your limb occasionally locks up from damage and infection and briefly becomes disabled. Things are getting really bad +#define WOUND_INFECTION_CRITICAL 12 +/// below here, your skin is almost entirely falling off and your limb locks up more frequently. You are within a stone's throw of septic paralysis and losing the limb +#define WOUND_INFECTION_SEPTIC 20 // above WOUND_INFECTION_SEPTIC, your limb is completely putrid and you start rolling to lose the entire limb by way of paralyzation. After 3 failed rolls (~4-5% each probably), the limb is paralyzed -#define WOUND_BURN_SANITIZATION_RATE 0.15 // how quickly sanitization removes infestation and decays per tick -#define WOUND_CUT_MAX_BLOODFLOW 8 // how much blood you can lose per tick per cut max. 8 is a LOT of blood for one cut so don't worry about hitting it easily -#define WOUND_BONE_HEAD_TIME_VARIANCE 20 // if we suffer a bone wound to the head that creates brain traumas, the timer for the trauma cycle is +/- by this percent (0-100) + +/// how quickly sanitization removes infestation and decays per tick +#define WOUND_BURN_SANITIZATION_RATE 0.15 +/// how much blood you can lose per tick per slash max. 8 is a LOT of blood for one cut so don't worry about hitting it easily +#define WOUND_SLASH_MAX_BLOODFLOW 8 +/// dead people don't bleed, but they can clot! this is the minimum amount of clotting per tick on dead people, so even critical cuts will slowly clot in dead people +#define WOUND_SLASH_DEAD_CLOT_MIN 0.05 +/// if we suffer a bone wound to the head that creates brain traumas, the timer for the trauma cycle is +/- by this percent (0-100) +#define WOUND_BONE_HEAD_TIME_VARIANCE 20 // The following are for persistent scar save formats -#define SCAR_SAVE_ZONE 1 // The body_zone we're applying to on granting -#define SCAR_SAVE_DESC 2 // The description we're loading -#define SCAR_SAVE_PRECISE_LOCATION 3 // The precise location we're loading -#define SCAR_SAVE_SEVERITY 4 // The severity the scar had +/// The version number of the scar we're saving +#define SCAR_SAVE_VERS 1 +/// The body_zone we're applying to on granting +#define SCAR_SAVE_ZONE 2 +/// The description we're loading +#define SCAR_SAVE_DESC 3 +/// The precise location we're loading +#define SCAR_SAVE_PRECISE_LOCATION 4 +/// The severity the scar had +#define SCAR_SAVE_SEVERITY 5 +///how many fields there are above (NOT INCLUDING THIS OBVIOUSLY) +#define SCAR_SAVE_LENGTH 5 + +// increment this number when you update the persistent scarring format in a way that invalidates previous saved scars (new fields, reordering, etc) +/// saved scars with a version lower than this will be discarded +#define SCAR_CURRENT_VERSION 1 + + +// With the wounds pt. 2 update, general dismemberment now requires 2 things for a limb to be dismemberable (bone only creatures just need the second): +// 1. Skin is mangled: A critical slash or pierce wound on that limb +// 2. Bone is mangled: At least a severe bone wound on that limb +// see [/obj/item/bodypart/proc/get_mangled_state] for more information +#define BODYPART_MANGLED_NONE 0 +#define BODYPART_MANGLED_BONE 1 +#define BODYPART_MANGLED_FLESH 2 +#define BODYPART_MANGLED_BOTH 3 + +// What kind of biology we have, and what wounds we can suffer, mostly relies on the HAS_FLESH and HAS_BONE species traits on human species +/// golems and androids, cannot suffer any wounds +#define BIO_INORGANIC 0 +/// skeletons and plasmemes, can only suffer bone wounds, only needs mangled bone to be able to dismember +#define BIO_JUST_BONE 1 +/// nothing right now, maybe slimepeople in the future, can only suffer slashing, piercing, and burn wounds +#define BIO_JUST_FLESH 2 +/// standard humanoids, can suffer all wounds, needs mangled bone and flesh to dismember +#define BIO_FLESH_BONE 3 + +/// If this wound requires having the HAS_FLESH flag for humanoids +#define FLESH_WOUND (1<<0) +/// If this wound requires having the HAS_BONE flag for humanaoids +#define BONE_WOUND (1<<1) +/// If having this wound counts as mangled flesh for dismemberment +#define MANGLES_FLESH (1<<2) +/// If having this wound counts as mangled bone for dismemberment +#define MANGLES_BONE (1<<3) +/// If this wound marks the limb as being allowed to have gauze applied +#define ACCEPTS_GAUZE (1<<4) diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index bef06a69e9..be576333cf 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -210,9 +210,9 @@ else return clamp(w_class * 6, 10, 100) // Multiply the item's weight class by 6, then clamp the value between 10 and 100 -/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area, current_force) +/mob/living/proc/send_item_attack_message(obj/item/I, mob/living/user, hit_area, obj/item/bodypart/hit_bodypart) var/message_verb = "attacked" - if(I.attack_verb && I.attack_verb.len) + if(length(I.attack_verb)) message_verb = "[pick(I.attack_verb)]" if(current_force < I.force * FEEBLE_ATTACK_MSG_THRESHOLD) message_verb = "[pick("feebly", "limply", "saplessly")] [message_verb]" diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm index b4a162c982..b8a3a10866 100644 --- a/code/controllers/subsystem/persistence.dm +++ b/code/controllers/subsystem/persistence.dm @@ -561,8 +561,8 @@ SUBSYSTEM_DEF(persistence) ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = "" else for(var/k in ending_human.all_wounds) - var/datum/wound/W = k - W.remove_wound() // so we can get the scars for open wounds + var/datum/wound/iter_wound = k + iter_wound.remove_wound() // so we can get the scars for open wounds if(!ending_human.client) return ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = ending_human.format_scars() diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm index b5b8849155..4f56f58d23 100644 --- a/code/datums/components/butchering.dm +++ b/code/datums/components/butchering.dm @@ -67,7 +67,7 @@ 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/brute/cut/critical/screaming_through_a_slit_throat = new + var/datum/wound/slash/critical/screaming_through_a_slit_throat = new screaming_through_a_slit_throat.apply_wound(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 ce124646f4..c43df20a5c 100644 --- a/code/datums/components/embedded.dm +++ b/code/datums/components/embedded.dm @@ -53,6 +53,8 @@ var/harmful var/mutable_appearance/overlay + var/damage = weapon.throwforce + /datum/component/embedded/Initialize(obj/item/I, datum/thrownthing/throwingdatum, obj/item/bodypart/part, @@ -146,22 +148,28 @@ victim.throw_alert("embeddedobject", /obj/screen/alert/embeddedobject) playsound(victim,'sound/weapons/bladeslice.ogg', 40) weapon.add_mob_blood(victim)//it embedded itself in you, of course it's bloody! - var/damage = weapon.w_class * impact_pain_mult - limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus=-30, sharpness = TRUE) + var/damage += weapon.w_class * impact_pain_mult SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded) else victim.visible_message("[weapon] sticks itself to [victim]'s [limb.name]!",ignored_mobs=victim) to_chat(victim, "[weapon] sticks itself to your [limb.name]!") + if(damage > 0) + var/armor = victim.run_armor_check(limb.body_zone, "melee", "Your armor has protected your [limb.name].", "Your armor has softened a hit to your [limb.name].",I.armour_penetration) + limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, blocked=armor, sharpness = I.get_sharpness()) + /// Called every time a carbon with a harmful embed moves, rolling a chance for the item to cause pain. The chance is halved if the carbon is crawling or walking. /datum/component/embedded/proc/jostleCheck() var/mob/living/carbon/victim = parent - var/chance = jostle_chance + var/pain_chance_current = jostle_chance if(victim.m_intent == MOVE_INTENT_WALK || !(victim.mobility_flags & MOBILITY_STAND)) - chance *= 0.5 + pain_chance_current *= 0.5 - if(harmful && prob(chance)) + if(pain_stam_pct && victim.stam_paralyzed) //if it's a less-lethal embed, give them a break if they're already stamcritted + pain_chance_current *= 0.2 + damage *= 0.5 + if(harmful && prob(pain_chance_current)) var/damage = weapon.w_class * jostle_pain_mult limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND) to_chat(victim, "[weapon] embedded in your [limb.name] jostles and stings!") @@ -199,7 +207,7 @@ if(harmful) var/damage = weapon.w_class * remove_pain_mult - limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, sharpness=TRUE) //It hurts to rip it out, get surgery you dingus. + limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND) //It hurts to rip it out, get surgery you dingus. victim.emote("scream") victim.visible_message("[victim] successfully rips [weapon] out of [victim.p_their()] [limb.name]!", "You successfully remove [weapon] from your [limb.name].") else @@ -279,11 +287,13 @@ limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND) to_chat(victim, "[weapon] embedded in your [limb.name] hurts!") - if(prob(fall_chance)) + var/fall_chance_current = fall_chance + if(victim.mobility_flags & ~MOBILITY_STAND) + fall_chance_current *= 0.2 + + if(prob(fall_chance_current)) fallOutCarbon() - - //////////////////////////////////////// //////////////TURF PROCS//////////////// //////////////////////////////////////// diff --git a/code/datums/components/pellet_cloud.dm b/code/datums/components/pellet_cloud.dm index 938d9f5f56..3eb6d61561 100644 --- a/code/datums/components/pellet_cloud.dm +++ b/code/datums/components/pellet_cloud.dm @@ -1,3 +1,8 @@ +// the following defines are used for [/datum/component/pellet_cloud/var/list/wound_info_by_part] to store the damage, wound_bonus, and bw_bonus for each bodypart hit +#define CLOUD_POSITION_DAMAGE 1 +#define CLOUD_POSITION_W_BONUS 2 +#define CLOUD_POSITION_BW_BONUS 3 + /* * This component is used when you want to create a bunch of shrapnel or projectiles (say, shrapnel from a fragmentation grenade, or buckshot from a shotgun) from a central point, * without necessarily printing a separate message for every single impact. This component should be instantiated right when you need it (like the moment of firing), then activated @@ -29,7 +34,10 @@ var/list/pellets = list() /// An associated list with the atom hit as the key and how many pellets they've eaten for the value, for printing aggregate messages var/list/targets_hit = list() - /// For grenades, any /mob/living's the grenade is moved onto, see [/datum/component/pellet_cloud/proc/handle_martyrs()] + + /// Another associated list for hit bodyparts on carbons so we can track how much wounding potential we have for each bodypart + var/list/wound_info_by_part = list() + /// For grenades, any /mob/living's the grenade is moved onto, see [/datum/component/pellet_cloud/proc/handle_martyrs] var/list/bodies /// For grenades, tracking people who die covering a grenade for achievement purposes, see [/datum/component/pellet_cloud/proc/handle_martyrs()] var/list/purple_hearts @@ -64,6 +72,7 @@ /datum/component/pellet_cloud/Destroy(force, silent) purple_hearts = null pellets = null + wound_info_by_part = null targets_hit = null bodies = null return ..() @@ -187,10 +196,26 @@ break ///One of our pellets hit something, record what it was and check if we're done (terminated == num_pellets) -/datum/component/pellet_cloud/proc/pellet_hit(obj/item/projectile/P, atom/movable/firer, atom/target, Angle) +/datum/component/pellet_cloud/proc/pellet_hit(obj/projectile/P, atom/movable/firer, atom/target, Angle, hit_zone) pellets -= P terminated++ hits++ + var/obj/item/bodypart/hit_part + if(iscarbon(target) && hit_zone) + var/mob/living/carbon/hit_carbon = target + hit_part = hit_carbon.get_bodypart(hit_zone) + if(hit_part) + target = hit_part + if(P.wound_bonus != CANT_WOUND) // handle wounding + // unfortunately, due to how pellet clouds handle finalizing only after every pellet is accounted for, that also means there might be a short delay in dealing wounds if one pellet goes wide + // while buckshot may reach a target or miss it all in one tick, we also have to account for possible ricochets that may take a bit longer to hit the target + if(isnull(wound_info_by_part[hit_part])) + wound_info_by_part[hit_part] = list(0, 0, 0) + wound_info_by_part[hit_part][CLOUD_POSITION_DAMAGE] += P.damage // these account for decay + wound_info_by_part[hit_part][CLOUD_POSITION_W_BONUS] += P.wound_bonus + wound_info_by_part[hit_part][CLOUD_POSITION_BW_BONUS] += P.bare_wound_bonus + P.wound_bonus = CANT_WOUND // actual wounding will be handled aggregate + targets_hit[target]++ if(targets_hit[target] == 1) RegisterSignal(target, COMSIG_PARENT_QDELETING, .proc/on_target_qdel, override=TRUE) @@ -231,13 +256,23 @@ for(var/atom/target in targets_hit) var/num_hits = targets_hit[target] UnregisterSignal(target, COMSIG_PARENT_QDELETING) - if(num_hits > 1) - target.visible_message("[target] is hit by [num_hits] [proj_name]s!", null, null, COMBAT_MESSAGE_RANGE, target) - to_chat(target, "You're hit by [num_hits] [proj_name]s!") - else - target.visible_message("[target] is hit by a [proj_name]!", null, null, COMBAT_MESSAGE_RANGE, target) - to_chat(target, "You're hit by a [proj_name]!") + var/obj/item/bodypart/hit_part + if(isbodypart(target)) + hit_part = target + target = hit_part.owner + var/damage_dealt = wound_info_by_part[hit_part][CLOUD_POSITION_DAMAGE] + var/w_bonus = wound_info_by_part[hit_part][CLOUD_POSITION_W_BONUS] + var/bw_bonus = wound_info_by_part[hit_part][CLOUD_POSITION_BW_BONUS] + var/wound_type = (initial(P.damage_type) == BRUTE) ? WOUND_BLUNT : WOUND_BURN // sharpness is handled in the wound rolling + wound_info_by_part[hit_part] = null + hit_part.painless_wound_roll(wound_type, damage_dealt, w_bonus, bw_bonus, initial(P.sharpness)) + if(num_hits > 1) + target.visible_message("[target] is hit by [num_hits] [proj_name]s[hit_part ? " in the [hit_part.name]" : ""]!", null, null, COMBAT_MESSAGE_RANGE, target) + to_chat(target, "You're hit by [num_hits] [proj_name]s[hit_part ? " in the [hit_part.name]" : ""]!") + else + target.visible_message("[target] is hit by a [proj_name][hit_part ? " in the [hit_part.name]" : ""]!", null, null, COMBAT_MESSAGE_RANGE, target) + to_chat(target, "You're hit by a [proj_name][hit_part ? " in the [hit_part.name]" : ""]!") UnregisterSignal(parent, COMSIG_PARENT_PREQDELETED) if(queued_delete) qdel(parent) @@ -281,3 +316,7 @@ targets_hit -= target bodies -= target purple_hearts -= target + +#undef CLOUD_POSITION_DAMAGE +#undef CLOUD_POSITION_W_BONUS +#undef CLOUD_POSITION_BW_BONUS diff --git a/code/datums/elements/embed.dm b/code/datums/elements/embed.dm index 8a7acde9cb..ac2ec1738e 100644 --- a/code/datums/elements/embed.dm +++ b/code/datums/elements/embed.dm @@ -37,10 +37,10 @@ if(!isitem(target) && !isprojectile(target)) return ELEMENT_INCOMPATIBLE + RegisterSignal(target, COMSIG_ELEMENT_ATTACH, .proc/severancePackage) if(isitem(target)) RegisterSignal(target, COMSIG_MOVABLE_IMPACT_ZONE, .proc/checkEmbedMob) RegisterSignal(target, COMSIG_MOVABLE_IMPACT, .proc/checkEmbedOther) - RegisterSignal(target, COMSIG_ELEMENT_ATTACH, .proc/severancePackage) RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/examined) RegisterSignal(target, COMSIG_EMBED_TRY_FORCE, .proc/tryForceEmbed) RegisterSignal(target, COMSIG_ITEM_DISABLE_EMBED, .proc/detachFromWeapon) @@ -68,7 +68,7 @@ if(isitem(target)) UnregisterSignal(target, list(COMSIG_MOVABLE_IMPACT_ZONE, COMSIG_ELEMENT_ATTACH, COMSIG_MOVABLE_IMPACT, COMSIG_PARENT_EXAMINE, COMSIG_EMBED_TRY_FORCE, COMSIG_ITEM_DISABLE_EMBED)) else - UnregisterSignal(target, list(COMSIG_PROJECTILE_SELF_ON_HIT)) + UnregisterSignal(target, list(COMSIG_PROJECTILE_SELF_ON_HIT, COMSIG_ELEMENT_ATTACH)) /// Checking to see if we're gonna embed into a human @@ -79,13 +79,13 @@ var/actual_chance = embed_chance if(!weapon.isEmbedHarmless()) // all the armor in the world won't save you from a kick me sign - var/armor = max(victim.run_armor_check(hit_zone, "bullet", silent=TRUE), victim.run_armor_check(hit_zone, "bomb", silent=TRUE)) // we'll be nice and take the better of bullet and bomb armor + var/armor = max(victim.run_armor_check(hit_zone, "bullet", silent=TRUE), victim.run_armor_check(hit_zone, "bomb", silent=TRUE)) * 0.5 // we'll be nice and take the better of bullet and bomb armor, halved if(armor) // we only care about armor penetration if there's actually armor to penetrate var/pen_mod = -armor + weapon.armour_penetration // even a little bit of armor can make a big difference for shrapnel with large negative armor pen actual_chance += pen_mod // doing the armor pen as a separate calc just in case this ever gets expanded on if(actual_chance <= 0) - victim.visible_message("[weapon] bounces off [victim]'s armor!", "[weapon] bounces off your armor!", vision_distance = COMBAT_MESSAGE_RANGE) + victim.visible_message("[weapon] bounces off [victim]'s armor, unable to embed!", "[weapon] bounces off your armor, unable to embed!", vision_distance = COMBAT_MESSAGE_RANGE) return var/roll_embed = prob(actual_chance) @@ -147,7 +147,7 @@ return TRUE ///A different embed element has been attached, so we'll detach and let them handle things -/datum/element/embed/proc/severancePackage(obj/item/weapon, datum/element/E) +/datum/element/embed/proc/severancePackage(obj/weapon, datum/element/E) if(istype(E, /datum/element/embed)) Detach(weapon) @@ -174,6 +174,10 @@ return // we don't care var/obj/item/payload = new payload_type(get_turf(hit)) + if(istype(payload, /obj/item/shrapnel/bullet)) + payload.name = P.name + payload.embedding = P.embedding + payload.updateEmbedding() var/did_embed if(iscarbon(hit)) var/mob/living/carbon/C = hit @@ -185,30 +189,21 @@ else did_embed = payload.tryEmbed(hit) - if(!did_embed) - payload.failedEmbed() + payload.tryEmbed(limb) Detach(P) /** - * tryForceEmbed() is called here when we fire COMSIG_EMBED_TRY_FORCE from [/obj/item/proc/tryEmbed]. Mostly, this means we're a piece of shrapnel from a projectile that just impacted something, and we're trying to embed in it. - * - * The reason for this extra mucking about is avoiding having to do an extra hitby(), and annoying the target by impacting them once with the projectile, then again with the shrapnel (which likely represents said bullet), and possibly - * AGAIN if we actually embed. This way, we save on at least one message. Runs the standard embed checks on the mob/turf. - * * Arguments: - * * I- what we're trying to embed, obviously - * * target- what we're trying to shish-kabob, either a bodypart, a carbon, or a closed turf + * * I- the item we're trying to insert into the target + * * target- what we're trying to shish-kabob, either a bodypart or a carbon * * hit_zone- if our target is a carbon, try to hit them in this zone, if we don't have one, pick a random one. If our target is a bodypart, we already know where we're hitting. * * forced- if we want this to succeed 100% */ /datum/element/embed/proc/tryForceEmbed(obj/item/I, atom/target, hit_zone, forced=FALSE) var/obj/item/bodypart/limb var/mob/living/carbon/C - var/turf/closed/T - if(!forced && !prob(embed_chance)) return - if(iscarbon(target)) C = target if(!hit_zone) @@ -218,10 +213,5 @@ limb = target hit_zone = limb.body_zone C = limb.owner - else if(isclosedturf(target)) - T = target - - if(C) - return checkEmbedMob(I, C, hit_zone, forced=TRUE) - else if(T) - return checkEmbedOther(I, T, forced=TRUE) + checkEmbed(I, C, hit_zone, forced=TRUE) + return TRUE diff --git a/code/datums/mutations/actions.dm b/code/datums/mutations/actions.dm index 7e6d567cfa..bd9ecaeeaa 100644 --- a/code/datums/mutations/actions.dm +++ b/code/datums/mutations/actions.dm @@ -410,7 +410,7 @@ throw_speed = 4 embedding = list("embedded_pain_multiplier" = 4, "embed_chance" = 100, "embedded_fall_chance" = 0) w_class = WEIGHT_CLASS_SMALL - sharpness = IS_SHARP + sharpness = SHARP_POINTY var/mob/living/carbon/human/fired_by /// if we missed our target var/missed = TRUE diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm index 2df2b20cbc..1b80c18407 100644 --- a/code/datums/mutations/hulk.dm +++ b/code/datums/mutations/hulk.dm @@ -23,6 +23,24 @@ if(proximity && (act_intent == INTENT_HARM)) //no telekinetic hulk attack return target.attack_hulk(owner) +/** + *Checks damage of a hulk's arm and applies bone wounds as necessary. + * + *Called by specific atoms being attacked, such as walls. If an atom + *does not call this proc, than punching that atom will not cause + *arm breaking (even if the atom deals recoil damage to hulks). + *Arguments: + *arg1 is the arm to evaluate damage of and possibly break. + */ +/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) + if(41 to 45) + arm.force_wound_upwards(/datum/wound/blunt/severe) + if(35 to 41) + arm.force_wound_upwards(/datum/wound/blunt/moderate) + /datum/mutation/human/hulk/on_life() if(owner.health < 0) on_losing(owner) diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 561329f02a..1d2c3e46ad 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -438,7 +438,7 @@ var/still_bleeding = FALSE for(var/thing in throat.wounds) var/datum/wound/W = thing - if(W.wound_type == WOUND_LIST_CUT && W.severity > WOUND_SEVERITY_MODERATE) + if(W.wound_type == WOUND_SLASH && W.severity > WOUND_SEVERITY_MODERATE) still_bleeding = TRUE break if(!still_bleeding) diff --git a/code/datums/status_effects/wound_effects.dm b/code/datums/status_effects/wound_effects.dm index 2c0c030425..fc075201dc 100644 --- a/code/datums/status_effects/wound_effects.dm +++ b/code/datums/status_effects/wound_effects.dm @@ -117,8 +117,7 @@ /datum/status_effect/wound/on_creation(mob/living/new_owner, incoming_wound) . = ..() - var/datum/wound/W = incoming_wound - linked_wound = W + linked_wound = incoming_wound linked_limb = linked_wound.limb /datum/status_effect/wound/on_remove() @@ -140,9 +139,9 @@ // bones -/datum/status_effect/wound/bone +/datum/status_effect/wound/blunt -/datum/status_effect/wound/bone/interact_speed_modifier() +/datum/status_effect/wound/blunt/interact_speed_modifier() var/mob/living/carbon/C = owner if(C.get_active_hand() == linked_limb) @@ -151,7 +150,7 @@ return 1 -/datum/status_effect/wound/bone/nextmove_modifier() +/datum/status_effect/wound/blunt/nextmove_modifier() var/mob/living/carbon/C = owner if(C.get_active_hand() == linked_limb) @@ -159,24 +158,34 @@ return 1 -/datum/status_effect/wound/bone/moderate +/datum/status_effect/wound/blunt/moderate id = "disjoint" -/datum/status_effect/wound/bone/severe +/datum/status_effect/wound/blunt/severe id = "hairline" -/datum/status_effect/wound/bone/critical +/datum/status_effect/wound/blunt/critical id = "compound" // cuts -/datum/status_effect/wound/cut/moderate +/datum/status_effect/wound/slash/moderate id = "abrasion" -/datum/status_effect/wound/cut/severe +/datum/status_effect/wound/slash/severe id = "laceration" -/datum/status_effect/wound/cut/critical +/datum/status_effect/wound/slash/critical id = "avulsion" +// pierce +/datum/status_effect/wound/pierce/moderate + id = "breakage" + +/datum/status_effect/wound/pierce/severe + id = "puncture" + +/datum/status_effect/wound/pierce/critical + id = "rupture" + // burns /datum/status_effect/wound/burn/moderate id = "seconddeg" diff --git a/code/datums/wounds/_scars.dm b/code/datums/wounds/_scars.dm index bfbaab835e..8cd0d8a047 100644 --- a/code/datums/wounds/_scars.dm +++ b/code/datums/wounds/_scars.dm @@ -53,8 +53,12 @@ if(victim) LAZYADD(victim.all_scars, src) - description = pick(W.scarring_descriptions) - precise_location = pick(limb.specific_locations) + if(victim && victim.get_biological_state() == BIO_JUST_BONE) + description = pick(strings(BONE_SCAR_FILE, W.scar_keyword)) || "general disfigurement" + else + description = pick(strings(FLESH_SCAR_FILE, W.scar_keyword)) || "general disfigurement" + + precise_location = pick(strings(SCAR_LOC_FILE, limb.body_zone)) switch(W.severity) if(WOUND_SEVERITY_MODERATE) visibility = 2 @@ -62,6 +66,9 @@ visibility = 3 if(WOUND_SEVERITY_CRITICAL) visibility = 5 + if(WOUND_SEVERITY_LOSS) + visibility = 7 + precise_location = "amputation" /// Used when we finalize a scar from a healing cut /datum/scar/proc/lazy_attach(obj/item/bodypart/BP, datum/wound/W) @@ -71,10 +78,11 @@ LAZYADD(victim.all_scars, src) /// Used to "load" a persistent scar -/datum/scar/proc/load(obj/item/bodypart/BP, description, specific_location, severity=WOUND_SEVERITY_SEVERE) - if(!(BP.body_zone in applicable_zones)) +/datum/scar/proc/load(obj/item/bodypart/BP, version, description, specific_location, severity=WOUND_SEVERITY_SEVERE) + if(!(BP.body_zone in applicable_zones) || !BP.is_organic_limb()) qdel(src) return + limb = BP src.severity = severity LAZYADD(limb.scars, src) @@ -90,6 +98,8 @@ visibility = 3 if(WOUND_SEVERITY_CRITICAL) visibility = 5 + if(WOUND_SEVERITY_LOSS) + visibility = 7 return TRUE /// What will show up in examine_more() if this scar is visible @@ -102,9 +112,12 @@ if(WOUND_SEVERITY_MODERATE) msg = "[msg]" if(WOUND_SEVERITY_SEVERE) - msg = "[msg]" + msg = "[msg]" if(WOUND_SEVERITY_CRITICAL) - msg = "[msg]" + msg = "[msg]" + if(WOUND_SEVERITY_LOSS) + msg = "[victim.p_their(TRUE)] [limb.name] [description]." // different format + msg = "[msg]" return "\t[msg]" /// Whether a scar can currently be seen by the viewer @@ -117,12 +130,12 @@ if(!ishuman(victim) || isobserver(viewer) || victim == viewer) return TRUE - var/mob/living/carbon/human/H = victim + var/mob/living/carbon/human/human_victim = victim if(istype(limb, /obj/item/bodypart/head)) - if((H.wear_mask && (H.wear_mask.flags_inv & HIDEFACE)) || (H.head && (H.head.flags_inv & HIDEFACE))) + if((human_victim.wear_mask && (human_victim.wear_mask.flags_inv & HIDEFACE)) || (human_victim.head && (human_victim.head.flags_inv & HIDEFACE))) return FALSE else if(limb.scars_covered_by_clothes) - var/num_covers = LAZYLEN(H.clothingonpart(limb)) + var/num_covers = LAZYLEN(human_victim.clothingonpart(limb)) if(num_covers + get_dist(viewer, victim) >= visibility) return FALSE @@ -131,4 +144,9 @@ /// Used to format a scar to safe in preferences for persistent scars /datum/scar/proc/format() if(!fake) - return "[limb.body_zone]|[description]|[precise_location]|[severity]" + return "[SCAR_CURRENT_VERSION]|[limb.body_zone]|[description]|[precise_location]|[severity]" + +/// Used to format a scar to safe in preferences for persistent scars +/datum/scar/proc/format_amputated(body_zone) + description = pick(list("is several skintone shades paler than the rest of the body", "is a gruesome patchwork of artificial flesh", "has a large series of attachment scars at the articulation points")) + return "[SCAR_CURRENT_VERSION]|[body_zone]|[description]|amputated|[WOUND_SEVERITY_LOSS]" \ No newline at end of file diff --git a/code/datums/wounds/_wounds.dm b/code/datums/wounds/_wounds.dm index b1ba49b7ab..29c87b32d4 100644 --- a/code/datums/wounds/_wounds.dm +++ b/code/datums/wounds/_wounds.dm @@ -33,15 +33,13 @@ /// 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_BONE, WOUND_LIST_CUT, or WOUND_LIST_BURN + /// The list of wounds it belongs in, WOUND_LIST_BLUNT, WOUND_LIST_SLASH, or WOUND_LIST_BURN var/wound_type /// 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 - /// If we only work on organics (everything right now) - var/organic_only = TRUE /// The bodypart we're parented to var/obj/item/bodypart/limb = null @@ -51,8 +49,6 @@ var/list/treatable_by_grabbed /// Tools with the specified tool flag will also be able to try directly treating this wound var/treatable_tool - /// Set to TRUE if we don't give a shit about the patient's comfort and are allowed to just use any random sharp thing on this wound. Will require an aggressive grab or more to perform - var/treatable_sharp /// How long it will take to treat this wound with a standard effective tool, assuming it doesn't need surgery var/base_treat_time = 5 SECONDS @@ -65,17 +61,13 @@ /// How much we're contributing to this limb's bleed_rate var/blood_flow - /// The minimum we need to roll on [/obj/item/bodypart/proc/check_wounding()] to begin suffering this wound, see check_wounding_mods() for more + /// The minimum we need to roll on [/obj/item/bodypart/proc/check_wounding] to begin suffering this wound, see check_wounding_mods() for more var/threshold_minimum /// How much having this wound will add to all future check_wounding() rolls on this limb, to allow progression to worse injuries with repeated damage var/threshold_penalty /// If we need to process each life tick var/processes = FALSE - /// If TRUE and an item that can treat multiple different types of coexisting wounds (gauze can be used to splint broken bones, staunch bleeding, and cover burns), we get first dibs if we come up first for it, then become nonpriority. - /// Otherwise, if no untreated wound claims the item, we cycle through the non priority wounds and pick a random one who can use that item. - var/treat_priority = FALSE - /// If having this wound makes currently makes the parent bodypart unusable var/disabling @@ -89,12 +81,15 @@ var/cryo_progress /// What kind of scars this wound will create description wise once healed - var/list/scarring_descriptions = list("general disfigurement") + var/scar_keyword = "generic" /// If we've already tried scarring while removing (since remove_wound calls qdel, and qdel calls remove wound, .....) TODO: make this cleaner var/already_scarred = FALSE /// If we forced this wound through badmin smite, we won't count it towards the round totals var/from_smite + /// What flags apply to this wound + var/wound_flags = (FLESH_WOUND | BONE_WOUND | ACCEPTS_GAUZE) + /datum/wound/Destroy() if(attached_surgery) QDEL_NULL(attached_surgery) @@ -115,13 +110,13 @@ * * smited- If this is a smite, we don't care about this wound for stat tracking purposes (not yet implemented) */ /datum/wound/proc/apply_wound(obj/item/bodypart/L, silent = FALSE, datum/wound/old_wound = null, smited = FALSE) - if(!istype(L) || !L.owner || !(L.body_zone in viable_zones) || isalien(L.owner)) + if(!istype(L) || !L.owner || !(L.body_zone in viable_zones) || isalien(L.owner) || !L.is_organic_limb()) qdel(src) return if(ishuman(L.owner)) var/mob/living/carbon/human/H = L.owner - if(organic_only && ((NOBLOOD in H.dna.species.species_traits) || !L.is_organic_limb())) + if(((wound_flags & BONE_WOUND) && !(HAS_BONE in H.dna.species.species_traits)) || ((wound_flags & FLESH_WOUND) && !(HAS_FLESH in H.dna.species.species_traits))) qdel(src) return @@ -161,7 +156,7 @@ victim.visible_message(msg, "Your [limb.name] [occur_text]!", vision_distance = vis_dist) if(sound_effect) - playsound(L.owner, sound_effect, 60 + 20 * severity, TRUE) + playsound(L.owner, sound_effect, 70 + 20 * severity, TRUE) if(!demoted) wound_injury(old_wound) @@ -181,7 +176,7 @@ SEND_SIGNAL(victim, COMSIG_CARBON_LOSE_WOUND, src, limb) if(limb && !ignore_limb) LAZYREMOVE(limb.wounds, src) - limb.update_wounds() + limb.update_wounds(replaced) /** * 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) @@ -189,7 +184,7 @@ * 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/brute/cut/severe + * * new_type- The TYPE PATH of the wound you want to replace this, like /datum/wound/slash/severe * * 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) @@ -206,7 +201,6 @@ /// Additional beneficial effects when the wound is gained, in case you want to give a temporary boost to allow the victim to try an escape or last stand /datum/wound/proc/second_wind() - switch(severity) if(WOUND_SEVERITY_MODERATE) victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_MODERATE) @@ -214,11 +208,13 @@ victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_SEVERE) if(WOUND_SEVERITY_CRITICAL) victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_CRITICAL) + if(WOUND_SEVERITY_LOSS) + victim.reagents.add_reagent(/datum/reagent/determination, WOUND_DETERMINATION_LOSS) /** - * try_treating() is an intercept run from [/mob/living/carbon/attackby()] right after surgeries but before anything else. Return TRUE here if the item is something that is relevant to treatment to take over the interaction. + * try_treating() is an intercept run from [/mob/living/carbon/proc/attackby] right after surgeries but before anything else. Return TRUE here if the item is something that is relevant to treatment to take over the interaction. * - * This proc leads into [/datum/wound/proc/treat()] and probably shouldn't be added onto in children types. You can specify what items or tools you want to be intercepted + * This proc leads into [/datum/wound/proc/treat] and probably shouldn't be added onto in children types. You can specify what items or tools you want to be intercepted * with var/list/treatable_by and var/treatable_tool, then if an item fulfills one of those requirements and our wound claims it first, it goes over to treat() and treat_self(). * * Arguments: @@ -258,7 +254,7 @@ treat(I, user) 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()] +/// 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) return FALSE @@ -288,10 +284,22 @@ if(cryo_progress > 33 * severity) qdel(src) +/// When synthflesh is applied to the victim, we call this. No sense in setting up an entire chem reaction system for wounds when we only care for a few chems. Probably will change in the future +/datum/wound/proc/on_synthflesh(power) + return + +/// Called when the patient is undergoing stasis, so that having fully treated a wound doesn't make you sit there helplessly until you think to unbuckle them +/datum/wound/proc/on_stasis() + return + /// Called when we're crushed in an airlock or firedoor, for one of the improvised joint dislocation fixes /datum/wound/proc/crush() return +/// Used when we're being dragged while bleeding, the value we return is how much bloodloss this wound causes from being dragged. Since it's a proc, you can let bandages soak some of the blood +/datum/wound/proc/drag_bleed_amount() + return + /** * get_examine_description() is used in carbon/examine and human/examine to show the status of this wound. Useful if you need to show some status like the wound being splinted or bandaged. * @@ -301,7 +309,8 @@ * * mob/user: The user examining the wound's owner, if that matters */ /datum/wound/proc/get_examine_description(mob/user) - return "[victim.p_their(TRUE)] [limb.name] [examine_desc]!" + . = "[victim.p_their(TRUE)] [limb.name] [examine_desc]" + . = severity <= WOUND_SEVERITY_MODERATE ? "[.]." : "[.]!" /datum/wound/proc/get_scanner_description(mob/user) return "Type: [name]\nSeverity: [severity_text()]\nDescription: [desc]\nRecommended Treatment: [treat_text]" diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index 80d922cba3..41e4e025ab 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -1,4 +1,3 @@ - /* Bones */ @@ -7,12 +6,10 @@ /* Base definition */ -/datum/wound/brute/bone - sound_effect = 'sound/effects/crack1.ogg' - wound_type = WOUND_LIST_BONE - - /// The item we're currently splinted with, if there is one - var/obj/item/stack/splinted +/datum/wound/blunt + sound_effect = 'sound/effects/wounds/crack1.ogg' + wound_type = WOUND_BLUNT + wound_flags = (BONE_WOUND | ACCEPTS_GAUZE) /// Have we been taped? var/taped @@ -31,12 +28,12 @@ /// 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/chance_internal_bleeding = 0 + var/internal_bleeding_chance = 0 /* Overwriting of base procs */ -/datum/wound/brute/bone/wound_injury(datum/wound/old_wound = null) +/datum/wound/blunt/wound_injury(datum/wound/old_wound = null) if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group) processes = TRUE active_trauma = victim.gain_trauma_type(brain_trauma_group, TRAUMA_RESILIENCE_WOUND) @@ -53,14 +50,14 @@ update_inefficiencies() -/datum/wound/brute/bone/remove_wound(ignore_limb, replaced) +/datum/wound/blunt/remove_wound(ignore_limb, replaced) limp_slowdown = 0 QDEL_NULL(active_trauma) if(victim) UnregisterSignal(victim, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) return ..() -/datum/wound/brute/bone/handle_process() +/datum/wound/blunt/handle_process() . = ..() if(limb.body_zone == BODY_ZONE_HEAD && brain_trauma_group && world.time > next_trauma_cycle) if(active_trauma) @@ -86,7 +83,7 @@ remove_wound() /// If we're a human who's punching something with a broken arm, we might hurt ourselves doing so -/datum/wound/brute/bone/proc/attack_with_hurt_hand(mob/M, atom/target, proximity) +/datum/wound/blunt/proc/attack_with_hurt_hand(mob/M, atom/target, proximity) if(victim.get_active_hand() != limb || victim.a_intent == INTENT_HELP || !ismob(target) || severity <= WOUND_SEVERITY_MODERATE) return @@ -104,61 +101,54 @@ limb.receive_damage(brute=rand(3,7)) return COMPONENT_NO_ATTACK_HAND -/datum/wound/brute/bone/receive_damage(wounding_type, wounding_dmg, wound_bonus) - if(!victim) +/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(NOBLOOD in human_victim.dna?.species.species_traits) + return - if(limb.body_zone == BODY_ZONE_CHEST && victim.blood_volume && prob(chance_internal_bleeding + wounding_dmg)) + 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("[victim] coughs up a bit of blood from the blow to [victim.p_their()] chest.", "You cough up a bit of blood from the blow to your chest.") + victim.visible_message("[victim] coughs up a bit of blood from the blow to [victim.p_their()] chest.", "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("[victim] spits out a string of blood from the blow to [victim.p_their()] chest!", "You spit out a string of blood from the blow to your chest!") + victim.visible_message("[victim] spits out a string of blood from the blow to [victim.p_their()] chest!", "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("[victim] chokes up a spray of blood from the blow to [victim.p_their()] chest!", "You choke up on a spray of blood from the blow to your chest!") + victim.visible_message("[victim] chokes up a spray of blood from the blow to [victim.p_their()] chest!", "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)) - if(!(wounding_type in list(WOUND_SHARP, WOUND_BURN)) || !splinted || wound_bonus == CANT_WOUND) - return - splinted.take_damage(wounding_dmg, damage_type = (wounding_type == WOUND_SHARP ? BRUTE : BURN), sound_effect = FALSE) - if(QDELETED(splinted)) - var/destroyed_verb = (wounding_type == WOUND_SHARP ? "torn" : "burned") - victim.visible_message("The splint securing [victim]'s [limb.name] is [destroyed_verb] away!", "The splint securing your [limb.name] is [destroyed_verb] away!", vision_distance=COMBAT_MESSAGE_RANGE) - splinted = null - treat_priority = TRUE - update_inefficiencies() - - -/datum/wound/brute/bone/get_examine_description(mob/user) - if(!splinted && !gelled && !taped) +/datum/wound/blunt/get_examine_description(mob/user) + if(!limb.current_gauze && !gelled && !taped) return ..() - var/msg = "" - if(!splinted) - msg = "[victim.p_their(TRUE)] [limb.name] [examine_desc]" + var/list/msg = list() + if(!limb.current_gauze) + msg += "[victim.p_their(TRUE)] [limb.name] [examine_desc]" else - var/splint_condition = "" + var/sling_condition = "" // how much life we have left in these bandages - switch(splinted.obj_integrity / splinted.max_integrity * 100) + switch(limb.current_gauze.obj_integrity / limb.current_gauze.max_integrity * 100) if(0 to 25) - splint_condition = "just barely " + sling_condition = "just barely " if(25 to 50) - splint_condition = "loosely " + sling_condition = "loosely " if(50 to 75) - splint_condition = "mostly " + sling_condition = "mostly " if(75 to INFINITY) - splint_condition = "tightly " + sling_condition = "tightly " - msg = "[victim.p_their(TRUE)] [limb.name] is [splint_condition] fastened in a splint of [splinted.name]" + msg += "[victim.p_their(TRUE)] [limb.name] is [sling_condition] fastened in a sling of [limb.current_gauze.name]" if(taped) msg += ", and appears to be reforming itself under some surgical tape!" @@ -166,58 +156,35 @@ msg += ", with fizzing flecks of blue bone gel sparking off the bone!" else msg += "!" - return "[msg]" + return "[msg.Join()]" /* - New common procs for /datum/wound/brute/bone/ + New common procs for /datum/wound/blunt/ */ -/datum/wound/brute/bone/proc/update_inefficiencies() +/datum/wound/blunt/proc/update_inefficiencies() if(limb.body_zone in list(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)) - if(splinted) - limp_slowdown = initial(limp_slowdown) * splinted.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(STATUS_EFFECT_LIMP) else if(limb.body_zone in list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM)) - if(splinted) - interaction_efficiency_penalty = 1 + ((interaction_efficiency_penalty - 1) * splinted.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) && splinted) - disabling = FALSE - else if(initial(disabling)) - disabling = TRUE + if(initial(disabling)) + disabling = !limb.current_gauze limb.update_wounds() -/* - BEWARE OF REDUNDANCY AHEAD THAT I MUST PARE DOWN -*/ - -/datum/wound/brute/bone/proc/splint(obj/item/stack/I, mob/user) - if(splinted && splinted.splint_factor >= I.splint_factor) - to_chat(user, "The splint already on [user == victim ? "your" : "[victim]'s"] [limb.name] is better than you can do with [I].") - return - - user.visible_message("[user] begins splinting [victim]'s [limb.name] with [I].", "You begin splinting [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") - - if(!do_after(user, base_treat_time * (user == victim ? 1.5 : 1), target = victim, extra_checks=CALLBACK(src, .proc/still_exists))) - return - - user.visible_message("[user] finishes splinting [victim]'s [limb.name]!", "You finish splinting [user == victim ? "your" : "[victim]'s"] [limb.name]!") - treat_priority = FALSE - splinted = new I.type(limb) - splinted.amount = 1 - I.use(1) - update_inefficiencies() - /* Moderate (Joint Dislocation) */ -/datum/wound/brute/bone/moderate +/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." @@ -230,15 +197,16 @@ threshold_minimum = 35 threshold_penalty = 15 treatable_tool = TOOL_BONESET - status_effect_type = /datum/status_effect/wound/bone/moderate - scarring_descriptions = list("light discoloring", "a slight blue tint") + wound_flags = (BONE_WOUND) + status_effect_type = /datum/status_effect/wound/blunt/moderate + scar_keyword = "bluntmoderate" -/datum/wound/brute/bone/moderate/crush() +/datum/wound/blunt/moderate/crush() if(prob(33)) victim.visible_message("[victim]'s dislocated [limb.name] pops back into place!", "Your dislocated [limb.name] pops back into place! Ow!") remove_wound() -/datum/wound/brute/bone/moderate/try_handling(mob/living/carbon/human/user) +/datum/wound/blunt/moderate/try_handling(mob/living/carbon/human/user) if(user.pulling != victim || user.zone_selected != limb.body_zone || user.a_intent == INTENT_GRAB) return FALSE @@ -256,7 +224,7 @@ return TRUE /// If someone is snapping our dislocated joint back into place by hand with an aggro grab and help intent -/datum/wound/brute/bone/moderate/proc/chiropractice(mob/living/carbon/human/user) +/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/still_exists))) @@ -275,7 +243,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/brute/bone/moderate/proc/malpractice(mob/living/carbon/human/user) +/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/still_exists))) @@ -293,7 +261,7 @@ malpractice(user) -/datum/wound/brute/bone/moderate/treat(obj/item/I, mob/user) +/datum/wound/blunt/moderate/treat(obj/item/I, mob/user) if(victim == user) victim.visible_message("[user] begins resetting [victim.p_their()] [limb.name] with [I].", "You begin resetting your [limb.name] with [I]...") else @@ -317,56 +285,57 @@ Severe (Hairline Fracture) */ -/datum/wound/brute/bone/severe +/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 splinting will prevent worsening situation." - examine_desc = "appears bruised and grotesquely swollen" - + 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/gauze, /obj/item/stack/medical/bone_gel) - status_effect_type = /datum/status_effect/wound/bone/severe - treat_priority = TRUE - scarring_descriptions = list("a faded, fist-sized bruise", "a vaguely triangular peel scar") + 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 - chance_internal_bleeding = 40 + internal_bleeding_chance = 40 + wound_flags = (BONE_WOUND | ACCEPTS_GAUZE | MANGLES_BONE) -/datum/wound/brute/bone/critical +/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 = "has a cracked bone sticking out of it" + 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/crack2.ogg' + 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/gauze, /obj/item/stack/medical/bone_gel) - status_effect_type = /datum/status_effect/wound/bone/critical - treat_priority = TRUE - scarring_descriptions = list("a section of janky skin lines and badly healed scars", "a large patch of uneven skin tone", "a cluster of calluses") + 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 - chance_internal_bleeding = 60 + internal_bleeding_chance = 60 + wound_flags = (BONE_WOUND | ACCEPTS_GAUZE | MANGLES_BONE) // doesn't make much sense for "a" bone to stick out of your head -/datum/wound/brute/bone/critical/apply_wound(obj/item/bodypart/L, silent, datum/wound/old_wound, smited) +/datum/wound/blunt/critical/apply_wound(obj/item/bodypart/L, silent, datum/wound/old_wound, smited) 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/brute/bone/proc/gel(obj/item/stack/medical/bone_gel/I, mob/user) +/datum/wound/blunt/proc/gel(obj/item/stack/medical/bone_gel/I, mob/user) if(gelled) to_chat(user, "[user == victim ? "Your" : "[victim]'s"] [limb.name] is already coated with bone gel!") return @@ -385,12 +354,12 @@ var/painkiller_bonus = 0 if(victim.drunkenness) painkiller_bonus += 5 - if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/medicine/morphine)) + if(victim.reagents?.has_reagent(/datum/reagent/medicine/morphine)) painkiller_bonus += 10 - if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/determination)) + if(victim.reagents?.has_reagent(/datum/reagent/determination)) painkiller_bonus += 5 - if(prob(25 + (20 * (severity - 2)) - painkiller_bonus)) // 25%/45% chance to fail self-applying with severe and critical wounds, modded by painkillers + 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("[victim] fails to finish applying [I] to [victim.p_their()] [limb.name], passing out from the pain!", "You black out from the pain of applying [I] to your [limb.name] before you can finish!") victim.AdjustUnconscious(5 SECONDS) return @@ -401,7 +370,7 @@ gelled = TRUE /// if someone is using surgical tape on our wound -/datum/wound/brute/bone/proc/tape(obj/item/stack/sticky_tape/surgical/I, mob/user) +/datum/wound/blunt/proc/tape(obj/item/stack/sticky_tape/surgical/I, mob/user) if(!gelled) to_chat(user, "[user == victim ? "Your" : "[victim]'s"] [limb.name] must be coated with bone gel to perform this emergency operation!") return @@ -426,15 +395,13 @@ taped = TRUE processes = TRUE -/datum/wound/brute/bone/treat(obj/item/I, mob/user) +/datum/wound/blunt/treat(obj/item/I, mob/user) if(istype(I, /obj/item/stack/medical/bone_gel)) gel(I, user) else if(istype(I, /obj/item/stack/sticky_tape/surgical)) tape(I, user) - else if(istype(I, /obj/item/stack/medical/gauze)) - splint(I, user) -/datum/wound/brute/bone/get_scanner_description(mob/user) +/datum/wound/blunt/get_scanner_description(mob/user) . = ..() . += "
" @@ -444,7 +411,7 @@ else if(!taped) . += "Continue Alternative Treatment: Apply surgical tape directly to injured limb to begin bone regeneration. Note, this is both excruciatingly painful and slow.\n" else - . += "Note: Bone regeneration in effect. Bone is [round((regen_points_current*100)/regen_points_needed,0.1)]% regenerated.\n" + . += "Note: Bone regeneration in effect. Bone is [round(regen_points_current*100/regen_points_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." diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm index 6a6629a0c9..0d66ee4cfb 100644 --- a/code/datums/wounds/burns.dm +++ b/code/datums/wounds/burns.dm @@ -1,14 +1,14 @@ - // 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 a_or_from = "from" - wound_type = WOUND_LIST_BURN + wound_type = WOUND_BURN processes = TRUE - sound_effect = 'sound/effects/sizzle1.ogg' + sound_effect = 'sound/effects/wounds/sizzle1.ogg' + wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE) - treatable_by = list(/obj/item/stack/medical/gauze, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) // sterilizer and alcohol will require reagent treatments, coming soon + 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 @@ -27,8 +27,6 @@ /// 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 - /// The current bandage we have for this wound (maybe move bandages to the limb?) - var/obj/item/stack/current_bandage /datum/wound/burn/handle_process() . = ..() @@ -47,15 +45,11 @@ sanitization += 0.3 flesh_healing += 0.5 - if(current_bandage) - current_bandage.absorption_capacity -= WOUND_BURN_SANITIZATION_RATE - if(current_bandage.absorption_capacity <= 0) - victim.visible_message("Pus soaks through \the [current_bandage] on [victim]'s [limb.name].", "Pus soaks through \the [current_bandage] on your [limb.name].", vision_distance=COMBAT_MESSAGE_RANGE) - QDEL_NULL(current_bandage) - treat_priority = TRUE + if(limb.current_gauze) + limb.seep_gauze(WOUND_BURN_SANITIZATION_RATE) if(flesh_healing > 0) - var/bandage_factor = (current_bandage ? current_bandage.splint_factor : 1) + var/bandage_factor = (limb.current_gauze ? limb.current_gauze.splint_factor : 1) flesh_damage = max(0, flesh_damage - 1) flesh_healing = max(0, flesh_healing - bandage_factor) // good bandages multiply the length of flesh healing @@ -67,7 +61,7 @@ // sanitization is checked after the clearing check but before the rest, because we freeze the effects of infection while we have sanitization if(sanitization > 0) - var/bandage_factor = (current_bandage ? current_bandage.splint_factor : 1) + var/bandage_factor = (limb.current_gauze ? limb.current_gauze.splint_factor : 1) infestation = max(0, infestation - WOUND_BURN_SANITIZATION_RATE) sanitization = max(0, sanitization - (WOUND_BURN_SANITIZATION_RATE * bandage_factor)) return @@ -122,10 +116,10 @@ if(strikes_to_lose_limb <= 0) return "[victim.p_their(TRUE)] [limb.name] is completely dead and unrecognizable as organic." - var/condition = "" - if(current_bandage) + var/list/condition = list("[victim.p_their(TRUE)] [limb.name] [examine_desc]") + if(limb.current_gauze) var/bandage_condition - switch(current_bandage.absorption_capacity) + switch(limb.current_gauze.absorption_capacity) if(0 to 1.25) bandage_condition = "nearly ruined " if(1.25 to 2.75) @@ -135,7 +129,7 @@ if(4 to INFINITY) bandage_condition = "clean " - condition += " underneath a dressing of [bandage_condition] [current_bandage.name]" + condition += " underneath a dressing of [bandage_condition] [limb.current_gauze.name]" else switch(infestation) if(WOUND_INFECTION_MODERATE to WOUND_INFECTION_SEVERE) @@ -149,7 +143,7 @@ else condition += "!" - return "[victim.p_their(TRUE)] [limb.name] [examine_desc][condition]" + return "[condition.Join()]" /datum/wound/burn/get_scanner_description(mob/user) if(strikes_to_lose_limb == 0) @@ -186,7 +180,7 @@ /// if someone is using ointment on our burns /datum/wound/burn/proc/ointment(obj/item/stack/medical/ointment/I, mob/user) user.visible_message("[user] begins applying [I] to [victim]'s [limb.name]...", "You begin applying [I] to [user == victim ? "your" : "[victim]'s"] [limb.name]...") - if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), target = victim)) + if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), extra_checks = CALLBACK(src, .proc/still_exists))) return limb.heal_damage(I.heal_brute, I.heal_burn) @@ -200,36 +194,6 @@ else try_treating(I, user) -/// for use in the burn dressing surgery since we don't want to make them do another do_after obviously -/datum/wound/burn/proc/force_bandage(obj/item/stack/medical/gauze/I, mob/user) - QDEL_NULL(current_bandage) - current_bandage = new I.type(limb) - current_bandage.amount = 1 - treat_priority = FALSE - sanitization += I.sanitization - I.use(1) - -/// if someone is wrapping gauze on our burns -/datum/wound/burn/proc/bandage(obj/item/stack/medical/gauze/I, mob/user) - if(current_bandage) - if(current_bandage.absorption_capacity > I.absorption_capacity + 1) - to_chat(user, "The [current_bandage] on [victim]'s [limb.name] is still in better condition than your [I.name]!") - return - user.visible_message("[user] begins to redress the burns on [victim]'s [limb.name] with [I]...", "You begin redressing the burns on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") - else - user.visible_message("[user] begins to dress the burns on [victim]'s [limb.name] with [I]...", "You begin dressing the burns on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") - - if(!do_after(user, (user == victim ? I.self_delay : I.other_delay), target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) - return - - user.visible_message("[user] applies [I] to [victim].", "You apply [I] to [user == victim ? "your" : "[victim]'s"] [limb.name].") - QDEL_NULL(current_bandage) - current_bandage = new I.type(limb) - current_bandage.amount = 1 - treat_priority = FALSE - sanitization += I.sanitization - I.use(1) - /// if someone is using mesh on our burns /datum/wound/burn/proc/mesh(obj/item/stack/medical/mesh/I, mob/user) user.visible_message("[user] begins wrapping [victim]'s [limb.name] with [I]...", "You begin wrapping [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") @@ -249,7 +213,7 @@ /// Paramedic UV penlights /datum/wound/burn/proc/uv(obj/item/flashlight/pen/paramedic/I, mob/user) - if(I.uv_cooldown > world.time) + if(!COOLDOWN_FINISHED(I, uv_cooldown)) to_chat(user, "[I] is still recharging!") return if(infestation <= 0 || infestation < sanitization) @@ -258,20 +222,29 @@ user.visible_message("[user] flashes the burns on [victim]'s [limb] with [I].", "You flash the burns on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I].", vision_distance=COMBAT_MESSAGE_RANGE) sanitization += I.uv_power - I.uv_cooldown = world.time + I.uv_cooldown_length + COOLDOWN_START(I, uv_cooldown, I.uv_cooldown_length) /datum/wound/burn/treat(obj/item/I, mob/user) - if(istype(I, /obj/item/stack/medical/gauze)) - bandage(I, user) - else if(istype(I, /obj/item/stack/medical/ointment)) + if(istype(I, /obj/item/stack/medical/ointment)) ointment(I, user) else if(istype(I, /obj/item/stack/medical/mesh)) mesh(I, user) else if(istype(I, /obj/item/flashlight/pen/paramedic)) uv(I, user) -/// basic support for instabitaluri/synthflesh healing flesh damage, more chem support in the future -/datum/wound/burn/proc/regenerate_flesh(amount) +// 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 <= 1)) + to_chat(victim, "The burns on your [limb.name] 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 @@ -287,7 +260,7 @@ 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 - scarring_descriptions = list("small amoeba-shaped skinmarks", "a faded streak of depressed skin") + scar_keyword = "burnmoderate" /datum/wound/burn/severe name = "Third Degree Burns" @@ -300,10 +273,10 @@ 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/gauze, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) + 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 - scarring_descriptions = list("a large, jagged patch of faded skin", "random spots of shiny, smooth skin", "spots of taut, leathery skin") + scar_keyword = "burnsevere" /datum/wound/burn/critical name = "Catastrophic Burns" @@ -313,11 +286,11 @@ 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/sizzle2.ogg' + 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/gauze, /obj/item/stack/medical/ointment, /obj/item/stack/medical/mesh) + 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 - scarring_descriptions = list("massive, disfiguring keloid scars", "several long streaks of badly discolored and malformed skin", "unmistakeable splotches of dead tissue from serious burns") + scar_keyword = "burncritical" diff --git a/code/datums/wounds/loss.dm b/code/datums/wounds/loss.dm new file mode 100644 index 0000000000..6c5e536fb2 --- /dev/null +++ b/code/datums/wounds/loss.dm @@ -0,0 +1,41 @@ +/datum/wound/loss + name = "Dismembered" + desc = "oof ouch!!" + + sound_effect = 'sound/effects/dismember.ogg' + severity = WOUND_SEVERITY_LOSS + threshold_minimum = 180 + status_effect_type = null + scar_keyword = "dismember" + wound_flags = null + +/// 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) + if(!istype(dismembered_part) || !dismembered_part.owner || !(dismembered_part.body_zone in viable_zones) || isalien(dismembered_part.owner) || !dismembered_part.can_dismember()) + qdel(src) + return + + already_scarred = TRUE // so we don't scar a limb we don't have. If I add different levels of amputation desc, do it here + + switch(wounding_type) + if(WOUND_BLUNT) + occur_text = "is shattered through the last bone holding it together, severing it completely!" + if(WOUND_SLASH) + occur_text = "is slashed through the last tissue holding it together, severing it completely!" + if(WOUND_PIERCE) + occur_text = "is pierced through the last tissue holding it together, severing it completely!" + if(WOUND_BURN) + occur_text = "is completely incinerated, falling to dust!" + + victim = dismembered_part.owner + + var/msg = "[victim]'s [dismembered_part.name] [occur_text]!" + + victim.visible_message(msg, "Your [dismembered_part.name] [occur_text]!") + + limb = dismembered_part + severity = WOUND_SEVERITY_LOSS + second_wind() + log_wound(victim, src) + dismembered_part.dismember(wounding_type == WOUND_BURN ? BURN : BRUTE) + qdel(src) diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm new file mode 100644 index 0000000000..3182c334bf --- /dev/null +++ b/code/datums/wounds/pierce.dm @@ -0,0 +1,170 @@ +/* + Pierce +*/ + +/datum/wound/pierce + 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/pierce/wound_injury(datum/wound/old_wound) + 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_gauze && limb.current_gauze.splint_factor) + wounding_dmg *= (1 - limb.current_gauze.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("Blood droplets fly from the hole in [victim]'s [limb.name].", "You cough up a bit of blood from the blow to your [limb.name].", vision_distance=COMBAT_MESSAGE_RANGE) + victim.bleed(blood_bled, TRUE) + if(14 to 19) + victim.visible_message("A small stream of blood spurts from the hole in [victim]'s [limb.name]!", "You spit out a string of blood from the blow to your [limb.name]!", 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("A spray of blood streams from the gash in [victim]'s [limb.name]!", "You choke up on a spray of blood from the blow to your [limb.name]!", 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/handle_process() + blood_flow = min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW) + + if(victim.bodytemperature < (BODYTEMP_NORMAL - 10)) + blood_flow -= 0.2 + if(prob(5)) + to_chat(victim, "You feel the [lowertext(name)] in your [limb.name] firming up from the cold!") + + if(victim.reagents?.has_reagent(/datum/reagent/toxin/heparin)) + blood_flow += 0.5 // old herapin 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) + blood_flow -= limb.current_gauze.absorption_rate * gauzed_clot_rate + limb.current_gauze.absorption_capacity -= limb.current_gauze.absorption_rate + + if(blood_flow <= 0) + qdel(src) + +/datum/wound/pierce/on_stasis() + . = ..() + if(blood_flow <= 0) + qdel(src) + +/datum/wound/pierce/treat(obj/item/I, mob/user) + if(istype(I, /obj/item/stack/medical/suture)) + suture(I, user) + else if(I.tool_behaviour == TOOL_CAUTERY || I.get_temperature() > 300) + tool_cauterize(I, user) + +/datum/wound/pierce/on_xadone(power) + . = ..() + 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) + . = ..() + 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 cut +/datum/wound/pierce/proc/suture(obj/item/stack/medical/suture/I, mob/user) + var/self_penalty_mult = (user == victim ? 1.4 : 1) + user.visible_message("[user] begins stitching [victim]'s [limb.name] with [I]...", "You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") + if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) + return + user.visible_message("[user] stitches up some of the bleeding on [victim].", "You stitch up some of the bleeding on [user == victim ? "yourself" : "[victim]"].") + var/blood_sutured = I.stop_bleeding / self_penalty_mult * 0.5 + blood_flow -= blood_sutured + limb.heal_damage(I.heal_brute, I.heal_burn) + + if(blood_flow > 0) + try_treating(I, user) + else + to_chat(user, "You successfully close the hole in [user == victim ? "your" : "[victim]'s"] [limb.name].") + +/// 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) + var/self_penalty_mult = (user == victim ? 1.5 : 1) + user.visible_message("[user] begins cauterizing [victim]'s [limb.name] with [I]...", "You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") + if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) + return + + user.visible_message("[user] cauterizes some of the bleeding on [victim].", "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) * 0.5 + blood_flow -= blood_cauterized + + if(blood_flow > 0) + try_treating(I, 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 = 15 + 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 = 25 + 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 = 40 + status_effect_type = /datum/status_effect/wound/pierce/critical + scar_keyword = "piercecritical" + wound_flags = (FLESH_WOUND | ACCEPTS_GAUZE | MANGLES_FLESH) diff --git a/code/datums/wounds/cuts.dm b/code/datums/wounds/slash.dm similarity index 60% rename from code/datums/wounds/cuts.dm rename to code/datums/wounds/slash.dm index 0ab3bbd5f8..5254fc3e73 100644 --- a/code/datums/wounds/cuts.dm +++ b/code/datums/wounds/slash.dm @@ -1,17 +1,16 @@ - /* Cuts */ -/datum/wound/brute/cut +/datum/wound/slash sound_effect = 'sound/weapons/slice.ogg' processes = TRUE - wound_type = WOUND_LIST_CUT - treatable_by = list(/obj/item/stack/medical/suture, /obj/item/stack/medical/gauze) + 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 - treat_priority = TRUE 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 @@ -27,75 +26,82 @@ var/max_per_type /// The maximum flow we've had so far var/highest_flow - /// How much flow we've already cauterized - var/cauterized - /// How much flow we've already sutured - var/sutured - /// The current bandage we have for this wound (maybe move bandages to the limb?) - var/obj/item/stack/current_bandage /// 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/brute/cut/wound_injury(datum/wound/brute/cut/old_wound = null) +/datum/wound/slash/wound_injury(datum/wound/slash/old_wound = null) blood_flow = initial_flow if(old_wound) 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 - if(old_wound.current_bandage) - current_bandage = old_wound.current_bandage - old_wound.current_bandage = null if(!highest_scar) highest_scar = new highest_scar.generate(limb, src, add_to_scars=FALSE) -/datum/wound/brute/cut/remove_wound(ignore_limb, replaced) +/datum/wound/slash/remove_wound(ignore_limb, replaced) if(!replaced && highest_scar) already_scarred = TRUE highest_scar.lazy_attach(limb) return ..() -/datum/wound/brute/cut/get_examine_description(mob/user) - if(!current_bandage) +/datum/wound/slash/get_examine_description(mob/user) + if(!limb.current_gauze) return ..() - var/bandage_condition = "" + var/list/msg = list("The cuts on [victim.p_their()] [limb.name] are wrapped with") // how much life we have left in these bandages - switch(current_bandage.absorption_capacity) + switch(limb.current_gauze.absorption_capacity) if(0 to 1.25) - bandage_condition = "nearly ruined " + msg += "nearly ruined " if(1.25 to 2.75) - bandage_condition = "badly worn " + msg += "badly worn " if(2.75 to 4) - bandage_condition = "slightly bloodied " + msg += "slightly bloodied " if(4 to INFINITY) - bandage_condition = "clean " - return "The cuts on [victim.p_their()] [limb.name] are wrapped with [bandage_condition] [current_bandage.name]!" + msg += "clean " + msg += "[limb.current_gauze.name]!" -/datum/wound/brute/cut/receive_damage(wounding_type, wounding_dmg, wound_bonus) - if(victim.stat != DEAD && wounding_type == WOUND_SHARP) // can't stab dead bodies to make it bleed faster this way + return "[msg.Join()]" + +/datum/wound/slash/receive_damage(wounding_type, wounding_dmg, wound_bonus) + if(victim.stat != DEAD && wounding_type == WOUND_SLASH) // can't stab dead bodies to make it bleed faster this way blood_flow += 0.05 * wounding_dmg -/datum/wound/brute/cut/handle_process() - blood_flow = min(blood_flow, WOUND_CUT_MAX_BLOODFLOW) +/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(victim.reagents && victim.reagents.has_reagent(/datum/reagent/toxin/heparin)) + if(limb.current_gauze) // gauze stops all bleeding from dragging on this limb, but wears the gauze out quicker + limb.seep_gauze(bleed_amt * 0.33) + return + + return bleed_amt + +/datum/wound/slash/handle_process() + if(victim.stat == DEAD) + blood_flow -= max(clot_rate, WOUND_SLASH_DEAD_CLOT_MIN) + if(blood_flow < minimum_flow) + if(demotes_to) + replace_wound(demotes_to) + return + qdel(src) + return + + blood_flow = min(blood_flow, WOUND_SLASH_MAX_BLOODFLOW) + + if(victim.reagents?.has_reagent(/datum/reagent/toxin/heparin)) blood_flow += 0.5 // old herapin 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 - else if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/medicine/coagulant)) - blood_flow -= 0.25 - if(current_bandage) + if(limb.current_gauze) if(clot_rate > 0) blood_flow -= clot_rate - blood_flow -= current_bandage.absorption_rate - current_bandage.absorption_capacity -= current_bandage.absorption_rate - if(current_bandage.absorption_capacity < 0) - victim.visible_message("Blood soaks through \the [current_bandage] on [victim]'s [limb.name].", "Blood soaks through \the [current_bandage] on your [limb.name].", vision_distance=COMBAT_MESSAGE_RANGE) - QDEL_NULL(current_bandage) - treat_priority = TRUE + blood_flow -= limb.current_gauze.absorption_rate + limb.seep_gauze(limb.current_gauze.absorption_rate) else blood_flow -= clot_rate @@ -109,41 +115,57 @@ to_chat(victim, "The cut on your [limb.name] 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/brute/cut/check_grab_treatments(obj/item/I, mob/user) +/datum/wound/slash/check_grab_treatments(obj/item/I, mob/user) if(istype(I, /obj/item/gun/energy/laser)) return TRUE -/datum/wound/brute/cut/treat(obj/item/I, mob/user) +/datum/wound/slash/treat(obj/item/I, mob/user) if(istype(I, /obj/item/gun/energy/laser)) las_cauterize(I, user) else if(I.tool_behaviour == TOOL_CAUTERY || I.get_temperature() > 300) tool_cauterize(I, user) - else if(istype(I, /obj/item/stack/medical/gauze)) - bandage(I, user) else if(istype(I, /obj/item/stack/medical/suture)) suture(I, user) -/datum/wound/brute/cut/try_handling(mob/living/carbon/human/user) +/datum/wound/slash/try_handling(mob/living/carbon/human/user) if(user.pulling != victim || user.zone_selected != limb.body_zone || user.a_intent == INTENT_GRAB) return FALSE - if(!iscatperson(user)) - return FALSE - - if(!(user.client?.prefs.vore_flags & LICKABLE)) + if(!isfelinid(user)) return FALSE lick_wounds(user) return TRUE /// if a felinid is licking this cut to reduce bleeding -/datum/wound/brute/cut/proc/lick_wounds(mob/living/carbon/human/user) +/datum/wound/slash/proc/lick_wounds(mob/living/carbon/human/user) if(INTERACTING_WITH(user, victim)) to_chat(user, "You're already interacting with [victim]!") return + if(user.is_mouth_covered()) + to_chat(user, "Your mouth is covered, you can't lick [victim]'s wounds!") + return + + if(!user.getorganslot(ORGAN_SLOT_TONGUE)) + to_chat(user, "You can't lick wounds without a tongue!") // f in chat + return + + // 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/datum/disease/D in victim.diseases) + user.ForceContractDisease(D) + user.visible_message("[user] begins licking the wounds on [victim]'s [limb.name].", "You begin licking the wounds on [victim]'s [limb.name]...", ignored_mobs=victim) to_chat(victim, "[user] begins to lick the wounds on your [limb.name].You successfully lower the severity of [victim]'s cuts.") -/datum/wound/brute/cut/on_xadone(power) +/datum/wound/slash/on_xadone(power) . = ..() 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) + . = ..() + 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/brute/cut/proc/las_cauterize(obj/item/gun/energy/laser/lasgun, mob/user) +/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("[user] begins aiming [lasgun] directly at [victim]'s [limb.name]...", "You begin aiming [lasgun] directly at [user == victim ? "your" : "[victim]'s"] [limb.name]...") if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) @@ -175,11 +201,10 @@ return victim.emote("scream") blood_flow -= damage / (5 * self_penalty_mult) // 20 / 5 = 4 bloodflow removed, p good - cauterized += damage / (5 * self_penalty_mult) victim.visible_message("The cuts on [victim]'s [limb.name] scar over!") /// If someone is using either a cautery tool or something with heat to cauterize this cut -/datum/wound/brute/cut/proc/tool_cauterize(obj/item/I, mob/user) +/datum/wound/slash/proc/tool_cauterize(obj/item/I, mob/user) var/self_penalty_mult = (user == victim ? 1.5 : 1) user.visible_message("[user] begins cauterizing [victim]'s [limb.name] with [I]...", "You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) @@ -191,7 +216,6 @@ victim.emote("scream") var/blood_cauterized = (0.6 / self_penalty_mult) blood_flow -= blood_cauterized - cauterized += blood_cauterized if(blood_flow > minimum_flow) try_treating(I, user) @@ -199,15 +223,15 @@ to_chat(user, "You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.") /// If someone is using a suture to close this cut -/datum/wound/brute/cut/proc/suture(obj/item/stack/medical/suture/I, mob/user) +/datum/wound/slash/proc/suture(obj/item/stack/medical/suture/I, mob/user) var/self_penalty_mult = (user == victim ? 1.4 : 1) user.visible_message("[user] begins stitching [victim]'s [limb.name] with [I]...", "You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") + if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) return user.visible_message("[user] stitches up some of the bleeding on [victim].", "You stitch up some of the bleeding on [user == victim ? "yourself" : "[victim]"].") var/blood_sutured = I.stop_bleeding / self_penalty_mult blood_flow -= blood_sutured - sutured += blood_sutured limb.heal_damage(I.heal_brute, I.heal_burn) if(blood_flow > minimum_flow) @@ -215,51 +239,31 @@ else if(demotes_to) to_chat(user, "You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.") -/// If someone is using gauze on this cut -/datum/wound/brute/cut/proc/bandage(obj/item/stack/I, mob/user) - if(current_bandage) - if(current_bandage.absorption_capacity > I.absorption_capacity + 1) - to_chat(user, "The [current_bandage] on [victim]'s [limb.name] is still in better condition than your [I.name]!") - return - else - user.visible_message("[user] begins rewrapping the cuts on [victim]'s [limb.name] with [I]...", "You begin rewrapping the cuts on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") - else - user.visible_message("[user] begins wrapping the cuts on [victim]'s [limb.name] with [I]...", "You begin wrapping the cuts on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...") - if(!do_after(user, base_treat_time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists))) - return - user.visible_message("[user] applies [I] to [victim]'s [limb.name].", "You bandage some of the bleeding on [user == victim ? "yourself" : "[victim]"].") - QDEL_NULL(current_bandage) - current_bandage = new I.type(limb) - current_bandage.amount = 1 - treat_priority = FALSE - I.use(1) - - -/datum/wound/brute/cut/moderate +/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/blood1.ogg' + sound_effect = 'sound/effects/wounds/blood1.ogg' severity = WOUND_SEVERITY_MODERATE initial_flow = 2 minimum_flow = 0.5 max_per_type = 3 - clot_rate = 0.15 + clot_rate = 0.12 threshold_minimum = 20 threshold_penalty = 10 - status_effect_type = /datum/status_effect/wound/cut/moderate - scarring_descriptions = list("light, faded lines", "minor cut marks", "a small faded slit", "a series of small scars") + status_effect_type = /datum/status_effect/wound/slash/moderate + scar_keyword = "slashmoderate" -/datum/wound/brute/cut/severe +/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/blood2.ogg' + sound_effect = 'sound/effects/wounds/blood2.ogg' severity = WOUND_SEVERITY_SEVERE initial_flow = 3.25 minimum_flow = 2.75 @@ -267,17 +271,17 @@ max_per_type = 4 threshold_minimum = 50 threshold_penalty = 25 - demotes_to = /datum/wound/brute/cut/moderate - status_effect_type = /datum/status_effect/wound/cut/severe - scarring_descriptions = list("a twisted line of faded gashes", "a gnarled sickle-shaped slice scar", "a long-faded puncture wound") + demotes_to = /datum/wound/slash/moderate + status_effect_type = /datum/status_effect/wound/slash/severe + scar_keyword = "slashsevere" -/datum/wound/brute/cut/critical +/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 spurting blood at an alarming rate" + examine_desc = "is carved down to the bone, spraying blood wildly" occur_text = "is torn open, spraying blood wildly" - sound_effect = 'sound/effects/blood3.ogg' + sound_effect = 'sound/effects/wounds/blood3.ogg' severity = WOUND_SEVERITY_CRITICAL initial_flow = 4.25 minimum_flow = 4 @@ -285,25 +289,7 @@ max_per_type = 5 threshold_minimum = 80 threshold_penalty = 40 - demotes_to = /datum/wound/brute/cut/severe - status_effect_type = /datum/status_effect/wound/cut/critical - scarring_descriptions = list("a winding path of very badly healed scar tissue", "a series of peaks and valleys along a gruesome line of cut scar tissue", "a grotesque snake of indentations and stitching scars") - -// TODO: see about moving dismemberment over to this, i'll have to add judging dismembering power/wound potential wrt item size i guess -/datum/wound/brute/cut/loss - name = "Dismembered" - desc = "oof ouch!!" - occur_text = "is violently dismembered!" - sound_effect = 'sound/effects/dismember.ogg' - viable_zones = list(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) - severity = WOUND_SEVERITY_LOSS - threshold_minimum = 180 - status_effect_type = null - -/datum/wound/brute/cut/loss/apply_wound(obj/item/bodypart/L, silent, datum/wound/brute/cut/old_wound, smited = FALSE) - if(!L.dismemberable) - qdel(src) - return - - L.dismember() - qdel(src) + 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) diff --git a/code/game/gamemodes/clown_ops/clown_weapons.dm b/code/game/gamemodes/clown_ops/clown_weapons.dm index afa3dbfeaa..a27cb02ea8 100644 --- a/code/game/gamemodes/clown_ops/clown_weapons.dm +++ b/code/game/gamemodes/clown_ops/clown_weapons.dm @@ -62,7 +62,7 @@ hitsound = null attack_verb_on = list("slipped") clumsy_check = FALSE - sharpness = IS_BLUNT + sharpness = SHARP_NONE sword_color = "yellow" heat = 0 light_color = "#ffff00" diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm index fd1a8690df..52623a9262 100644 --- a/code/game/machinery/doors/door.dm +++ b/code/game/machinery/doors/door.dm @@ -345,7 +345,8 @@ L.visible_message("[src] closes on [L], crushing [L.p_them()]!", "[src] closes on you and crushes you!") if(iscarbon(L)) var/mob/living/carbon/C = L - for(var/datum/wound/W in C.all_wounds) + for(var/i in C.all_wounds) // should probably replace with signal + var/datum/wound/W = i W.crush(DOOR_CRUSH_DAMAGE) if(isalien(L)) //For xenos L.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans. diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index a3bbf95413..d4c8b32a6b 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -108,12 +108,12 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb mouse_drag_pointer = MOUSE_ACTIVE_POINTER //the icon to indicate this object is being dragged - var/list/embedding = NONE + var/list/embedding var/flags_cover = 0 //for flags such as GLASSESCOVERSEYES var/heat = 0 - ///All items with sharpness of IS_SHARP or higher will automatically get the butchering component. - var/sharpness = IS_BLUNT + ///All items with sharpness of SHARP_EDGED or higher will automatically get the butchering component. + var/sharpness = SHARP_NONE var/tool_behaviour = NONE var/toolspeed = 1 @@ -211,7 +211,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb if(GLOB.rpg_loot_items) AddComponent(/datum/component/fantasy) - if(sharpness) //give sharp objects butchering functionality, for consistency + if(sharpness && force > 5) //give sharp objects butchering functionality, for consistency AddComponent(/datum/component/butchering, 80 * toolspeed) /obj/item/proc/check_allowed_items(atom/target, not_inside, target_self) @@ -1097,7 +1097,7 @@ GLOBAL_VAR_INIT(embedpocalypse, FALSE) // if true, all items will be able to emb /obj/item/proc/updateEmbedding() - if(!islist(embedding) || !LAZYLEN(embedding)) + if(!LAZYLEN(embedding)) return AddElement(/datum/element/embed,\ diff --git a/code/game/objects/items/chainsaw.dm b/code/game/objects/items/chainsaw.dm index f382aa1ed3..ebb26fab93 100644 --- a/code/game/objects/items/chainsaw.dm +++ b/code/game/objects/items/chainsaw.dm @@ -16,7 +16,7 @@ custom_materials = list(/datum/material/iron=13000) attack_verb = list("sawed", "torn", "cut", "chopped", "diced") hitsound = "swing_hit" - sharpness = IS_SHARP + sharpness = SHARP_EDGED actions_types = list(/datum/action/item_action/startchainsaw) tool_behaviour = TOOL_SAW toolspeed = 0.5 @@ -71,10 +71,6 @@ /obj/item/chainsaw/update_icon_state() icon_state = "chainsaw_[on ? "on" : "off"]" -/obj/item/chainsaw/get_dismemberment_chance() - if(wielded) - . = ..() - /obj/item/chainsaw/doomslayer name = "THE GREAT COMMUNICATOR" desc = "VRRRRRRR!!!" diff --git a/code/game/objects/items/dualsaber.dm b/code/game/objects/items/dualsaber.dm index 08460993ee..9db9449fcb 100644 --- a/code/game/objects/items/dualsaber.dm +++ b/code/game/objects/items/dualsaber.dm @@ -105,7 +105,7 @@ to_chat(user, "You lack the grace to wield this!") return COMPONENT_TWOHANDED_BLOCK_WIELD wielded = TRUE - sharpness = IS_SHARP + sharpness = SHARP_EDGED w_class = w_class_on total_mass = total_mass_on hitsound = 'sound/weapons/blade1.ogg' diff --git a/code/game/objects/items/fireaxe.dm b/code/game/objects/items/fireaxe.dm index 7cb22d5eb0..6fb7b89262 100644 --- a/code/game/objects/items/fireaxe.dm +++ b/code/game/objects/items/fireaxe.dm @@ -13,11 +13,12 @@ slot_flags = ITEM_SLOT_BACK attack_verb = list("attacked", "chopped", "cleaved", "torn", "cut") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED max_integrity = 200 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30) resistance_flags = FIRE_PROOF - wound_bonus = -20 + wound_bonus = -15 + bare_wound_bonus = 20 var/wielded = FALSE // track wielded status on item /obj/item/fireaxe/Initialize() diff --git a/code/game/objects/items/holy_weapons.dm b/code/game/objects/items/holy_weapons.dm index 691b4c4228..58146be20f 100644 --- a/code/game/objects/items/holy_weapons.dm +++ b/code/game/objects/items/holy_weapons.dm @@ -352,7 +352,7 @@ w_class = WEIGHT_CLASS_HUGE slot_flags = ITEM_SLOT_BACK|ITEM_SLOT_BELT block_chance = 30 - sharpness = IS_SHARP + sharpness = SHARP_EDGED hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") @@ -452,7 +452,7 @@ w_class = WEIGHT_CLASS_BULKY armour_penetration = 35 slot_flags = ITEM_SLOT_BACK - sharpness = IS_SHARP + sharpness = SHARP_EDGED attack_verb = list("chopped", "sliced", "cut", "reaped") /obj/item/nullrod/scythe/Initialize() @@ -575,7 +575,7 @@ righthand_file = 'icons/mob/inhands/weapons/chainsaw_righthand.dmi' w_class = WEIGHT_CLASS_HUGE item_flags = ABSTRACT - sharpness = IS_SHARP + sharpness = SHARP_EDGED attack_verb = list("sawed", "torn", "cut", "chopped", "diced") hitsound = 'sound/weapons/chainsawhit.ogg' total_mass = TOTAL_MASS_HAND_REPLACEMENT @@ -594,7 +594,7 @@ name = "clown dagger" desc = "Used for absolutely hilarious sacrifices." hitsound = 'sound/items/bikehorn.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") /obj/item/nullrod/pride_hammer @@ -645,7 +645,7 @@ throw_speed = 4 throw_range = 7 throwforce = 30 - sharpness = IS_SHARP + sharpness = SHARP_EDGED attack_verb = list("enlightened", "redpilled") /obj/item/nullrod/armblade @@ -657,7 +657,7 @@ righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi' item_flags = ABSTRACT w_class = WEIGHT_CLASS_HUGE - sharpness = IS_SHARP + sharpness = SHARP_EDGED wound_bonus = -20 bare_wound_bonus = 25 total_mass = TOTAL_MASS_HAND_REPLACEMENT @@ -699,7 +699,7 @@ force = 15 block_chance = 40 slot_flags = ITEM_SLOT_BACK - sharpness = IS_BLUNT + sharpness = SHARP_NONE hitsound = "swing_hit" attack_verb = list("smashed", "slammed", "whacked", "thwacked") icon = 'icons/obj/items_and_weapons.dmi' @@ -754,7 +754,7 @@ name = "arrhythmic knife" w_class = WEIGHT_CLASS_HUGE desc = "They say fear is the true mind killer, but stabbing them in the head works too. Honour compels you to not sheathe it once drawn." - sharpness = IS_SHARP + sharpness = SHARP_EDGED slot_flags = null hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") @@ -782,7 +782,7 @@ desc = "Holding this makes you look absolutely devilish." attack_verb = list("poked", "impaled", "pierced", "jabbed") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/nullrod/egyptian name = "egyptian staff" diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm index 8f274c04aa..e7cf8defc9 100644 --- a/code/game/objects/items/kitchen.dm +++ b/code/game/objects/items/kitchen.dm @@ -18,7 +18,7 @@ name = "fork" desc = "Pointy." icon_state = "fork" - force = 5 + force = 4 w_class = WEIGHT_CLASS_TINY throwforce = 0 throw_speed = 3 @@ -28,6 +28,7 @@ attack_verb = list("attacked", "stabbed", "poked") hitsound = 'sound/weapons/bladeslice.ogg' armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) + sharpness = SHARP_POINTY var/datum/reagent/forkload //used to eat omelette /obj/item/kitchen/fork/suicide_act(mob/living/carbon/user) @@ -61,7 +62,7 @@ throw_speed = 4 throw_range = 6 embedding = list("pain_mult" = 2, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15) - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/kitchen/knife name = "kitchen knife" @@ -76,7 +77,7 @@ throw_range = 6 custom_materials = list(/datum/material/iron=12000) attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - sharpness = IS_SHARP_ACCURATE + sharpness = SHARP_POINTY armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50) var/bayonet = FALSE //Can this be attached to a gun? wound_bonus = -5 diff --git a/code/game/objects/items/melee/energy.dm b/code/game/objects/items/melee/energy.dm index 20960da7c6..5e102a502e 100644 --- a/code/game/objects/items/melee/energy.dm +++ b/code/game/objects/items/melee/energy.dm @@ -102,7 +102,7 @@ attack_verb_off = list("tapped", "poked") throw_speed = 3 throw_range = 5 - sharpness = IS_SHARP + sharpness = SHARP_EDGED embedding = list("embed_chance" = 75, "impact_pain_mult" = 10) armour_penetration = 35 item_flags = NEEDS_PERMIT | ITEM_CAN_PARRY @@ -174,7 +174,7 @@ sword_color = null //stops icon from breaking when turned on. hitcost = 75 //Costs more than a standard cyborg esword w_class = WEIGHT_CLASS_NORMAL - sharpness = IS_SHARP + sharpness = SHARP_EDGED light_color = "#40ceff" tool_behaviour = TOOL_SAW toolspeed = 0.7 @@ -249,7 +249,7 @@ throw_range = 1 w_class = WEIGHT_CLASS_BULKY//So you can't hide it in your pocket or some such. var/datum/effect_system/spark_spread/spark_system - sharpness = IS_SHARP + sharpness = SHARP_EDGED //Most of the other special functions are handled in their own files. aka special snowflake code so kewl /obj/item/melee/transforming/energy/blade/Initialize() @@ -285,7 +285,7 @@ attack_verb_off = list("tapped", "poked") throw_speed = 3 throw_range = 5 - sharpness = IS_SHARP + sharpness = SHARP_EDGED embedding = list("embedded_pain_multiplier" = 6, "embed_chance" = 20, "embedded_fall_chance" = 60) armour_penetration = 10 block_chance = 35 diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index ee24579e9a..3b312fe047 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -44,7 +44,7 @@ throwforce = 10 hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "impaled", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - sharpness = IS_SHARP + sharpness = SHARP_EDGED total_mass = TOTAL_MASS_HAND_REPLACEMENT /obj/item/melee/synthetic_arm_blade/Initialize() @@ -64,7 +64,7 @@ throwforce = 15 w_class = WEIGHT_CLASS_BULKY armour_penetration = 75 - sharpness = IS_SHARP + sharpness = SHARP_EDGED attack_verb = list("slashed", "cut") hitsound = 'sound/weapons/rapierhit.ogg' custom_materials = list(/datum/material/iron = 1000) @@ -168,7 +168,7 @@ flags_1 = CONDUCT_1 obj_flags = UNIQUE_RENAME w_class = WEIGHT_CLASS_BULKY - sharpness = IS_SHARP_ACCURATE //It cant be sharpend cook -_- + sharpness = SHARP_POINTY //It cant be sharpend cook -_- attack_verb = list("stabs", "punctures", "pierces", "pokes") hitsound = 'sound/weapons/rapierhit.ogg' total_mass = 0.4 diff --git a/code/game/objects/items/melee/transforming.dm b/code/game/objects/items/melee/transforming.dm index 386a6e9acc..fbdb19bd1c 100644 --- a/code/game/objects/items/melee/transforming.dm +++ b/code/game/objects/items/melee/transforming.dm @@ -1,5 +1,5 @@ /obj/item/melee/transforming - sharpness = IS_SHARP + sharpness = SHARP_EDGED var/active = FALSE var/force_on = 30 //force when active var/faction_bonus_force = 0 //Bonus force dealt against certain factions diff --git a/code/game/objects/items/pitchfork.dm b/code/game/objects/items/pitchfork.dm index 49d0b64498..b296e2d0cb 100644 --- a/code/game/objects/items/pitchfork.dm +++ b/code/game/objects/items/pitchfork.dm @@ -9,7 +9,7 @@ w_class = WEIGHT_CLASS_BULKY attack_verb = list("attacked", "impaled", "pierced") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED max_integrity = 200 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 30) resistance_flags = FIRE_PROOF diff --git a/code/game/objects/items/sharpener.dm b/code/game/objects/items/sharpener.dm index 6bf0b27fb4..fc19e61cd6 100644 --- a/code/game/objects/items/sharpener.dm +++ b/code/game/objects/items/sharpener.dm @@ -39,7 +39,7 @@ I.force = clamp(I.force + increment, 0, max) user.visible_message("[user] sharpens [I] with [src]!", "You sharpen [I], making it much more deadly than before.") - I.sharpness = IS_SHARP_ACCURATE + I.sharpness = SHARP_POINTY I.throwforce = clamp(I.throwforce + increment, 0, max) I.name = "[prefix] [I.name]" name = "worn out [name]" diff --git a/code/game/objects/items/shrapnel.dm b/code/game/objects/items/shrapnel.dm index b74b0563b7..906c474aa8 100644 --- a/code/game/objects/items/shrapnel.dm +++ b/code/game/objects/items/shrapnel.dm @@ -7,13 +7,13 @@ icon_state = "large" w_class = WEIGHT_CLASS_TINY item_flags = DROPDEL - sharpness = TRUE + sharpness = SHARP_EDGED /obj/item/shrapnel/stingball // stingbang grenades name = "stingball" embedding = list(embed_chance=90, fall_chance=3, jostle_chance=7, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.7, pain_mult=5, jostle_pain_mult=6, rip_time=15, embed_chance_turf_mod=-100) icon_state = "tiny" - sharpness = FALSE + sharpness = SHARP_NONE /obj/item/shrapnel/bullet // bullets name = "bullet" @@ -30,24 +30,25 @@ /obj/item/projectile/bullet/shrapnel name = "flying shrapnel shard" - damage = 8 - range = 10 + damage = 14 + range = 20 armour_penetration = -30 dismemberment = 5 ricochets_max = 2 - ricochet_chance = 40 + ricochet_chance = 70 shrapnel_type = /obj/item/shrapnel ricochet_incidence_leeway = 60 - sharpness = TRUE - wound_bonus = 30 + sharpness = SHARP_EDGED + wound_bonus = 40 /obj/item/projectile/bullet/shrapnel/mega name = "flying shrapnel hunk" - range = 25 - dismemberment = 10 - ricochets_max = 4 - ricochet_chance = 90 - ricochet_decay_chance = 0.9 + range = 45 + dismemberment = 15 + ricochets_max = 6 + ricochet_chance = 130 + ricochet_incidence_leeway = 0 + ricochet_delay_chance = 0.9 /obj/item/projectile/bullet/pellet/stingball name = "stingball pellet" @@ -71,10 +72,10 @@ name = "breakbang pellet" damage = 10 wound_bonus = 40 - sharpness = FALSE + sharpness = SHARP_NONE /obj/item/projectile/bullet/pellet/stingball/shred name = "shredbang pellet" damage = 10 wound_bonus = 30 - sharpness = TRUE + sharpness = SHARP_EDGED diff --git a/code/game/objects/items/spear.dm b/code/game/objects/items/spear.dm index 41cb68559b..f40c774551 100644 --- a/code/game/objects/items/spear.dm +++ b/code/game/objects/items/spear.dm @@ -15,14 +15,14 @@ custom_materials = list(/datum/material/iron=1150, /datum/material/glass=2075) hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "poked", "jabbed", "torn", "gored") - sharpness = IS_SHARP + sharpness = SHARP_EDGED max_integrity = 200 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) var/obj/item/grenade/explosive = null var/war_cry = "AAAAARGH!!!" var/icon_prefix = "spearglass" var/wielded = FALSE // track wielded status on item - wound_bonus = -25 + wound_bonus = -15 bare_wound_bonus = 15 /obj/item/spear/Initialize() @@ -179,7 +179,7 @@ custom_materials = null hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "poked", "jabbed", "torn", "gored") - sharpness = IS_SHARP + sharpness = SHARP_EDGED icon_prefix = "bone_spear" /obj/item/spear/bonespear/ComponentInitialize() diff --git a/code/game/objects/items/stacks/medical.dm b/code/game/objects/items/stacks/medical.dm index b358608ee4..cf70776a16 100644 --- a/code/game/objects/items/stacks/medical.dm +++ b/code/game/objects/items/stacks/medical.dm @@ -132,11 +132,34 @@ // gauze is only relevant for wounds, which are handled in the wounds themselves /obj/item/stack/medical/gauze/try_heal(mob/living/M, mob/user, silent) var/obj/item/bodypart/limb = M.get_bodypart(check_zone(user.zone_selected)) - if(limb) - if(limb.brute_dam > 40) - to_chat(user, "The bleeding on [user==M ? "your" : "[M]'s"] [limb.name] is from bruising, and cannot be treated with [src]!") - else - to_chat(user, "There's no bleeding on [user==M ? "your" : "[M]'s"] [limb.name]") + if(!limb) + to_chat(user, "There's nothing there to bandage!") + return + if(!LAZYLEN(limb.wounds)) + to_chat(user, "There's no wounds that require bandaging on [user==M ? "your" : "[M]'s"] [limb.name]!") // good problem to have imo + return + + var/gauzeable_wound = FALSE + for(var/i in limb.wounds) + var/datum/wound/woundies = i + if(woundies.wound_flags & ACCEPTS_GAUZE) + gauzeable_wound = TRUE + break + if(!gauzeable_wound) + to_chat(user, "There's no wounds that require bandaging on [user==M ? "your" : "[M]'s"] [limb.name]!") // good problem to have imo + return + + if(limb.current_gauze && (limb.current_gauze.absorption_capacity * 0.8 > absorption_capacity)) // ignore if our new wrap is < 20% better than the current one, so someone doesn't bandage it 5 times in a row + to_chat(user, "The bandage currently on [user==M ? "your" : "[M]'s"] [limb.name] is still in good condition!") + return + + user.visible_message("[user] begins wrapping the wounds on [M]'s [limb.name] with [src]...", "You begin wrapping the wounds on [user == M ? "your" : "[M]'s"] [limb.name] with [src]...") + + if(!do_after(user, (user == M ? self_delay : other_delay), target=M)) + return + + user.visible_message("[user] applies [src] to [M]'s [limb.name].", "You bandage the wounds on [user == M ? "yourself" : "[M]'s"] [limb.name].") + limb.apply_gauze(src) /obj/item/stack/medical/gauze/attackby(obj/item/I, mob/user, params) if(I.tool_behaviour == TOOL_WIRECUTTER || I.get_sharpness()) @@ -378,9 +401,9 @@ C.emote("scream") for(var/i in C.bodyparts) var/obj/item/bodypart/bone = i - var/datum/wound/brute/bone/severe/oof_ouch = new + var/datum/wound/blunt/severe/oof_ouch = new oof_ouch.apply_wound(bone) - var/datum/wound/brute/bone/critical/oof_OUCH = new + var/datum/wound/blunt/critical/oof_OUCH = new oof_OUCH.apply_wound(bone) for(var/i in C.bodyparts) diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm index d4baea2487..29b4dea6d8 100644 --- a/code/game/objects/items/stacks/sheets/glass.dm +++ b/code/game/objects/items/stacks/sheets/glass.dm @@ -289,7 +289,7 @@ GLOBAL_LIST_INIT(plastitaniumglass_recipes, list( resistance_flags = ACID_PROOF armor = list("melee" = 100, "bullet" = 0, "laser" = 0, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 100) max_integrity = 40 - sharpness = IS_SHARP + sharpness = SHARP_EDGED var/icon_prefix embedding = list("embed_chance" = 65) diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index 9560f7fab3..1f2a65321d 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -33,6 +33,8 @@ heat = 3800 tool_behaviour = TOOL_WELDER toolspeed = 1 + wound_bonus = 10 + bare_wound_bonus = 15 /obj/item/weldingtool/Initialize() . = ..() diff --git a/code/game/objects/items/toys.dm b/code/game/objects/items/toys.dm index fe2e0df2eb..029a02b9f9 100644 --- a/code/game/objects/items/toys.dm +++ b/code/game/objects/items/toys.dm @@ -447,7 +447,7 @@ block_parry_data = null attack_verb = list("attacked", "struck", "hit") total_mass_on = TOTAL_MASS_TOY_SWORD - sharpness = IS_BLUNT + sharpness = SHARP_NONE /obj/item/dualsaber/toy/ComponentInitialize() AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=0, wieldsound='sound/weapons/saberon.ogg', unwieldsound='sound/weapons/saberoff.ogg') @@ -466,7 +466,7 @@ attack_verb = list("attacked", "struck", "hit") total_mass_on = TOTAL_MASS_TOY_SWORD slowdown_wielded = 0 - sharpness = IS_BLUNT + sharpness = SHARP_NONE /obj/item/dualsaber/hypereutactic/toy/ComponentInitialize() AddComponent(/datum/component/two_handed, force_unwielded=0, force_wielded=0, wieldsound='sound/weapons/saberon.ogg', unwieldsound='sound/weapons/saberoff.ogg') diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 56737cd1a9..0f6be3cf60 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -65,7 +65,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 w_class = WEIGHT_CLASS_NORMAL attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") block_chance = 50 - sharpness = IS_SHARP + sharpness = SHARP_EDGED max_integrity = 200 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF @@ -231,7 +231,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") block_chance = 50 - sharpness = IS_SHARP + sharpness = SHARP_EDGED max_integrity = 200 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50) resistance_flags = FIRE_PROOF @@ -297,13 +297,13 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' force = 2 - throwforce = 20 //This is never used on mobs since this has a 100% embed chance. + throwforce = 10 //This is never used on mobs since this has a 100% embed chance. throw_speed = 4 embedding = list("pain_mult" = 4, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15) armour_penetration = 40 w_class = WEIGHT_CLASS_SMALL - sharpness = IS_SHARP + sharpness = SHARP_EDGED custom_materials = list(/datum/material/iron=500, /datum/material/glass=500) resistance_flags = FIRE_PROOF @@ -316,7 +316,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 /obj/item/throwing_star/toy name = "toy throwing star" desc = "An aerodynamic disc strapped with adhesive for sticking to people, good for playing pranks and getting yourself killed by security." - sharpness = IS_BLUNT + sharpness = SHARP_NONE force = 0 throwforce = 0 embedding = list("pain_mult" = 0, "jostle_pain_mult" = 0, "embed_chance" = 100, "fall_chance" = 0) @@ -353,7 +353,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 icon_state = extended_icon_state attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED else force = initial(force) w_class = WEIGHT_CLASS_SMALL @@ -361,7 +361,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 icon_state = retracted_icon_state attack_verb = list("stubbed", "poked") hitsound = 'sound/weapons/genhit.ogg' - sharpness = IS_BLUNT + sharpness = SHARP_NONE /obj/item/switchblade/suicide_act(mob/user) user.visible_message("[user] is slitting [user.p_their()] own throat with [src]! It looks like [user.p_theyre()] trying to commit suicide!") @@ -462,7 +462,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 throwforce = 0 throw_range = 0 throw_speed = 0 - sharpness = IS_SHARP + sharpness = SHARP_EDGED attack_verb = list("sawed", "torn", "cut", "chopped", "diced") hitsound = 'sound/weapons/chainsawhit.ogg' total_mass = TOTAL_MASS_HAND_REPLACEMENT @@ -860,7 +860,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 block_chance = 40 throwforce = 20 throw_speed = 4 - sharpness = IS_SHARP + sharpness = SHARP_EDGED attack_verb = list("cut", "sliced", "diced") w_class = WEIGHT_CLASS_BULKY slot_flags = ITEM_SLOT_BACK diff --git a/code/game/turfs/simulated/walls.dm b/code/game/turfs/simulated/walls.dm index df63cf93e6..8661682424 100644 --- a/code/game/turfs/simulated/walls.dm +++ b/code/game/turfs/simulated/walls.dm @@ -125,18 +125,45 @@ dismantle_wall(1) return -/turf/closed/wall/attack_hulk(mob/user, does_attack_animation = 0) - ..(user, 1) +/turf/closed/wall/attack_hulk(mob/living/carbon/user) + ..() + var/obj/item/bodypart/arm = user.hand_bodyparts[user.active_hand_index] + if(!arm) + return + if(arm.disabled) + return if(prob(hardness)) - playsound(src, 'sound/effects/meteorimpact.ogg', 100, 1) + playsound(src, 'sound/effects/meteorimpact.ogg', 100, TRUE) user.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk") + hulk_recoil(arm, user) dismantle_wall(1) + else - playsound(src, 'sound/effects/bang.ogg', 50, 1) + playsound(src, 'sound/effects/bang.ogg', 50, TRUE) add_dent(WALL_DENT_HIT) - to_chat(user, text("You punch the wall.")) + user.visible_message("[user] smashes \the [src]!", \ + "You smash \the [src]!", \ + "You hear a booming smash!") return TRUE +/** + *Deals damage back to the hulk's arm. + * + *When a hulk manages to break a wall using their hulk smash, this deals back damage to the arm used. + *This is in its own proc just to be easily overridden by other wall types. Default allows for three + *smashed walls per arm. Also, we use CANT_WOUND here because wounds are random. Wounds are applied + *by hulk code based on arm damage and checked when we call break_an_arm(). + *Arguments: + **arg1 is the arm to deal damage to. + **arg2 is the hulk + */ +/turf/closed/wall/proc/hulk_recoil(obj/item/bodypart/arm, mob/living/carbon/human/hulkman, var/damage = 20) + arm.receive_damage(brute = damage, blocked = 0, wound_bonus = CANT_WOUND) + var/datum/mutation/human/hulk/smasher = locate(/datum/mutation/human/hulk) in hulkman.dna.mutations + if(!smasher || !damage) //sanity check but also snow and wood walls deal no recoil damage, so no arm breaky + return + smasher.break_an_arm(arm) + /turf/closed/wall/attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) . = ..() if(.) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index d0dc3c789e..5eb1ede525 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -1282,8 +1282,8 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits ADMIN_PUNISHMENT_ROD, ADMIN_PUNISHMENT_PICKLE, ADMIN_PUNISHMENT_FRY, - ADMIN_PUNISHMENT_CRACK, - ADMIN_PUNISHMENT_BLEED, + ADMIN_PUNISHMENT_CRACK, + ADMIN_PUNISHMENT_BLEED, ADMIN_PUNISHMENT_SCARIFY) @@ -1368,16 +1368,18 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE) return var/mob/living/carbon/C = target - for(var/obj/item/bodypart/squish_part in C.bodyparts) - var/type_wound = pick(list(/datum/wound/brute/bone/critical, /datum/wound/brute/bone/severe, /datum/wound/brute/bone/critical, /datum/wound/brute/bone/severe, /datum/wound/brute/bone/moderate)) + for(var/i in C.bodyparts) + var/obj/item/bodypart/squish_part = i + 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)) squish_part.force_wound_upwards(type_wound, smited=TRUE) if(ADMIN_PUNISHMENT_BLEED) if(!iscarbon(target)) to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE) return var/mob/living/carbon/C = target - for(var/obj/item/bodypart/slice_part in C.bodyparts) - var/type_wound = pick(list(/datum/wound/brute/cut/severe, /datum/wound/brute/cut/moderate)) + for(var/i in C.bodyparts) + var/obj/item/bodypart/slice_part = i + var/type_wound = pick(list(/datum/wound/slash/severe, /datum/wound/slash/moderate)) slice_part.force_wound_upwards(type_wound, smited=TRUE) type_wound = pick(list(/datum/wound/brute/cut/critical, /datum/wound/brute/cut/severe, /datum/wound/brute/cut/moderate)) slice_part.force_wound_upwards(type_wound, smited=TRUE) @@ -1387,9 +1389,53 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits if(!iscarbon(target)) to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE) return - var/mob/living/carbon/C = target - C.generate_fake_scars(rand(1, 4)) - to_chat(C, "You feel your body grow jaded and torn...") + var/mob/living/carbon/dude = target + dude.generate_fake_scars(rand(1, 4)) + to_chat(dude, "You feel your body grow jaded and torn...") + if(ADMIN_PUNISHMENT_PERFORATE) + if(!iscarbon(target)) + to_chat(usr,"This must be used on a carbon mob.", confidential = TRUE) + return + + var/list/how_fucked_is_this_dude = list("A little", "A lot", "So fucking much", "FUCK THIS DUDE") + var/hatred = input("How much do you hate this guy?") in how_fucked_is_this_dude + var/repetitions + var/shots_per_limb_per_rep = 2 + var/damage + switch(hatred) + if("A little") + repetitions = 1 + damage = 5 + if("A lot") + repetitions = 2 + + damage = 8 + if("So fucking much") + repetitions = 3 + damage = 10 + if("FUCK THIS DUDE") + repetitions = 4 + damage = 10 + + var/mob/living/carbon/dude = target + var/list/open_adj_turfs = get_adjacent_open_turfs(dude) + var/list/wound_bonuses = list(15, 70, 110, 250) + + var/delay_per_shot = 1 + var/delay_counter = 1 + + dude.Immobilize(5 SECONDS) + for(var/wound_bonus_rep in 1 to repetitions) + for(var/i in dude.bodyparts) + var/obj/item/bodypart/slice_part = i + var/shots_this_limb = 0 + for(var/t in shuffle(open_adj_turfs)) + var/turf/iter_turf = t + addtimer(CALLBACK(GLOBAL_PROC, .proc/firing_squad, dude, iter_turf, slice_part.body_zone, wound_bonuses[wound_bonus_rep], damage), delay_counter) + delay_counter += delay_per_shot + shots_this_limb++ + if(shots_this_limb > shots_per_limb_per_rep) + break if(ADMIN_PUNISHMENT_PICKLE) target.turn_into_pickle() if(ADMIN_PUNISHMENT_FRY) @@ -1397,6 +1443,31 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits punish_log(target, punishment) +/** + * firing_squad is a proc for the :B:erforate smite to shoot each individual bullet at them, so that we can add actual delays without sleep() nonsense + * + * Hilariously, if you drag someone away mid smite, the bullets will still chase after them from the original spot, possibly hitting other people. Too funny to fix imo + * + * Arguments: + * * target- guy we're shooting obviously + * * source_turf- where the bullet begins, preferably on a turf next to the target + * * body_zone- which bodypart we're aiming for, if there is one there + * * wound_bonus- the wounding power we're assigning to the bullet, since we don't care about the base one + * * damage- the damage we're assigning to the bullet, since we don't care about the base one + */ +/proc/firing_squad(mob/living/carbon/target, turf/source_turf, body_zone, wound_bonus, damage) + if(!target.get_bodypart(body_zone)) + return + playsound(target, 'sound/weapons/gun/revolver/shot.ogg', 100) + var/obj/projectile/bullet/smite/divine_wrath = new(source_turf) + divine_wrath.damage = damage + divine_wrath.wound_bonus = wound_bonus + divine_wrath.original = target + divine_wrath.def_zone = body_zone + divine_wrath.spread = 0 + divine_wrath.preparePixelProjectile(target, source_turf) + divine_wrath.fire() + /client/proc/punish_log(var/whom, var/punishment) var/msg = "[key_name_admin(usr)] punished [key_name_admin(whom)] with [punishment]." message_admins(msg) diff --git a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm index 9301d0c239..b32237b7fb 100644 --- a/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm +++ b/code/modules/antagonists/bloodsucker/objects/bloodsucker_crypt.dm @@ -361,9 +361,9 @@ torture_time -= I.force / 4 torture_dmg_brute += I.force / 4 //torture_dmg_burn += I. - if(I.sharpness == IS_SHARP) + if(I.sharpness == SHARP_EDGED) torture_time -= 1 - else if(I.sharpness == IS_SHARP_ACCURATE) + else if(I.sharpness == SHARP_POINTY) torture_time -= 2 if(istype(I, /obj/item/weldingtool)) var/obj/item/weldingtool/welder = I diff --git a/code/modules/antagonists/changeling/powers/mutations.dm b/code/modules/antagonists/changeling/powers/mutations.dm index 7d50374e96..24288be078 100644 --- a/code/modules/antagonists/changeling/powers/mutations.dm +++ b/code/modules/antagonists/changeling/powers/mutations.dm @@ -164,7 +164,7 @@ armour_penetration = 20 hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") - sharpness = IS_SHARP + sharpness = SHARP_EDGED wound_bonus = -60 bare_wound_bonus = 20 var/can_drop = FALSE diff --git a/code/modules/antagonists/changeling/powers/regenerate.dm b/code/modules/antagonists/changeling/powers/regenerate.dm index bcebd8c62e..a88422e7eb 100644 --- a/code/modules/antagonists/changeling/powers/regenerate.dm +++ b/code/modules/antagonists/changeling/powers/regenerate.dm @@ -30,8 +30,8 @@ C.regenerate_limbs(1) C.regenerate_organs() for(var/i in C.all_wounds) - var/datum/wound/W = i - W.remove_wound() + var/datum/wound/iter_wound = i + iter_wound.remove_wound() if(!user.getorganslot(ORGAN_SLOT_BRAIN)) var/obj/item/organ/brain/B if(C.has_dna() && C.dna.species.mutant_brain) diff --git a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm index 234f0445e0..9af1c54170 100644 --- a/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm +++ b/code/modules/antagonists/clockcult/clock_items/clock_weapons/ratvarian_spear.dm @@ -8,7 +8,7 @@ force = 15 //Extra damage is dealt to targets in attack() throwforce = 25 armour_penetration = 10 - sharpness = IS_SHARP_ACCURATE + sharpness = SHARP_POINTY attack_verb = list("stabbed", "poked", "slashed") hitsound = 'sound/weapons/bladeslice.ogg' w_class = WEIGHT_CLASS_BULKY diff --git a/code/modules/antagonists/cult/cult_items.dm b/code/modules/antagonists/cult/cult_items.dm index 4e9d40d91c..1b1c461dbc 100644 --- a/code/modules/antagonists/cult/cult_items.dm +++ b/code/modules/antagonists/cult/cult_items.dm @@ -53,7 +53,7 @@ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' flags_1 = CONDUCT_1 - sharpness = IS_SHARP + sharpness = SHARP_EDGED w_class = WEIGHT_CLASS_BULKY force = 30 // whoever balanced this got beat in the head by a bible too many times good lord throwforce = 10 @@ -114,7 +114,7 @@ armour_penetration = 45 throw_speed = 1 throw_range = 3 - sharpness = IS_SHARP + sharpness = SHARP_EDGED light_color = "#ff0000" attack_verb = list("cleaved", "slashed", "torn", "hacked", "ripped", "diced", "carved") icon_state = "cultbastard" @@ -708,7 +708,7 @@ armour_penetration = 30 block_chance = 30 attack_verb = list("attacked", "impaled", "stabbed", "torn", "gored") - sharpness = IS_SHARP + sharpness = SHARP_EDGED hitsound = 'sound/weapons/bladeslice.ogg' var/datum/action/innate/cult/spear/spear_act var/wielded = FALSE // track wielded status on item diff --git a/code/modules/antagonists/slaughter/slaughter.dm b/code/modules/antagonists/slaughter/slaughter.dm index 35a674fb0e..3ae9cfcfb0 100644 --- a/code/modules/antagonists/slaughter/slaughter.dm +++ b/code/modules/antagonists/slaughter/slaughter.dm @@ -38,7 +38,7 @@ melee_damage_upper = 22.5 wound_bonus = -10 bare_wound_bonus = 0 - sharpness = TRUE + sharpness = SHARP_EDGED see_in_dark = 8 blood_volume = 0 //No bleeding on getting shot, for skeddadles lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm index 2701a2d006..d8a8e9a1be 100644 --- a/code/modules/antagonists/wizard/equipment/artefact.dm +++ b/code/modules/antagonists/wizard/equipment/artefact.dm @@ -259,7 +259,7 @@ to_chat(target, "You suddenly feel very hot") target.adjust_bodytemperature(50) GiveHint(target) - else if(is_pointed(I)) + else if(I.get_sharpness() == SHARP_POINTY) to_chat(target, "You feel a stabbing pain in [parse_zone(user.zone_selected)]!") target.DefaultCombatKnockdown(40) GiveHint(target) diff --git a/code/modules/cargo/packs/goodies.dm b/code/modules/cargo/packs/goodies.dm index 2ff02d0473..86a7c73a34 100644 --- a/code/modules/cargo/packs/goodies.dm +++ b/code/modules/cargo/packs/goodies.dm @@ -81,3 +81,9 @@ desc = "Contains one hellgun, an old pattern of laser gun infamous for its ability to horribly disfigure targets with burns. Technically violates the Space Geneva Convention when used on humanoids." cost = 1500 contains = list(/obj/item/gun/energy/laser/hellgun) + +/datum/supply_pack/goody/medipen_twopak + name = "Medipen Two-Pak" + desc = "Contains one standard epinephrine medipen and one standard emergency first-aid kit medipen. For when you want to prepare for the worst." + cost = 500 + contains = list(/obj/item/reagent_containers/hypospray/medipen, /obj/item/reagent_containers/hypospray/medipen/ekit) diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm index 5eacc2f583..ce66fc52d5 100644 --- a/code/modules/cargo/packs/medical.dm +++ b/code/modules/cargo/packs/medical.dm @@ -218,3 +218,18 @@ /obj/item/storage/box/beakers) crate_name = "virus containment unit crate" crate_type = /obj/structure/closet/crate/secure/plasma + +/datum/supply_pack/medical/medipen_variety + name = "Medipen Variety-Pak" + desc = "Contains eight different medipens in three different varieties, to assist in quickly treating seriously injured patients." + cost = 2000 + contains = list(/obj/item/reagent_containers/hypospray/medipen/, + /obj/item/reagent_containers/hypospray/medipen/, + /obj/item/reagent_containers/hypospray/medipen/ekit, + /obj/item/reagent_containers/hypospray/medipen/ekit, + /obj/item/reagent_containers/hypospray/medipen/ekit, + /obj/item/reagent_containers/hypospray/medipen/blood_loss, + /obj/item/reagent_containers/hypospray/medipen/blood_loss, + /obj/item/reagent_containers/hypospray/medipen/blood_loss + + crate_name = "medipen crate" diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 75e914ea68..c0107ebd9f 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -832,7 +832,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) dat += "Socks Color:     Change
" dat += "Backpack:[backbag]" dat += "Jumpsuit:
[jumpsuit_style]
" - if(CAN_SCAR in pref_species.species_traits) + if((HAS_FLESH in pref_species.species_traits) || (HAS_BONE in pref_species.species_traits)) dat += "
Temporal Scarring:
[(persistent_scars) ? "Enabled" : "Disabled"]" dat += "Clear scar slots" dat += "Uplink Location:[uplink_spawn_loc]" diff --git a/code/modules/clothing/glasses/_glasses.dm b/code/modules/clothing/glasses/_glasses.dm index 01effea6f2..350a577fb1 100644 --- a/code/modules/clothing/glasses/_glasses.dm +++ b/code/modules/clothing/glasses/_glasses.dm @@ -96,7 +96,7 @@ throw_speed = 4 attack_verb = list("sliced") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/clothing/glasses/meson/eyepatch name = "eyepatch mesons" @@ -180,7 +180,7 @@ throw_speed = 4 attack_verb = list("sliced") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED vision_correction = 1 glass_colour_type = /datum/client_colour/glass_colour/lightgreen @@ -237,7 +237,7 @@ throw_speed = 4 attack_verb = list("sliced") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/clothing/glasses/sunglasses/garb/supergarb name = "black giga gar glasses" @@ -257,7 +257,7 @@ throw_speed = 4 attack_verb = list("sliced") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED glass_colour_type = /datum/client_colour/glass_colour/orange /obj/item/clothing/glasses/sunglasses/gar/supergar diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm index c745cd74f0..9ca98b0bca 100644 --- a/code/modules/clothing/glasses/hud.dm +++ b/code/modules/clothing/glasses/hud.dm @@ -70,7 +70,7 @@ flash_protect = -2 lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE glass_colour_type = /datum/client_colour/glass_colour/green - + /obj/item/clothing/glasses/hud/health/night/syndicate name = "combat night vision health scanner HUD" desc = "An advanced shielded medical heads-up display that allows soldiers to approximate how much lead poisoning their allies have suffered in complete darkness." @@ -221,7 +221,7 @@ throw_speed = 4 attack_verb = list("sliced") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/clothing/glasses/hud/security/sunglasses/gars/supergars name = "giga HUD gar glasses" diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index b61743729f..cf7dbc7462 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -8,7 +8,7 @@ equip_delay_other = 40 max_integrity = 250 resistance_flags = NONE - armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50, "wound" = 15) + armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 50, "wound" = 10) /obj/item/clothing/suit/armor/Initialize() @@ -58,7 +58,7 @@ icon_state = "hos" item_state = "greatcoat" body_parts_covered = CHEST|GROIN|ARMS|LEGS - armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 90, "wound" = 20) + armor = list("melee" = 30, "bullet" = 30, "laser" = 30, "energy" = 10, "bomb" = 25, "bio" = 0, "rad" = 0, "fire" = 70, "acid" = 90, "wound" = 10) cold_protection = CHEST|GROIN|LEGS|ARMS heat_protection = CHEST|GROIN|LEGS|ARMS strip_delay = 80 @@ -148,7 +148,7 @@ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS cold_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - armor = list("melee" = 50, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80, "wound" = 30) + armor = list("melee" = 50, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 80, "acid" = 80, "wound" = 20) blocks_shove_knockdown = TRUE strip_delay = 80 equip_delay_other = 60 diff --git a/code/modules/food_and_drinks/drinks/drinks/bottle.dm b/code/modules/food_and_drinks/drinks/drinks/bottle.dm index d87eb8fbc0..e31a9704df 100644 --- a/code/modules/food_and_drinks/drinks/drinks/bottle.dm +++ b/code/modules/food_and_drinks/drinks/drinks/bottle.dm @@ -87,7 +87,7 @@ hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("stabbed", "slashed", "attacked") var/icon/broken_outline = icon('icons/obj/drinks.dmi', "broken") - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/broken_bottle/Initialize() . = ..() diff --git a/code/modules/food_and_drinks/food/snacks.dm b/code/modules/food_and_drinks/food/snacks.dm index adb8e47c94..45b64fbece 100644 --- a/code/modules/food_and_drinks/food/snacks.dm +++ b/code/modules/food_and_drinks/food/snacks.dm @@ -247,21 +247,9 @@ All foods are distributed among various categories. Use common sense. to_chat(user, "You cannot slice [src] here! You need a table or at least a tray.") return FALSE - var/slices_lost = 0 - if (accuracy >= IS_SHARP_ACCURATE) - user.visible_message( \ - "[user] slices [src].", \ - "You slice [src]." \ - ) - else - user.visible_message( \ - "[user] inaccurately slices [src] with [W]!", \ - "You inaccurately slice [src] with your [W]!" \ - ) - slices_lost = rand(1,min(1,round(slices_num/2))) - + user.visible_message("[user] slices [src].", "You slice [src].") var/reagents_per_slice = reagents.total_volume/slices_num - for(var/i=1 to (slices_num-slices_lost)) + for(var/i=1 to slices_num) var/obj/item/reagent_containers/food/snacks/slice = new slice_path (loc) initialize_slice(slice, reagents_per_slice) qdel(src) diff --git a/code/modules/goonchat/browserassets/css/browserOutput.css b/code/modules/goonchat/browserassets/css/browserOutput.css index 93c733391e..2669a3634a 100644 --- a/code/modules/goonchat/browserassets/css/browserOutput.css +++ b/code/modules/goonchat/browserassets/css/browserOutput.css @@ -303,7 +303,10 @@ h1.alert, h2.alert {color: #000000;} .passive {color: #660000;} .userdanger {color: #ff0000; font-weight: bold; font-size: 185%;} +.bolddanger {color: #c51e1e;font-weight: bold;} .danger {color: #ff0000;} +.tinydanger {color: #c51e1e; font-size: 85%;} +.smalldanger {color: #c51e1e; font-size: 90%;} .warning {color: #ff0000; font-style: italic;} .alertwarning {color: #FF0000; font-weight: bold} .boldwarning {color: #ff0000; font-style: italic; font-weight: bold} @@ -313,8 +316,9 @@ h1.alert, h2.alert {color: #000000;} .rose {color: #ff5050;} .info {color: #0000CC;} .notice {color: #000099;} -.tinynotice {color: #6685f5; font-style: italic; font-size: 85%;} -.smallnotice {color: #6685f5; font-style: italic; font-size: 90%;} +.tinynotice {color: #6685f5; font-style: italic; font-size: 85%;} +.smallnotice {color: #6685f5; font-size: 90%;} +.smallnoticeital {color: #6685f5; font-style: italic; font-size: 90%;} .boldnotice {color: #000099; font-weight: bold;} .adminnotice {color: #0000ff;} .adminhelp {color: #ff0000; font-weight: bold;} diff --git a/code/modules/hydroponics/hydroitemdefines.dm b/code/modules/hydroponics/hydroitemdefines.dm index 9b5983c8e9..abf6632939 100644 --- a/code/modules/hydroponics/hydroitemdefines.dm +++ b/code/modules/hydroponics/hydroitemdefines.dm @@ -82,7 +82,7 @@ custom_materials = list(/datum/material/iron = 15000) attack_verb = list("chopped", "torn", "cut") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/hatchet/Initialize() . = ..() diff --git a/code/modules/mining/equipment/kinetic_crusher.dm b/code/modules/mining/equipment/kinetic_crusher.dm index 745c46b131..ab1d7a3d2e 100644 --- a/code/modules/mining/equipment/kinetic_crusher.dm +++ b/code/modules/mining/equipment/kinetic_crusher.dm @@ -17,7 +17,7 @@ custom_materials = list(/datum/material/iron=1150, /datum/material/glass=2075) hitsound = 'sound/weapons/bladeslice.ogg' attack_verb = list("smashed", "crushed", "cleaved", "chopped", "pulped") - sharpness = IS_SHARP + sharpness = SHARP_EDGED actions_types = list(/datum/action/item_action/toggle_light) var/list/trophies = list() var/charged = TRUE diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm index 50a3dec9dd..27259ce812 100644 --- a/code/modules/mining/equipment/mining_tools.dm +++ b/code/modules/mining/equipment/mining_tools.dm @@ -143,7 +143,7 @@ w_class = WEIGHT_CLASS_NORMAL custom_materials = list(/datum/material/iron=350) attack_verb = list("bashed", "bludgeoned", "thrashed", "whacked") - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/shovel/Initialize() . = ..() @@ -181,4 +181,4 @@ w_class = WEIGHT_CLASS_NORMAL toolspeed = 0.7 attack_verb = list("slashed", "impaled", "stabbed", "sliced") - sharpness = IS_SHARP + sharpness = SHARP_EDGED diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index bfdb731869..8a7ae3ab39 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -659,7 +659,7 @@ hitsound = 'sound/weapons/bladeslice.ogg' hitsound_on = 'sound/weapons/bladeslice.ogg' w_class = WEIGHT_CLASS_BULKY - sharpness = IS_SHARP + sharpness = SHARP_EDGED faction_bonus_force = 30 nemesis_factions = list("mining", "boss") var/transform_cooldown @@ -765,7 +765,7 @@ lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' flags_1 = CONDUCT_1 - sharpness = IS_SHARP + sharpness = SHARP_EDGED w_class = WEIGHT_CLASS_BULKY force = 1 throwforce = 1 diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm index d3dbfac8c8..42d4a78433 100644 --- a/code/modules/mob/living/bloodcrawl.dm +++ b/code/modules/mob/living/bloodcrawl.dm @@ -73,7 +73,7 @@ if(victim.stat == CONSCIOUS) src.visible_message("[victim] kicks free of the blood pool just before entering it!", null, "You hear splashing and struggling.") - else if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/consumable/ethanol/demonsblood)) + else if(victim.reagents?.has_reagent(/datum/reagent/consumable/ethanol/demonsblood, needs_metabolizing = TRUE)) visible_message("Something prevents [victim] from entering the pool!", "A strange force is blocking [victim] from entering!", "You hear a splash and a thud.") else victim.forceMove(src) @@ -104,7 +104,7 @@ if(!victim) return FALSE - if(victim.reagents && victim.reagents.has_reagent(/datum/reagent/consumable/ethanol/devilskiss)) + if(victim.reagents?.has_reagent(/datum/reagent/consumable/ethanol/devilskiss, needs_metabolizing = TRUE)) to_chat(src, "AAH! THEIR FLESH! IT BURNS!") adjustBruteLoss(25) //I can't use adjustHealth() here because bloodcrawl affects /mob/living and adjustHealth() only affects simple mobs var/found_bloodpool = FALSE diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 4b7e27656b..33d6f09c5a 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -92,17 +92,8 @@ if(!all_wounds || !(user.a_intent == INTENT_HELP || user == src)) return ..() - // The following priority/nonpriority searching is so that if we have two wounds on a limb that use the same item for treatment (gauze can bandage cuts AND splint broken bones), - // we prefer whichever wound is not already treated (ignore the splinted broken bone for the open cut). If there's no priority wounds that this can treat, go through the - // non-priority ones randomly. - var/list/nonpriority_wounds = list() - for(var/datum/wound/W in shuffle(all_wounds)) - if(!W.treat_priority) - nonpriority_wounds += W - else if(W.treat_priority && W.try_treating(I, user)) - return 1 - - for(var/datum/wound/W in shuffle(nonpriority_wounds)) + for(var/i in shuffle(all_wounds)) + var/datum/wound/W = i if(W.try_treating(I, user)) return 1 @@ -1225,16 +1216,16 @@ /** * generate_fake_scars()- for when you want to scar someone, but you don't want to hurt them first. These scars don't count for temporal scarring (hence, fake) * - * If you want a specific wound scar, pass that wound type as the second arg, otherwise you can pass a list like WOUND_LIST_CUT to generate a random cut scar. + * If you want a specific wound scar, pass that wound type as the second arg, otherwise you can pass a list like WOUND_LIST_SLASH to generate a random cut scar. * * Arguments: * * num_scars- A number for how many scars you want to add - * * forced_type- Which wound or category of wounds you want to choose from, WOUND_LIST_BONE, WOUND_LIST_CUT, or WOUND_LIST_BURN (or some combination). If passed a list, picks randomly from the listed wounds. Defaults to all 3 types + * * forced_type- Which wound or category of wounds you want to choose from, WOUND_LIST_BLUNT, WOUND_LIST_SLASH, or WOUND_LIST_BURN (or some combination). If passed a list, picks randomly from the listed wounds. Defaults to all 3 types */ /mob/living/carbon/proc/generate_fake_scars(num_scars, forced_type) for(var/i in 1 to num_scars) - var/datum/scar/S = new - var/obj/item/bodypart/BP = pick(bodyparts) + var/datum/scar/scaries = new + var/obj/item/bodypart/scar_part = pick(bodyparts) var/wound_type if(forced_type) @@ -1243,9 +1234,17 @@ else wound_type = forced_type else - wound_type = pick(WOUND_LIST_BONE + WOUND_LIST_CUT + WOUND_LIST_BURN) + wound_type = pick(GLOB.global_all_wound_types) - var/datum/wound/W = new wound_type - S.generate(BP, W) - S.fake = TRUE - QDEL_NULL(W) + var/datum/wound/phantom_wound = new wound_type + scaries.generate(scar_part, phantom_wound) + scaries.fake = TRUE + QDEL_NULL(phantom_wound) + +/** + * get_biological_state is a helper used to see what kind of wounds we roll for. By default we just assume carbons (read:monkeys) are flesh and bone, but humans rely on their species datums + * + * go look at the species def for more info [/datum/species/proc/get_biological_state] + */ +/mob/living/carbon/proc/get_biological_state() + return BIO_FLESH_BONE diff --git a/code/modules/mob/living/carbon/carbon_defense.dm b/code/modules/mob/living/carbon/carbon_defense.dm index 196cec849d..66a0b7869d 100644 --- a/code/modules/mob/living/carbon/carbon_defense.dm +++ b/code/modules/mob/living/carbon/carbon_defense.dm @@ -76,7 +76,7 @@ if(!affecting) //missing limb? we select the first bodypart (you can never have zero, because of chest) affecting = bodyparts[1] SEND_SIGNAL(I, COMSIG_ITEM_ATTACK_ZONE, src, user, affecting) - send_item_attack_message(I, user, affecting.name, totitemdamage) + send_item_attack_message(I, user, affecting.name, affecting, totitemdamage) I.do_stagger_action(src, user, totitemdamage) if(I.force) apply_damage(totitemdamage, I.damtype, affecting, wound_bonus = I.wound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness()) //CIT CHANGE - replaces I.force with totitemdamage @@ -100,12 +100,6 @@ head.add_mob_blood(src) update_inv_head() - //dismemberment - var/probability = I.get_dismemberment_chance(affecting) - if(prob(probability)) - if(affecting.dismember(I.damtype)) - I.add_mob_blood(src) - playsound(get_turf(src), I.get_dismember_sound(), 80, 1) return TRUE //successful attack /mob/living/carbon/attack_drone(mob/living/simple_animal/drone/user) @@ -132,9 +126,10 @@ if(S.next_step(user, act_intent)) return TRUE - for(var/datum/wound/W in all_wounds) + for(var/i in all_wounds) + var/datum/wound/W = i if(W.try_handling(user)) - return 1 + return TRUE /mob/living/carbon/attack_paw(mob/living/carbon/monkey/M) @@ -151,14 +146,14 @@ if(M.a_intent == INTENT_HELP) help_shake_act(M) - return 0 + return FALSE . = ..() if(.) //successful monkey bite. for(var/thing in M.diseases) var/datum/disease/D = thing ForceContractDisease(D) - return 1 + return TRUE /mob/living/carbon/attack_slime(mob/living/simple_animal/slime/M) @@ -400,7 +395,7 @@ to_chat(src, "Your eyes are really starting to hurt. This can't be good for you!") if(has_bane(BANE_LIGHT)) mind.disrupt_spells(-500) - return 1 + return TRUE else if(damage == 0) // just enough protection if(prob(20)) to_chat(src, "Something bright flashes in the corner of your vision!") @@ -475,3 +470,35 @@ var/obj/item/bodypart/limb = get_bodypart(zone) if(!limb) return + +/mob/living/carbon/send_item_attack_message(obj/item/I, mob/living/user, hit_area, obj/item/bodypart/hit_bodypart, totitemdamage) + var/message_verb = "attacked" + if(length(I.attack_verb)) + message_verb = "[pick(I.attack_verb)]" + else if(!I.force) + return + + var/extra_wound_details = "" + if(I.damtype == BRUTE && hit_bodypart.can_dismember()) + var/mangled_state = hit_bodypart.get_mangled_state() + var/bio_state = get_biological_state() + if(mangled_state == BODYPART_MANGLED_BOTH) + extra_wound_details = ", threatening to sever it entirely" + else if((mangled_state == BODYPART_MANGLED_FLESH && I.get_sharpness()) || (mangled_state & BODYPART_MANGLED_BONE && bio_state == BIO_JUST_BONE)) + extra_wound_details = ", [I.get_sharpness() == SHARP_EDGED ? "slicing" : "piercing"] through to the bone" + else if((mangled_state == BODYPART_MANGLED_BONE && I.get_sharpness()) || (mangled_state & BODYPART_MANGLED_FLESH && bio_state == BIO_JUST_FLESH)) + extra_wound_details = ", [I.get_sharpness() == SHARP_EDGED ? "slicing" : "piercing"] at the remaining tissue" + + var/message_hit_area = "" + if(hit_area) + message_hit_area = " in the [hit_area]" + var/attack_message = "[src] is [message_verb][message_hit_area] with [I][extra_wound_details]!" + var/attack_message_local = "You're [message_verb][message_hit_area] with [I][extra_wound_details]!" + if(user in viewers(src, null)) + attack_message = "[user] [message_verb] [src][message_hit_area] with [I][extra_wound_details]!" + attack_message_local = "[user] [message_verb] you[message_hit_area] with [I][extra_wound_details]!" + if(user == src) + attack_message_local = "You [message_verb] yourself[message_hit_area] with [I][extra_wound_details]" + visible_message("[attack_message]",\ + "[attack_message_local]", null, COMBAT_MESSAGE_RANGE) + return TRUE diff --git a/code/modules/mob/living/carbon/damage_procs.dm b/code/modules/mob/living/carbon/damage_procs.dm index ddf1019f2a..5c5a1d6d52 100644 --- a/code/modules/mob/living/carbon/damage_procs.dm +++ b/code/modules/mob/living/carbon/damage_procs.dm @@ -1,6 +1,6 @@ -/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE) +/mob/living/carbon/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) SEND_SIGNAL(src, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone) var/hit_percent = (100-blocked)/100 if(!forced && hit_percent <= 0) @@ -202,7 +202,7 @@ //Damages ONE bodypart randomly selected from damagable ones. //It automatically updates damage overlays if necessary //It automatically updates health status -/mob/living/carbon/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE) +/mob/living/carbon/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) var/list/obj/item/bodypart/parts = get_damageable_bodyparts() if(!parts.len) return diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm index be046a3713..5eabae16f7 100644 --- a/code/modules/mob/living/carbon/examine.dm +++ b/code/modules/mob/living/carbon/examine.dm @@ -44,7 +44,8 @@ msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!\n" else msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!\n" - for(var/datum/wound/W in BP.wounds) + for(var/i in BP.wounds) + var/datum/wound/W = i msg += "[W.get_examine_description(user)]\n" for(var/X in disabled) @@ -109,7 +110,7 @@ switch(scar_severity) if(1 to 2) - msg += "[t_He] [t_has] visible scarring, you can look again to take a closer look...\n" + msg += "[t_He] [t_has] visible scarring, you can look again to take a closer look...\n" if(3 to 4) msg += "[t_He] [t_has] several bad scars, you can look again to take a closer look...\n" if(5 to 6) diff --git a/code/modules/mob/living/carbon/human/damage_procs.dm b/code/modules/mob/living/carbon/human/damage_procs.dm index 5cd00b7e6a..04ec1196fd 100644 --- a/code/modules/mob/living/carbon/human/damage_procs.dm +++ b/code/modules/mob/living/carbon/human/damage_procs.dm @@ -1,5 +1,5 @@ // depending on the species, it will run the corresponding apply_damage code there -/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE) +/mob/living/carbon/human/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) return dna.species.apply_damage(damage, damagetype, def_zone, blocked, src, forced, spread_damage, wound_bonus, bare_wound_bonus, sharpness) diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 285134201f..1fbc098e42 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -163,8 +163,9 @@ msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] stuck to [t_his] [BP.name]!\n" else msg += "[t_He] [t_has] \a [icon2html(I, user)] [I] embedded in [t_his] [BP.name]!\n" - for(var/datum/wound/W in BP.wounds) - msg += "[W.get_examine_description(user)]\n" + for(var/i in BP.wounds) + var/datum/wound/iter_wound = i + msg += "[iter_wound.get_examine_description(user)]\n" for(var/X in disabled) var/obj/item/bodypart/BP = X @@ -270,7 +271,12 @@ bleeding_limbs += BP var/num_bleeds = LAZYLEN(bleeding_limbs) - var/bleed_text = "[t_He] [t_is] bleeding from [t_his]" + var/list/bleed_text + if(appears_dead) + bleed_text = list("Blood is visible in [t_his] open") + else + bleed_text = list("[t_He] [t_is] bleeding from [t_his]") + switch(num_bleeds) if(1 to 2) bleed_text += " [bleeding_limbs[1].name][num_bleeds == 2 ? " and [bleeding_limbs[2].name]" : ""]" @@ -280,8 +286,15 @@ bleed_text += " [BP.name]," bleed_text += " and [bleeding_limbs[num_bleeds].name]" - bleed_text += "!\n" - msg += bleed_text + + if(appears_dead) + bleed_text += ", but it has pooled and is not flowing.\n" + else + if(reagents.has_reagent(/datum/reagent/toxin/heparin, needs_metabolizing = TRUE)) + bleed_text += " incredibly quickly" + + bleed_text += "!\n" + msg += bleed_text.Join() if(reagents.has_reagent(/datum/reagent/teslium)) msg += "[t_He] [t_is] emitting a gentle blue glow!\n" @@ -365,7 +378,7 @@ switch(scar_severity) if(1 to 2) - msg += "[t_He] [t_has] visible scarring, you can look again to take a closer look...\n" + msg += "[t_He] [t_has] visible scarring, you can look again to take a closer look...\n" if(3 to 4) msg += "[t_He] [t_has] several bad scars, you can look again to take a closer look...\n" if(5 to 6) diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 8672c0e83d..af95b9e1b7 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -154,19 +154,29 @@ /// For use formatting all of the scars this human has for saving for persistent scarring /mob/living/carbon/human/proc/format_scars() - if(!all_scars) + var/list/missing_bodyparts = get_missing_limbs() + if(!all_scars && !length(missing_bodyparts)) return var/scars = "" + for(var/i in missing_bodyparts) + var/datum/scar/scaries = new + scars += "[scaries.format_amputated(i)]" for(var/i in all_scars) - var/datum/scar/S = i - scars += "[S.format()];" + var/datum/scar/scaries = i + scars += "[scaries.format()];" return scars /// Takes a single scar from the persistent scar loader and recreates it from the saved data /mob/living/carbon/human/proc/load_scar(scar_line) var/list/scar_data = splittext(scar_line, "|") - if(LAZYLEN(scar_data) != 4) + if(LAZYLEN(scar_data) != SCAR_SAVE_LENGTH) return // invalid, should delete - var/obj/item/bodypart/BP = get_bodypart("[scar_data[SCAR_SAVE_ZONE]]") - var/datum/scar/S = new - return S.load(BP, scar_data[SCAR_SAVE_DESC], scar_data[SCAR_SAVE_PRECISE_LOCATION], text2num(scar_data[SCAR_SAVE_SEVERITY])) + var/version = text2num(scar_data[SCAR_SAVE_VERS]) + if(!version || version < SCAR_CURRENT_VERSION) // get rid of old scars + 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])) + +/mob/living/carbon/human/get_biological_state() + return dna.species.get_biological_state() diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index ba6fde421d..84d1f5a270 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -73,7 +73,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/datum/outfit/outfit_important_for_life // A path to an outfit that is important for species life e.g. plasmaman outfit // species-only traits. Can be found in DNA.dm - var/list/species_traits = list(CAN_SCAR) //by default they can scar unless set to something else + var/list/species_traits = list(HAS_FLESH,HAS_BONE) //by default they can scar and have bones/flesh unless set to something else // generic traits tied to having the species var/list/inherent_traits = list() var/inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID @@ -1743,20 +1743,13 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) apply_damage(totitemdamage * weakness, I.damtype, def_zone, armor_block, H, wound_bonus = Iwound_bonus, bare_wound_bonus = I.bare_wound_bonus, sharpness = I.get_sharpness()) - H.send_item_attack_message(I, user, hit_area, totitemdamage) + H.send_item_attack_message(I, user, hit_area, affecting, totitemdamage) I.do_stagger_action(H, user, totitemdamage) if(!totitemdamage) return 0 //item force is zero - //dismemberment - var/probability = I.get_dismemberment_chance(affecting) - if(prob(probability) || (HAS_TRAIT(H, TRAIT_EASYDISMEMBER) && prob(probability))) //try twice - if(affecting.dismember(I.damtype)) - I.add_mob_blood(H) - playsound(get_turf(H), I.get_dismember_sound(), 80, 1) - var/bloody = 0 if(((I.damtype == BRUTE) && I.force && prob(25 + (I.force * 2)))) if(affecting.status == BODYPART_ORGANIC) @@ -1956,7 +1949,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) append_message += ", causing them to drop [target_held_item]" log_combat(user, target, "shoved", append_message) -/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE) +/datum/species/proc/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) SEND_SIGNAL(H, COMSIG_MOB_APPLY_DAMGE, damage, damagetype, def_zone, wound_bonus, bare_wound_bonus, sharpness) // make sure putting wound_bonus here doesn't screw up other signals or uses for this signal var/hit_percent = (100-(blocked+armor))/100 hit_percent = (hit_percent * (100-H.physiology.damage_resistance))/100 @@ -2032,6 +2025,25 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) // called before a projectile hit return +/** + + + + * The human species version of [/mob/living/carbon/proc/get_biological_state]. Depends on the HAS_FLESH and HAS_BONE species traits, having bones lets you have bone wounds, having flesh lets you have burn, slash, and piercing wounds + + + + */ + + + +/datum/species/proc/get_biological_state(mob/living/carbon/human/H) + . = BIO_INORGANIC + if(HAS_FLESH in species_traits) + . |= BIO_JUST_FLESH + if(HAS_BONE in species_traits) + . |= BIO_JUST_BONE + ///////////// //BREATHING// ///////////// 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 409781efb2..9036aa10ec 100644 --- a/code/modules/mob/living/carbon/human/species_types/abductors.dm +++ b/code/modules/mob/living/carbon/human/species_types/abductors.dm @@ -3,7 +3,7 @@ id = "abductor" say_mod = "gibbers" sexes = FALSE - species_traits = list(NOBLOOD,NOEYES,NOGENITALS,NOAROUSAL,CAN_SCAR) + species_traits = list(NOBLOOD,NOEYES,NOGENITALS,NOAROUSAL,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_VIRUSIMMUNE,TRAIT_CHUNKYFINGERS,TRAIT_NOHUNGER,TRAIT_NOBREATH) mutanttongue = /obj/item/organ/tongue/abductor diff --git a/code/modules/mob/living/carbon/human/species_types/angel.dm b/code/modules/mob/living/carbon/human/species_types/angel.dm index 2d43c9964e..81c016ec96 100644 --- a/code/modules/mob/living/carbon/human/species_types/angel.dm +++ b/code/modules/mob/living/carbon/human/species_types/angel.dm @@ -2,7 +2,7 @@ name = "Angel" id = "angel" default_color = "FFFFFF" - species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,CAN_SCAR) + species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE) mutant_bodyparts = list("tail_human" = "None", "ears" = "None", "wings" = "Angel") use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM no_equip = list(SLOT_BACK) diff --git a/code/modules/mob/living/carbon/human/species_types/bugmen.dm b/code/modules/mob/living/carbon/human/species_types/bugmen.dm index a51dadb523..fb52d10be4 100644 --- a/code/modules/mob/living/carbon/human/species_types/bugmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/bugmen.dm @@ -3,7 +3,7 @@ id = "insect" say_mod = "chitters" default_color = "00FF00" - species_traits = list(LIPS,EYECOLOR,HAIR,FACEHAIR,MUTCOLORS,HORNCOLOR,WINGCOLOR,CAN_SCAR) + species_traits = list(LIPS,EYECOLOR,HAIR,FACEHAIR,MUTCOLORS,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "insect_wings" = "None", "insect_fluff" = "None", "mam_snouts" = "None", "taur" = "None", "insect_markings" = "None") diff --git a/code/modules/mob/living/carbon/human/species_types/dullahan.dm b/code/modules/mob/living/carbon/human/species_types/dullahan.dm index 4e5aa57b0a..29341646a0 100644 --- a/code/modules/mob/living/carbon/human/species_types/dullahan.dm +++ b/code/modules/mob/living/carbon/human/species_types/dullahan.dm @@ -2,8 +2,8 @@ name = "Dullahan" id = "dullahan" default_color = "FFFFFF" - species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS) - inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH,CAN_SCAR) + species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE) + inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH) mutant_bodyparts = list("tail_human" = "None", "ears" = "None", "deco_wings" = "None") use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM mutant_brain = /obj/item/organ/brain/dullahan diff --git a/code/modules/mob/living/carbon/human/species_types/dwarves.dm b/code/modules/mob/living/carbon/human/species_types/dwarves.dm index 009dba7707..3c1d877543 100644 --- a/code/modules/mob/living/carbon/human/species_types/dwarves.dm +++ b/code/modules/mob/living/carbon/human/species_types/dwarves.dm @@ -6,7 +6,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) // name = "Dwarf" id = "dwarf" //Also called Homo sapiens pumilionis default_color = "FFFFFF" - species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,CAN_SCAR) + species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_DWARF,TRAIT_SNOB) limbs_id = "human" use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM diff --git a/code/modules/mob/living/carbon/human/species_types/flypeople.dm b/code/modules/mob/living/carbon/human/species_types/flypeople.dm index c3ec8b42ea..ca5b683134 100644 --- a/code/modules/mob/living/carbon/human/species_types/flypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/flypeople.dm @@ -2,7 +2,7 @@ name = "Anthromorphic Fly" id = "fly" say_mod = "buzzes" - species_traits = list(NOEYES,CAN_SCAR) + species_traits = list(NOEYES,HAS_FLESH,HAS_BONE) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BUG mutanttongue = /obj/item/organ/tongue/fly mutantliver = /obj/item/organ/liver/fly diff --git a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm b/code/modules/mob/living/carbon/human/species_types/furrypeople.dm index d87b0c074c..f4713f3005 100644 --- a/code/modules/mob/living/carbon/human/species_types/furrypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/furrypeople.dm @@ -3,7 +3,7 @@ id = "mammal" default_color = "4B4B4B" icon_limbs = DEFAULT_BODYPART_ICON_CITADEL - species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,HORNCOLOR,WINGCOLOR,CAN_SCAR) + species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAIR,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE) inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_BEAST mutant_bodyparts = list("mcolor" = "FFFFFF","mcolor2" = "FFFFFF","mcolor3" = "FFFFFF", "mam_snouts" = "Husky", "mam_tail" = "Husky", "mam_ears" = "Husky", "deco_wings" = "None", "mam_body_markings" = "Husky", "taur" = "None", "horns" = "None", "legs" = "Plantigrade", "meat_type" = "Mammalian") @@ -55,7 +55,7 @@ say_mod = "hisses" default_color = "00FF00" icon_limbs = DEFAULT_BODYPART_ICON_CITADEL - species_traits = list(MUTCOLORS,EYECOLOR,LIPS,CAN_SCAR) + species_traits = list(MUTCOLORS,EYECOLOR,LIPS,HAS_FLESH,HAS_BONE) mutant_bodyparts = list("xenotail"="Xenomorph Tail","xenohead"="Standard","xenodorsal"="Standard", "mam_body_markings" = "Xeno","mcolor" = "0F0","mcolor2" = "0F0","mcolor3" = "0F0","taur" = "None", "legs" = "Digitigrade") attack_verb = "slash" attack_sound = 'sound/weapons/slash.ogg' diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm index b164fb1ba0..40f65968bf 100644 --- a/code/modules/mob/living/carbon/human/species_types/humans.dm +++ b/code/modules/mob/living/carbon/human/species_types/humans.dm @@ -3,7 +3,7 @@ id = "human" default_color = "FFFFFF" - species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS_PARTSONLY,WINGCOLOR,CAN_SCAR) + species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,MUTCOLORS_PARTSONLY,WINGCOLOR,HAS_FLESH,HAS_BONE) mutant_bodyparts = list("mcolor" = "FFFFFF", "mcolor2" = "FFFFFF","mcolor3" = "FFFFFF","tail_human" = "None", "ears" = "None", "taur" = "None", "deco_wings" = "None") use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM skinned_type = /obj/item/stack/sheet/animalhide/human diff --git a/code/modules/mob/living/carbon/human/species_types/ipc.dm b/code/modules/mob/living/carbon/human/species_types/ipc.dm index 96efaebd74..411defdcaf 100644 --- a/code/modules/mob/living/carbon/human/species_types/ipc.dm +++ b/code/modules/mob/living/carbon/human/species_types/ipc.dm @@ -6,7 +6,7 @@ icon_limbs = DEFAULT_BODYPART_ICON_CITADEL blacklisted = 0 sexes = 0 - species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING) + species_traits = list(MUTCOLORS,NOEYES,NOTRANSSTING,HAS_FLESH,HAS_BONE) inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID mutant_bodyparts = list("ipc_screen" = "Blank", "ipc_antenna" = "None") meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc diff --git a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm index e97db7aced..b18f5522dd 100644 --- a/code/modules/mob/living/carbon/human/species_types/jellypeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/jellypeople.dm @@ -4,7 +4,7 @@ id = "jelly" default_color = "00FF90" say_mod = "chirps" - species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,WINGCOLOR) + species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,WINGCOLOR,HAS_FLESH,HAS_BONE) mutantlungs = /obj/item/organ/lungs/slime mutant_heart = /obj/item/organ/heart/slime mutant_bodyparts = list("mcolor" = "FFFFFF", "mam_tail" = "None", "mam_ears" = "None", "mam_snouts" = "None", "taur" = "None", "deco_wings" = "None") diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index a424969175..960dd0c3d3 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -4,7 +4,7 @@ id = "lizard" say_mod = "hisses" default_color = "00FF00" - species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR,CAN_SCAR) + species_traits = list(MUTCOLORS,EYECOLOR,HAIR,FACEHAIR,LIPS,HORNCOLOR,WINGCOLOR,HAS_FLESH,HAS_BONE) mutant_bodyparts = list("tail_lizard", "snout", "spines", "horns", "frills", "body_markings", "legs", "taur", "deco_wings") inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID|MOB_REPTILE mutanttongue = /obj/item/organ/tongue/lizard diff --git a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm index 8e8c65b15e..ecb27a06b5 100644 --- a/code/modules/mob/living/carbon/human/species_types/mushpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/mushpeople.dm @@ -8,7 +8,7 @@ nojumpsuit = TRUE say_mod = "poofs" //what does a mushroom sound like - species_traits = list(MUTCOLORS, NOEYES, NO_UNDERWEAR,NOGENITALS,NOAROUSAL,CAN_SCAR) + species_traits = list(MUTCOLORS, NOEYES, NO_UNDERWEAR,NOGENITALS,NOAROUSAL,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_NOBREATH) speedmod = 1.5 //faster than golems but not by much diff --git a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm index 91d3135ae1..2d9e2ccfc3 100644 --- a/code/modules/mob/living/carbon/human/species_types/plasmamen.dm +++ b/code/modules/mob/living/carbon/human/species_types/plasmamen.dm @@ -4,7 +4,7 @@ say_mod = "rattles" sexes = 0 meat = /obj/item/stack/sheet/mineral/plasma - species_traits = list(NOBLOOD,NOTRANSSTING,NOGENITALS) + species_traits = list(NOBLOOD,NOTRANSSTING,NOGENITALS,HAS_BONE) inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RADIMMUNE,TRAIT_NOHUNGER,TRAIT_CALCIUM_HEALER) inherent_biotypes = MOB_HUMANOID|MOB_MINERAL mutantlungs = /obj/item/organ/lungs/plasmaman diff --git a/code/modules/mob/living/carbon/human/species_types/podpeople.dm b/code/modules/mob/living/carbon/human/species_types/podpeople.dm index 4806d4a6a1..758fdf71ee 100644 --- a/code/modules/mob/living/carbon/human/species_types/podpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/podpeople.dm @@ -3,7 +3,7 @@ name = "Anthromorphic Plant" id = "pod" default_color = "59CE00" - species_traits = list(MUTCOLORS,EYECOLOR,CAN_SCAR) + species_traits = list(MUTCOLORS,EYECOLOR,CAN_SCAR,HAS_FLESH,HAS_BONE) attack_verb = "slash" attack_sound = 'sound/weapons/slice.ogg' miss_sound = 'sound/weapons/slashmiss.ogg' 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 2776c6d919..610bf37f9a 100644 --- a/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/shadowpeople.dm @@ -9,8 +9,8 @@ blacklisted = 1 ignored_by = list(/mob/living/simple_animal/hostile/faithless) meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/shadow - species_traits = list(NOBLOOD,NOEYES,CAN_SCAR) - inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_NOBREATH,CAN_SCAR) + species_traits = list(NOBLOOD,NOEYES,HAS_FLESH,HAS_BONE) + inherent_traits = list(TRAIT_RADIMMUNE,TRAIT_VIRUSIMMUNE,TRAIT_NOBREATH) dangerous_existence = 1 mutanteyes = /obj/item/organ/eyes/night_vision @@ -164,7 +164,7 @@ righthand_file = 'icons/mob/inhands/antag/changeling_righthand.dmi' item_flags = ABSTRACT | DROPDEL w_class = WEIGHT_CLASS_HUGE - sharpness = IS_SHARP + sharpness = SHARP_EDGED total_mass = TOTAL_MASS_HAND_REPLACEMENT /obj/item/light_eater/Initialize() diff --git a/code/modules/mob/living/carbon/human/species_types/skeletons.dm b/code/modules/mob/living/carbon/human/species_types/skeletons.dm index 78efddf70d..86451875d2 100644 --- a/code/modules/mob/living/carbon/human/species_types/skeletons.dm +++ b/code/modules/mob/living/carbon/human/species_types/skeletons.dm @@ -5,7 +5,7 @@ blacklisted = 0 sexes = 0 meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/skeleton - species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL) + species_traits = list(NOBLOOD,NOGENITALS,NOAROUSAL,HAS_BONE) inherent_traits = list(TRAIT_NOBREATH,TRAIT_RADIMMUNE,TRAIT_PIERCEIMMUNE,TRAIT_NOHUNGER,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_FAKEDEATH, TRAIT_CALCIUM_HEALER) inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID mutanttongue = /obj/item/organ/tongue/bone diff --git a/code/modules/mob/living/carbon/human/species_types/synthliz.dm b/code/modules/mob/living/carbon/human/species_types/synthliz.dm index af2e83ee0f..146fd37187 100644 --- a/code/modules/mob/living/carbon/human/species_types/synthliz.dm +++ b/code/modules/mob/living/carbon/human/species_types/synthliz.dm @@ -4,7 +4,7 @@ icon_limbs = DEFAULT_BODYPART_ICON_CITADEL say_mod = "beeps" default_color = "00FF00" - species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR) + species_traits = list(MUTCOLORS,NOTRANSSTING,EYECOLOR,LIPS,HAIR,HAS_FLESH,HAS_BONE) inherent_biotypes = MOB_ROBOTIC|MOB_HUMANOID mutant_bodyparts = list("ipc_antenna" = "Synthetic Lizard - Antennae","mam_tail" = "Synthetic Lizard", "mam_snouts" = "Synthetic Lizard - Snout", "legs" = "Digitigrade", "mam_body_markings" = "Synthetic Lizard - Plates", "taur" = "None") meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/ipc diff --git a/code/modules/mob/living/carbon/human/species_types/vampire.dm b/code/modules/mob/living/carbon/human/species_types/vampire.dm index 9c9220132c..9341622dfa 100644 --- a/code/modules/mob/living/carbon/human/species_types/vampire.dm +++ b/code/modules/mob/living/carbon/human/species_types/vampire.dm @@ -2,7 +2,7 @@ name = "Vampire" id = "vampire" default_color = "FFFFFF" - species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD) + species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,DRINKSBLOOD,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_NOHUNGER,TRAIT_NOBREATH) inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID mutant_bodyparts = list("mcolor" = "FFFFFF", "tail_human" = "None", "ears" = "None", "deco_wings" = "None") diff --git a/code/modules/mob/living/carbon/human/species_types/zombies.dm b/code/modules/mob/living/carbon/human/species_types/zombies.dm index ab0838c873..1c745c0366 100644 --- a/code/modules/mob/living/carbon/human/species_types/zombies.dm +++ b/code/modules/mob/living/carbon/human/species_types/zombies.dm @@ -8,7 +8,7 @@ sexes = 0 blacklisted = 1 meat = /obj/item/reagent_containers/food/snacks/meat/slab/human/mutant/zombie - species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING,CAN_SCAR) + species_traits = list(NOBLOOD,NOZOMBIE,NOTRANSSTING,HAS_FLESH,HAS_BONE) inherent_traits = list(TRAIT_RESISTCOLD,TRAIT_RESISTHIGHPRESSURE,TRAIT_RESISTLOWPRESSURE,TRAIT_RADIMMUNE,TRAIT_EASYDISMEMBER,TRAIT_LIMBATTACHMENT,TRAIT_NOBREATH,TRAIT_NODEATH,TRAIT_FAKEDEATH) inherent_biotypes = MOB_UNDEAD|MOB_HUMANOID mutanttongue = /obj/item/organ/tongue/zombie @@ -44,7 +44,7 @@ /datum/species/zombie/infectious/spec_stun(mob/living/carbon/human/H,amount) . = min(20, amount) -/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE) +/datum/species/zombie/infectious/apply_damage(damage, damagetype = BRUTE, def_zone = null, blocked, mob/living/carbon/human/H, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) . = ..() if(.) regen_cooldown = world.time + REGENERATION_DELAY @@ -62,9 +62,9 @@ C.heal_overall_damage(heal_amt,heal_amt) C.adjustToxLoss(-heal_amt) for(var/i in C.all_wounds) - var/datum/wound/W = i - if(prob(4-W.severity)) - W.remove_wound() + var/datum/wound/iter_wound = i + if(prob(4-iter_wound.severity)) + iter_wound.remove_wound() if(!C.InCritical() && prob(4)) playsound(C, pick(spooks), 50, TRUE, 10) diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm index 012808647e..47c9062148 100644 --- a/code/modules/mob/living/damage_procs.dm +++ b/code/modules/mob/living/damage_procs.dm @@ -14,7 +14,7 @@ * * Returns TRUE if damage applied */ -/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE) +/mob/living/proc/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, spread_damage = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) var/hit_percent = (100-blocked)/100 if(!damage || (hit_percent <= 0)) return 0 @@ -245,7 +245,7 @@ update_stamina() // damage ONE external organ, organ gets randomly selected from damaged ones. -/mob/living/proc/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE) +/mob/living/proc/take_bodypart_damage(brute = 0, burn = 0, stamina = 0, updating_health = TRUE, required_status, check_armor = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) adjustBruteLoss(brute, FALSE) //zero as argument for no instant health update adjustFireLoss(burn, FALSE) adjustStaminaLoss(stamina, FALSE) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 9850afc1a3..f7bb9cda90 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -605,41 +605,55 @@ SEND_SIGNAL(item, COMSIG_ITEM_WEARERCROSSED, AM) /mob/living/proc/makeTrail(turf/target_turf, turf/start, direction) - if(!has_gravity()) + if(!has_gravity() || !isturf(start) || !blood_volume) return - var/blood_exists = FALSE + var/blood_exists = locate(/obj/effect/decal/cleanable/trail_holder) in start - for(var/obj/effect/decal/cleanable/trail_holder/C in start) //checks for blood splatter already on the floor - blood_exists = TRUE - if(isturf(start)) - var/trail_type = getTrail() - if(trail_type) - var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1) - if(blood_volume && blood_volume > max((BLOOD_VOLUME_NORMAL*blood_ratio)*(1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold - blood_volume = max(blood_volume - max(1, brute_ratio * 2), 0) //that depends on our brute damage. - var/newdir = get_dir(target_turf, start) - if(newdir != direction) - newdir = newdir | direction - if(newdir == 3) //N + S - newdir = NORTH - else if(newdir == 12) //E + W - newdir = EAST - if((newdir in GLOB.cardinals) && (prob(50))) - newdir = turn(get_dir(target_turf, start), 180) - if(!blood_exists) - new /obj/effect/decal/cleanable/trail_holder(start, get_static_viruses()) + var/trail_type = getTrail() + if(!trail_type) + return - for(var/obj/effect/decal/cleanable/trail_holder/TH in start) - if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled) - TH.existing_dirs += newdir - TH.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir)) - TH.transfer_mob_blood_dna(src) + var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1) + if(blood_volume < max(BLOOD_VOLUME_NORMAL*(1 - brute_ratio * 0.25), 0))//don't leave trail if blood volume below a threshold + return + + var/bleed_amount = bleedDragAmount() + blood_volume = max(blood_volume - bleed_amount, 0) //that depends on our brute damage. + var/newdir = get_dir(target_turf, start) + if(newdir != direction) + newdir = newdir | direction + if(newdir == (NORTH|SOUTH)) + newdir = NORTH + else if(newdir == (EAST|WEST)) + newdir = EAST + if((newdir in GLOB.cardinals) && (prob(50))) + newdir = turn(get_dir(target_turf, start), 180) + if(!blood_exists) + new /obj/effect/decal/cleanable/trail_holder(start, get_static_viruses()) + + for(var/obj/effect/decal/cleanable/trail_holder/TH in start) + if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled) + TH.existing_dirs += newdir + TH.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir)) + TH.transfer_mob_blood_dna(src) /mob/living/carbon/human/makeTrail(turf/T) if((NOBLOOD in dna.species.species_traits) || !is_bleeding() || bleedsuppress) return ..() +///Returns how much blood we're losing from being dragged a tile, from [mob/living/proc/makeTrail] +/mob/living/proc/bleedDragAmount() + var/brute_ratio = round(getBruteLoss() / maxHealth, 0.1) + return max(1, brute_ratio * 2) + +/mob/living/carbon/bleedDragAmount() + var/bleed_amount = 0 + for(var/i in all_wounds) + var/datum/wound/iter_wound = i + bleed_amount += iter_wound.drag_bleed_amount() + return bleed_amount + /mob/living/proc/getTrail() if(getBruteLoss() < 300) return pick("ltrails_1", "ltrails_2") diff --git a/code/modules/mob/living/silicon/damage_procs.dm b/code/modules/mob/living/silicon/damage_procs.dm index b89f249c80..7530630d74 100644 --- a/code/modules/mob/living/silicon/damage_procs.dm +++ b/code/modules/mob/living/silicon/damage_procs.dm @@ -1,5 +1,5 @@ -/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE) +/mob/living/silicon/apply_damage(damage = 0,damagetype = BRUTE, def_zone = null, blocked = FALSE, forced = FALSE, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) var/hit_percent = (100-blocked)/100 if(!damage || (!forced && hit_percent <= 0)) return 0 diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm index dc3c90cc64..30f469ec7f 100644 --- a/code/modules/mob/living/simple_animal/hostile/bear.dm +++ b/code/modules/mob/living/simple_animal/hostile/bear.dm @@ -33,7 +33,7 @@ melee_damage_upper = 15 wound_bonus = -5 bare_wound_bonus = 10 // BEAR wound bonus am i right - sharpness = TRUE + sharpness = SHARP_EDGED attack_verb_continuous = "claws" attack_verb_simple = "claw" attack_sound = 'sound/weapons/bladeslice.ogg' diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm index 4ea8a3c5dc..fd37bb26aa 100644 --- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm +++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm @@ -79,7 +79,7 @@ melee_damage_upper = 15 wound_bonus = -10 bare_wound_bonus = 20 - sharpness = TRUE + sharpness = SHARP_EDGED icon_state = "syndicate_knife" icon_living = "syndicate_knife" loot = list(/obj/effect/gibspawner/human) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 1102559aca..706bcc46f5 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -145,7 +145,7 @@ //How much bare wounding power it has var/bare_wound_bonus = 0 //If the attacks from this are sharp - var/sharpness = FALSE + var/sharpness = SHARP_NONE /mob/living/simple_animal/Initialize() . = ..() diff --git a/code/modules/ninja/energy_katana.dm b/code/modules/ninja/energy_katana.dm index e6d53d914f..00cfa94893 100644 --- a/code/modules/ninja/energy_katana.dm +++ b/code/modules/ninja/energy_katana.dm @@ -14,7 +14,7 @@ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") block_chance = 50 slot_flags = ITEM_SLOT_BELT - sharpness = IS_SHARP + sharpness = SHARP_EDGED max_integrity = 200 resistance_flags = LAVA_PROOF | FIRE_PROOF | ACID_PROOF var/datum/effect_system/spark_spread/spark_system diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 08252d4e05..77ff8e9d8d 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -84,7 +84,7 @@ throw_speed = 4 colour = "crimson" custom_materials = list(/datum/material/gold = 750) - sharpness = IS_SHARP + sharpness = SHARP_EDGED resistance_flags = FIRE_PROOF unique_reskin = list("Oak" = "pen-fountain-o", "Gold" = "pen-fountain-g", @@ -180,7 +180,7 @@ */ /obj/item/pen/edagger attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") //these wont show up if the pen is off - sharpness = IS_SHARP + sharpness = SHARP_EDGED var/on = FALSE embedding = list(embed_chance = EMBED_CHANCE) diff --git a/code/modules/projectiles/guns/energy/special.dm b/code/modules/projectiles/guns/energy/special.dm index 6489920b98..20e847326e 100644 --- a/code/modules/projectiles/guns/energy/special.dm +++ b/code/modules/projectiles/guns/energy/special.dm @@ -125,7 +125,7 @@ flags_1 = CONDUCT_1 attack_verb = list("attacked", "slashed", "cut", "sliced") force = 12 - sharpness = IS_SHARP + sharpness = SHARP_EDGED inaccuracy_modifier = 0.25 can_charge = 0 diff --git a/code/modules/projectiles/guns/magic/staff.dm b/code/modules/projectiles/guns/magic/staff.dm index b23b059d89..6ebdc5e7b8 100644 --- a/code/modules/projectiles/guns/magic/staff.dm +++ b/code/modules/projectiles/guns/magic/staff.dm @@ -83,7 +83,7 @@ force = 20 armour_penetration = 75 block_chance = 50 - sharpness = IS_SHARP + sharpness = SHARP_EDGED max_charges = 4 /obj/item/gun/magic/staff/spellblade/Initialize() diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 1e1559fc6a..199842d8e2 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -156,7 +156,7 @@ wound_bonus = CANT_WOUND /// For telling whether we want to roll for bone breaking or lacerations if we're bothering with wounds - sharpness = FALSE + sharpness = SHARP_NONE /obj/item/projectile/Initialize() . = ..() diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 6a081f9b03..bc0030afc3 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -8,4 +8,4 @@ flag = "bullet" hitsound_wall = "ricochet" impact_effect_type = /obj/effect/temp_visual/impact_effect - sharpness = TRUE \ No newline at end of file + sharpness = SHARP_EDGED \ No newline at end of file diff --git a/code/modules/projectiles/projectile/bullets/revolver.dm b/code/modules/projectiles/projectile/bullets/revolver.dm index c793e9f95e..c61ce57c1d 100644 --- a/code/modules/projectiles/projectile/bullets/revolver.dm +++ b/code/modules/projectiles/projectile/bullets/revolver.dm @@ -20,7 +20,7 @@ ricochet_auto_aim_angle = 10 ricochet_auto_aim_range = 3 wound_bonus = -35 - sharpness = TRUE + sharpness = SHARP_EDGED /obj/item/projectile/bullet/c38/match name = ".38 Match bullet" diff --git a/code/modules/projectiles/projectile/bullets/shotgun.dm b/code/modules/projectiles/projectile/bullets/shotgun.dm index 6e4a72aff0..cc98331004 100644 --- a/code/modules/projectiles/projectile/bullets/shotgun.dm +++ b/code/modules/projectiles/projectile/bullets/shotgun.dm @@ -4,12 +4,12 @@ /obj/item/projectile/bullet/shotgun_slug/executioner name = "executioner slug" // admin only, can dismember limbs - sharpness = TRUE + sharpness = SHARP_EDGED wound_bonus = 0 /obj/item/projectile/bullet/shotgun_slug/pulverizer name = "pulverizer slug" // admin only, can crush bones - sharpness = FALSE + sharpness = SHARP_NONE wound_bonus = 0 /obj/item/projectile/bullet/shotgun_beanbag @@ -17,7 +17,7 @@ damage = 10 stamina = 70 wound_bonus = 20 - sharpness = FALSE + sharpness = SHARP_NONE /obj/item/projectile/bullet/incendiary/shotgun name = "incendiary slug" diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index 0c3de579b6..d76f6af165 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -217,6 +217,9 @@ /datum/reagent/consumable/milk/on_mob_life(mob/living/carbon/M) if(HAS_TRAIT(M, TRAIT_CALCIUM_HEALER)) M.heal_bodypart_damage(1.5,0, 0) + for(var/i in M.all_wounds) + var/datum/wound/iter_wound = i + iter_wound.on_xadone(2) . = 1 else if(M.getBruteLoss() && prob(20)) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 07c80322ae..bcf1bc8e0a 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -171,7 +171,7 @@ //Applies brute and burn damage to the organ. Returns 1 if the damage-icon states changed at all. //Damage will not exceed max_damage using this proc //Cannot apply negative damage -/obj/item/bodypart/proc/receive_damage(brute = 0, burn = 0, stamina = 0, blocked = 0, updating_health = TRUE, required_status = null, wound_bonus = 0, bare_wound_bonus = 0, sharpness = FALSE) // maybe separate BRUTE_SHARP and BRUTE_OTHER eventually somehow hmm +/obj/item/bodypart/proc/receive_damage(brute = 0, burn = 0, stamina = 0, blocked = 0, updating_health = TRUE, required_status = null, wound_bonus = 0, bare_wound_bonus = 0, sharpness = SHARP_NONE) // maybe separate BRUTE_SHARP and BRUTE_OTHER eventually somehow hmm if(owner && (owner.status_flags & GODMODE)) return FALSE //godmode var/dmg_mlt = CONFIG_GET(number/damage_multiplier) @@ -260,9 +260,9 @@ switch(woundtype) if(WOUND_SHARP) - wounds_checking = WOUND_LIST_CUT + wounds_checking = WOUND_LIST_SLASH if(WOUND_BRUTE) - wounds_checking = WOUND_LIST_BONE + wounds_checking = WOUND_LIST_BLUNT if(WOUND_BURN) wounds_checking = WOUND_LIST_BURN diff --git a/code/modules/surgery/bone_mending.dm b/code/modules/surgery/bone_mending.dm index 81d9fa8d97..0c0083575b 100644 --- a/code/modules/surgery/bone_mending.dm +++ b/code/modules/surgery/bone_mending.dm @@ -8,7 +8,7 @@ target_mobtypes = list(/mob/living/carbon/human) possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD) requires_real_bodypart = TRUE - targetable_wound = /datum/wound/brute/bone/severe + targetable_wound = /datum/wound/blunt/severe /datum/surgery/repair_bone_hairline/can_start(mob/living/user, mob/living/carbon/target) if(..()) @@ -23,7 +23,7 @@ target_mobtypes = list(/mob/living/carbon/human) possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD) requires_real_bodypart = TRUE - targetable_wound = /datum/wound/brute/bone/critical + targetable_wound = /datum/wound/blunt/critical /datum/surgery/repair_bone_compound/can_start(mob/living/user, mob/living/carbon/target) if(..()) diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index 150016f570..4546be22d7 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -163,7 +163,7 @@ item_flags = SURGICAL_TOOL attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP_ACCURATE + sharpness = SHARP_POINTY tool_behaviour = TOOL_SCALPEL toolspeed = 1 bare_wound_bonus = 20 @@ -181,7 +181,7 @@ force = 16 toolspeed = 0.7 light_color = LIGHT_COLOR_GREEN - sharpness = IS_SHARP_ACCURATE + sharpness = SHARP_POINTY /obj/item/scalpel/advanced/Initialize() . = ..() @@ -221,7 +221,7 @@ attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") toolspeed = 0.5 hitsound = 'sound/weapons/bladeslice.ogg' - sharpness = IS_SHARP_ACCURATE + sharpness = SHARP_POINTY /obj/item/scalpel/suicide_act(mob/user) user.visible_message("[user] is slitting [user.p_their()] [pick("wrists", "throat", "stomach")] with [src]! It looks like [user.p_theyre()] trying to commit suicide!") @@ -245,7 +245,7 @@ throw_range = 5 custom_materials = list(/datum/material/iron=10000, /datum/material/glass=6000) attack_verb = list("attacked", "slashed", "sawed", "cut") - sharpness = IS_SHARP + sharpness = SHARP_EDGED tool_behaviour = TOOL_SAW toolspeed = 1 wound_bonus = 10 @@ -272,7 +272,7 @@ custom_materials = list(/datum/material/iron=10000, /datum/material/glass=6000) toolspeed = 0.5 attack_verb = list("attacked", "slashed", "sawed", "cut") - sharpness = IS_SHARP + sharpness = SHARP_EDGED /obj/item/surgical_drapes name = "surgical drapes" diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm index a7b9b6a298..040f3ce487 100644 --- a/code/modules/vending/_vending.dm +++ b/code/modules/vending/_vending.dm @@ -530,8 +530,8 @@ GLOBAL_LIST_EMPTY(vending_products) for(var/i in C.bodyparts) var/obj/item/bodypart/squish_part = i if(squish_part.is_organic_limb()) - //var/type_wound = pick(WOUND_LIST_BONE) - var/type_wound = pick(list(/datum/wound/brute/bone/critical, /datum/wound/brute/bone/severe, /datum/wound/brute/bone/critical, /datum/wound/brute/bone/severe, /datum/wound/brute/bone/moderate)) + //var/type_wound = pick(WOUND_LIST_BLUNT) + 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)) squish_part.force_wound_upwards(type_wound) else squish_part.receive_damage(brute=30) diff --git a/code/modules/zombie/items.dm b/code/modules/zombie/items.dm index 7038e9df7c..2b02e0e26e 100644 --- a/code/modules/zombie/items.dm +++ b/code/modules/zombie/items.dm @@ -12,10 +12,10 @@ var/icon_right = "bloodhand_right" hitsound = 'sound/hallucinations/growl1.ogg' force = 18 - sharpness = IS_SHARP_ACCURATE //it's a claw, they're sharp. + sharpness = SHARP_POINTY //it's a claw, they're sharp. damtype = "brute" total_mass = TOTAL_MASS_HAND_REPLACEMENT - sharpness = IS_SHARP + sharpness = SHARP_EDGED wound_bonus = -30 bare_wound_bonus = 15 diff --git a/tgstation.dme b/tgstation.dme index 6b3bf6eb88..2a7156f043 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -353,7 +353,6 @@ #include "code\datums\ai_laws.dm" #include "code\datums\armor.dm" #include "code\datums\beam.dm" -#include "code\datums\beepsky_fashion.dm" #include "code\datums\browser.dm" #include "code\datums\callback.dm" #include "code\datums\chatmessage.dm" From 8360bb1a7f52b651edf1bfefdd93a64dd792be96 Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 24 Jul 2020 23:44:57 +0100 Subject: [PATCH 05/91] section 2 --- code/modules/cargo/packs/medical.dm | 2 +- code/modules/hydroponics/grown/banana.dm | 6 + code/modules/mob/living/living_defense.dm | 15 +- .../ninja/suit/n_suit_verbs/ninja_stars.dm | 2 +- code/modules/paperwork/pen.dm | 1 + .../projectiles/boxes_magazines/ammo_boxes.dm | 2 +- code/modules/projectiles/gun.dm | 3 +- code/modules/projectiles/projectile.dm | 36 ++- .../modules/projectiles/projectile/bullets.dm | 10 +- .../projectiles/projectile/bullets/lmg.dm | 10 +- .../projectiles/projectile/bullets/pistol.dm | 2 + .../projectile/bullets/revolver.dm | 16 +- .../projectiles/projectile/bullets/rifle.dm | 3 + .../projectiles/projectile/bullets/shotgun.dm | 23 +- .../projectiles/projectile/bullets/smg.dm | 6 + .../chemistry/reagents/drink_reagents.dm | 21 +- .../chemistry/reagents/medicine_reagents.dm | 69 ++++- .../chemistry/reagents/other_reagents.dm | 8 + .../reagents/chemistry/recipes/medicine.dm | 12 + .../reagents/reagent_containers/hypospray.dm | 2 +- .../reagents/reagent_containers/syringes.dm | 1 + code/modules/surgery/bodyparts/_bodyparts.dm | 253 ++++++++++++++---- .../surgery/bodyparts/dismemberment.dm | 61 ++++- code/modules/surgery/bodyparts/head.dm | 3 +- code/modules/surgery/bodyparts/parts.dm | 2 +- code/modules/surgery/burn_dressing.dm | 3 +- code/modules/surgery/repair_puncture.dm | 108 ++++++++ code/modules/vending/_vending.dm | 3 +- interface/stylesheet.dm | 7 +- sound/effects/{ => wounds}/blood1.ogg | Bin sound/effects/{ => wounds}/blood2.ogg | Bin sound/effects/{ => wounds}/blood3.ogg | Bin sound/effects/{ => wounds}/crack1.ogg | Bin sound/effects/{ => wounds}/crack2.ogg | Bin sound/effects/wounds/crackandbleed.ogg | Bin 0 -> 15662 bytes sound/effects/wounds/pierce1.ogg | Bin 0 -> 8726 bytes sound/effects/wounds/pierce2.ogg | Bin 0 -> 17779 bytes sound/effects/wounds/pierce3.ogg | Bin 0 -> 19758 bytes sound/effects/{ => wounds}/sizzle1.ogg | Bin sound/effects/{ => wounds}/sizzle2.ogg | Bin strings/wounds/bone_scar_desc.json | 26 ++ strings/wounds/flesh_scar_desc.json | 86 ++++++ strings/wounds/scar_loc.json | 52 ++++ tgstation.dme | 5 +- 44 files changed, 760 insertions(+), 99 deletions(-) create mode 100644 code/modules/surgery/repair_puncture.dm rename sound/effects/{ => wounds}/blood1.ogg (100%) rename sound/effects/{ => wounds}/blood2.ogg (100%) rename sound/effects/{ => wounds}/blood3.ogg (100%) rename sound/effects/{ => wounds}/crack1.ogg (100%) rename sound/effects/{ => wounds}/crack2.ogg (100%) create mode 100644 sound/effects/wounds/crackandbleed.ogg create mode 100644 sound/effects/wounds/pierce1.ogg create mode 100644 sound/effects/wounds/pierce2.ogg create mode 100644 sound/effects/wounds/pierce3.ogg rename sound/effects/{ => wounds}/sizzle1.ogg (100%) rename sound/effects/{ => wounds}/sizzle2.ogg (100%) create mode 100644 strings/wounds/bone_scar_desc.json create mode 100644 strings/wounds/flesh_scar_desc.json create mode 100644 strings/wounds/scar_loc.json diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm index ce66fc52d5..6a4165f840 100644 --- a/code/modules/cargo/packs/medical.dm +++ b/code/modules/cargo/packs/medical.dm @@ -230,6 +230,6 @@ /obj/item/reagent_containers/hypospray/medipen/ekit, /obj/item/reagent_containers/hypospray/medipen/blood_loss, /obj/item/reagent_containers/hypospray/medipen/blood_loss, - /obj/item/reagent_containers/hypospray/medipen/blood_loss + /obj/item/reagent_containers/hypospray/medipen/blood_loss) crate_name = "medipen crate" diff --git a/code/modules/hydroponics/grown/banana.dm b/code/modules/hydroponics/grown/banana.dm index 0411a80443..81318f8fe1 100644 --- a/code/modules/hydroponics/grown/banana.dm +++ b/code/modules/hydroponics/grown/banana.dm @@ -27,6 +27,12 @@ juice_results = list(/datum/reagent/consumable/banana = 0) distill_reagent = /datum/reagent/consumable/ethanol/bananahonk +/obj/item/reagent_containers/food/snacks/grown/banana/generate_trash(atom/location) + . = ..() + var/obj/item/grown/bananapeel/peel = . + if(istype(peel)) + peel.grind_results = list(/datum/reagent/consumable/banana_peel = seed.potency * 0.2) + /obj/item/reagent_containers/food/snacks/grown/banana/suicide_act(mob/user) user.visible_message("[user] is aiming [src] at [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!") playsound(loc, 'sound/items/bikehorn.ogg', 50, 1, -1) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index e24e9641bf..bc88a048ea 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -85,7 +85,7 @@ totaldamage = block_calculate_resultant_damage(totaldamage, returnlist) var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null) if(!P.nodamage) - apply_damage(totaldamage, P.damage_type, def_zone, armor, wound_bonus=P.wound_bonus, bare_wound_bonus=P.bare_wound_bonus, sharpness=P.sharpness) + apply_damage(totaldamage, P.damage_type, def_zone, armor, wound_bonus = P.wound_bonus, bare_wound_bonus = P.bare_wound_bonus, sharpness = P.sharpness) if(P.dismemberment) check_projectile_dismemberment(P, def_zone) var/missing = 100 - final_percent @@ -135,12 +135,13 @@ dtype = I.damtype if(!blocked) - visible_message("[src] has been hit by [I].", \ - "You have been hit by [I].") - var/armor = run_armor_check(impacting_zone, "melee", "Your armor has protected your [parse_zone(impacting_zone)].", "Your armor has softened hit to your [parse_zone(impacting_zone)].",I.armour_penetration) - apply_damage(total_damage, dtype, impacting_zone, armor, sharpness=I.sharpness) - if(I.thrownby) - log_combat(I.thrownby, src, "threw and hit", I) + if(!nosell_hit) + visible_message("[src] is hit by [I]!", \ + "You're hit by [I]!") + if(!I.throwforce) + return + var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration) + apply_damage(I.throwforce, dtype, zone, armor, sharpness=I.get_sharpness(), wound_bonus=(nosell_hit * CANT_WOUND)) else return 1 else diff --git a/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm b/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm index 508722ecf2..57faad9493 100644 --- a/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm +++ b/code/modules/ninja/suit/n_suit_verbs/ninja_stars.dm @@ -14,5 +14,5 @@ /obj/item/throwing_star/ninja name = "ninja throwing star" - throwforce = 30 + throwforce = 20 embedding = list("pain_mult" = 6, "embed_chance" = 100, "fall_chance" = 0, "embed_chance_turf_mod" = 15) diff --git a/code/modules/paperwork/pen.dm b/code/modules/paperwork/pen.dm index 77ff8e9d8d..997ada6b21 100644 --- a/code/modules/paperwork/pen.dm +++ b/code/modules/paperwork/pen.dm @@ -28,6 +28,7 @@ var/degrees = 0 var/font = PEN_FONT embedding = list() + sharpness = SHARP_POINTY /obj/item/pen/suicide_act(mob/user) user.visible_message("[user] is scribbling numbers all over [user.p_them()]self with [src]! It looks like [user.p_theyre()] trying to commit sudoku...") diff --git a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm index e4674f4f4c..987efc0404 100644 --- a/code/modules/projectiles/boxes_magazines/ammo_boxes.dm +++ b/code/modules/projectiles/boxes_magazines/ammo_boxes.dm @@ -47,7 +47,7 @@ /obj/item/ammo_box/c38/dumdum name = "speed loader (.38 DumDum)" - desc = "Designed to quickly reload revolvers. DumDum bullets shatter on impact and shred the target's innards, likely getting caught inside." + desc = "Designed to quickly reload revolvers. These rounds expand on impact, allowing them to shred the target and cause massive bleeding. Very weak against armor and distant targets." ammo_type = /obj/item/ammo_casing/c38/dumdum /obj/item/ammo_box/c38/match diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index f34343debd..679f80dcc1 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -186,7 +186,8 @@ return if(iscarbon(target)) var/mob/living/carbon/C = target - for(var/datum/wound/W in C.all_wounds) + for(var/i in C.all_wounds) + var/datum/wound/W = i if(W.try_treating(src, user)) return // another coward cured! diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 199842d8e2..cb9a758e3f 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -149,19 +149,28 @@ var/temporary_unstoppable_movement = FALSE - ///If defined, on hit we create an item of this type then call hitby() on the hit target with this + ///If defined, on hit we create an item of this type then call hitby() on the hit target with this, mainly used for embedding items (bullets) in targets var/shrapnel_type ///If TRUE, hit mobs even if they're on the floor and not our target var/hit_stunned_targets = FALSE wound_bonus = CANT_WOUND + ///How much we want to drop both wound_bonus and bare_wound_bonus (to a minimum of 0 for the latter) per tile, for falloff purposes + var/wound_falloff_tile + ///How much we want to drop the embed_chance value, if we can embed, per tile, for falloff purposes + var/embed_falloff_tile /// For telling whether we want to roll for bone breaking or lacerations if we're bothering with wounds sharpness = SHARP_NONE + ///If we have a shrapnel_type defined, these embedding stats will be passed to the spawned shrapnel type, which will roll for embedding on the target + var/list/embedding + /obj/item/projectile/Initialize() . = ..() permutated = list() decayedRange = range + if(embedding) + updateEmbedding() /** * Artificially modified to be called at around every world.icon_size pixels of movement. @@ -169,6 +178,11 @@ */ /obj/item/projectile/proc/Range() range-- + if(wound_bonus != CANT_WOUND) + wound_bonus += wound_falloff_tile + bare_wound_bonus = max(0, bare_wound_bonus + wound_falloff_tile) + if(embedding) + embedding["embed_chance"] += embed_falloff_tile if(range <= 0 && loc) on_range() @@ -815,6 +829,26 @@ /obj/item/projectile/experience_pressure_difference() return +///Like [/obj/item/proc/updateEmbedding] but for projectiles instead, call this when you want to add embedding or update the stats on the embedding element +/obj/projectile/proc/updateEmbedding() + if(!shrapnel_type || !LAZYLEN(embedding)) + return + + AddElement(/datum/element/embed,\ + embed_chance = (!isnull(embedding["embed_chance"]) ? embedding["embed_chance"] : EMBED_CHANCE),\ + fall_chance = (!isnull(embedding["fall_chance"]) ? embedding["fall_chance"] : EMBEDDED_ITEM_FALLOUT),\ + pain_chance = (!isnull(embedding["pain_chance"]) ? embedding["pain_chance"] : EMBEDDED_PAIN_CHANCE),\ + pain_mult = (!isnull(embedding["pain_mult"]) ? embedding["pain_mult"] : EMBEDDED_PAIN_MULTIPLIER),\ + remove_pain_mult = (!isnull(embedding["remove_pain_mult"]) ? embedding["remove_pain_mult"] : EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER),\ + rip_time = (!isnull(embedding["rip_time"]) ? embedding["rip_time"] : EMBEDDED_UNSAFE_REMOVAL_TIME),\ + ignore_throwspeed_threshold = (!isnull(embedding["ignore_throwspeed_threshold"]) ? embedding["ignore_throwspeed_threshold"] : FALSE),\ + impact_pain_mult = (!isnull(embedding["impact_pain_mult"]) ? embedding["impact_pain_mult"] : EMBEDDED_IMPACT_PAIN_MULTIPLIER),\ + jostle_chance = (!isnull(embedding["jostle_chance"]) ? embedding["jostle_chance"] : EMBEDDED_JOSTLE_CHANCE),\ + jostle_pain_mult = (!isnull(embedding["jostle_pain_mult"]) ? embedding["jostle_pain_mult"] : EMBEDDED_JOSTLE_PAIN_MULTIPLIER),\ + pain_stam_pct = (!isnull(embedding["pain_stam_pct"]) ? embedding["pain_stam_pct"] : EMBEDDED_PAIN_STAM_PCT),\ + projectile_payload = shrapnel_type) + return TRUE + /////// MISC HELPERS //////// /// Is this atom reflectable with ""standardized"" reflection methods like you know eshields and deswords and similar /proc/is_energy_reflectable_projectile(atom/A) diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index bc0030afc3..9fb7e83577 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -8,4 +8,12 @@ flag = "bullet" hitsound_wall = "ricochet" impact_effect_type = /obj/effect/temp_visual/impact_effect - sharpness = SHARP_EDGED \ No newline at end of file + sharpness = SHARP_POINTY + shrapnel_type = /obj/item/shrapnel/bullet + embedding = list(embed_chance=15, fall_chance=2, jostle_chance=0, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.5, pain_mult=3, rip_time=10) + wound_falloff_tile = -5 + embed_falloff_tile = -5 + +/obj/projectile/bullet/smite + name = "divine retribution" + damage = 10 diff --git a/code/modules/projectiles/projectile/bullets/lmg.dm b/code/modules/projectiles/projectile/bullets/lmg.dm index 2ea1fe7c9a..e3eff6dcb0 100644 --- a/code/modules/projectiles/projectile/bullets/lmg.dm +++ b/code/modules/projectiles/projectile/bullets/lmg.dm @@ -25,8 +25,10 @@ /obj/item/projectile/bullet/mm195x129 name = "1.95x129mm bullet" - damage = 45 + damage = 40 armour_penetration = 5 + wound_bonus = -50 + wound_falloff_tile = 0 /obj/item/projectile/bullet/mm195x129_ap name = "1.95x129mm armor-piercing bullet" @@ -35,8 +37,12 @@ /obj/item/projectile/bullet/mm195x129_hp name = "1.95x129mm hollow-point bullet" - damage = 60 + damage = 50 armour_penetration = -60 + sharpness = SHARP_EDGED + wound_bonus = -40 + bare_wound_bonus = 30 + wound_falloff_tile = -8 /obj/item/projectile/bullet/incendiary/mm195x129 name = "1.95x129mm incendiary bullet" diff --git a/code/modules/projectiles/projectile/bullets/pistol.dm b/code/modules/projectiles/projectile/bullets/pistol.dm index 38c9c9f7d9..23a749415c 100644 --- a/code/modules/projectiles/projectile/bullets/pistol.dm +++ b/code/modules/projectiles/projectile/bullets/pistol.dm @@ -3,11 +3,13 @@ /obj/item/projectile/bullet/c9mm name = "9mm bullet" damage = 20 + embedding = list(embed_chance=15, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10) /obj/item/projectile/bullet/c9mm_ap name = "9mm armor-piercing bullet" damage = 15 armour_penetration = 40 + embedding = null /obj/item/projectile/bullet/incendiary/c9mm name = "9mm incendiary bullet" diff --git a/code/modules/projectiles/projectile/bullets/revolver.dm b/code/modules/projectiles/projectile/bullets/revolver.dm index c61ce57c1d..95d43ba1ce 100644 --- a/code/modules/projectiles/projectile/bullets/revolver.dm +++ b/code/modules/projectiles/projectile/bullets/revolver.dm @@ -19,8 +19,9 @@ ricochet_chance = 50 ricochet_auto_aim_angle = 10 ricochet_auto_aim_range = 3 - wound_bonus = -35 - sharpness = SHARP_EDGED + wound_bonus = -20 + bare_wound_bonus = 10 + embedding = list(embed_chance=15, fall_chance=2, jostle_chance=2, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=3, jostle_pain_mult=5, rip_time=10) /obj/item/projectile/bullet/c38/match name = ".38 Match bullet" @@ -43,13 +44,21 @@ ricochet_chance = 130 ricochet_decay_damage = 0.8 shrapnel_type = NONE + sharpness = SHARP_NONE + embedding = null +// premium .38 ammo from cargo, weak against armor, lower base damage, but excellent at embedding and causing slice wounds at close range /obj/item/projectile/bullet/c38/dumdum name = ".38 DumDum bullet" damage = 15 armour_penetration = -30 ricochets_max = 0 - shrapnel_type = /obj/item/shrapnel/bullet/c38/dumdum + sharpness = SHARP_EDGED + wound_bonus = 20 + bare_wound_bonus = 20 + embedding = list(embed_chance=75, fall_chance=3, jostle_chance=4, ignore_throwspeed_threshold=TRUE, pain_stam_pct=0.4, pain_mult=5, jostle_pain_mult=6, rip_time=10) + wound_falloff_tile = -5 + embed_falloff_tile = -15 /obj/item/projectile/bullet/c38/rubber name = ".38 rubber bullet" @@ -102,6 +111,7 @@ /obj/item/projectile/bullet/a357 name = ".357 bullet" damage = 60 + wound_bonus = -70 /obj/item/projectile/bullet/a357/ap name = ".357 armor-piercing bullet" diff --git a/code/modules/projectiles/projectile/bullets/rifle.dm b/code/modules/projectiles/projectile/bullets/rifle.dm index ae1611cb00..ce30f5e787 100644 --- a/code/modules/projectiles/projectile/bullets/rifle.dm +++ b/code/modules/projectiles/projectile/bullets/rifle.dm @@ -3,12 +3,15 @@ /obj/item/projectile/bullet/a556 name = "5.56mm bullet" damage = 35 + wound_bonus = -40 // 7.62 (Nagant Rifle) /obj/item/projectile/bullet/a762 name = "7.62 bullet" damage = 60 + wound_bonus = -35 + wound_falloff_tile = 0 /obj/item/projectile/bullet/a762_enchanted name = "enchanted 7.62 bullet" diff --git a/code/modules/projectiles/projectile/bullets/shotgun.dm b/code/modules/projectiles/projectile/bullets/shotgun.dm index cc98331004..69f976d213 100644 --- a/code/modules/projectiles/projectile/bullets/shotgun.dm +++ b/code/modules/projectiles/projectile/bullets/shotgun.dm @@ -1,16 +1,18 @@ /obj/item/projectile/bullet/shotgun_slug name = "12g shotgun slug" - damage = 60 + damage = 50 + sharpness = SHARP_POINTY + wound_bonus = 0 /obj/item/projectile/bullet/shotgun_slug/executioner name = "executioner slug" // admin only, can dismember limbs sharpness = SHARP_EDGED - wound_bonus = 0 + wound_bonus = 80 /obj/item/projectile/bullet/shotgun_slug/pulverizer name = "pulverizer slug" // admin only, can crush bones sharpness = SHARP_NONE - wound_bonus = 0 + wound_bonus = 80 /obj/item/projectile/bullet/shotgun_beanbag name = "beanbag slug" @@ -18,6 +20,7 @@ stamina = 70 wound_bonus = 20 sharpness = SHARP_NONE + embedding = null /obj/item/projectile/bullet/incendiary/shotgun name = "incendiary slug" @@ -83,18 +86,22 @@ return BULLET_ACT_HIT /obj/item/projectile/bullet/pellet - var/tile_dropoff = 0.75 + var/tile_dropoff = 0.45 var/tile_dropoff_s = 1.25 /obj/item/projectile/bullet/pellet/shotgun_buckshot name = "buckshot pellet" - damage = 12.5 - wound_bonus = -10 + damage = 7.5 + wound_bonus = 5 + bare_wound_bonus = 5 + wound_falloff_tile = -2.5 // low damage + additional dropoff will already curb wounding potential anything past point blank /obj/item/projectile/bullet/pellet/shotgun_rubbershot name = "rubbershot pellet" damage = 2 stamina = 15 + sharpness = SHARP_NONE + embedding = null /obj/item/projectile/bullet/pellet/Range() ..() @@ -106,8 +113,10 @@ qdel(src) /obj/item/projectile/bullet/pellet/shotgun_improvised - tile_dropoff = 0.55 //Come on it does 6 damage don't be like that. + tile_dropoff = 0.35 //Come on it does 6 damage don't be like that. damage = 6 + wound_bonus = 0 + bare_wound_bonus = 7.5 /obj/item/projectile/bullet/pellet/shotgun_improvised/Initialize() . = ..() diff --git a/code/modules/projectiles/projectile/bullets/smg.dm b/code/modules/projectiles/projectile/bullets/smg.dm index eb4c8e9776..5c9d5b92a3 100644 --- a/code/modules/projectiles/projectile/bullets/smg.dm +++ b/code/modules/projectiles/projectile/bullets/smg.dm @@ -3,6 +3,8 @@ /obj/item/projectile/bullet/c45 name = ".45 bullet" damage = 30 + wound_bonus = -10 + wound_falloff_tile = -10 /obj/item/projectile/bullet/c45_cleaning name = ".45 bullet" @@ -51,11 +53,15 @@ /obj/item/projectile/bullet/c46x30mm name = "4.6x30mm bullet" damage = 15 + wound_bonus = -5 + bare_wound_bonus = 5 + embed_falloff_tile = -4 /obj/item/projectile/bullet/c46x30mm_ap name = "4.6x30mm armor-piercing bullet" damage = 12.5 armour_penetration = 40 + embedding = null /obj/item/projectile/bullet/incendiary/c46x30mm name = "4.6x30mm incendiary bullet" diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm index d76f6af165..6b933ce759 100644 --- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm @@ -1016,4 +1016,23 @@ if(M.getToxLoss() && prob(30)) M.adjustToxLoss(-1, 0) ..() - . = TRUE \ No newline at end of file + . = TRUE + +// i googled "natural coagulant" and a couple of results came up for banana peels, so after precisely 30 more seconds of research, i now dub grinding banana peels good for your blood +/datum/reagent/consumable/banana_peel + name = "Pulped Banana Peel" + description = "Okay, so you put a banana peel in a grinder... Why, exactly?" + color = "#863333" // rgb: 175, 175, 0 + reagent_state = SOLID + taste_description = "stringy, bitter pulp" + glass_name = "glass of banana peel pulp" + glass_desc = "Okay, so you put a banana peel in a grinder... Why, exactly?" + +/datum/reagent/consumable/baked_banana_peel + name = "Baked Banana Peel Powder" + description = "You took a banana peel... pulped it... baked it... Where are you going with this?" + color = "#863333" // rgb: 175, 175, 0 + reagent_state = SOLID + taste_description = "bitter powder" + glass_name = "glass of banana peel powder" + description = "You took a banana peel... pulped it... baked it... Where are you going with this?" diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 050b1f29b5..60f86283c0 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -145,8 +145,8 @@ M.adjustToxLoss(-power, 0, TRUE) //heals TOXINLOVERs M.adjustCloneLoss(-power, 0) for(var/i in M.all_wounds) - var/datum/wound/W = i - W.on_xadone(power) + var/datum/wound/iter_wound = i + iter_wound.on_xadone(power) REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC) //fixes common causes for disfiguration . = 1 metabolization_rate = REAGENTS_METABOLISM * (0.00001 * (M.bodytemperature ** 2) + 0.5) @@ -196,8 +196,8 @@ M.adjustToxLoss(-power, 0, TRUE) M.adjustCloneLoss(-power, 0) for(var/i in M.all_wounds) - var/datum/wound/W = i - W.on_xadone(power) + var/datum/wound/iter_wound = i + iter_wound.on_xadone(power) REMOVE_TRAIT(M, TRAIT_DISFIGURED, TRAIT_GENERIC) . = 1 ..() @@ -365,7 +365,7 @@ /datum/reagent/medicine/salglu_solution name = "Saline-Glucose Solution" - description = "Has a 33% chance per metabolism cycle to heal brute and burn damage. Can be used as a temporary blood substitute." + description = "Has a 33% chance per metabolism cycle to heal brute and burn damage. Can be used as a temporary blood substitute, as well as slowly speeding blood regeneration." reagent_state = LIQUID color = "#DCDCDC" metabolization_rate = 0.5 * REAGENTS_METABOLISM @@ -373,6 +373,7 @@ taste_description = "sweetness and salt" var/last_added = 0 var/maximum_reachable = BLOOD_VOLUME_NORMAL - 10 //So that normal blood regeneration can continue with salglu active + var/extra_regen = 0.25 // in addition to acting as temporary blood, also add this much to their actual blood per tick pH = 5.5 /datum/reagent/medicine/salglu_solution/on_mob_life(mob/living/carbon/M) @@ -385,7 +386,7 @@ var/amount_to_add = min(M.blood_volume, volume*5) var/new_blood_level = min(M.blood_volume + amount_to_add, maximum_reachable) last_added = new_blood_level - M.blood_volume - M.blood_volume = new_blood_level + M.blood_volume = new_blood_level + extra_regen if(prob(33)) M.adjustBruteLoss(-0.5*REM, 0) M.adjustFireLoss(-0.5*REM, 0) @@ -471,8 +472,9 @@ else if(method in list(PATCH, TOUCH)) M.adjustBruteLoss(-1 * reac_volume) M.adjustFireLoss(-1 * reac_volume) - for(var/datum/wound/burn/burn_wound in C.all_wounds) - burn_wound.regenerate_flesh(reac_volume) + for(var/i in carbies.all_wounds) + var/datum/wound/iter_wound = i + iter_wound.on_synthflesh(reac_volume) if(show_message) to_chat(M, "You feel your burns and bruises healing! It stings like hell!") SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "painful_medicine", /datum/mood_event/painful_medicine) @@ -1592,10 +1594,57 @@ to_chat(C, "[pick(GLOB.wisdoms)]") //give them a random wisdom ..() -// handled in cut wounds process +// helps bleeding wounds clot faster /datum/reagent/medicine/coagulant name = "Sanguirite" - description = "A coagulant used to help open cuts clot faster." + description = "A proprietary coagulant used to help bleeding wounds clot faster." reagent_state = LIQUID color = "#bb2424" metabolization_rate = 0.25 * REAGENTS_METABOLISM + +overdose_threshold = 20 + /// How much base clotting we do per bleeding wound, multiplied by the below number for each bleeding wound + var/clot_rate = 0.25 + /// If we have multiple bleeding wounds, we count the number of bleeding wounds, then multiply the clot rate by this^(n) before applying it to each cut, so more cuts = less clotting per cut (though still more total clotting) + var/clot_coeff_per_wound = 0.9 + +/datum/reagent/medicine/coagulant/on_mob_life(mob/living/carbon/M) + . = ..() + if(!M.blood_volume || !M.all_wounds) + return + + var/effective_clot_rate = clot_rate + + for(var/i in M.all_wounds) + var/datum/wound/iter_wound = i + if(iter_wound.blood_flow) + effective_clot_rate *= clot_coeff_per_wound + + for(var/i in M.all_wounds) + var/datum/wound/iter_wound = i + iter_wound.blood_flow = max(0, iter_wound.blood_flow - effective_clot_rate) + +/datum/reagent/medicine/coagulant/overdose_process(mob/living/M) + . = ..() + if(!M.blood_volume) + return + + if(prob(15)) + M.losebreath += rand(2,4) + M.adjustOxyLoss(rand(1,3)) + if(prob(30)) + to_chat(M, "You can feel your blood clotting up in your veins!") + else if(prob(10)) + to_chat(M, "You feel like your blood has stopped moving!") + if(prob(50)) + var/obj/item/organ/lungs/our_lungs = M.getorganslot(ORGAN_SLOT_LUNGS) + our_lungs.applyOrganDamage(1) + else + var/obj/item/organ/heart/our_heart = M.getorganslot(ORGAN_SLOT_HEART) + our_heart.applyOrganDamage(1) + +// can be synthesized on station rather than bought. made by grinding a banana peel, heating it up, then mixing the banana peel powder with salglu +/datum/reagent/medicine/coagulant/weak + name = "Synthi-Sanguirite" + description = "A synthetic coagulant used to help bleeding wounds clot faster. Not quite as effective as name brand Sanguirite, especially on patients with lots of cuts." + clot_coeff_per_wound = 0.8 diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 5c5821381e..5b6418779b 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -244,6 +244,11 @@ glass_desc = "The father of all refreshments." shot_glass_icon_state = "shotglassclear" +/datum/reagent/water/on_mob_life(mob/living/carbon/M) + . = ..() + if(M.blood_volume) + M.blood_volume += 0.1 // water is good for you! + /* * Water reaction to turf */ @@ -334,6 +339,8 @@ return ..() /datum/reagent/water/holywater/on_mob_life(mob/living/carbon/M) + if(M.blood_volume) + M.blood_volume += 0.1 // water is good for you! if(!data) data = list("misc" = 1) data["misc"]++ @@ -2304,6 +2311,7 @@ metabolization_rate = 0.75 * REAGENTS_METABOLISM // 5u (WOUND_DETERMINATION_CRITICAL) will last for ~17 ticks /// Whether we've had at least WOUND_DETERMINATION_SEVERE (2.5u) of determination at any given time. No damage slowdown immunity or indication we're having a second wind if it's just a single moderate wound var/significant = FALSE + self_consuming = TRUE /datum/reagent/determination/on_mob_end_metabolize(mob/living/carbon/M) if(significant) diff --git a/code/modules/reagents/chemistry/recipes/medicine.dm b/code/modules/reagents/chemistry/recipes/medicine.dm index e591daeb8e..bb9a951cac 100644 --- a/code/modules/reagents/chemistry/recipes/medicine.dm +++ b/code/modules/reagents/chemistry/recipes/medicine.dm @@ -50,6 +50,18 @@ results = list(/datum/reagent/medicine/salglu_solution = 3) required_reagents = list(/datum/reagent/consumable/sodiumchloride = 1, /datum/reagent/water = 1, /datum/reagent/consumable/sugar = 1) +/datum/chemical_reaction/baked_banana_peel + results = list(/datum/reagent/consumable/baked_banana_peel = 1) + required_temp = 413.15 // if it's good enough for caramel it's good enough for this + required_reagents = list(/datum/reagent/consumable/banana_peel = 1) + mix_message = "The pulp dries up and takes on a powdery state!" + mob_react = FALSE + +/datum/chemical_reaction/coagulant_weak + results = list(/datum/reagent/medicine/coagulant/weak = 3) + required_reagents = list(/datum/reagent/medicine/salglu_solution = 2, /datum/reagent/consumable/baked_banana_peel = 1) + mob_react = FALSE + /datum/chemical_reaction/mine_salve name = "Miner's Salve" id = /datum/reagent/medicine/mine_salve diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index 7dcf996cab..f37210ad1c 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -135,7 +135,7 @@ /obj/item/reagent_containers/hypospray/medipen/ekit name = "emergency first-aid autoinjector" - desc = "An epinephrine medipen with trace amounts of coagulants and antibiotics to help stabilize bad cuts and burns." + desc = "An epinephrine medipen with extra coagulant and antibiotics to help stabilize bad cuts and burns." volume = 15 amount_per_transfer_from_this = 15 list_reagents = list(/datum/reagent/medicine/epinephrine = 12, /datum/reagent/medicine/coagulant = 2.5, /datum/reagent/medicine/spaceacillin = 0.5) diff --git a/code/modules/reagents/reagent_containers/syringes.dm b/code/modules/reagents/reagent_containers/syringes.dm index 4ab1470667..4b73ebde4a 100644 --- a/code/modules/reagents/reagent_containers/syringes.dm +++ b/code/modules/reagents/reagent_containers/syringes.dm @@ -16,6 +16,7 @@ custom_materials = list(/datum/material/iron=10, /datum/material/glass=20) reagent_flags = TRANSPARENT custom_price = PRICE_CHEAP_AS_FREE + sharpness = SHARP_POINTY /obj/item/reagent_containers/syringe/Initialize() . = ..() diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index bcf1bc8e0a..c79f50c03c 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -86,12 +86,12 @@ /// A hat won't cover your face, but a shirt covering your chest will cover your... you know, chest var/scars_covered_by_clothes = TRUE - /// Descriptions for the locations on the limb for scars to be assigned, just cosmetic - var/list/specific_locations = list("general area") /// So we know if we need to scream if this limb hits max damage var/last_maxed /// How much generic bleedstacks we have on this bodypart var/generic_bleedstacks + /// If we have a gauze wrapping currently applied (not including splints) + var/obj/item/stack/current_gauze /obj/item/bodypart/examine(mob/user) . = ..() @@ -151,8 +151,20 @@ var/turf/T = get_turf(src) if(status != BODYPART_ROBOTIC) playsound(T, 'sound/misc/splort.ogg', 50, 1, -1) - for(var/obj/item/I in src) - I.forceMove(T) + if(current_gauze) + QDEL_NULL(current_gauze) + for(var/obj/item/organ/drop_organ in get_organs()) + drop_organ.transfer_to_limb(src, owner) + +///since organs aren't actually stored in the bodypart themselves while attached to a person, we have to query the owner for what we should have +/obj/item/bodypart/proc/get_organs() + if(!owner) + return + . = list() + for(var/i in owner.internal_organs) //internal organs inside the dismembered limb are dropped. + var/obj/item/organ/organ_check = i + if(check_zone(organ_check.zone) == body_zone) + . += organ_check /obj/item/bodypart/proc/consider_processing() if(stamina_dam > DAMAGE_PRECISION) @@ -192,16 +204,64 @@ if(ALIEN_BODYPART,LARVA_BODYPART) //aliens take some additional burn //nothing can burn with so much snowflake code around burn *= 1.2 - var/wounding_type = (brute > burn ? WOUND_BRUTE : WOUND_BURN) + /* + // START WOUND HANDLING + */ + + // what kind of wounds we're gonna roll for, take the greater between brute and burn, then if it's brute, we subdivide based on sharpness + var/wounding_type = (brute > burn ? WOUND_BLUNT : WOUND_BURN) var/wounding_dmg = max(brute, burn) - if(wounding_type == WOUND_BRUTE && sharpness) - wounding_type = WOUND_SHARP - // i know this is effectively the same check as above but i don't know if those can null the damage by rounding and want to be safe - if(owner && wounding_dmg > 4 && wound_bonus != CANT_WOUND) - // if you want to make tox wounds or some other type, this will need to be expanded and made more modular - // handle all our wounding stuff + var/mangled_state = get_mangled_state() + var/bio_state = owner.get_biological_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) + if(sharpness == SHARP_EDGED) + wounding_type = WOUND_SLASH + else if(sharpness == SHARP_POINTY) + wounding_type = WOUND_PIERCE + + //Handling for bone only/flesh only(none right now)/flesh and bone targets + switch(bio_state) + // if we're bone only, all cutting attacks go straight to the bone + if(BIO_JUST_BONE) + if(wounding_type == WOUND_SLASH) + wounding_type = WOUND_BLUNT + wounding_dmg *= (easy_dismember ? 1 : 0.5) + 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_JUST_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 && sharpness) + playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100) + if(wounding_type == WOUND_SLASH && !easy_dismember) + wounding_dmg *= 0.5 // edged weapons pass along 50% 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_BOTH && 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 + if(owner && wounding_dmg >= WOUND_MINIMUM_DAMAGE && wound_bonus != CANT_WOUND) check_wounding(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus) + for(var/i in wounds) + var/datum/wound/iter_wound = i + iter_wound.receive_damage(wounding_type, wounding_dmg, wound_bonus) + + /* + // END WOUND HANDLING + */ + + //back to our regularly scheduled program, we now actually apply damage if there's room below limb damage cap + var/can_inflict = max_damage - get_damage() var/total_damage = brute + burn @@ -213,10 +273,6 @@ if(can_inflict <= 0) return FALSE - for(var/i in wounds) - var/datum/wound/W = i - W.receive_damage(wounding_type, wounding_dmg, wound_bonus) - brute_dam += brute burn_dam += burn @@ -236,14 +292,58 @@ update_disabled() return update_bodypart_damage_state() +/// Allows us to roll for and apply a wound without actually dealing damage. Used for aggregate wounding power with pellet clouds +/obj/item/bodypart/proc/painless_wound_roll(wounding_type, phantom_wounding_dmg, wound_bonus, bare_wound_bonus, sharpness=SHARP_NONE) + if(!owner || phantom_wounding_dmg <= WOUND_MINIMUM_DAMAGE || wound_bonus == CANT_WOUND) + return + + var/mangled_state = get_mangled_state() + var/bio_state = owner.get_biological_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) + if(sharpness == SHARP_EDGED) + wounding_type = WOUND_SLASH + else if(sharpness == SHARP_POINTY) + wounding_type = WOUND_PIERCE + + //Handling for bone only/flesh only(none right now)/flesh and bone targets + switch(bio_state) + // if we're bone only, all cutting attacks go straight to the bone + if(BIO_JUST_BONE) + if(wounding_type == WOUND_SLASH) + wounding_type = WOUND_BLUNT + phantom_wounding_dmg *= (easy_dismember ? 1 : 0.5) + 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_JUST_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 && sharpness) + playsound(src, "sound/effects/wounds/crackandbleed.ogg", 100) + if(wounding_type == WOUND_SLASH && !easy_dismember) + phantom_wounding_dmg *= 0.5 // edged weapons pass along 50% 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_BOTH && 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) + /** * check_wounding() is where we handle rolling for, selecting, and applying a wound if we meet the criteria * - * We generate a "score" for how woundable the attack was based on the damage and other factors discussed in [check_wounding_mods()], then go down the list from most severe to least severe wounds in that category. + * We generate a "score" for how woundable the attack was based on the damage and other factors discussed in [/obj/item/bodypart/proc/check_wounding_mods], then go down the list from most severe to least severe wounds in that category. * We can promote a wound from a lesser to a higher severity this way, but we give up if we have a wound of the given type and fail to roll a higher severity, so no sidegrades/downgrades * * Arguments: - * * woundtype- Either WOUND_SHARP, WOUND_BRUTE, or WOUND_BURN based on the attack type. + * * woundtype- Either WOUND_BLUNT, WOUND_SLASH, WOUND_PIERCE, or WOUND_BURN based on the attack type. * * damage- How much damage is tied to this attack, since wounding potential scales with damage in an attack (see: WOUND_DAMAGE_EXPONENT) * * wound_bonus- The wound_bonus of an attack * * bare_wound_bonus- The bare_wound_bonus of an attack @@ -252,19 +352,24 @@ // actually roll wounds if applicable if(HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE)) damage *= 1.5 + else + damage = min(damage, WOUND_MAX_CONSIDERED_DAMAGE) var/base_roll = rand(1, round(damage ** WOUND_DAMAGE_EXPONENT)) var/injury_roll = base_roll injury_roll += check_woundings_mods(woundtype, damage, wound_bonus, bare_wound_bonus) - var/list/wounds_checking + var/list/wounds_checking = GLOB.global_wound_types[woundtype] - switch(woundtype) - if(WOUND_SHARP) - wounds_checking = WOUND_LIST_SLASH - if(WOUND_BRUTE) - wounds_checking = WOUND_LIST_BLUNT - if(WOUND_BURN) - wounds_checking = WOUND_LIST_BURN + // 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 + var/list/clothing = human_wearer.clothingonpart(src) + for(var/i in clothing) + var/obj/item/clothing/clothes_check = i + // unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary + if(clothes_check.armor.getRating("wound")) + bare_wound_bonus = 0 + break //cycle through the wounds of the relevant category from the most severe down for(var/PW in wounds_checking) @@ -279,21 +384,22 @@ replaced_wound = existing_wound if(initial(possible_wound.threshold_minimum) < injury_roll) + var/datum/wound/new_wound if(replaced_wound) - var/datum/wound/new_wound = replaced_wound.replace_wound(possible_wound) - log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll) + new_wound = replaced_wound.replace_wound(possible_wound) + log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll) // dismembering wounds are logged in the apply_wound() for loss wounds since they delete themselves immediately, these will be immediately returned else - var/datum/wound/new_wound = new possible_wound + new_wound = new possible_wound new_wound.apply_wound(src) log_wound(owner, new_wound, damage, wound_bonus, bare_wound_bonus, base_roll) - return + return new_wound // try forcing a specific wound, but only if there isn't already a wound of that severity or greater for that type on this bodypart /obj/item/bodypart/proc/force_wound_upwards(specific_woundtype, smited = FALSE) var/datum/wound/potential_wound = specific_woundtype for(var/i in wounds) var/datum/wound/existing_wound = i - if(existing_wound.type in (initial(potential_wound.wound_type))) + if(existing_wound.wound_type == initial(potential_wound.wound_type)) 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) return @@ -301,12 +407,20 @@ var/datum/wound/new_wound = new potential_wound new_wound.apply_wound(src, smited = smited) +/** + * check_wounding_mods() is where we handle the various modifiers of a wound roll + * + * A short list of things we consider: any armor a human target may be wearing, and if they have no wound armor on the limb, if we have a bare_wound_bonus to apply, plus the plain wound_bonus + * We also flick through all of the wounds we currently have on this limb and add their threshold penalties, so that having lots of bad wounds makes you more liable to get hurt worse + * Lastly, we add the inherent wound_resistance variable the bodypart has (heads and chests are slightly harder to wound), and a small bonus if the limb is already disabled + * + * Arguments: + * * It's the same ones on [receive_damage] + */ /obj/item/bodypart/proc/check_woundings_mods(wounding_type, damage, wound_bonus, bare_wound_bonus) var/armor_ablation = 0 var/injury_mod = 0 - //var/bwb = 0 - if(owner && ishuman(owner)) var/mob/living/carbon/human/H = owner var/list/clothing = H.clothingonpart(src) @@ -314,7 +428,7 @@ var/obj/item/clothing/C = c // unlike normal armor checks, we tabluate these piece-by-piece manually so we can also pass on appropriate damage the clothing's limbs if necessary armor_ablation += C.armor.getRating("wound") - if(wounding_type == WOUND_SHARP) + if(wounding_type == WOUND_SLASH) C.take_damage_zone(body_zone, damage, BRUTE, armour_penetration) else if(wounding_type == WOUND_BURN && damage >= 10) // lazy way to block freezing from shredding clothes without adding another var onto apply_damage() C.take_damage_zone(body_zone, damage, BURN, armour_penetration) @@ -330,7 +444,7 @@ injury_mod += W.threshold_penalty var/part_mod = -wound_resistance - if(is_disabled()) + if(get_damage(TRUE) >= max_damage) part_mod += disabled_wound_penalty injury_mod += part_mod @@ -383,11 +497,11 @@ return BODYPART_DISABLED_WOUND if(can_dismember() && !HAS_TRAIT(owner, TRAIT_NODISMEMBER)) . = disabled //inertia, to avoid limbs healing 0.1 damage and being re-enabled - if((get_damage(TRUE) >= max_damage) || (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) && (get_damage(TRUE) >= (max_damage * 0.6)))) //Easy limb disable disables the limb at 40% health instead of 0% + if(get_damage(TRUE) >= max_damage * (HAS_TRAIT(owner, TRAIT_EASYLIMBDISABLE) ? 0.6 : 1)) //Easy limb disable disables the limb at 40% health instead of 0% if(!last_maxed) owner.emote("scream") last_maxed = TRUE - if(!is_organic_limb()) + if(!is_organic_limb() || stamina_dam >= max_damage) return BODYPART_DISABLED_DAMAGE else if(disabled && (get_damage(TRUE) <= (max_damage * 0.8))) // reenabled at 80% now instead of 50% as of wounds update last_maxed = FALSE @@ -741,17 +855,29 @@ /obj/item/bodypart/proc/get_wound_type(checking_type) if(isnull(wounds)) return - for(var/thing in wounds) - var/datum/wound/W = thing - if(istype(W, checking_type)) - return W + for(var/i in wounds) + if(istype(i, checking_type)) + return i -/// very rough start for updating efficiency and other stats on a body part whenever a wound is gained/lost -/obj/item/bodypart/proc/update_wounds() +/** + * update_wounds() is called whenever a wound is gained or lost on this bodypart, as well as if there's a change of some kind on a bone wound possibly changing disabled status + * + * Covers tabulating the damage multipliers we have from wounds (burn specifically), as well as deleting our gauze wrapping if we don't have any wounds that can use bandaging + * + * Arguments: + * * replaced- If true, this is being called from the remove_wound() of a wound that's being replaced, so the bandage that already existed is still relevant, but the new wound hasn't been added yet + */ +/obj/item/bodypart/proc/update_wounds(replaced = FALSE) var/dam_mul = 1 //initial(wound_damage_multiplier) // we can only have one wound per type, but remember there's multiple types - for(var/datum/wound/W in wounds) - dam_mul *= W.damage_mulitplier_penalty + // we can (normally) only have one wound per type, but remember there's multiple types (smites like :B:loodless can generate multiple cuts on a limb) + for(var/i in wounds) + var/datum/wound/iter_wound = i + dam_mul *= iter_wound.damage_mulitplier_penalty + + if(!LAZYLEN(wounds) && current_gauze && !replaced) + owner.visible_message("\The [current_gauze] on [owner]'s [name] fall away.", "The [current_gauze] on your [name] fall away.") + QDEL_NULL(current_gauze) wound_damage_multiplier = dam_mul update_disabled() @@ -761,8 +887,6 @@ var/bleed_rate = 0 if(generic_bleedstacks > 0) bleed_rate++ - if(brute_dam >= 40) - bleed_rate += (brute_dam * 0.008) //We want an accurate reading of .len listclearnulls(embedded_objects) @@ -773,5 +897,40 @@ for(var/thing in wounds) var/datum/wound/W = thing bleed_rate += W.blood_flow - + if(owner.mobility_flags & ~MOBILITY_STAND) + bleed_rate *= 0.75 return bleed_rate + +/** + * apply_gauze() is used to- well, apply gauze to a bodypart + * + * As of the Wounds 2 PR, all bleeding is now bodypart based rather than the old bleedstacks system, and 90% of standard bleeding comes from flesh wounds (the exception is embedded weapons). + * The same way bleeding is totaled up by bodyparts, gauze now applies to all wounds on the same part. Thus, having a slash wound, a pierce wound, and a broken bone wound would have the gauze + * applying blood staunching to the first two wounds, while also acting as a sling for the third one. Once enough blood has been absorbed or all wounds with the ACCEPTS_GAUZE flag have been cleared, + * the gauze falls off. + * + * Arguments: + * * gauze- Just the gauze stack we're taking a sheet from to apply here + */ +/obj/item/bodypart/proc/apply_gauze(obj/item/stack/gauze) + if(!istype(gauze) || !gauze.absorption_capacity) + return + QDEL_NULL(current_gauze) + current_gauze = new gauze.type(src, 1) + gauze.use(1) + +/** + * 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 bandages fall off and we're left with nothing. + * + * 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?) + */ +/obj/item/bodypart/proc/seep_gauze(seep_amt = 0) + if(!current_gauze) + return + current_gauze.absorption_capacity -= seep_amt + if(current_gauze.absorption_capacity < 0) + owner.visible_message("\The [current_gauze] on [owner]'s [name] fall away in rags.", "\The [current_gauze] on your [name] fall away in rags.", vision_distance=COMBAT_MESSAGE_RANGE) + QDEL_NULL(current_gauze) diff --git a/code/modules/surgery/bodyparts/dismemberment.dm b/code/modules/surgery/bodyparts/dismemberment.dm index 2ce6ca8862..fa003e3f3c 100644 --- a/code/modules/surgery/bodyparts/dismemberment.dm +++ b/code/modules/surgery/bodyparts/dismemberment.dm @@ -4,7 +4,7 @@ return TRUE //Dismember a limb -/obj/item/bodypart/proc/dismember(dam_type = BRUTE) +/obj/item/bodypart/proc/dismember(dam_type = BRUTE, silent=TRUE) if(!owner) return FALSE var/mob/living/carbon/C = owner @@ -16,7 +16,8 @@ return FALSE var/obj/item/bodypart/affecting = C.get_bodypart(BODY_ZONE_CHEST) affecting.receive_damage(clamp(brute_dam/2 * affecting.body_damage_coeff, 15, 50), clamp(burn_dam/2 * affecting.body_damage_coeff, 0, 50), wound_bonus=CANT_WOUND) //Damage the chest based on limb's existing damage - C.visible_message("[C]'s [src.name] has been violently dismembered!") + if(!silent) + C.visible_message("[C]'s [name] is violently dismembered!") C.emote("scream") SEND_SIGNAL(C, COMSIG_ADD_MOOD_EVENT, "dismembered", /datum/mood_event/dismembered) drop_limb() @@ -30,6 +31,7 @@ burn() return TRUE add_mob_blood(C) + C.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) @@ -80,8 +82,6 @@ if(organ_spilled) C.visible_message("[C]'s internal organs spill out onto the floor!") - - //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) @@ -153,7 +153,52 @@ forceMove(Tsec) +/** + * get_mangled_state() is relevant for flesh and bone bodyparts, and returns whether this bodypart has mangled skin, mangled bone, or both (or neither i guess) + * + * Dismemberment for flesh and bone requires the victim to have the skin on their bodypart destroyed (either a critical cut or piercing wound), and at least a hairline fracture + * (severe bone), at which point we can start rolling for dismembering. The attack must also deal at least 10 damage, and must be a brute attack of some kind (sorry for now, cakehat, maybe later) + * + * Returns: BODYPART_MANGLED_NONE if we're fine, BODYPART_MANGLED_FLESH if our skin is broken, BODYPART_MANGLED_BONE if our bone is broken, or BODYPART_MANGLED_BOTH if both are broken and we're up for dismembering + */ +/obj/item/bodypart/proc/get_mangled_state() + . = BODYPART_MANGLED_NONE + for(var/i in wounds) + var/datum/wound/iter_wound = i + if((iter_wound.wound_flags & MANGLES_BONE)) + . |= BODYPART_MANGLED_BONE + if((iter_wound.wound_flags & MANGLES_FLESH)) + . |= BODYPART_MANGLED_FLESH + +/** + * try_dismember() is used, once we've confirmed that a flesh and bone bodypart has both the skin and bone mangled, to actually roll for it + * + * Mangling is described in the above proc, [/obj/item/bodypart/proc/get_mangled_state()]. This simply makes the roll for whether we actually dismember or not + * using how damaged the limb already is, and how much damage this blow was for. If we have a critical bone wound instead of just a severe, we add +10% to the roll. + * Lastly, we choose which kind of dismember we want based on the wounding type we hit with. Note we don't care about all the normal mods or armor for this + * + * Arguments: + * * wounding_type: Either WOUND_BLUNT, WOUND_SLASH, or WOUND_PIERCE, basically only matters for the dismember message + * * wounding_dmg: The damage of the strike that prompted this roll, higher damage = higher chance + * * wound_bonus: Not actually used right now, but maybe someday + * * bare_wound_bonus: ditto above + */ +/obj/item/bodypart/proc/try_dismember(wounding_type, wounding_dmg, wound_bonus, bare_wound_bonus) + if(wounding_dmg < DISMEMBER_MINIMUM_DAMAGE) + return + + var/base_chance = wounding_dmg + (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 10% more + base_chance += 10 + + if(!prob(base_chance)) + return + + var/datum/wound/loss/dismembering = new + dismembering.apply_dismember(src, wounding_type) + + return TRUE //when a limb is dropped, the internal organs are removed from the mob and put into the limb /obj/item/organ/proc/transfer_to_limb(obj/item/bodypart/LB, mob/living/carbon/C) @@ -378,7 +423,7 @@ /mob/living/carbon/regenerate_limb(limb_zone, noheal) var/obj/item/bodypart/L if(get_bodypart(limb_zone)) - return 0 + return FALSE L = newBodyPart(limb_zone, 0, 0) if(L) if(!noheal) @@ -386,6 +431,8 @@ L.burn_dam = 0 L.brutestate = 0 L.burnstate = 0 - + var/datum/scar/scaries = new + var/datum/wound/loss/phantom_loss = new // stolen valor, really + scaries.generate(L, phantom_loss) L.attach_limb(src, 1) - return 1 + return TRUE diff --git a/code/modules/surgery/bodyparts/head.dm b/code/modules/surgery/bodyparts/head.dm index a67f16b934..13b1140527 100644 --- a/code/modules/surgery/bodyparts/head.dm +++ b/code/modules/surgery/bodyparts/head.dm @@ -36,11 +36,10 @@ var/custom_head wound_resistance = 10 - specific_locations = list("left eyebrow", "cheekbone", "neck", "throat", "jawline", "entire face") scars_covered_by_clothes = FALSE /obj/item/bodypart/head/can_dismember(obj/item/I) - if(!((owner.stat == DEAD) || owner.InFullCritical())) + if(owner && !((owner.stat == DEAD) || owner.InFullCritical())) return FALSE return ..() diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm index a18b31e4c1..5a887ee6b7 100644 --- a/code/modules/surgery/bodyparts/parts.dm +++ b/code/modules/surgery/bodyparts/parts.dm @@ -12,7 +12,7 @@ var/obj/item/cavity_item /obj/item/bodypart/chest/can_dismember(obj/item/I) - if(!((owner.stat == DEAD) || owner.InFullCritical())) + if(!((owner.stat == DEAD) || owner.InFullCritical()) || !get_organs()) return FALSE return ..() diff --git a/code/modules/surgery/burn_dressing.dm b/code/modules/surgery/burn_dressing.dm index 1688f7b5d1..8bfa52d245 100644 --- a/code/modules/surgery/burn_dressing.dm +++ b/code/modules/surgery/burn_dressing.dm @@ -94,7 +94,8 @@ log_combat(user, target, "dressed burns in", addition="INTENT: [uppertext(user.a_intent)]") burn_wound.sanitization += 3 burn_wound.flesh_healing += 5 - burn_wound.force_bandage(tool) + var/obj/item/bodypart/the_part = target.get_bodypart(target_zone) + the_part.apply_gauze(tool) else to_chat(user, "[target] has no burns there!") return ..() diff --git a/code/modules/surgery/repair_puncture.dm b/code/modules/surgery/repair_puncture.dm new file mode 100644 index 0000000000..12aefefc82 --- /dev/null +++ b/code/modules/surgery/repair_puncture.dm @@ -0,0 +1,108 @@ + +/////BURN FIXING SURGERIES////// + +//the step numbers of each of these two, we only currently use the first to switch back and forth due to advancing after finishing steps anyway +#define REALIGN_INNARDS 1 +#define WELD_VEINS 2 + +///// Repair puncture wounds +/datum/surgery/repair_puncture + name = "Repair puncture" + steps = list(/datum/surgery_step/incise, /datum/surgery_step/repair_innards, /datum/surgery_step/seal_veins, /datum/surgery_step/close) // repeat between steps 2 and 3 until healed + target_mobtypes = list(/mob/living/carbon) + possible_locs = list(BODY_ZONE_R_ARM,BODY_ZONE_L_ARM,BODY_ZONE_R_LEG,BODY_ZONE_L_LEG,BODY_ZONE_CHEST,BODY_ZONE_HEAD) + requires_real_bodypart = TRUE + targetable_wound = /datum/wound/pierce + +/datum/surgery/repair_puncture/can_start(mob/living/user, mob/living/carbon/target) + . = ..() + 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) + return(pierce_wound && pierce_wound.blood_flow > 0) + +//SURGERY STEPS + +///// realign the blood vessels so we can reweld them +/datum/surgery_step/repair_innards + name = "realign blood vessels" + implements = list(TOOL_HEMOSTAT = 100, TOOL_SCALPEL = 85, TOOL_WIRECUTTER = 40) + 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 + if(!pierce_wound) + user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_selected)].", "You look for [target]'s [parse_zone(user.zone_selected)]...") + return + + if(pierce_wound.blood_flow <= 0) + to_chat(user, "[target]'s [parse_zone(user.zone_selected)] has no puncture to repair!") + surgery.status++ + return + + display_results(user, target, "You begin to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)]...", + "[user] begins to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)] with [tool].", + "[user] begins to realign the torn blood vessels in [target]'s [parse_zone(user.zone_selected)].") + +/datum/surgery_step/repair_innards/success(mob/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 + if(!pierce_wound) + to_chat(user, "[target] has no puncture wound there!") + return ..() + + display_results(user, target, "You successfully realign some of the blood vessels in [target]'s [parse_zone(target_zone)].", + "[user] successfully realigns some of the blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!", + "[user] successfully realigns some of the blood vessels in [target]'s [parse_zone(target_zone)]!") + log_combat(user, target, "excised infected flesh in", addition="INTENT: [uppertext(user.a_intent)]") + surgery.operated_bodypart.receive_damage(brute=3, wound_bonus=CANT_WOUND) + pierce_wound.blood_flow -= 0.25 + return ..() + +/datum/surgery_step/repair_innards/failure(mob/user, mob/living/target, target_zone, obj/item/tool, datum/surgery/surgery, var/fail_prob = 0) + . = ..() + display_results(user, target, "You jerk apart some of the blood vessels in [target]'s [parse_zone(target_zone)].", + "[user] jerks apart some of the blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!", + "[user] jerk apart some of the blood vessels in [target]'s [parse_zone(target_zone)]!") + surgery.operated_bodypart.receive_damage(brute=rand(4,8), sharpness=SHARP_EDGED, wound_bonus = 10) + +///// Sealing the vessels back together +/datum/surgery_step/seal_veins + name = "weld veins" // if your doctor says they're going to weld your blood vessels back together, you're either A) on SS13, or B) in grave mortal peril + implements = list(TOOL_CAUTERY = 100, /obj/item/gun/energy/laser = 90, TOOL_WELDER = 70, /obj/item = 30) + time = 4 SECONDS + +/datum/surgery_step/seal_veins/tool_check(mob/user, obj/item/tool) + if(implement_type == TOOL_WELDER || implement_type == /obj/item) + return tool.get_temperature() + + 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 + if(!pierce_wound) + user.visible_message("[user] looks for [target]'s [parse_zone(user.zone_selected)].", "You look for [target]'s [parse_zone(user.zone_selected)]...") + return + display_results(user, target, "You begin to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)]...", + "[user] begins to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)] with [tool].", + "[user] begins to meld some of the split blood vessels in [target]'s [parse_zone(user.zone_selected)].") + +/datum/surgery_step/seal_veins/success(mob/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 + if(!pierce_wound) + to_chat(user, "[target] has no puncture there!") + return ..() + + display_results(user, target, "You successfully meld some of the split blood vessels in [target]'s [parse_zone(target_zone)] with [tool].", + "[user] successfully melds some of the split blood vessels in [target]'s [parse_zone(target_zone)] with [tool]!", + "[user] successfully melds some of the split blood vessels in [target]'s [parse_zone(target_zone)]!") + log_combat(user, target, "dressed burns in", addition="INTENT: [uppertext(user.a_intent)]") + pierce_wound.blood_flow -= 0.5 + if(pierce_wound.blood_flow > 0) + surgery.status = REALIGN_INNARDS + to_chat(user, "There still seems to be misaligned blood vessels to finish...") + else + to_chat(user, "You've repaired all the internal damage in [target]'s [parse_zone(target_zone)]!") + return ..() + +#undef REALIGN_INNARDS +#undef WELD_VEINS diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm index 040f3ce487..7a5356ce06 100644 --- a/code/modules/vending/_vending.dm +++ b/code/modules/vending/_vending.dm @@ -530,8 +530,7 @@ GLOBAL_LIST_EMPTY(vending_products) for(var/i in C.bodyparts) var/obj/item/bodypart/squish_part = i if(squish_part.is_organic_limb()) - //var/type_wound = pick(WOUND_LIST_BLUNT) - 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)) + var/type_wound = pick(list(/datum/wound/blunt/critical, /datum/wound/blunt/severe, /datum/wound/blunt/moderate)) squish_part.force_wound_upwards(type_wound) else squish_part.receive_damage(brute=30) diff --git a/interface/stylesheet.dm b/interface/stylesheet.dm index 9f3d8911ec..9c35ddb75f 100644 --- a/interface/stylesheet.dm +++ b/interface/stylesheet.dm @@ -66,7 +66,9 @@ h1.alert, h2.alert {color: #000000;} .passive {color: #660000;} .userdanger {color: #ff0000; font-weight: bold; font-size: 3;} -.danger {color: #ff0000;} +.danger {color: #ff0000; font-weight: bold;} +.tinydanger {color: #ff0000; font-size: 85%;} +.smalldanger {color: #ff0000; font-size: 90%;} .warning {color: #ff0000; font-style: italic;} .boldwarning {color: #ff0000; font-style: italic; font-weight: bold} .announce {color: #228b22; font-weight: bold;} @@ -75,6 +77,9 @@ h1.alert, h2.alert {color: #000000;} .rose {color: #ff5050;} .info {color: #0000CC;} .notice {color: #000099;} +.tinynotice {color: #000099; font-size: 85%;} +.smallnotice {color: #000099; font-size: 90%;} +.smallnoticeital {color: #000099; font-style: italic; font-size: 90%;} .boldnotice {color: #000099; font-weight: bold;} .adminnotice {color: #0000ff;} .adminhelp {color: #ff0000; font-weight: bold;} diff --git a/sound/effects/blood1.ogg b/sound/effects/wounds/blood1.ogg similarity index 100% rename from sound/effects/blood1.ogg rename to sound/effects/wounds/blood1.ogg diff --git a/sound/effects/blood2.ogg b/sound/effects/wounds/blood2.ogg similarity index 100% rename from sound/effects/blood2.ogg rename to sound/effects/wounds/blood2.ogg diff --git a/sound/effects/blood3.ogg b/sound/effects/wounds/blood3.ogg similarity index 100% rename from sound/effects/blood3.ogg rename to sound/effects/wounds/blood3.ogg diff --git a/sound/effects/crack1.ogg b/sound/effects/wounds/crack1.ogg similarity index 100% rename from sound/effects/crack1.ogg rename to sound/effects/wounds/crack1.ogg diff --git a/sound/effects/crack2.ogg b/sound/effects/wounds/crack2.ogg similarity index 100% rename from sound/effects/crack2.ogg rename to sound/effects/wounds/crack2.ogg diff --git a/sound/effects/wounds/crackandbleed.ogg b/sound/effects/wounds/crackandbleed.ogg new file mode 100644 index 0000000000000000000000000000000000000000..ea07f13d482087be78a525d993bf912626925e46 GIT binary patch literal 15662 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�U|E2pS-PVJnM8WxMioIfus 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 S<^2F2lVd6ny$diMr~d^L?J`vW literal 0 HcmV?d00001 diff --git a/sound/effects/wounds/pierce1.ogg b/sound/effects/wounds/pierce1.ogg new file mode 100644 index 0000000000000000000000000000000000000000..cd7b7c39610214fd14ae4e6bb2e267f9f91fb3b7 GIT binary patch literal 8726 zcmb7Jc|4Tg_kYGNOUf=XM2vl{C?&gzG{e}JEMprKV`PcO8WI{~$r1`7e6ozKh^)zy z>^s?0*|MehJ;UeweSN;aKYq*ex^rLWIrrXk?mhRs&pr1U11Bd#fCBjYX}WYwFrA0K zhn$7@-0`w=!ID`J{F~#JH3P^IQ4KL5kNo#T9!YKyUszK*>2mnb=LzMp9C5JO)a9l-BM%idaQASz>xIUmJ-lJ$NwI-HBV8jsO%=mCI1dLk z7dtn!l>Hs|(;)vk(n#0PNJZZTgNEL?gZ6N7f>0kTI057P=)r|iXj{*P| z0LUu3m=w@nw=)?KoUhFm5J{$Hi?l!aN7jJUkGhvU0Utpg7OLRD4ggdD9!8hyHLdow zZs#ob!YKrgSR0uNkCGvBhpQxxny&~XjH`WBSv*U}WJV2uMpUH}2xCL)2!#Kug5{>z zMZ@w^>^fjCd9j_cZO~9=<)xg2TWa*MoLg|Qf*c|eE;(q9{ZU6dfnB}63k_pY1BLvn zI$8%5oD0ZwIAW3|AIm#l78JmPrT}!Guzf7$?ds+2TIcOKC5$*N+$$&9hg39_S3wzR z4j7?KP*zs=+y{Kz2a?=}jE@Loce6_OvHvVbONT;$taD0)b1;G+j4*qNKou5IL;*OE zO_C)VJ$os3PA68_h2ZFyf|1@=};Ms|zE}#QYk!J%;`$jMN#ya^Cj_TBxE~$C{ z*P`m&E(WNAwrum{Jucc_LbOK~ZU?|URYeN5c}Zwv722>@w7oUjy!Ad1jXsbp8UD2i z;I@O0DyxL1;gz<8D?O}=J$(vYtojHA{l5Q0F=Puq@)vL+0vV1;u6R26c-teh;6brm z*>viR$C|(nk=b+5)K96KT}sTU^H~LKX?=}RMrk571u1FRZl%R^w{Gs)bZj@Q<7rFQ z(@&|`Ze7OI++)h`bQ*1O!Do=iy_nA2%54kwbNQS~TQFh@jy3y~x{zPP22xSPG!asb z(XqTEq1f&M>-6qMr5SKU)My%}hTaOK_8iiGbkUP}px(bL`Xl#I1^3N%n5#7-1R5Ai zW5*_tCy;Q~JB~RaOST=BbM|qp7Q7(z7Lr>e*E{5BkuvPl=~<_u8Nwvl~-Ojv8Xf3R(ys_C=M9gKPD|a!-|URS?2|v`PiS2oEc@}<8GFW8>YkR``;fc_V zG9mrX5?vb#2Ac}KteT*^7_wXSvg7(V(1sVR`V`T9DD;32dZZFij2iV!vF9J*P_$G9#QnLQcWcXUhf8{~L0$oTFc+M8AxTUW|+tjY@Kf zN-eB;?$%MVQv1J_eI|UZgb8aH%(qDW=xTa%?%5c71HcSWU zg^}G2(uHm%@HGb6L8=%E4^mYZ(h zEs#gVb|}rKhkn*ANXLFwf;~Z!U%k3@m(z{9m0%fR;1NT?3;ra+K&Vgwo)iFc+xivV zJ`KcY1;kIiUYts=x0P<6o*}CyYCr>l(l;Tw_Zp!sJ}dO~gRhDRBNRf>eZ&YgwyoEf zq(3y^jzHloD&1{;-N$xR`YOOz_X%$+i+k=PJ7|lc$J$4tOh8dMeUkxqL!7%6tL6|p z$|Om1AQ5engtJLRPYh}F;xq?{RtOy0BGGEf2W_^aKeUBIC53~nGgUY%E{~~;&p<^s zV5X*|9R)#vxFF7Kvzb>yG;rXT->0;EcDG6>RAP~!X`Ze~}nuM%7!t`8SD zwT*LninH3)9NG#*B?a1(&^Ei_Qw962>oJ9eD}~=ryc7HQ{x!p!&GC9^B5rKgeZpzH zK5l*Xck2_(*n8QPO6+)jiNw22`5?5Zf1b-&-pa4q<=T4bm0H>H`oGvv14Af_3lRf} z;jOxKqM=0o5hP+mRbPG2*!h4W;OUJdltFH9EVO_`rI52xUQrfquN3W zu~P|_O-xdQNrs;`XUJ{lfV&ivj4`f~gDh}NHjzsmCYd+rs#iR~BTFNIy$N4P2csL< zFetZ}@6C+-3I&gI*U}s|`}uStqp}!Z7!fWen@F@{ENC`HMw4=k>@lVD9QNJWM2;I` zrC@`*>^zr!rxICt`mypsa4yE6gMy-zL<>MsFjz~ck}fDpc}Wx;p(okG0goyMMZpSM zKv9w{rs}$qNkltISj(_oXH83z1#LDd9v%Zu*CIx#YS5J_x7qYqc?@Zri>#dMhL|Ea z!d-ED)UHU0l!S3DUEr|qAPs+3zaAZ+Q6U>hdd!WBj%(3+m`3EG^3MT)hihsMKOQm`!Wj`Yx5aQIV@(uENT zaCmVz5)LmQfv`P6hOOHtqA70{Iq0a00r*BwiI1Ba2u1WrsZbBAW*>-3A2O#`0X0x5 zdCUPFn9MOk4d8GStmMRK2=x4&qdqtg4*GrGWX{-jV4nhN2!{saye;mCGw5z_O6H7I zx?3rEOn`{sjId1^t^KiIFU{Dtrbh`hu<`=<6KESbyz z(}%a4zS4lTo>>|+#%%#mOha5XhM z1mq*xR!hu}n&d&dBGLkwov4sF?28o_$FXbV&fO$1`@U7&Vu~qIqMZqV0OL%|01N$v z?$-ow<4Zi2M`jWN@T!rrt?5{15WpI6Sy0STKCA=#n->=UH!qurlso1L6K{bKCHDh) z@DImh$wuSz{+kEOCCekX!g9f+Tl6?vA%d-cQ>Xt;A^+7c2MPas1UQUd;Akwl$_^t- zAyZ_%N0eADcz?M&4IYWNsWKdl%)%a@xAX;$93M=Tq21go#c zwxi|{p`#%|6GcCuijd_4B&1~KC{-g`wMJX0y}74Dq<$!~sIi2wG=Bk3=rlCaU%av& zAu>KqmGK-&dvv1%1LjEpXro~{)yu2>u#HwHvYk#>7tEjl;1ke53pChLXlN+3_0FtA zP7BJZA<0*;K+pkIxi+J0h17K ztAxQMBwK_;&%>l7L?p$Uzwn)Re6+-V$*K}1@z~nTQgabXe4$qnK@2>yJ^XoQ zz4AV!R{x=GHdqONp>Y4;efEhLbQzWUUIEXWpUMyRmQc8ERJgqPF|*YB=DCI6ms{O+ zqhfFKwGUEH(SO^M+B1#b-OTsYs*PV^_&Be?<k97vSiYV#7n?EsK2Sor;gn9<0#t1wsrkIeoq#-JM1pBhKmbrE-Ze-# zWIW5;nh>n75}6fQ)usKZ-%Q)hc!Wy>g%a+X+DbE6(D&DQHQ!`ocX;8?dFTDCj`lRM z1jx++)1iF|$ZjIn@{>}6uZNY7e$kRv?+UKyn&`dNbyu_3N-biyqsE8AfcOV*>JstX z!V1y~``d-Ebv?%BrUdzt_eisx`ee!Lf`TD$97_fTHc(k-2|B6oWY&rA;Rfslmo82$ zJv7By#lEzyvVWvrk#*-$yod&gB~UYeb(!BOz;7uVzItfMx@1KbV$}~*UerI#O<-U03j2Wad+E?q%76?~)&1EJc6}3X2 z2X63}iVryDKkM-_e%pG}_4$~|?CiGxu*YAiHR8E%Pfp*{(+n{F5N}X4QYlgC@Z2+` zaO>M*`C<5~GPgeUWfn$-f(j~Bvg4dV@bLR-RiX#>&+P{PvnpJS@{~FPY2R5asEcm- zQde1jg`Rof^7Bbq^!FEQl2Z!v`cEI%I0tAIM*ShBocXWHtq{p41t*!8KseX-0nqr9x zl+@1j{g+JrrC)2^s*1`Z3idjM5<81qZe118zy3_hb(*0jD>_i>t-$k!yL0Dy&yXS* zeI!&z3x-Tg!e24ny<4ao5*nO-gBW7ped;d*LwqFrd{aT^0??wRxvX+M_=^DJxvb1R zJ`pjK-o3ShLQ|Uklg@^+UDx!a-7og}`JCszp$~Xuj@}mVuOI2=Vr~ONR!$IF zQVda6wf}1GGz%5bxsjW_=TNWC{kyhqu79+kY|{ZxACvkA|M~}E5}<+tw@;{^!_8lz z*tmcu7?s}VZvX4fD|1Z8H6xF}n|UtrlVc0i&Gf2^!|L7}i6@O7O7F|Lq6AjO0YO!& zND3g#2Q7I*Y*E09CM!?%qITANW{|2JxcrS5$8+&zI z+os-S(pg2)Yb3EkmRGB-PeOTseCgXJ(Ls9sRDqQ>F7B51mue%_9;}*w?5vQ&wx36s z^Jpa$*x#Y0zx0wC$VYfE_KTV+OsTB8$+O68ZcT1ApyZ7oob$7L*_v1zV%TGKXZ&H+ zVE6hLxwz)vrBN6szrKp}p3nJh+umps3j@|}hlf~#{-x}syDaI1xF-}5xdGL+r#WBx zbpC<9{2~(a5_dAX5YIPeQxRPEWAUmL|MkF~rO`rd=|B0L$saj;s&=gkxeYn^mLFNc zWjRiXRM|Yq)h^$=!dQk?g0}}KDnHZ_J{QZ^^7E}+bRaipx^NN#5 zuk2h#0eA}n`A8H71=roFa8x}5yipe<(S$O)Zhx;R86E8tP|>Tu6(qjd*!liU;x=m; z5Aq@Y$#^EUu6gVF6la@$QhrF%(f-HfOm5)LAY{isYtIR3K~$0hBRJ5=Kb$ z4HTh7M%|s4l|k^qwZ71aru5=b4D4X5di%k}%wKCiPnL~UOcg0bQ{9kzn>v;hx^C&V zKSmcbYk5{wO%Bs+sxEl#shbu5)p3GOshTJ=1NP#w971j}=Iks_r0e4nF~+yi=asoO z-+M|1JddWXnPd4{=9x*EVp6`8z#iq7?{2}7p+@+v`CMs{8)tQxX3pK*lEUR-7BRv< z^T#H%HG5)&xq*e>MxM%M3&Q9O{6^fPn!MN0c%L4x3N!>XI3;}-wRlf#o%@^v53ai= z9HBFF|F=sr>FgU}14GeNFIzq{ z1%yEWLqJO6qp*fCU2+nC+(0Ep;cSHv^wn)wBt6o!kV7q>y=sd+Y;Wu2*+Lb#1me({uA^r^Pr20_MTLt8x&L4kSq&Rzt z(QxtBVBDJlXGObYnmMz}fagea2Q?mI4-7J1x+t0QB(Am^9n(>z{q9X>bXA||0iSSe zv)Z>jN(o29D;=R6+etvfDIf)4qgU%IlXSssxVtP^n;A_yEecWq`~Wb{cbPD~cA^%+M(>&7KnMzh_T`3*vvaaMN6gpph%oU&fE^63 z*{JyW)*f1`s7B<~Zjb`wjUW4quS1rSIDk%lagLF$G8F&=WSyOESQs@vk6eh2dZ98_ zvSL}ddr_(K(^uwx-=Jc8Of}v5)M4s$(C6kd3a87V4Zzow#b>=@BkxUWOqgDQ=*eF} z6w>XUZ_QKpPh1xnvEjCEIekuJF#3Udy>^6c`-w=b5c8>^FT9SYzg>%Q;OQF?L5(HY z)izG}E*I)jSXWaa@WjjI=X_kt_r@k1S>h54-#n?XOUyYD)b`}*rs)R3xn7~1)Z5)g z_h&Z)DmNPFj4-ii3&m?AHvb-)(_;hm!UBa90DM@8kJzF)s`NAh+{OXBa$OBsDA+fXM` z|9qj)|0j}GuIizg*4#}A{Q0u4^V9UwFP^5>NIC19TV4$MwB#$sGk67p_%pO@#@Bwfr*LG4dKL5Ud`O`C5XK7W5$3daRldm>5@?^cQk$Jy>7F_I`o_sz zfaYrbX|YBYI_O)eX-Zo*D4cDY5}>l2${QQNKb~sGC2j z)u`UogY;i#mFOZpz5p=bN%(;NGe(N0lVU#&uoa{q+jn9s2b-V@)qkq!;S^Nx3(%>#GqGI4YEOHY0>I(-)^8YhnoeFX@sa$ilACvG%<;lP z6!1R&-MvPJfm4v*2>tp?+;{J3QASeSrr+(C$CY}uy#4*KaCtcYnbh-`?FEuylKakK zjRJK)N}o1xh2kY8o*TGDD@y#8lU_8~UlZBo=aOeIu+z55VKI~RWj+u#38m`1ekRsG z35`?68w2oAagYI;dki~>l$MusNe$;?- zBgHNKZ{`Ty+0T*mse@}w$diuCa>YW+*~^H5)KSN$8*PEqV0!g(L^oPha`e8vedlRj zq_WG68jj3wy(&!3yz9e5`wBb6*i?c)IQvd19oE^ey~!7NZN^NVP8^i>)VOC8>rbeB z^L6!XHm(d8t-OouN|k)X%c?2B6d5fsiWfI?EWW@ImYx%qfzm0Y;pj*z7O00+Kr%+XM*mANIung?}vNkZGl zQ3&S80vvr?pb7*3&LuzOZwuhZ5dgFFV2_2&XmaMF$~br0c`m7AO$n-5oEsm(*qcLr~X22iS$LH z;$>sMAt_xqZfI60H6RKY*KJ+IrRi!4qAOjQ9*E8gol9Gbx?(uLT6QzANH#5U<=c)X z?I&KKfn_>b-={PCdhYkOiJ{%_)%R^bfymHRduhp8z*v@R5>B7~? zYY()ySNtD!?_XVj0`1omdCt6m+rB&Xz$)nKokMPGyW&4Vf%b*7XNw1Wsr%o@-CgfU zG~}fJv2XINIHl&NB7^6YMcl>6Qp55F8T&#_hpnYv(JPhQZrLLx1-t2}i+eZgSHUiK3Jr?6Dx06ix2s7he7w(qKklsq3X{4FkME+8ASn<0j z%lu1cuur|1zav7cwY)LWX!4y<;dsch`d1^+;%6%r(lzGRCUo-4y~Q;sIeqdWXj z!ot*^B&+E~1J3=rVyCN(t5aXcQCvI^;ASl<4?jKs^D_)lGMi5CwEAOGCV{zse9e*u zJRfc-n$I-3JrQXgJ=Bam6T`LGWIbn6u3iDf^qn4Ke`jPy$m0=2ZFO1IZQj56EXmI% zdoo{+LRNY!UJTK-QQi50elo1rBa$BFfmqDFWr`K}=Hf|H4XG!^%=&US`P!-#`@XvH zkc%s{#{CZET#nnNwL<3Ug+J0LFVE1_-tUng-@P@0M@rW3wM7uSbxTp1QfUR|O}t4A z2Cg{$lx}Ig{ER!dpLfCe)c3yF{M53)e6C%xH6M9sFXb1Zr|(=Amlvd263YmTpTV+A zMvnf8?e%cTAu`fW%QCdO1$Sg1T^T-B!<4VF-@2=#D4-A;#ZvC7_s}rh7C0b{Tbp3ovP?QWV(6({sh!uu!^4)%Outn;xAvm;?*5iZhav_ zyU#3aNWwY4mHC3tPs^gc{YTAlS1sM|ux6y*%#LEfEUq-ya@^(|j_jxI(c4u<@C&l_ xD-m^k2C_uDd!zl=G))>Z6h#4BZ{4d~r)qjJKX2bPrnVVNPY*?S+_Gl_{tH82f2sfg literal 0 HcmV?d00001 diff --git a/sound/effects/wounds/pierce2.ogg b/sound/effects/wounds/pierce2.ogg new file mode 100644 index 0000000000000000000000000000000000000000..4977cab299f273a74f00de7c2f7425e04c150ede GIT binary patch literal 17779 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 SldO-Z&s+!&4h{|u4h{~SE}iWF literal 0 HcmV?d00001 diff --git a/sound/effects/sizzle1.ogg b/sound/effects/wounds/sizzle1.ogg similarity index 100% rename from sound/effects/sizzle1.ogg rename to sound/effects/wounds/sizzle1.ogg diff --git a/sound/effects/sizzle2.ogg b/sound/effects/wounds/sizzle2.ogg similarity index 100% rename from sound/effects/sizzle2.ogg rename to sound/effects/wounds/sizzle2.ogg diff --git a/strings/wounds/bone_scar_desc.json b/strings/wounds/bone_scar_desc.json new file mode 100644 index 0000000000..3540547c4a --- /dev/null +++ b/strings/wounds/bone_scar_desc.json @@ -0,0 +1,26 @@ +{ + "generic": ["general disfigurement"], + + "bluntmoderate": [ + "the bone equivalent of a faded bruise", + "a series of tiny chip marks" + ], + + "bluntsevere": [ + "a series of faded hairline cracks", + "a small bone dent" + ], + + "bluntcritical": [ + "large streaks of refilled cracks", + "a fractal of reformed stress marks", + "a cluster of calluses" + ], + + "dismember": [ + "is slightly misaligned", + "has clearly been dropped recently", + "has a damaged socket" + ] + +} \ No newline at end of file diff --git a/strings/wounds/flesh_scar_desc.json b/strings/wounds/flesh_scar_desc.json new file mode 100644 index 0000000000..fb2b927a30 --- /dev/null +++ b/strings/wounds/flesh_scar_desc.json @@ -0,0 +1,86 @@ +{ + "generic": ["general disfigurement"], + + "bluntmoderate": [ + "light discoloring", + "a slight blue tint" + ], + + "bluntsevere": [ + "a faded, fist-sized bruise", + "a vaguely triangular peel scar" + ], + + "bluntcritical": [ + "a section of janky skin lines and badly healed scars", + "a large patch of uneven skin tone", + "a cluster of calluses" + ], + + + + "slashmoderate": [ + "light, faded lines", + "minor cut marks", + "a small faded slit", + "a series of small scars" + ], + + "slashsevere": [ + "a twisted line of faded gashes", + "a gnarled sickle-shaped slice scar" + ], + + "slashcritical": [ + "a winding path of very badly healed scar tissue", + "a series of peaks and valleys along a gruesome line of cut scar tissue", + "a grotesque snake of indentations and stitching scars" + ], + + + + "piercemoderate": [ + "a small, faded bruise", + "a small twist of reformed skin", + "a thumb-sized puncture scar" + ], + + "piercesevere": [ + "an ink-splat shaped pocket of scar tissue", + "a long-faded puncture wound", + "a tumbling puncture hole with evidence of faded stitching" + ], + + "piercecritical": [ + "a rippling shockwave of scar tissue", + "a wide, scattered cloud of shrapnel marks", + "a gruesome multi-pronged puncture scar" + ], + + + + "burnmoderate": [ + "small amoeba-shaped skinmarks", + "a faded streak of depressed skin" + ], + + "burnsevere": [ + "a large, jagged patch of faded skin", + "random spots of shiny, smooth skin", + "spots of taut, leathery skin" + ], + + "burncritical": [ + "massive, disfiguring keloid scars", + "several long streaks of badly discolored and malformed skin", + "unmistakeable splotches of dead tissue from serious burns" + ], + + + "dismember": [ + "is several skintone shades paler than the rest of the body", + "is a gruesome patchwork of artificial flesh", + "has a large series of attachment scars at the articulation points" + ] + +} \ No newline at end of file diff --git a/strings/wounds/scar_loc.json b/strings/wounds/scar_loc.json new file mode 100644 index 0000000000..f721294925 --- /dev/null +++ b/strings/wounds/scar_loc.json @@ -0,0 +1,52 @@ +{ + "": ["general area"], + + "head": [ + "left eyebrow", + "cheekbone", + "neck", + "throat", + "jawline", + "entire face" + ], + + "chest": [ + "upper chest", + "lower abdomen", + "midsection", + "collarbone", + "lower back" + ], + + "l_arm": [ + "outer left forearm", + "inner left wrist", + "left elbow", + "left bicep", + "left shoulder" + ], + + "r_arm": [ + "outer right forearm", + "inner right wrist", + "right elbow", + "right bicep", + "right shoulder" + ], + + "l_leg": [ + "inner left thigh", + "outer left calf", + "outer left hip", + "left kneecap", + "lower left shin" + ], + + "r_leg": [ + "inner right thigh", + "outer right calf", + "outer right hip", + "right kneecap", + "lower right shin" + ] +} \ No newline at end of file diff --git a/tgstation.dme b/tgstation.dme index 2a7156f043..59fe18bdff 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -659,7 +659,9 @@ #include "code\datums\wounds\_wounds.dm" #include "code\datums\wounds\bones.dm" #include "code\datums\wounds\burns.dm" -#include "code\datums\wounds\cuts.dm" +#include "code\datums\wounds\loss.dm" +#include "code\datums\wounds\pierce.dm" +#include "code\datums\wounds\slash.dm" #include "code\game\alternate_appearance.dm" #include "code\game\atoms.dm" #include "code\game\atoms_movable.dm" @@ -3290,6 +3292,7 @@ #include "code\modules\surgery\plastic_surgery.dm" #include "code\modules\surgery\prosthetic_replacement.dm" #include "code\modules\surgery\remove_embedded_object.dm" +#include "code\modules\surgery\repair_puncture.dm" #include "code\modules\surgery\surgery.dm" #include "code\modules\surgery\surgery_step.dm" #include "code\modules\surgery\tools.dm" From 315e7e1f997bae60b0bc623a5601c6030cadb327 Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 24 Jul 2020 23:49:15 +0100 Subject: [PATCH 06/91] bugfixes --- code/controllers/subsystem/persistence.dm | 4 ++-- code/datums/wounds/slash.dm | 2 +- code/modules/admin/verbs/randomverbs.dm | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm index b8a3a10866..5b60747725 100644 --- a/code/controllers/subsystem/persistence.dm +++ b/code/controllers/subsystem/persistence.dm @@ -561,8 +561,8 @@ SUBSYSTEM_DEF(persistence) ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = "" else for(var/k in ending_human.all_wounds) - var/datum/wound/iter_wound = k - iter_wound.remove_wound() // so we can get the scars for open wounds + var/datum/wound/iter_wound = k + iter_wound.remove_wound() // so we can get the scars for open wounds if(!ending_human.client) return ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = ending_human.format_scars() diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm index 5254fc3e73..41a6a1ae14 100644 --- a/code/datums/wounds/slash.dm +++ b/code/datums/wounds/slash.dm @@ -142,7 +142,7 @@ if(user.pulling != victim || user.zone_selected != limb.body_zone || user.a_intent == INTENT_GRAB) return FALSE - if(!isfelinid(user)) + if(!iscatperson(user)) return FALSE lick_wounds(user) diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 5eb1ede525..69f02c58c5 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -1381,9 +1381,9 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits var/obj/item/bodypart/slice_part = i var/type_wound = pick(list(/datum/wound/slash/severe, /datum/wound/slash/moderate)) slice_part.force_wound_upwards(type_wound, smited=TRUE) - type_wound = pick(list(/datum/wound/brute/cut/critical, /datum/wound/brute/cut/severe, /datum/wound/brute/cut/moderate)) + type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe, /datum/wound/slash/moderate)) slice_part.force_wound_upwards(type_wound, smited=TRUE) - type_wound = pick(list(/datum/wound/brute/cut/critical, /datum/wound/brute/cut/severe)) + type_wound = pick(list(/datum/wound/slash/critical, /datum/wound/slash/severe)) slice_part.force_wound_upwards(type_wound, smited=TRUE) if(ADMIN_PUNISHMENT_SCARIFY) if(!iscarbon(target)) From 3ca098fe98009fb476272c8db003ffc9c02eb3a8 Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sat, 25 Jul 2020 00:22:24 +0100 Subject: [PATCH 07/91] bugfixes --- code/_onclick/item_attack.dm | 15 ++++++------ code/datums/components/embedded.dm | 20 ++++++--------- code/datums/components/pellet_cloud.dm | 2 +- code/datums/elements/embed.dm | 20 ++++++--------- code/game/objects/items/latexballoon.dm | 2 +- code/game/objects/items/shrapnel.dm | 2 +- code/modules/admin/verbs/randomverbs.dm | 4 +-- code/modules/mob/living/living_defense.dm | 4 +-- code/modules/projectiles/projectile.dm | 23 ------------------ .../modules/projectiles/projectile/bullets.dm | 2 +- .../chemistry/reagents/medicine_reagents.dm | 5 ++-- .../reagents/reagent_containers/hypospray.dm | 7 ++++++ sound/weapons/shot.ogg | Bin 0 -> 10751 bytes tgstation.dme | 1 + 14 files changed, 39 insertions(+), 68 deletions(-) create mode 100644 sound/weapons/shot.ogg diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index be576333cf..838741108d 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -214,21 +214,20 @@ var/message_verb = "attacked" if(length(I.attack_verb)) message_verb = "[pick(I.attack_verb)]" - if(current_force < I.force * FEEBLE_ATTACK_MSG_THRESHOLD) - message_verb = "[pick("feebly", "limply", "saplessly")] [message_verb]" else if(!I.force) return var/message_hit_area = "" if(hit_area) message_hit_area = " in the [hit_area]" - var/attack_message = "[src] has been [message_verb][message_hit_area] with [I]." + var/attack_message = "[src] is [message_verb][message_hit_area] with [I]!" + var/attack_message_local = "You're [message_verb][message_hit_area] with [I]!" if(user in viewers(src, null)) - attack_message = "[user] has [message_verb] [src][message_hit_area] with [I]!" + attack_message = "[user] [message_verb] [src][message_hit_area] with [I]!" + attack_message_local = "[user] [message_verb] you[message_hit_area] with [I]!" + if(user == src) + attack_message_local = "You [message_verb] yourself[message_hit_area] with [I]" visible_message("[attack_message]",\ - "[attack_message]", null, COMBAT_MESSAGE_RANGE) - if(hit_area == BODY_ZONE_HEAD) - if(prob(2)) - playsound(src, 'sound/weapons/dink.ogg', 30, 1) + "[attack_message_local]", null, COMBAT_MESSAGE_RANGE) return 1 /// How much stamina this takes to swing this is not for realism purposes hecc off. diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm index c43df20a5c..da1d05d012 100644 --- a/code/datums/components/embedded.dm +++ b/code/datums/components/embedded.dm @@ -53,8 +53,6 @@ var/harmful var/mutable_appearance/overlay - var/damage = weapon.throwforce - /datum/component/embedded/Initialize(obj/item/I, datum/thrownthing/throwingdatum, obj/item/bodypart/part, @@ -142,39 +140,35 @@ weapon.forceMove(victim) RegisterSignal(weapon, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING), .proc/byeItemCarbon) + var/damage = weapon.throwforce if(harmful) victim.visible_message("[weapon] embeds itself in [victim]'s [limb.name]!",ignored_mobs=victim) to_chat(victim, "[weapon] embeds itself in your [limb.name]!") victim.throw_alert("embeddedobject", /obj/screen/alert/embeddedobject) playsound(victim,'sound/weapons/bladeslice.ogg', 40) weapon.add_mob_blood(victim)//it embedded itself in you, of course it's bloody! - var/damage += weapon.w_class * impact_pain_mult + damage += weapon.w_class * impact_pain_mult SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded) else victim.visible_message("[weapon] sticks itself to [victim]'s [limb.name]!",ignored_mobs=victim) to_chat(victim, "[weapon] sticks itself to your [limb.name]!") if(damage > 0) - var/armor = victim.run_armor_check(limb.body_zone, "melee", "Your armor has protected your [limb.name].", "Your armor has softened a hit to your [limb.name].",I.armour_penetration) - limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, blocked=armor, sharpness = I.get_sharpness()) + var/armor = victim.run_armor_check(limb.body_zone, "melee", "Your armor has protected your [limb.name].", "Your armor has softened a hit to your [limb.name].",weapon.armour_penetration) + limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, blocked=armor, sharpness = weapon.get_sharpness()) /// Called every time a carbon with a harmful embed moves, rolling a chance for the item to cause pain. The chance is halved if the carbon is crawling or walking. /datum/component/embedded/proc/jostleCheck() var/mob/living/carbon/victim = parent - - var/pain_chance_current = jostle_chance + var/chance = jostle_chance if(victim.m_intent == MOVE_INTENT_WALK || !(victim.mobility_flags & MOBILITY_STAND)) - pain_chance_current *= 0.5 + chance *= 0.5 - if(pain_stam_pct && victim.stam_paralyzed) //if it's a less-lethal embed, give them a break if they're already stamcritted - pain_chance_current *= 0.2 - damage *= 0.5 - if(harmful && prob(pain_chance_current)) + if(harmful && prob(chance)) var/damage = weapon.w_class * jostle_pain_mult limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND) to_chat(victim, "[weapon] embedded in your [limb.name] jostles and stings!") - /// Called when then item randomly falls out of a carbon. This handles the damage and descriptors, then calls safe_remove() /datum/component/embedded/proc/fallOutCarbon() var/mob/living/carbon/victim = parent diff --git a/code/datums/components/pellet_cloud.dm b/code/datums/components/pellet_cloud.dm index 3eb6d61561..6a1028cc65 100644 --- a/code/datums/components/pellet_cloud.dm +++ b/code/datums/components/pellet_cloud.dm @@ -196,7 +196,7 @@ break ///One of our pellets hit something, record what it was and check if we're done (terminated == num_pellets) -/datum/component/pellet_cloud/proc/pellet_hit(obj/projectile/P, atom/movable/firer, atom/target, Angle, hit_zone) +/datum/component/pellet_cloud/proc/pellet_hit(obj/item/projectile/P, atom/movable/firer, atom/target, Angle, hit_zone) pellets -= P terminated++ hits++ diff --git a/code/datums/elements/embed.dm b/code/datums/elements/embed.dm index ac2ec1738e..876414330f 100644 --- a/code/datums/elements/embed.dm +++ b/code/datums/elements/embed.dm @@ -2,7 +2,7 @@ The presence of this element allows an item (or a projectile carrying an item) to embed itself in a human or turf when it is thrown into a target (whether by hand, gun, or explosive wave) with either at least 4 throwspeed (EMBED_THROWSPEED_THRESHOLD) or ignore_throwspeed_threshold set to TRUE. Items meant to be used as shrapnel for projectiles should have ignore_throwspeed_threshold set to true. - Whether we're dealing with a direct /obj/item (throwing a knife at someone) or an /obj/projectile with a shrapnel_type, how we handle things plays out the same, with one extra step separating them. + Whether we're dealing with a direct /obj/item (throwing a knife at someone) or an /obj/item/projectile with a shrapnel_type, how we handle things plays out the same, with one extra step separating them. Items simply make their COMSIG_MOVABLE_IMPACT or COMSIG_MOVABLE_IMPACT_ZONE check (against a closed turf or a carbon, respectively), while projectiles check on COMSIG_PROJECTILE_SELF_ON_HIT. Upon a projectile hitting a valid target, it spawns whatever type of payload it has defined, then has that try to embed itself in the target on its own. @@ -169,7 +169,7 @@ * it to call tryForceEmbed() on its own embed element (it's out of our hands here, our projectile is done), where it will run through all the checks it needs to. */ /datum/element/embed/proc/checkEmbedProjectile(obj/item/projectile/P, atom/movable/firer, atom/hit, angle, hit_zone) - if(!iscarbon(hit) && !isclosedturf(hit)) + if(!iscarbon(hit)) Detach(P) return // we don't care @@ -178,16 +178,10 @@ payload.name = P.name payload.embedding = P.embedding payload.updateEmbedding() - var/did_embed - if(iscarbon(hit)) - var/mob/living/carbon/C = hit - var/obj/item/bodypart/limb - limb = C.get_bodypart(hit_zone) - if(!limb) - limb = C.get_bodypart() - did_embed = payload.tryEmbed(limb) - else - did_embed = payload.tryEmbed(hit) + var/mob/living/carbon/C = hit + var/obj/item/bodypart/limb = C.get_bodypart(hit_zone) + if(!limb) + limb = C.get_bodypart() payload.tryEmbed(limb) Detach(P) @@ -213,5 +207,5 @@ limb = target hit_zone = limb.body_zone C = limb.owner - checkEmbed(I, C, hit_zone, forced=TRUE) + checkEmbedMob(I, C, hit_zone, forced=TRUE) return TRUE diff --git a/code/game/objects/items/latexballoon.dm b/code/game/objects/items/latexballoon.dm index ef5b7b6cba..b2f8b4bee2 100644 --- a/code/game/objects/items/latexballoon.dm +++ b/code/game/objects/items/latexballoon.dm @@ -54,5 +54,5 @@ var/obj/item/tank/T = W blow(T, user) return - if (W.get_sharpness() || W.get_temperature() || is_pointed(W)) + if (W.get_sharpness() || W.get_temperature()) burst() diff --git a/code/game/objects/items/shrapnel.dm b/code/game/objects/items/shrapnel.dm index 906c474aa8..5904cb6c0b 100644 --- a/code/game/objects/items/shrapnel.dm +++ b/code/game/objects/items/shrapnel.dm @@ -48,7 +48,7 @@ ricochets_max = 6 ricochet_chance = 130 ricochet_incidence_leeway = 0 - ricochet_delay_chance = 0.9 + ricochet_decay_chance = 0.9 /obj/item/projectile/bullet/pellet/stingball name = "stingball pellet" diff --git a/code/modules/admin/verbs/randomverbs.dm b/code/modules/admin/verbs/randomverbs.dm index 69f02c58c5..ed8f2e8f93 100644 --- a/code/modules/admin/verbs/randomverbs.dm +++ b/code/modules/admin/verbs/randomverbs.dm @@ -1458,8 +1458,8 @@ GLOBAL_LIST_EMPTY(custom_outfits) //Admin created outfits /proc/firing_squad(mob/living/carbon/target, turf/source_turf, body_zone, wound_bonus, damage) if(!target.get_bodypart(body_zone)) return - playsound(target, 'sound/weapons/gun/revolver/shot.ogg', 100) - var/obj/projectile/bullet/smite/divine_wrath = new(source_turf) + playsound(target, 'sound/weapons/shot.ogg', 100) + var/obj/item/projectile/bullet/smite/divine_wrath = new(source_turf) divine_wrath.damage = damage divine_wrath.wound_bonus = wound_bonus divine_wrath.original = target diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index bc88a048ea..c69383924a 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -140,8 +140,8 @@ "You're hit by [I]!") if(!I.throwforce) return - var/armor = run_armor_check(zone, "melee", "Your armor has protected your [parse_zone(zone)].", "Your armor has softened hit to your [parse_zone(zone)].",I.armour_penetration) - apply_damage(I.throwforce, dtype, zone, armor, sharpness=I.get_sharpness(), wound_bonus=(nosell_hit * CANT_WOUND)) + var/armor = run_armor_check(impacting_zone, "melee", "Your armor has protected your [parse_zone(impacting_zone)].", "Your armor has softened hit to your [parse_zone(impacting_zone)].",I.armour_penetration) + apply_damage(I.throwforce, dtype, impacting_zone, armor, sharpness=I.get_sharpness(), wound_bonus=(nosell_hit * CANT_WOUND)) else return 1 else diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index cb9a758e3f..dbc4a4fedc 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -162,9 +162,6 @@ /// For telling whether we want to roll for bone breaking or lacerations if we're bothering with wounds sharpness = SHARP_NONE - ///If we have a shrapnel_type defined, these embedding stats will be passed to the spawned shrapnel type, which will roll for embedding on the target - var/list/embedding - /obj/item/projectile/Initialize() . = ..() permutated = list() @@ -829,26 +826,6 @@ /obj/item/projectile/experience_pressure_difference() return -///Like [/obj/item/proc/updateEmbedding] but for projectiles instead, call this when you want to add embedding or update the stats on the embedding element -/obj/projectile/proc/updateEmbedding() - if(!shrapnel_type || !LAZYLEN(embedding)) - return - - AddElement(/datum/element/embed,\ - embed_chance = (!isnull(embedding["embed_chance"]) ? embedding["embed_chance"] : EMBED_CHANCE),\ - fall_chance = (!isnull(embedding["fall_chance"]) ? embedding["fall_chance"] : EMBEDDED_ITEM_FALLOUT),\ - pain_chance = (!isnull(embedding["pain_chance"]) ? embedding["pain_chance"] : EMBEDDED_PAIN_CHANCE),\ - pain_mult = (!isnull(embedding["pain_mult"]) ? embedding["pain_mult"] : EMBEDDED_PAIN_MULTIPLIER),\ - remove_pain_mult = (!isnull(embedding["remove_pain_mult"]) ? embedding["remove_pain_mult"] : EMBEDDED_UNSAFE_REMOVAL_PAIN_MULTIPLIER),\ - rip_time = (!isnull(embedding["rip_time"]) ? embedding["rip_time"] : EMBEDDED_UNSAFE_REMOVAL_TIME),\ - ignore_throwspeed_threshold = (!isnull(embedding["ignore_throwspeed_threshold"]) ? embedding["ignore_throwspeed_threshold"] : FALSE),\ - impact_pain_mult = (!isnull(embedding["impact_pain_mult"]) ? embedding["impact_pain_mult"] : EMBEDDED_IMPACT_PAIN_MULTIPLIER),\ - jostle_chance = (!isnull(embedding["jostle_chance"]) ? embedding["jostle_chance"] : EMBEDDED_JOSTLE_CHANCE),\ - jostle_pain_mult = (!isnull(embedding["jostle_pain_mult"]) ? embedding["jostle_pain_mult"] : EMBEDDED_JOSTLE_PAIN_MULTIPLIER),\ - pain_stam_pct = (!isnull(embedding["pain_stam_pct"]) ? embedding["pain_stam_pct"] : EMBEDDED_PAIN_STAM_PCT),\ - projectile_payload = shrapnel_type) - return TRUE - /////// MISC HELPERS //////// /// Is this atom reflectable with ""standardized"" reflection methods like you know eshields and deswords and similar /proc/is_energy_reflectable_projectile(atom/A) diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 9fb7e83577..b408957aa7 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -14,6 +14,6 @@ wound_falloff_tile = -5 embed_falloff_tile = -5 -/obj/projectile/bullet/smite +/obj/item/projectile/bullet/smite name = "divine retribution" damage = 10 diff --git a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm index 60f86283c0..8bb34c0a82 100644 --- a/code/modules/reagents/chemistry/reagents/medicine_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/medicine_reagents.dm @@ -472,7 +472,7 @@ else if(method in list(PATCH, TOUCH)) M.adjustBruteLoss(-1 * reac_volume) M.adjustFireLoss(-1 * reac_volume) - for(var/i in carbies.all_wounds) + for(var/i in C.all_wounds) var/datum/wound/iter_wound = i iter_wound.on_synthflesh(reac_volume) if(show_message) @@ -1601,8 +1601,7 @@ reagent_state = LIQUID color = "#bb2424" metabolization_rate = 0.25 * REAGENTS_METABOLISM - -overdose_threshold = 20 + overdose_threshold = 20 /// How much base clotting we do per bleeding wound, multiplied by the below number for each bleeding wound var/clot_rate = 0.25 /// If we have multiple bleeding wounds, we count the number of bleeding wounds, then multiply the clot rate by this^(n) before applying it to each cut, so more cuts = less clotting per cut (though still more total clotting) diff --git a/code/modules/reagents/reagent_containers/hypospray.dm b/code/modules/reagents/reagent_containers/hypospray.dm index f37210ad1c..9bce478e04 100644 --- a/code/modules/reagents/reagent_containers/hypospray.dm +++ b/code/modules/reagents/reagent_containers/hypospray.dm @@ -140,6 +140,13 @@ amount_per_transfer_from_this = 15 list_reagents = list(/datum/reagent/medicine/epinephrine = 12, /datum/reagent/medicine/coagulant = 2.5, /datum/reagent/medicine/spaceacillin = 0.5) +/obj/item/reagent_containers/hypospray/medipen/blood_loss + name = "hypovolemic-response autoinjector" + desc = "A medipen designed to stabilize and rapidly reverse severe bloodloss." + volume = 15 + amount_per_transfer_from_this = 15 + list_reagents = list(/datum/reagent/medicine/epinephrine = 5, /datum/reagent/medicine/coagulant = 2.5, /datum/reagent/iron = 3.5, /datum/reagent/medicine/salglu_solution = 4) + /obj/item/reagent_containers/hypospray/medipen/stimulants name = "illegal stimpack medipen" desc = "A highly illegal medipen due to its load and small injections, allow for five uses before being drained" diff --git a/sound/weapons/shot.ogg b/sound/weapons/shot.ogg new file mode 100644 index 0000000000000000000000000000000000000000..6c574829732ec15055ee0337c409269373e0bd3c GIT binary patch literal 10751 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 literal 0 HcmV?d00001 diff --git a/tgstation.dme b/tgstation.dme index 59fe18bdff..7188cce401 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -353,6 +353,7 @@ #include "code\datums\ai_laws.dm" #include "code\datums\armor.dm" #include "code\datums\beam.dm" +#include "code\datums\beepsky_fashion.dm" #include "code\datums\browser.dm" #include "code\datums\callback.dm" #include "code\datums\chatmessage.dm" From 2a3f45f7afc749816dfa7924bdb4b5208bbd9af4 Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sat, 25 Jul 2020 01:10:12 +0100 Subject: [PATCH 08/91] fixes --- code/datums/components/embedded.dm | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm index da1d05d012..1f2d4baf99 100644 --- a/code/datums/components/embedded.dm +++ b/code/datums/components/embedded.dm @@ -139,15 +139,14 @@ limb.embedded_objects |= weapon // on the inside... on the inside... weapon.forceMove(victim) RegisterSignal(weapon, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING), .proc/byeItemCarbon) - - var/damage = weapon.throwforce + var/damage = 0 if(harmful) victim.visible_message("[weapon] embeds itself in [victim]'s [limb.name]!",ignored_mobs=victim) to_chat(victim, "[weapon] embeds itself in your [limb.name]!") victim.throw_alert("embeddedobject", /obj/screen/alert/embeddedobject) playsound(victim,'sound/weapons/bladeslice.ogg', 40) weapon.add_mob_blood(victim)//it embedded itself in you, of course it's bloody! - damage += weapon.w_class * impact_pain_mult + damage = weapon.w_class * impact_pain_mult SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded) else victim.visible_message("[weapon] sticks itself to [victim]'s [limb.name]!",ignored_mobs=victim) @@ -160,15 +159,20 @@ /// Called every time a carbon with a harmful embed moves, rolling a chance for the item to cause pain. The chance is halved if the carbon is crawling or walking. /datum/component/embedded/proc/jostleCheck() var/mob/living/carbon/victim = parent - var/chance = jostle_chance - if(victim.m_intent == MOVE_INTENT_WALK || !(victim.mobility_flags & MOBILITY_STAND)) - chance *= 0.5 - if(harmful && prob(chance)) - var/damage = weapon.w_class * jostle_pain_mult + var/damage = weapon.w_class * pain_mult + var/pain_chance_current = jostle_chance + if(victim.m_intent == MOVE_INTENT_WALK || !(victim.mobility_flags & MOBILITY_STAND)) + pain_chance_current *= 0.5 + + if(pain_stam_pct && IS_STAMCRIT(victim)) //if it's a less-lethal embed, give them a break if they're already stamcritted + pain_chance_current *= 0.2 + damage *= 0.5 + if(harmful && prob(pain_chance_current)) limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND) to_chat(victim, "[weapon] embedded in your [limb.name] jostles and stings!") + /// Called when then item randomly falls out of a carbon. This handles the damage and descriptors, then calls safe_remove() /datum/component/embedded/proc/fallOutCarbon() var/mob/living/carbon/victim = parent From 697301ad5349350e9338f6bca4caa2e82f7978b3 Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sat, 25 Jul 2020 01:26:54 +0100 Subject: [PATCH 09/91] error fixies? --- html/changelogs/.all_changelog.yml | 146 +++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) diff --git a/html/changelogs/.all_changelog.yml b/html/changelogs/.all_changelog.yml index 662e458972..ff088383d2 100644 --- a/html/changelogs/.all_changelog.yml +++ b/html/changelogs/.all_changelog.yml @@ -26372,3 +26372,149 @@ DO NOT EDIT THIS FILE BY HAND! AUTOMATICALLY GENERATED BY ss13_genchangelog.py. - bugfix: small error with pet carrier logic fixed and also making sure simple mobs are catered for properly inside bluespace jars - bugfix: fixes coin related issue +2020-07-17: + ShizCalev, Fikou: + - bugfix: Added some sanity checking for varedit values. + - bugfix: Fixed an exploit involving coins and mints that could crash the server. + - bugfix: Fixed an exploit that would allow you to destroy round-critical / indestructible + items with folders. + - bugfix: Swarmers can no longer cut power lines by deconstructing catwalks underneath + them. + - bugfix: Fixed a scenario that allowed infinite resource generation via ore machines. + - bugfix: you can no longer inject html in ahelps + - admin: you cant either, jannies + timothyteakettle: + - bugfix: fixes a small pickle related issue + - rscadd: recent culinary and scientific advancements have brought forth new pickle + related technologies +2020-07-19: + Arturlang: + - rscadd: TGUI 3.0 and enables all the UIs, plus the smart asset cache, and all + the things required for them + EmeraldSundisk: + - rscadd: Adds a pool to Delta Station + - rscadd: Adds light fixtures to specified areas + - tweak: Relocates objects in impacted areas of Delta's starboard maintenance + MrJWhit: + - rscadd: Adds a small light next to the kitchen counter + Putnam3145: + - bugfix: Pen uplinks no longer broken + TheObserver-sys: + - rscadd: 'Adds a new reaction: Slime Extractification. Take 30u Slime Jelly, 5u + Frost Oil, and 5u plasma to generate a fresh grey slime extract.' + Yakumo Chen: + - tweak: Hierophant club now checks for friendly fire by default. + b1tt3r1n0: + - rscadd: Added the updated circle game + silicons: + - rscadd: Unarmed parry is now a thing. + timothyteakettle: + - rscadd: plushies in the loadout have been replaced with a box that lets you choose + one instead + - bugfix: wrestling should no longer have the ability to permanently rotate people + - rscadd: you can now select to wear a snail shell as your backpack in the customization + menu + zeroisthebiggay: + - tweak: martial arts twenty minpop + - bugfix: records +2020-07-20: + lolman360: + - tweak: Service borgs now have synthesizers instead of a violin and guitar. + - bugfix: borg RSF +2020-07-21: + Arturlang: + - bugfix: Decal painter ui now works, yay? + CameronWoof: + - rscadd: Adds aloe, a new growable plant + - rscadd: Adds medicated sutures and advanced regenerative meshes + - bugfix: Polypyrylium oligomers and liquid electricity now correctly populate + Chiirno: + - rscadd: Alt-click pill bottles places top-most pill into active hand. + - tweak: Moved dice bags from pill_bottle/dice to box/dice to avoid dice bags being + affected from medical specific pill bottle changes. + DeltaFire15: + - bugfix: Swarmers can once again eat items as long as there's nothing living in + them. + Funce: + - bugfix: Genetics spiderwebs are no longer impassable walls + Kraseo: + - balance: Damp rags no longer instantly apply their chemicals onto someone. + SiliconMain: + - tweak: Geigers can no longer be contaminated + TheSpaghetti: + - rscadd: new snowflake trait + kappa-sama: + - balance: advanced surgery duffel bag no longer comes with a nukie medkit. it costs + 4 less telecrystals to make up for this colossal nerf. + - tweak: quartered the weight of the stray cargo pod event from 2x normal to 1/2 + normal + silicons: + - tweak: survivalists (from summon guns/magic) are proper objective'd pseudoantagonists + again + - tweak: summon guns/magic can only be used once each + - tweak: summon guns/magic now only cost one point each + - imageadd: ':dsmile: :dfrown: :dhsmile: :dpog: :dneutral:' + - bugfix: gravity should update for mobs a fair bit faster + - rscadd: voting can now be done from the stat panel if the system is plurality + and approval + timothyteakettle: + - rscadd: new fried component used for frying objects + - bugfix: various frying bugs fixed such as being able to unfry items and frying + turfs with cold cooking oil +2020-07-22: + Ludox: + - rscdel: You can no longer be brainwashed into giving birth to a fake baby + kappa-sama: + - balance: brainwashing disk has lost its cost buffs (3->5) and is role restricted + once more (medical doctor/roboticist) +2020-07-23: + DeltaFire15: + - bugfix: Traits are no longer fucked + Putnam3145: + - tweak: Slight optimization in chat code. + kappa-sama: + - bugfix: tendril chests being empty + zeroisthebiggay: + - rscadd: fetish content +2020-07-24: + EmeraldSundisk: + - rscadd: Adds a CMO office, along with Virology and Genetics labs to Omega Station + - rscadd: Adds a second chemistry station to the chemistry lab + - tweak: Adjusts the locations of some objects in medical to accommodate these new + additions + - tweak: Relocates the morgue + - tweak: Relocates items in impacted areas of maintenance as well as the library + - bugfix: Fixes an air line Bartholomew somehow knocked out + Linzolle: + - bugfix: wounds now have a description on examine + Owai-Seek: + - rscadd: Meatball Sub, Meatloaf + Meatloaf Slices, Bear Chili, Mashed Potatoes + - rscadd: Buttered Potatoes, Fancy Cracker Pack, Spiral Soup, Sweet and Sour Chicken + - tweak: Organised the Food DMI a bit. + - tweak: Deleted some stray pixels on some sprites. + - tweak: Nuggie boxes are now centered correctly. + - imageadd: Icons for the the food items in this PR. + Sneakyrat6: + - bugfix: Fixes dressers not giving you undies + - bugfix: Fixes Snaxi not loading properly because of typos + - rscadd: You can now burn photos + Zandario: + - spellcheck: Murdered **tipes** and gave birth to **is**. + silicons: + - tweak: sanitization now doesn't cut off 15.7 or something million possible colors + from character preferences (instead of only allowing 16 values for R G and B, + it now allows 256 each) + - balance: projectiles are by default 17.5 tiles per second instead of 12.5 + timothyteakettle: + - rscadd: due to recent innovative research in the medical field, you now have bones + - tweak: zombie claws are now sharp and do less damage, but can destroy non-lifeforms + far faster + - tweak: zombies now take less stamina damage + - rscadd: beepsky can now wear hats + zeroisthebiggay: + - imageadd: rad and kravglove sprites +2020-07-25: + CameronWoof: + - bugfix: Aloe now has an icon. + timothyteakettle: + - bugfix: beepsky replaces the word THREAT_LEVEL with the actual threat level \ No newline at end of file From b708be60e9729d7e3e30729b2551d1a113cee8ff Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sat, 25 Jul 2020 02:12:21 +0100 Subject: [PATCH 10/91] hey look ma i removed a space --- code/datums/components/embedded.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/datums/components/embedded.dm b/code/datums/components/embedded.dm index 1f2d4baf99..51098756d3 100644 --- a/code/datums/components/embedded.dm +++ b/code/datums/components/embedded.dm @@ -29,7 +29,6 @@ */ - /datum/component/embedded dupe_mode = COMPONENT_DUPE_ALLOWED var/obj/item/bodypart/limb From e18bfb41b7d88a789779067362983d3770738dc9 Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sat, 25 Jul 2020 02:16:39 +0100 Subject: [PATCH 11/91] woopsy --- code/modules/mob/living/bloodcrawl.dm | 4 ++-- code/modules/mob/living/carbon/human/examine.dm | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm index 42d4a78433..24d456bf8f 100644 --- a/code/modules/mob/living/bloodcrawl.dm +++ b/code/modules/mob/living/bloodcrawl.dm @@ -73,7 +73,7 @@ if(victim.stat == CONSCIOUS) src.visible_message("[victim] kicks free of the blood pool just before entering it!", null, "You hear splashing and struggling.") - else if(victim.reagents?.has_reagent(/datum/reagent/consumable/ethanol/demonsblood, needs_metabolizing = TRUE)) + else if(victim.reagents?.has_reagent(/datum/reagent/consumable/ethanol/demonsblood)) visible_message("Something prevents [victim] from entering the pool!", "A strange force is blocking [victim] from entering!", "You hear a splash and a thud.") else victim.forceMove(src) @@ -104,7 +104,7 @@ if(!victim) return FALSE - if(victim.reagents?.has_reagent(/datum/reagent/consumable/ethanol/devilskiss, needs_metabolizing = TRUE)) + if(victim.reagents?.has_reagent(/datum/reagent/consumable/ethanol/devilskiss)) to_chat(src, "AAH! THEIR FLESH! IT BURNS!") adjustBruteLoss(25) //I can't use adjustHealth() here because bloodcrawl affects /mob/living and adjustHealth() only affects simple mobs var/found_bloodpool = FALSE diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm index 1fbc098e42..10192f9d21 100644 --- a/code/modules/mob/living/carbon/human/examine.dm +++ b/code/modules/mob/living/carbon/human/examine.dm @@ -290,7 +290,7 @@ if(appears_dead) bleed_text += ", but it has pooled and is not flowing.\n" else - if(reagents.has_reagent(/datum/reagent/toxin/heparin, needs_metabolizing = TRUE)) + if(reagents.has_reagent(/datum/reagent/toxin/heparin)) bleed_text += " incredibly quickly" bleed_text += "!\n" From 4f7ea622d69f1c2636a1760e2e5dcddc612db8b4 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sat, 25 Jul 2020 18:15:05 +0100 Subject: [PATCH 12/91] hey this is important --- tgstation.dme | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tgstation.dme b/tgstation.dme index 2a7156f043..7a4d75e87b 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -659,7 +659,9 @@ #include "code\datums\wounds\_wounds.dm" #include "code\datums\wounds\bones.dm" #include "code\datums\wounds\burns.dm" -#include "code\datums\wounds\cuts.dm" +#include "code\datums\wounds\loss.dm" +#include "code\datums\wounds\pierce.dm" +#include "code\datums\wounds\slash.dm" #include "code\game\alternate_appearance.dm" #include "code\game\atoms.dm" #include "code\game\atoms_movable.dm" From 3a894f79d040bf7d7d8b5635494a710ad73d704b Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sat, 25 Jul 2020 19:56:46 +0100 Subject: [PATCH 13/91] less rng reliant this is way better --- code/modules/surgery/bodyparts/_bodyparts.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index c79f50c03c..0adadf1bf8 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -355,7 +355,7 @@ else damage = min(damage, WOUND_MAX_CONSIDERED_DAMAGE) - var/base_roll = rand(1, round(damage ** WOUND_DAMAGE_EXPONENT)) + var/base_roll = rand(max(damage/2.5,15), round(damage ** 1.3)) var/injury_roll = base_roll injury_roll += check_woundings_mods(woundtype, damage, wound_bonus, bare_wound_bonus) var/list/wounds_checking = GLOB.global_wound_types[woundtype] From 8b2a92994fd714b84e4fd884ebc990f3f5e70d40 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sat, 25 Jul 2020 20:14:41 +0100 Subject: [PATCH 14/91] less rng reliance --- code/__DEFINES/wounds.dm | 2 +- code/datums/wounds/bones.dm | 6 +++--- code/datums/wounds/burns.dm | 12 ++++++------ code/datums/wounds/pierce.dm | 6 +++--- code/datums/wounds/slash.dm | 6 +++--- code/modules/surgery/bodyparts/_bodyparts.dm | 2 +- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/code/__DEFINES/wounds.dm b/code/__DEFINES/wounds.dm index c87e2f8bbd..69ed45a817 100644 --- a/code/__DEFINES/wounds.dm +++ b/code/__DEFINES/wounds.dm @@ -1,5 +1,5 @@ -#define WOUND_DAMAGE_EXPONENT 1.4 +#define WOUND_DAMAGE_EXPONENT 1.3 /// an attack must do this much damage after armor in order to roll for being a wound (incremental pressure damage need not apply) #define WOUND_MINIMUM_DAMAGE 5 diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index 41e4e025ab..3335356b7e 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -194,7 +194,7 @@ 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_minimum = 45 threshold_penalty = 15 treatable_tool = TOOL_BONESET wound_flags = (BONE_WOUND) @@ -295,7 +295,7 @@ severity = WOUND_SEVERITY_SEVERE interaction_efficiency_penalty = 2 limp_slowdown = 6 - threshold_minimum = 60 + threshold_minimum = 70 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 @@ -316,7 +316,7 @@ interaction_efficiency_penalty = 4 limp_slowdown = 9 sound_effect = 'sound/effects/wounds/crack2.ogg' - threshold_minimum = 115 + threshold_minimum = 125 threshold_penalty = 50 disabling = TRUE treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/bone_gel) diff --git a/code/datums/wounds/burns.dm b/code/datums/wounds/burns.dm index 0d66ee4cfb..f3e22807cf 100644 --- a/code/datums/wounds/burns.dm +++ b/code/datums/wounds/burns.dm @@ -255,8 +255,8 @@ 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 + damage_mulitplier_penalty = 1.05 + threshold_minimum = 50 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 @@ -269,8 +269,8 @@ 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 + damage_mulitplier_penalty = 1.1 + threshold_minimum = 90 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) @@ -285,9 +285,9 @@ 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 + damage_mulitplier_penalty = 1.15 sound_effect = 'sound/effects/wounds/sizzle2.ogg' - threshold_minimum = 140 + threshold_minimum = 150 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) diff --git a/code/datums/wounds/pierce.dm b/code/datums/wounds/pierce.dm index 3182c334bf..56c60b31d7 100644 --- a/code/datums/wounds/pierce.dm +++ b/code/datums/wounds/pierce.dm @@ -129,7 +129,7 @@ gauzed_clot_rate = 0.8 internal_bleeding_chance = 30 internal_bleeding_coefficient = 1.25 - threshold_minimum = 30 + threshold_minimum = 40 threshold_penalty = 15 status_effect_type = /datum/status_effect/wound/pierce/moderate scar_keyword = "piercemoderate" @@ -146,7 +146,7 @@ gauzed_clot_rate = 0.6 internal_bleeding_chance = 60 internal_bleeding_coefficient = 1.5 - threshold_minimum = 50 + threshold_minimum = 60 threshold_penalty = 25 status_effect_type = /datum/status_effect/wound/pierce/severe scar_keyword = "piercesevere" @@ -163,7 +163,7 @@ gauzed_clot_rate = 0.4 internal_bleeding_chance = 80 internal_bleeding_coefficient = 1.75 - threshold_minimum = 100 + threshold_minimum = 110 threshold_penalty = 40 status_effect_type = /datum/status_effect/wound/pierce/critical scar_keyword = "piercecritical" diff --git a/code/datums/wounds/slash.dm b/code/datums/wounds/slash.dm index 41a6a1ae14..32b16c2daf 100644 --- a/code/datums/wounds/slash.dm +++ b/code/datums/wounds/slash.dm @@ -252,7 +252,7 @@ minimum_flow = 0.5 max_per_type = 3 clot_rate = 0.12 - threshold_minimum = 20 + threshold_minimum = 30 threshold_penalty = 10 status_effect_type = /datum/status_effect/wound/slash/moderate scar_keyword = "slashmoderate" @@ -269,7 +269,7 @@ minimum_flow = 2.75 clot_rate = 0.07 max_per_type = 4 - threshold_minimum = 50 + threshold_minimum = 60 threshold_penalty = 25 demotes_to = /datum/wound/slash/moderate status_effect_type = /datum/status_effect/wound/slash/severe @@ -287,7 +287,7 @@ minimum_flow = 4 clot_rate = -0.05 // critical cuts actively get worse instead of better max_per_type = 5 - threshold_minimum = 80 + threshold_minimum = 90 threshold_penalty = 40 demotes_to = /datum/wound/slash/severe status_effect_type = /datum/status_effect/wound/slash/critical diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index 0adadf1bf8..f30d49c4c0 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -355,7 +355,7 @@ else damage = min(damage, WOUND_MAX_CONSIDERED_DAMAGE) - var/base_roll = rand(max(damage/2.5,15), round(damage ** 1.3)) + var/base_roll = rand(max(damage/1.5,25), round(damage ** WOUND_THRESHOLD_MINIMUM)) var/injury_roll = base_roll injury_roll += check_woundings_mods(woundtype, damage, wound_bonus, bare_wound_bonus) var/list/wounds_checking = GLOB.global_wound_types[woundtype] From c1932be528402bc3d6dfc747487728d2ab6b989d Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sat, 25 Jul 2020 21:53:11 +0100 Subject: [PATCH 15/91] last second edit woops --- code/modules/surgery/bodyparts/_bodyparts.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/surgery/bodyparts/_bodyparts.dm b/code/modules/surgery/bodyparts/_bodyparts.dm index f30d49c4c0..3d88282937 100644 --- a/code/modules/surgery/bodyparts/_bodyparts.dm +++ b/code/modules/surgery/bodyparts/_bodyparts.dm @@ -355,7 +355,7 @@ else damage = min(damage, WOUND_MAX_CONSIDERED_DAMAGE) - var/base_roll = rand(max(damage/1.5,25), round(damage ** WOUND_THRESHOLD_MINIMUM)) + var/base_roll = rand(max(damage/1.5,25), round(damage ** WOUND_DAMAGE_EXPONENT)) var/injury_roll = base_roll injury_roll += check_woundings_mods(woundtype, damage, wound_bonus, bare_wound_bonus) var/list/wounds_checking = GLOB.global_wound_types[woundtype] From 75c40f6d930e17943e540aea326b4c464e7a0627 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 26 Jul 2020 18:51:19 +0100 Subject: [PATCH 16/91] what if wound values didnt suck --- code/game/objects/items/storage/toolbox.dm | 3 +- code/game/objects/items/tools/crowbar.dm | 3 ++ code/game/objects/items/tools/screwdriver.dm | 3 ++ code/game/objects/items/tools/weldingtool.dm | 4 +- code/game/objects/items/tools/wrench.dm | 3 ++ code/game/objects/items/weaponry.dm | 2 + .../clothing/spacesuits/_spacesuits.dm | 4 +- .../modules/clothing/spacesuits/chronosuit.dm | 4 +- code/modules/clothing/spacesuits/hardsuit.dm | 14 +++--- .../clothing/spacesuits/miscellaneous.dm | 48 +++++++++---------- code/modules/clothing/spacesuits/plasmamen.dm | 12 ++--- code/modules/clothing/spacesuits/syndi.dm | 4 +- .../under/jobs/Plasmaman/civilian_service.dm | 2 +- .../under/jobs/Plasmaman/engineering.dm | 2 +- .../clothing/under/jobs/Plasmaman/medsci.dm | 2 +- .../clothing/under/jobs/Plasmaman/security.dm | 2 +- .../clothing/under/jobs/civilian/civilian.dm | 2 +- .../clothing/under/jobs/engineering.dm | 4 +- code/modules/clothing/under/jobs/medical.dm | 14 +++--- code/modules/clothing/under/jobs/rnd.dm | 8 ++-- code/modules/clothing/under/miscellaneous.dm | 2 +- code/modules/clothing/under/syndicate.dm | 20 ++++---- 22 files changed, 87 insertions(+), 75 deletions(-) diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm index 5e3ff67f4c..ed0ee8ad07 100644 --- a/code/game/objects/items/storage/toolbox.dm +++ b/code/game/objects/items/storage/toolbox.dm @@ -20,7 +20,8 @@ GLOBAL_LIST_EMPTY(rubber_toolbox_icons) var/has_latches = TRUE var/can_rubberify = TRUE rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE //very protecc too - wound_bonus = 5 + wound_bonus = -10 + bare_wound_bonus = 5 /obj/item/storage/toolbox/greyscale icon_state = "toolbox_default" diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm index 91e8c49e5a..569e86747e 100644 --- a/code/game/objects/items/tools/crowbar.dm +++ b/code/game/objects/items/tools/crowbar.dm @@ -18,6 +18,9 @@ toolspeed = 1 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) + wound_bonus = -10 + bare_wound_bonus = 5 + /obj/item/crowbar/suicide_act(mob/user) user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm index e9f517a9f1..86c223606d 100644 --- a/code/game/objects/items/tools/screwdriver.dm +++ b/code/game/objects/items/tools/screwdriver.dm @@ -31,6 +31,9 @@ "yellow" = rgb(255, 165, 0) ) + wound_bonus = -10 + bare_wound_bonus = 5 + /obj/item/screwdriver/suicide_act(mob/user) user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!") return(BRUTELOSS) diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index 1f2a65321d..2e12a2ab8c 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -33,8 +33,8 @@ heat = 3800 tool_behaviour = TOOL_WELDER toolspeed = 1 - wound_bonus = 10 - bare_wound_bonus = 15 + wound_bonus = 0 + bare_wound_bonus = 5 /obj/item/weldingtool/Initialize() . = ..() diff --git a/code/game/objects/items/tools/wrench.dm b/code/game/objects/items/tools/wrench.dm index 678096db28..e1c09f394e 100644 --- a/code/game/objects/items/tools/wrench.dm +++ b/code/game/objects/items/tools/wrench.dm @@ -18,6 +18,9 @@ toolspeed = 1 armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 30) + wound_bonus = -10 + bare_wound_bonus = 5 + /obj/item/wrench/suicide_act(mob/user) user.visible_message("[user] is beating [user.p_them()]self to death with [src]! It looks like [user.p_theyre()] trying to commit suicide!") playsound(loc, 'sound/weapons/genhit.ogg', 50, 1, -1) diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index 0f6be3cf60..cc9a8747fa 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -260,6 +260,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 w_class = WEIGHT_CLASS_NORMAL custom_materials = list(/datum/material/iron=1150, /datum/material/glass=75) attack_verb = list("hit", "bludgeoned", "whacked", "bonked") + wound_bonus = -10 /obj/item/wirerod/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/shard)) @@ -591,6 +592,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 obj_flags = UNIQUE_RENAME var/chaplain_spawnable = TRUE total_mass = TOTAL_MASS_MEDIEVAL_WEAPON + wound_bonus = -5 /obj/item/melee/baseball_bat/chaplain/Initialize() . = ..() diff --git a/code/modules/clothing/spacesuits/_spacesuits.dm b/code/modules/clothing/spacesuits/_spacesuits.dm index 82dd3142ed..cba27845f1 100644 --- a/code/modules/clothing/spacesuits/_spacesuits.dm +++ b/code/modules/clothing/spacesuits/_spacesuits.dm @@ -7,7 +7,7 @@ clothing_flags = STOPSPRESSUREDAMAGE | THICKMATERIAL | BLOCK_GAS_SMOKE_EFFECT | ALLOWINTERNALS item_state = "spaceold" permeability_coefficient = 0.01 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70, "wound" = 5) flags_inv = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDEFACIALHAIR|HIDESNOUT dynamic_hair_suffix = "" dynamic_fhair_suffix = "" @@ -36,7 +36,7 @@ body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS allowed = list(/obj/item/flashlight, /obj/item/tank/internals) slowdown = 1 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 50, "fire" = 80, "acid" = 70, "wound" = 5) flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT|HIDETAUR cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT diff --git a/code/modules/clothing/spacesuits/chronosuit.dm b/code/modules/clothing/spacesuits/chronosuit.dm index 4590d46219..de1c7fe903 100644 --- a/code/modules/clothing/spacesuits/chronosuit.dm +++ b/code/modules/clothing/spacesuits/chronosuit.dm @@ -4,7 +4,7 @@ icon_state = "chronohelmet" item_state = "chronohelmet" slowdown = 1 - armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 60, "bomb" = 30, "bio" = 90, "rad" = 90, "fire" = 100, "acid" = 100) + armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 60, "bomb" = 30, "bio" = 90, "rad" = 90, "fire" = 100, "acid" = 100, "wound" = 80) resistance_flags = FIRE_PROOF | ACID_PROOF var/obj/item/clothing/suit/space/chronos/suit = null @@ -19,7 +19,7 @@ icon_state = "chronosuit" item_state = "chronosuit" actions_types = list(/datum/action/item_action/toggle) - armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 60, "bomb" = 30, "bio" = 90, "rad" = 90, "fire" = 100, "acid" = 1000) + armor = list("melee" = 60, "bullet" = 60, "laser" = 60, "energy" = 60, "bomb" = 30, "bio" = 90, "rad" = 90, "fire" = 100, "acid" = 1000, "wound" = 80) resistance_flags = FIRE_PROOF | ACID_PROOF mutantrace_variation = STYLE_DIGITIGRADE var/list/chronosafe_items = list(/obj/item/chrono_eraser, /obj/item/gun/energy/chrono_gun) diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm index f563c1029d..0d1f1139f5 100644 --- a/code/modules/clothing/spacesuits/hardsuit.dm +++ b/code/modules/clothing/spacesuits/hardsuit.dm @@ -5,7 +5,7 @@ icon_state = "hardsuit0-engineering" item_state = "eng_helm" max_integrity = 300 - armor = list("melee" = 10, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 50, "acid" = 75) + armor = list("melee" = 10, "bullet" = 5, "laser" = 10, "energy" = 5, "bomb" = 10, "bio" = 100, "rad" = 75, "fire" = 50, "acid" = 75, "wound" = 10) var/basestate = "hardsuit" var/brightness_on = 4 //luminosity when on var/on = FALSE @@ -721,7 +721,7 @@ item_state = "rig0-soviet" hardsuit_type = "soviet" icon_state = "rig0-soviet" - armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75) + armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75, "wound" = 15) mutantrace_variation = NONE /obj/item/clothing/suit/space/hardsuit/soviet @@ -730,7 +730,7 @@ item_state = "rig-soviet" icon_state = "rig-soviet" slowdown = 0.8 - armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75) + armor = list("melee" = 40, "bullet" = 30, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 75, "wound" = 15) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/soviet mutantrace_variation = NONE @@ -775,7 +775,7 @@ item_state = "ert_medical" hardsuit_type = "ert_medical" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf - armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95) + armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95, "wound" = 30) slowdown = 0 max_charges = 5 @@ -804,7 +804,7 @@ icon_state = "hardsuit0-ert_medical" item_state = "hardsuit0-ert_medical" hardsuit_type = "ert_medical" - armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95) + armor = list("melee" = 0, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 95, "acid" = 95, "wound" = 30) /obj/item/clothing/head/helmet/space/hardsuit/shielded/ctf/red icon_state = "hardsuit0-ert_security" @@ -883,7 +883,7 @@ max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | LAVA_PROOF heat_protection = HEAD - armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100) + armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100, "wound" = 30) brightness_on = 7 allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator) var/energy_color = "#35FFF0" @@ -927,7 +927,7 @@ item_state = "swat_suit" max_heat_protection_temperature = FIRE_SUIT_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | LAVA_PROOF - armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100) + armor = list(melee = 50, bullet = 10, laser = 10, energy = 10, bomb = 50, bio = 100, rad = 50, fire = 100, acid = 100, "wound" = 30) allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/storage/bag/ore, /obj/item/pickaxe) helmettype = /obj/item/clothing/head/helmet/space/hardsuit/lavaknight heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index ee70f54ed0..35dc7d0485 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -51,7 +51,7 @@ Contains: icon_state = "heavy" item_state = "swat_suit" allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/kitchen/knife/combat) - armor = list("melee" = 40, "bullet" = 30, "laser" = 30,"energy" = 30, "bomb" = 50, "bio" = 90, "rad" = 20, "fire" = 100, "acid" = 100) + armor = list("melee" = 40, "bullet" = 30, "laser" = 30,"energy" = 30, "bomb" = 50, "bio" = 90, "rad" = 20, "fire" = 100, "acid" = 100, "wound" = 25) strip_delay = 120 resistance_flags = FIRE_PROOF | ACID_PROOF mutantrace_variation = STYLE_DIGITIGRADE @@ -63,7 +63,7 @@ Contains: dynamic_hair_suffix = "+generic" dynamic_fhair_suffix = "+generic" flags_inv = 0 - armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 30) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -79,7 +79,7 @@ Contains: flags_inv = 0 w_class = WEIGHT_CLASS_NORMAL allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals) - armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 80, "bullet" = 80, "laser" = 50, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 30) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = FIRE_PROOF | ACID_PROOF @@ -140,7 +140,7 @@ Contains: desc = "A thick, space-proof tricorne from the royal Space Queen. It's lined with a layer of reflective kevlar." icon_state = "pirate" item_state = "pirate" - armor = list("melee" = 30, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 60, "acid" = 75) + armor = list("melee" = 30, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 60, "acid" = 75, "wound" = 30) flags_inv = HIDEHAIR strip_delay = 40 equip_delay_other = 20 @@ -163,7 +163,7 @@ Contains: flags_inv = 0 allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/melee/transforming/energy/sword/pirate, /obj/item/clothing/glasses/eyepatch, /obj/item/reagent_containers/food/drinks/bottle/rum) slowdown = 0 - armor = list("melee" = 30, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 60, "acid" = 75) + armor = list("melee" = 30, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 60, "acid" = 75, "wound" = 30) strip_delay = 40 equip_delay_other = 20 mutantrace_variation = STYLE_DIGITIGRADE @@ -175,7 +175,7 @@ Contains: icon_state = "hardsuit0-ert_commander" item_state = "hardsuit0-ert_commander" hardsuit_type = "ert_commander" - armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80) + armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80. "wound" = 30) strip_delay = 130 brightness_on = 7 resistance_flags = ACID_PROOF @@ -191,7 +191,7 @@ Contains: item_state = "ert_command" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals) - armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80) + armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80, "wound" = 30) slowdown = 0 strip_delay = 130 resistance_flags = ACID_PROOF @@ -244,7 +244,7 @@ Contains: icon_state = "hardsuit0-ert_commander-alert" item_state = "hardsuit0-ert_commander-alert" hardsuit_type = "ert_commander-alert" - armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 50) brightness_on = 8 resistance_flags = FIRE_PROOF | ACID_PROOF @@ -254,7 +254,7 @@ Contains: icon_state = "ert_command-alert" item_state = "ert_command-alert" helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/alert - armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 70, "bullet" = 55, "laser" = 50, "energy" = 50, "bomb" = 65, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 50) resistance_flags = FIRE_PROOF | ACID_PROOF mutantrace_variation = STYLE_DIGITIGRADE|STYLE_SNEK_TAURIC @@ -303,7 +303,7 @@ Contains: icon_state = "space" item_state = "s_suit" desc = "A lightweight space suit with the basic ability to protect the wearer from the vacuum of space during emergencies." - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 65) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 65, "wound" = 10) /obj/item/clothing/head/helmet/space/eva name = "EVA helmet" @@ -311,7 +311,7 @@ Contains: item_state = "space" desc = "A lightweight space helmet with the basic ability to protect the wearer from the vacuum of space during emergencies." flash_protect = 0 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 65) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 20, "fire" = 50, "acid" = 65, "wound" = 10) //Radiation /obj/item/clothing/head/helmet/space/rad @@ -319,7 +319,7 @@ Contains: desc = "A special helmet that protects against radiation and space. Not much else unfortunately." icon_state = "cespace_helmet" item_state = "nothing" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0, "wound" = 5) resistance_flags = FIRE_PROOF rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE actions_types = list() @@ -329,7 +329,7 @@ Contains: desc = "A special suit that protects against radiation and space. Not much else unfortunately." icon_state = "hardsuit-rad" item_state = "nothing" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 100, "fire" = 0, "acid" = 0, "wound" = 5) resistance_flags = FIRE_PROOF rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE mutantrace_variation = NONE @@ -339,7 +339,7 @@ Contains: desc = "An advanced, space-proof helmet. It appears to be modeled after an old-world eagle." icon_state = "griffinhat" item_state = "griffinhat" - armor = list("melee" = 20, "bullet" = 40, "laser" = 30, "energy" = 25, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80) + armor = list("melee" = 20, "bullet" = 40, "laser" = 30, "energy" = 25, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80, "wound" = 20) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = ACID_PROOF | FIRE_PROOF @@ -351,7 +351,7 @@ Contains: icon_state = "freedom" item_state = "freedom" allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals) - armor = list("melee" = 20, "bullet" = 40, "laser" = 30,"energy" = 25, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80) + armor = list("melee" = 20, "bullet" = 40, "laser" = 30,"energy" = 25, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80, "wound" = 20) strip_delay = 130 max_heat_protection_temperature = FIRE_IMMUNITY_MAX_TEMP_PROTECT resistance_flags = ACID_PROOF | FIRE_PROOF @@ -364,7 +364,7 @@ Contains: desc = "Spaceworthy and it looks like a space carp's head, smells like one too." icon_state = "carp_helm" item_state = "syndicate" - armor = list("melee" = -20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 75) //As whimpy as a space carp + armor = list("melee" = -20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 75, "wound" = 5) //As whimpy as a space carp brightness_on = 0 //luminosity when on actions_types = list() mutantrace_variation = NONE @@ -380,7 +380,7 @@ Contains: icon_state = "carp_suit" item_state = "space_suit_syndicate" slowdown = 0 //Space carp magic, never stop believing - armor = list("melee" = -20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 75) //As whimpy whimpy whoo + armor = list("melee" = -20, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 75, "fire" = 60, "acid" = 75, "wound" = 5) //As whimpy whimpy whoo allowed = list(/obj/item/tank/internals, /obj/item/gun/ballistic/automatic/speargun) //I'm giving you a hint here helmettype = /obj/item/clothing/head/helmet/space/hardsuit/carp mutantrace_variation = STYLE_DIGITIGRADE @@ -442,14 +442,14 @@ Contains: /obj/item/clothing/suit/space/hardsuit/ert/paranormal/inquisitor/old desc = "Powerful wards are built into this hardsuit, protecting the user from all manner of paranormal threats. Alas, this one looks pretty worn out and rusted." - armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60) + armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60, "wound" = 20) slowdown = 0.8 helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor/old charges = 12 /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor/old desc = "A helmet worn by those who deal with paranormal threats for a living. Alas, this one looks pretty worn out and rusted." - armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60) + armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60, "wound" = 20) charges = 12 /obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker @@ -467,14 +467,14 @@ Contains: /obj/item/clothing/suit/space/hardsuit/ert/paranormal/beserker/old desc = "Voices echo from the hardsuit, driving the user insane. This one is pretty battle-worn, but still fearsome." - armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60) + armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60, "wound" = 20) slowdown = 0.8 helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/beserker/old charges = 6 /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/beserker/old desc = "Peering into the eyes of the helmet is enough to seal damnation. This one is pretty battle-worn, but still fearsome." - armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60) + armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60, "wound" = 20) charges = 6 /obj/item/clothing/head/helmet/space/fragile @@ -482,7 +482,7 @@ Contains: desc = "A bulky, air-tight helmet meant to protect the user during emergency situations. It doesn't look very durable." icon_state = "syndicate-helm-orange" item_state = "syndicate-helm-orange" - armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0) + armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0, "wound" = 5) strip_delay = 65 /obj/item/clothing/suit/space/fragile @@ -492,7 +492,7 @@ Contains: icon_state = "syndicate-orange" item_state = "syndicate-orange" slowdown = 2 - armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0) + armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0), "wound" = 5 strip_delay = 65 /obj/item/clothing/suit/space/fragile/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) @@ -525,7 +525,7 @@ Contains: icon_state = "hunter" item_state = "swat_suit" allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/restraints/handcuffs, /obj/item/tank/internals, /obj/item/kitchen/knife/combat) - armor = list("melee" = 60, "bullet" = 40, "laser" = 40, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 60, "bullet" = 40, "laser" = 40, "energy" = 50, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wpound" = 25) strip_delay = 130 resistance_flags = FIRE_PROOF | ACID_PROOF diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index f17eb91b74..5128f77433 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -5,7 +5,7 @@ name = "EVA plasma envirosuit" desc = "A special plasma containment suit designed to be space-worthy, as well as worn over other clothing. Like its smaller counterpart, it can automatically extinguish the wearer in a crisis, and holds twice as many charges." allowed = list(/obj/item/gun, /obj/item/ammo_casing, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword, /obj/item/restraints/handcuffs, /obj/item/tank) - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75, "wound" = 10) resistance_flags = FIRE_PROOF icon_state = "plasmaman_suit" item_state = "plasmaman_suit" @@ -40,7 +40,7 @@ icon_state = "plasmaman-helm" item_state = "plasmaman-helm" strip_delay = 80 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75, "wound" = 10) resistance_flags = FIRE_PROOF var/brightness_on = 4 //luminosity when the light is on var/on = FALSE @@ -77,7 +77,7 @@ desc = "A plasmaman containment helmet designed for security officers, protecting them from being flashed and burning alive, along-side other undesirables." icon_state = "security_envirohelm" item_state = "security_envirohelm" - armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75, "wound" = 20) /obj/item/clothing/head/helmet/space/plasmaman/security/warden name = "warden's plasma envirosuit helmet" @@ -132,7 +132,7 @@ desc = "A sturdier plasmaman envirohelmet designed for research directors." icon_state = "rd_envirohelm" item_state = "rd_envirohelm" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 100, "rad" = 0, "fire" = 100, "acid" = 75, "wound" = 10) /obj/item/clothing/head/helmet/space/plasmaman/robotics name = "robotics plasma envirosuit helmet" @@ -145,7 +145,7 @@ desc = "A space-worthy helmet specially designed for engineer plasmamen, the usual purple stripes being replaced by engineering's orange." icon_state = "engineer_envirohelm" item_state = "engineer_envirohelm" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 10, "fire" = 100, "acid" = 75) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 10, "fire" = 100, "acid" = 75, "wound" = 10) /obj/item/clothing/head/helmet/space/plasmaman/engineering/ce name = "chief engineer's plasma envirosuit helmet" @@ -194,7 +194,7 @@ desc = "A blue and gold envirohelm designed for the station's captain, nonetheless. Made of superior materials to protect them from the station hazards and more." icon_state = "captain_envirohelm" item_state = "captain_envirohelm" - armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 10, "fire" = 100, "acid" = 85) + armor = list("melee" = 10, "bullet" = 10, "laser" = 10, "energy" = 10, "bomb" = 10, "bio" = 100, "rad" = 10, "fire" = 100, "acid" = 85, "wound" = 15) /obj/item/clothing/head/helmet/space/plasmaman/curator name = "curator's plasma envirosuit helmet" diff --git a/code/modules/clothing/spacesuits/syndi.dm b/code/modules/clothing/spacesuits/syndi.dm index 662e333f59..f55379da2f 100644 --- a/code/modules/clothing/spacesuits/syndi.dm +++ b/code/modules/clothing/spacesuits/syndi.dm @@ -4,7 +4,7 @@ icon_state = "syndicate" item_state = "syndicate" desc = "Has a tag on it: Totally not property of an enemy corporation, honest!" - armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85) + armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85, "wound" = 20) /obj/item/clothing/suit/space/syndicate name = "red space suit" @@ -13,7 +13,7 @@ desc = "Has a tag on it: Totally not property of an enemy corporation, honest!" w_class = WEIGHT_CLASS_NORMAL allowed = list(/obj/item/gun, /obj/item/ammo_box, /obj/item/ammo_casing, /obj/item/melee/baton, /obj/item/melee/transforming/energy/sword/saber, /obj/item/restraints/handcuffs, /obj/item/tank/internals) - armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85) + armor = list("melee" = 40, "bullet" = 50, "laser" = 30,"energy" = 15, "bomb" = 30, "bio" = 30, "rad" = 30, "fire" = 80, "acid" = 85, "wound" = 20) mutantrace_variation = STYLE_DIGITIGRADE //Green syndicate space suit diff --git a/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm b/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm index 5928819b16..082d783bea 100644 --- a/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm +++ b/code/modules/clothing/under/jobs/Plasmaman/civilian_service.dm @@ -57,7 +57,7 @@ desc = "An expensive piece of plasmaman envirosuit fashion. guaranteed to keep you cool while the station goes down in fierceful fires." icon_state = "captain_envirosuit" item_state = "captain_envirosuit" - armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95, "wound" = 15) sensor_mode = SENSOR_COORDS random_sensor = FALSE diff --git a/code/modules/clothing/under/jobs/Plasmaman/engineering.dm b/code/modules/clothing/under/jobs/Plasmaman/engineering.dm index 15eb189fa8..4850a605e7 100644 --- a/code/modules/clothing/under/jobs/Plasmaman/engineering.dm +++ b/code/modules/clothing/under/jobs/Plasmaman/engineering.dm @@ -3,7 +3,7 @@ desc = "An air-tight suit designed to be used by plasmamen exployed as engineers, the usual purple stripes being replaced by engineer's orange. It protects the user from fire and acid damage." icon_state = "engineer_envirosuit" item_state = "engineer_envirosuit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 10, "fire" = 95, "acid" = 95) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 10, "fire" = 95, "acid" = 95, "wound" = 5) /obj/item/clothing/under/plasmaman/engineering/ce name = "chief engineer's plasma envirosuit" diff --git a/code/modules/clothing/under/jobs/Plasmaman/medsci.dm b/code/modules/clothing/under/jobs/Plasmaman/medsci.dm index 03d089c10d..52f817dcce 100644 --- a/code/modules/clothing/under/jobs/Plasmaman/medsci.dm +++ b/code/modules/clothing/under/jobs/Plasmaman/medsci.dm @@ -21,7 +21,7 @@ desc = "A plasmaman envirosuit designed for the research director to aid them in their job of directing research into the right direction." icon_state = "rd_envirosuit" item_state = "rd_envirosuit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95, "wound" = 5) /obj/item/clothing/under/plasmaman/robotics name = "robotics plasma envirosuit" diff --git a/code/modules/clothing/under/jobs/Plasmaman/security.dm b/code/modules/clothing/under/jobs/Plasmaman/security.dm index ddbda041f3..3330d72844 100644 --- a/code/modules/clothing/under/jobs/Plasmaman/security.dm +++ b/code/modules/clothing/under/jobs/Plasmaman/security.dm @@ -3,7 +3,7 @@ desc = "A plasmaman containment suit designed for security officers, offering a limited amount of extra protection." icon_state = "security_envirosuit" item_state = "security_envirosuit" - armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 100, "rad" = 0, "fire" = 95, "acid" = 95, "wound" = 10) sensor_mode = SENSOR_COORDS random_sensor = FALSE diff --git a/code/modules/clothing/under/jobs/civilian/civilian.dm b/code/modules/clothing/under/jobs/civilian/civilian.dm index 4eb6a18258..5dffc8f88d 100644 --- a/code/modules/clothing/under/jobs/civilian/civilian.dm +++ b/code/modules/clothing/under/jobs/civilian/civilian.dm @@ -110,7 +110,7 @@ desc = "It's the official uniform of the station's janitor. It has minor protection from biohazards." name = "janitor's jumpsuit" icon_state = "janitor" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/rank/civilian/janitor/skirt name = "janitor's jumpskirt" diff --git a/code/modules/clothing/under/jobs/engineering.dm b/code/modules/clothing/under/jobs/engineering.dm index 3eaaa42620..5693468b3b 100644 --- a/code/modules/clothing/under/jobs/engineering.dm +++ b/code/modules/clothing/under/jobs/engineering.dm @@ -4,7 +4,7 @@ name = "chief engineer's jumpsuit" icon_state = "chiefengineer" item_state = "gy_suit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 80, "acid" = 40) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 80, "acid" = 40, "wound" = 5) resistance_flags = NONE /obj/item/clothing/under/rank/engineering/chief_engineer/skirt @@ -39,7 +39,7 @@ name = "engineer's jumpsuit" icon_state = "engine" item_state = "engi_suit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 60, "acid" = 20) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 60, "acid" = 20, "wound" = 5) resistance_flags = NONE /obj/item/clothing/under/rank/engineering/engineer/hazard diff --git a/code/modules/clothing/under/jobs/medical.dm b/code/modules/clothing/under/jobs/medical.dm index c4eedf93a4..c66b972624 100644 --- a/code/modules/clothing/under/jobs/medical.dm +++ b/code/modules/clothing/under/jobs/medical.dm @@ -4,7 +4,7 @@ icon_state = "cmo" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/rank/medical/chief_medical_officer/skirt name = "chief medical officer's jumpskirt" @@ -30,7 +30,7 @@ icon_state = "genetics" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/rank/medical/geneticist/skirt name = "geneticist's jumpskirt" @@ -48,7 +48,7 @@ icon_state = "virology" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/rank/medical/virologist/skirt name = "virologist's jumpskirt" @@ -66,7 +66,7 @@ icon_state = "chemistry" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 65) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 50, "acid" = 65, "wound" = 5) /obj/item/clothing/under/rank/medical/chemist/skirt name = "chemist's jumpskirt" @@ -84,7 +84,7 @@ icon_state = "paramedic-dark" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/rank/medical/paramedic/light desc = "It's made of a special fiber that provides minor protection against biohazards. It has a dark blue cross on the chest denoting that the wearer is a trained paramedic." @@ -110,7 +110,7 @@ icon_state = "nursesuit" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) body_parts_covered = CHEST|GROIN|ARMS fitted = NO_FEMALE_UNIFORM can_adjust = FALSE @@ -122,7 +122,7 @@ icon_state = "medical" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/rank/medical/doctor/blue name = "blue medical scrubs" diff --git a/code/modules/clothing/under/jobs/rnd.dm b/code/modules/clothing/under/jobs/rnd.dm index f7bd6d5e33..03eb910736 100644 --- a/code/modules/clothing/under/jobs/rnd.dm +++ b/code/modules/clothing/under/jobs/rnd.dm @@ -3,7 +3,7 @@ name = "research director's vest suit" icon_state = "director" item_state = "lb_suit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 35) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 35, "wound" = 5) can_adjust = FALSE /obj/item/clothing/under/rank/rnd/research_director/skirt @@ -20,7 +20,7 @@ name = "research director's tan suit" icon_state = "rdwhimsy" item_state = "rdwhimsy" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) can_adjust = TRUE alt_covers_chest = TRUE @@ -39,7 +39,7 @@ name = "research director's turtleneck" icon_state = "rdturtle" item_state = "p_suit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 10, "bio" = 10, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) can_adjust = TRUE alt_covers_chest = TRUE @@ -59,7 +59,7 @@ icon_state = "toxins" item_state = "w_suit" permeability_coefficient = 0.5 - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 10, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/rank/rnd/scientist/skirt name = "scientist's jumpskirt" diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm index 997f10a379..bc38cb6664 100644 --- a/code/modules/clothing/under/miscellaneous.dm +++ b/code/modules/clothing/under/miscellaneous.dm @@ -66,7 +66,7 @@ gas_transfer_coefficient = 0.01 permeability_coefficient = 0.01 body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS - armor = list("melee" = 100, "bullet" = 100, "laser" = 100,"energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100) + armor = list("melee" = 100, "bullet" = 100, "laser" = 100,"energy" = 100, "bomb" = 100, "bio" = 100, "rad" = 100, "fire" = 100, "acid" = 100, "wound" = 1000) //wound defense at 100 wont stop wounds cold_protection = CHEST | GROIN | LEGS | FEET | ARMS | HANDS min_cold_protection_temperature = SPACE_SUIT_MIN_TEMP_PROTECT heat_protection = CHEST|GROIN|LEGS|FEET|ARMS|HANDS diff --git a/code/modules/clothing/under/syndicate.dm b/code/modules/clothing/under/syndicate.dm index 8a88e99d05..a0b5bbc143 100644 --- a/code/modules/clothing/under/syndicate.dm +++ b/code/modules/clothing/under/syndicate.dm @@ -4,7 +4,7 @@ icon_state = "syndicate" item_state = "bl_suit" has_sensor = NO_SENSORS - armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5) alt_covers_chest = TRUE /obj/item/clothing/under/syndicate/skirt @@ -13,7 +13,7 @@ icon_state = "syndicate_skirt" item_state = "bl_suit" has_sensor = NO_SENSORS - armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5) alt_covers_chest = TRUE fitted = FEMALE_UNIFORM_TOP mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON @@ -24,7 +24,7 @@ icon_state = "bloodred_pajamas" item_state = "bl_suit" dummy_thick = TRUE - armor = list("melee" = 10, "bullet" = 10, "laser" = 10,"energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 50, "acid" = 40) + armor = list("melee" = 10, "bullet" = 10, "laser" = 10,"energy" = 10, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 50, "acid" = 40, "wound" = 10) resistance_flags = FIRE_PROOF | ACID_PROOF can_adjust = FALSE @@ -33,21 +33,21 @@ desc = "Do operatives dream of nuclear sheep?" icon_state = "bloodred_pajamas" item_state = "bl_suit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5) /obj/item/clothing/under/syndicate/tacticool name = "tacticool turtleneck" desc = "Just looking at it makes you want to buy an SKS, go into the woods, and -operate-." icon_state = "tactifool" item_state = "bl_suit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5) /obj/item/clothing/under/syndicate/tacticool/skirt name = "tacticool skirtleneck" desc = "Just looking at it makes you want to buy an SKS, go into the woods, and -operate-." icon_state = "tactifool_skirt" item_state = "bl_suit" - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 5) fitted = FEMALE_UNIFORM_TOP mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON @@ -57,7 +57,7 @@ icon_state = "tactifool" item_state = "bl_suit" has_sensor = TRUE - armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) /obj/item/clothing/under/syndicate/sniper name = "Tactical turtleneck suit" @@ -78,7 +78,7 @@ desc = "Badly translated labels tell you to clean this in Vodka. Great for squatting in." icon_state = "trackpants" can_adjust = FALSE - armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 10, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) resistance_flags = NONE /obj/item/clothing/under/syndicate/combat @@ -93,7 +93,7 @@ desc = "Military grade tracksuits for frontline squatting." icon_state = "rus_under" can_adjust = FALSE - armor = list("melee" = 5, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0) + armor = list("melee" = 5, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 0, "acid" = 0, "wound" = 5) resistance_flags = NONE mutantrace_variation = STYLE_DIGITIGRADE|STYLE_NO_ANTHRO_ICON @@ -103,7 +103,7 @@ icon_state = "syndicatebaseball" item_state = "syndicatebaseball" has_sensor = NO_SENSORS - armor = list("melee" = 15, "bullet" = 5, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40) + armor = list("melee" = 15, "bullet" = 5, "laser" = 0,"energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 40, "wound" = 10) alt_covers_chest = TRUE mutantrace_variation = USE_TAUR_CLIP_MASK From 36d6246bc1735dc017b3ece7adda4b738f2fb814 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 26 Jul 2020 18:54:57 +0100 Subject: [PATCH 17/91] it is now harder to deal wounds --- code/__DEFINES/wounds.dm | 4 ++-- code/datums/wounds/bones.dm | 6 +++--- code/modules/clothing/spacesuits/miscellaneous.dm | 4 ++-- code/modules/surgery/tools.dm | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/code/__DEFINES/wounds.dm b/code/__DEFINES/wounds.dm index 69ed45a817..8d92641cde 100644 --- a/code/__DEFINES/wounds.dm +++ b/code/__DEFINES/wounds.dm @@ -1,5 +1,5 @@ -#define WOUND_DAMAGE_EXPONENT 1.3 +#define WOUND_DAMAGE_EXPONENT 1.225 /// an attack must do this much damage after armor in order to roll for being a wound (incremental pressure damage need not apply) #define WOUND_MINIMUM_DAMAGE 5 @@ -31,7 +31,7 @@ #define WOUND_DETERMINATION_LOSS 7.5 /// the max amount of determination you can have -#define WOUND_DETERMINATION_MAX 10 +#define WOUND_DETERMINATION_MAX 10c /// set wound_bonus on an item or attack to this to disable checking wounding for the attack #define CANT_WOUND -100 diff --git a/code/datums/wounds/bones.dm b/code/datums/wounds/bones.dm index 3335356b7e..128c860a6d 100644 --- a/code/datums/wounds/bones.dm +++ b/code/datums/wounds/bones.dm @@ -193,7 +193,7 @@ 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 + limp_slowdown = 1.5 threshold_minimum = 45 threshold_penalty = 15 treatable_tool = TOOL_BONESET @@ -294,7 +294,7 @@ severity = WOUND_SEVERITY_SEVERE interaction_efficiency_penalty = 2 - limp_slowdown = 6 + limp_slowdown = 4 threshold_minimum = 70 threshold_penalty = 30 treatable_by = list(/obj/item/stack/sticky_tape/surgical, /obj/item/stack/medical/bone_gel) @@ -314,7 +314,7 @@ severity = WOUND_SEVERITY_CRITICAL interaction_efficiency_penalty = 4 - limp_slowdown = 9 + limp_slowdown = 6 sound_effect = 'sound/effects/wounds/crack2.ogg' threshold_minimum = 125 threshold_penalty = 50 diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index 35dc7d0485..5124c5d62e 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -175,7 +175,7 @@ Contains: icon_state = "hardsuit0-ert_commander" item_state = "hardsuit0-ert_commander" hardsuit_type = "ert_commander" - armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80. "wound" = 30) + armor = list("melee" = 65, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 50, "bio" = 100, "rad" = 100, "fire" = 80, "acid" = 80, "wound" = 30) strip_delay = 130 brightness_on = 7 resistance_flags = ACID_PROOF @@ -492,7 +492,7 @@ Contains: icon_state = "syndicate-orange" item_state = "syndicate-orange" slowdown = 2 - armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0), "wound" = 5 + armor = list("melee" = 5, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 10, "fire" = 0, "acid" = 0, "wound" = 5) strip_delay = 65 /obj/item/clothing/suit/space/fragile/run_block(mob/living/owner, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone, final_block_chance, list/block_return) diff --git a/code/modules/surgery/tools.dm b/code/modules/surgery/tools.dm index 4546be22d7..c4ded65e9c 100644 --- a/code/modules/surgery/tools.dm +++ b/code/modules/surgery/tools.dm @@ -248,8 +248,8 @@ sharpness = SHARP_EDGED tool_behaviour = TOOL_SAW toolspeed = 1 - wound_bonus = 10 - bare_wound_bonus = 15 + wound_bonus = 5 + bare_wound_bonus = 10 /obj/item/circular_saw/Initialize() . = ..() From e9b397cbad4490730c40a95c7a687a0550d8ecf7 Mon Sep 17 00:00:00 2001 From: GlitchyCore Date: Sun, 26 Jul 2020 16:41:48 -0500 Subject: [PATCH 18/91] ADDS END ROUND SOUND --- code/controllers/subsystem/ticker.dm | 3 ++- .../CitadelStationHasSeenBetterDays.ogg | Bin 0 -> 57606 bytes 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 sound/roundend/CitadelStationHasSeenBetterDays.ogg diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 765f0c8382..0336109add 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -711,7 +711,8 @@ SUBSYSTEM_DEF(ticker) 'sound/roundend/yeehaw.ogg', 'sound/roundend/disappointed.ogg', 'sound/roundend/gondolabridge.ogg', - 'sound/roundend/haveabeautifultime.ogg'\ + 'sound/roundend/haveabeautifultime.ogg', + 'CitadelStationHasSeenBetterDays'\ ) SEND_SOUND(world, sound(round_end_sound)) diff --git a/sound/roundend/CitadelStationHasSeenBetterDays.ogg b/sound/roundend/CitadelStationHasSeenBetterDays.ogg new file mode 100644 index 0000000000000000000000000000000000000000..2fa0c5b33c3c3d96b2fdb11c3d6476afed04cd54 GIT binary patch literal 57606 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 Date: Sun, 26 Jul 2020 16:59:26 -0500 Subject: [PATCH 19/91] hey you know what it'd be good if the filepath was actually there instead of the the .ogg name --- code/controllers/subsystem/ticker.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 0336109add..21a4ac88a5 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -712,7 +712,7 @@ SUBSYSTEM_DEF(ticker) 'sound/roundend/disappointed.ogg', 'sound/roundend/gondolabridge.ogg', 'sound/roundend/haveabeautifultime.ogg', - 'CitadelStationHasSeenBetterDays'\ + 'sound/roundend/CitadelStationHasSeenBetterDays'\ ) SEND_SOUND(world, sound(round_end_sound)) From 28bf5d23444052bf233700846f9c24b52829d7e2 Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Sun, 26 Jul 2020 23:15:56 +0100 Subject: [PATCH 20/91] remove c --- code/__DEFINES/wounds.dm | 2 +- code/modules/reagents/chemistry/reagents/other_reagents.dm | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/code/__DEFINES/wounds.dm b/code/__DEFINES/wounds.dm index 8d92641cde..73ada71423 100644 --- a/code/__DEFINES/wounds.dm +++ b/code/__DEFINES/wounds.dm @@ -31,7 +31,7 @@ #define WOUND_DETERMINATION_LOSS 7.5 /// the max amount of determination you can have -#define WOUND_DETERMINATION_MAX 10c +#define WOUND_DETERMINATION_MAX 10 /// set wound_bonus on an item or attack to this to disable checking wounding for the attack #define CANT_WOUND -100 diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 783e1a59fd..81ad676613 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -2345,7 +2345,6 @@ color = "#E6E6DA" taste_mult = 0 - /datum/reagent/hairball name = "Hairball" description = "A bundle of keratinous bits and fibers, not easily digestible." @@ -2393,4 +2392,4 @@ M.reagents.del_reagent(/datum/reagent/hairball) return ..() - + From bbda8dbf790d90374ed9208de5b15ba3b446d432 Mon Sep 17 00:00:00 2001 From: Timothy Teakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Mon, 27 Jul 2020 18:48:44 +0100 Subject: [PATCH 21/91] make detective the same, remove blood and paraplegic --- code/modules/jobs/job_types/detective.dm | 2 +- code/modules/jobs/job_types/head_of_security.dm | 2 +- code/modules/jobs/job_types/security_officer.dm | 2 +- code/modules/jobs/job_types/warden.dm | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/code/modules/jobs/job_types/detective.dm b/code/modules/jobs/job_types/detective.dm index e5afe7e1b3..463113f14c 100644 --- a/code/modules/jobs/job_types/detective.dm +++ b/code/modules/jobs/job_types/detective.dm @@ -23,7 +23,7 @@ mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) display_order = JOB_DISPLAY_ORDER_DETECTIVE - blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/nonviolent, /datum/quirk/paraplegic) + blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/monophobia) threat = 1 /datum/outfit/job/detective diff --git a/code/modules/jobs/job_types/head_of_security.dm b/code/modules/jobs/job_types/head_of_security.dm index 9d870b069a..3d7d07d894 100644 --- a/code/modules/jobs/job_types/head_of_security.dm +++ b/code/modules/jobs/job_types/head_of_security.dm @@ -31,7 +31,7 @@ paycheck_department = ACCOUNT_SEC display_order = JOB_DISPLAY_ORDER_HEAD_OF_SECURITY - blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/poor_aim, /datum/quirk/blindness, /datum/quirk/monophobia, /datum/quirk/insanity, /datum/quirk/blooddeficiency) + blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/blindness, /datum/quirk/monophobia, /datum/quirk/insanity) threat = 3 /datum/outfit/job/hos diff --git a/code/modules/jobs/job_types/security_officer.dm b/code/modules/jobs/job_types/security_officer.dm index 466131899d..7e71b2d1f4 100644 --- a/code/modules/jobs/job_types/security_officer.dm +++ b/code/modules/jobs/job_types/security_officer.dm @@ -23,7 +23,7 @@ mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) display_order = JOB_DISPLAY_ORDER_SECURITY_OFFICER - blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/poor_aim, /datum/quirk/blindness, /datum/quirk/monophobia, /datum/quirk/blooddeficiency) + blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/blindness, /datum/quirk/monophobia) threat = 2 /datum/job/officer/get_access() diff --git a/code/modules/jobs/job_types/warden.dm b/code/modules/jobs/job_types/warden.dm index 8b36e995da..22e3f9b0f1 100644 --- a/code/modules/jobs/job_types/warden.dm +++ b/code/modules/jobs/job_types/warden.dm @@ -24,7 +24,7 @@ mind_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM) display_order = JOB_DISPLAY_ORDER_WARDEN - blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/poor_aim, /datum/quirk/blindness, /datum/quirk/monophobia, /datum/quirk/blooddeficiency) + blacklisted_quirks = list(/datum/quirk/mute, /datum/quirk/brainproblems, /datum/quirk/nonviolent, /datum/quirk/paraplegic, /datum/quirk/blindness, /datum/quirk/monophobia) threat = 2 /datum/job/warden/get_access() From cf7678c7d4a27be369f9e8c616752d04ef1473bf Mon Sep 17 00:00:00 2001 From: GlitchyCore Date: Mon, 27 Jul 2020 14:41:10 -0500 Subject: [PATCH 22/91] hey let's forget to add the filetype to this instead of making sure it would actually work --- code/controllers/subsystem/ticker.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 21a4ac88a5..0bc4e6665a 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -712,7 +712,7 @@ SUBSYSTEM_DEF(ticker) 'sound/roundend/disappointed.ogg', 'sound/roundend/gondolabridge.ogg', 'sound/roundend/haveabeautifultime.ogg', - 'sound/roundend/CitadelStationHasSeenBetterDays'\ + 'sound/roundend/CitadelStationHasSeenBetterDays.ogg'\ ) SEND_SOUND(world, sound(round_end_sound)) From ef39e62e39af7d042850b3475e5f61b55e0e51cb Mon Sep 17 00:00:00 2001 From: Artur Date: Wed, 29 Jul 2020 02:11:14 +0300 Subject: [PATCH 23/91] Makes bloodsucker death not spam now actually working --- code/modules/antagonists/bloodsucker/bloodsucker_life.dm | 8 +++++--- code/modules/antagonists/bloodsucker/datum_bloodsucker.dm | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm index 47a98623db..208b1be87b 100644 --- a/code/modules/antagonists/bloodsucker/bloodsucker_life.dm +++ b/code/modules/antagonists/bloodsucker/bloodsucker_life.dm @@ -13,7 +13,7 @@ /datum/antagonist/bloodsucker/proc/LifeTick()// Should probably run from life.dm, same as handle_changeling, but will be an utter pain to move set waitfor = FALSE // Don't make on_gain() wait for this function to finish. This lets this code run on the side. var/notice_healing - while(owner && !AmFinalDeath()) // owner.has_antag_datum(ANTAG_DATUM_BLOODSUCKER) == src + while(owner && !AmFinalDeath()) if(owner.current.stat == CONSCIOUS && !poweron_feed && !HAS_TRAIT(owner.current, TRAIT_FAKEDEATH)) // Deduct Blood AddBloodVolume(passive_blood_drain) // -.1 currently if(HandleHealing(1)) // Heal @@ -272,13 +272,15 @@ /datum/antagonist/bloodsucker/AmFinalDeath() return owner && owner.AmFinalDeath() -/datum/antagonist/changeling/AmFinalDeath() - return owner && owner.AmFinalDeath() /datum/mind/proc/AmFinalDeath() return !current || QDELETED(current) || !isliving(current) || isbrain(current) || !get_turf(current) // NOTE: "isliving()" is not the same as STAT == CONSCIOUS. This is to make sure you're not a BORG (aka silicon) /datum/antagonist/bloodsucker/proc/FinalDeath() + //Dont bother if we are already supposed to be dead + if(FinalDeath) + return + FinalDeath = TRUE //We are now supposed to die. Lets not spam it. if(!iscarbon(owner.current)) //Check for non carbons. owner.current.gib() return diff --git a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm index 888db8193b..d732742e51 100644 --- a/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm +++ b/code/modules/antagonists/bloodsucker/datum_bloodsucker.dm @@ -37,6 +37,7 @@ var/had_toxlover var/level_bloodcost var/passive_blood_drain = -0.1 //The amount of blood we loose each bloodsucker life() tick + var/FinalDeath //Have we reached final death? Used to prevent spam. // LISTS var/static/list/defaultTraits = list (TRAIT_STABLEHEART, TRAIT_NOBREATH, TRAIT_SLEEPIMMUNE, TRAIT_NOCRITDAMAGE, TRAIT_RESISTCOLD, TRAIT_RADIMMUNE, TRAIT_NIGHT_VISION, \ TRAIT_NOSOFTCRIT, TRAIT_NOHARDCRIT, TRAIT_AGEUSIA, TRAIT_COLDBLOODED, TRAIT_NONATURALHEAL, TRAIT_NOMARROW, TRAIT_NOPULSE, TRAIT_VIRUSIMMUNE, TRAIT_NODECAP, TRAIT_NOGUT) @@ -683,6 +684,8 @@ owner.current.hud_used.sunlight_display.invisibility = INVISIBILITY_ABSTRACT /datum/antagonist/bloodsucker/proc/update_hud(updateRank=FALSE) + if(FinalDeath) + return // No Hud? Get out. if(!owner.current.hud_used) return From 0772d6687f451dfe531d0c50eb8b5f5155b88b63 Mon Sep 17 00:00:00 2001 From: Seris02 Date: Thu, 30 Jul 2020 08:01:25 +0800 Subject: [PATCH 24/91] ghost chilis fixed --- code/modules/hydroponics/grown/chili.dm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/code/modules/hydroponics/grown/chili.dm b/code/modules/hydroponics/grown/chili.dm index 1f60afe655..54481f7d37 100644 --- a/code/modules/hydroponics/grown/chili.dm +++ b/code/modules/hydroponics/grown/chili.dm @@ -81,8 +81,9 @@ wine_power = 50 /obj/item/reagent_containers/food/snacks/grown/ghost_chili/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) - if( ismob(loc) ) - held_mob = loc + . = ..() + held_mob = loc + if(istype(held_mob)) START_PROCESSING(SSobj, src) /obj/item/reagent_containers/food/snacks/grown/ghost_chili/process() From b8522a2ae0e9011583a52fa9ef2692bcbde3ccf0 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Wed, 29 Jul 2020 20:04:47 -0700 Subject: [PATCH 25/91] ok --- code/modules/instruments/songs/_song.dm | 10 ++++++++++ .../mob/living/simple_animal/guardian/guardian.dm | 12 +++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/code/modules/instruments/songs/_song.dm b/code/modules/instruments/songs/_song.dm index 463398d2f2..8d40f68cd4 100644 --- a/code/modules/instruments/songs/_song.dm +++ b/code/modules/instruments/songs/_song.dm @@ -303,3 +303,13 @@ return TRUE var/obj/structure/musician/M = parent return M.should_stop_playing(user) + +/datum/song/holoparasite + var/mob/living/simple_animal/hostile/guardian/stand + +/datum/song/holoparasite/updateDialog() + stand.ui_interact(src) + +/datum/song/holoparasite/should_stop_playing(mob/user) + return FALSE + diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index 73ebfa7c77..332d781fdd 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -60,11 +60,13 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians var/magic_fluff_string = "You draw the Coder, symbolizing bugs and errors. This shouldn't happen! Submit a bug report!" var/tech_fluff_string = "BOOT SEQUENCE COMPLETE. ERROR MODULE LOADED. THIS SHOULDN'T HAPPEN. Submit a bug report!" var/carp_fluff_string = "CARP CARP CARP SOME SORT OF HORRIFIC BUG BLAME THE CODERS CARP CARP CARP" + /// sigh, fine. + var/datum/song/holoparasite/music_datum /mob/living/simple_animal/hostile/guardian/Initialize(mapload, theme) GLOB.parasites += src updatetheme(theme) - + music_datum = new(src, get_allowed_instrument_ids()) . = ..() /mob/living/simple_animal/hostile/guardian/med_hud_set_health() @@ -84,8 +86,16 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians /mob/living/simple_animal/hostile/guardian/Destroy() GLOB.parasites -= src + QDEL_NULL(music_datum) return ..() +/mob/living/simple_animal/hostile/guardian/verb/music_interact() + set name = "Access Internal Synthesizer" + set desc = "ACcess your internal musical synthesizer" + set category = "IC" + + music_datum.ui_interact(src) + /mob/living/simple_animal/hostile/guardian/proc/updatetheme(theme) //update the guardian's theme if(!theme) theme = pick("magic", "tech", "carp") From ba0c77a8bd2ab70f47b0a121c561ffbcee13c745 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Wed, 29 Jul 2020 20:13:39 -0700 Subject: [PATCH 26/91] fix --- code/modules/instruments/songs/_song.dm | 6 ++++++ code/modules/instruments/songs/editor.dm | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/code/modules/instruments/songs/_song.dm b/code/modules/instruments/songs/_song.dm index 8d40f68cd4..26ed5e5dd3 100644 --- a/code/modules/instruments/songs/_song.dm +++ b/code/modules/instruments/songs/_song.dm @@ -307,9 +307,15 @@ /datum/song/holoparasite var/mob/living/simple_animal/hostile/guardian/stand +/datum/song/holoparasite/New(atom/parent, list/instrument_ids) + . = ..() + stand = istype(parent, /mob/living/simple_animal/hostile/guardian) && parent + /datum/song/holoparasite/updateDialog() stand.ui_interact(src) /datum/song/holoparasite/should_stop_playing(mob/user) return FALSE +/datum/song/holoparasite/check_can_use(mob/user) + return user == stand) diff --git a/code/modules/instruments/songs/editor.dm b/code/modules/instruments/songs/editor.dm index d9595797d7..8c5171667a 100644 --- a/code/modules/instruments/songs/editor.dm +++ b/code/modules/instruments/songs/editor.dm @@ -109,8 +109,11 @@ linenum++ updateDialog(usr) // make sure updates when complete +/datum/song/proc/check_can_use(mob/user) + return user.canUseTopic(parent, TRUE, FALSE, FALSE, FALSE) + /datum/song/Topic(href, href_list) - if(!usr.canUseTopic(parent, TRUE, FALSE, FALSE, FALSE)) + if(!check_can_use(usr)) usr << browse(null, "window=instrument") usr.unset_machine() return From 3a773809b6f450dec448b3b98b08cc50deaf9b53 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Fri, 31 Jul 2020 00:22:46 -0700 Subject: [PATCH 27/91] Update guardian.dm --- code/modules/mob/living/simple_animal/guardian/guardian.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/simple_animal/guardian/guardian.dm b/code/modules/mob/living/simple_animal/guardian/guardian.dm index 332d781fdd..02bf95eaad 100644 --- a/code/modules/mob/living/simple_animal/guardian/guardian.dm +++ b/code/modules/mob/living/simple_animal/guardian/guardian.dm @@ -91,7 +91,7 @@ GLOBAL_LIST_EMPTY(parasites) //all currently existing/living guardians /mob/living/simple_animal/hostile/guardian/verb/music_interact() set name = "Access Internal Synthesizer" - set desc = "ACcess your internal musical synthesizer" + set desc = "Access your internal musical synthesizer" set category = "IC" music_datum.ui_interact(src) From 1c2bc1b632725e58000af46e782f8e0d172f67e9 Mon Sep 17 00:00:00 2001 From: silicons <2003111+silicons@users.noreply.github.com> Date: Fri, 31 Jul 2020 00:24:48 -0700 Subject: [PATCH 28/91] Update _song.dm --- code/modules/instruments/songs/_song.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/instruments/songs/_song.dm b/code/modules/instruments/songs/_song.dm index 26ed5e5dd3..d842dbc003 100644 --- a/code/modules/instruments/songs/_song.dm +++ b/code/modules/instruments/songs/_song.dm @@ -318,4 +318,4 @@ return FALSE /datum/song/holoparasite/check_can_use(mob/user) - return user == stand) + return (user == stand) From 8d63714f3a4c70ebd48f15ab33bd6fd57aa450df Mon Sep 17 00:00:00 2001 From: timothyteakettle <59849408+timothyteakettle@users.noreply.github.com> Date: Fri, 31 Jul 2020 23:04:29 +0100 Subject: [PATCH 29/91] make tongue preference dna --- code/modules/client/preferences.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 75e914ea68..fe09b5f8c9 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -2796,6 +2796,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) if(custom_tongue != "default") var/new_tongue = GLOB.roundstart_tongues[custom_tongue] if(new_tongue) + character.dna.species.mutanttongue = new_tongue //this means we get our tongue when we clone var/obj/item/organ/tongue/T = character.getorganslot(ORGAN_SLOT_TONGUE) if(T) qdel(T) From 79590f6dc9b57e7c74c1df86979132eb98bfffb6 Mon Sep 17 00:00:00 2001 From: Changelogs Date: Sat, 1 Aug 2020 00:40:55 +0000 Subject: [PATCH 30/91] Automatic changelog compile [ci skip] --- html/changelog.html | 16 ++++++++++++++++ html/changelogs/.all_changelog.yml | 10 ++++++++++ html/changelogs/AutoChangeLog-pr-12952.yml | 5 ----- html/changelogs/AutoChangeLog-pr-12962.yml | 4 ---- html/changelogs/AutoChangeLog-pr-12964.yml | 4 ---- html/changelogs/AutoChangeLog-pr-12967.yml | 4 ---- 6 files changed, 26 insertions(+), 17 deletions(-) delete mode 100644 html/changelogs/AutoChangeLog-pr-12952.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-12962.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-12964.yml delete mode 100644 html/changelogs/AutoChangeLog-pr-12967.yml diff --git a/html/changelog.html b/html/changelog.html index 8c93566692..b87a49f7f2 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -50,6 +50,22 @@ -->
+

01 August 2020

+

dapnee updated:

+
    +
  • added cake hat to bar, adds another atmostech spawn
  • +
  • sinks point in the right direction, APC won't spawn off the wall in circuits
  • +
  • changes commissary APC so it actually powers the room, adds a missing AIR alarm, arrivals no longer has active atmos tiles.
  • +
+

silicons updated:

+
    +
  • toy shotguns no longer need 2 hands to fire
  • +
+

timothyteakettle updated:

+
    +
  • monkeys no longer continuously bleed everywhere
  • +
+

30 July 2020

Adelphon updated: