diff --git a/code/__defines/armor.dm b/code/__defines/armor.dm
index c43e7cc2f26..e39a42430a7 100644
--- a/code/__defines/armor.dm
+++ b/code/__defines/armor.dm
@@ -2,12 +2,12 @@
// Some levels are marked with what they intend to block in such way.
#define ARMOR_BALLISTIC_MINOR 10
-#define ARMOR_BALLISTIC_SMALL 25
-#define ARMOR_BALLISTIC_PISTOL 50 //Blocks holdout and normal pistol ammo
-#define ARMOR_BALLISTIC_RESISTANT 65
-#define ARMOR_BALLISTIC_RIFLE 80 //Blocks rifle rounds
-#define ARMOR_BALLISTIC_AP 95
-#define ARMOR_BALLISTIC_HEAVY 110
+#define ARMOR_BALLISTIC_SMALL 15
+#define ARMOR_BALLISTIC_PISTOL 30
+#define ARMOR_BALLISTIC_RESISTANT 60
+#define ARMOR_BALLISTIC_RIFLE 90
+#define ARMOR_BALLISTIC_AP 120
+#define ARMOR_BALLISTIC_HEAVY 150
#define ARMOR_LASER_MINOR 10
#define ARMOR_LASER_SMALL 25 //Blocks small e-guns
diff --git a/code/game/objects/items/__item.dm b/code/game/objects/items/__item.dm
index d9164b23c5e..29d237a4a47 100644
--- a/code/game/objects/items/__item.dm
+++ b/code/game/objects/items/__item.dm
@@ -225,7 +225,7 @@
for(var/type in armor)
if(armor[type]) // Don't set it if it gives no armor anyway, which is many items.
set_extension(src, armor_type, armor, armor_degradation_speed)
- break
+
if(randpixel && (!pixel_x && !pixel_y) && isturf(loc)) //hopefully this will prevent us from messing with mapper-set pixel_x/y
pixel_x = rand(-randpixel, randpixel)
pixel_y = rand(-randpixel, randpixel)
diff --git a/maps/modpack_testing/modpack_testing.dm b/maps/modpack_testing/modpack_testing.dm
index 47b6b146814..3f733708096 100644
--- a/maps/modpack_testing/modpack_testing.dm
+++ b/maps/modpack_testing/modpack_testing.dm
@@ -12,6 +12,7 @@
#include "../../mods/content/bigpharma/_bigpharma.dme"
#include "../../mods/content/biomods/_biomods.dme"
#include "../../mods/content/blacksmithy/_blacksmithy.dme"
+ #include "../../mods/content/bosniastation/_bosniastation.dme"
#include "../../mods/content/blob/_blob.dme"
#include "../../mods/content/breath_holding/_breath_holding.dme"
#include "../../mods/content/byond_membership/_byond_membership.dm"
diff --git a/mods/content/bosniastation/_bosniastation.dm b/mods/content/bosniastation/_bosniastation.dm
new file mode 100644
index 00000000000..f49eccb91c3
--- /dev/null
+++ b/mods/content/bosniastation/_bosniastation.dm
@@ -0,0 +1,2 @@
+/decl/modpack/bosnia
+ name = "Bosniastation"
\ No newline at end of file
diff --git a/mods/content/bosniastation/_bosniastation.dme b/mods/content/bosniastation/_bosniastation.dme
new file mode 100644
index 00000000000..88169455548
--- /dev/null
+++ b/mods/content/bosniastation/_bosniastation.dme
@@ -0,0 +1,9 @@
+#ifndef MODPACK_BOSNIA
+#define BOSNIA
+// BEGIN_INCLUDE
+#include "_bosniastation.dm"
+#include "armor_rework.dm"
+#include "organ_rework.dm"
+#include "organ_tweaks.dm"
+// END_INCLUDE
+#endif
\ No newline at end of file
diff --git a/mods/content/bosniastation/armor_rework.dm b/mods/content/bosniastation/armor_rework.dm
new file mode 100644
index 00000000000..29ffb5e34b3
--- /dev/null
+++ b/mods/content/bosniastation/armor_rework.dm
@@ -0,0 +1,383 @@
+//first step of our evil plan is to replace most armor extensions with an ablative equivalent
+
+/datum/extension/armor/ablative/on_blocking(damage, damage_type, damage_flags, armor_pen, blocked)
+ if(!(damage_type == BRUTE || damage_type == BURN))
+ return
+ if(armor_degradation_coef)
+ var/key = SSmaterials.get_armor_key(damage_type, damage_flags)
+ var/damage_blocked = round(damage * blocked)
+ if(damage_blocked)
+ var/new_armor = max(0, get_value(key) - armor_degradation_coef * (damage_blocked + armor_pen))
+ set_value(key, new_armor)
+ var/mob/M = holder.get_recursive_loc_of_type(/mob)
+ if(istype(M))
+ var/list/visible = get_visible_damage()
+ for(var/k in visible)
+ if(LAZYACCESS(last_reported_damage, k) != visible[k])
+ LAZYSET(last_reported_damage, k, visible[k])
+ if (visible[k] == "completely destroyed")
+ to_chat(M, SPAN_DANGER("The [k] armor on \the [holder] is [visible[k]]!"))
+ else
+ to_chat(M, SPAN_WARNING("The [k] armor on \the [holder] has [visible[k]] damage now!"))
+
+/datum/extension/armor/ablative/proc/repair_damage(damage_type, arg_key)
+ get_damage()
+ var/list/keys
+ switch (damage_type)
+ if (BRUTE)
+ keys = list(ARMOR_BULLET, ARMOR_BOMB, ARMOR_MELEE)
+ if (BURN)
+ keys = list(ARMOR_LASER, ARMOR_BOMB, ARMOR_ENERGY)
+ if (TOX)
+ keys = list(ARMOR_BIO)
+ if (IRRADIATE)
+ keys = list(ARMOR_RAD)
+ if (ELECTROCUTE)
+ keys = list(ARMOR_ENERGY)
+ if (arg_key)
+ keys = list(arg_key)
+ var/success = FALSE
+ for (var/key in keys)
+ if (0 < max_armor_values[key] - armor_values[key])
+ success = TRUE
+ set_value(key, max_armor_values[key])
+ return success
+
+/datum/extension/armor/ablative/get_visible_damage()
+ var/list/damages = get_damage()
+ if(!LAZYLEN(damages))
+ return
+ var/result = list()
+ for(var/key in damages)
+ switch(round(100 * damages[key]/max_armor_values[key]))
+ if(5 to 10)
+ result[key] = "minor"
+ if(11 to 25)
+ result[key] = "moderate"
+ if(26 to 50)
+ result[key] = "serious"
+ if(51 to 99)
+ result[key] = "catastrophic"
+ if(100)
+ result[key] = "completely destroyed"
+ return result
+
+/datum/extension/armor/ablative/rig
+ var/sealed = FALSE
+
+/datum/extension/armor/ablative/rig/get_value(key)
+ if(key == ARMOR_BIO && sealed)
+ return 100
+ return ..()
+
+/obj/item/clothing/get_examine_strings(mob/user, distance, infix, suffix)
+ . = ..()
+ var/datum/extension/armor/ablative/armor_datum = get_extension(src, /datum/extension/armor)
+ if(istype(armor_datum, /datum/extension/armor/ablative) && length(armor_datum.get_visible_damage()))
+ . += SPAN_WARNING("It has some damage.")
+
+ if(LAZYLEN(accessories))
+ . += "It has the following attached: [counting_english_list(accessories)]"
+
+ switch(ironed_state)
+ if(WRINKLES_WRINKLY)
+ . += "It's wrinkly."
+ if(WRINKLES_NONE)
+ . += "It's completely wrinkle-free!"
+
+ var/obj/item/clothing/sensor/vitals/sensor = locate() in accessories
+ if(sensor)
+ switch(sensor.sensor_mode)
+ if(VITALS_SENSOR_OFF)
+ . += "Its sensors appear to be disabled."
+ if(VITALS_SENSOR_BINARY)
+ . += "Its binary life sensors appear to be enabled."
+ if(VITALS_SENSOR_VITAL)
+ . += "Its vital tracker appears to be enabled."
+ if(VITALS_SENSOR_TRACKING)
+ . += "Its vital tracker and tracking beacon appear to be enabled."
+
+#define RAG_COUNT(X) ceil((LAZYACCESS(X.matter, /decl/material/solid/organic/cloth) * 0.65) / SHEET_MATERIAL_AMOUNT)
+
+/obj/item/clothing/get_examine_hints(mob/user, distance, infix, suffix)
+ . = ..()
+ var/rags = RAG_COUNT(src)
+ if(rags)
+ LAZYADD(., SPAN_SUBTLE("With a sharp object, you could cut \the [src] up into [rags] section\s."))
+
+ if(length(clothing_state_modifiers))
+ var/list/interactions = list()
+ for(var/modifier_type in clothing_state_modifiers)
+ var/decl/clothing_state_modifier/modifier = GET_DECL(modifier_type)
+ interactions += modifier.name
+ LAZYADD(., SPAN_SUBTLE("Use alt-click to [english_list(interactions, and_text = " or ")]."))
+
+#undef RAG_COUNT
+
+/obj/item/clothing/Topic(href, href_list, datum/topic_state/state)
+ var/mob/user = usr
+ if(istype(user))
+ var/turf/T = get_turf(src)
+ var/can_see = T.CanUseTopic(user, global.view_topic_state) != STATUS_CLOSE
+ if(href_list["list_ungabunga"])
+ if(length(accessories) && can_see)
+ var/list/ties = list()
+ for(var/accessory in accessories)
+ ties += "[html_icon(accessory)] \a [accessory]"
+ to_chat(user, "Attached to \the [src] [length(ties) == 1 ? "is" : "are"] [english_list(ties)].")
+ return TOPIC_HANDLED
+ if(href_list["list_armor_damage"] && can_see)
+ var/datum/extension/armor/ablative/armor_datum = get_extension(src, /datum/extension/armor)
+ if(istype(armor_datum))
+ var/list/damages = armor_datum.get_visible_damage()
+ to_chat(user, "\The [src] [html_icon(src)] has some damage:")
+ for(var/key in damages)
+ if (damages[key] == "completely destroyed")
+ to_chat(user, "
[capitalize(damages[key])] [key] armor.")
+ else
+ to_chat(user, "[capitalize(damages[key])] damage to the [key] armor.")
+ return TOPIC_HANDLED
+ . = ..()
+
+//we also change how blocking works
+/datum/extension/armor/get_blocked(damage_type, damage_flags, armor_pen = 0, damage = 5)
+ var/key = SSmaterials.get_armor_key(damage_type, damage_flags)
+ if(!key)
+ return 0
+
+ var/armor = get_value(key) - armor_pen
+ if (damage_flags & (DAM_SHARP | DAM_LASER))
+ if (armor < 0)
+ return 0
+ if (armor > 0)
+ return 0.98
+ else
+ return 0.5
+ armor = max(0, armor)
+ if(!armor)
+ return 0
+
+ var/efficiency = min(damage / (armor_range_mult * armor), 1)
+ var/coef = damage <= armor ? under_armor_mult : over_armor_mult
+ return max(1 - coef * efficiency, 0)
+
+/mob/living/human/get_thickness(obj/item/organ/external/def_zone)
+ if(!def_zone)
+ def_zone = ran_zone()
+ if(!istype(def_zone))
+ def_zone = GET_EXTERNAL_ORGAN(src, def_zone)
+ if(!def_zone)
+ return ..()
+
+ . = list()
+ for(var/slot in global.standard_clothing_slots)
+ var/obj/item/clothing/gear = get_equipped_item(slot)
+ if(!istype(gear))
+ continue
+ if(length(gear.accessories))
+ for(var/obj/item/clothing/accessory in gear.accessories)
+ if(accessory.body_parts_covered & def_zone.body_part)
+ . *= accessory.agony_mod
+ if(gear.body_parts_covered & def_zone.body_part)
+ . *= gear.armor
+
+/mob/living/apply_damage(damage = 0, damagetype = BRUTE, def_zone, damage_flags = 0, obj/used_weapon, armor_pen, silent = FALSE, obj/item/organ/external/given_organ)
+
+ if(status_flags & GODMODE)
+ return FALSE
+
+ if(!damage)
+ return FALSE
+ var/list/before_armor = list(damage, damagetype, damage_flags)
+ var/list/after_armor = modify_damage_by_armor(def_zone, damage, damagetype, damage_flags, src, armor_pen, silent)
+ damage = after_armor[1]
+ damagetype = after_armor[2]
+ damage_flags = after_armor[3] // args modifications in case of parent calls
+ if(!damage)
+ return FALSE
+
+ if (before_armor[3] & DAM_SHARP)
+ var/agony_mod = get_thickness(def_zone)
+ var/raw_block = before_armor[1] - after_armor[1]
+ take_damage(raw_block * agony_mod, PAIN)
+
+ switch(damagetype)
+ if(BURN)
+ if(has_genetic_condition(GENE_COND_COLD_RESISTANCE))
+ return
+ take_damage(damage, BURN, damage_flags, used_weapon, armor_pen)
+ if(ELECTROCUTE)
+ electrocute_act(damage, used_weapon, 1, def_zone)
+ else
+ take_damage(damage, damagetype, damage_flags, used_weapon, armor_pen)
+ return TRUE
+
+/mob/living/proc/get_thickness(obj/item/organ/external/def_zone)
+ return 0.5
+
+//this is just so armor datums match up
+
+/mob/GetVoice()
+ var/voice_sub
+ var/obj/item/rig/rig = get_rig()
+ if(rig?.speech?.voice_holder?.active && rig.speech.voice_holder.voice)
+ voice_sub = rig.speech.voice_holder.voice
+
+ if(!voice_sub)
+
+ var/list/check_gear = list(get_equipped_item(slot_wear_mask_str), get_equipped_item(slot_head_str))
+ if(rig)
+ var/datum/extension/armor/ablative/rig/armor_datum = get_extension(rig, /datum/extension/armor)
+ if(istype(armor_datum) && armor_datum.sealed && rig.helmet == get_equipped_item(slot_head_str))
+ check_gear |= rig
+
+ for(var/obj/item/gear in check_gear)
+ if(!gear)
+ continue
+ var/obj/item/voice_changer/changer = locate() in gear
+ if(changer && changer.active && changer.voice)
+ voice_sub = changer.voice
+
+ if(voice_sub)
+ return voice_sub
+
+ return real_name || name
+
+//repairs
+/obj/item/clothing/suit/space/proc/repair_armor(var/damtype, var/mob/user)
+ var/datum/extension/armor/ablative/armor_datum = get_extension(src, /datum/extension/armor)
+ if (istype(armor_datum) && armor_datum.repair_damage(damtype, null))
+ user.visible_message(
+ SPAN_NOTICE("\The [user] repairs the armor of \the [src]."),
+ SPAN_NOTICE("You repair the armor of \the [src].")
+ )
+
+/obj/item/clothing/suit/space/attackby(obj/item/used_item, mob/user)
+ if(istype(used_item,/obj/item/stack/material))
+ var/repair_power = 0
+ switch(used_item.get_material_type())
+ if(/decl/material/solid/metal/steel)
+ repair_power = 2
+ if(/decl/material/solid/organic/plastic)
+ repair_power = 1
+
+ if(!repair_power)
+ return FALSE
+
+ if(ishuman(loc))
+ var/mob/living/human/H = loc
+ if(H.get_equipped_item(slot_wear_suit_str) == src)
+ to_chat(user, SPAN_WARNING("You cannot repair \the [src] while it is being worn."))
+ return TRUE
+
+ var/obj/item/stack/P = used_item
+ var/use_amt = min(P.get_amount(), 3)
+ if(!use_amt || !P.use(use_amt))
+ return FALSE
+
+ repair_armor(BURN, user)
+
+ if(burn_damage <= 0)
+ to_chat(user, "There is no surface damage on \the [src] to repair.") //maybe change the descriptor to more obvious? idk what
+ return TRUE
+
+ repair_breaches(BURN, use_amt * repair_power, user)
+ return TRUE
+
+ else if(IS_WELDER(used_item))
+
+ if(ishuman(loc))
+ var/mob/living/human/H = loc
+ if(H.get_equipped_item(slot_wear_suit_str) == src)
+ to_chat(user, SPAN_WARNING("You cannot repair \the [src] while it is being worn."))
+ return TRUE
+
+ var/obj/item/weldingtool/welder = used_item
+ if(!welder.weld(5))
+ to_chat(user, SPAN_WARNING("You need more welding fuel to repair this suit."))
+ return TRUE
+
+ repair_armor(BRUTE, user)
+
+ if (brute_damage <= 0)
+ to_chat(user, "There is no structural damage on \the [src] to repair.")
+ return TRUE
+
+ repair_breaches(BRUTE, 3, user)
+ return TRUE
+
+ else if(istype(used_item, /obj/item/stack/tape_roll/duct_tape))
+ var/datum/breach/target_breach //Target the largest unpatched breach.
+ for(var/datum/breach/B in breaches)
+ if(B.patched)
+ continue
+ if(!target_breach || (B.class > target_breach.class))
+ target_breach = B
+
+ if(!target_breach)
+ to_chat(user, "There are no open breaches to seal with \the [used_item].")
+ else
+ var/obj/item/stack/tape_roll/duct_tape/D = used_item
+ var/amount_needed = ceil(target_breach.class * 2)
+ if(!D.can_use(amount_needed))
+ to_chat(user, SPAN_WARNING("There's not enough [D.plural_name] in your [src] to seal \the [target_breach.descriptor] on \the [src]! You need at least [amount_needed] [D.plural_name]."))
+ return TRUE
+
+ if(do_after(user, user.get_equipped_item(slot_wear_suit_str) == src? 6 SECONDS : 3 SECONDS, isliving(loc)? loc : null)) //Sealing a breach on your own suit is awkward and time consuming
+ D.use(amount_needed)
+ playsound(src, 'sound/effects/tape.ogg',25)
+ user.visible_message(
+ SPAN_NOTICE("\The [user] uses some [D.plural_name] to seal \the [target_breach.descriptor] on \the [src]."),
+ SPAN_NOTICE("You use [amount_needed] [D.plural_name] of \the [used_item] to seal \the [target_breach.descriptor] on \the [src].")
+ )
+ target_breach.patched = TRUE
+ target_breach.update_descriptor()
+ calc_breach_damage()
+ return TRUE
+ return ..()
+
+//now we change clothing to match
+
+/obj/item/rig
+ armor_type = /datum/extension/armor/ablative/rig
+ armor_degradation_speed = 0.075
+ var/agony_mod = 0.75
+
+/obj/item/rig/light
+ agony_mod = 1
+
+/obj/item/rig/merc/heavy
+ agony_mod = 0.5
+
+/obj/item/clothing
+ armor_type = /datum/extension/armor/ablative
+ armor_degradation_speed = 0.1
+ var/agony_mod = 0.9
+
+/obj/item/clothing/suit/armor/bulletproof
+ agony_mod = 0.75
+
+/obj/item/clothing/suit/armor/riot
+ agony_mod = 0.5
+
+/obj/item/clothing/shoes/legguards/riot
+ agony_mod = 0.5
+
+/obj/item/clothing/gloves/armguards/riot
+ agony_mod = 0.5
+
+/obj/item/clothing/suit/bomb_suit
+ agony_mod = 0.75
+
+/obj/item/clothing/suit/armor/forged
+ armor_degradation_speed = 0.2
+
+/obj/item/clothing/suit/armor/crafted
+ armor_degradation_speed = 0.2
+
+/obj/item/clothing/armor_attachment/plate
+ armor_degradation_speed = 0.3
+ agony_mod = 1
+
+/obj/item/clothing/head/helmet/riot
+ agony_mod = 0.5
\ No newline at end of file
diff --git a/mods/content/bosniastation/organ_rework.dm b/mods/content/bosniastation/organ_rework.dm
new file mode 100644
index 00000000000..600b15470e4
--- /dev/null
+++ b/mods/content/bosniastation/organ_rework.dm
@@ -0,0 +1,362 @@
+//we separate this horror from the rest of organ stuff as it is almost entirely one line changes in massive blocks of code but also kind of has to be a mod
+
+#define DAM_ARTERY 128 // Massively reduces chance of organ damage, while increasing chance of severing an artery
+
+/decl/grab/normal/attack_throat(var/obj/item/grab/grab, var/obj/item/used_item, mob/user)
+ var/mob/living/affecting = grab.get_affecting_mob()
+ if(!affecting)
+ return
+ if(!user.check_intent(I_FLAG_HARM))
+ return 0 // Not trying to hurt them.
+
+ if(!used_item.has_edge() || !used_item.get_attack_force(user) || used_item.atom_damage_type != BRUTE)
+ return 0 //unsuitable weapon
+ user.visible_message("\The [user] begins to slit [affecting]'s throat with \the [used_item]!")
+
+ user.next_move = world.time + 20 //also should prevent user from triggering this repeatedly
+ if(!do_after(user, 20*user.skill_delay_mult(SKILL_COMBAT) , progress = 0))
+ return 0
+ if(!(grab && grab.affecting == affecting)) //check that we still have a grab
+ return 0
+
+ var/damage_mod = 1
+ var/damage_flags = used_item.damage_flags() | DAM_ARTERY
+ //presumably, if they are wearing a helmet that stops pressure effects, then it probably covers the throat as well
+ var/force = used_item.expend_attack_force(user)
+ var/obj/item/clothing/head/helmet = affecting.get_equipped_item(slot_head_str)
+ if(istype(helmet) && (helmet.body_parts_covered & SLOT_HEAD) && (helmet.item_flags & ITEM_FLAG_AIRTIGHT) && !isnull(helmet.max_pressure_protection))
+ var/datum/extension/armor/armor_datum = get_extension(helmet, /datum/extension/armor)
+ if(armor_datum)
+ damage_mod -= armor_datum.get_blocked(BRUTE, damage_flags, used_item.armor_penetration, force*1.5)
+
+ var/total_damage = 0
+ for(var/i in 1 to 3)
+ var/damage = min(force*1.5, 20)*damage_mod
+ affecting.apply_damage(damage, used_item.atom_damage_type, BP_HEAD, damage_flags, armor_pen = 100, used_weapon=used_item)
+ total_damage += damage
+
+ if(total_damage)
+ user.visible_message("\The [user] slit [affecting]'s throat open with \the [used_item]!")
+
+ if(used_item.hitsound)
+ playsound(affecting.loc, used_item.hitsound, 50, 1, -1)
+
+ grab.last_action = world.time
+
+ admin_attack_log(user, affecting, "Knifed their victim", "Was knifed", "knifed")
+ return 1
+
+/obj/item/organ/external/take_damage(damage, damage_type = BRUTE, damage_flags, inflicter, armor_pen = 0, silent, do_update_health, override_droplimb)
+
+ if(!owner)
+ return ..()
+
+ var/final_brute_mod = get_brute_mod(damage_flags) + (0.2 * burn_dam/max_damage) // extra brute taken if you have burn damage. why? ask whoever originally coded it.
+ var/final_burn_mod = get_burn_mod(damage_flags)
+
+ var/brute = damage_type == BRUTE ? round(damage * final_brute_mod, 0.1) : 0
+ var/burn = damage_type == BURN ? round(damage * final_burn_mod, 0.1) : 0
+
+ if((brute <= 0) && (burn <= 0))
+ return 0
+
+ var/sharp = (damage_flags & DAM_SHARP)
+ var/edge = (damage_flags & DAM_EDGE)
+ var/laser = (damage_flags & DAM_LASER)
+ var/blunt = !!(brute && !sharp && !edge)
+
+ // Handle some status-based damage multipliers.
+ if(BP_IS_CRYSTAL(src) && burn && laser)
+ brute += burn // Stress fracturing from heat!
+ owner.bodytemperature += burn
+ burn = 0
+ if(prob(25))
+ owner.visible_message(SPAN_WARNING("\The [owner]'s crystalline [name] shines with absorbed energy!"))
+
+ if(inflicter)
+ add_autopsy_data(inflicter, brute + burn)
+
+ var/spillover = 0
+ var/pure_brute = brute
+ if(!is_damageable(brute + burn))
+ spillover = brute_dam + burn_dam + brute - max_damage
+ if(spillover > 0)
+ brute = max(brute - spillover, 0)
+ else
+ spillover = brute_dam + burn_dam + brute + burn - max_damage
+ if(spillover > 0)
+ burn = max(burn - spillover, 0)
+
+ //If limb took enough damage, try to cut or tear it off
+ if(owner && loc == owner)
+ owner.update_health() //droplimb will call update_health() again if it does end up being called
+ if((limb_flags & ORGAN_FLAG_CAN_AMPUTATE) && get_config_value(/decl/config/toggle/on/health_limbs_can_break))
+ var/total_damage = brute_dam + burn_dam + brute + burn + spillover
+ var/threshold = max_damage * get_config_value(/decl/config/num/health_organ_health_multiplier)
+ if(total_damage > threshold)
+ if(attempt_dismemberment(pure_brute, burn, sharp, edge, inflicter, spillover, total_damage > threshold*6, override_droplimb = override_droplimb))
+ return
+
+ //blunt damage is gud at fracturing
+ if(brute_dam + brute > min_broken_damage && prob(brute_dam + brute * (1+blunt)) )
+ fracture()
+
+ // High brute damage or sharp objects may damage internal organs
+ if(LAZYLEN(internal_organs) && damage_internal_organs(brute, burn, damage_flags))
+ brute /= 2
+ burn /= 2
+
+ if((status & ORGAN_BROKEN) && brute)
+ jostle_bone(brute)
+ if(can_feel_pain() && prob(40))
+ owner.emote(/decl/emote/audible/scream) //getting hit on broken hand hurts
+
+ // If the limbs can break, make sure we don't exceed the maximum damage a limb can take before breaking
+ var/datum/wound/created_wound
+ var/block_cut = (species.species_flags & SPECIES_FLAG_NO_MINOR_CUT) && brute <= 15
+ var/can_cut = !block_cut && !BP_IS_PROSTHETIC(src) && (sharp || prob(brute))
+
+ if(brute)
+ var/to_create = BRUISE
+ if(can_cut)
+ to_create = CUT
+ //need to check sharp again here so that blunt damage that was strong enough to break skin doesn't give puncture wounds
+ if(sharp && !edge)
+ to_create = PIERCE
+ var/arterial = damage_flags & DAM_ARTERY
+ created_wound = createwound(to_create, brute, arterial)
+
+ if(burn)
+ if(laser)
+ created_wound = createwound(LASER, burn)
+ if(prob(40))
+ owner.ignite_fire()
+ else
+ created_wound = createwound(BURN, burn)
+
+ //Initial pain spike
+ add_pain(0.6*burn + 0.4*brute)
+
+ //Disturb treated burns
+ if(brute > 5)
+ var/disturbed = 0
+ for(var/datum/wound/burn/wound in wounds)
+ if((wound.disinfected || wound.salved) && prob(brute + wound.damage))
+ wound.disinfected = 0
+ wound.salved = 0
+ disturbed += wound.damage
+ if(disturbed)
+ to_chat(owner,"Ow! Your burns were disturbed.")
+ add_pain(0.5*disturbed)
+
+ //If there are still hurties to dispense
+ if (spillover)
+ owner.shock_stage += spillover * get_config_value(/decl/config/num/health_organ_damage_spillover_multiplier)
+
+ // sync the organ's damage with its wounds
+ update_damages()
+ if(do_update_health)
+ owner.update_health()
+ if(status & ORGAN_BLEEDING)
+ owner.update_bandages()
+
+ if(owner && update_damstate())
+ owner.update_damage_overlays()
+
+ if(created_wound && isobj(inflicter))
+ var/obj/O = inflicter
+ O.after_wounding(src, created_wound)
+
+ return created_wound
+
+/obj/item/organ/external/createwound(var/type = CUT, var/damage, var/surgical, var/arterial = FALSE)
+
+ if(!owner || damage <= 0)
+ return
+
+ if(BP_IS_CRYSTAL(src))
+ type = SHATTER
+ if(damage >= 15 || prob(1))
+ playsound(loc, 'sound/effects/hit_on_shattered_glass.ogg', 40, 1) // Crash!
+ else if((limb_flags & ORGAN_FLAG_SKELETAL) || (BP_IS_PROSTHETIC(src) && !bodytype.is_robotic))
+ if(type == BURN)
+ type = CHARRED
+ else
+ type = SHATTER
+
+ //moved these before the open_wound check so that having many small wounds for example doesn't somehow protect you from taking internal damage (because of the return)
+ //Brute damage can possibly trigger an internal wound, too.
+ var/local_damage = brute_dam + burn_dam + damage
+ if(!surgical && (type in list(CUT, PIERCE, BRUISE)) && damage > 15 && local_damage > 30)
+
+ var/internal_damage
+ if(prob(damage + (arterial)*50) && sever_artery())
+ internal_damage = TRUE
+ if(prob(ceil(damage/4)) && sever_tendon())
+ internal_damage = TRUE
+ if(internal_damage)
+ owner.custom_pain("You feel something rip in your [name]!", 50, affecting = src)
+
+ //Burn damage can cause fluid loss due to blistering and cook-off
+ if((type in list(BURN, LASER)) && (damage > 5 || damage + burn_dam >= 15) && !BP_IS_PROSTHETIC(src))
+ var/fluid_loss_severity
+ switch(type)
+ if(BURN) fluid_loss_severity = FLUIDLOSS_WIDE_BURN
+ if(LASER) fluid_loss_severity = FLUIDLOSS_CONC_BURN
+ var/fluid_loss = (damage/(owner.get_max_health() - get_config_value(/decl/config/num/health_health_threshold_dead))) * SPECIES_BLOOD_DEFAULT * fluid_loss_severity
+ owner.remove_blood(fluid_loss)
+
+ // first check whether we can widen an existing wound
+ if(!surgical && LAZYLEN(wounds) && prob(max(50+(number_wounds-1)*10,90)))
+ if((type == CUT || type == BRUISE) && damage >= 5)
+ //we need to make sure that the wound we are going to worsen is compatible with the type of damage...
+ var/list/compatible_wounds = list()
+ for (var/datum/wound/wound in wounds)
+ if (wound.can_worsen(type, damage))
+ compatible_wounds += wound
+
+ if(compatible_wounds.len)
+ var/datum/wound/wound = pick(compatible_wounds)
+ wound.open_wound(damage)
+ if(owner && prob(25))
+ if(BP_IS_CRYSTAL(src))
+ owner.visible_message(SPAN_DANGER("The cracks in \the [owner]'s [name] spread."),\
+ SPAN_DANGER("The cracks in your [name] spread."),\
+ SPAN_DANGER("You hear the cracking of crystal."))
+ else if(BP_IS_PROSTHETIC(src))
+ owner.visible_message(SPAN_DANGER("The damage to \the [owner]'s [name] worsens."),\
+ SPAN_DANGER("The damage to your [name] worsens."),\
+ SPAN_DANGER("You hear the screech of abused metal."))
+ else
+ owner.visible_message(SPAN_DANGER("The wound on \the [owner]'s [name] widens with a nasty ripping noise."),\
+ SPAN_DANGER("The wound on your [name] widens with a nasty ripping noise."),\
+ SPAN_DANGER("You hear a nasty ripping noise, as if flesh is being torn apart."))
+ return wound
+
+ //Creating wound
+ var/wound_type = get_wound_type(type, damage)
+
+ if(wound_type)
+ var/datum/wound/wound = new wound_type(damage, src, surgical)
+
+ //Check whether we can add the wound to an existing wound
+ if(surgical)
+ wound.autoheal_cutoff = 0
+ else
+ for(var/datum/wound/other in wounds)
+ if(other.can_merge_wounds(wound))
+ other.merge_wound(wound)
+ return other
+ LAZYADD(wounds, wound)
+ return wound
+
+/obj/item/organ/external/damage_internal_organs(brute, burn, damage_flags)
+ if(!LAZYLEN(internal_organs))
+ return FALSE
+
+ var/laser = (damage_flags & DAM_LASER)
+ var/sharp = (damage_flags & DAM_SHARP)
+
+ var/damage_amt = brute
+ var/cur_damage = brute_dam
+ if(laser || BP_IS_PROSTHETIC(src))
+ damage_amt += burn
+ cur_damage += burn_dam
+
+ if(!damage_amt)
+ return FALSE
+
+ var/organ_damage_threshold = 10
+ if(sharp || organ_tag == BP_HEAD)
+ organ_damage_threshold *= 0.5
+ if(laser)
+ organ_damage_threshold *= 2
+ var/arterial = damage_flags & DAM_ARTERY
+ if(!(cur_damage + damage_amt >= max_damage) && !(damage_amt >= organ_damage_threshold + arterial * 50))
+ return FALSE
+ var/success = FALSE
+ var/list/victims = list()
+ for(var/obj/item/organ/internal/organ in internal_organs)
+ if(organ.get_organ_damage() < organ.max_damage)
+ victims[organ] = min(organ.relative_size + 3 * damage_amt/organ_damage_threshold, 100)
+ var/organ_chance = victims[organ]
+ if (!sharp)
+ organ_chance = min(100, organ_chance*1.5)
+
+ if(prob(organ_chance))
+ var/local_damage_reduction = 0
+ if(encased && !(status & ORGAN_BROKEN)) //ribs protect
+ local_damage_reduction += 0.35
+ if (damage_flags & DAM_SHARP)
+ local_damage_reduction += 0.25
+ damage_amt -= damage_amt*organ.damage_reduction
+ damage_amt -= damage_amt*local_damage_reduction
+ damage_amt = max(damage_amt, 0)
+ organ.take_damage(damage_amt)
+ success = TRUE
+ return success
+
+/obj/item/gun/play_fire_sound(atom/movable/firer, obj/item/projectile/P)
+ var/shot_sound = fire_sound
+ var/shot_sound_vol = 50
+ if((istype(P) && P.fire_sound))
+ shot_sound = P.fire_sound
+ shot_sound_vol = P.fire_sound_vol
+ if(silencer)
+ shot_sound_vol = P.fire_sound_vol_silenced
+
+ playsound(firer, shot_sound, shot_sound_vol, 1)
+
+//Suicide handling.
+
+/obj/item/gun/handle_suicide(mob/living/user)
+ if(!ishuman(user))
+ return
+ var/mob/living/human/M = user
+
+ mouthshoot = 1
+ admin_attacker_log(user, "is attempting to suicide with \a [src]")
+ M.visible_message("[user] sticks their gun in their mouth, ready to pull the trigger...")
+ if(!do_after(user, 40, progress=0))
+ M.visible_message(SPAN_NOTICE("[user] decided life was worth living."))
+ mouthshoot = 0
+ return
+
+ if(safety())
+ user.visible_message("*click click*", SPAN_DANGER("*click*"))
+ playsound(src.loc, 'sound/weapons/empty.ogg', 100, 1)
+ mouthshoot = 0
+ return
+
+ var/obj/item/projectile/in_chamber = consume_next_projectile()
+ if (istype(in_chamber))
+ user.visible_message("[user] pulls the trigger.")
+ var/shot_sound = in_chamber.fire_sound? in_chamber.fire_sound : fire_sound
+ if(silencer)
+ playsound(user, shot_sound, 10, 1)
+ else
+ playsound(user, shot_sound, 50, 1)
+ if(istype(in_chamber, /obj/item/projectile/beam/lastertag))
+ user.show_message("You feel rather silly, trying to commit suicide with a toy.")
+ mouthshoot = 0
+ return
+
+ in_chamber.on_hit(M)
+ if (in_chamber.atom_damage_type != PAIN)
+ log_and_message_admins("[key_name(user)] commited suicide using \a [src]")
+ var/shot_damage = in_chamber.damage
+ if (istype (in_chamber, /obj/item/projectile/bullet/pellet)) //handle buckshot
+ var/obj/item/projectile/bullet/pellet/shell = in_chamber
+ shot_damage = shell.pellets*shell.damage
+ user.apply_damage(shot_damage, in_chamber.atom_damage_type, BP_HEAD, in_chamber.damage_flags(), used_weapon = "Point blank shot in the mouth with \a [in_chamber]")
+ user.death()
+ else
+ to_chat(user, "Ow...")
+ user.apply_effect(110,PAIN,0)
+ qdel(in_chamber)
+ mouthshoot = 0
+ return
+ else
+ handle_click_empty(user)
+ mouthshoot = 0
+ return
diff --git a/mods/content/bosniastation/organ_tweaks.dm b/mods/content/bosniastation/organ_tweaks.dm
new file mode 100644
index 00000000000..44ce4982f73
--- /dev/null
+++ b/mods/content/bosniastation/organ_tweaks.dm
@@ -0,0 +1,18 @@
+/obj/item/organ/internal/brain //brain tweaks are inadvisable without the full rework, but they are separate for clarity
+ relative_size = 40
+ damage_reduction = -2
+
+/obj/item/organ/internal/brain/take_damage(damage, damage_type = BRUTE, damage_flags, inflicter, armor_pen = 0, silent, do_update_health)
+ . = ..()
+ if (owner && damage >= 10 && _organ_damage > 75) //This probably won't be triggered by oxyloss or mercury. Probably.
+ var/damage_secondary = damage * 0.20
+ owner.flash_eyes()
+ SET_STATUS_MAX(owner, STAT_BLURRY, damage_secondary)
+ SET_STATUS_MAX(owner, STAT_CONFUSE, damage_secondary * 2)
+ SET_STATUS_MAX(owner, STAT_PARA, damage_secondary)
+ SET_STATUS_MAX(owner, STAT_WEAK, round(damage, 1))
+ if (prob(30))
+ addtimer(CALLBACK(src, PROC_REF(brain_damage_callback), damage), rand(6, 20) SECONDS, TIMER_UNIQUE)
+
+/obj/item/organ/internal/heart
+ damage_reduction = 0
\ No newline at end of file