/* ._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._. */ /*-=-=-=-=-=-=-=-=-=-=-=-=-=-ISSUES=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/ /* '~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~' */ /* - healing spells for lings/etc should stop bleeding - iron and sugar have effects on blood: sugar reduces low blood_volume effects, research it & iron - Bleeding rework: if you have open surgical wounds your bleeding shouldn't drop to 0 - Processor still needs to be finished. - Blood donation is better now with IVs, but the processor still could be useful - With how cheap sutures are to make, they need more drawbacks/bandages need less, so people actually have a reason to use bandages. - Vampires?? ?????? - Open wounds, limb loss, etc need to bleed more/be more obvious that they're bleeding. - Maybe a rewrite to the limb system so it doesn't SUCK re: bugs and interaction with other systems. (medborgs not being able to remove limbs and crap like that - ???) */ /* ._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._. */ /*-=-=-=-=-=-=-=-=-=-=-=-=-BLOOD-STUFF-=-=-=-=-=-=-=-=-=-=-=-=-*/ /* '~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~' */ var/global/haine_blood_debug = 0 /client/proc/haine_blood_debug() set desc = "Toggle blood debug messages." set name = "Haine Blood Debug" set hidden = 1 haine_blood_debug = !( haine_blood_debug ) logTheThing("admin", usr, null, "toggled blood debug messages [haine_blood_debug ? "on" : "off"].") logTheThing("diary", usr, null, "toggled blood debug messages [haine_blood_debug ? "on" : "off"].", "admin") message_admins("[key_name(usr)] toggled blood debug messages [haine_blood_debug ? "on" : "off"]") // for logging purposes /proc/dam_num2name(var/damtype) if (isnull(damtype)) return "error" switch (damtype) if (DAMAGE_STAB) return "damage_stab" if (DAMAGE_CUT) return "damage_cut" if (DAMAGE_BLUNT) return "damage_blunt" if (DAMAGE_BURN) return "damage_burn" if (DAMAGE_CRUSH) return "damage_crush" return "error" /* ._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._. */ /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=PROCS=-=-=-=-=-=-=-=-==-=-=-=-=-=*/ /* '~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~' */ /* ---------- WHAT'S HERE ---------- take_bleeding_damage(mob/some_idiot, mob/some_jerk, damage, damage_type, bloodsplatter = 1, turf/T) some_idiot is your target who takes the damage, some_jerk is the guy what did it to some_idiot for things that would cause bloodsplatter and increase bleeding - damage determines how much blood is lost - damage_types: DAMAGE_STAB, DAMAGE_CUT, DAMAGE_BLUNT, DAMAGE_BURN - these will affect the chance of increasing bleeding - bloodsplatter var just in case that needs to be taken care of elsewhere??? if it's 0 it'll just remove [damage] from some_idiot's blood_volume without the decal appearing - T will pass a turf to bleed() in case you need the blood to appear in more places than just where some_idiot is if you don't give it T it defaults to some_idiot's turf - if the damage_type is DAMAGE_BURN and a bleeding increase doesn't occur, there's a chance that repair_bleeding_damage() will be triggered ---------- repair_bleeding_damage(mob/some_idiot, repair_chance, repair_amount) for things that'll fix bleeding: sutures, bandages, etc - repair_chance will be affected by how much some_idiot is bleeding already: higher levels of bleeding have a better chance of repair - repair_amount should be 1-10, and will be subtracted from some_idiot's bleeding ---------- bleed(mob/some_idiot, num_amount, vis_amount, turf/T) creates bloodsplatter on T, or if it isn't passed T, some_idiot's turf - num_amount is how much blood to lose - vis_amount is how much blood to spawn visually, 1-5 (see the dynamic blood decal in decal.dm for more info) I keep having to make this same thing over and over so this is just a timesaver for me you should probably use take_bleeding_damage() instead of this unless you have some need to make someone bleed without making their bleeding increase ---------- transfer_blood(mob/living/carbon/human/some_idiot, atom/A, amount) take [amount] total blood and reagents (combined) out of some_idiot and transfer it into A currently used by syringes and IVs it removes blood from some_idiot's blood_volume and reagents from their reagent holder ---------- blood_slash(mob/some_idiot, bleed_amount, atom/A, direction, splatters = 4) creates a trail of blood in either the direction provided, or, failing that, some_idiot's direction - bleed_amount is how much blood to lose FOR EACH BLOODSPLATTER + THE INITIAL ONE, this defaults to bleed_amount * 5 - direction and A are optional in case you want to create the slash in a place/direction other than some_idiot's (ie some_idiot is inside something) - splatters is how many decals to spawn made for suicides where you cut your throat, but maybe you can find some other use for it ---------- animate_blood_damage(mob/some_idiot, mob/some_jerk) WIP, doesn't work yet. you can ignore this. ---------- staunch_bleeding(mob/some_idiot) a proc under /mob/living/carbon/human for putting pressure on wounds to stop bleeding. this is already used where it needs to be used, you can probably ignore it. ---------- END ---------- */ /* ============================================ */ /* ---------- take_bleeding_damage() ---------- */ /* ============================================ */ /proc/take_bleeding_damage(var/mob/some_idiot as mob, var/mob/some_jerk as mob, var/damage as num, var/damage_type = DAMAGE_CUT, var/bloodsplatter = 1, var/turf/T as turf) if (!T) // I forget why I set T as a variable OH WELL T = get_turf(some_idiot) if (!blood_system) if (bloodsplatter) // we at least wanna create the decal anyway bleed(some_idiot, 0, 5, T) //animate_blood_damage(some_idiot, some_jerk) return if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [some_idiot] begins bleed damage proc") if (!ishuman(some_idiot)) // maybe later borgs will bleed. not now though. if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [some_idiot] is not human so bleed damage was canceled") return var/mob/living/carbon/human/H = some_idiot if (H.stat == 2 || H.nodamage || !H.can_bleed) if (H.bleeding) H.bleeding = 0 H.bleeding_internal = 0 if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] is dead or immortal or otherwise not supposed to bleed, so their bleeding has been set to 0 and bleed damage was canceled") return if ((!isvampire(H) && H.blood_volume > 0) || (isvampire(H) && H.get_vampire_blood() > 0)) // make sure we have blood to bleed if (bloodsplatter) // make sure we want to make bloodsplatter bleed(H, damage, 5, T) // actually bleed //animate_blood_damage(some_idiot, some_jerk) if (isvampire(H)) // we can go now, we don't need to do anything else for vamps return if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s blood level is [H.blood_volume]") else H.bleeding = 0 // if we don't have any blood to bleed, just stop okay, just stop. H.bleeding_internal = 0 if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] has no blood and their bleeding has been set to 0 and bleed damage was canceled") return if (H.bleeding >= 10) // don't bleed more if you're already at bleeding 10 tia if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s bleeding was [H.bleeding] and has been set to 10 and bleed damage was canceled") H.bleeding = 10 return var/increase_chance = rand(30, 50) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s initial increase chance is [increase_chance]") if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s initial bleeding is [H.bleeding]") switch (H.bleeding) if (-INFINITY to 0) increase_chance += rand(30, 50) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s increase chance increased to [increase_chance]") if (1 to 3) increase_chance += rand(20, 30) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s increase chance increased to [increase_chance]") if (4 to 6) increase_chance += rand(5, 20) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s increase chance increased to [increase_chance]") if (7 to 8) increase_chance += rand(0, 5) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s increase chance increased to [increase_chance]") if (9 to INFINITY) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s bleeding was already high and chance was not increased") if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s damage type is [dam_num2name(damage_type)]") switch (damage_type) if (DAMAGE_STAB) increase_chance += rand(0, 10) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s increase chance increased to [increase_chance]") if (DAMAGE_CUT) increase_chance += rand(5, 20) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s increase chance increased to [increase_chance]") if (DAMAGE_BLUNT) increase_chance -= rand(10, 30) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s increase chance decreased to [increase_chance]") if (DAMAGE_BURN) if (!H.is_heat_resistant()) increase_chance -= rand(30, 50) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s increase chance decreased to [increase_chance]") if (ischangeling(H)) increase_chance -= rand(10, 20) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] is a changeling - [H]'s increase chance decreased to [increase_chance]") /* if (isvampire(H)) increase_chance -= rand(10, 20) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] is a vampire - [H]'s increase chance decreased to [increase_chance]") */ if(H.traitHolder && H.traitHolder.hasTrait("hemophilia")) increase_chance *= 3 var/final_increase_chance = min(increase_chance, 100) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s final increase chance is [final_increase_chance]") if (prob(final_increase_chance)) H.bleeding ++ switch (H.bleeding) if (-INFINITY to 1) H.show_text("You start bleeding!", "red") if (1 to 8) if (prob(33)) H.show_text("You[pick(" start bleeding even worse", " start bleeding even more", " start bleeding more", "r bleeding worsens", "r bleeding gets worse")]!", "red") if (9 to INFINITY) H.show_text("You can't go on very long with blood pouring out of you like this!", "red") if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] rolls bleeding increase, bleeding is now [H.bleeding]") else if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s bleeding does not increase") if (damage_type == DAMAGE_BURN && !H.is_heat_resistant() && H.bleeding > 0) if (prob(rand(30,50))) repair_bleeding_damage(H, rand(30,50), rand(1,3)) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] rolls bleeding repair due to DAMAGE_BURN") /* ============================================== */ /* ---------- repair_bleeding_damage() ---------- */ /* ============================================== */ /proc/repair_bleeding_damage(var/mob/some_idiot as mob, var/repair_chance as num, var/repair_amount as num) if (!blood_system) return if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [some_idiot] begins bleeding repair") if (!ishuman(some_idiot)) // if they aren't human they shouldn't be able to bleed!! if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [some_idiot] is not human so repair was canceled") return var/mob/living/carbon/human/H = some_idiot if (H.stat == 2) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] is dead and their bleeding has been set to 0 and repair was canceled") H.bleeding = 0 // no just stop bleeding entirely okay, you're dead, stop it H.bleeding_internal = 0 return if (isvampire(H)) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] is a vampire and their bleeding has been set to 0 and repair was canceled") H.bleeding = 0 // bleh im a vampar H.bleeding_internal = 0 return if (H.blood_volume <= 0) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] has no blood and their bleeding has been set to 0 and repair was canceled") H.bleeding = 0 // you have no blood so stop trying to bleed H.bleeding_internal = 0 return if (repair_amount <= 0) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s repair_amount was set as [repair_amount] so repair was canceled") return // you wouldn't have done anything anyway if (repair_chance < 100) // if it's already 100 we don't need to go through all the crap down here if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s initial repair chance is [repair_chance]") switch (H.bleeding) if (-INFINITY to 0) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] isn't bleeding and repair has been stopped") return // there's nothing to fix here, go home if (1 to 2) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s bleeding was already low and chance was not increased") if (3 to 4) repair_chance += rand(0, 5) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s repair chance increased to [repair_chance]") if (5 to 7) repair_chance += rand(5, 20) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s repair chance increased to [repair_chance]") if (8 to 9) repair_chance += rand(20, 30) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s repair chance increased to [repair_chance]") if (10 to INFINITY) repair_chance += rand(30, 50) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s repair chance increased to [repair_chance]") var/final_repair_chance = min(repair_chance, 100) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s final repair chance is [final_repair_chance]") if (prob(final_repair_chance)) H.bleeding -= repair_amount if (!H.bleeding && H.get_surgery_status()) H.bleeding ++ switch (H.bleeding) if (-INFINITY to 0) H.show_text("Your bleeding stops!", "red") if (1 to 8) switch (repair_amount) if (1 to 3) H.show_text("Your bleeding [pick("slows", "slows down", "slightly slows", "slows a little", "gets slightly slower", "barely slows")]!", "red") if (4 to 6) H.show_text("Your bleeding [pick("slows", "slows down", "slows a lot", "slows down a lot", "really slows down")]!", "red") if (7 to 10) H.show_text("Your bleeding [pick("slows", "slows down", "slows a lot", "slows down a lot", "really slows down", "slows way down", "nearly stops", "has almost stopped", "is barely a trickle now")]!", "red") if (9 to INFINITY) H.show_text("You can't go on very long with blood pouring out of you like this!", "red") if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s bleeding repaired by [repair_amount], now [H.bleeding]") if (H.bleeding < 0) H.bleeding = 0 if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s bleeding dropped below 0 and was reset to 0") else if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] rolled no repair") /* ============================= */ /* ---------- bleed() ---------- */ /* ============================= */ /proc/bleed(var/mob/living/some_idiot as mob, var/num_amount as num, var/vis_amount as num, var/turf/T as turf) if (!T) T = get_turf(some_idiot) var/mob/living/carbon/human/H = some_idiot if (!blood_system) // we're here because we want to create a decal, so create it anyway var/obj/decal/cleanable/blood/dynamic/B = locate(/obj/decal/cleanable/blood/dynamic) in T var/blood_color_to_pass = DEFAULT_BLOOD_COLOR if (istype(H)) blood_color_to_pass = H.blood_color if (!B) // look for an existing dynamic blood decal and add to it if you find one B = new /obj/decal/cleanable/blood/dynamic(T) B.add_volume(blood_color_to_pass, vis_amount) else B.add_volume(blood_color_to_pass, vis_amount) if (some_idiot.blood_id) B.reagents.add_reagent(some_idiot.blood_id, num_amount) if (istype(H)) if (H.is_changeling()) B.ling_blood = 1 if (some_idiot.bioHolder) B.blood_DNA = some_idiot.bioHolder.Uid B.blood_type = some_idiot.bioHolder.bloodType else B.blood_DNA = "--unidentified substance--" B.blood_type = "--unidentified substance--" return if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [some_idiot] begins bleed") if (!istype(H)) // if they aren't human they shouldn't be able to bleed!! if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [some_idiot] is not human so bleed was canceled") return if (H.stat == 2 || H.nodamage || !H.can_bleed) if (H.bleeding) H.bleeding = 0 // stop that if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [some_idiot] is either dead, immortal, or has can_bleed disabled, so bleed was canceled") return if (isvampire(H)) // vampires should be special if (H.bleeding) H.bleeding = 0 // we don't need this to be anything above 0 for vamps if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [some_idiot] is a vampire with a bleeding above 0, so it was reset to 0") if ((!isvampire(H) && H.blood_volume > 0) || (isvampire(H) && H.get_vampire_blood() > 0)) // you shouldn't bleed unless you have blood okay if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [H] blood level [H.blood_volume]") var/obj/decal/cleanable/blood/dynamic/B = locate(/obj/decal/cleanable/blood/dynamic) in T if (!B) // look for an existing dynamic blood decal and add to it if you find one B = new /obj/decal/cleanable/blood/dynamic(T) B.add_volume(H.blood_color, vis_amount) if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [H] creates new blood decal") else B.add_volume(H.blood_color, vis_amount) if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [H] adds volume to existing blood decal") if (H.is_changeling()) B.ling_blood = 1 if (H.bleeding > 4 && B.reagents && B.reagents.total_volume < 90 && H.reagents && H.reagents.total_volume) if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [H] transfers reagents to blood decal [log_reagents(H)]") H.reagents.trans_to(B, min(round(H.bleeding / 2, 1), 5)) B.blood_DNA = some_idiot.bioHolder.Uid B.blood_type = some_idiot.bioHolder.bloodType if (isvampire(H)) H.change_vampire_blood(-5) //num_amount // gunna go with a set number as a test if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [H] bleeds -5 from vamp_blood_remaining and their vamp_blood_remaining becomes [H.get_vampire_blood()]") else H.blood_volume -= num_amount // time to bleed if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [H] bleeds [num_amount] and their blood level becomes [H.blood_volume]") if (H.blood_volume < 0) // you shouldn't have negative blood okay H.blood_volume = 0 if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [H]'s blood volume dropped below 0 and was reset to 0") else return /* ====================================== */ /* ---------- transfer_blood() ---------- */ /* ====================================== */ /proc/transfer_blood(var/mob/living/some_idiot as mob, var/atom/A as obj|mob, var/amount = 5) if (!some_idiot || !A || !istype(some_idiot)) return 0 var/mob/living/carbon/human/some_human_idiot = some_idiot // this is shit, but thenagain for SOME REASON a global proc is handling specifics of blood if (!A.reagents || (!istype(some_human_idiot) && !some_idiot.reagents)) return 0 if (istype(some_human_idiot)) if (isvampire(some_human_idiot) && (some_human_idiot.get_vampire_blood() <= 0) || (!isvampire(some_human_idiot) && !some_human_idiot.reagents && !some_human_idiot.blood_volume)) return 0 var/reagents_to_transfer = (amount / 5) * 2 var/blood_to_transfer = (amount - min(reagents_to_transfer, some_idiot.reagents.total_volume)) var/datum/bioHolder/bloodHolder = null if (istype(some_human_idiot)) if (isvampire(some_human_idiot) && (some_human_idiot.get_vampire_blood() < blood_to_transfer)) blood_to_transfer = some_human_idiot.get_vampire_blood() // Ignore that second container of blood entirely if it's a vampire (Convair880). if (!isvampire(some_human_idiot) && (some_human_idiot.blood_volume < blood_to_transfer)) blood_to_transfer = some_human_idiot.blood_volume bloodHolder = new/datum/bioHolder(null) bloodHolder.CopyOther(some_idiot.bioHolder) bloodHolder.ownerName = some_idiot.real_name var/datum/reagent/R = null if (ischangeling(some_idiot)) A.reagents.add_reagent("bloodc", blood_to_transfer, bloodHolder) R = A.reagents.get_reagent("bloodc") else A.reagents.add_reagent(some_idiot.blood_id, blood_to_transfer, bloodHolder) R = A.reagents.get_reagent(some_idiot.blood_id) if (R && (R.id == "blood" || R.id == "bloodc") && istype(some_human_idiot)) var/datum/reagent/blood/B = R var/list/SP = A.reagents.aggregate_pathogens() for (var/uid in some_human_idiot.pathogens) if (!(uid in SP)) var/datum/pathogen/P = unpool(/datum/pathogen) P.setup(0, some_human_idiot.pathogens[uid], 0) B.pathogens[uid] = P if (istype(some_human_idiot)) // Vampires can't use this trick to inflate their blood count, because they can't get more than ~30% of it back (Convair880). if (blood_system && (isvampire(some_human_idiot) && (some_human_idiot.get_vampire_blood() >= blood_to_transfer))) some_human_idiot.change_vampire_blood(-blood_to_transfer) // Ignore that second container of blood entirely if it's a vampire (Convair880). if (blood_system && !isvampire(some_idiot) && (some_human_idiot.blood_volume >= blood_to_transfer)) some_human_idiot.blood_volume -= blood_to_transfer if (blood_to_transfer < amount) some_idiot.reagents.trans_to(A, (amount - blood_to_transfer)) return 1 /* =================================== */ /* ---------- blood_slash() ---------- */ /* =================================== */ /proc/blood_slash(var/mob/some_idiot as mob, var/bleed_amount as num, var/atom/A as mob|obj|turf, var/direction, var/splatters = 4) var/turf/target var/turf/end_target if (!some_idiot) // what do you want and also what are you doing here?! if (haine_blood_debug) logTheThing("debug", null, null, "HAINE BLOOD DEBUG: blood_slash: not passed a mob, exiting") return if (!ishuman(some_idiot)) // no stop trying to bleed you aren't human if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: blood_slash: passed non-human mob [some_idiot], exiting") return if (!A) // if we aren't provided with a separate target, use some_idiot target = some_idiot.loc if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: blood_slash: no origin point specified, using [some_idiot]'s location") else target = A.loc if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: blood_slash: origin point set to [A]") take_bleeding_damage(some_idiot, null, bleed_amount, DAMAGE_CUT, 1, target) if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [some_idiot] enters take_bleeding_damage from blood_slash") if (!direction) // if we aren't provided with a direction, use some_idiot again direction = some_idiot.dir if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: blood_slash: no direction specified, using [some_idiot]'s dir") for (var/i = 0, i < splatters, i++) switch (direction) if (NORTH) end_target = locate(target.x, target.y+i, target.z) if (SOUTH) end_target = locate(target.x, target.y-i, target.z) if (EAST) end_target = locate(target.x+i, target.y, target.z) if (WEST) end_target = locate(target.x-i, target.y, target.z) bleed(some_idiot, bleed_amount, 5, end_target) if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [some_idiot] enters bleed from blood_slash") /* ============================================ */ /* ---------- animate_blood_damage() ---------- */ /* ============================================ */ //proc/animate_blood_damage(var/mob/some_idiot as mob, var/mob/some_jerk as mob) /* DEBUG_MESSAGE("made it into proc") if (!some_idiot || !ishuman(some_idiot)) // what're we gunna do here? return 0 var/blood_color = DEFAULT_BLOOD_COLOR // default is #990000 atm, a dark-ish red. if (ishuman(some_idiot)) // only humans have the blood_color var DEBUG_MESSAGE("some_idiot [some_idiot] is human") blood_color = some_idiot:blood_color // they might have ~extra-fab blood~ so we wanna use whatever color they have var/anim_offset_y = 0 // vertical offset var/anim_offset_x = 0 // horizontal offset if (some_idiot.lying) // are we laying around on the floor like some kinda bum? DEBUG_MESSAGE("some_idiot [some_idiot] is lying down") if (some_jerk) // our attacker, if we've got one switch (some_jerk.zone_sel.selecting) // where're they aiming? if ("head") DEBUG_MESSAGE("some_jerk [some_jerk] is aiming at the head") anim_offset_y = rand(-2,-10) anim_offset_x = rand(6,12) if ("chest" || "l_arm" || "r_arm") DEBUG_MESSAGE("some_jerk [some_jerk] is aiming at the chest/arms") anim_offset_y = rand(-2,-12) anim_offset_x = rand(8,15) if ("l_leg" || "r_leg") DEBUG_MESSAGE("some_jerk [some_jerk] is aiming at the legs") anim_offset_y = rand(0,-12) anim_offset_x = rand(-7,-15) else // otherwise... DEBUG_MESSAGE("some_jerk not passed") anim_offset_y = rand(7,-12) anim_offset_x = rand(8,-15) else // if we aren't on the ground DEBUG_MESSAGE("some_idiot [some_idiot] is standing") if (some_jerk) switch (some_jerk.zone_sel.selecting) if ("head") DEBUG_MESSAGE("some_jerk [some_jerk] is aiming at the head") anim_offset_y = rand(8,14) anim_offset_x = rand(-5,3) if ("chest" || "l_arm" || "r_arm") DEBUG_MESSAGE("some_jerk [some_jerk] is aiming at the chest/arms") anim_offset_y = rand(-5,6) anim_offset_x = rand(-9,7) if ("l_leg" || "r_leg") DEBUG_MESSAGE("some_jerk [some_jerk] is aiming at the legs") anim_offset_y = rand(-5,-15) anim_offset_x = rand(-7,-5) else DEBUG_MESSAGE("some_jerk not passed") anim_offset_y = rand(-15,14) anim_offset_x = rand(-9,-7) some_idiot:damage_animation:icon_state = "bloodhit" some_idiot:damage_animation:pixel_y = anim_offset_y some_idiot:damage_animation:pixel_x = anim_offset_x some_idiot:damage_animation:color = blood_color some_idiot:damage_animation:transform = turn(some_idiot:damage_animation:transform, rand(0, 359)) DEBUG_MESSAGE("anim y [some_idiot:damage_animation:pixel_y], anim x [some_idiot:damage_animation:pixel_x], blood color [some_idiot:damage_animation:color]") DEBUG_MESSAGE("adding overlay") some_idiot.overlays += some_idiot:damage_animation spawn(15) DEBUG_MESSAGE("removing overlay") some_idiot:damage_animation:icon_state = "blank" some_idiot.overlays -= some_idiot:damage_animation */ /* ======================================== */ /* ---------- staunch_bleeding() ---------- */ /* ======================================== */ /mob/proc/staunch_bleeding(var/mob/some_idiot) // stolen from ISN's shake_awake() proc if (!src || !some_idiot) return 0 if (istype(some_idiot,/mob/living/carbon/human/)) var/mob/living/carbon/human/H = some_idiot var/his_her = "[H.gender == "male" ? "his" : "her"]" if (H.being_staunched) src.show_text("[H == src ? "You're" : "Someone's"] already putting pressure on [H == src ? "your" : "[H]'s"] wounds!", "red") return if (H) H.add_fingerprint(src) // Just put 'em on the mob itself, like pulling does. Simplifies forensic analysis a bit (Convair880). // if (H.w_uniform) // H.w_uniform.add_fingerprint(src) H.being_staunched = 1 src.tri_message("[src] puts pressure on [src == H ? "[his_her]" : "[H]'s"] wounds, trying to stop the bleeding!",\ src, "You put pressure on [src == H ? "your" : "[H]'s"] wounds, trying to stop the bleeding!",\ H, "[H == src ? "You put" : "[src] puts"] pressure on your wounds, trying to stop the bleeding!") if (do_mob(src, H, 100)) var/original_bleed = H.bleeding repair_bleeding_damage(H, 20, rand(1,2)) if (original_bleed > H.bleeding) switch (H.bleeding) if (-INFINITY to 0) src.show_text("The bleeding stops!", "blue") if (1 to 8) src.show_text("The bleeding slows!", "blue") if (9 to INFINITY) src.show_text("It barely helps!", "red") else if (original_bleed == H.bleeding) src.show_text("The bleeding doesn't slow at all!", "red") else if (original_bleed < H.bleeding) // what src.show_text("Oh fuck somehow the bleeding got WORSE!", "red") H.being_staunched = 0 return 1 else src.show_text("You were interrupted!", "red") H.being_staunched = 0 return 0 else return 0 /* ._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._. */ /*-=-=-=-=-=-=-=-=-=-=-=INTERNAL-BLEEDING=-=-=-=-=-=-=-=-=-=-=-*/ /* '~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~' */ /proc/internal_bleeding_damage(var/mob/some_idiot as mob, var/mob/some_jerk as mob, var/damage as num) if (!blood_system) return if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [some_idiot] begins internal bleed damage proc") if (!ishuman(some_idiot)) // maybe later borgs will bleed. not now though. if (haine_blood_debug) logTheThing("debug", some_idiot, null, "HAINE BLOOD DEBUG: [some_idiot] is not human so internal bleed damage was canceled") return var/mob/living/carbon/human/H = some_idiot if (H.stat == 2 || H.nodamage || !H.can_bleed || isvampire(H)) if (H.bleeding) H.bleeding = 0 H.bleeding_internal = 0 if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] is dead/immortal/a vampire/otherwise not supposed to bleed, so their bleeding has been set to 0 and internal bleed damage was canceled") return if (!(H.blood_volume > 0)) // make sure we have blood to bleed H.bleeding = 0 // if we don't have any blood to bleed, just stop okay, just stop. H.bleeding_internal = 0 if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] has no blood and their bleeding has been set to 0 and internal bleed damage was canceled") return if (H.bleeding_internal >= 10) // don't bleed more if you're already at bleeding 10 tia if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s internal bleeding was [H.bleeding_internal] and has been set to 10 and internal bleed damage was canceled") H.bleeding_internal = 10 return var/increase_chance = rand(30, 50) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s initial increase chance is [increase_chance]") if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s initial internal bleeding is [H.bleeding_internal]") switch (H.bleeding_internal) if (-INFINITY to 1) increase_chance += rand(30, 50) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s increase chance increased to [increase_chance]") if (2) increase_chance += rand(20, 30) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s increase chance increased to [increase_chance]") if (3) increase_chance += rand(5, 20) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s increase chance increased to [increase_chance]") if (4) increase_chance += rand(0, 5) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s increase chance increased to [increase_chance]") if (5 to INFINITY) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s internal bleeding was already high and chance was not increased") if (some_jerk && some_jerk.zone_sel && some_jerk.zone_sel.selecting) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [some_jerk]'s target zone is [some_jerk.zone_sel.selecting]") switch (some_jerk.zone_sel.selecting) if ("head") increase_chance += rand(0, 10) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s increase chance increased to [increase_chance]") if (ischangeling(H)) increase_chance -= rand(10, 20) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] is a changeling - [H]'s increase chance decreased to [increase_chance]") var/final_increase_chance = min(increase_chance, 100) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s final increase chance is [final_increase_chance]") if (prob(final_increase_chance)) H.bleeding_internal ++ if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H] rolls internal bleeding increase, internal bleeding is now [H.bleeding_internal]") else if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s internal bleeding does not increase") H.bleeding_internal = minmax(H.bleeding_internal, 0, 5) if (haine_blood_debug) logTheThing("debug", H, null, "HAINE BLOOD DEBUG: [H]'s internal bleeding is [H.bleeding_internal] after minmax") /* ._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._. */ /*-=-=-=-=-=-=-=-=-=-=-=MEDICAL-EQUIPMENT=-=-=-=-=-=-=-=-=-=-=-*/ /* '~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~' */ /* ---------- BLOOD PROCESSOR ---------- */ /* ._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._. */ /*-=-=-=-=-=-=-=-=-=-=-=-=-TEST=-ITEMS=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* '~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~'-._.-'~' */ /obj/item/test_toilet name = "test toilet" desc = "this is for testing bleeding stuff" w_class = 1.0 icon = 'icons/obj/objects.dmi' icon_state = "toilet" flags = FPRINT | CONDUCT | TABLEPASS var/damage_type = DAMAGE_CUT attack_self(mob/user as mob) var/selection = input("Select damage type", "Damage Type", "CUT") as anything in list("STAB", "CUT", "BLUNT", "BURN") if (!selection) return switch (selection) if ("STAB") src.damage_type = DAMAGE_STAB if ("CUT") src.damage_type = DAMAGE_CUT if ("BLUNT") src.damage_type = DAMAGE_BLUNT if ("BURN") src.damage_type = DAMAGE_BURN attack(mob/M as mob, mob/user as mob) user.visible_message("[user] attacks [M] with [src], set to [dam_num2name(src.damage_type)]!", "You attack [M] with [src], set to [src.damage_type]!") switch(src.damage_type) if (DAMAGE_STAB) playsound(M, 'sound/effects/bloody_stab.ogg', 30, 1) if (DAMAGE_CUT) playsound(M, 'sound/weapons/slashcut.ogg', 30, 1) if (DAMAGE_BLUNT) playsound(M, 'sound/weapons/smash.ogg', 30, 1) if (DAMAGE_BURN) playsound(M, 'sound/effects/mag_fireballlaunch.ogg', 30, 1) take_bleeding_damage(M, user, 1, src.damage_type) /obj/item/test_dagger name = "test dagger" desc = "this is for testing bleeding stuff" w_class = 1.0 icon = 'icons/obj/weapons.dmi' icon_state = "dagger" inhand_image_icon = 'icons/mob/inhand/hand_food.dmi' item_state = "knife" force = 0.0 throwforce = 0.0 throw_range = 16 flags = FPRINT | TABLEPASS | NOSHIELD burn_type = 1 throw_impact(atom/A) if(iscarbon(A)) if (istype(usr, /mob)) A:lastattacker = usr A:lastattackertime = world.time playsound(A, 'sound/effects/bloody_stab.ogg', 60, 1) take_bleeding_damage(A, null, rand(2,3), DAMAGE_STAB) attack(target as mob, mob/user as mob) ..() playsound(target, 'sound/effects/bloody_stab.ogg', 60, 1) take_bleeding_damage(target, user, rand(2,3), DAMAGE_STAB)