mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 10:43:20 +00:00
Ballistics v2 draft
This commit is contained in:
246
code/modules/mob/living/bullet_act_ch.dm
Normal file
246
code/modules/mob/living/bullet_act_ch.dm
Normal file
@@ -0,0 +1,246 @@
|
||||
#define BULLET_AP_DIVISOR 200
|
||||
#define AP_DIVISOR 4152
|
||||
#define ARMOR_Y_INTERCEPT 0.2
|
||||
#define ARMOR_SLOPE 0.017
|
||||
#define PENETRATION_PROBABILITY_EXP_BASE 2
|
||||
#define PENETRATION_PROBABILITY_EXP_MULT 30
|
||||
|
||||
#define BULLET_DEFLECTED_PAIN_DIVISOR 5000
|
||||
#define BULLET_DEFLECTED_BULLET_DIVISOR 70
|
||||
#define BULLET_DEFLECTED_MELEE_DIVISOR 280
|
||||
|
||||
#define SKIN_LOSS_COEFFICIENT 61
|
||||
#define ARMOR_LOSS_COEFFICIENT 200
|
||||
#define ARMOR_LOSS_MIN_MULT 0.5
|
||||
#define ARMOR_LOSS_MIN_ARMOR 20
|
||||
#define INTERNAL_LOSS_COEFFICIENT 250
|
||||
#define ORGAN_LOSS_COEFFICIENT 350
|
||||
#define ORGAN_LEAVE_EARLY list("l_arm", "r_arm", "l_hand", "r_hand", "l_foot", "r_foot")
|
||||
#define HIT_ORGAN_CHANCE_VITALS 90
|
||||
#define HIT_VITAL_ORGAN_CHANCE 30
|
||||
|
||||
#define BONE_HIT_CHANCE list("torso" = 0.2, "groin" = 0.2, "l_foot" = 0.8, "r_foot" = 0.8, "l_leg" = 0.35, "r_leg" = 0.35, "l_arm" = 0.65, "r_arm" = 0.65, "l_hand" = 0.8, "r_hand" = 0.8)
|
||||
#define BONE_HIT_CHANCE_UNENCASED 45
|
||||
#define BONE_HIT_CHANCE_ENCASED 80
|
||||
#define BONE_JOULES_PERHP_AVG 30
|
||||
#define BONE_JOULES_PERHP_DEV 10
|
||||
#define BONE_HP_AVG 25
|
||||
|
||||
#define PROB_LEAVE_EARLY_FIRST 20
|
||||
#define PROB_LEAVE_EARLY_SECOND 40
|
||||
|
||||
#define GAUSSIAN_RANDOM(vars...) ((-2*log(rand()))**0.5 * cos(6.28318530718*rand()))
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////// CADYN'S BALLISTICS ////////////////////////////////////////////////////////////////////////// ORIGINAL FROM CHOMPSTATION ////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/mob/living/proc/handle_ballistics(var/obj/item/projectile/bullet/P, var/def_zone)
|
||||
var/ballistic_armor = getarmor(def_zone, "bullet")
|
||||
var/melee_armor = getarmor(def_zone, "melee")
|
||||
var/obj/item/organ/external/hit_organ
|
||||
var/mob/living/carbon/human/H = src
|
||||
if(istype(H))
|
||||
hit_organ = H.get_organ(def_zone)
|
||||
var/penetration_chance = armor_penetration_probability(ballistic_armor,P)
|
||||
if(!prob(penetration_chance)) //Boo-hoo we got deflected. Do boring agony/bruises stuff.
|
||||
var/pain_hit = hit_organ ? "into your [hit_organ]" : "into you"
|
||||
|
||||
var/hurt_value = P.velocity * P.grains / (BULLET_DEFLECTED_PAIN_DIVISOR * (1 + ballistic_armor/70 + melee_armor/280)) //Better armor spreads out the energy better.
|
||||
var/hurt_value_pain = hurt_value ** 1.5
|
||||
var/hurt_value_bruise = max(0,hurt_value-5)
|
||||
|
||||
var/absorber = ballistic_armor ? "armor" : "body" //There is a super tiny chance that small rounds can get deflected without armor, so this is just incase.
|
||||
|
||||
to_chat(src,"<span class='warning'>You feel the energy of the bullet painfully transfered [pain_hit] as your [absorber] deflects it!</span>")
|
||||
apply_damage(hurt_value_pain,HALLOSS,def_zone)
|
||||
if(hurt_value_bruise)
|
||||
apply_damage(hurt_value_bruise,BRUTE,def_zone)
|
||||
P.sub_velocity(P.velocity)
|
||||
return 2
|
||||
else //Now the FUN begins
|
||||
var/area_over_mass = P.diam * P.diam / P.grains
|
||||
//Most of these calculations don't involve energies because I'm treating flesh and organic tissue as a fluid since it's squishy and stuff.
|
||||
//Since drag is proportional to velocity, we can do things on an m*v basis instead of an mv^2 basis.
|
||||
//Obviously bones are more solid, so we do actual energy calculations for that.
|
||||
var/energy_dumped_organic = 0
|
||||
var/vel_lost_armor = ballistic_armor >= ARMOR_LOSS_MIN_ARMOR ? ARMOR_LOSS_COEFFICIENT * area_over_mass * ((1 + ARMOR_LOSS_MIN_MULT) - penetration_chance) : 0
|
||||
P.sub_velocity(vel_lost_armor)
|
||||
|
||||
var/energy_past = P.energy
|
||||
var/internal_loss = INTERNAL_LOSS_COEFFICIENT * area_over_mass
|
||||
var/vel_lost_skin = SKIN_LOSS_COEFFICIENT * area_over_mass
|
||||
P.sub_velocity(vel_lost_skin + internal_loss)
|
||||
energy_dumped_organic += (energy_past - P.energy)
|
||||
if(prob(PROB_LEAVE_EARLY_FIRST) || !P.velocity)
|
||||
energy_to_damage(energy_dumped_organic)
|
||||
return 1
|
||||
if(hit_organ)
|
||||
return organ_handle_ballistics(P,hit_organ,energy_dumped_organic,internal_loss,ballistic_armor)
|
||||
else
|
||||
return general_handle_ballistics(P,def_zone,energy_dumped_organic,internal_loss,ballistic_armor)
|
||||
|
||||
/mob/living/proc/organ_handle_ballistics(var/obj/item/projectile/bullet/P,var/obj/item/organ/external/hit_organ,var/energy_dumped_organic,var/internal_loss,var/ballistic_armor)
|
||||
var/energy_past
|
||||
var/area_over_mass = P.diam * P.diam / P.grains
|
||||
var/bone_chance = BONE_HIT_CHANCE_UNENCASED
|
||||
if(hit_organ.encased)
|
||||
bone_chance = BONE_HIT_CHANCE_ENCASED
|
||||
else
|
||||
bone_chance = BONE_HIT_CHANCE[hit_organ.organ_tag]
|
||||
if(prob(bone_chance))
|
||||
var/energy_to_fracture = max(300, hit_organ.min_broken_damage * (GAUSSIAN_RANDOM()*BONE_JOULES_PERHP_DEV + BONE_JOULES_PERHP_AVG))
|
||||
if(energy_to_fracture>=P.energy) //We don't have enough energy to get through the bone. This is the end for us!
|
||||
energy_dumped_organic += P.energy/2 //About half of our remaining energy will go into fucking up this boi, the rest is absorbed by the bone
|
||||
P.sub_velocity(P.velocity)
|
||||
energy_to_damage(energy_dumped_organic)
|
||||
return 2
|
||||
else
|
||||
P.sub_energy(energy_to_fracture)
|
||||
energy_dumped_organic += P.energy / 3 //About a third of the energy that goes into fracturing the bone also goes into fucking up tissues.
|
||||
if(!(hit_organ & ORGAN_BROKEN))
|
||||
hit_organ.fracture()
|
||||
|
||||
if(hit_organ.internal_organs.len && P.velocity > area_over_mass*ORGAN_LOSS_COEFFICIENT && prob(90))
|
||||
energy_past = P.energy
|
||||
P.sub_velocity(internal_loss)
|
||||
damage_organ_energy(energy_past - P.energy, pick(hit_organ.internal_organs))
|
||||
if(!P.velocity)
|
||||
energy_to_damage(energy_dumped_organic)
|
||||
return 2
|
||||
energy_past = P.energy
|
||||
P.sub_velocity(internal_loss)
|
||||
energy_dumped_organic += P.energy
|
||||
if(!P.velocity || (hit_organ.organ_tag in ORGAN_LEAVE_EARLY) || prob(PROB_LEAVE_EARLY_SECOND))
|
||||
energy_to_damage(energy_dumped_organic)
|
||||
return P.velocity ? -1 : 2
|
||||
|
||||
if(prob(bone_chance))
|
||||
var/energy_to_fracture = max(300, hit_organ.min_broken_damage * (GAUSSIAN_RANDOM()*BONE_JOULES_PERHP_DEV + BONE_JOULES_PERHP_AVG))
|
||||
if(energy_to_fracture>=P.energy) //We don't have enough energy to get through the bone. This is the end for us!
|
||||
energy_dumped_organic += P.energy/2 //About half of our remaining energy will go into fucking up this boi, the rest is absorbed by the bone
|
||||
P.sub_velocity(P.velocity)
|
||||
energy_to_damage(energy_dumped_organic)
|
||||
return 2
|
||||
else
|
||||
P.sub_energy(energy_to_fracture)
|
||||
energy_dumped_organic += P.energy / 3 //About a third of the energy that goes into fracturing the bone also goes into fucking up tissues.
|
||||
if(!(hit_organ & ORGAN_BROKEN))
|
||||
hit_organ.fracture()
|
||||
energy_past = P.energy
|
||||
P.sub_velocity(internal_loss)
|
||||
energy_dumped_organic += P.energy
|
||||
if(!P.velocity)
|
||||
energy_to_damage(energy_dumped_organic)
|
||||
return 2
|
||||
var/penetration_chance = armor_penetration_probability(ballistic_armor,P)
|
||||
if(prob(penetration_chance))
|
||||
energy_to_damage(energy_dumped_organic)
|
||||
return -1
|
||||
else
|
||||
return organ_handle_ballistics(P,hit_organ,energy_dumped_organic,internal_loss,ballistic_armor)
|
||||
|
||||
/mob/living/proc/general_handle_ballistics(var/obj/item/projectile/bullet/P,var/def_zone,var/energy_dumped_organic,var/internal_loss,var/ballistic_armor)
|
||||
var/energy_past
|
||||
var/area_over_mass = P.diam * P.diam / P.grains
|
||||
var/bone_chance = BONE_HIT_CHANCE_UNENCASED
|
||||
if(prob(bone_chance))
|
||||
var/energy_to_fracture = max(300, BONE_HP_AVG * (GAUSSIAN_RANDOM()*BONE_JOULES_PERHP_DEV + BONE_JOULES_PERHP_AVG))
|
||||
if(energy_to_fracture>=P.energy) //We don't have enough energy to get through the bone. This is the end for us!
|
||||
energy_dumped_organic += P.energy/2 //About half of our remaining energy will go into fucking up this boi, the rest is absorbed by the bone
|
||||
P.sub_velocity(P.velocity)
|
||||
energy_to_damage(energy_dumped_organic)
|
||||
return 2
|
||||
else
|
||||
P.sub_energy(energy_to_fracture)
|
||||
energy_dumped_organic += P.energy / 3 //About a third of the energy that goes into fracturing the bone also goes into fucking up tissues.
|
||||
|
||||
if(P.velocity > area_over_mass * ORGAN_LOSS_COEFFICIENT && prob(HIT_VITAL_ORGAN_CHANCE))
|
||||
energy_past = P.energy
|
||||
P.sub_velocity(internal_loss)
|
||||
energy_dumped_organic += (energy_past - P.energy) * 2
|
||||
if(!P.velocity)
|
||||
energy_to_damage(energy_dumped_organic)
|
||||
return 2
|
||||
energy_past = P.energy
|
||||
P.sub_velocity(internal_loss)
|
||||
energy_dumped_organic += P.energy
|
||||
if(!P.velocity || (def_zone in ORGAN_LEAVE_EARLY) || prob(PROB_LEAVE_EARLY_SECOND))
|
||||
energy_to_damage(energy_dumped_organic)
|
||||
return P.velocity ? -1 : 2
|
||||
|
||||
if(prob(bone_chance))
|
||||
var/energy_to_fracture = max(300, BONE_HP_AVG * (GAUSSIAN_RANDOM()*BONE_JOULES_PERHP_DEV + BONE_JOULES_PERHP_AVG))
|
||||
if(energy_to_fracture>=P.energy) //We don't have enough energy to get through the bone. This is the end for us!
|
||||
energy_dumped_organic += P.energy/2 //About half of our remaining energy will go into fucking up this boi, the rest is absorbed by the bone
|
||||
P.sub_velocity(P.velocity)
|
||||
energy_to_damage(energy_dumped_organic)
|
||||
return 2
|
||||
else
|
||||
P.sub_energy(energy_to_fracture)
|
||||
energy_dumped_organic += P.energy / 3 //About a third of the energy that goes into fracturing the bone also goes into fucking up tissues.
|
||||
|
||||
energy_past = P.energy
|
||||
P.sub_velocity(internal_loss)
|
||||
energy_dumped_organic += P.energy
|
||||
if(!P.velocity)
|
||||
energy_to_damage(energy_dumped_organic)
|
||||
return 2
|
||||
var/penetration_chance = armor_penetration_probability(ballistic_armor,P)
|
||||
if(prob(penetration_chance))
|
||||
energy_to_damage(energy_dumped_organic)
|
||||
return -1
|
||||
else
|
||||
return general_handle_ballistics(P,def_zone,energy_dumped_organic,internal_loss,ballistic_armor)
|
||||
|
||||
/mob/living/proc/damage_organ_energy(var/energy,var/obj/item/organ/internal/target)
|
||||
log_and_message_admins("damage_organ_energy([energy])")
|
||||
return
|
||||
|
||||
/mob/living/proc/energy_to_damage(var/energy)
|
||||
log_and_message_admins("energy_to_damage([energy])")
|
||||
return
|
||||
|
||||
/mob/living/proc/armor_penetration_probability(var/armor, var/obj/item/projectile/bullet/P)
|
||||
var/bullet_ap_value = (1+((P.armor_penetration)/BULLET_AP_DIVISOR))
|
||||
var/ap_value = P.velocity * bullet_ap_value * (P.grains / P.diam)**(2/3) / AP_DIVISOR
|
||||
var/armor_value = ARMOR_Y_INTERCEPT + ARMOR_SLOPE * armor
|
||||
var/penetration_chance = 100 / (1 + PENETRATION_PROBABILITY_EXP_BASE**(-PENETRATION_PROBABILITY_EXP_MULT*(ap_value - armor_value)))
|
||||
return penetration_chance
|
||||
|
||||
/mob/living/bullet_act(var/obj/item/projectile/P, var/def_zone)
|
||||
if(P.check_armour == "bullet")
|
||||
return handle_ballistics(P,def_zone)
|
||||
else
|
||||
return ..()
|
||||
|
||||
#undef BULLET_AP_DIVISOR
|
||||
#undef AP_DIVISOR
|
||||
#undef ARMOR_Y_INTERCEPT
|
||||
#undef ARMOR_SLOPE
|
||||
#undef PENETRATION_PROBABILITY_EXP_BASE
|
||||
#undef PENETRATION_PROBABILITY_EXP_MULT
|
||||
|
||||
#undef BULLET_DEFLECTED_PAIN_DIVISOR
|
||||
#undef BULLET_DEFLECTED_BULLET_DIVISOR
|
||||
#undef BULLET_DEFLECTED_MELEE_DIVISOR
|
||||
|
||||
#undef SKIN_LOSS_COEFFICIENT
|
||||
#undef ARMOR_LOSS_COEFFICIENT
|
||||
#undef ARMOR_LOSS_MIN_MULT
|
||||
#undef ARMOR_LOSS_MIN_ARMOR
|
||||
#undef INTERNAL_LOSS_COEFFICIENT
|
||||
#undef ORGAN_LOSS_COEFFICIENT
|
||||
#undef ORGAN_LEAVE_EARLY
|
||||
#undef HIT_ORGAN_CHANCE_VITALS
|
||||
#undef HIT_VITAL_ORGAN_CHANCE
|
||||
|
||||
#undef BONE_HIT_CHANCE
|
||||
#undef BONE_HIT_CHANCE_UNENCASED
|
||||
#undef BONE_HIT_CHANCE_ENCASED
|
||||
#undef BONE_JOULES_PERHP_AVG
|
||||
#undef BONE_JOULES_PERHP_DEV
|
||||
#undef BONE_HP_AVG
|
||||
|
||||
#undef PROB_LEAVE_EARLY_FIRST
|
||||
#undef PROB_LEAVE_EARLY_SECOND
|
||||
@@ -105,6 +105,7 @@
|
||||
bolt_name="charging handle"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY | CHAMBER_ON_RELOAD
|
||||
bolt_release = null
|
||||
muzzle_velocity = 853
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolvingrifle
|
||||
manual_chamber = FALSE
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#define BOLT_CASING_EJECTED 16
|
||||
#define BOLT_CASING_CHAMBERED 32
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////// CADYN'S BALLISTICS ////////////////////////////////////////////////////////////////////////// ORIGINAL FROM CHOMPSTATION ////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/obj/item/weapon/gun/projectile
|
||||
var/manual_chamber = TRUE
|
||||
var/auto_loading_type = CLOSED_BOLT | LOCK_MANUAL_LOCK | LOCK_SLAPPABLE
|
||||
@@ -21,6 +25,7 @@
|
||||
var/bolt_open = FALSE
|
||||
var/bolt_locked = FALSE
|
||||
var/bolt_release = "bolt release"
|
||||
var/muzzle_velocity = 500 // meters per second
|
||||
|
||||
/obj/item/weapon/gun/projectile/handle_post_fire(mob/user, atom/target, var/pointblank=0, var/reflex=0)
|
||||
if(fire_anim)
|
||||
@@ -415,4 +420,11 @@
|
||||
set category = "Object"
|
||||
set src in view(1)
|
||||
|
||||
switch_firemodes(usr)
|
||||
switch_firemodes(usr)
|
||||
|
||||
/obj/item/weapon/gun/projectile/process_accuracy(obj/projectile, mob/living/user, atom/target, var/burst, var/held_twohanded)
|
||||
. = ..()
|
||||
var/obj/item/projectile/bullet/P = projectile
|
||||
if(!istype(P))
|
||||
return
|
||||
P.velocity = muzzle_velocity
|
||||
@@ -581,6 +581,13 @@
|
||||
if(check_penetrate(A))
|
||||
passthrough = TRUE
|
||||
penetrating--
|
||||
//CHOMPEdit Begin
|
||||
var/obj/item/projectile/bullet/this = src
|
||||
if(istype(this))
|
||||
if(!this.velocity)
|
||||
passthrough = FALSE
|
||||
penetrating = 0
|
||||
//CHOMPEdit End
|
||||
|
||||
if(passthrough)
|
||||
trajectory_ignore_forcemove = TRUE
|
||||
|
||||
25
code/modules/projectiles/projectile/bullets_ch.dm
Normal file
25
code/modules/projectiles/projectile/bullets_ch.dm
Normal file
@@ -0,0 +1,25 @@
|
||||
#define GRAINS_PER_KG 15432.4
|
||||
|
||||
/obj/item/projectile/bullet
|
||||
var/diam = 9 //mm
|
||||
var/velocity = 500 //Meters per second
|
||||
var/hollow_point = FALSE
|
||||
var/grains = 115 //I hope the unit is obvious
|
||||
var/energy //Joules
|
||||
|
||||
/obj/item/projectile/bullet/launch_projectile(atom/target, target_zone, mob/user, params, angle_override, forced_spread = 0)
|
||||
energy = velocity * velocity * (grains / GRAINS_PER_KG)
|
||||
return ..()
|
||||
|
||||
/obj/item/projectile/bullet/proc/sub_velocity(var/amount)
|
||||
velocity = max(0,velocity - amount)
|
||||
energy = velocity * velocity * (grains / GRAINS_PER_KG)
|
||||
|
||||
/obj/item/projectile/bullet/proc/sub_energy(var/amount)
|
||||
energy = max(0,energy - amount)
|
||||
velocity = sqrt(2*energy/(grains / GRAINS_PER_KG))
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a762
|
||||
diam = 7.62
|
||||
velocity = 700
|
||||
grains = 123
|
||||
@@ -2610,6 +2610,7 @@
|
||||
#include "code\modules\mob\language\station_YW.dm"
|
||||
#include "code\modules\mob\language\synthetic.dm"
|
||||
#include "code\modules\mob\living\autohiss.dm"
|
||||
#include "code\modules\mob\living\bullet_act_ch.dm"
|
||||
#include "code\modules\mob\living\damage_procs.dm"
|
||||
#include "code\modules\mob\living\death.dm"
|
||||
#include "code\modules\mob\living\default_language.dm"
|
||||
@@ -3496,6 +3497,7 @@
|
||||
#include "code\modules\projectiles\projectile\beams_vr.dm"
|
||||
#include "code\modules\projectiles\projectile\blob.dm"
|
||||
#include "code\modules\projectiles\projectile\bullets.dm"
|
||||
#include "code\modules\projectiles\projectile\bullets_ch.dm"
|
||||
#include "code\modules\projectiles\projectile\bullets_vr.dm"
|
||||
#include "code\modules\projectiles\projectile\change.dm"
|
||||
#include "code\modules\projectiles\projectile\energy.dm"
|
||||
|
||||
Reference in New Issue
Block a user