port1
This commit is contained in:
@@ -140,6 +140,7 @@
|
||||
#define CUSTOM_SKINTONE 24 //adds a "_g" suffix to bodypart overlays icon states if a custom skintone is used.
|
||||
#define HORNCOLOR 25
|
||||
#define WINGCOLOR 26
|
||||
#define CAN_SCAR 27 // If this species can be scarred (fleshy)
|
||||
|
||||
//organ slots
|
||||
#define ORGAN_SLOT_BRAIN "brain"
|
||||
|
||||
@@ -12,4 +12,9 @@
|
||||
#define SHOVABLE_ONTO (1<<9) //called on turf.shove_act() to consider whether an object should have a niche effect (defined in their own shove_act()) when someone is pushed onto it, or do a sanity CanPass() check.
|
||||
#define BLOCK_Z_FALL (1<<10)
|
||||
|
||||
/// Integrity defines for clothing (not flags but close enough)
|
||||
#define CLOTHING_PRISTINE 0 // We have no damage on the clothing
|
||||
#define CLOTHING_DAMAGED 1 // There's some damage on the clothing but it still has at least one functioning bodypart and can be equipped
|
||||
#define CLOTHING_SHREDDED 2 // The clothing is useless and cannot be equipped unless repaired first
|
||||
|
||||
// If you add new ones, be sure to add them to /obj/Initialize as well for complete mapping support
|
||||
|
||||
@@ -74,6 +74,9 @@
|
||||
#define ADMIN_PUNISHMENT_MAZING "Puzzle"
|
||||
#define ADMIN_PUNISHMENT_PIE "Cream Pie"
|
||||
#define ADMIN_PUNISHMENT_CUSTOM_PIE "Custom Cream Pie"
|
||||
#define ADMIN_PUNISHMENT_CRACK ":B:oneless"
|
||||
#define ADMIN_PUNISHMENT_BLEED ":B:loodless"
|
||||
#define ADMIN_PUNISHMENT_SCARIFY "Scarify"
|
||||
|
||||
#define AHELP_ACTIVE 1
|
||||
#define AHELP_CLOSED 2
|
||||
|
||||
@@ -250,7 +250,14 @@
|
||||
#define COMPONENT_INTERRUPT_LIFE_BIOLOGICAL 1 // interrupt biological processes
|
||||
#define COMPONENT_INTERRUPT_LIFE_PHYSICAL 2 // interrupt physical handling
|
||||
|
||||
// /mob/living/carbon signals
|
||||
// /mob/living/carbon physiology signals
|
||||
#define COMSIG_CARBON_GAIN_WOUND "carbon_gain_wound" //from /datum/wound/proc/apply_wound() (/mob/living/carbon/C, /datum/wound/W, /obj/item/bodypart/L)
|
||||
#define COMSIG_CARBON_LOSE_WOUND "carbon_lose_wound" //from /datum/wound/proc/remove_wound() (/mob/living/carbon/C, /datum/wound/W, /obj/item/bodypart/L)
|
||||
///from base of /obj/item/bodypart/proc/attach_limb(): (new_limb, special) allows you to fail limb attachment
|
||||
#define COMSIG_CARBON_ATTACH_LIMB "carbon_attach_limb"
|
||||
#define COMPONENT_NO_ATTACH (1<<0)
|
||||
#define COMSIG_CARBON_REMOVE_LIMB "carbon_remove_limb" //from base of /obj/item/bodypart/proc/drop_limb(special, dismembered)
|
||||
|
||||
#define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity))
|
||||
#define COMSIG_CARBON_IDENTITY_TRANSFERRED_TO "carbon_id_transferred_to" //from datum/dna/transfer_identity(): (datum/dna, transfer_SE)
|
||||
#define COMSIG_CARBON_TACKLED "carbon_tackled" //sends from tackle.dm on tackle completion
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
#define BODYPART_NOT_DISABLED 0
|
||||
#define BODYPART_DISABLED_DAMAGE 1
|
||||
#define BODYPART_DISABLED_PARALYSIS 2
|
||||
#define BODYPART_DISABLED_WOUND 3
|
||||
|
||||
#define DEFAULT_BODYPART_ICON 'icons/mob/human_parts.dmi'
|
||||
#define DEFAULT_BODYPART_ICON_ORGANIC 'icons/mob/human_parts_greyscale.dmi'
|
||||
@@ -103,12 +104,14 @@
|
||||
#define TRAUMA_RESILIENCE_BASIC 1 //Curable with chems
|
||||
#define TRAUMA_RESILIENCE_SURGERY 2 //Curable with brain surgery
|
||||
#define TRAUMA_RESILIENCE_LOBOTOMY 3 //Curable with lobotomy
|
||||
#define TRAUMA_RESILIENCE_MAGIC 4 //Curable only with magic
|
||||
#define TRAUMA_RESILIENCE_ABSOLUTE 5 //This is here to stay
|
||||
#define TRAUMA_RESILIENCE_WOUND 4 //Curable by healing the head wound
|
||||
#define TRAUMA_RESILIENCE_MAGIC 5 //Curable only with magic
|
||||
#define TRAUMA_RESILIENCE_ABSOLUTE 6 //This is here to stay
|
||||
|
||||
//Limit of traumas for each resilience tier
|
||||
#define TRAUMA_LIMIT_BASIC 3
|
||||
#define TRAUMA_LIMIT_SURGERY 2
|
||||
#define TRAUMA_LIMIT_WOUND 2
|
||||
#define TRAUMA_LIMIT_LOBOTOMY 3
|
||||
#define TRAUMA_LIMIT_MAGIC 3
|
||||
#define TRAUMA_LIMIT_ABSOLUTE INFINITY
|
||||
@@ -315,4 +318,4 @@
|
||||
#define EYE_CONTACT_RANGE 5
|
||||
|
||||
/// If you examine the same atom twice in this timeframe, we call examine_more() instead of examine()
|
||||
#define EXAMINE_MORE_TIME 1 SECONDS
|
||||
#define EXAMINE_MORE_TIME 1 SECONDS
|
||||
|
||||
@@ -36,6 +36,8 @@
|
||||
|
||||
#define STATUS_EFFECT_REGENERATIVE_CORE /datum/status_effect/regenerative_core //removes damage slowdown while giving a slow regenerating effect
|
||||
|
||||
#define STATUS_EFFECT_DETERMINED /datum/status_effect/determined //currently in a combat high from being seriously wounded
|
||||
|
||||
/////////////
|
||||
// DEBUFFS //
|
||||
/////////////
|
||||
@@ -107,6 +109,8 @@
|
||||
|
||||
#define STATUS_EFFECT_ELECTROSTAFF /datum/status_effect/electrostaff //slows down victim
|
||||
|
||||
#define STATUS_EFFECT_LIMP /datum/status_effect/limp //For when you have a busted leg (or two!) and want additional slowdown when walking on that leg
|
||||
|
||||
/////////////
|
||||
// NEUTRAL //
|
||||
/////////////
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
//Glasswork Tools
|
||||
#define TOOL_BLOW "blowing_rod"
|
||||
#define TOOL_GLASS_CUT "glasskit"
|
||||
#define TOOL_BONESET "bonesetter"
|
||||
|
||||
// If delay between the start and the end of tool operation is less than MIN_TOOL_SOUND_DELAY,
|
||||
// tool sound is only played when op is started. If not, it's played twice.
|
||||
|
||||
@@ -228,7 +228,7 @@
|
||||
#define TRAIT_SPRINT_LOCKED "sprint_locked"
|
||||
|
||||
//non-mob traits
|
||||
#define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it
|
||||
#define TRAIT_PARALYSIS "paralysis" //Used for limb-based paralysis, where replacing the limb will fix it
|
||||
#define VEHICLE_TRAIT "vehicle" // inherited from riding vehicles
|
||||
#define INNATE_TRAIT "innate"
|
||||
|
||||
|
||||
43
code/__DEFINES/wounds.dm
Normal file
43
code/__DEFINES/wounds.dm
Normal file
@@ -0,0 +1,43 @@
|
||||
#define WOUND_DAMAGE_EXPONENT 1.4
|
||||
|
||||
#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
|
||||
|
||||
// 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_MAX 10
|
||||
|
||||
// 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)
|
||||
|
||||
// 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
|
||||
// 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)
|
||||
|
||||
// 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
|
||||
@@ -81,6 +81,10 @@
|
||||
if (CONFIG_GET(flag/log_attack))
|
||||
WRITE_LOG(GLOB.world_attack_log, "ATTACK: [text]")
|
||||
|
||||
/proc/log_wounded(text)
|
||||
if (CONFIG_GET(flag/log_attack))
|
||||
WRITE_LOG(GLOB.world_attack_log, "WOUND: [text]")
|
||||
|
||||
/proc/log_manifest(ckey, datum/mind/mind,mob/body, latejoin = FALSE)
|
||||
if (CONFIG_GET(flag/log_manifest))
|
||||
WRITE_LOG(GLOB.world_manifest_log, "[ckey] \\ [body.real_name] \\ [mind.assigned_role] \\ [mind.special_role ? mind.special_role : "NONE"] \\ [latejoin ? "LATEJOIN":"ROUNDSTART"]")
|
||||
|
||||
@@ -339,10 +339,24 @@
|
||||
/proc/isLeap(y)
|
||||
return ((y) % 4 == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
|
||||
|
||||
|
||||
/// For finding out what body parts a body zone covers, the inverse of the below basically
|
||||
/proc/zone2body_parts_covered(def_zone)
|
||||
switch(def_zone)
|
||||
if(BODY_ZONE_CHEST)
|
||||
return list(CHEST, GROIN)
|
||||
if(BODY_ZONE_HEAD)
|
||||
return list(HEAD)
|
||||
if(BODY_ZONE_L_ARM)
|
||||
return list(ARM_LEFT, HAND_LEFT)
|
||||
if(BODY_ZONE_R_ARM)
|
||||
return list(ARM_RIGHT, HAND_RIGHT)
|
||||
if(BODY_ZONE_L_LEG)
|
||||
return list(LEG_LEFT, FOOT_LEFT)
|
||||
if(BODY_ZONE_R_LEG)
|
||||
return list(LEG_RIGHT, FOOT_RIGHT)
|
||||
|
||||
//Turns a Body_parts_covered bitfield into a list of organ/limb names.
|
||||
//(I challenge you to find a use for this)
|
||||
//(I challenge you to find a use for this) -I found a use for it!!
|
||||
/proc/body_parts_covered2organ_names(bpc)
|
||||
var/list/covered_parts = list()
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
Otherwise pretty standard.
|
||||
*/
|
||||
/mob/living/carbon/human/UnarmedAttack(atom/A, proximity)
|
||||
var/obj/item/bodypart/check_arm = get_active_hand()
|
||||
if(check_arm && check_arm.is_disabled() == BODYPART_DISABLED_WOUND)
|
||||
to_chat(src, "<span class='warning'>The damage in your [check_arm.name] is preventing you from using it! Get it fixed, or at least splinted!</span>")
|
||||
return
|
||||
|
||||
if(!has_active_hand()) //can't attack without a hand.
|
||||
to_chat(src, "<span class='notice'>You look at your arm and sigh.</span>")
|
||||
|
||||
@@ -268,6 +268,7 @@ SUBSYSTEM_DEF(persistence)
|
||||
SaveRandomizedRecipes()
|
||||
SavePanicBunker()
|
||||
SavePaintings()
|
||||
SaveScars()
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/LoadPanicBunker()
|
||||
var/bunker_path = file("data/bunker_passthrough.json")
|
||||
@@ -547,3 +548,24 @@ SUBSYSTEM_DEF(persistence)
|
||||
var/json_file = file("data/paintings.json")
|
||||
fdel(json_file)
|
||||
WRITE_FILE(json_file, json_encode(paintings))
|
||||
|
||||
/datum/controller/subsystem/persistence/proc/SaveScars()
|
||||
for(var/i in GLOB.joined_player_list)
|
||||
var/mob/living/carbon/human/ending_human = get_mob_by_ckey(i)
|
||||
if(!istype(ending_human) || !ending_human.mind || !ending_human.client || !ending_human.client.prefs || !ending_human.client.prefs.persistent_scars)
|
||||
continue
|
||||
|
||||
var/mob/living/carbon/human/original_human = ending_human.mind.original_character
|
||||
if(!original_human || original_human.stat == DEAD || !original_human.all_scars || !(original_human == ending_human))
|
||||
if(ending_human.client) // i was told if i don't check this every step of the way byond might decide a client ceases to exist mid proc so here we go
|
||||
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
|
||||
if(!ending_human.client)
|
||||
return
|
||||
ending_human.client.prefs.scars_list["[ending_human.client.prefs.scars_index]"] = ending_human.format_scars()
|
||||
if(!ending_human.client)
|
||||
return
|
||||
ending_human.client.prefs.save_character()
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]"
|
||||
#define ARMORID "armor-[melee]-[bullet]-[laser]-[energy]-[bomb]-[bio]-[rad]-[fire]-[acid]-[magic]-[wound]"
|
||||
|
||||
/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
|
||||
/proc/getArmor(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0)
|
||||
. = locate(ARMORID)
|
||||
if (!.)
|
||||
. = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
|
||||
. = new /datum/armor(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, wound)
|
||||
|
||||
/datum/armor
|
||||
datum_flags = DF_USE_TAG
|
||||
@@ -17,8 +17,9 @@
|
||||
var/fire
|
||||
var/acid
|
||||
var/magic
|
||||
var/wound
|
||||
|
||||
/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
|
||||
/datum/armor/New(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0)
|
||||
src.melee = melee
|
||||
src.bullet = bullet
|
||||
src.laser = laser
|
||||
@@ -29,15 +30,16 @@
|
||||
src.fire = fire
|
||||
src.acid = acid
|
||||
src.magic = magic
|
||||
src.wound = wound
|
||||
tag = ARMORID
|
||||
|
||||
/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0)
|
||||
return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic)
|
||||
/datum/armor/proc/modifyRating(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 0, rad = 0, fire = 0, acid = 0, magic = 0, wound = 0)
|
||||
return getArmor(src.melee+melee, src.bullet+bullet, src.laser+laser, src.energy+energy, src.bomb+bomb, src.bio+bio, src.rad+rad, src.fire+fire, src.acid+acid, src.magic+magic, src.wound+wound)
|
||||
|
||||
/datum/armor/proc/modifyAllRatings(modifier = 0)
|
||||
return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier)
|
||||
return getArmor(melee+modifier, bullet+modifier, laser+modifier, energy+modifier, bomb+modifier, bio+modifier, rad+modifier, fire+modifier, acid+modifier, magic+modifier, wound+modifier)
|
||||
|
||||
/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic)
|
||||
/datum/armor/proc/setRating(melee, bullet, laser, energy, bomb, bio, rad, fire, acid, magic, wound)
|
||||
return getArmor((isnull(melee) ? src.melee : melee),\
|
||||
(isnull(bullet) ? src.bullet : bullet),\
|
||||
(isnull(laser) ? src.laser : laser),\
|
||||
@@ -47,19 +49,20 @@
|
||||
(isnull(rad) ? src.rad : rad),\
|
||||
(isnull(fire) ? src.fire : fire),\
|
||||
(isnull(acid) ? src.acid : acid),\
|
||||
(isnull(magic) ? src.magic : magic))
|
||||
(isnull(magic) ? src.magic : magic),\
|
||||
(isnull(wound) ? src.wound : wound))
|
||||
|
||||
/datum/armor/proc/getRating(rating)
|
||||
return vars[rating]
|
||||
|
||||
/datum/armor/proc/getList()
|
||||
return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic)
|
||||
return list("melee" = melee, "bullet" = bullet, "laser" = laser, "energy" = energy, "bomb" = bomb, "bio" = bio, "rad" = rad, "fire" = fire, "acid" = acid, "magic" = magic, "wound" = wound)
|
||||
|
||||
/datum/armor/proc/attachArmor(datum/armor/AA)
|
||||
return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic)
|
||||
return getArmor(melee+AA.melee, bullet+AA.bullet, laser+AA.laser, energy+AA.energy, bomb+AA.bomb, bio+AA.bio, rad+AA.rad, fire+AA.fire, acid+AA.acid, magic+AA.magic, wound+AA.wound)
|
||||
|
||||
/datum/armor/proc/detachArmor(datum/armor/AA)
|
||||
return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic)
|
||||
return getArmor(melee-AA.melee, bullet-AA.bullet, laser-AA.laser, energy-AA.energy, bomb-AA.bomb, bio-AA.bio, rad-AA.rad, fire-AA.fire, acid-AA.acid, magic-AA.magic, wound-AA.wound)
|
||||
|
||||
/datum/armor/vv_edit_var(var_name, var_value)
|
||||
if (var_name == NAMEOF(src, tag))
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
if(get_dist(owner, stalker) <= 1)
|
||||
playsound(owner, 'sound/magic/demon_attack1.ogg', 50)
|
||||
owner.visible_message("<span class='warning'>[owner] is torn apart by invisible claws!</span>", "<span class='userdanger'>Ghostly claws tear your body apart!</span>")
|
||||
owner.take_bodypart_damage(rand(20, 45))
|
||||
owner.take_bodypart_damage(rand(20, 45), wound_bonus=CANT_WOUND)
|
||||
else if(prob(50))
|
||||
stalker.forceMove(get_step_towards(stalker, owner))
|
||||
if(get_dist(owner, stalker) <= 8)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
var/speed = 80 //time in deciseconds taken to butcher something
|
||||
var/effectiveness = 100 //percentage effectiveness; numbers above 100 yield extra drops
|
||||
var/bonus_modifier = 0 //percentage increase to bonus item chance
|
||||
var/butcher_sound = 'sound/weapons/slice.ogg' //sound played when butchering
|
||||
var/butcher_sound = 'sound/effects/butcher.ogg' //sound played when butchering
|
||||
var/butchering_enabled = TRUE
|
||||
var/can_be_blunt = FALSE
|
||||
|
||||
@@ -64,8 +64,11 @@
|
||||
H.visible_message("<span class='danger'>[user] slits [H]'s throat!</span>", \
|
||||
"<span class='userdanger'>[user] slits your throat...</span>")
|
||||
log_combat(user, H, "finishes slicing the throat of")
|
||||
H.apply_damage(source.force, BRUTE, BODY_ZONE_HEAD)
|
||||
H.bleed_rate = clamp(H.bleed_rate + 20, 0, 30)
|
||||
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
|
||||
screaming_through_a_slit_throat.apply_wound(slit_throat)
|
||||
H.apply_status_effect(/datum/status_effect/neck_slice)
|
||||
|
||||
/datum/component/butchering/proc/Butcher(mob/living/butcher, mob/living/meat)
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
var/damage = rand(min_damage, max_damage)
|
||||
if(HAS_TRAIT(H, TRAIT_LIGHT_STEP))
|
||||
damage *= 0.75
|
||||
H.apply_damage(damage, BRUTE, picked_def_zone)
|
||||
H.apply_damage(damage, BRUTE, picked_def_zone, wound_bonus = CANT_WOUND)
|
||||
|
||||
if(cooldown < world.time - 10) //cooldown to avoid message spam.
|
||||
if(!H.incapacitated(ignore_restraints = TRUE))
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
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)
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus=-30, sharpness = TRUE)
|
||||
SEND_SIGNAL(victim, COMSIG_ADD_MOOD_EVENT, "embedded", /datum/mood_event/embedded)
|
||||
else
|
||||
victim.visible_message("<span class='danger'>[weapon] sticks itself to [victim]'s [limb.name]!</span>",ignored_mobs=victim)
|
||||
@@ -163,7 +163,7 @@
|
||||
|
||||
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)
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND)
|
||||
to_chat(victim, "<span class='userdanger'>[weapon] embedded in your [limb.name] jostles and stings!</span>")
|
||||
|
||||
|
||||
@@ -173,7 +173,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)
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND)
|
||||
victim.visible_message("<span class='danger'>[weapon] falls out of [victim.name]'s [limb.name]!</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='userdanger'>[weapon] falls out of your [limb.name]!</span>")
|
||||
else
|
||||
@@ -199,7 +199,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) //It hurts to rip it out, get surgery you dingus.
|
||||
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.
|
||||
victim.emote("scream")
|
||||
victim.visible_message("<span class='notice'>[victim] successfully rips [weapon] out of [victim.p_their()] [limb.name]!</span>", "<span class='notice'>You successfully remove [weapon] from your [limb.name].</span>")
|
||||
else
|
||||
@@ -276,7 +276,7 @@
|
||||
damage *= 0.7
|
||||
|
||||
if(harmful && prob(chance))
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage)
|
||||
limb.receive_damage(brute=(1-pain_stam_pct) * damage, stamina=pain_stam_pct * damage, wound_bonus = CANT_WOUND)
|
||||
to_chat(victim, "<span class='userdanger'>[weapon] embedded in your [limb.name] hurts!</span>")
|
||||
|
||||
if(prob(fall_chance))
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
///Store the thrownthing datum for later use
|
||||
/datum/component/tackler/proc/registerTackle(mob/living/carbon/user, datum/thrownthing/TT)
|
||||
tackle = TT
|
||||
tackle.thrower = user
|
||||
|
||||
///See if we can tackle or not. If we can, leap!
|
||||
/datum/component/tackler/proc/checkTackle(mob/living/carbon/user, atom/A, params)
|
||||
|
||||
@@ -64,7 +64,8 @@ Bonus
|
||||
if(bleed)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
H.bleed_rate += 5 * power
|
||||
var/obj/item/bodypart/random_part = pick(H.bodyparts)
|
||||
random_part.generic_bleedstacks += 5 * power
|
||||
return 1
|
||||
|
||||
/*
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
else
|
||||
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, TRUE, -1)
|
||||
log_combat(A, D, "strong punched (Sleeping Carp)")//so as to not double up on logging
|
||||
D.apply_damage((damage + 15) + crit_damage, BRUTE, affecting)
|
||||
D.apply_damage((damage + 15) + crit_damage, BRUTE, affecting, wound_bonus = CANT_WOUND)
|
||||
return TRUE
|
||||
|
||||
///Crashing Wave Kick: Harm Disarm combo, throws people seven tiles backwards
|
||||
@@ -56,7 +56,7 @@
|
||||
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, TRUE, -1)
|
||||
var/atom/throw_target = get_edge_target_turf(D, A.dir)
|
||||
D.throw_at(throw_target, 7, 14, A)
|
||||
D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST)
|
||||
D.apply_damage(damage, BRUTE, BODY_ZONE_CHEST, wound_bonus = CANT_WOUND, wound_bonus = CANT_WOUND)
|
||||
log_combat(A, D, "launchkicked (Sleeping Carp)")
|
||||
return TRUE
|
||||
|
||||
@@ -66,14 +66,14 @@
|
||||
A.do_attack_animation(D, ATTACK_EFFECT_KICK)
|
||||
playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, TRUE, -1)
|
||||
if((D.mobility_flags & MOBILITY_STAND))
|
||||
D.apply_damage(damage, BRUTE, BODY_ZONE_HEAD)
|
||||
D.apply_damage(damage, BRUTE, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND)
|
||||
D.DefaultCombatKnockdown(50, override_hardstun = 0.01, override_stamdmg = 0)
|
||||
D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD) //A cit specific change form the tg port to really punish anyone who tries to stand up
|
||||
D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND) //A cit specific change form the tg port to really punish anyone who tries to stand up
|
||||
D.visible_message("<span class='warning'>[A] kicks [D] in the head, sending them face first into the floor!</span>", \
|
||||
"<span class='userdanger'>You are kicked in the head by [A], sending you crashing to the floor!</span>", "<span class='hear'>You hear a sickening sound of flesh hitting flesh!</span>", COMBAT_MESSAGE_RANGE, A)
|
||||
else
|
||||
D.apply_damage(damage*0.5, BRUTE, BODY_ZONE_HEAD)
|
||||
D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD)
|
||||
D.apply_damage(damage*0.5, BRUTE, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND)
|
||||
D.apply_damage(damage + 35, STAMINA, BODY_ZONE_HEAD, wound_bonus = CANT_WOUND)
|
||||
D.drop_all_held_items()
|
||||
D.visible_message("<span class='warning'>[A] kicks [D] in the head!</span>", \
|
||||
"<span class='userdanger'>You are kicked in the head by [A]!</span>", "<span class='hear'>You hear a sickening sound of flesh hitting flesh!</span>", COMBAT_MESSAGE_RANGE, A)
|
||||
@@ -99,7 +99,7 @@
|
||||
D.visible_message("<span class='danger'>[A] [atk_verb]s [D]!</span>", \
|
||||
"<span class='userdanger'>[A] [atk_verb]s you!</span>", null, null, A)
|
||||
to_chat(A, "<span class='danger'>You [atk_verb] [D]!</span>")
|
||||
D.apply_damage(damage, BRUTE, affecting)
|
||||
D.apply_damage(damage, BRUTE, affecting, wound_bonus = CANT_WOUND)
|
||||
playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, TRUE, -1)
|
||||
if(CHECK_MOBILITY(D, MOBILITY_STAND) && damage >= stunthreshold)
|
||||
to_chat(D, "<span class='danger'>You stumble and fall!</span>")
|
||||
|
||||
@@ -66,6 +66,9 @@
|
||||
/// Our skill holder.
|
||||
var/datum/skill_holder/skill_holder
|
||||
|
||||
///What character we spawned in as- either at roundstart or latejoin, so we know for persistent scars if we ended as the same person or not
|
||||
var/mob/original_character
|
||||
|
||||
/datum/mind/New(var/key)
|
||||
skill_holder = new(src)
|
||||
src.key = key
|
||||
@@ -90,6 +93,7 @@
|
||||
return language_holder
|
||||
|
||||
/datum/mind/proc/transfer_to(mob/new_character, var/force_key_move = 0)
|
||||
var/original_character = null
|
||||
var/old_character = current
|
||||
var/signals = SEND_SIGNAL(new_character, COMSIG_MOB_PRE_PLAYER_CHANGE, new_character, old_character) | SEND_SIGNAL(src, COMSIG_PRE_MIND_TRANSFER, new_character, old_character)
|
||||
if(signals & COMPONENT_STOP_MIND_TRANSFER)
|
||||
|
||||
@@ -77,10 +77,14 @@
|
||||
description = "<span class='boldwarning'>Pull it out!</span>\n"
|
||||
mood_change = -7
|
||||
|
||||
/datum/mood_event/table
|
||||
description = "<span class='warning'>Someone threw me on a table!</span>\n"
|
||||
mood_change = -2
|
||||
timeout = 2 MINUTES
|
||||
/datum/mood_event/table_limbsmash
|
||||
description = "<span class='warning'>That fucking table, man that hurts...</span>\n"
|
||||
mood_change = -3
|
||||
timeout = 3 MINUTES
|
||||
|
||||
/datum/mood_event/table_limbsmash/add_effects(obj/item/bodypart/banged_limb)
|
||||
if(banged_limb)
|
||||
description = "<span class='warning'>My fucking [banged_limb.name], man that hurts...</span>\n"
|
||||
|
||||
/datum/mood_event/table/add_effects()
|
||||
if(ishuman(owner))
|
||||
|
||||
@@ -441,6 +441,10 @@
|
||||
owner.adjustBruteLoss(-10, FALSE)
|
||||
owner.adjustFireLoss(-5, FALSE)
|
||||
owner.adjustOxyLoss(-10)
|
||||
if(!iscarbon(owner))
|
||||
return
|
||||
var/mob/living/carbon/C = owner
|
||||
QDEL_LIST(C.all_scars)
|
||||
|
||||
/obj/screen/alert/status_effect/fleshmend
|
||||
name = "Fleshmend"
|
||||
|
||||
@@ -430,10 +430,19 @@
|
||||
|
||||
/datum/status_effect/neck_slice/tick()
|
||||
var/mob/living/carbon/human/H = owner
|
||||
if(H.stat == DEAD || H.bleed_rate <= 8)
|
||||
var/obj/item/bodypart/throat = H.get_bodypart(BODY_ZONE_HEAD)
|
||||
if(H.stat == DEAD || !throat)
|
||||
H.remove_status_effect(/datum/status_effect/neck_slice)
|
||||
if(prob(10))
|
||||
H.emote(pick("gasp", "gag", "choke"))
|
||||
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)
|
||||
still_bleeding = TRUE
|
||||
break
|
||||
if(!still_bleeding)
|
||||
H.remove_status_effect(/datum/status_effect/neck_slice)
|
||||
|
||||
/mob/living/proc/apply_necropolis_curse(set_curse, duration = 10 MINUTES)
|
||||
var/datum/status_effect/necropolis_curse/C = has_status_effect(STATUS_EFFECT_NECROPOLIS_CURSE)
|
||||
|
||||
@@ -279,3 +279,7 @@
|
||||
/datum/status_effect/grouped/before_remove(source)
|
||||
sources -= source
|
||||
return !length(sources)
|
||||
|
||||
//do_after modifier!
|
||||
/datum/status_effect/proc/interact_speed_modifier()
|
||||
return 1
|
||||
|
||||
186
code/datums/status_effects/wound_effects.dm
Normal file
186
code/datums/status_effects/wound_effects.dm
Normal file
@@ -0,0 +1,186 @@
|
||||
|
||||
// The shattered remnants of your broken limbs fill you with determination!
|
||||
/obj/screen/alert/status_effect/determined
|
||||
name = "Determined"
|
||||
desc = "The serious wounds you've sustained have put your body into fight-or-flight mode! Now's the time to look for an exit!"
|
||||
icon_state = "regenerative_core"
|
||||
|
||||
/datum/status_effect/determined
|
||||
id = "determined"
|
||||
alert_type = /obj/screen/alert/status_effect/determined
|
||||
|
||||
/datum/status_effect/determined/on_apply()
|
||||
. = ..()
|
||||
owner.visible_message("<span class='danger'>[owner] grits [owner.p_their()] teeth in pain!</span>", "<span class='notice'><b>Your senses sharpen as your body tenses up from the wounds you've sustained!</b></span>", vision_distance=COMBAT_MESSAGE_RANGE)
|
||||
|
||||
/datum/status_effect/determined/on_remove()
|
||||
owner.visible_message("<span class='danger'>[owner]'s body slackens noticeably!</span>", "<span class='warning'><b>Your adrenaline rush dies off, and the pain from your wounds come aching back in...</b></span>", vision_distance=COMBAT_MESSAGE_RANGE)
|
||||
return ..()
|
||||
|
||||
/datum/status_effect/limp
|
||||
id = "limp"
|
||||
status_type = STATUS_EFFECT_REPLACE
|
||||
tick_interval = 10
|
||||
alert_type = /obj/screen/alert/status_effect/limp
|
||||
var/msg_stage = 0//so you dont get the most intense messages immediately
|
||||
/// The left leg of the limping person
|
||||
var/obj/item/bodypart/l_leg/left
|
||||
/// The right leg of the limping person
|
||||
var/obj/item/bodypart/r_leg/right
|
||||
/// Which leg we're limping with next
|
||||
var/obj/item/bodypart/next_leg
|
||||
/// How many deciseconds we limp for on the left leg
|
||||
var/slowdown_left = 0
|
||||
/// How many deciseconds we limp for on the right leg
|
||||
var/slowdown_right = 0
|
||||
|
||||
/datum/status_effect/limp/on_apply()
|
||||
if(!iscarbon(owner))
|
||||
return FALSE
|
||||
var/mob/living/carbon/C = owner
|
||||
left = C.get_bodypart(BODY_ZONE_L_LEG)
|
||||
right = C.get_bodypart(BODY_ZONE_R_LEG)
|
||||
update_limp()
|
||||
RegisterSignal(C, COMSIG_MOVABLE_MOVED, .proc/check_step)
|
||||
RegisterSignal(C, list(COMSIG_CARBON_GAIN_WOUND, COMSIG_CARBON_LOSE_WOUND, COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB), .proc/update_limp)
|
||||
return TRUE
|
||||
|
||||
/datum/status_effect/limp/on_remove()
|
||||
UnregisterSignal(owner, list(COMSIG_MOVABLE_MOVED, COMSIG_CARBON_GAIN_WOUND, COMSIG_CARBON_LOSE_WOUND, COMSIG_CARBON_ATTACH_LIMB, COMSIG_CARBON_REMOVE_LIMB))
|
||||
|
||||
/obj/screen/alert/status_effect/limp
|
||||
name = "Limping"
|
||||
desc = "One or more of your legs has been wounded, slowing down steps with that leg! Get it fixed, or at least splinted!"
|
||||
|
||||
/datum/status_effect/limp/proc/check_step(mob/whocares, OldLoc, Dir, forced)
|
||||
if(!owner.client || !(owner.mobility_flags & MOBILITY_STAND) || !owner.has_gravity() || (owner.movement_type & FLYING) || forced)
|
||||
return
|
||||
var/determined_mod = 1
|
||||
if(owner.has_status_effect(STATUS_EFFECT_DETERMINED))
|
||||
determined_mod = 0.25
|
||||
if(next_leg == left)
|
||||
owner.client.move_delay += slowdown_left * determined_mod
|
||||
next_leg = right
|
||||
else
|
||||
owner.client.move_delay += slowdown_right * determined_mod
|
||||
next_leg = left
|
||||
|
||||
/datum/status_effect/limp/proc/update_limp()
|
||||
var/mob/living/carbon/C = owner
|
||||
left = C.get_bodypart(BODY_ZONE_L_LEG)
|
||||
right = C.get_bodypart(BODY_ZONE_R_LEG)
|
||||
|
||||
if(!left && !right)
|
||||
C.remove_status_effect(src)
|
||||
return
|
||||
|
||||
slowdown_left = 0
|
||||
slowdown_right = 0
|
||||
|
||||
if(left)
|
||||
for(var/thing in left.wounds)
|
||||
var/datum/wound/W = thing
|
||||
slowdown_left += W.limp_slowdown
|
||||
|
||||
if(right)
|
||||
for(var/thing in right.wounds)
|
||||
var/datum/wound/W = thing
|
||||
slowdown_right += W.limp_slowdown
|
||||
|
||||
// this handles losing your leg with the limp and the other one being in good shape as well
|
||||
if(!slowdown_left && !slowdown_right)
|
||||
C.remove_status_effect(src)
|
||||
return
|
||||
|
||||
|
||||
/////////////////////////
|
||||
//////// WOUNDS /////////
|
||||
/////////////////////////
|
||||
|
||||
// wound alert
|
||||
/obj/screen/alert/status_effect/wound
|
||||
name = "Wounded"
|
||||
desc = "Your body has sustained serious damage, click here to inspect yourself."
|
||||
|
||||
/obj/screen/alert/status_effect/wound/Click()
|
||||
var/mob/living/carbon/C = usr
|
||||
C.check_self_for_injuries()
|
||||
|
||||
// wound status effect base
|
||||
/datum/status_effect/wound
|
||||
id = "wound"
|
||||
status_type = STATUS_EFFECT_MULTIPLE
|
||||
var/obj/item/bodypart/linked_limb
|
||||
var/datum/wound/linked_wound
|
||||
alert_type = NONE
|
||||
|
||||
/datum/status_effect/wound/on_creation(mob/living/new_owner, incoming_wound)
|
||||
. = ..()
|
||||
var/datum/wound/W = incoming_wound
|
||||
linked_wound = W
|
||||
linked_limb = linked_wound.limb
|
||||
|
||||
/datum/status_effect/wound/on_remove()
|
||||
linked_wound = null
|
||||
linked_limb = null
|
||||
UnregisterSignal(owner, COMSIG_CARBON_LOSE_WOUND)
|
||||
|
||||
/datum/status_effect/wound/on_apply()
|
||||
if(!iscarbon(owner))
|
||||
return FALSE
|
||||
RegisterSignal(owner, COMSIG_CARBON_LOSE_WOUND, .proc/check_remove)
|
||||
return TRUE
|
||||
|
||||
/// check if the wound getting removed is the wound we're tied to
|
||||
/datum/status_effect/wound/proc/check_remove(mob/living/L, datum/wound/W)
|
||||
if(W == linked_wound)
|
||||
qdel(src)
|
||||
|
||||
|
||||
// bones
|
||||
/datum/status_effect/wound/bone
|
||||
|
||||
/datum/status_effect/wound/bone/interact_speed_modifier()
|
||||
var/mob/living/carbon/C = owner
|
||||
|
||||
if(C.get_active_hand() == linked_limb)
|
||||
to_chat(C, "<span class='warning'>The [lowertext(linked_wound)] in your [linked_limb.name] slows your progress!</span>")
|
||||
return linked_wound.interaction_efficiency_penalty
|
||||
|
||||
return 1
|
||||
|
||||
/datum/status_effect/wound/bone/nextmove_modifier()
|
||||
var/mob/living/carbon/C = owner
|
||||
|
||||
if(C.get_active_hand() == linked_limb)
|
||||
return linked_wound.interaction_efficiency_penalty
|
||||
|
||||
return 1
|
||||
|
||||
/datum/status_effect/wound/bone/moderate
|
||||
id = "disjoint"
|
||||
/datum/status_effect/wound/bone/severe
|
||||
id = "hairline"
|
||||
|
||||
/datum/status_effect/wound/bone/critical
|
||||
id = "compound"
|
||||
|
||||
// cuts
|
||||
/datum/status_effect/wound/cut/moderate
|
||||
id = "abrasion"
|
||||
|
||||
/datum/status_effect/wound/cut/severe
|
||||
id = "laceration"
|
||||
|
||||
/datum/status_effect/wound/cut/critical
|
||||
id = "avulsion"
|
||||
|
||||
// burns
|
||||
/datum/status_effect/wound/burn/moderate
|
||||
id = "seconddeg"
|
||||
|
||||
/datum/status_effect/wound/burn/severe
|
||||
id = "thirddeg"
|
||||
|
||||
/datum/status_effect/wound/burn/critical
|
||||
id = "fourthdeg"
|
||||
@@ -122,3 +122,19 @@
|
||||
if(H)
|
||||
var/datum/species/species = H.dna.species
|
||||
species.disliked_food &= ~ALCOHOL
|
||||
|
||||
/datum/quirk/longtimer
|
||||
name = "Longtimer"
|
||||
desc = "You've been around for a long time and seen more than your fair share of action, suffering some pretty nasty scars along the way. For whatever reason, you've declined to get them removed or augmented."
|
||||
value = 0
|
||||
gain_text = "<span class='notice'>Your body has seen better days.</span>"
|
||||
lose_text = "<span class='notice'>Your sins may wash away, but those scars are here to stay...</span>"
|
||||
medical_record_text = "Patient has withstood significant physical trauma and declined plastic surgery procedures to heal scarring."
|
||||
/// the minimum amount of scars we can generate
|
||||
var/min_scars = 3
|
||||
/// the maximum amount of scars we can generate
|
||||
var/max_scars = 7
|
||||
|
||||
/datum/quirk/longtimer/on_spawn()
|
||||
var/mob/living/carbon/C = quirk_holder
|
||||
C.generate_fake_scars(rand(min_scars, max_scars))
|
||||
|
||||
134
code/datums/wounds/_scars.dm
Normal file
134
code/datums/wounds/_scars.dm
Normal file
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
* scars are cosmetic datums that are assigned to bodyparts once they recover from wounds. Each wound type and severity have their own descriptions for what the scars
|
||||
* look like, and then each body part has a list of "specific locations" like your elbow or wrist or wherever the scar can appear, to make it more interesting than "right arm"
|
||||
*
|
||||
*
|
||||
* Arguments:
|
||||
* *
|
||||
*/
|
||||
/datum/scar
|
||||
var/obj/item/bodypart/limb
|
||||
var/mob/living/carbon/victim
|
||||
var/severity
|
||||
var/description
|
||||
var/precise_location
|
||||
|
||||
/// Scars from the longtimer quirk are "fake" and won't be saved with persistent scarring, since it makes you spawn with a lot by default
|
||||
var/fake=FALSE
|
||||
|
||||
/// How many tiles away someone can see this scar, goes up with severity. Clothes covering this limb will decrease visibility by 1 each, except for the head/face which is a binary "is mask obscuring face" check
|
||||
var/visibility = 2
|
||||
/// Whether this scar can actually be covered up by clothing
|
||||
var/coverable = TRUE
|
||||
/// What zones this scar can be applied to
|
||||
var/list/applicable_zones = list(BODY_ZONE_CHEST, BODY_ZONE_HEAD, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_ARM, BODY_ZONE_R_LEG)
|
||||
|
||||
/datum/scar/Destroy(force, ...)
|
||||
if(limb)
|
||||
LAZYREMOVE(limb.scars, src)
|
||||
if(victim)
|
||||
LAZYREMOVE(victim.all_scars, src)
|
||||
. = ..()
|
||||
|
||||
/**
|
||||
* generate() is used to actually fill out the info for a scar, according to the limb and wound it is provided.
|
||||
*
|
||||
* After creating a scar, call this on it while targeting the scarred bodypart with a given wound to apply the scar.
|
||||
*
|
||||
* Arguments:
|
||||
* * BP- The bodypart being targeted
|
||||
* * W- The wound being used to generate the severity and description info
|
||||
* * add_to_scars- Should always be TRUE unless you're just storing a scar for later usage, like how cuts want to store a scar for the highest severity of cut, rather than the severity when the wound is fully healed (probably demoted to moderate)
|
||||
*/
|
||||
/datum/scar/proc/generate(obj/item/bodypart/BP, datum/wound/W, add_to_scars=TRUE)
|
||||
if(!(BP.body_zone in applicable_zones))
|
||||
qdel(src)
|
||||
return
|
||||
limb = BP
|
||||
severity = W.severity
|
||||
if(limb.owner)
|
||||
victim = limb.owner
|
||||
if(add_to_scars)
|
||||
LAZYADD(limb.scars, src)
|
||||
if(victim)
|
||||
LAZYADD(victim.all_scars, src)
|
||||
|
||||
description = pick(W.scarring_descriptions)
|
||||
precise_location = pick(limb.specific_locations)
|
||||
switch(W.severity)
|
||||
if(WOUND_SEVERITY_MODERATE)
|
||||
visibility = 2
|
||||
if(WOUND_SEVERITY_SEVERE)
|
||||
visibility = 3
|
||||
if(WOUND_SEVERITY_CRITICAL)
|
||||
visibility = 5
|
||||
|
||||
/// Used when we finalize a scar from a healing cut
|
||||
/datum/scar/proc/lazy_attach(obj/item/bodypart/BP, datum/wound/W)
|
||||
LAZYADD(BP.scars, src)
|
||||
if(BP.owner)
|
||||
victim = BP.owner
|
||||
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))
|
||||
qdel(src)
|
||||
return
|
||||
limb = BP
|
||||
src.severity = severity
|
||||
LAZYADD(limb.scars, src)
|
||||
if(BP.owner)
|
||||
victim = BP.owner
|
||||
LAZYADD(victim.all_scars, src)
|
||||
src.description = description
|
||||
precise_location = specific_location
|
||||
switch(severity)
|
||||
if(WOUND_SEVERITY_MODERATE)
|
||||
visibility = 2
|
||||
if(WOUND_SEVERITY_SEVERE)
|
||||
visibility = 3
|
||||
if(WOUND_SEVERITY_CRITICAL)
|
||||
visibility = 5
|
||||
return TRUE
|
||||
|
||||
/// What will show up in examine_more() if this scar is visible
|
||||
/datum/scar/proc/get_examine_description(mob/viewer)
|
||||
if(!victim || !is_visible(viewer))
|
||||
return
|
||||
|
||||
var/msg = "[victim.p_they(TRUE)] [victim.p_have()] [description] on [victim.p_their()] [precise_location]."
|
||||
switch(severity)
|
||||
if(WOUND_SEVERITY_MODERATE)
|
||||
msg = "<span class='tinynotice'>[msg]</span>"
|
||||
if(WOUND_SEVERITY_SEVERE)
|
||||
msg = "<span class='smallnotice'>[msg]</span>"
|
||||
if(WOUND_SEVERITY_CRITICAL)
|
||||
msg = "<span class='smallnotice'><b>[msg]</b></span>"
|
||||
return "\t[msg]"
|
||||
|
||||
/// Whether a scar can currently be seen by the viewer
|
||||
/datum/scar/proc/is_visible(mob/viewer)
|
||||
if(!victim || !viewer)
|
||||
return
|
||||
if(get_dist(viewer, victim) > visibility)
|
||||
return
|
||||
|
||||
if(!ishuman(victim) || isobserver(viewer) || victim == viewer)
|
||||
return TRUE
|
||||
|
||||
var/mob/living/carbon/human/H = 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)))
|
||||
return FALSE
|
||||
else if(limb.scars_covered_by_clothes)
|
||||
var/num_covers = LAZYLEN(H.clothingonpart(limb))
|
||||
if(num_covers + get_dist(viewer, victim) >= visibility)
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/// 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]"
|
||||
309
code/datums/wounds/cuts.dm
Normal file
309
code/datums/wounds/cuts.dm
Normal file
@@ -0,0 +1,309 @@
|
||||
|
||||
/*
|
||||
Cuts
|
||||
*/
|
||||
|
||||
/datum/wound/brute/cut
|
||||
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)
|
||||
treatable_by_grabbed = list(/obj/item/gun/energy/laser)
|
||||
treatable_tool = TOOL_CAUTERY
|
||||
treat_priority = TRUE
|
||||
base_treat_time = 3 SECONDS
|
||||
|
||||
/// How much blood we start losing when this wound is first applied
|
||||
var/initial_flow
|
||||
/// When we have less than this amount of flow, either from treatment or clotting, we demote to a lower cut or are healed of the wound
|
||||
var/minimum_flow
|
||||
/// How fast our blood flow will naturally decrease per tick, not only do larger cuts bleed more faster, they clot slower
|
||||
var/clot_rate
|
||||
|
||||
/// Once the blood flow drops below minimum_flow, we demote it to this type of wound. If there's none, we're all better
|
||||
var/demotes_to
|
||||
|
||||
/// How much staunching per type (cautery, suturing, bandaging) you can have before that type is no longer effective for this cut NOT IMPLEMENTED
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
return ..()
|
||||
|
||||
var/bandage_condition = ""
|
||||
// how much life we have left in these bandages
|
||||
switch(current_bandage.absorption_capacity)
|
||||
if(0 to 1.25)
|
||||
bandage_condition = "nearly ruined "
|
||||
if(1.25 to 2.75)
|
||||
bandage_condition = "badly worn "
|
||||
if(2.75 to 4)
|
||||
bandage_condition = "slightly bloodied "
|
||||
if(4 to INFINITY)
|
||||
bandage_condition = "clean "
|
||||
return "<B>The cuts on [victim.p_their()] [limb.name] are wrapped with [bandage_condition] [current_bandage.name]!</B>"
|
||||
|
||||
/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
|
||||
blood_flow += 0.05 * wounding_dmg
|
||||
|
||||
/datum/wound/brute/cut/handle_process()
|
||||
blood_flow = min(blood_flow, WOUND_CUT_MAX_BLOODFLOW)
|
||||
|
||||
if(victim.reagents && 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(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("<span class='danger'>Blood soaks through \the [current_bandage] on [victim]'s [limb.name].</span>", "<span class='warning'>Blood soaks through \the [current_bandage] on your [limb.name].</span>", vision_distance=COMBAT_MESSAGE_RANGE)
|
||||
QDEL_NULL(current_bandage)
|
||||
treat_priority = TRUE
|
||||
else
|
||||
blood_flow -= clot_rate
|
||||
|
||||
if(blood_flow > highest_flow)
|
||||
highest_flow = blood_flow
|
||||
|
||||
if(blood_flow < minimum_flow)
|
||||
if(demotes_to)
|
||||
replace_wound(demotes_to)
|
||||
else
|
||||
to_chat(victim, "<span class='green'>The cut on your [limb.name] has stopped bleeding!</span>")
|
||||
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)
|
||||
if(istype(I, /obj/item/gun/energy/laser))
|
||||
return TRUE
|
||||
|
||||
/datum/wound/brute/cut/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)
|
||||
if(user.pulling != victim || user.zone_selected != limb.body_zone || user.a_intent == INTENT_GRAB)
|
||||
return FALSE
|
||||
|
||||
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)
|
||||
if(INTERACTING_WITH(user, victim))
|
||||
to_chat(user, "<span class='warning'>You're already interacting with [victim]!</span>")
|
||||
return
|
||||
|
||||
user.visible_message("<span class='notice'>[user] begins licking the wounds on [victim]'s [limb.name].</span>", "<span class='notice'>You begin licking the wounds on [victim]'s [limb.name]...</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='notice'>[user] begins to lick the wounds on your [limb.name].</span")
|
||||
if(!do_after(user, base_treat_time, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
|
||||
user.visible_message("<span class='notice'>[user] licks the wounds on [victim]'s [limb.name].</span>", "<span class='notice'>You lick some of the wounds on [victim]'s [limb.name]</span>", ignored_mobs=victim)
|
||||
to_chat(victim, "<span class='green'>[user] licks the wounds on your [limb.name]!</span")
|
||||
blood_flow -= 0.5
|
||||
|
||||
if(blood_flow > minimum_flow)
|
||||
try_handling(user)
|
||||
else if(demotes_to)
|
||||
to_chat(user, "<span class='green'>You successfully lower the severity of [victim]'s cuts.</span>")
|
||||
|
||||
/datum/wound/brute/cut/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
|
||||
|
||||
/// 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)
|
||||
var/self_penalty_mult = (user == victim ? 1.25 : 1)
|
||||
user.visible_message("<span class='warning'>[user] begins aiming [lasgun] directly at [victim]'s [limb.name]...</span>", "<span class='userdanger'>You begin aiming [lasgun] directly at [user == victim ? "your" : "[victim]'s"] [limb.name]...</span>")
|
||||
if(!do_after(user, base_treat_time * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
var/damage = lasgun.chambered.BB.damage
|
||||
lasgun.chambered.BB.wound_bonus -= 30
|
||||
lasgun.chambered.BB.damage *= self_penalty_mult
|
||||
if(!lasgun.process_fire(victim, victim, TRUE, null, limb.body_zone))
|
||||
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("<span class='warning'>The cuts on [victim]'s [limb.name] scar over!</span>")
|
||||
|
||||
/// 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)
|
||||
var/self_penalty_mult = (user == victim ? 1.5 : 1)
|
||||
user.visible_message("<span class='danger'>[user] begins cauterizing [victim]'s [limb.name] with [I]...</span>", "<span class='danger'>You begin cauterizing [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
|
||||
var/time_mod = user.mind?.get_skill_modifier(/datum/skill/healing, SKILL_SPEED_MODIFIER) || 1
|
||||
if(!do_after(user, base_treat_time * time_mod * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
|
||||
user.visible_message("<span class='green'>[user] cauterizes some of the bleeding on [victim].</span>", "<span class='green'>You cauterize some of the bleeding on [victim].</span>")
|
||||
limb.receive_damage(burn = 2 + severity, wound_bonus = CANT_WOUND)
|
||||
if(prob(30))
|
||||
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)
|
||||
else if(demotes_to)
|
||||
to_chat(user, "<span class='green'>You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.</span>")
|
||||
|
||||
/// If someone is using a suture to close this cut
|
||||
/datum/wound/brute/cut/proc/suture(obj/item/stack/medical/suture/I, mob/user)
|
||||
var/self_penalty_mult = (user == victim ? 1.4 : 1)
|
||||
user.visible_message("<span class='notice'>[user] begins stitching [victim]'s [limb.name] with [I]...</span>", "<span class='notice'>You begin stitching [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
|
||||
var/time_mod = user.mind?.get_skill_modifier(/datum/skill/healing, SKILL_SPEED_MODIFIER) || 1
|
||||
if(!do_after(user, base_treat_time * time_mod * self_penalty_mult, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
user.visible_message("<span class='green'>[user] stitches up some of the bleeding on [victim].</span>", "<span class='green'>You stitch up some of the bleeding on [user == victim ? "yourself" : "[victim]"].</span>")
|
||||
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)
|
||||
try_treating(I, user)
|
||||
else if(demotes_to)
|
||||
to_chat(user, "<span class='green'>You successfully lower the severity of [user == victim ? "your" : "[victim]'s"] cuts.</span>")
|
||||
|
||||
/// 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, "<span class='warning'>The [current_bandage] on [victim]'s [limb.name] is still in better condition than your [I.name]!</span>")
|
||||
return
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] begins rewrapping the cuts on [victim]'s [limb.name] with [I]...</span>", "<span class='warning'>You begin rewrapping the cuts on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
|
||||
else
|
||||
user.visible_message("<span class='warning'>[user] begins wrapping the cuts on [victim]'s [limb.name] with [I]...</span>", "<span class='warning'>You begin wrapping the cuts on [user == victim ? "your" : "[victim]'s"] [limb.name] with [I]...</span>")
|
||||
var/time_mod = user.mind?.get_skill_modifier(/datum/skill/healing, SKILL_SPEED_MODIFIER) || 1
|
||||
if(!do_after(user, base_treat_time * time_mod, target=victim, extra_checks = CALLBACK(src, .proc/still_exists)))
|
||||
return
|
||||
|
||||
user.visible_message("<span class='green'>[user] applies [I] to [victim]'s [limb.name].</span>", "<span class='green'>You bandage some of the bleeding on [user == victim ? "yourself" : "[victim]"].</span>")
|
||||
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
|
||||
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'
|
||||
severity = WOUND_SEVERITY_MODERATE
|
||||
initial_flow = 2
|
||||
minimum_flow = 0.5
|
||||
max_per_type = 3
|
||||
clot_rate = 0.15
|
||||
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")
|
||||
|
||||
/datum/wound/brute/cut/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'
|
||||
severity = WOUND_SEVERITY_SEVERE
|
||||
initial_flow = 3.25
|
||||
minimum_flow = 2.75
|
||||
clot_rate = 0.07
|
||||
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")
|
||||
|
||||
/datum/wound/brute/cut/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"
|
||||
occur_text = "is torn open, spraying blood wildly"
|
||||
sound_effect = 'sound/effects/blood3.ogg'
|
||||
severity = WOUND_SEVERITY_CRITICAL
|
||||
initial_flow = 4.25
|
||||
minimum_flow = 4
|
||||
clot_rate = -0.05 // critical cuts actively get worse instead of better
|
||||
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)
|
||||
@@ -982,6 +982,37 @@ Proc for attack log creation, because really why not
|
||||
var/reverse_message = "has been [what_done] by [ssource][postfix]"
|
||||
target.log_message(reverse_message, LOG_ATTACK, color="orange", log_globally=FALSE)
|
||||
|
||||
/**
|
||||
* log_wound() is for when someone is *attacked* and suffers a wound. Note that this only captures wounds from damage, so smites/forced wounds aren't logged, as well as demotions like cuts scabbing over
|
||||
*
|
||||
* Note that this has no info on the attack that dealt the wound: information about where damage came from isn't passed to the bodypart's damaged proc. When in doubt, check the attack log for attacks at that same time
|
||||
* TODO later: Add logging for healed wounds, though that will require some rewriting of healing code to prevent admin heals from spamming the logs. Not high priority
|
||||
*
|
||||
* Arguments:
|
||||
* * victim- The guy who got wounded
|
||||
* * suffered_wound- The wound, already applied, that we're logging. It has to already be attached so we can get the limb from it
|
||||
* * dealt_damage- How much damage is associated with the attack that dealt with this wound.
|
||||
* * dealt_wound_bonus- The wound_bonus, if one was specified, of the wounding attack
|
||||
* * dealt_bare_wound_bonus- The bare_wound_bonus, if one was specified *and applied*, of the wounding attack. Not shown if armor was present
|
||||
* * base_roll- Base wounding ability of an attack is a random number from 1 to (dealt_damage ** WOUND_DAMAGE_EXPONENT). This is the number that was rolled in there, before mods
|
||||
*/
|
||||
/proc/log_wound(atom/victim, datum/wound/suffered_wound, dealt_damage, dealt_wound_bonus, dealt_bare_wound_bonus, base_roll)
|
||||
var/message = "has suffered: [suffered_wound] to [suffered_wound.limb.name]" // maybe indicate if it's a promote/demote?
|
||||
|
||||
if(dealt_damage)
|
||||
message += " | Damage: [dealt_damage]"
|
||||
// The base roll is useful since it can show how lucky someone got with the given attack. For example, dealing a cut
|
||||
if(base_roll)
|
||||
message += "(rolled [base_roll]/[dealt_damage ** WOUND_DAMAGE_EXPONENT])"
|
||||
|
||||
if(dealt_wound_bonus)
|
||||
message += " | WB: [dealt_wound_bonus]"
|
||||
|
||||
if(dealt_bare_wound_bonus)
|
||||
message += " | BWB: [dealt_bare_wound_bonus]"
|
||||
|
||||
victim.log_message(message, LOG_ATTACK, color="blue")
|
||||
|
||||
// Filter stuff
|
||||
/atom/proc/add_filter(name,priority,list/params)
|
||||
LAZYINITLIST(filter_data)
|
||||
|
||||
@@ -343,6 +343,10 @@
|
||||
/obj/machinery/door/proc/crush()
|
||||
for(var/mob/living/L in get_turf(src))
|
||||
L.visible_message("<span class='warning'>[src] closes on [L], crushing [L.p_them()]!</span>", "<span class='userdanger'>[src] closes on you and crushes you!</span>")
|
||||
if(iscarbon(L))
|
||||
var/mob/living/carbon/C = L
|
||||
for(var/datum/wound/W in C.all_wounds)
|
||||
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.
|
||||
L.emote("roar")
|
||||
|
||||
@@ -183,9 +183,21 @@
|
||||
var/T = get_turf(target)
|
||||
if(locate(/mob/living) in T)
|
||||
new /obj/effect/temp_visual/medical_holosign(T,user) //produce a holographic glow
|
||||
holo_cooldown = world.time + 100
|
||||
holo_cooldown = world.time + 10 SECONDS
|
||||
return
|
||||
|
||||
// see: [/datum/wound/burn/proc/uv()]
|
||||
/obj/item/flashlight/pen/paramedic
|
||||
name = "paramedic penlight"
|
||||
desc = "A high-powered UV penlight intended to help stave off infection in the field on serious burned patients. Probably really bad to look into."
|
||||
icon_state = "penlight_surgical"
|
||||
/// Our current UV cooldown
|
||||
var/uv_cooldown = 0
|
||||
/// How long between UV fryings
|
||||
var/uv_cooldown_length = 1 MINUTES
|
||||
/// How much sanitization to apply to the burn wound
|
||||
var/uv_power = 1
|
||||
|
||||
/obj/effect/temp_visual/medical_holosign
|
||||
name = "medical holosign"
|
||||
desc = "A small holographic glow that indicates a medic is coming to treat a patient."
|
||||
|
||||
@@ -10,6 +10,14 @@ NANITE SCANNER
|
||||
GENETICS SCANNER
|
||||
|
||||
*/
|
||||
|
||||
// Describes the three modes of scanning available for health analyzers
|
||||
#define SCANMODE_HEALTH 0
|
||||
#define SCANMODE_CHEMICAL 1
|
||||
#define SCANMODE_WOUND 2
|
||||
#define SCANNER_CONDENSED 0
|
||||
#define SCANNER_VERBOSE 1
|
||||
|
||||
/obj/item/t_scanner
|
||||
name = "\improper T-ray scanner"
|
||||
desc = "A terahertz-ray emitter and scanner used to detect underfloor objects such as cables and pipes."
|
||||
@@ -80,7 +88,7 @@ GENETICS SCANNER
|
||||
throw_range = 7
|
||||
custom_materials = list(/datum/material/iron=200)
|
||||
var/mode = 1
|
||||
var/scanmode = 0
|
||||
var/scanmode = SCANMODE_HEALTH
|
||||
var/advanced = FALSE
|
||||
|
||||
/obj/item/healthanalyzer/suicide_act(mob/living/carbon/user)
|
||||
@@ -88,37 +96,40 @@ GENETICS SCANNER
|
||||
return BRUTELOSS
|
||||
|
||||
/obj/item/healthanalyzer/attack_self(mob/user)
|
||||
if(!scanmode)
|
||||
to_chat(user, "<span class='notice'>You switch the health analyzer to scan chemical contents.</span>")
|
||||
scanmode = 1
|
||||
else
|
||||
to_chat(user, "<span class='notice'>You switch the health analyzer to check physical health.</span>")
|
||||
scanmode = 0
|
||||
scanmode = (scanmode + 1) % 3
|
||||
switch(scanmode)
|
||||
if(SCANMODE_HEALTH)
|
||||
to_chat(user, "<span class='notice'>You switch the health analyzer to check physical health.</span>")
|
||||
if(SCANMODE_CHEMICAL)
|
||||
to_chat(user, "<span class='notice'>You switch the health analyzer to scan chemical contents.</span>")
|
||||
if(SCANMODE_WOUND)
|
||||
to_chat(user, "<span class='notice'>You switch the health analyzer to report extra info on wounds.</span>")
|
||||
|
||||
/obj/item/healthanalyzer/attack(mob/living/M, mob/living/carbon/human/user)
|
||||
flick("[icon_state]-scan", src) //makes it so that it plays the scan animation upon scanning, including clumsy scanning
|
||||
|
||||
// Clumsiness/brain damage check
|
||||
if ((HAS_TRAIT(user, TRAIT_CLUMSY) || HAS_TRAIT(user, TRAIT_DUMB)) && prob(50))
|
||||
to_chat(user, "<span class='notice'>You stupidly try to analyze the floor's vitals!</span>")
|
||||
user.visible_message("<span class='warning'>[user] has analyzed the floor's vitals!</span>")
|
||||
var/msg = "<span class='info'>*---------*\nAnalyzing results for The floor:\n\tOverall status: <b>Healthy</b>\n"
|
||||
msg += "Key: <font color='blue'>Suffocation</font>/<font color='green'>Toxin</font>/<font color='#FF8000'>Burn</font>/<font color='red'>Brute</font>\n"
|
||||
msg += "\tDamage specifics: <font color='blue'>0</font>-<font color='green'>0</font>-<font color='#FF8000'>0</font>-<font color='red'>0</font>\n"
|
||||
msg += "Body temperature: ???\n"
|
||||
msg += "*---------*</span>"
|
||||
to_chat(user, msg)
|
||||
user.visible_message("<span class='warning'>[user] analyzes the floor's vitals!</span>", \
|
||||
"<span class='notice'>You stupidly try to analyze the floor's vitals!</span>")
|
||||
to_chat(user, "<span class='info'>Analyzing results for The floor:\n\tOverall status: <b>Healthy</b></span>\
|
||||
\n<span class='info'>Key: <font color='blue'>Suffocation</font>/<font color='green'>Toxin</font>/<font color='#FF8000'>Burn</font>/<font color='red'>Brute</font></span>\
|
||||
\n<span class='info'>\tDamage specifics: <font color='blue'>0</font>-<font color='green'>0</font>-<font color='#FF8000'>0</font>-<font color='red'>0</font></span>\
|
||||
\n<span class='info'>Body temperature: ???</span>")
|
||||
return
|
||||
|
||||
user.visible_message("<span class='notice'>[user] has analyzed [M]'s vitals.</span>")
|
||||
user.visible_message("<span class='notice'>[user] analyzes [M]'s vitals.</span>", \
|
||||
"<span class='notice'>You analyze [M]'s vitals.</span>")
|
||||
|
||||
if(scanmode == 0)
|
||||
if(scanmode == SCANMODE_HEALTH)
|
||||
healthscan(user, M, mode, advanced)
|
||||
else if(scanmode == 1)
|
||||
else if(scanmode == SCANMODE_CHEMICAL)
|
||||
chemscan(user, M)
|
||||
else
|
||||
woundscan(user, M, src)
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
|
||||
// Used by the PDA medical scanner too
|
||||
/proc/healthscan(mob/user, mob/living/M, mode = 1, advanced = FALSE)
|
||||
if(isliving(user) && (user.incapacitated() || user.eye_blind))
|
||||
@@ -402,6 +413,17 @@ GENETICS SCANNER
|
||||
msg += "<span class='danger'> Intervention recommended.</span>\n"
|
||||
else
|
||||
msg += "\n"
|
||||
// Wounds
|
||||
if(iscarbon(M))
|
||||
var/mob/living/carbon/C = M
|
||||
var/list/wounded_parts = C.get_wounded_bodyparts()
|
||||
for(var/i in wounded_parts)
|
||||
var/obj/item/bodypart/wounded_part = i
|
||||
msg += "<span class='alert ml-1'><b>Warning: Physical trauma[LAZYLEN(wounded_part.wounds) > 1? "s" : ""] detected in [wounded_part.name]</b>"
|
||||
for(var/k in wounded_part.wounds)
|
||||
var/datum/wound/W = k
|
||||
msg += "<div class='ml-2'>Type: [W.name]\nSeverity: [W.severity_text()]\nRecommended Treatment: [W.treat_text]</div>\n" // less lines than in woundscan() so we don't overload people trying to get basic med info
|
||||
msg += "</span>\n"
|
||||
|
||||
for(var/thing in M.diseases)
|
||||
var/datum/disease/D = thing
|
||||
@@ -414,7 +436,7 @@ GENETICS SCANNER
|
||||
var/blood_typepath = C.get_blood_id()
|
||||
if(blood_typepath)
|
||||
if(ishuman(C))
|
||||
if(H.bleed_rate)
|
||||
if(H.is_bleeding())
|
||||
msg += "<span class='danger'>Subject is bleeding!</span>\n"
|
||||
var/blood_percent = round((C.scan_blood_volume() / (BLOOD_VOLUME_NORMAL * C.blood_ratio))*100)
|
||||
var/blood_type = C.dna.blood_type
|
||||
@@ -505,6 +527,63 @@ GENETICS SCANNER
|
||||
desc = "A hand-held body scanner able to distinguish vital signs of the subject with high accuracy."
|
||||
advanced = TRUE
|
||||
|
||||
/// Displays wounds with extended information on their status vs medscanners
|
||||
/proc/woundscan(mob/user, mob/living/carbon/patient, obj/item/healthanalyzer/wound/scanner)
|
||||
if(!istype(patient))
|
||||
return
|
||||
|
||||
var/render_list = ""
|
||||
for(var/i in patient.get_wounded_bodyparts())
|
||||
var/obj/item/bodypart/wounded_part = i
|
||||
render_list += "<span class='alert ml-1'><b>Warning: Physical trauma[LAZYLEN(wounded_part.wounds) > 1? "s" : ""] detected in [wounded_part.name]</b>"
|
||||
for(var/k in wounded_part.wounds)
|
||||
var/datum/wound/W = k
|
||||
render_list += "<div class='ml-2'>[W.get_scanner_description()]</div>\n"
|
||||
render_list += "</span>"
|
||||
|
||||
if(render_list == "")
|
||||
playsound(scanner, 'sound/machines/ping.ogg', 50, FALSE)
|
||||
to_chat(user, "<span class='notice'>\The [scanner] makes a happy ping and briefly displays a smiley face with several exclamation points! It's really excited to report that [patient] has no wounds!</span>")
|
||||
else
|
||||
to_chat(user, jointext(render_list, ""))
|
||||
|
||||
/obj/item/healthanalyzer/wound
|
||||
name = "first aid analyzer"
|
||||
icon_state = "adv_spectrometer"
|
||||
desc = "A prototype MeLo-Tech medical scanner used to diagnose injuries and recommend treatment for serious wounds, but offers no further insight into the patient's health. You hope the final version is less annoying to read!"
|
||||
var/next_encouragement
|
||||
var/greedy
|
||||
|
||||
/obj/item/healthanalyzer/wound/attack_self(mob/user)
|
||||
if(next_encouragement < world.time)
|
||||
playsound(src, 'sound/machines/ping.ogg', 50, FALSE)
|
||||
var/list/encouragements = list("briefly displays a happy face, gazing emptily at you", "briefly displays a spinning cartoon heart", "displays an encouraging message about eating healthy and exercising", \
|
||||
"reminds you that everyone is doing their best", "displays a message wishing you well", "displays a sincere thank-you for your interest in first-aid", "formally absolves you of all your sins")
|
||||
to_chat(user, "<span class='notice'>\The [src] makes a happy ping and [pick(encouragements)]!</span>")
|
||||
next_encouragement = world.time + 10 SECONDS
|
||||
greedy = FALSE
|
||||
else if(!greedy)
|
||||
to_chat(user, "<span class='warning'>\The [src] displays an eerily high-definition frowny face, chastizing you for asking it for too much encouragement.</span>")
|
||||
greedy = TRUE
|
||||
else
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 50, FALSE)
|
||||
if(isliving(user))
|
||||
var/mob/living/L = user
|
||||
to_chat(L, "<span class='warning'>\The [src] makes a disappointed buzz and pricks your finger for being greedy. Ow!</span>")
|
||||
L.adjustBruteLoss(4)
|
||||
L.dropItemToGround(src)
|
||||
|
||||
/obj/item/healthanalyzer/wound/attack(mob/living/carbon/patient, mob/living/carbon/human/user)
|
||||
add_fingerprint(user)
|
||||
user.visible_message("<span class='notice'>[user] scans [patient] for serious injuries.</span>", "<span class='notice'>You scan [patient] for serious injuries.</span>")
|
||||
|
||||
if(!istype(patient))
|
||||
playsound(src, 'sound/machines/buzz-sigh.ogg', 30, TRUE)
|
||||
to_chat(user, "<span class='notice'>\The [src] makes a sad buzz and briefly displays a frowny face, indicating it can't scan [patient].</span>")
|
||||
return
|
||||
|
||||
woundscan(user, patient, src)
|
||||
|
||||
/obj/item/analyzer
|
||||
desc = "A hand-held environmental scanner which reports current gas levels. Alt-Click to use the built in barometer function."
|
||||
name = "analyzer"
|
||||
@@ -878,3 +957,9 @@ GENETICS SCANNER
|
||||
return "[HM.name] ([HM.alias])"
|
||||
else
|
||||
return HM.alias
|
||||
|
||||
#undef SCANMODE_HEALTH
|
||||
#undef SCANMODE_CHEMICAL
|
||||
#undef SCANMODE_WOUND
|
||||
#undef SCANNER_CONDENSED
|
||||
#undef SCANNER_VERBOSE
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
max_integrity = 200
|
||||
armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 70)
|
||||
resistance_flags = FIRE_PROOF
|
||||
wound_bonus = -110
|
||||
bare_wound_bonus = 20
|
||||
block_parry_data = /datum/block_parry_data/dual_esword
|
||||
var/hacked = FALSE
|
||||
/// Can this reflect all energy projectiles?
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
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
|
||||
var/wielded = FALSE // track wielded status on item
|
||||
|
||||
/obj/item/fireaxe/Initialize()
|
||||
|
||||
@@ -60,6 +60,14 @@
|
||||
shrapnel_type = /obj/item/projectile/bullet/pellet/stingball/mega
|
||||
shrapnel_radius = 12
|
||||
|
||||
/obj/item/grenade/stingbang/breaker
|
||||
name = "breakbang"
|
||||
shrapnel_type = /obj/projectile/bullet/pellet/stingball/breaker
|
||||
|
||||
/obj/item/grenade/stingbang/shred
|
||||
name = "shredbang"
|
||||
shrapnel_type = /obj/projectile/bullet/pellet/stingball/shred
|
||||
|
||||
/obj/item/grenade/stingbang/prime(mob/living/lanced_by)
|
||||
if(iscarbon(loc))
|
||||
var/mob/living/carbon/C = loc
|
||||
|
||||
@@ -225,6 +225,7 @@
|
||||
throwforce = 10
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
obj_flags = UNIQUE_RENAME
|
||||
wound_bonus = -10
|
||||
var/chaplain_spawnable = TRUE
|
||||
total_mass = TOTAL_MASS_MEDIEVAL_WEAPON
|
||||
|
||||
@@ -657,6 +658,8 @@
|
||||
item_flags = ABSTRACT
|
||||
w_class = WEIGHT_CLASS_HUGE
|
||||
sharpness = IS_SHARP
|
||||
wound_bonus = -20
|
||||
bare_wound_bonus = 25
|
||||
total_mass = TOTAL_MASS_HAND_REPLACEMENT
|
||||
|
||||
/obj/item/nullrod/armblade/Initialize()
|
||||
|
||||
@@ -79,6 +79,8 @@
|
||||
sharpness = IS_SHARP_ACCURATE
|
||||
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
|
||||
bare_wound_bonus = 10
|
||||
custom_price = PRICE_NORMAL
|
||||
|
||||
/obj/item/kitchen/knife/Initialize()
|
||||
|
||||
@@ -506,7 +506,9 @@
|
||||
if(prob(50))
|
||||
step(W, pick(GLOB.alldirs))
|
||||
ADD_TRAIT(H, TRAIT_DISFIGURED, TRAIT_GENERIC)
|
||||
H.bleed_rate = 5
|
||||
for(var/i in H.bodyparts)
|
||||
var/obj/item/bodypart/BP = i
|
||||
BP.generic_bleedstacks += 5
|
||||
H.gib_animation()
|
||||
sleep(3)
|
||||
H.adjustBruteLoss(1000) //to make the body super-bloody
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
force = 14
|
||||
throwforce = 10
|
||||
wound_bonus = 15
|
||||
bare_wound_bonus = 10
|
||||
reach = 2
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
attack_verb = list("flogged", "whipped", "lashed", "disciplined")
|
||||
@@ -268,6 +270,8 @@
|
||||
var/force_off // Damage when off - not stunning
|
||||
var/weight_class_on // What is the new size class when turned on
|
||||
|
||||
wound_bonus = 15
|
||||
|
||||
/obj/item/melee/classic_baton/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -393,6 +397,7 @@
|
||||
force_off = 0
|
||||
weight_class_on = WEIGHT_CLASS_BULKY
|
||||
total_mass = TOTAL_MASS_NORMAL_ITEM
|
||||
bare_wound_bonus = 5
|
||||
|
||||
/obj/item/melee/classic_baton/telescopic/suicide_act(mob/user)
|
||||
var/mob/living/carbon/human/H = user
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
target.visible_message("<span class='danger'>[user]'s powerfist lets out a weak hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
|
||||
"<span class='userdanger'>[user]'s punch strikes with force!</span>")
|
||||
return
|
||||
target.apply_damage(totalitemdamage * fisto_setting, BRUTE)
|
||||
target.apply_damage(totalitemdamage * fisto_setting, BRUTE, wound_bonus = -25*fisto_setting**2)
|
||||
target.visible_message("<span class='danger'>[user]'s powerfist lets out a loud hiss as [user.p_they()] punch[user.p_es()] [target.name]!</span>", \
|
||||
"<span class='userdanger'>You cry out in pain as [user]'s punch flings you backwards!</span>")
|
||||
new /obj/effect/temp_visual/kinetic_blast(target.loc)
|
||||
|
||||
@@ -7,11 +7,13 @@
|
||||
icon_state = "large"
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
item_flags = DROPDEL
|
||||
sharpness = TRUE
|
||||
|
||||
/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
|
||||
|
||||
/obj/item/shrapnel/bullet // bullets
|
||||
name = "bullet"
|
||||
@@ -28,7 +30,7 @@
|
||||
|
||||
/obj/item/projectile/bullet/shrapnel
|
||||
name = "flying shrapnel shard"
|
||||
damage = 9
|
||||
damage = 8
|
||||
range = 10
|
||||
armour_penetration = -30
|
||||
dismemberment = 5
|
||||
@@ -36,6 +38,8 @@
|
||||
ricochet_chance = 40
|
||||
shrapnel_type = /obj/item/shrapnel
|
||||
ricochet_incidence_leeway = 60
|
||||
sharpness = TRUE
|
||||
wound_bonus = 30
|
||||
|
||||
/obj/item/projectile/bullet/shrapnel/mega
|
||||
name = "flying shrapnel hunk"
|
||||
@@ -62,3 +66,15 @@
|
||||
name = "megastingball pellet"
|
||||
ricochets_max = 6
|
||||
ricochet_chance = 110
|
||||
|
||||
/obj/projectile/bullet/pellet/stingball/breaker
|
||||
name = "breakbang pellet"
|
||||
damage = 10
|
||||
wound_bonus = 40
|
||||
sharpness = FALSE
|
||||
|
||||
/obj/projectile/bullet/pellet/stingball/shred
|
||||
name = "shredbang pellet"
|
||||
damage = 10
|
||||
wound_bonus = 30
|
||||
sharpness = TRUE
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
var/war_cry = "AAAAARGH!!!"
|
||||
var/icon_prefix = "spearglass"
|
||||
var/wielded = FALSE // track wielded status on item
|
||||
wound_bonus = -25
|
||||
bare_wound_bonus = 15
|
||||
|
||||
/obj/item/spear/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -15,6 +15,16 @@
|
||||
var/self_delay = 50
|
||||
var/other_delay = 0
|
||||
var/repeating = FALSE
|
||||
/// How much brute we heal per application
|
||||
var/heal_brute
|
||||
/// How much burn we heal per application
|
||||
var/heal_burn
|
||||
/// How much we reduce bleeding per application on cut wounds
|
||||
var/stop_bleeding
|
||||
/// How much sanitization to apply to burns on application
|
||||
var/sanitization
|
||||
/// How much we add to flesh_healing for burn wounds on application
|
||||
var/flesh_regeneration
|
||||
|
||||
/obj/item/stack/medical/attack(mob/living/M, mob/user)
|
||||
. = ..()
|
||||
@@ -70,8 +80,9 @@
|
||||
icon_state = "brutepack"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
||||
var/heal_brute = 20
|
||||
self_delay = 20
|
||||
heal_brute = 40
|
||||
self_delay = 40
|
||||
other_delay = 20
|
||||
grind_results = list(/datum/reagent/medicine/styptic_powder = 10)
|
||||
|
||||
/obj/item/stack/medical/bruise_pack/one
|
||||
@@ -95,7 +106,8 @@
|
||||
M.heal_bodypart_damage((heal_brute/2))
|
||||
return TRUE
|
||||
if(iscarbon(M))
|
||||
return heal_carbon(M, user, heal_brute, 0)
|
||||
return heal_carbon(M, user, heal_brute, heal_burn)
|
||||
to_chat(user, "<span class='warning'>You can't heal [M] with \the [src]!</span>")
|
||||
to_chat(user, "<span class='notice'>You can't heal [M] with the \the [src]!</span>")
|
||||
|
||||
/obj/item/stack/medical/bruise_pack/suicide_act(mob/user)
|
||||
@@ -104,24 +116,27 @@
|
||||
|
||||
/obj/item/stack/medical/gauze
|
||||
name = "medical gauze"
|
||||
desc = "A roll of elastic cloth that is extremely effective at stopping bleeding, heals minor wounds."
|
||||
desc = "A roll of elastic cloth, perfect for stabilizing all kinds of wounds, from cuts and burns, to broken bones. "
|
||||
gender = PLURAL
|
||||
singular_name = "medical gauze"
|
||||
icon_state = "gauze"
|
||||
var/stop_bleeding = 1800
|
||||
var/heal_brute = 5
|
||||
self_delay = 10
|
||||
self_delay = 50
|
||||
other_delay = 20
|
||||
amount = 6
|
||||
absorption_rate = 0.25
|
||||
absorption_capacity = 5
|
||||
splint_factor = 0.35
|
||||
custom_price = PRICE_REALLY_CHEAP
|
||||
|
||||
/obj/item/stack/medical/gauze/heal(mob/living/M, mob/user)
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
if(!H.bleedsuppress && H.bleed_rate) //so you can't stack bleed suppression
|
||||
H.suppress_bloodloss(stop_bleeding)
|
||||
to_chat(user, "<span class='notice'>You stop the bleeding of [M]!</span>")
|
||||
H.adjustBruteLoss(-(heal_brute))
|
||||
return TRUE
|
||||
to_chat(user, "<span class='notice'>You can not use \the [src] on [M]!</span>")
|
||||
// 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, "<span class='warning'>The bleeding on [user==M ? "your" : "[M]'s"] [limb.name] is from bruising, and cannot be treated with [src]!</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>There's no bleeding on [user==M ? "your" : "[M]'s"] [limb.name]</span>")
|
||||
|
||||
/obj/item/stack/medical/gauze/attackby(obj/item/I, mob/user, params)
|
||||
if(I.tool_behaviour == TOOL_WIRECUTTER || I.get_sharpness())
|
||||
@@ -143,9 +158,12 @@
|
||||
/obj/item/stack/medical/gauze/improvised
|
||||
name = "improvised gauze"
|
||||
singular_name = "improvised gauze"
|
||||
desc = "A roll of cloth roughly cut from something that can stop bleeding, but does not heal wounds."
|
||||
stop_bleeding = 900
|
||||
heal_brute = 0
|
||||
desc = "A roll of cloth roughly cut from something that does a decent job of stabilizing wounds, but less efficiently so than real medical gauze."
|
||||
self_delay = 60
|
||||
other_delay = 30
|
||||
absorption_rate = 0.15
|
||||
absorption_capacity = 4
|
||||
|
||||
/obj/item/stack/medical/gauze/adv
|
||||
name = "sterilized medical gauze"
|
||||
@@ -161,49 +179,28 @@
|
||||
is_cyborg = 1
|
||||
cost = 250
|
||||
|
||||
/obj/item/stack/medical/ointment
|
||||
name = "ointment"
|
||||
desc = "Used to treat those nasty burn wounds."
|
||||
gender = PLURAL
|
||||
singular_name = "ointment"
|
||||
icon_state = "ointment"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
||||
var/heal_burn = 20
|
||||
self_delay = 20
|
||||
grind_results = list(/datum/reagent/medicine/silver_sulfadiazine = 10)
|
||||
|
||||
/obj/item/stack/medical/ointment/one
|
||||
amount = 1
|
||||
|
||||
/obj/item/stack/medical/ointment/heal(mob/living/M, mob/user)
|
||||
if(M.stat == DEAD)
|
||||
to_chat(user, "<span class='notice'> [M] is dead. You can not help [M.p_them()]!</span>")
|
||||
return
|
||||
if(iscarbon(M))
|
||||
return heal_carbon(M, user, 0, heal_burn)
|
||||
if(AmBloodsucker(M))
|
||||
return
|
||||
to_chat(user, "<span class='notice'>You can't heal [M] with the \the [src]!</span>")
|
||||
|
||||
/obj/item/stack/medical/ointment/suicide_act(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] is squeezing \the [src] into [user.p_their()] mouth! [user.p_do(TRUE)]n't [user.p_they()] know that stuff is toxic?</span>")
|
||||
return TOXLOSS
|
||||
|
||||
/obj/item/stack/medical/suture
|
||||
name = "suture"
|
||||
desc = "Sterile sutures used to seal up cuts and lacerations."
|
||||
desc = "Basic sterile sutures used to seal up cuts and lacerations and stop bleeding."
|
||||
gender = PLURAL
|
||||
singular_name = "suture"
|
||||
icon_state = "suture"
|
||||
self_delay = 30
|
||||
other_delay = 10
|
||||
amount = 15
|
||||
max_amount = 15
|
||||
amount = 10
|
||||
max_amount = 10
|
||||
repeating = TRUE
|
||||
var/heal_brute = 10
|
||||
heal_brute = 10
|
||||
stop_bleeding = 0.6
|
||||
grind_results = list(/datum/reagent/medicine/spaceacillin = 2)
|
||||
|
||||
/obj/item/stack/medical/suture/emergency
|
||||
name = "emergency suture"
|
||||
desc = "A value pack of cheap sutures, not very good at repairing damage, but still decent at stopping bleeding."
|
||||
heal_brute = 5
|
||||
amount = 5
|
||||
max_amount = 5
|
||||
|
||||
/obj/item/stack/medical/suture/one
|
||||
amount = 1
|
||||
|
||||
@@ -223,10 +220,40 @@
|
||||
to_chat(user, "<span class='notice'>[M] is at full health.</span>")
|
||||
return FALSE
|
||||
user.visible_message("<span class='green'>[user] applies \the [src] on [M].</span>", "<span class='green'>You apply \the [src] on [M].</span>")
|
||||
M.heal_bodypart_damage(heal_brute)
|
||||
return heal_carbon(M, user, heal_brute, heal_burn)
|
||||
return TRUE
|
||||
|
||||
to_chat(user, "<span class='warning'>You can't heal [M] with the \the [src]!</span>")
|
||||
to_chat(user, "<span class='warning'>You can't heal [M] with \the [src]!</span>")
|
||||
|
||||
/obj/item/stack/medical/ointment
|
||||
name = "ointment"
|
||||
desc = "Basic burn ointment, rated effective for second degree burns with proper bandaging, though it's still an effective stabilizer for worse burns. Not terribly good at outright healing burns though."
|
||||
gender = PLURAL
|
||||
singular_name = "ointment"
|
||||
icon_state = "ointment"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
||||
amount = 10
|
||||
max_amount = 10
|
||||
self_delay = 40
|
||||
other_delay = 20
|
||||
|
||||
heal_burn = 5
|
||||
flesh_regeneration = 2.5
|
||||
sanitization = 0.3
|
||||
grind_results = list(/datum/reagent/medicine/C2/lenturi = 10)
|
||||
|
||||
/obj/item/stack/medical/ointment/heal(mob/living/M, mob/user)
|
||||
if(M.stat == DEAD)
|
||||
to_chat(user, "<span class='warning'>[M] is dead! You can not help [M.p_them()].</span>")
|
||||
return
|
||||
if(iscarbon(M))
|
||||
return heal_carbon(M, user, heal_brute, heal_burn)
|
||||
to_chat(user, "<span class='warning'>You can't heal [M] with \the [src]!</span>")
|
||||
|
||||
/obj/item/stack/medical/ointment/suicide_act(mob/living/user)
|
||||
user.visible_message("<span class='suicide'>[user] is squeezing \the [src] into [user.p_their()] mouth! [user.p_do(TRUE)]n't [user.p_they()] know that stuff is toxic?</span>")
|
||||
return TOXLOSS
|
||||
|
||||
/obj/item/stack/medical/mesh
|
||||
name = "regenerative mesh"
|
||||
@@ -237,9 +264,11 @@
|
||||
self_delay = 30
|
||||
other_delay = 10
|
||||
amount = 15
|
||||
heal_burn = 10
|
||||
max_amount = 15
|
||||
repeating = TRUE
|
||||
var/heal_burn = 10
|
||||
sanitization = 0.75
|
||||
flesh_regeneration = 3
|
||||
var/is_open = TRUE ///This var determines if the sterile packaging of the mesh has been opened.
|
||||
grind_results = list(/datum/reagent/medicine/spaceacillin = 2)
|
||||
|
||||
@@ -264,8 +293,8 @@
|
||||
to_chat(user, "<span class='warning'>[M] is dead! You can not help [M.p_them()].</span>")
|
||||
return
|
||||
if(iscarbon(M))
|
||||
return heal_carbon(M, user, 0, heal_burn)
|
||||
to_chat(user, "<span class='warning'>You can't heal [M] with the \the [src]!</span>")
|
||||
return heal_carbon(M, user, heal_brute, heal_burn)
|
||||
to_chat(user, "<span class='warning'>You can't heal [M] with \the [src]!</span>")
|
||||
|
||||
|
||||
/obj/item/stack/medical/mesh/try_heal(mob/living/M, mob/user, silent = FALSE)
|
||||
@@ -294,3 +323,49 @@
|
||||
playsound(src, 'sound/items/poster_ripped.ogg', 20, TRUE)
|
||||
return
|
||||
. = ..()
|
||||
|
||||
/obj/item/stack/medical/bone_gel
|
||||
name = "bone gel"
|
||||
singular_name = "bone gel"
|
||||
desc = "A potent medical gel that, when applied to a damaged bone in a proper surgical setting, triggers an intense melding reaction to repair the wound. Can be directly applied alongside surgical sticky tape to a broken bone in dire circumstances, though this is very harmful to the patient and not recommended."
|
||||
|
||||
icon = 'icons/obj/surgery.dmi'
|
||||
icon_state = "bone-gel"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
||||
|
||||
amount = 4
|
||||
self_delay = 20
|
||||
grind_results = list(/datum/reagent/medicine/C2/libital = 10)
|
||||
novariants = TRUE
|
||||
|
||||
/obj/item/stack/medical/bone_gel/attack(mob/living/M, mob/user)
|
||||
to_chat(user, "<span class='warning'>Bone gel can only be used on fractured limbs!</span>")
|
||||
return
|
||||
|
||||
/obj/item/stack/medical/bone_gel/suicide_act(mob/user)
|
||||
if(iscarbon(user))
|
||||
var/mob/living/carbon/C = user
|
||||
C.visible_message("<span class='suicide'>[C] is squirting all of \the [src] into [C.p_their()] mouth! That's not proper procedure! It looks like [C.p_theyre()] trying to commit suicide!</span>")
|
||||
if(do_after(C, 2 SECONDS))
|
||||
C.emote("scream")
|
||||
for(var/i in C.bodyparts)
|
||||
var/obj/item/bodypart/bone = i
|
||||
var/datum/wound/brute/bone/severe/oof_ouch = new
|
||||
oof_ouch.apply_wound(bone)
|
||||
var/datum/wound/brute/bone/critical/oof_OUCH = new
|
||||
oof_OUCH.apply_wound(bone)
|
||||
|
||||
for(var/i in C.bodyparts)
|
||||
var/obj/item/bodypart/bone = i
|
||||
bone.receive_damage(brute=60)
|
||||
use(1)
|
||||
return (BRUTELOSS)
|
||||
else
|
||||
C.visible_message("<span class='suicide'>[C] screws up like an idiot and still dies anyway!</span>")
|
||||
return (BRUTELOSS)
|
||||
|
||||
/obj/item/stack/medical/bone_gel/cyborg
|
||||
custom_materials = null
|
||||
is_cyborg = 1
|
||||
cost = 250
|
||||
|
||||
@@ -119,6 +119,7 @@
|
||||
#include "code\__DEFINES\vv.dm"
|
||||
#include "code\__DEFINES\wall_dents.dm"
|
||||
#include "code\__DEFINES\wires.dm"
|
||||
#include "code\__DEFINES\wounds.dm"
|
||||
#include "code\__DEFINES\_flags\_flags.dm"
|
||||
#include "code\__DEFINES\_flags\item_flags.dm"
|
||||
#include "code\__DEFINES\_flags\obj_flags.dm"
|
||||
@@ -624,6 +625,7 @@
|
||||
#include "code\datums\status_effects\gas.dm"
|
||||
#include "code\datums\status_effects\neutral.dm"
|
||||
#include "code\datums\status_effects\status_effect.dm"
|
||||
#include "code\datums\status_effects\wound_effects.dm"
|
||||
#include "code\datums\traits\_quirk.dm"
|
||||
#include "code\datums\traits\good.dm"
|
||||
#include "code\datums\traits\negative.dm"
|
||||
@@ -651,6 +653,8 @@
|
||||
#include "code\datums\wires\syndicatebomb.dm"
|
||||
#include "code\datums\wires\tesla_coil.dm"
|
||||
#include "code\datums\wires\vending.dm"
|
||||
#include "code\datums\wounds\_scars.dm"
|
||||
#include "code\datums\wounds\cuts.dm"
|
||||
#include "code\game\alternate_appearance.dm"
|
||||
#include "code\game\atoms.dm"
|
||||
#include "code\game\atoms_movable.dm"
|
||||
|
||||
Reference in New Issue
Block a user