mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2026-08-30 16:48:12 +01:00
@@ -0,0 +1,301 @@
|
||||
#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 BULLET_DEFLECTED_PAIN_EXPONENT 1.5
|
||||
#define BULLET_DEFLECTED_BRUISE_SUBTRACT 5
|
||||
|
||||
GLOBAL_VAR_INIT(SKIN_LOSS_COEFFICIENT,16)
|
||||
GLOBAL_VAR_INIT(ARMOR_LOSS_COEFFICIENT,150)
|
||||
GLOBAL_VAR_INIT(ARMOR_LOSS_MIN_MULT,0.5)
|
||||
GLOBAL_VAR_INIT(ARMOR_LOSS_MIN_ARMOR,20)
|
||||
GLOBAL_VAR_INIT(INTERNAL_LOSS_COEFFICIENT,195)
|
||||
#define ORGAN_LOSS_COEFFICIENT 350
|
||||
#define HIT_VITAL_ORGAN_CHANCE 35
|
||||
|
||||
#define BONE_HIT_CHANCE_UNENCASED 45
|
||||
#define BONE_HIT_CHANCE_ENCASED 80
|
||||
GLOBAL_VAR_INIT(BONE_JOULES_PERHP_AVG,2)
|
||||
GLOBAL_VAR_INIT(BONE_JOULES_PERHP_DEV,1)
|
||||
GLOBAL_VAR_INIT(BONE_JOULES_MIN,100)
|
||||
#define BONE_HP_AVG 25
|
||||
|
||||
GLOBAL_VAR_INIT(HOLLOW_POINT_VELLOSS_BONUS,2.35)
|
||||
GLOBAL_VAR_INIT(HOLLOW_POINT_CONVERSION_EFF,1.15)
|
||||
|
||||
#define PROB_LEAVE_EARLY_FIRST 20
|
||||
#define PROB_LEAVE_EARLY_SECOND 40
|
||||
|
||||
GLOBAL_VAR_INIT(ENERGY_DAMAGE_FLESH_FACTOR,0.03)
|
||||
GLOBAL_VAR_INIT(ENERGY_DAMAGE_ORGAN_FACTOR,0.035)
|
||||
|
||||
#ifndef GAUSSIAN_RANDOM
|
||||
#define GAUSSIAN_RANDOM(vars...) ((-2*log(rand()))**0.5 * cos(6.28318530718*rand()))
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
////////////// CADYN'S BALLISTICS ////////////////////////////////////////////////////////////////////////// ORIGINAL FROM CHOMPSTATION ////////
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/mob/living/proc/handle_ballistics(var/obj/item/projectile/bullet/P, var/def_zone)
|
||||
var/list/updated_organ_weight = list()
|
||||
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)
|
||||
for(var/ext_organ in ballistic_variables["organ_hit_weight"])
|
||||
var/list/input = list()
|
||||
var/obj/item/organ/external/ref_ext_organ = H.get_organ(ext_organ)
|
||||
for(var/int_organ in ballistic_variables["organ_hit_weight"][ext_organ])
|
||||
var/ref_int_organ = H.internal_organs_by_name[int_organ]
|
||||
if(ref_ext_organ && ref_int_organ && (ref_int_organ in ref_ext_organ.internal_organs))
|
||||
input[ref_int_organ] = ballistic_variables["organ_hit_weight"][ext_organ][int_organ]
|
||||
if(input.len)
|
||||
updated_organ_weight[ref_ext_organ] = input
|
||||
//log_and_message_admins("Beginning handle_ballistics")
|
||||
var/penetration_chance = armor_penetration_probability(ballistic_armor,P)
|
||||
if(!prob(penetration_chance)) //Boo-hoo we got deflected. Do boring agony/bruises stuff.
|
||||
//log_and_message_admins("Bullet deflected")
|
||||
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/BULLET_DEFLECTED_BULLET_DIVISOR + melee_armor/BULLET_DEFLECTED_MELEE_DIVISOR)) //Better armor spreads out the energy better.
|
||||
var/hurt_value_pain = hurt_value ** BULLET_DEFLECTED_PAIN_EXPONENT
|
||||
var/hurt_value_bruise = max(0,hurt_value-BULLET_DEFLECTED_BRUISE_SUBTRACT)
|
||||
|
||||
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
|
||||
//log_and_message_admins("Bullet penetrated")
|
||||
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/conversion_efficiency = P.hollow_point ? GLOB.HOLLOW_POINT_CONVERSION_EFF : 1
|
||||
var/vel_loss_multiplier = P.hollow_point ? GLOB.HOLLOW_POINT_VELLOSS_BONUS : 1
|
||||
|
||||
var/energy_dumped_organic = 0
|
||||
var/vel_lost_armor = ballistic_armor >= GLOB.ARMOR_LOSS_MIN_ARMOR ? GLOB.ARMOR_LOSS_COEFFICIENT * area_over_mass * ((1 + GLOB.ARMOR_LOSS_MIN_MULT) - penetration_chance/100) : 0
|
||||
P.sub_velocity(vel_lost_armor)
|
||||
|
||||
var/energy_past = P.energy
|
||||
var/internal_loss = vel_loss_multiplier * GLOB.INTERNAL_LOSS_COEFFICIENT * area_over_mass
|
||||
var/vel_lost_skin = vel_loss_multiplier * GLOB.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 * conversion_efficiency,def_zone)
|
||||
return 1
|
||||
if(hit_organ)
|
||||
//log_and_message_admins("organ_handle_ballistics called. hit_organ = [hit_organ], energy_dumped_organic = [energy_dumped_organic], internal_loss = [internal_loss], ballistic_armor = [ballistic_armor], P.velocity = [P.velocity], P.energy = [P.energy]")
|
||||
return organ_handle_ballistics(P,hit_organ,energy_dumped_organic,internal_loss,ballistic_armor,updated_organ_weight)
|
||||
else
|
||||
//log_and_message_admins("general_handle_ballistics called.")
|
||||
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/list/updated_organ_weight)
|
||||
var/conversion_efficiency = P.hollow_point ? GLOB.HOLLOW_POINT_CONVERSION_EFF : 1
|
||||
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 = ballistic_variables["bone_chance_unencased"][hit_organ.organ_tag]
|
||||
//log_and_message_admins("Bone hit chance is [bone_chance], organ is [hit_organ]")
|
||||
if(prob(bone_chance))
|
||||
var/energy_to_fracture = max(GLOB.BONE_JOULES_MIN, hit_organ.min_broken_damage * (GAUSSIAN_RANDOM()*GLOB.BONE_JOULES_PERHP_DEV + GLOB.BONE_JOULES_PERHP_AVG))
|
||||
//log_and_message_admins("Bone hit, bone_chance1. energy_to_fracture = [energy_to_fracture]")
|
||||
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)
|
||||
//log_and_message_admins("Insufficient projectile energy. Stopping projectile.")
|
||||
energy_to_damage(energy_dumped_organic * conversion_efficiency,hit_organ.organ_tag)
|
||||
return 2
|
||||
else
|
||||
//log_and_message_admins("Sufficient projectile energy to pass through bone.")
|
||||
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.status & ORGAN_BROKEN))
|
||||
//log_and_message_admins("Fracturing [hit_organ]")
|
||||
hit_organ.fracture()
|
||||
//log_and_message_admins("Bone checking done. hit_organ = [hit_organ], energy_dumped_organic = [energy_dumped_organic], internal_loss = [internal_loss], ballistic_armor = [ballistic_armor], P.velocity = [P.velocity], P.energy = [P.energy]")
|
||||
if(hit_organ.internal_organs.len && P.velocity > area_over_mass*ORGAN_LOSS_COEFFICIENT && prob(ballistic_variables["organ_hit_chance"][hit_organ.organ_tag]) && updated_organ_weight[hit_organ] && updated_organ_weight[hit_organ].len)
|
||||
//log_and_message_admins("Organ was hit by bullet.")
|
||||
energy_past = P.energy
|
||||
P.sub_velocity(internal_loss)
|
||||
damage_organ_energy((energy_past - P.energy) * conversion_efficiency, pickweight(updated_organ_weight[hit_organ]))
|
||||
if(!P.velocity)
|
||||
//log_and_message_admins("Organ stopped bullet.")
|
||||
energy_to_damage(energy_dumped_organic * conversion_efficiency,hit_organ.organ_tag)
|
||||
return 2
|
||||
//log_and_message_admins("Organ check done, hit_organ = [hit_organ], energy_dumped_organic = [energy_dumped_organic], internal_loss = [internal_loss], ballistic_armor = [ballistic_armor], P.velocity = [P.velocity], P.energy = [P.energy]")
|
||||
energy_past = P.energy
|
||||
P.sub_velocity(internal_loss)
|
||||
energy_dumped_organic += energy_past - P.energy
|
||||
if(!P.velocity || (hit_organ.organ_tag in ballistic_variables["organ_leave_early"]) || prob(PROB_LEAVE_EARLY_SECOND))
|
||||
energy_to_damage(energy_dumped_organic * conversion_efficiency,hit_organ.organ_tag)
|
||||
return P.velocity ? -1 : 2
|
||||
//log_and_message_admins("Internal_loss 2 stopped bullet")
|
||||
//log_and_message_admins("Internal_loss 2 completed, hit_organ = [hit_organ], energy_dumped_organic = [energy_dumped_organic], internal_loss = [internal_loss], ballistic_armor = [ballistic_armor], P.velocity = [P.velocity], P.energy = [P.energy]")
|
||||
if(prob(bone_chance))
|
||||
var/energy_to_fracture = max(GLOB.BONE_JOULES_MIN, hit_organ.min_broken_damage * (GAUSSIAN_RANDOM()*GLOB.BONE_JOULES_PERHP_DEV + GLOB.BONE_JOULES_PERHP_AVG))
|
||||
//log_and_message_admins("Bone hit, bone_chance1. energy_to_fracture = [energy_to_fracture]")
|
||||
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)
|
||||
//log_and_message_admins("Insufficient projectile energy. Stopping projectile.")
|
||||
energy_to_damage(energy_dumped_organic * conversion_efficiency,hit_organ.organ_tag)
|
||||
return 2
|
||||
else
|
||||
//log_and_message_admins("Sufficient projectile energy to pass through bone.")
|
||||
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.status & ORGAN_BROKEN))
|
||||
//log_and_message_admins("Fracturing [hit_organ]")
|
||||
hit_organ.fracture()
|
||||
energy_past = P.energy
|
||||
P.sub_velocity(internal_loss)
|
||||
energy_dumped_organic += energy_past - P.energy
|
||||
if(!P.velocity)
|
||||
//log_and_message_admins("Internal_loss 3 stopped bullet")
|
||||
energy_to_damage(energy_dumped_organic * conversion_efficiency,hit_organ.organ_tag)
|
||||
return 2
|
||||
//log_and_message_admins("Internal_loss 3 completed. hit_organ = [hit_organ], energy_dumped_organic = [energy_dumped_organic], internal_loss = [internal_loss], ballistic_armor = [ballistic_armor], P.velocity = [P.velocity], P.energy = [P.energy]")
|
||||
var/penetration_chance = armor_penetration_probability(ballistic_armor,P)
|
||||
if(prob(penetration_chance))
|
||||
//log_and_message_admins("Projectile exiting.")
|
||||
energy_to_damage(energy_dumped_organic * conversion_efficiency,hit_organ.organ_tag)
|
||||
return -1
|
||||
else
|
||||
//log_and_message_admins("Projectile continuing inside body")
|
||||
energy_dumped_organic += P.energy / 3
|
||||
P.sub_velocity(P.velocity)
|
||||
energy_to_damage(energy_dumped_organic * conversion_efficiency,hit_organ.organ_tag)
|
||||
return 2
|
||||
|
||||
/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/conversion_efficiency = P.hollow_point ? GLOB.HOLLOW_POINT_CONVERSION_EFF : 1
|
||||
var/energy_past
|
||||
var/area_over_mass = P.diam * P.diam / P.grains
|
||||
var/bone_chance = BONE_HIT_CHANCE_UNENCASED
|
||||
//if(def_zone in ballistic_variables["bone_chance_unencased"])
|
||||
//bone_chance = ballistic_variables["bone_chance_unencased"][def_zone]
|
||||
if(prob(bone_chance))
|
||||
var/energy_to_fracture = max(GLOB.BONE_JOULES_MIN, BONE_HP_AVG * (GAUSSIAN_RANDOM()*GLOB.BONE_JOULES_PERHP_DEV + GLOB.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 * conversion_efficiency,def_zone)
|
||||
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) * 1.5
|
||||
if(!P.velocity)
|
||||
energy_to_damage(energy_dumped_organic * conversion_efficiency,def_zone)
|
||||
return 2
|
||||
energy_past = P.energy
|
||||
P.sub_velocity(internal_loss)
|
||||
energy_dumped_organic += energy_past - P.energy
|
||||
if(!P.velocity || (def_zone in ballistic_variables["organ_leave_early"]) || prob(PROB_LEAVE_EARLY_SECOND))
|
||||
energy_to_damage(energy_dumped_organic * conversion_efficiency,def_zone)
|
||||
return P.velocity ? -1 : 2
|
||||
|
||||
if(prob(bone_chance))
|
||||
var/energy_to_fracture = max(GLOB.BONE_JOULES_MIN, BONE_HP_AVG * (GAUSSIAN_RANDOM()*GLOB.BONE_JOULES_PERHP_DEV + GLOB.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 * conversion_efficiency,def_zone)
|
||||
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 += energy_past - P.energy
|
||||
if(!P.velocity)
|
||||
energy_to_damage(energy_dumped_organic * conversion_efficiency,def_zone)
|
||||
return 2
|
||||
var/penetration_chance = armor_penetration_probability(ballistic_armor,P)
|
||||
if(prob(penetration_chance))
|
||||
energy_to_damage(energy_dumped_organic * conversion_efficiency,def_zone)
|
||||
return -1
|
||||
else
|
||||
energy_dumped_organic += P.energy / 3
|
||||
P.sub_velocity(P.velocity)
|
||||
energy_to_damage(energy_dumped_organic * conversion_efficiency,def_zone)
|
||||
return 2
|
||||
|
||||
/mob/living/proc/damage_organ_energy(var/energy,var/obj/item/organ/internal/target)
|
||||
var/damage = round(energy*GLOB.ENERGY_DAMAGE_ORGAN_FACTOR)
|
||||
//log_and_message_admins("damage_organ_energy([energy]) : [target].take_damage([damage])")
|
||||
target.take_damage(damage)
|
||||
return
|
||||
|
||||
/mob/living/proc/energy_to_damage(var/energy,var/def_zone)
|
||||
var/damage = round(energy*GLOB.ENERGY_DAMAGE_FLESH_FACTOR)
|
||||
//log_and_message_admins("energy_to_damage([energy]) : apply_damage([damage], BRUTE, [def_zone])")
|
||||
apply_damage(damage, BRUTE, def_zone)
|
||||
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)
|
||||
//log_and_message_admins("bullet_act_ch")
|
||||
var/obj/item/projectile/bullet/B = P
|
||||
if(P.check_armour == "bullet" && istype(B) && !B.old_bullet_act)
|
||||
//log_and_message_admins("is bullet")
|
||||
return handle_ballistics(P,def_zone)
|
||||
else
|
||||
//log_and_message_admins("is not bullet")
|
||||
return ..()
|
||||
|
||||
/mob/living
|
||||
var/list/ballistic_variables = list(\
|
||||
"bone_chance_unencased" = list(BP_HEAD = 5, BP_TORSO = 20, BP_GROIN = 20, BP_L_FOOT = 80, BP_R_FOOT = 80, BP_L_LEG = 35, BP_R_LEG = 35, BP_L_ARM = 65, BP_R_ARM = 65, BP_L_HAND = 80, BP_R_HAND = 80), \
|
||||
"organ_leave_early" = list("l_arm", "r_arm", "l_hand", "r_hand", "l_foot", "r_foot"), \
|
||||
"organ_hit_weight" = list(\
|
||||
BP_HEAD = list(\
|
||||
/*Standard organs*/O_BRAIN = 90, O_EYES = 5, \
|
||||
/*Diona organs*/O_RESPONSE = 10, O_RESPONSE = 15, O_GBLADDER = 15, \
|
||||
/*Replicant organs*/O_VRLINK = 20, \
|
||||
/*Xeno organs*/O_ACID = 10, O_RESIN = 10), \
|
||||
BP_TORSO = list(\
|
||||
/*Standard organs*/O_HEART = 5, O_LUNGS = 50, O_SPLEEN = 15, O_VOICE = 10, \
|
||||
/*Synth organs*/O_CELL = 5, O_PUMP = 15, O_HEATSINK = 35, O_CYCLER = 15, O_DIAGNOSTIC = 10, \
|
||||
/*Promethean organs*/O_REGBRUTE = 20, O_REGBURN = 20, O_REGOXY = 20, O_REGTOX = 20, \
|
||||
/*Diona organs*/O_STRATA = 35, O_BRAIN = 20, O_NUTRIENT = 10, \
|
||||
/*Replicant organs*/O_AREJECT = 35, \
|
||||
/*Xeno organs*/O_PLASMA = 10, O_HIVE = 10), \
|
||||
BP_GROIN = list(\
|
||||
/*Standard organs*/O_INTESTINES = 50, O_STOMACH = 20, O_LIVER = 20, O_KIDNEYS = 15, O_APPENDIX = 5, \
|
||||
/*Diona organs*/O_POLYP = 10, O_ANCHOR = 15, \
|
||||
/*Replicant organs*/O_VENTC = 20, \
|
||||
/*Xeno organs*/ O_EGG = 25) ), \
|
||||
"organ_hit_chance" = list(BP_HEAD = 95, BP_TORSO = 90, BP_GROIN = 90) )
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
#define BULLET_PENETRATED 1<<0
|
||||
#define BULLET_BONECHECK1_TRUE 1<<1
|
||||
#define BULLET_ORGANCHECK_TRUE 1<<2
|
||||
#define BULLET_BONECHECK2_TRUE 1<<3
|
||||
#define BULLET_PASSED_LEAVE_EARLY 1<<4
|
||||
#define BULLET_PASSED_BONECHECK1 1<<5
|
||||
#define BULLET_PASSED_ORGANCHECK 1<<6
|
||||
#define BULLET_PASSED_INTERNALCHECK2 1<<7
|
||||
#define BULLET_PASSED_BONECHECK2 1<<8
|
||||
#define BULLET_PASSED_INTERNALCHECK3 1<<9
|
||||
#define BULLET_TESTS 150
|
||||
|
||||
/mob/living/carbon/human/monkey/testerboyo
|
||||
name = "testerboyo"
|
||||
var/the_big_armor = 0
|
||||
|
||||
/mob/living/carbon/human/monkey/testerboyo/getarmor(var/def_zone,var/type)
|
||||
return the_big_armor
|
||||
|
||||
/proc/test_all_ballistics()
|
||||
var/mob/living/carbon/human/monkey/testerboyo/tester = new()
|
||||
var/obj/item/projectile/bullet/pistol/test1 = new()
|
||||
var/obj/item/projectile/bullet/pistol/ap/test2 = new()
|
||||
var/obj/item/projectile/bullet/pistol/hp/test3 = new()
|
||||
var/obj/item/projectile/bullet/pistol/medium/test4 = new()
|
||||
var/obj/item/projectile/bullet/pistol/medium/ap/test5 = new()
|
||||
var/obj/item/projectile/bullet/pistol/medium/hp/test6 = new()
|
||||
var/obj/item/projectile/bullet/pistol/strong/test7 = new()
|
||||
var/obj/item/projectile/bullet/shotgun/test8 = new()
|
||||
var/obj/item/projectile/bullet/shotgun/buckshot/test9 = new()
|
||||
var/obj/item/projectile/bullet/rifle/a762/test10 = new()
|
||||
var/obj/item/projectile/bullet/rifle/a762/ap/test11 = new()
|
||||
var/obj/item/projectile/bullet/rifle/a762/hp/test12 = new()
|
||||
var/obj/item/projectile/bullet/rifle/a545/test13 = new()
|
||||
var/obj/item/projectile/bullet/rifle/a545/ap/test14 = new()
|
||||
var/obj/item/projectile/bullet/rifle/a545/hp/test15 = new()
|
||||
var/obj/item/projectile/bullet/rifle/a145/test16 = new()
|
||||
var/obj/item/projectile/bullet/rifle/a145/highvel/test17 = new()
|
||||
var/obj/item/projectile/bullet/rifle/a44rifle/test18 = new()
|
||||
var/obj/item/projectile/bullet/rifle/a95/test19 = new()
|
||||
var/obj/item/projectile/bullet/rifle/a762/lmg/test20 = new()
|
||||
test_ballistics(test1,tester)
|
||||
test_ballistics(test2,tester)
|
||||
test_ballistics(test3,tester)
|
||||
test_ballistics(test4,tester)
|
||||
test_ballistics(test5,tester)
|
||||
test_ballistics(test6,tester)
|
||||
test_ballistics(test7,tester)
|
||||
test_ballistics(test8,tester)
|
||||
test_ballistics(test9,tester)
|
||||
test_ballistics(test10,tester)
|
||||
test_ballistics(test11,tester)
|
||||
test_ballistics(test12,tester)
|
||||
test_ballistics(test13,tester)
|
||||
test_ballistics(test14,tester)
|
||||
test_ballistics(test15,tester)
|
||||
test_ballistics(test16,tester)
|
||||
test_ballistics(test17,tester)
|
||||
test_ballistics(test18,tester)
|
||||
test_ballistics(test19,tester)
|
||||
test_ballistics(test20,tester)
|
||||
qdel(tester)
|
||||
qdel(test1)
|
||||
qdel(test2)
|
||||
qdel(test3)
|
||||
qdel(test4)
|
||||
qdel(test5)
|
||||
qdel(test6)
|
||||
qdel(test7)
|
||||
qdel(test8)
|
||||
qdel(test9)
|
||||
qdel(test10)
|
||||
qdel(test11)
|
||||
qdel(test12)
|
||||
qdel(test13)
|
||||
qdel(test14)
|
||||
qdel(test15)
|
||||
qdel(test16)
|
||||
qdel(test17)
|
||||
qdel(test18)
|
||||
qdel(test19)
|
||||
qdel(test20)
|
||||
|
||||
|
||||
/proc/test_ballistics(var/obj/item/projectile/bullet/P,var/mob/living/carbon/human/monkey/testerboyo/tester)
|
||||
var/list/data = list()
|
||||
for(var/armor_level in list(0,5,10,20,50,80))
|
||||
data["[armor_level]"] = list()
|
||||
data["[armor_level]"]["average"] = list()
|
||||
tester.the_big_armor = armor_level
|
||||
var/bp_num = 0
|
||||
for(var/body_part in list(BP_TORSO,BP_HEAD,BP_R_LEG,BP_R_ARM,BP_R_HAND))
|
||||
bp_num++
|
||||
data["[armor_level]"][body_part] = list()
|
||||
for(var/i = 0,i<BULLET_TESTS,i++)
|
||||
P.velocity = initial(P.velocity)
|
||||
P.sub_velocity(0)
|
||||
var/out = tester.handle_ballistics(P,body_part)
|
||||
for(var/x = 0,x<10,x++)
|
||||
var/input = (out["chex"] & (1<<x)) ? 1 : 0
|
||||
data["[armor_level]"][body_part]["[x]"] += input
|
||||
data["[armor_level]"]["average"]["[x]"] += input
|
||||
data["[armor_level]"][body_part]["10"] += out["energy"]
|
||||
data["[armor_level]"][body_part]["10"] /= BULLET_TESTS
|
||||
data["[armor_level]"]["average"]["10"] += data["[armor_level]"][body_part]["10"]
|
||||
for(var/x = 0,x<11,x++)
|
||||
data["[armor_level]"]["average"]["[x]"] /= bp_num
|
||||
for(var/entry in data["[armor_level]"])
|
||||
var/string_to_send = "[P.type]: Armor level [armor_level]: [entry]:"
|
||||
for(var/x = 0,x<11,x++)
|
||||
string_to_send += " [x]:[data["[armor_level]"][entry]["[x]"]]"
|
||||
log_and_message_admins(string_to_send)
|
||||
|
||||
|
||||
|
||||
|
||||
/proc/lazy_return_testing(var/chex,var/energy)
|
||||
return list("chex" = chex, "energy" = energy)
|
||||
|
||||
/mob/living/carbon/human/monkey/testerboyo/handle_ballistics(var/obj/item/projectile/bullet/P, var/def_zone)
|
||||
var/chex = 0
|
||||
var/list/updated_organ_weight = list()
|
||||
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)
|
||||
for(var/ext_organ in ballistic_variables["organ_hit_weight"])
|
||||
var/list/input = list()
|
||||
var/obj/item/organ/external/ref_ext_organ = H.get_organ(ext_organ)
|
||||
for(var/int_organ in ballistic_variables["organ_hit_weight"][ext_organ])
|
||||
var/ref_int_organ = H.internal_organs_by_name[int_organ]
|
||||
if(ref_ext_organ && ref_int_organ && (ref_int_organ in ref_ext_organ.internal_organs))
|
||||
input[ref_int_organ] = ballistic_variables["organ_hit_weight"][ext_organ][int_organ]
|
||||
if(input.len)
|
||||
updated_organ_weight[ref_ext_organ] = input
|
||||
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/BULLET_DEFLECTED_BULLET_DIVISOR + melee_armor/BULLET_DEFLECTED_MELEE_DIVISOR)) //Better armor spreads out the energy better.
|
||||
var/hurt_value_pain = hurt_value ** BULLET_DEFLECTED_PAIN_EXPONENT
|
||||
var/hurt_value_bruise = max(0,hurt_value-BULLET_DEFLECTED_BRUISE_SUBTRACT)
|
||||
|
||||
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 lazy_return_testing(chex,0)
|
||||
else //Now the FUN begins
|
||||
chex |= BULLET_PENETRATED
|
||||
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/conversion_efficiency = P.hollow_point ? 0.925 : 1
|
||||
var/vel_loss_multiplier = P.hollow_point ? GLOB.HOLLOW_POINT_VELLOSS_BONUS : 1
|
||||
|
||||
var/energy_dumped_organic = 0
|
||||
var/vel_lost_armor = ballistic_armor >= GLOB.ARMOR_LOSS_MIN_ARMOR ? GLOB.ARMOR_LOSS_COEFFICIENT * area_over_mass * ((1 + GLOB.ARMOR_LOSS_MIN_MULT) - penetration_chance/100) : 0
|
||||
P.sub_velocity(vel_lost_armor)
|
||||
|
||||
var/energy_past = P.energy
|
||||
var/internal_loss = vel_loss_multiplier * GLOB.INTERNAL_LOSS_COEFFICIENT * area_over_mass
|
||||
var/vel_lost_skin = vel_loss_multiplier * GLOB.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)
|
||||
return lazy_return_testing(chex,energy_dumped_organic)
|
||||
if(hit_organ)
|
||||
chex |= BULLET_PASSED_LEAVE_EARLY
|
||||
return organ_handle_ballistics(P,hit_organ,energy_dumped_organic,internal_loss,ballistic_armor,updated_organ_weight,chex)
|
||||
else
|
||||
return general_handle_ballistics(P,def_zone,energy_dumped_organic,internal_loss,ballistic_armor)
|
||||
|
||||
/mob/living/carbon/human/monkey/testerboyo/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/list/updated_organ_weight,var/chex)
|
||||
//var/conversion_efficiency = P.hollow_point ? 0.8 : 1
|
||||
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 = ballistic_variables["bone_chance_unencased"][hit_organ.organ_tag]
|
||||
if(prob(bone_chance))
|
||||
chex |= BULLET_BONECHECK1_TRUE
|
||||
var/energy_to_fracture = max(GLOB.BONE_JOULES_MIN, hit_organ.min_broken_damage * (GAUSSIAN_RANDOM()*GLOB.BONE_JOULES_PERHP_DEV + GLOB.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)
|
||||
return lazy_return_testing(chex,energy_dumped_organic)
|
||||
else
|
||||
P.sub_energy(energy_to_fracture)
|
||||
energy_dumped_organic += energy_to_fracture / 3 //About a third of the energy that goes into fracturing the bone also goes into fucking up tissues.
|
||||
chex |= BULLET_PASSED_BONECHECK1
|
||||
if(hit_organ.internal_organs.len && P.velocity > area_over_mass*ORGAN_LOSS_COEFFICIENT && prob(ballistic_variables["organ_hit_chance"][hit_organ.organ_tag]) && updated_organ_weight[hit_organ] && updated_organ_weight[hit_organ].len)
|
||||
chex |= BULLET_ORGANCHECK_TRUE
|
||||
energy_past = P.energy
|
||||
P.sub_velocity(internal_loss)
|
||||
if(!P.velocity)
|
||||
return lazy_return_testing(chex,energy_dumped_organic)
|
||||
chex |= BULLET_PASSED_ORGANCHECK
|
||||
energy_past = P.energy
|
||||
P.sub_velocity(internal_loss)
|
||||
energy_dumped_organic += energy_past - P.energy
|
||||
if(!P.velocity || (hit_organ.organ_tag in ballistic_variables["organ_leave_early"]) || prob(PROB_LEAVE_EARLY_SECOND))
|
||||
return lazy_return_testing(chex,energy_dumped_organic)
|
||||
chex |= BULLET_PASSED_INTERNALCHECK2
|
||||
if(prob(bone_chance))
|
||||
chex |= BULLET_BONECHECK2_TRUE
|
||||
var/energy_to_fracture = max(GLOB.BONE_JOULES_MIN, hit_organ.min_broken_damage * (GAUSSIAN_RANDOM()*GLOB.BONE_JOULES_PERHP_DEV + GLOB.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)
|
||||
return lazy_return_testing(chex,energy_dumped_organic)
|
||||
else
|
||||
P.sub_energy(energy_to_fracture)
|
||||
energy_dumped_organic += energy_to_fracture / 3 //About a third of the energy that goes into fracturing the bone also goes into fucking up tissues.
|
||||
chex |= BULLET_PASSED_BONECHECK2
|
||||
energy_past = P.energy
|
||||
P.sub_velocity(internal_loss)
|
||||
energy_dumped_organic += energy_past - P.energy
|
||||
if(!P.velocity)
|
||||
return lazy_return_testing(chex,energy_dumped_organic)
|
||||
chex |= BULLET_PASSED_INTERNALCHECK3
|
||||
var/penetration_chance = armor_penetration_probability(ballistic_armor,P)
|
||||
if(prob(penetration_chance))
|
||||
return lazy_return_testing(chex,energy_dumped_organic)
|
||||
else
|
||||
energy_dumped_organic += P.energy / 3
|
||||
P.sub_velocity(P.velocity)
|
||||
return lazy_return_testing(chex,energy_dumped_organic)
|
||||
@@ -2,30 +2,80 @@
|
||||
/obj/item/weapon/gun/projectile/automatic
|
||||
bolt_name="charging handle"
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/mini_uzi
|
||||
auto_loading_type = OPEN_BOLT
|
||||
/obj/item/weapon/gun/projectile/automatic/advanced_smg
|
||||
muzzle_velocity = 390 //Based off MPX
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/tommygun
|
||||
auto_loading_type = OPEN_BOLT
|
||||
/obj/item/weapon/gun/projectile/automatic/c20r
|
||||
muzzle_velocity = 285 //Based off UMP-45, since apparently this 10mm smg fires .45 ftw. May be fixed in future updates.
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/sts35
|
||||
muzzle_velocity = 900 //Based off AK-74
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/wt550
|
||||
muzzle_velocity = 375 //Guestimation
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/z8
|
||||
muzzle_velocity = 750 //Based off HK417 16 in barrel.
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/l6_saw
|
||||
bolt_name="charging_handle"
|
||||
bolt_name="charging handle"
|
||||
auto_loading_type = OPEN_BOLT
|
||||
bolt_release = null
|
||||
muzzle_velocity = 960 //Prototype PU-21(https://en.wikipedia.org/wiki/IP-2)
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/as24
|
||||
muzzle_velocity = 470 //Temporary, might be changed.
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/mini_uzi
|
||||
auto_loading_type = OPEN_BOLT
|
||||
muzzle_velocity = 280 //Mac-10 .45
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/p90 //Finally a gun that exists irl. oh wait fuck they decided to chamber the p90 in 9mm kms
|
||||
muzzle_velocity = 397 //Guestimation. Will hopefully be able to replace with actual 5.7mm at some point.
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/tommygun //Phew, an actual gun that fires the correct cartridge.
|
||||
auto_loading_type = OPEN_BOLT
|
||||
muzzle_velocity = 285
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/bullpup
|
||||
muzzle_velocity = 880 //7.62 NATO Bullpup was unsurprisingly difficult to find https://en.wikipedia.org/wiki/Kel-Tec_RFB
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/combatsmg
|
||||
muzzle_velocity = 370 //Guestimation
|
||||
|
||||
//automatic_vr.dm
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/battlerifle
|
||||
muzzle_velocity = 370 //Not a real rifle or cartridge. Guestimating.
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/pdw
|
||||
muzzle_velocity = 390 //MPX
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/stg
|
||||
muzzle_velocity = 685 //STG-44
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/sol
|
||||
muzzle_velocity = 380 //Guestimation
|
||||
|
||||
//automatic_yw.dm
|
||||
/obj/item/weapon/gun/projectile/automatic/mg42
|
||||
bolt_name="charging_handle"
|
||||
bolt_name="charging handle"
|
||||
auto_loading_type = OPEN_BOLT
|
||||
bolt_release = null
|
||||
muzzle_velocity = 740 //Real gun.
|
||||
|
||||
//boltaction.dm
|
||||
/obj/item/weapon/gun/projectile/shotgun/pump/rifle
|
||||
muzzle_velocity = 860 //Guestimation
|
||||
|
||||
//caseless.dm
|
||||
/obj/item/weapon/gun/projectile/caseless
|
||||
bolt_name="charging handle"
|
||||
muzzle_velocity = 380 //Based of 9mm, because this fires 9mm projectiles. Will be fixed in future updates, likely.
|
||||
|
||||
//contender.dm
|
||||
/obj/item/weapon/gun/projectile/contender
|
||||
/obj/item/weapon/gun/projectile/contender //To be updated to use .357
|
||||
manual_chamber = FALSE
|
||||
muzzle_velocity = 370
|
||||
|
||||
//dartgun.dm
|
||||
/obj/item/weapon/gun/projectile/dartgun
|
||||
@@ -34,82 +84,144 @@
|
||||
//pistol.dm
|
||||
/obj/item/weapon/gun/projectile/colt
|
||||
bolt_name="slide"
|
||||
bolt_release = "slide release"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY
|
||||
muzzle_velocity = 253 //M1911
|
||||
|
||||
/obj/item/weapon/gun/projectile/sec
|
||||
bolt_name="slide"
|
||||
bolt_release = "slide release"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY
|
||||
muzzle_velocity = 253 //M1911
|
||||
|
||||
/obj/item/weapon/gun/projectile/silenced
|
||||
bolt_name="slide"
|
||||
bolt_release = "slide release"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY
|
||||
muzzle_velocity = 240 //Guestimation, minus velocity for suppressor
|
||||
|
||||
/obj/item/weapon/gun/projectile/deagle
|
||||
bolt_name="slide"
|
||||
bolt_release = "slide release"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY
|
||||
muzzle_velocity = 430 //Guestimation, everyone uses .50AE lol
|
||||
|
||||
/obj/item/weapon/gun/projectile/gyropistol
|
||||
bolt_name="slide"
|
||||
bolt_release = "slide release"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY
|
||||
|
||||
/obj/item/weapon/gun/projectile/pistol
|
||||
bolt_name="slide"
|
||||
bolt_release = "slide release"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY
|
||||
muzzle_velocity = 300 //P365
|
||||
|
||||
/obj/item/weapon/gun/projectile/pirate
|
||||
manual_chamber = FALSE
|
||||
|
||||
/obj/item/weapon/gun/projectile/derringer
|
||||
manual_chamber = FALSE
|
||||
muzzle_velocity = 350 //Guestimation
|
||||
|
||||
/obj/item/weapon/gun/projectile/luger
|
||||
bolt_name="slide"
|
||||
bolt_release = "slide release"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY
|
||||
muzzle_velocity = 350 //Luger
|
||||
|
||||
/obj/item/weapon/gun/projectile/p92x
|
||||
bolt_name="slide"
|
||||
bolt_release = "slide release"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY
|
||||
muzzle_velocity = 370
|
||||
|
||||
//pistol_vr.dm
|
||||
/obj/item/weapon/gun/projectile/lamia
|
||||
bolt_name="slide"
|
||||
bolt_release = "slide release"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY
|
||||
muzzle_velocity = 400 //Guestimation
|
||||
|
||||
/obj/item/weapon/gun/projectile/giskard
|
||||
|
||||
/obj/item/weapon/gun/projectile/giskard //To be updated to .380
|
||||
bolt_name="slide"
|
||||
bolt_release = "slide release"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY
|
||||
muzzle_velocity = 300 //Guestimation
|
||||
|
||||
//pistol_yw.dm
|
||||
/obj/item/weapon/gun/projectile/automatic/glock
|
||||
bolt_name="slide"
|
||||
bolt_release = "slide release"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY
|
||||
muzzle_velocity = 375 //Actual gun.
|
||||
|
||||
/obj/item/weapon/gun/projectile/ppk
|
||||
bolt_name="slide"
|
||||
bolt_release = "slide release"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY
|
||||
muzzle_velocity = 310 //Guestimation since PPK doesn't fire 9mm
|
||||
|
||||
/obj/item/weapon/gun/projectile/m2024
|
||||
bolt_name="slide"
|
||||
bolt_release = "slide release"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY
|
||||
muzzle_velocity = 260 //Guestimation
|
||||
|
||||
/obj/item/weapon/gun/projectile/fluff/m1911
|
||||
bolt_name="slide"
|
||||
bolt_release = "slide release"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY
|
||||
muzzle_velocity = 253 //M1911
|
||||
|
||||
//revolver.dm
|
||||
/obj/item/weapon/gun/projectile/revolver
|
||||
/obj/item/weapon/gun/projectile/revolver //To be updated to use .375
|
||||
manual_chamber = FALSE
|
||||
muzzle_velocity = 330 //Guestimation
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/detective //To be updated to use .38
|
||||
muzzle_velocity = 350 //Guestimation
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/detective45 //Awful.
|
||||
muzzle_velocity = 230 //Guestimation
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/deckard //To be updated to use .38
|
||||
muzzle_velocity = 365
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/judge
|
||||
muzzle_velocity = 440 //Temporary
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/lemat
|
||||
muzzle_velocity = 365
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/webley
|
||||
muzzle_velocity = 340 //Guestimation
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/consul
|
||||
muzzle_velocity = 350 //Guestimation
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/nova
|
||||
muzzle_velocity = 330 //Guestimation
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/cerberus
|
||||
muzzle_velocity = 340 //Guestimation
|
||||
|
||||
//semiauto.dm
|
||||
/obj/item/weapon/gun/projectile/garand
|
||||
/obj/item/weapon/gun/projectile/garand //To be updated to use .30 springfield.
|
||||
bolt_name="charging handle"
|
||||
auto_loading_type = CLOSED_BOLT | LOCK_OPEN_EMPTY | CHAMBER_ON_RELOAD
|
||||
bolt_release = null
|
||||
muzzle_velocity = 853 //Actual gun.
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolvingrifle
|
||||
manual_chamber = FALSE
|
||||
muzzle_velocity = 500 //Guestimation from leveraction .44 minus some for being a revolver.
|
||||
|
||||
//shotgun.dm
|
||||
/obj/item/weapon/gun/projectile/shotgun
|
||||
muzzle_velocity = 470 //Temporary
|
||||
|
||||
/obj/item/weapon/gun/projectile/shotgun/pump
|
||||
manual_chamber = FALSE
|
||||
|
||||
@@ -119,10 +231,13 @@
|
||||
//shotgun_yw.dm
|
||||
/obj/item/weapon/gun/projectile/revolvershotgun
|
||||
manual_chamber = FALSE
|
||||
muzzle_velocity = 470 //Temporary
|
||||
|
||||
//sniper.dm
|
||||
/obj/item/weapon/gun/projectile/heavysniper
|
||||
manual_chamber = FALSE
|
||||
muzzle_velocity = 1132 //Istiglal IST-14.5 anti-materiel rifle
|
||||
|
||||
/obj/item/weapon/gun/projectile/SVD
|
||||
bolt_name = "charging handle"
|
||||
/obj/item/weapon/gun/projectile/SVD //To be updated to use actual 7.62x54 instead of 7.62 NATO
|
||||
bolt_name = "charging handle"
|
||||
muzzle_velocity = 830 //Actual gun.
|
||||
|
||||
@@ -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,28 @@
|
||||
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
|
||||
|
||||
//Special ammo handling bullshit
|
||||
|
||||
/obj/item/weapon/gun/projectile/pirate/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.sub_velocity(P.velocity * 0.3) //Yeah, a gun that supposedly shoots any bullet is gonna be pretty shit.
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/lemat/process_accuracy(obj/projectile, mob/living/user, atom/target, var/burst, var/held_twohanded)
|
||||
. = ..()
|
||||
var/obj/item/projectile/bullet/P = projectile
|
||||
P.velocity = initial(P.velocity)
|
||||
if(!istype(P))
|
||||
return
|
||||
P.sub_velocity(P.velocity - 35)
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
#define GRAINS_PER_KG 15432.4
|
||||
|
||||
/obj/item/projectile/bullet
|
||||
var/diam = 9 //mm
|
||||
var/energy_add = 0
|
||||
var/velocity = 500 //Meters per second
|
||||
var/hollow_point = FALSE
|
||||
var/grains = 115 //I hope the unit is obvious
|
||||
var/energy //Joules
|
||||
var/old_bullet_act = FALSE
|
||||
|
||||
/obj/item/projectile/bullet/launch_projectile(atom/target, target_zone, mob/user, params, angle_override, forced_spread = 0)
|
||||
energy = 0.5 * velocity * velocity * (grains / GRAINS_PER_KG) + energy_add
|
||||
sub_energy(0)
|
||||
return ..()
|
||||
|
||||
/obj/item/projectile/bullet/proc/sub_velocity(var/amount)
|
||||
velocity = max(0,velocity - amount)
|
||||
energy = 0.5 * 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))
|
||||
|
||||
//Pistol projectiles
|
||||
|
||||
/obj/item/projectile/bullet/pistol //9x19mm
|
||||
diam = 9
|
||||
grains = 108
|
||||
velocity = 381
|
||||
|
||||
/obj/item/projectile/bullet/pistol/ap
|
||||
grains = 66
|
||||
energy_add = 893
|
||||
velocity = 595
|
||||
armor_penetration = 25
|
||||
|
||||
/obj/item/projectile/bullet/pistol/hp
|
||||
grains = 131
|
||||
velocity = 350
|
||||
energy_add = -96.18
|
||||
hollow_point = TRUE
|
||||
armor_penetration = -50
|
||||
|
||||
/obj/item/projectile/bullet/pistol/medium //.45
|
||||
diam = 11.43
|
||||
grains = 230
|
||||
velocity = 295
|
||||
|
||||
/obj/item/projectile/bullet/pistol/medium/ap
|
||||
grains = 173
|
||||
energy_add = 374
|
||||
velocity = 347
|
||||
armor_penetration = 25
|
||||
|
||||
/obj/item/projectile/bullet/pistol/medium/hp
|
||||
grains = 230
|
||||
velocity = 286
|
||||
armor_penetration = -50
|
||||
|
||||
/obj/item/projectile/bullet/pistol/strong //.357 and .44 are grouped because ftw
|
||||
grains = 240
|
||||
velocity = 360
|
||||
|
||||
//Shotgun projectiles
|
||||
|
||||
/obj/item/projectile/bullet/shotgun //Slug
|
||||
grains = 657
|
||||
velocity = 489
|
||||
armor_penetration = -50 //Slugs needed a nerf. Will probably fix the stats for shotguns in general in future updates.
|
||||
|
||||
/obj/item/projectile/bullet/shotgun/buckshot //#00 Buckshot
|
||||
damage = 5
|
||||
name = "buckshot pellet"
|
||||
diam = 8.38
|
||||
grains = 53.8
|
||||
velocity = 489
|
||||
armor_penetration = -30
|
||||
|
||||
/obj/item/projectile/bullet/shotgun/buckshot/shell
|
||||
use_submunitions = TRUE
|
||||
submunition_spread_max = 67.5
|
||||
submunitions = list(/obj/item/projectile/bullet/shotgun/buckshot = 8)
|
||||
|
||||
/obj/item/ammo_casing/a12g/pellet
|
||||
name = "shotgun buckshot shell"
|
||||
desc = "A 12 gauge buckshot shell."
|
||||
icon_state = "gshell"
|
||||
projectile_type = /obj/item/projectile/bullet/shotgun/buckshot/shell
|
||||
|
||||
//Rifle projectiles
|
||||
/obj/item/projectile/bullet/rifle
|
||||
armor_penetration = 0 //No. Rifle rounds don't get extra AP by default, their nature already makes them more armor penetrating.
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a762 //7.62x51 NATO
|
||||
diam = 7.62
|
||||
grains = 147
|
||||
velocity = 850
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a762/ap
|
||||
grains = 150.5
|
||||
velocity = 854.6
|
||||
armor_penetration = 50
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a762/hp
|
||||
grains = 175
|
||||
energy_add = -539.978
|
||||
velocity = 792
|
||||
armor_penetration = -50
|
||||
hollow_point = TRUE
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a545
|
||||
diam = 5.45
|
||||
grains = 53
|
||||
velocity = 880
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a545/ap
|
||||
grains = 57
|
||||
velocity = 890
|
||||
armor_penetration = 50
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a545/hp
|
||||
hollow_point = TRUE
|
||||
armor_penetration = -50
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a145 // 14.5×114mm
|
||||
grains = 921
|
||||
velocity = 1000
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a145/highvel
|
||||
grains = 700
|
||||
energy_add = 9979
|
||||
velocity = 1200
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a44rifle
|
||||
diam = 10.9
|
||||
grains = 240
|
||||
velocity = 536.448
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a95 //I hate you. There is no real world analog for 9.5x40mm, I will guestimate from the 9x39mm russian round and give it some bonus for future points or whatever
|
||||
diam = 9.5
|
||||
grains = 310
|
||||
velocity = 365
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a762/lmg //This is actually 7.92x57 ffs
|
||||
diam = 7.92
|
||||
grains = 181
|
||||
velocity = 820
|
||||
|
||||
//Various "We're not dealing with this shit because of how bad it is" (Some of these may be implemented into the new system with later updates)
|
||||
/obj/item/projectile/bullet/magnetic
|
||||
old_bullet_act = TRUE
|
||||
|
||||
/obj/item/projectile/bullet/pellet
|
||||
old_bullet_act = TRUE
|
||||
|
||||
/obj/item/projectile/bullet/pellet/shotgun/flak
|
||||
old_bullet_act = TRUE
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a762/hunter
|
||||
old_bullet_act = TRUE
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a545/hunter
|
||||
old_bullet_act = TRUE
|
||||
|
||||
/obj/item/projectile/bullet/suffocationbullet
|
||||
old_bullet_act = TRUE
|
||||
|
||||
/obj/item/projectile/bullet/cyanideround
|
||||
old_bullet_act = TRUE
|
||||
|
||||
/obj/item/projectile/bullet/burstbullet
|
||||
old_bullet_act = TRUE
|
||||
|
||||
/obj/item/projectile/bullet/incendiary
|
||||
old_bullet_act = TRUE
|
||||
|
||||
/obj/item/projectile/bullet/practice
|
||||
old_bullet_act = TRUE
|
||||
|
||||
/obj/item/projectile/bullet/blank
|
||||
old_bullet_act = TRUE
|
||||
|
||||
/obj/item/projectile/bullet/srmrocket
|
||||
old_bullet_act = TRUE
|
||||
|
||||
/obj/item/projectile/bullet/chemdart
|
||||
old_bullet_act = TRUE
|
||||
|
||||
/obj/item/projectile/bullet/gyro
|
||||
old_bullet_act = TRUE
|
||||
Reference in New Issue
Block a user