diff --git a/code/datums/greyscale/greyscale_configs.dm b/code/datums/greyscale/greyscale_configs.dm
index 7276807de8f..4c00fbf565d 100644
--- a/code/datums/greyscale/greyscale_configs.dm
+++ b/code/datums/greyscale/greyscale_configs.dm
@@ -262,336 +262,6 @@
json_config = 'code/datums/greyscale/json_configs/projectiles.json'
icon_file = 'icons/obj/items/projectiles.dmi'
-
-/datum/greyscale_config/gun
- json_config = 'code/datums/greyscale/json_configs/gun.json'
- icon_file ='icons/Marine/greyscale_gun/gun.dmi'
- prefix = "t18_"
- ignore_states = list("loaded_fire", "belt", "loaded_l", "loaded_a", "unloaded_a")
-
-/datum/greyscale_config/gun/tx11
- prefix = "tx11_"
-/datum/greyscale_config/gun/tx15
- prefix = "tx15_"
-
-/datum/greyscale_config/gun/t90
- prefix = "t90_"
-
-/datum/greyscale_config/gun/sg29
- prefix = "sg29_"
-
-//Pistols
-/datum/greyscale_config/gun/pistol
- ignore_states = list("loaded_fire", "loaded_l", "loaded_a", "unloaded_a")
- prefix = "tp14_"
-
-/datum/greyscale_config/gun/pistol/tp23
- prefix = "tp23_"
-
-/datum/greyscale_config/gun/pistol/tx7
- ignore_states = list("loaded_fire", "loaded_l")
- prefix = "tx7_"
-
-/datum/greyscale_config/gun/pistol/tep
- icon_file ='icons/Marine/greyscale_gun/gun_64.dmi'
- ignore_states = list("loaded_fire", "loaded_a", "unloaded_a")
- prefix = "tep_"
-
-//Revolvers
-/datum/greyscale_config/gun/revolver
- json_config = 'code/datums/greyscale/json_configs/gun_revolver.json'
- ignore_states = list()
- prefix = "tp44_"
-
-//64 pixel guns
-/datum/greyscale_config/gun/gun64
- icon_file ='icons/Marine/greyscale_gun/gun_64.dmi'
- prefix = "t12_"
-/datum/greyscale_config/gun/gun64/t42
- prefix = "t42_"
-/datum/greyscale_config/gun/gun64/t81
- prefix = "t81_"
-/datum/greyscale_config/gun/gun64/t21
- prefix = "t21_"
-
-/datum/greyscale_config/gun/gun64/t60
- ignore_states = list("belt", "loaded_l", "loaded_a", "unloaded_a")
- prefix = "t60_"
-
-/datum/greyscale_config/gun/gun64/t37
- prefix = "t37_"
-
-/datum/greyscale_config/gun/gun64/lasgun
- ignore_states = list("loaded_fire", "belt", "loaded_a", "unloaded_a")
- prefix = "ter_"
-
-/datum/greyscale_config/gun/gun64/lasgun/tec
- prefix = "tec_"
-
-/datum/greyscale_config/gun/gun64/lasgun/tem
- prefix = "tem_"
-
-/datum/greyscale_config/gun/gun64/lasgun/tes
- prefix = "tes_"
-
-
-/datum/greyscale_config/gun/gun64/shotgun
- json_config = 'code/datums/greyscale/json_configs/gun_shotgun.json'
- ignore_states = list()
- prefix = "t35_"
-
-/datum/greyscale_config/gun/gun64/shotgun/tl127
- prefix = "tl127_"
-
-//Mob Sprites for guns
-
-/datum/greyscale_config/worn_gun
- json_config = 'code/datums/greyscale/json_configs/gun_mob.json'
- icon_file = 'icons/Marine/greyscale_gun/back.dmi'
- prefix = "t12_"
-
-/datum/greyscale_config/worn_gun/t42
- prefix = "t42_"
-
-/datum/greyscale_config/worn_gun/t18
- prefix = "t18_"
-
-/datum/greyscale_config/worn_gun/t81
- prefix = "t81_"
-
-/datum/greyscale_config/worn_gun/t21
- prefix = "t21_"
-
-/datum/greyscale_config/worn_gun/t35
- prefix = "t35_"
-
-/datum/greyscale_config/worn_gun/tx11
- prefix = "tx11_"
-
-/datum/greyscale_config/worn_gun/tx15
- prefix = "tx15_"
-
-/datum/greyscale_config/worn_gun/t90
- prefix = "t90_"
-
-/datum/greyscale_config/worn_gun/t37
- prefix = "t37_"
-
-/datum/greyscale_config/worn_gun/ter
- prefix = "ter_"
-
-/datum/greyscale_config/worn_gun/tec
- prefix = "tec_"
-
-/datum/greyscale_config/worn_gun/tem
- prefix = "tem_"
-
-/datum/greyscale_config/worn_gun/tes
- prefix = "tes_"
-
-/datum/greyscale_config/worn_gun/t60
- prefix = "t60_"
-
-/datum/greyscale_config/worn_gun/sg29
- prefix = "sg29_"
-
-/datum/greyscale_config/worn_gun/tl127
- prefix = "tl127_"
-
-/datum/greyscale_config/worn_gun/suit
- icon_file = 'icons/Marine/greyscale_gun/suit.dmi'
-
-/datum/greyscale_config/worn_gun/suit/t42
- prefix = "t42_"
-
-/datum/greyscale_config/worn_gun/suit/t18
- prefix = "t18_"
-
-/datum/greyscale_config/worn_gun/suit/t81
- prefix = "t81_"
-
-/datum/greyscale_config/worn_gun/suit/t21
- prefix = "t21_"
-
-/datum/greyscale_config/worn_gun/suit/t35
- prefix = "t35_"
-
-/datum/greyscale_config/worn_gun/suit/tx11
- prefix = "tx11_"
-
-/datum/greyscale_config/worn_gun/suit/tx15
- prefix = "tx15_"
-
-/datum/greyscale_config/worn_gun/suit/t90
- prefix = "t90_"
-
-/datum/greyscale_config/worn_gun/suit/t37
- prefix = "t37_"
-
-/datum/greyscale_config/worn_gun/suit/ter
- prefix = "ter_"
-/datum/greyscale_config/worn_gun/suit/tec
- prefix = "tec_"
-/datum/greyscale_config/worn_gun/suit/tem
- prefix = "tem_"
-/datum/greyscale_config/worn_gun/suit/tes
- prefix = "tes_"
-
-/datum/greyscale_config/worn_gun/suit/t60
- prefix = "t60_"
-
-/datum/greyscale_config/worn_gun/suit/tl127
- prefix = "tl127_"
-
-/datum/greyscale_config/worn_gun/suit/sg29
- prefix = "sg29_"
-
-/datum/greyscale_config/gun_inhand
- json_config = 'code/datums/greyscale/json_configs/gun_hands.json'
- icon_file = 'icons/Marine/greyscale_gun/l_hand.dmi'
- prefix = "t12_"
-
-/datum/greyscale_config/gun_inhand/t42
- icon_file = 'icons/Marine/greyscale_gun/l_hand_64.dmi'
- prefix = "t42_"
-
-/datum/greyscale_config/gun_inhand/t18
- prefix = "t18_"
-
-/datum/greyscale_config/gun_inhand/t81
- prefix = "t81_"
-
-/datum/greyscale_config/gun_inhand/t21
- icon_file = 'icons/Marine/greyscale_gun/l_hand_64.dmi'
- prefix = "t21_"
-
-/datum/greyscale_config/gun_inhand/t35
- prefix = "t35_"
-
-/datum/greyscale_config/gun_inhand/tx11
- prefix = "tx11_"
-
-/datum/greyscale_config/gun_inhand/tx15
- prefix = "tx15_"
-
-/datum/greyscale_config/gun_inhand/tp14
- prefix = "tp14_"
-
-/datum/greyscale_config/gun_inhand/tp23
- prefix = "tp23_"
-
-/datum/greyscale_config/gun_inhand/tp44
- prefix = "tp44_"
-
-/datum/greyscale_config/gun_inhand/t90
- prefix = "t90_"
-
-/datum/greyscale_config/gun_inhand/t37
- icon_file = 'icons/Marine/greyscale_gun/l_hand_64.dmi'
- prefix = "t37_"
-
-/datum/greyscale_config/gun_inhand/ter
- prefix = "ter_"
-/datum/greyscale_config/gun_inhand/tep
- prefix = "tep_"
-/datum/greyscale_config/gun_inhand/tec
- prefix = "tec_"
-/datum/greyscale_config/gun_inhand/tem
- prefix = "tem_"
-/datum/greyscale_config/gun_inhand/tes
- prefix = "tes_"
-
-/datum/greyscale_config/gun_inhand/tx7
- prefix = "tx7_"
-
-/datum/greyscale_config/gun_inhand/t60
- icon_file = 'icons/Marine/greyscale_gun/l_hand_64.dmi'
- prefix = "t60_"
-
-/datum/greyscale_config/gun_inhand/tl127
- icon_file = 'icons/Marine/greyscale_gun/l_hand_64.dmi'
- prefix = "tl127_"
-
-/datum/greyscale_config/gun_inhand/sg29
- prefix = "sg29_"
-
-/datum/greyscale_config/gun_inhand/r_hand
- icon_file = 'icons/Marine/greyscale_gun/r_hand.dmi'
-
-/datum/greyscale_config/gun_inhand/r_hand/t42
- icon_file = 'icons/Marine/greyscale_gun/r_hand_64.dmi'
- prefix = "t42_"
-
-/datum/greyscale_config/gun_inhand/r_hand/t18
- prefix = "t18_"
-
-/datum/greyscale_config/gun_inhand/r_hand/t81
- prefix = "t81_"
-
-/datum/greyscale_config/gun_inhand/r_hand/t21
- icon_file = 'icons/Marine/greyscale_gun/r_hand_64.dmi'
- prefix = "t21_"
-
-/datum/greyscale_config/gun_inhand/r_hand/t35
- prefix = "t35_"
-
-/datum/greyscale_config/gun_inhand/r_hand/tx11
- prefix = "tx11_"
-
-/datum/greyscale_config/gun_inhand/r_hand/tx15
- prefix = "tx15_"
-
-/datum/greyscale_config/gun_inhand/r_hand/tp14
- prefix = "tp14_"
-
-/datum/greyscale_config/gun_inhand/r_hand/tp23
- prefix = "tp23_"
-
-/datum/greyscale_config/gun_inhand/r_hand/tp44
- prefix = "tp44_"
-
-/datum/greyscale_config/gun_inhand/r_hand/t90
- prefix = "t90_"
-
-/datum/greyscale_config/gun_inhand/r_hand/t37
- icon_file = 'icons/Marine/greyscale_gun/r_hand_64.dmi'
- prefix = "t37_"
-
-/datum/greyscale_config/gun_inhand/r_hand/ter
- prefix = "ter_"
-/datum/greyscale_config/gun_inhand/r_hand/tep
- prefix = "tep_"
-/datum/greyscale_config/gun_inhand/r_hand/tec
- prefix = "tec_"
-/datum/greyscale_config/gun_inhand/r_hand/tem
- prefix = "tem_"
-/datum/greyscale_config/gun_inhand/r_hand/tes
- prefix = "tes_"
-
-/datum/greyscale_config/gun_inhand/r_hand/tx7
- prefix = "tx7_"
-
-/datum/greyscale_config/gun_inhand/r_hand/t60
- icon_file = 'icons/Marine/greyscale_gun/r_hand_64.dmi'
- prefix = "t60_"
-
-/datum/greyscale_config/gun_inhand/r_hand/tl127
- icon_file = 'icons/Marine/greyscale_gun/r_hand_64.dmi'
- prefix = "tl127_"
-
-/datum/greyscale_config/gun_inhand/r_hand/sg29
- prefix = "sg29_"
-
-//Attachments
-/datum/greyscale_config/gun_attachment
- json_config = 'code/datums/greyscale/json_configs/attachments.json'
- icon_file = 'icons/Marine/greyscale_gun/attachments.dmi'
-
-/datum/greyscale_config/gun_attachment_64
- json_config = 'code/datums/greyscale/json_configs/attachments_64.json'
- icon_file = 'icons/Marine/greyscale_gun/attachments_64.dmi'
-
-
/*
* MECHS
*/
diff --git a/code/modules/projectiles/ammo_datums.dm b/code/modules/projectiles/ammo_datums.dm
deleted file mode 100644
index 8edf5ca506f..00000000000
--- a/code/modules/projectiles/ammo_datums.dm
+++ /dev/null
@@ -1,4717 +0,0 @@
-#define DEBUG_STAGGER_SLOWDOWN 0
-
-GLOBAL_LIST_INIT(no_sticky_resin, typecacheof(list(/obj/item/clothing/mask/facehugger, /obj/alien/egg, /obj/structure/mineral_door, /obj/alien/resin, /obj/structure/bed/nest))) //For sticky/acid spit
-
-/datum/ammo
- var/name = "generic bullet"
- var/icon = 'icons/obj/items/projectiles.dmi'
- var/icon_state = "bullet"
- ///used in icons/obj/items/ammo for use in generating handful sprites
- var/handful_icon_state = "bullet"
- ///how much of this ammo you can carry in a handful
- var/handful_amount = 8
- ///Bullet type on the Ammo HUD
- var/hud_state = "unknown"
- var/hud_state_empty = "unknown"
- ///The icon that is displayed when the bullet bounces off something.
- var/ping = "ping_b"
- ///When it deals damage.
- var/sound_hit
- ///When it's blocked by human armor.
- var/sound_armor
- ///When it misses someone.
- var/sound_miss
- ///When it bounces off something.
- var/sound_bounce
-
- ///This is added to the bullet's base accuracy
- var/accuracy = 0
- ///How much the accuracy varies when fired
- var/accuracy_var_low = 1
- var/accuracy_var_high = 1
- ///For most guns, this is where the bullet dramatically looses accuracy. Not for snipers though
- var/accurate_range = 5
- ///Snipers use this to simulate poor accuracy at close ranges
- var/accurate_range_min = 0
- ///Weapons will get a large accuracy buff at this short range
- var/point_blank_range = 0
- ///This will de-increment a counter on the bullet
- var/max_range = 20
- ///How much the ammo scatters when burst fired, added to gun scatter, along with other mods
- var/scatter = 0
- ///This is the base damage of the bullet as it is fired
- var/damage = 0
- ///How much damage the bullet loses per turf traveled
- var/damage_falloff = 1
- ///BRUTE, BURN, TOX, OXY, CLONE are the only things that should be in here
- var/damage_type = BRUTE
- ///How much armor it ignores before calculations take place
- var/penetration = 0
- ///How much extra penetration applies to xeno
- var/additional_xeno_penetration = 0
- ///The % chance it will imbed in a human
- var/shrapnel_chance = 0
- ///How fast the projectile moves
- var/shell_speed = 2
- ///Type path of the extra projectiles
- var/bonus_projectiles_type
- ///How many extra projectiles it shoots out. Works kind of like firing on burst, but all of the projectiles travel together
- var/bonus_projectiles_amount = 0
- ///Degrees scattered per two projectiles, each in a different direction.
- var/bonus_projectiles_scatter = 8
- ///How far the bullet can travel before incurring a chance of hitting barricades; normally 1.
- var/barricade_clear_distance = 1
- ///Does this have an override for the armor type the ammo should test? Bullet by default
- var/armor_type = BULLET
- ///How many stacks of sundering to apply to a mob on hit
- var/sundering = 0
- ///how much damage airbursts do to mobs around the target, multiplier of the bullet's damage
- var/airburst_multiplier = 0.1
- ///What kind of behavior the ammo has
- var/flags_ammo_behavior = NONE
- ///Determines what color our bullet will be when it flies
- var/bullet_color = COLOR_WHITE
- ///If this ammo is hitscan, the icon of beam coming out from the gun
- var/hitscan_effect_icon = "beam"
- ///A multiplier applied to piercing projectile, that reduces its damage/penetration/sundering on hit
- var/on_pierce_multiplier = 1
- ///greyscale config for the bullet items associated with the ammo
- var/handful_greyscale_config = null
- ///greyscale color for the bullet items associated with the ammo
- var/handful_greyscale_colors = null
- ///greyscale config for the projectile associated with the ammo
- var/projectile_greyscale_config = null
- ///greyscale color for the projectile associated with the ammo
- var/projectile_greyscale_colors = null
- ///Multiplier for deflagrate chance
- var/deflagrate_multiplier = 1
- ///Flat damage caused if fire_burst is triggered by deflagrate
- var/fire_burst_damage = 10
- ///Base fire stacks added on hit if the projectile has AMMO_INCENDIARY
- var/incendiary_strength = 10
- ///Embeding shrapnel type
- var/shrapnel_type = /obj/item/shard/shrapnel
-
-/datum/ammo/proc/do_at_max_range(turf/T, obj/projectile/proj)
- return
-
-///Does it do something special when shield blocked? Ie. a flare or grenade that still blows up.
-/datum/ammo/proc/on_shield_block(mob/M, obj/projectile/proj)
- return
-
-///Special effects when hitting dense turfs.
-/datum/ammo/proc/on_hit_turf(turf/T, obj/projectile/proj)
- return
-
-///Special effects when hitting mobs.
-/datum/ammo/proc/on_hit_mob(mob/M, obj/projectile/proj)
- return
-
-///Special effects when hitting objects.
-/datum/ammo/proc/on_hit_obj(obj/O, obj/projectile/proj)
- return
-
-///Special effects for leaving a turf. Only called if the projectile has AMMO_LEAVE_TURF enabled
-/datum/ammo/proc/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
- return
-
-///Handles CC application on the victim
-/datum/ammo/proc/staggerstun(mob/victim, obj/projectile/proj, max_range = 5, stun = 0, weaken = 0, stagger = 0, slowdown = 0, knockback = 0, soft_size_threshold = 3, hard_size_threshold = 2)
- if(!victim)
- CRASH("staggerstun called without a mob target")
- if(!isliving(victim))
- return
- if(get_dist_euclidean(proj.starting_turf, victim) > max_range)
- return
- var/impact_message = ""
- if(isxeno(victim))
- var/mob/living/carbon/xenomorph/xeno_victim = victim
- if(xeno_victim.fortify) //If we're fortified we don't give a shit about staggerstun.
- impact_message += span_xenodanger("Your fortified stance braces you against the impact.")
- return
-
- if(xeno_victim.endure) //Endure allows us to ignore staggerstun.
- impact_message += span_xenodanger("You endure the impact from [proj], shrugging off its effects.")
- return
-
- if(xeno_victim.crest_defense) //Crest defense halves all effects, and protects us from the stun.
- impact_message += span_xenodanger("Your crest protects you against some of the impact.")
- slowdown *= 0.5
- stagger *= 0.5
- stun = 0
-
- //Check for and apply hard CC.
- if(hard_size_threshold >= victim.mob_size && (stun || weaken || knockback))
- var/mob/living/living_victim = victim
- if(living_victim.IsStun() || living_victim.IsParalyzed()) //Prevent chain stunning.
- stun = 0
- weaken = 0
-
- if(stun || weaken)
- var/list/stunlist = list(stun, weaken, stagger, slowdown)
- if(SEND_SIGNAL(living_victim, COMSIG_LIVING_PROJECTILE_STUN, stunlist, armor_type, penetration))
- stun = stunlist[1]
- weaken = stunlist[2]
- stagger = stunlist[3]
- slowdown = stunlist[4]
- living_victim.apply_effects(stun,weaken)
-
- if(knockback)
- if(isxeno(victim))
- impact_message += span_xenodanger("The blast knocks you off your feet!")
- else
- impact_message += span_highdanger("The blast knocks you off your feet!")
- victim.knockback(proj, knockback, 5)
-
- //Check for and apply soft CC
- if(iscarbon(victim))
- var/mob/living/carbon/carbon_victim = victim
- #if DEBUG_STAGGER_SLOWDOWN
- to_chat(world, span_debuginfo("Damage: Initial stagger is: [target.IsStaggered()]"))
- #endif
- if(!HAS_TRAIT(carbon_victim, TRAIT_STAGGER_RESISTANT)) //Some mobs like the Queen are immune to projectile stagger
- carbon_victim.adjust_stagger(stagger)
- #if DEBUG_STAGGER_SLOWDOWN
- to_chat(world, span_debuginfo("Damage: Final stagger is: [target.IsStaggered()]"))
- #endif
- #if DEBUG_STAGGER_SLOWDOWN
- to_chat(world, span_debuginfo("Damage: Initial slowdown is: [target.slowdown]"))
- #endif
- carbon_victim.add_slowdown(slowdown)
- #if DEBUG_STAGGER_SLOWDOWN
- to_chat(world, span_debuginfo("Damage: Final slowdown is: [target.slowdown]"))
- #endif
- to_chat(victim, "[impact_message]") //Summarize all the bad shit that happened
-
-
-/datum/ammo/proc/airburst(atom/target, obj/projectile/proj)
- if(!target || !proj)
- CRASH("airburst() error: target [isnull(target) ? "null" : target] | proj [isnull(proj) ? "null" : proj]")
- for(var/mob/living/carbon/victim in orange(1, target))
- if(proj.firer == victim)
- continue
- victim.visible_message(span_danger("[victim] is hit by backlash from \a [proj.name]!"),
- isxeno(victim) ? span_xenodanger("We are hit by backlash from \a [proj.name]!") : span_highdanger("You are hit by backlash from \a [proj.name]!"))
- victim.apply_damage(proj.damage * proj.airburst_multiplier, proj.ammo.damage_type, blocked = armor_type, updating_health = TRUE)
-
-///handles the probability of a projectile hit to trigger fire_burst, based off actual damage done
-/datum/ammo/proc/deflagrate(atom/target, obj/projectile/proj)
- if(!target || !proj)
- CRASH("deflagrate() error: target [isnull(target) ? "null" : target] | proj [isnull(proj) ? "null" : proj]")
- if(!istype(target, /mob/living))
- return
-
- var/mob/living/victim = target
- var/deflagrate_chance = victim.modify_by_armor(proj.damage - (proj.distance_travelled * proj.damage_falloff), FIRE, proj.penetration) * deflagrate_multiplier
- if(prob(deflagrate_chance))
- new /obj/effect/temp_visual/shockwave(get_turf(victim), 2)
- playsound(target, "incendiary_explosion", 40)
- fire_burst(target, proj)
-
-///the actual fireblast triggered by deflagrate
-/datum/ammo/proc/fire_burst(atom/target, obj/projectile/proj)
- if(!target || !proj)
- CRASH("fire_burst() error: target [isnull(target) ? "null" : target] | proj [isnull(proj) ? "null" : proj]")
- for(var/mob/living/carbon/victim in range(1, target))
- if(victim == target)
- victim.visible_message(span_danger("[victim] bursts into flames as they are deflagrated by \a [proj.name]!"))
- else
- victim.visible_message(span_danger("[victim] is scorched by [target] as they burst into flames!"),
- isxeno(victim) ? span_xenodanger("We are scorched by [target] as they burst into flames!") : span_highdanger("you are scorched by [target] as they burst into flames!"))
- //Damages the victims, inflicts brief stagger+slow, and ignites
- victim.apply_damage(fire_burst_damage, BURN, blocked = FIRE, updating_health = TRUE)
-
- staggerstun(victim, proj, 30, stagger = 1 SECONDS, slowdown = 0.5)
- victim.adjust_fire_stacks(5)
- victim.IgniteMob()
-
-
-/datum/ammo/proc/fire_bonus_projectiles(obj/projectile/main_proj, atom/shooter, atom/source, range, speed, angle, target, origin_override)
- var/effect_icon = ""
- var/proj_type = /obj/projectile
- if(istype(main_proj, /obj/projectile/hitscan))
- proj_type = /obj/projectile/hitscan
- var/obj/projectile/hitscan/main_proj_hitscan = main_proj
- effect_icon = main_proj_hitscan.effect_icon
- for(var/i = 1 to bonus_projectiles_amount) //Want to run this for the number of bonus projectiles.
- var/obj/projectile/new_proj = new proj_type(main_proj.loc, effect_icon)
- if(bonus_projectiles_type)
- new_proj.generate_bullet(bonus_projectiles_type)
- else //If no bonus type is defined then the extra projectiles are the same as the main one.
- new_proj.generate_bullet(src)
-
- if(isgun(source))
- var/obj/item/weapon/gun/gun = source
- gun.apply_gun_modifiers(new_proj, target, shooter)
-
- //Scatter here is how many degrees extra stuff deviate from the main projectile, first two the same amount, one to each side, and from then on the extra pellets keep widening the arc.
- var/new_angle = angle + (main_proj.ammo.bonus_projectiles_scatter * ((i % 2) ? (-(i + 1) * 0.5) : (i * 0.5)))
- if(new_angle < 0)
- new_angle += 360
- else if(new_angle > 360)
- new_angle -= 360
- new_proj.fire_at(target, shooter, source, range, speed, new_angle, TRUE, loc_override = origin_override)
-
-///A variant of Fire_bonus_projectiles without fixed scatter and no link between gun and bonus_projectile accuracy
-/datum/ammo/proc/fire_directionalburst(obj/projectile/main_proj, atom/shooter, atom/source, projectile_amount, range, speed, angle, target)
- var/effect_icon = ""
- var/proj_type = /obj/projectile
- if(istype(main_proj, /obj/projectile/hitscan))
- proj_type = /obj/projectile/hitscan
- var/obj/projectile/hitscan/main_proj_hitscan = main_proj
- effect_icon = main_proj_hitscan.effect_icon
- for(var/i = 1 to projectile_amount) //Want to run this for the number of bonus projectiles.
- var/obj/projectile/new_proj = new proj_type(main_proj.loc, effect_icon)
- if(bonus_projectiles_type)
- new_proj.generate_bullet(bonus_projectiles_type)
- else //If no bonus type is defined then the extra projectiles are the same as the main one.
- new_proj.generate_bullet(src)
-
- if(isgun(source))
- var/obj/item/weapon/gun/gun = source
- gun.apply_gun_modifiers(new_proj, target, shooter)
-
- //Scatter here is how many degrees extra stuff deviate from the main projectile's firing angle. Fully randomised with no 45 degree cap like normal bullets
- var/f = (i-1)
- var/new_angle = angle + (main_proj.ammo.bonus_projectiles_scatter * ((f % 2) ? (-(f + 1) * 0.5) : (f * 0.5)))
- if(new_angle < 0)
- new_angle += 360
- if(new_angle > 360)
- new_angle -= 360
- new_proj.fire_at(target, main_proj.loc, source, range, speed, new_angle, TRUE)
-
-/datum/ammo/proc/drop_flame(turf/T)
- if(!istype(T))
- return
- T.ignite(20, 20)
-
-
-/datum/ammo/proc/set_smoke()
- return
-
-
-/datum/ammo/proc/drop_nade(turf/T)
- return
-
-///called on projectile process() when AMMO_SPECIAL_PROCESS flag is active
-/datum/ammo/proc/ammo_process(obj/projectile/proj, damage)
- CRASH("ammo_process called with unimplemented process!")
-
-///bounces the projectile by creating a new projectile and calculating an angle of reflection
-/datum/ammo/proc/reflect(turf/T, obj/projectile/proj, scatter_variance)
- if(!bonus_projectiles_type)
- return
-
- var/new_range = proj.proj_max_range - proj.distance_travelled
- if(new_range <= 0)
- return
-
- var/dir_to_proj = get_dir(T, proj)
- if(ISDIAGONALDIR(dir_to_proj))
- var/list/cardinals = list(turn(dir_to_proj, 45), turn(dir_to_proj, -45))
- for(var/direction in cardinals)
- var/turf/turf_to_check = get_step(T, direction)
- if(turf_to_check.density)
- cardinals -= direction
- dir_to_proj = pick(cardinals)
-
- var/perpendicular_angle = Get_Angle(T, get_step(T, dir_to_proj))
- var/new_angle = (perpendicular_angle + (perpendicular_angle - proj.dir_angle - 180) + rand(-scatter_variance, scatter_variance))
-
- if(new_angle < -360)
- new_angle += 720 //north is 0 instead of 360
- else if(new_angle < 0)
- new_angle += 360
- else if(new_angle > 360)
- new_angle -= 360
-
- bonus_projectiles_amount = 1
- fire_bonus_projectiles(proj, T, proj.shot_from, new_range, proj.projectile_speed, new_angle, null, get_step(T, dir_to_proj))
- bonus_projectiles_amount = 0
-
-/*
-//================================================
- Default Ammo
-//================================================
-*/
-//Only when things screw up do we use this as a placeholder.
-/datum/ammo/bullet
- name = "default bullet"
- icon_state = "bullet"
- flags_ammo_behavior = AMMO_BALLISTIC
- sound_hit = "ballistic_hit"
- sound_armor = "ballistic_armor"
- sound_miss = "ballistic_miss"
- sound_bounce = "ballistic_bounce"
- point_blank_range = 2
- accurate_range_min = 0
- shell_speed = 3
- damage = 10
- shrapnel_chance = 10
- bullet_color = COLOR_VERY_SOFT_YELLOW
- barricade_clear_distance = 2
-
-/*
-//================================================
- Pistol Ammo
-//================================================
-*/
-
-/datum/ammo/bullet/pistol
- name = "pistol bullet"
- hud_state = "pistol"
- hud_state_empty = "pistol_empty"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- damage = 20
- penetration = 5
- accurate_range = 5
- sundering = 1
-
-/datum/ammo/bullet/pistol/tiny
- name = "light pistol bullet"
- hud_state = "pistol_light"
- damage = 15
- penetration = 5
- sundering = 0.5
-
-/datum/ammo/bullet/pistol/tiny/ap
- name = "light pistol bullet"
- hud_state = "pistol_lightap"
- damage = 22.5
- penetration = 15 //So it can actually hurt something.
- sundering = 0.5
- damage_falloff = 1.5
-
-
-/datum/ammo/bullet/pistol/tranq
- name = "tranq bullet"
- hud_state = "pistol_tranq"
- damage = 25
- damage_type = STAMINA
-
-/datum/ammo/bullet/pistol/tranq/on_hit_mob(mob/victim, obj/projectile/proj)
- if(iscarbon(victim))
- var/mob/living/carbon/carbon_victim = victim
- carbon_victim.reagents.add_reagent(/datum/reagent/toxin/potassium_chlorophoride, 1)
-
-/datum/ammo/bullet/pistol/hollow
- name = "hollowpoint pistol bullet"
- hud_state = "pistol_hollow"
- accuracy = -10
- shrapnel_chance = 45
- sundering = 2
-
-/datum/ammo/bullet/pistol/hollow/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, stagger = 2 SECONDS, slowdown = 0.5, knockback = 1)
-
-/datum/ammo/bullet/pistol/ap
- name = "armor-piercing pistol bullet"
- hud_state = "pistol_ap"
- damage = 20
- penetration = 12.5
- shrapnel_chance = 15
- sundering = 0.5
-
-/datum/ammo/bullet/pistol/heavy
- name = "heavy pistol bullet"
- hud_state = "pistol_heavy"
- damage = 30
- penetration = 5
- shrapnel_chance = 25
- sundering = 2.15
-
-/datum/ammo/bullet/pistol/superheavy
- name = "high impact pistol bullet"
- hud_state = "pistol_superheavy"
- damage = 45
- penetration = 15
- sundering = 3
- damage_falloff = 0.75
-
-/datum/ammo/bullet/pistol/superheavy/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, stagger = 0.5 SECONDS, slowdown = 0.5, knockback = 1)
-
-/datum/ammo/bullet/pistol/superheavy/derringer
- handful_amount = 2
- handful_icon_state = "derringer"
-
-/datum/ammo/bullet/pistol/superheavy/derringer/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, slowdown = 0.5)
-
-/datum/ammo/bullet/pistol/mech
- name = "super-heavy pistol bullet"
- hud_state = "pistol_superheavy"
- damage = 45
- penetration = 20
- sundering = 1
-
-/datum/ammo/bullet/pistol/mech/burst
- name = "super-heavy pistol bullet"
- damage = 35
- penetration = 10
- sundering = 0.5
-
-/datum/ammo/bullet/pistol/incendiary
- name = "incendiary pistol bullet"
- hud_state = "pistol_fire"
- damage_type = BURN
- shrapnel_chance = 0
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY
- damage = 20
-
-/datum/ammo/bullet/pistol/squash
- name = "squash-head pistol bullet"
- hud_state = "pistol_squash"
- accuracy = 5
- damage = 32
- penetration = 10
- shrapnel_chance = 25
- sundering = 2
-
-/datum/ammo/bullet/pistol/mankey
- name = "live monkey"
- icon_state = "monkey1"
- hud_state = "monkey"
- hud_state_empty = "monkey_empty"
- ping = null //no bounce off.
- damage_type = BURN
- flags_ammo_behavior = AMMO_INCENDIARY|AMMO_IGNORE_ARMOR
- shell_speed = 2
- damage = 15
-
-
-/datum/ammo/bullet/pistol/mankey/on_hit_mob(mob/M, obj/projectile/P)
- if(!M.stat && !ismonkey(M))
- P.visible_message(span_danger("The [src] chimpers furiously!"))
- new /mob/living/carbon/human/species/monkey(P.loc)
-
-/*
-//================================================
- Revolver Ammo
-//================================================
-*/
-
-/datum/ammo/bullet/revolver
- name = "revolver bullet"
- hud_state = "revolver"
- hud_state_empty = "revolver_empty"
- handful_amount = 7
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- damage = 45
- penetration = 10
- sundering = 3
-
-/datum/ammo/bullet/revolver/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, stagger = 2 SECONDS, slowdown = 0.5, knockback = 1)
-
-/datum/ammo/bullet/revolver/rifle
- name = ".44 Long Special bullet"
- hud_state = "revolver_impact"
- handful_amount = 8
- damage = 60
- penetration = 30
- sundering = 3
- damage_falloff = 0
- shell_speed = 3.5
-
-/datum/ammo/bullet/revolver/t500
- name = ".500 Nigro Express revolver bullet"
- icon_state = "nigro"
- icon = 'icons/obj/items/ammo.dmi'
- handful_amount = 5
- damage = 100
- penetration = 40
- sundering = 0.5
-
-/datum/ammo/bullet/revolver/t500/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, stagger = 0, slowdown = 0, knockback = 1)
-
-/datum/ammo/bullet/revolver/t500/qk
- name = ".500 'Queen Killer' revolver bullet"
- icon_state = "nigro_qk"
- icon = 'icons/obj/items/ammo.dmi'
- handful_amount = 5
- damage = 100
- penetration = 40
- sundering = 0
-
-/datum/ammo/bullet/revolver/t500/qk/on_hit_mob(mob/M,obj/projectile/P)
- if(isxenoqueen(M))
- var/mob/living/carbon/xenomorph/X = M
- X.apply_damage(40)
- staggerstun(M, P, stagger = 0, slowdown = 0, knockback = 0)
- to_chat(X, span_highdanger("Something burn inside you!"))
- return
- staggerstun(M, P, stagger = 0, slowdown = 0, knockback = 1)
-
-/datum/ammo/bullet/revolver/tp44
- name = "standard revolver bullet"
- damage = 40
- penetration = 15
- sundering = 1
-
-/datum/ammo/bullet/revolver/tp44/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, knockback = 1)
-
-/datum/ammo/bullet/revolver/small
- name = "small revolver bullet"
- hud_state = "revolver_small"
- damage = 30
-
-/datum/ammo/bullet/revolver/small/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, slowdown = 0.5)
-
-/datum/ammo/bullet/revolver/marksman
- name = "slimline revolver bullet"
- hud_state = "revolver_slim"
- shrapnel_chance = 0
- damage_falloff = 0
- accuracy = 15
- accurate_range = 15
- damage = 30
- penetration = 10
-
-/datum/ammo/bullet/revolver/judge
- name = "oversized revolver bullet"
- hud_state = "revolver_slim"
- shrapnel_chance = 0
- damage_falloff = 0
- accuracy = 15
- accurate_range = 15
- damage = 70
- penetration = 10
-
-/datum/ammo/bullet/revolver/heavy
- name = "heavy revolver bullet"
- hud_state = "revolver_heavy"
- damage = 50
- penetration = 5
- accuracy = -10
-
-/datum/ammo/bullet/revolver/t76
- name = "magnum bullet"
- handful_amount = 5
- damage = 100
- penetration = 40
- sundering = 0.5
-
-/datum/ammo/bullet/revolver/t76/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, weaken = 2 SECONDS, knockback = 1)
-
-/datum/ammo/bullet/revolver/highimpact
- name = "high-impact revolver bullet"
- hud_state = "revolver_impact"
- handful_amount = 6
- damage = 50
- penetration = 20
- sundering = 3
-
-/datum/ammo/bullet/revolver/highimpact/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, weaken = 2 SECONDS, stagger = 2 SECONDS, slowdown = 1, knockback = 1)
-
-/datum/ammo/bullet/revolver/ricochet
- bonus_projectiles_type = /datum/ammo/bullet/revolver/small
- bonus_projectiles_scatter = 0
-
-/datum/ammo/bullet/revolver/ricochet/one
- bonus_projectiles_type = /datum/ammo/bullet/revolver/ricochet
-
-/datum/ammo/bullet/revolver/ricochet/two
- bonus_projectiles_type = /datum/ammo/bullet/revolver/ricochet/one
-
-/datum/ammo/bullet/revolver/ricochet/three
- bonus_projectiles_type = /datum/ammo/bullet/revolver/ricochet/two
-
-/datum/ammo/bullet/revolver/ricochet/four
- bonus_projectiles_type = /datum/ammo/bullet/revolver/ricochet/three
-
-/datum/ammo/bullet/revolver/ricochet/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, slowdown = 0.5)
-
-/datum/ammo/bullet/revolver/ricochet/on_hit_turf(turf/T, obj/projectile/proj)
- reflect(T, proj, 10)
-
-/*
-//================================================
- SMG Ammo
-//================================================
-*/
-
-/datum/ammo/bullet/smg
- name = "submachinegun bullet"
- hud_state = "smg"
- hud_state_empty = "smg_empty"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- accuracy_var_low = 7
- accuracy_var_high = 7
- damage = 20
- accurate_range = 4
- damage_falloff = 1
- sundering = 0.5
- penetration = 5
-
-/datum/ammo/bullet/smg/ap
- name = "armor-piercing submachinegun bullet"
- hud_state = "smg_ap"
- damage = 15
- penetration = 30
- sundering = 3
-
-/datum/ammo/bullet/smg/acp
- name = "submachinegun ACP bullet"
- hud_state = "smg"
- hud_state_empty = "smg_empty"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- accuracy_var_low = 7
- accuracy_var_high = 7
- damage = 20
- accurate_range = 4
- damage_falloff = 1
- sundering = 0.4
- penetration = 0
- shrapnel_chance = 25
-
-/datum/ammo/bullet/smg/ap/hv
- name = "high velocity armor-piercing submachinegun bullet"
- shell_speed = 4
-
-/datum/ammo/bullet/smg/hollow
- name = "hollow-point submachinegun bullet"
- hud_state = "pistol_squash"
- flags_ammo_behavior = AMMO_BALLISTIC
- damage = 35
- penetration = 0
- damage_falloff = 3
- shrapnel_chance = 45
-
-/datum/ammo/bullet/smg/incendiary
- name = "incendiary submachinegun bullet"
- hud_state = "smg_fire"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY
- damage = 18
- penetration = 0
-
-/datum/ammo/bullet/smg/rad
- name = "radioactive submachinegun bullet"
- hud_state = "smg_rad"
- damage = 15
- penetration = 15
- sundering = 1
-
-/datum/ammo/bullet/smg/rad/on_hit_mob(mob/M, obj/projectile/proj)
- if(!isliving(M))
- return
- var/mob/living/living_victim = M
- if(!prob(living_victim.modify_by_armor(proj.damage, BIO, penetration, proj.def_zone)))
- return
- living_victim.apply_radiation(2, 2)
-
-/datum/ammo/bullet/smg/mech
- name = "super-heavy submachinegun bullet"
- damage = 20
- sundering = 0.25
- penetration = 10
-
-/*
-//================================================
- Rifle Ammo
-//================================================
-*/
-
-/datum/ammo/bullet/rifle
- name = "rifle bullet"
- hud_state = "rifle"
- hud_state_empty = "rifle_empty"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- accurate_range = 12
- damage = 25
- penetration = 5
- sundering = 0.5
-
-/datum/ammo/bullet/rifle/T25
- name = "smartmachinegun bullet"
- bullet_color = COLOR_SOFT_RED //Red bullets to indicate friendly fire restriction
- hud_state = "smartgun"
- hud_state_empty = "smartgun_empty"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- accurate_range = 20
- damage = 20
- penetration = 10
- sundering = 1.5
-
-/datum/ammo/bullet/rifle/ap
- name = "armor-piercing rifle bullet"
- hud_state = "rifle_ap"
- damage = 20
- penetration = 25
- sundering = 3
-
-/datum/ammo/bullet/rifle/hv
- name = "high-velocity rifle bullet"
- hud_state = "hivelo"
- damage = 20
- penetration = 20
- sundering = 1.25
-
-/datum/ammo/bullet/rifle/heavy
- name = "heavy rifle bullet"
- hud_state = "rifle_heavy"
- damage = 30
- penetration = 10
- sundering = 1.25
-
-/datum/ammo/bullet/rifle/heavy/ap
- name = "heavy rifle bullet"
- damage = 25
- penetration = 25
- sundering = 3.5
-
-/datum/ammo/bullet/rifle/repeater
- name = "heavy impact rifle bullet"
- hud_state = "sniper"
- damage = 70
- penetration = 20
- sundering = 1.25
-
-/datum/ammo/bullet/rifle/repeater/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, max_range = 3, slowdown = 2, stagger = 1 SECONDS)
-
-/datum/ammo/bullet/rifle/incendiary
- name = "incendiary rifle bullet"
- hud_state = "rifle_fire"
- damage_type = BURN
- shrapnel_chance = 0
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY
- accuracy = -10
-
-/datum/ammo/bullet/rifle/machinegun
- name = "machinegun bullet"
- hud_state = "rifle_heavy"
- damage = 25
- penetration = 10
- sundering = 0.75
-
-/datum/ammo/bullet/rifle/som_machinegun
- name = "machinegun bullet"
- hud_state = "rifle_heavy"
- damage = 28
- penetration = 12.5
- sundering = 1
-
-/datum/ammo/bullet/rifle/som_machinegun/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, max_range = 20, slowdown = 0.5)
-
-/datum/ammo/bullet/rifle/tx8
- name = "A19 high velocity bullet"
- hud_state = "hivelo"
- hud_state_empty = "hivelo_empty"
- damage_falloff = 0
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- accurate_range = 15
- damage = 40
- penetration = 20
- sundering = 10
- bullet_color = COLOR_SOFT_RED
-
-/datum/ammo/bullet/rifle/tx8/incendiary
- name = "high velocity incendiary bullet"
- hud_state = "hivelo_fire"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB
- damage = 25
- penetration = 20
- sundering = 2.5
- bullet_color = LIGHT_COLOR_FIRE
-
-/datum/ammo/bullet/rifle/tx8/impact
- name = "high velocity impact bullet"
- hud_state = "hivelo_impact"
- damage = 30
- penetration = 10
- sundering = 12.5
-
-/datum/ammo/bullet/rifle/tx8/impact/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, max_range = 14, slowdown = 1, knockback = 1)
-
-/datum/ammo/bullet/rifle/mpi_km
- name = "crude heavy rifle bullet"
- hud_state = "rifle_crude"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- damage = 30
- penetration = 15
- sundering = 1.75
-
-/datum/ammo/bullet/rifle/standard_dmr
- name = "marksman bullet"
- hud_state = "hivelo"
- hud_state_empty = "hivelo_empty"
- damage_falloff = 0.5
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- accurate_range = 25
- accurate_range_min = 6
- max_range = 40
- damage = 65
- penetration = 15
- sundering = 2
-
-/datum/ammo/bullet/rifle/garand
- name = "heavy marksman bullet"
- hud_state = "sniper"
- damage = 75
- penetration = 25
- sundering = 1.25
-
-/datum/ammo/bullet/rifle/standard_br
- name = "light marksman bullet"
- hud_state = "hivelo"
- hud_state_empty = "hivelo_empty"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- penetration = 15
- damage = 32.5
- sundering = 1.25
-
-/datum/ammo/bullet/rifle/standard_br/ap
- name = "light marksman armor piercing bullet"
- penetration = 25
- damage = 27.5
- sundering = 3.25
-
-/datum/ammo/bullet/rifle/icc_confrontationrifle
- name = "armor-piercing heavy rifle bullet"
- hud_state = "rifle_ap"
- damage = 50
- penetration = 40
- sundering = 3.5
-
-/datum/ammo/bullet/rifle/mech
- name = "super-heavy rifle bullet"
- damage = 25
- penetration = 15
- sundering = 0.5
- damage_falloff = 0.8
-
-/datum/ammo/bullet/rifle/mech/burst
- damage = 35
- penetration = 10
-
-/datum/ammo/bullet/rifle/mech/lmg
- damage = 20
- penetration = 20
- damage_falloff = 0.7
-
-/*
-//================================================
- Shotgun Ammo
-//================================================
-*/
-
-/datum/ammo/bullet/shotgun
- hud_state_empty = "shotgun_empty"
- shell_speed = 2
- handful_amount = 5
-
-
-/datum/ammo/bullet/shotgun/slug
- name = "shotgun slug"
- handful_icon_state = "shotgun slug"
- hud_state = "shotgun_slug"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- shell_speed = 3
- max_range = 15
- damage = 100
- penetration = 20
- sundering = 7.5
-
-/datum/ammo/bullet/shotgun/slug/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, weaken = 2 SECONDS, stagger = 2 SECONDS, knockback = 1, slowdown = 2)
-
-
-/datum/ammo/bullet/shotgun/beanbag
- name = "beanbag slug"
- handful_icon_state = "beanbag slug"
- icon_state = "beanbag"
- hud_state = "shotgun_beanbag"
- flags_ammo_behavior = AMMO_BALLISTIC
- damage = 15
- max_range = 15
- shrapnel_chance = 0
- accuracy = 5
-
-/datum/ammo/bullet/shotgun/beanbag/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, weaken = 2 SECONDS, stagger = 4 SECONDS, knockback = 1, slowdown = 2, hard_size_threshold = 1)
-
-/datum/ammo/bullet/shotgun/incendiary
- name = "incendiary slug"
- handful_icon_state = "incendiary slug"
- hud_state = "shotgun_fire"
- damage_type = BRUTE
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY|AMMO_SUNDERING
- max_range = 10
- damage = 100
- penetration = 15
- sundering = 0
- bullet_color = COLOR_TAN_ORANGE
-
-/datum/ammo/bullet/shotgun/incendiary/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, weaken = 1 SECONDS, knockback = 1, slowdown = 1)
-
-/datum/ammo/bullet/shotgun/flechette
- name = "shotgun flechette shell"
- handful_icon_state = "shotgun flechette shell"
- icon_state = "flechette"
- hud_state = "shotgun_flechette"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- bonus_projectiles_type = /datum/ammo/bullet/shotgun/flechette/flechette_spread
- bonus_projectiles_amount = 2
- bonus_projectiles_scatter = 3
- accuracy_var_low = 8
- accuracy_var_high = 8
- max_range = 15
- damage = 50
- damage_falloff = 0.5
- penetration = 15
- sundering = 7
-
-/datum/ammo/bullet/shotgun/flechette/flechette_spread
- name = "additional flechette"
- damage = 40
- sundering = 5
-
-/datum/ammo/bullet/shotgun/buckshot
- name = "shotgun buckshot shell"
- handful_icon_state = "shotgun buckshot shell"
- icon_state = "buckshot"
- hud_state = "shotgun_buckshot"
- bonus_projectiles_type = /datum/ammo/bullet/shotgun/spread
- bonus_projectiles_amount = 5
- bonus_projectiles_scatter = 4
- accuracy_var_low = 9
- accuracy_var_high = 9
- accurate_range = 3
- max_range = 10
- damage = 40
- damage_falloff = 4
-
-/datum/ammo/bullet/shotgun/buckshot/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, weaken = 2 SECONDS, stagger = 2 SECONDS, knockback = 2, slowdown = 0.5, max_range = 3)
-
-/datum/ammo/bullet/shotgun/spread
- name = "additional buckshot"
- icon_state = "buckshot"
- accuracy_var_low = 9
- accuracy_var_high = 9
- accurate_range = 3
- max_range = 10
- damage = 40
- damage_falloff = 4
-
-
-/datum/ammo/bullet/shotgun/frag
- name = "shotgun explosive shell"
- handful_icon_state = "shotgun tracker shell"
- hud_state = "shotgun_tracker"
- flags_ammo_behavior = AMMO_BALLISTIC
- bonus_projectiles_type = /datum/ammo/bullet/shotgun/frag/frag_spread
- bonus_projectiles_amount = 2
- bonus_projectiles_scatter = 6
- accuracy_var_low = 8
- accuracy_var_high = 8
- max_range = 15
- damage = 10
- damage_falloff = 0.5
- penetration = 0
-
-/datum/ammo/bullet/shotgun/frag/drop_nade(turf/T)
- explosion(T, weak_impact_range = 2)
-
-/datum/ammo/bullet/shotgun/frag/on_hit_mob(mob/M, obj/projectile/P)
- drop_nade(get_turf(M))
-
-/datum/ammo/bullet/shotgun/frag/on_hit_obj(obj/O, obj/projectile/P)
- drop_nade(O.density ? P.loc : O.loc)
-
-/datum/ammo/bullet/shotgun/frag/on_hit_turf(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-/datum/ammo/bullet/shotgun/frag/do_at_max_range(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-/datum/ammo/bullet/shotgun/frag/frag_spread
- name = "additional frag shell"
- damage = 5
-
-/datum/ammo/bullet/shotgun/sx16_buckshot
- name = "shotgun buckshot shell" //16 gauge is between 12 and 410 bore.
- handful_icon_state = "shotgun buckshot shell"
- icon_state = "buckshot"
- hud_state = "shotgun_buckshot"
- bonus_projectiles_type = /datum/ammo/bullet/shotgun/sx16_buckshot/spread
- bonus_projectiles_amount = 4
- bonus_projectiles_scatter = 10
- accuracy_var_low = 10
- accuracy_var_high = 10
- max_range = 10
- damage = 25
- damage_falloff = 4
-
-/datum/ammo/bullet/shotgun/sx16_buckshot/spread
- name = "additional buckshot"
-
-/datum/ammo/bullet/shotgun/sx16_flechette
- name = "shotgun flechette shell"
- handful_icon_state = "shotgun flechette shell"
- icon_state = "flechette"
- hud_state = "shotgun_flechette"
- bonus_projectiles_type = /datum/ammo/bullet/shotgun/sx16_flechette/spread
- bonus_projectiles_amount = 4
- bonus_projectiles_scatter = 8
- accuracy_var_low = 7
- accuracy_var_high = 7
- max_range = 15
- damage = 15
- damage_falloff = 0.5
- penetration = 15
-
-/datum/ammo/bullet/shotgun/sx16_flechette/spread
- name = "additional flechette"
-
-/datum/ammo/bullet/shotgun/sx16_slug
- name = "shotgun slug"
- handful_icon_state = "shotgun slug"
- hud_state = "shotgun_slug"
- shell_speed = 3
- max_range = 15
- damage = 40
- penetration = 20
-
-/datum/ammo/bullet/shotgun/sx16_slug/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, slowdown = 1, knockback = 1)
-
-/datum/ammo/bullet/shotgun/tx15_flechette
- name = "shotgun flechette shell"
- handful_icon_state = "shotgun flechette shell"
- icon_state = "flechette"
- hud_state = "shotgun_flechette"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- bonus_projectiles_type = /datum/ammo/bullet/shotgun/tx15_flechette/spread
- bonus_projectiles_amount = 4
- bonus_projectiles_scatter = 2
- max_range = 15
- damage = 17
- damage_falloff = 0.25
- penetration = 15
- sundering = 1.5
-
-/datum/ammo/bullet/shotgun/tx15_flechette/spread
- name = "additional flechette"
-
-/datum/ammo/bullet/shotgun/tx15_slug
- name = "shotgun slug"
- handful_icon_state = "shotgun slug"
- hud_state = "shotgun_slug"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- shell_speed = 3
- max_range = 15
- damage = 60
- penetration = 30
- sundering = 3.5
-
-/datum/ammo/bullet/shotgun/tx15_slug/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, slowdown = 2, knockback = 1)
-
-/datum/ammo/bullet/shotgun/mbx900_buckshot
- name = "light shotgun buckshot shell" // If .410 is the smallest shotgun shell, then...
- handful_icon_state = "light shotgun buckshot shell"
- icon_state = "buckshot"
- hud_state = "shotgun_buckshot"
- bonus_projectiles_type = /datum/ammo/bullet/shotgun/mbx900_buckshot/spread
- bonus_projectiles_amount = 2
- bonus_projectiles_scatter = 10
- accuracy_var_low = 10
- accuracy_var_high = 10
- max_range = 10
- damage = 50
- damage_falloff = 1
-
-/datum/ammo/bullet/shotgun/mbx900_buckshot/spread
- name = "additional buckshot"
- damage = 40
-
-/datum/ammo/bullet/shotgun/mbx900_sabot
- name = "light shotgun sabot shell"
- handful_icon_state = "light shotgun sabot shell"
- icon_state = "shotgun_slug"
- hud_state = "shotgun_sabot"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- shell_speed = 5
- max_range = 30
- damage = 50
- penetration = 40
- sundering = 3
-
-/datum/ammo/bullet/shotgun/mbx900_tracker
- name = "light shotgun tracker round"
- handful_icon_state = "light shotgun tracker round"
- icon_state = "shotgun_slug"
- hud_state = "shotgun_tracker"
- shell_speed = 4
- max_range = 30
- damage = 5
- penetration = 100
-
-/datum/ammo/bullet/shotgun/mbx900_tracker/on_hit_mob(mob/living/victim, obj/projectile/proj)
- victim.AddComponent(/datum/component/dripping, DRIP_ON_TIME, 40 SECONDS, 2 SECONDS)
-
-/datum/ammo/bullet/shotgun/tracker
- name = "shotgun tracker shell"
- handful_icon_state = "shotgun tracker shell"
- icon_state = "shotgun_slug"
- hud_state = "shotgun_tracker"
- shell_speed = 4
- max_range = 30
- damage = 5
- penetration = 100
-
-/datum/ammo/bullet/shotgun/tracker/on_hit_mob(mob/living/victim, obj/projectile/proj)
- victim.AddComponent(/datum/component/dripping, DRIP_ON_TIME, 40 SECONDS, 2 SECONDS)
-
-
-/datum/ammo/bullet/shotgun/mech
- name = "super-heavy shotgun buckshot shell"
- icon_state = "buckshot"
- hud_state = "shotgun_buckshot"
- bonus_projectiles_type = /datum/ammo/bullet/shotgun/mech/spread
- bonus_projectiles_amount = 2
- bonus_projectiles_scatter = 5
- accuracy_var_low = 10
- accuracy_var_high = 10
- max_range = 10
- damage = 100
- damage_falloff = 4
-
-/datum/ammo/bullet/shotgun/mech/spread
- name = "super-heavy additional buckshot"
- icon_state = "buckshot"
- max_range = 10
- damage = 75
- damage_falloff = 4
-
-/datum/ammo/bullet/shotgun/mech/on_hit_mob(mob/M, obj/projectile/proj)
- staggerstun(M, proj, weaken = 2 SECONDS, stagger = 2 SECONDS, knockback = 2, slowdown = 0.5, max_range = 3)
-
-/*
-//================================================
- Sniper Ammo
-//================================================
-*/
-
-/datum/ammo/bullet/sniper
- name = "sniper bullet"
- hud_state = "sniper"
- hud_state_empty = "sniper_empty"
- damage_falloff = 0
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SNIPER|AMMO_SUNDERING
- accurate_range_min = 7
- shell_speed = 4
- accurate_range = 30
- max_range = 40
- damage = 90
- penetration = 50
- sundering = 15
-
-/datum/ammo/bullet/sniper/incendiary
- name = "incendiary sniper bullet"
- hud_state = "sniper_fire"
- accuracy = 0
- damage_type = BURN
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY|AMMO_SNIPER|AMMO_SUNDERING
- accuracy_var_high = 7
- max_range = 20
- damage = 70
- penetration = 30
- sundering = 5
-
-/datum/ammo/bullet/sniper/flak
- name = "flak sniper bullet"
- hud_state = "sniper_flak"
- damage = 90
- penetration = 0
- sundering = 15
- airburst_multiplier = 0.5
-
-/datum/ammo/bullet/sniper/flak/on_hit_mob(mob/victim, obj/projectile/proj)
- staggerstun(victim, proj, max_range = 30, slowdown = 2)
- airburst(victim, proj)
-
-/datum/ammo/bullet/sniper/svd
- name = "crude sniper bullet"
- handful_icon_state = "crude sniper bullet"
- hud_state = "sniper_crude"
- handful_amount = 5
- damage = 75
- penetration = 35
- sundering = 15
-
-/datum/ammo/bullet/sniper/martini
- name = "crude heavy sniper bullet"
- handful_icon_state = "crude heavy sniper bullet"
- hud_state = "sniper_crude"
- handful_amount = 5
- flags_ammo_behavior = AMMO_BALLISTIC
- damage = 120
- penetration = 40
- accurate_range_min = 0
- ///shatter effection duration when hitting mobs
- var/shatter_duration = 10 SECONDS
-
-/datum/ammo/bullet/sniper/martini/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, weaken = 0.5 SECONDS, stagger = 1 SECONDS, knockback = 2, slowdown = 0.5, max_range = 10)
-
-/datum/ammo/bullet/sniper/elite
- name = "supersonic sniper bullet"
- hud_state = "sniper_supersonic"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- accuracy = 20
- damage = 100
- penetration = 60
- sundering = 50
-
-/datum/ammo/bullet/sniper/pfc
- name = "high caliber rifle bullet"
- hud_state = "sniper_heavy"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_SNIPER
- damage = 80
- penetration = 30
- sundering = 7.5
- damage_falloff = 0.25
-
-/datum/ammo/bullet/sniper/pfc/flak
- name = "high caliber flak rifle bullet"
- hud_state = "sniper_heavy_flak"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_SNIPER
- damage = 40
- penetration = 10
- sundering = 10
- damage_falloff = 0.25
-
-/datum/ammo/bullet/sniper/pfc/flak/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, knockback = 4, slowdown = 1.5, stagger = 2 SECONDS, max_range = 17)
-
-
-/datum/ammo/bullet/sniper/auto
- name = "high caliber rifle bullet"
- hud_state = "sniper_auto"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_SNIPER
- damage = 50
- penetration = 30
- sundering = 2
- damage_falloff = 0.25
-
-/datum/ammo/bullet/sniper/clf_heavyrifle
- name = "high velocity incendiary sniper bullet"
- handful_icon_state = "ptrs"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY|AMMO_SNIPER|AMMO_SUNDERING
- hud_state = "sniper_fire"
- accurate_range_min = 4
- shell_speed = 5
- damage = 120
- penetration = 60
- sundering = 20
-
-/datum/ammo/bullet/sniper/mech
- name = "light anti-tank bullet"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_SNIPER|AMMO_IFF
- damage = 100
- penetration = 35
- sundering = 0
- damage_falloff = 0.3
-
-/*
-//================================================
- Special Ammo
-//================================================
-*/
-
-/datum/ammo/bullet/smartmachinegun
- name = "smartmachinegun bullet"
- bullet_color = COLOR_SOFT_RED //Red bullets to indicate friendly fire restriction
- hud_state = "smartgun"
- hud_state_empty = "smartgun_empty"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- accurate_range = 12
- damage = 20
- penetration = 15
- sundering = 2
-
-/datum/ammo/bullet/smart_minigun
- name = "smartminigun bullet"
- bullet_color = COLOR_SOFT_RED //Red bullets to indicate friendly fire restriction
- hud_state = "smartgun_minigun"
- hud_state_empty = "smartgun_empty"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- accurate_range = 12
- damage = 10
- penetration = 25
- sundering = 1
- damage_falloff = 0.1
-
-/datum/ammo/bullet/smarttargetrifle
- name = "smart marksman bullet"
- bullet_color = COLOR_SOFT_RED //Red bullets to indicate friendly fire restriction
- hud_state = "smartgun"
- hud_state_empty = "smartgun_empty"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- damage = 40
- max_range = 40
- penetration = 30
- sundering = 3
- shell_speed = 4
- damage_falloff = 0.5
- accurate_range = 25
- accurate_range_min = 3
-
-/datum/ammo/bullet/cupola
- name = "cupola bullet"
- bullet_color = COLOR_SOFT_RED //Red bullets to indicate friendly fire restriction
- hud_state = "smartgun"
- hud_state_empty = "smartgun_empty"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_IFF
- accurate_range = 12
- damage = 30
- penetration = 10
- sundering = 1
-
-/datum/ammo/bullet/spottingrifle
- name = "smart spotting bullet"
- bullet_color = COLOR_SOFT_RED //Red bullets to indicate friendly fire restriction
- hud_state = "spotrifle"
- hud_state_empty = "smartgun_empty"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- damage = 50
- penetration = 25
- sundering = 5
- shell_speed = 4
- accurate_range = 12
- max_range = 12
-
-/datum/ammo/bullet/spottingrifle/highimpact
- name = "smart high-impact spotting bullet"
- hud_state = "spotrifle_impact"
- damage = 10
- sundering = 0.5
-
-/datum/ammo/bullet/spottingrifle/highimpact/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, stagger = 1 SECONDS, slowdown = 1, max_range = 12)
-
-/datum/ammo/bullet/spottingrifle/heavyrubber
- name = "smart heavy-rubber spotting bullet"
- hud_state = "spotrifle_rubber"
- damage = 10
- sundering = 0.5
-
-/datum/ammo/bullet/spottingrifle/heavyrubber/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, slowdown = 3, max_range = 12)
-
-/datum/ammo/bullet/spottingrifle/plasmaloss
- name = "smart tanglefoot spotting bullet"
- hud_state = "spotrifle_plasmaloss"
- damage = 10
- sundering = 0.5
- var/datum/effect_system/smoke_spread/smoke_system
-
-/datum/ammo/bullet/spottingrifle/plasmaloss/on_hit_mob(mob/living/victim, obj/projectile/proj)
- if(isxeno(victim))
- var/mob/living/carbon/xenomorph/X = victim
- X.use_plasma(20 + 0.2 * X.xeno_caste.plasma_max * X.xeno_caste.plasma_regen_limit) // This is draining 20%+20 flat per hit.
- var/datum/effect_system/smoke_spread/plasmaloss/S = new
- S.set_up(0, victim, 3)
- S.start()
-
-/datum/ammo/bullet/spottingrifle/plasmaloss/on_hit_obj(obj/O, obj/projectile/P)
- var/turf/T = get_turf(O)
- drop_tg_smoke(T.density ? P.loc : T)
-
-/datum/ammo/bullet/spottingrifle/plasmaloss/on_hit_turf(turf/T, obj/projectile/P)
- drop_tg_smoke(T.density ? P.loc : T)
-
-/datum/ammo/bullet/spottingrifle/plasmaloss/do_at_max_range(turf/T, obj/projectile/P)
- drop_tg_smoke(T.density ? P.loc : T)
-
-/datum/ammo/bullet/spottingrifle/plasmaloss/set_smoke()
- smoke_system = new /datum/effect_system/smoke_spread/plasmaloss()
-
-/datum/ammo/bullet/spottingrifle/plasmaloss/proc/drop_tg_smoke(turf/T)
- if(T.density)
- return
-
- set_smoke()
- smoke_system.set_up(0, T, 3)
- smoke_system.start()
- smoke_system = null
-
-/datum/ammo/bullet/spottingrifle/tungsten
- name = "smart tungsten spotting bullet"
- hud_state = "spotrifle_tungsten"
- damage = 10
- sundering = 0.5
-
-/datum/ammo/bullet/spottingrifle/tungsten/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, weaken = 2 SECONDS, stagger = 0.5 SECONDS, knockback = 1, max_range = 12)
-
-/datum/ammo/bullet/spottingrifle/flak
- name = "smart flak spotting bullet"
- hud_state = "spotrifle_flak"
- damage = 60
- sundering = 0.5
- airburst_multiplier = 0.5
-
-/datum/ammo/bullet/spottingrifle/flak/on_hit_mob(mob/victim, obj/projectile/proj)
- airburst(victim, proj)
-
-/datum/ammo/bullet/spottingrifle/incendiary
- name = "smart incendiary spotting bullet"
- hud_state = "spotrifle_incend"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY
- damage_type = BURN
- damage = 10
- sundering = 0.5
-
-/datum/ammo/bullet/turret
- name = "autocannon bullet"
- bullet_color = COLOR_SOFT_RED
- hud_state = "rifle"
- hud_state_empty = "rifle_empty"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_SENTRY
- accurate_range = 10
- damage = 25
- penetration = 20
- damage_falloff = 0.25
-
-/datum/ammo/bullet/turret/dumb
- icon_state = "bullet"
-
-/datum/ammo/bullet/turret/gauss
- name = "heavy gauss turret slug"
- hud_state = "rifle_heavy"
- damage = 60
-
-/datum/ammo/bullet/turret/mini
- name = "small caliber autocannon bullet"
- damage = 20
- penetration = 20
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SENTRY
-
-
-/datum/ammo/bullet/machinegun //Adding this for the MG Nests (~Art)
- name = "machinegun bullet"
- icon_state = "bullet" // Keeping it bog standard with the turret but allows it to be changed.
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- hud_state = "minigun"
- hud_state_empty = "smartgun_empty"
- accurate_range = 12
- damage = 40 //Reduced damage due to vastly increased mobility
- penetration = 40 //Reduced penetration due to vastly increased mobility
- accuracy = 5
- barricade_clear_distance = 2
- sundering = 5
-
-/datum/ammo/bullet/minigun
- name = "minigun bullet"
- hud_state = "minigun"
- hud_state_empty = "smartgun_empty"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- accuracy_var_low = 3
- accuracy_var_high = 3
- accurate_range = 5
- damage = 25
- penetration = 15
- shrapnel_chance = 25
- sundering = 2.5
-
-/datum/ammo/bullet/minigun/mech
- name = "vulcan bullet"
- damage = 30
- penetration = 10
- sundering = 0.5
-
-/datum/ammo/bullet/minigun/ltaap
- name = "chaingun bullet"
- damage = 30
- penetration = 10
- sundering = 0
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_IFF
- damage_falloff = 2
- accuracy = 80
-
-/datum/ammo/bullet/auto_cannon
- name = "autocannon high-velocity bullet"
- hud_state = "minigun"
- hud_state_empty = "smartgun_empty"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_TURF|AMMO_PASS_THROUGH_MOVABLE
- accurate_range_min = 6
- accuracy_var_low = 3
- accuracy_var_high = 3
- damage = 30
- penetration = 50
- sundering = 1
- max_range = 35
- ///Bonus flat damage to walls, balanced around resin walls.
- var/autocannon_wall_bonus = 20
-
-/datum/ammo/bullet/auto_cannon/on_hit_turf(turf/T, obj/projectile/P)
- P.proj_max_range -= 20
-
- if(istype(T, /turf/closed/wall))
- var/turf/closed/wall/wall_victim = T
- wall_victim.take_damage(autocannon_wall_bonus, P.damtype, P.armor_type)
-
-/datum/ammo/bullet/auto_cannon/on_hit_mob(mob/M, obj/projectile/P)
- P.proj_max_range -= 5
- staggerstun(M, P, max_range = 20, slowdown = 1)
-
-/datum/ammo/bullet/auto_cannon/on_hit_obj(obj/O, obj/projectile/P)
- P.proj_max_range -= 5
-
-/datum/ammo/bullet/auto_cannon/flak
- name = "autocannon smart-detonating bullet"
- hud_state = "sniper_flak"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_EXPLOSIVE
- damage = 50
- penetration = 30
- sundering = 5
- max_range = 30
- airburst_multiplier = 1
- autocannon_wall_bonus = 5
-
-/datum/ammo/bullet/auto_cannon/flak/on_hit_mob(mob/victim, obj/projectile/proj)
- airburst(victim, proj)
-
-/datum/ammo/bullet/auto_cannon/do_at_max_range(turf/T, obj/projectile/proj)
- airburst(T, proj)
-
-/datum/ammo/bullet/railgun
- name = "armor piercing railgun slug"
- hud_state = "railgun_ap"
- icon_state = "blue_bullet"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_TURF|AMMO_PASS_THROUGH_MOVABLE
- shell_speed = 4
- max_range = 14
- damage = 150
- penetration = 100
- sundering = 20
- bullet_color = COLOR_PULSE_BLUE
- on_pierce_multiplier = 0.85
-
-/datum/ammo/bullet/railgun/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, weaken = 2 SECONDS, stagger = 4 SECONDS, slowdown = 2, knockback = 2)
-
-/datum/ammo/bullet/railgun/hvap
- name = "high velocity railgun slug"
- hud_state = "railgun_hvap"
- shell_speed = 5
- max_range = 21
- damage = 100
- penetration = 30
- sundering = 50
-
-/datum/ammo/bullet/railgun/hvap/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, stagger = 2 SECONDS, knockback = 3)
-
-/datum/ammo/bullet/railgun/smart
- name = "smart armor piercing railgun slug"
- hud_state = "railgun_smart"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_TURF|AMMO_PASS_THROUGH_MOVABLE|AMMO_IFF
- damage = 100
- penetration = 20
- sundering = 20
-
-/datum/ammo/bullet/railgun/smart/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, stagger = 3 SECONDS, slowdown = 3)
-
-/datum/ammo/bullet/apfsds
- name = "\improper APFSDS round"
- hud_state = "alloy_spike"
- icon_state = "blue_bullet"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOVABLE|AMMO_UNWIELDY
- shell_speed = 4
- max_range = 14
- damage = 150
- penetration = 100
- sundering = 0
- bullet_color = COLOR_PULSE_BLUE
- on_pierce_multiplier = 0.85
-
-/datum/ammo/tx54
- name = "20mm airburst grenade"
- icon_state = "20mm_flight"
- hud_state = "grenade_airburst"
- hud_state_empty = "grenade_empty"
- handful_icon_state = "20mm_airburst"
- handful_amount = 3
- ping = null //no bounce off.
- sound_bounce = "rocket_bounce"
- flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_SUNDERING
- armor_type = BOMB
- damage_falloff = 0.5
- shell_speed = 2
- accurate_range = 12
- max_range = 15
- damage = 12 //impact damage from a grenade to the dome
- penetration = 0
- sundering = 0
- shrapnel_chance = 0
- bonus_projectiles_type = /datum/ammo/bullet/tx54_spread
- bonus_projectiles_scatter = 10
- ///How many
- var/bonus_projectile_quantity = 7
-
- handful_greyscale_config = /datum/greyscale_config/ammo
- handful_greyscale_colors = COLOR_AMMO_AIRBURST
-
- projectile_greyscale_config = /datum/greyscale_config/projectile
- projectile_greyscale_colors = COLOR_AMMO_AIRBURST
-
-/datum/ammo/tx54/on_hit_mob(mob/M, obj/projectile/proj)
- staggerstun(M, proj, slowdown = 0.5, knockback = 1)
- playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
- fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 4, 3, Get_Angle(proj.firer, M) )
-
-/datum/ammo/tx54/on_hit_obj(obj/O, obj/projectile/proj)
- playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
- fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 4, 3, Get_Angle(proj.firer, O) )
-
-/datum/ammo/tx54/on_hit_turf(turf/T, obj/projectile/proj)
- playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
- fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 4, 3, Get_Angle(proj.firer, T) )
-
-/datum/ammo/tx54/do_at_max_range(turf/T, obj/projectile/proj)
- playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
- fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 4, 3, Get_Angle(proj.firer, get_turf(proj)) )
-
-/datum/ammo/tx54/incendiary
- name = "20mm incendiary grenade"
- hud_state = "grenade_fire"
- bonus_projectiles_type = /datum/ammo/bullet/tx54_spread/incendiary
- bullet_color = LIGHT_COLOR_FIRE
- handful_greyscale_colors = COLOR_AMMO_INCENDIARY
- projectile_greyscale_colors = COLOR_AMMO_INCENDIARY
-
-/datum/ammo/tx54/smoke
- name = "20mm tactical smoke grenade"
- hud_state = "grenade_hide"
- bonus_projectiles_type = /datum/ammo/bullet/tx54_spread/smoke
- bonus_projectiles_scatter = 24
- bonus_projectile_quantity = 5
- handful_greyscale_colors = COLOR_AMMO_TACTICAL_SMOKE
- projectile_greyscale_colors = COLOR_AMMO_TACTICAL_SMOKE
-
-/datum/ammo/tx54/smoke/dense
- name = "20mm smoke grenade"
- hud_state = "grenade_smoke"
- bonus_projectiles_type = /datum/ammo/bullet/tx54_spread/smoke/dense
- handful_greyscale_colors = COLOR_AMMO_SMOKE
- projectile_greyscale_colors = COLOR_AMMO_SMOKE
-
-/datum/ammo/tx54/smoke/tangle
- name = "20mm tanglefoot grenade"
- hud_state = "grenade_drain"
- bonus_projectiles_type = /datum/ammo/bullet/tx54_spread/smoke/tangle
- handful_greyscale_colors = COLOR_AMMO_TANGLEFOOT
- projectile_greyscale_colors = COLOR_AMMO_TANGLEFOOT
-
-/datum/ammo/tx54/razor
- name = "20mm razorburn grenade"
- hud_state = "grenade_razor"
- bonus_projectiles_type = /datum/ammo/bullet/tx54_spread/razor
- bonus_projectiles_scatter = 50
- bonus_projectile_quantity = 3
- handful_greyscale_colors = COLOR_AMMO_RAZORBURN
- projectile_greyscale_colors = COLOR_AMMO_RAZORBURN
-
-/datum/ammo/tx54/he
- name = "20mm HE grenade"
- hud_state = "grenade_he"
- bonus_projectiles_type = null
- max_range = 12
- handful_greyscale_colors = COLOR_AMMO_HIGH_EXPLOSIVE
- projectile_greyscale_colors = COLOR_AMMO_HIGH_EXPLOSIVE
-
-/datum/ammo/tx54/he/drop_nade(turf/T)
- cell_explosion(T, 45, 25)
-
-/datum/ammo/tx54/he/on_hit_mob(mob/M, obj/projectile/P)
- drop_nade(get_turf(M))
-
-/datum/ammo/tx54/he/on_hit_obj(obj/O, obj/projectile/P)
- drop_nade(get_turf(O))
-
-/datum/ammo/tx54/he/on_hit_turf(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-/datum/ammo/tx54/he/do_at_max_range(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-//The secondary projectiles
-/datum/ammo/bullet/tx54_spread
- name = "Shrapnel"
- icon_state = "flechette"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB
- accuracy_var_low = 5
- accuracy_var_high = 5
- max_range = 4
- damage = 20
- penetration = 20
- sundering = 3
- damage_falloff = 0
-
-/datum/ammo/bullet/tx54_spread/on_hit_mob(mob/M, obj/projectile/proj)
- staggerstun(M, proj, max_range = 3, stagger = 0.6 SECONDS, slowdown = 0.3)
-
-/datum/ammo/bullet/tx54_spread/incendiary
- name = "incendiary flechette"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB|AMMO_INCENDIARY|AMMO_LEAVE_TURF
- damage = 15
- penetration = 10
- sundering = 1.5
-
-/datum/ammo/bullet/tx54_spread/incendiary/on_hit_mob(mob/M, obj/projectile/proj)
- return
-
-/datum/ammo/bullet/tx54_spread/incendiary/drop_flame(turf/T)
- if(!istype(T))
- return
- T.ignite(5, 10)
-
-/datum/ammo/bullet/tx54_spread/incendiary/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
- drop_flame(T)
-
-/datum/ammo/bullet/tx54_spread/smoke
- name = "chemical bomblet"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_PASS_THROUGH_MOB|AMMO_LEAVE_TURF
- max_range = 3
- damage = 5
- penetration = 0
- sundering = 0
- ///The smoke type loaded in this ammo
- var/datum/effect_system/smoke_spread/trail_spread_system = /datum/effect_system/smoke_spread/tactical
-
-/datum/ammo/bullet/tx54_spread/smoke/New()
- . = ..()
-
- trail_spread_system = new trail_spread_system(only_once = FALSE)
-
-/datum/ammo/bullet/tx54_spread/smoke/Destroy()
- if(trail_spread_system)
- QDEL_NULL(trail_spread_system)
- return ..()
-
-/datum/ammo/bullet/tx54_spread/smoke/on_hit_mob(mob/M, obj/projectile/proj)
- return
-
-/datum/ammo/bullet/tx54_spread/smoke/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
- trail_spread_system.set_up(0, T)
- trail_spread_system.start()
-
-/datum/ammo/bullet/tx54_spread/smoke/dense
- trail_spread_system = /datum/effect_system/smoke_spread/bad
-
-/datum/ammo/bullet/tx54_spread/smoke/tangle
- trail_spread_system = /datum/effect_system/smoke_spread/plasmaloss
-
-/datum/ammo/bullet/tx54_spread/razor
- name = "chemical bomblet"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_PASS_THROUGH_MOB|AMMO_LEAVE_TURF
- max_range = 4
- damage = 5
- penetration = 0
- sundering = 0
- ///The foam type loaded in this ammo
- var/datum/effect_system/foam_spread/chemical_payload
- ///The reagent content of the projectile
- var/datum/reagents/reagent_list
-
-/datum/ammo/bullet/tx54_spread/razor/New()
- . = ..()
-
- chemical_payload = new
- reagent_list = new
- reagent_list.add_reagent(/datum/reagent/foaming_agent = 1)
- reagent_list.add_reagent(/datum/reagent/toxin/nanites = 7)
-
-/datum/ammo/bullet/tx54_spread/razor/Destroy()
- if(chemical_payload)
- QDEL_NULL(chemical_payload)
- return ..()
-
-/datum/ammo/bullet/tx54_spread/razor/on_hit_mob(mob/M, obj/projectile/proj)
- return
-
-/datum/ammo/bullet/tx54_spread/razor/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
- chemical_payload.set_up(0, T, reagent_list, RAZOR_FOAM)
- chemical_payload.start()
-
-/datum/ammo/tx54/mech
- name = "30mm fragmentation grenade"
- bonus_projectiles_type = /datum/ammo/bullet/tx54_spread/mech
- damage = 15
- penetration = 10
- projectile_greyscale_colors = "#4f0303"
-
-/datum/ammo/bullet/tx54_spread/mech
- damage = 15
- penetration = 10
- sundering = 0.5
-
-/datum/ammo/bullet/tx54_spread/mech/on_hit_mob(mob/M, obj/projectile/proj)
- staggerstun(M, proj, max_range = 3, slowdown = 0.2)
-
-//10-gauge Micro rail shells - aka micronades
-/datum/ammo/bullet/micro_rail
- hud_state_empty = "grenade_empty_flash"
- handful_icon_state = "micro_grenade_airburst"
- flags_ammo_behavior = AMMO_BALLISTIC
- shell_speed = 2
- handful_amount = 3
- max_range = 3 //failure to detonate if the target is too close
- damage = 15
- bonus_projectiles_scatter = 12
- ///How many bonus projectiles to generate. New var so it doesn't trigger on firing
- var/bonus_projectile_quantity = 5
- ///Max range for the bonus projectiles
- var/bonus_projectile_range = 7
- ///projectile speed for the bonus projectiles
- var/bonus_projectile_speed = 3
-
-/datum/ammo/bullet/micro_rail/do_at_max_range(turf/T, obj/projectile/proj)
- playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
- var/datum/effect_system/smoke_spread/smoke = new
- smoke.set_up(0, get_turf(proj), 1)
- smoke.start()
- fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, bonus_projectile_range, bonus_projectile_speed, Get_Angle(proj.firer, get_turf(proj)) )
-
-//piercing scatter shot
-/datum/ammo/bullet/micro_rail/airburst
- name = "micro grenade"
- handful_icon_state = "micro_grenade_airburst"
- hud_state = "grenade_airburst"
- bonus_projectiles_type = /datum/ammo/bullet/micro_rail_spread
-
-//incendiary piercing scatter shot
-/datum/ammo/bullet/micro_rail/dragonbreath
- name = "micro grenade"
- handful_icon_state = "micro_grenade_incendiary"
- hud_state = "grenade_fire"
- bonus_projectiles_type = /datum/ammo/bullet/micro_rail_spread/incendiary
- bonus_projectile_range = 6
-
-//cluster grenade. Bomblets explode in a rough cone pattern
-/datum/ammo/bullet/micro_rail/cluster
- name = "micro grenade"
- handful_icon_state = "micro_grenade_cluster"
- hud_state = "grenade_he"
- bonus_projectiles_type = /datum/ammo/micro_rail_cluster
- bonus_projectile_quantity = 7
- bonus_projectile_range = 6
- bonus_projectile_speed = 2
-
-//creates a literal smokescreen
-/datum/ammo/bullet/micro_rail/smoke_burst
- name = "micro grenade"
- handful_icon_state = "micro_grenade_smoke"
- hud_state = "grenade_smoke"
- bonus_projectiles_type = /datum/ammo/smoke_burst
- bonus_projectiles_scatter = 20
- bonus_projectile_range = 6
- bonus_projectile_speed = 2
-
-//submunitions for micro grenades
-/datum/ammo/bullet/micro_rail_spread
- name = "Shrapnel"
- icon_state = "flechette"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB
- accuracy_var_low = 5
- accuracy_var_high = 5
- max_range = 7
- damage = 20
- penetration = 20
- sundering = 3
- damage_falloff = 1
-
-/datum/ammo/bullet/micro_rail_spread/on_hit_mob(mob/M, obj/projectile/proj)
- staggerstun(M, proj, stagger = 1 SECONDS, slowdown = 0.5)
-
-/datum/ammo/bullet/micro_rail_spread/incendiary
- name = "incendiary flechette"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB|AMMO_INCENDIARY|AMMO_LEAVE_TURF
- damage = 15
- penetration = 5
- sundering = 1.5
- max_range = 6
-
-/datum/ammo/bullet/micro_rail_spread/incendiary/on_hit_mob(mob/M, obj/projectile/proj)
- staggerstun(M, proj, stagger = 0.4 SECONDS, slowdown = 0.2)
-
-/datum/ammo/bullet/micro_rail_spread/incendiary/drop_flame(turf/T)
- if(!istype(T))
- return
- T.ignite(5, 10)
-
-/datum/ammo/bullet/micro_rail_spread/incendiary/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
- if(prob(40))
- drop_flame(T)
-
-/datum/ammo/micro_rail_cluster
- name = "bomblet"
- icon_state = "bullet"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_LEAVE_TURF
- sound_hit = "ballistic_hit"
- sound_armor = "ballistic_armor"
- sound_miss = "ballistic_miss"
- sound_bounce = "ballistic_bounce"
- shell_speed = 2
- damage = 5
- accuracy = -60 //stop you from just emptying all the bomblets into one guys face for big damage
- shrapnel_chance = 0
- max_range = 6
- bullet_color = COLOR_VERY_SOFT_YELLOW
- ///the smoke effect at the point of detonation
- var/datum/effect_system/smoke_spread/smoketype = /datum/effect_system/smoke_spread
- ///Total damage applied to victims by the exploding bomblet
- var/explosion_damage = 20
- ///Amount of stagger applied by the exploding bomblet
- var/stagger_amount = 2 SECONDS
- ///Amount of slowdown applied by the exploding bomblet
- var/slow_amount = 1
- ///range of bomblet explosion
- var/explosion_range = 2
-
-///handles the actual bomblet detonation
-/datum/ammo/micro_rail_cluster/proc/detonate(turf/T, obj/projectile/P)
- playsound(T, sound(get_sfx("explosion_micro")), 30, falloff = 5)
- var/datum/effect_system/smoke_spread/smoke = new smoketype()
- smoke.set_up(0, T, rand(1,2))
- smoke.start()
-
- var/list/turf/target_turfs = generate_true_cone(T, explosion_range, -1, 359, 0, air_pass = TRUE)
- for(var/turf/target_turf AS in target_turfs)
- for(var/target in target_turf)
- if(isliving(target))
- var/mob/living/living_target = target
- living_target.visible_message(span_danger("[living_target] is hit by the bomblet blast!"),
- isxeno(living_target) ? span_xenodanger("We are hit by the bomblet blast!") : span_highdanger("you are hit by the bomblet blast!"))
- living_target.apply_damages(explosion_damage * 0.5, explosion_damage * 0.5, 0, 0, 0, blocked = BOMB, updating_health = TRUE)
- staggerstun(living_target, P, stagger = stagger_amount, slowdown = slow_amount)
- else if(isobj(target))
- var/obj/obj_victim = target
- obj_victim.take_damage(explosion_damage, BRUTE, BOMB)
-
-/datum/ammo/micro_rail_cluster/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
- ///chance to detonate early, scales with distance and capped, to avoid lots of immediate detonations, and nothing reach max range respectively.
- var/detonate_probability = min(proj.distance_travelled * 4, 16)
- if(prob(detonate_probability))
- proj.proj_max_range = proj.distance_travelled
-
-/datum/ammo/micro_rail_cluster/on_hit_mob(mob/M, obj/projectile/P)
- detonate(get_turf(P), P)
-
-/datum/ammo/micro_rail_cluster/on_hit_obj(obj/O, obj/projectile/P)
- detonate(get_turf(P), P)
-
-/datum/ammo/micro_rail_cluster/on_hit_turf(turf/T, obj/projectile/P)
- detonate(T.density ? P.loc : T, P)
-
-/datum/ammo/micro_rail_cluster/do_at_max_range(turf/T, obj/projectile/P)
- detonate(T.density ? P.loc : T, P)
-
-/datum/ammo/smoke_burst
- name = "micro smoke canister"
- icon_state = "bullet"
- flags_ammo_behavior = AMMO_BALLISTIC
- sound_hit = "ballistic_hit"
- sound_armor = "ballistic_armor"
- sound_miss = "ballistic_miss"
- sound_bounce = "ballistic_bounce"
- shell_speed = 2
- damage = 5
- shrapnel_chance = 0
- max_range = 6
- bullet_color = COLOR_VERY_SOFT_YELLOW
- /// smoke type created when the projectile detonates
- var/datum/effect_system/smoke_spread/smoketype = /datum/effect_system/smoke_spread/bad
- ///radius this smoke will encompass
- var/smokeradius = 1
-
-/datum/ammo/smoke_burst/drop_nade(turf/T)
- var/datum/effect_system/smoke_spread/smoke = new smoketype()
- playsound(T, 'sound/effects/smoke.ogg', 25, 1, 4)
- smoke.set_up(smokeradius, T, rand(5,9))
- smoke.start()
-
-/datum/ammo/smoke_burst/on_hit_mob(mob/M, obj/projectile/P)
- drop_nade(get_turf(P))
-
-/datum/ammo/smoke_burst/on_hit_obj(obj/O, obj/projectile/P)
- drop_nade(get_turf(P))
-
-/datum/ammo/smoke_burst/on_hit_turf(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-/datum/ammo/smoke_burst/do_at_max_range(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-
-/datum/ammo/ags_shrapnel
- name = "fragmentation grenade"
- icon_state = "grenade_projectile"
- hud_state = "grenade_frag"
- hud_state_empty = "grenade_empty"
- handful_icon_state = "40mm_grenade"
- handful_amount = 1
- ping = null //no bounce off.
- sound_bounce = "rocket_bounce"
- flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_IFF
- armor_type = BOMB
- damage_falloff = 0.5
- shell_speed = 2
- accurate_range = 12
- max_range = 21
- damage = 15
- shrapnel_chance = 0
- bonus_projectiles_type = /datum/ammo/bullet/ags_spread
- bonus_projectiles_scatter = 20
- var/bonus_projectile_quantity = 15
-
-
-/datum/ammo/ags_shrapnel/on_hit_mob(mob/M, obj/projectile/proj)
- playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
- fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 2, 3, Get_Angle(proj.firer, M) )
-
-/datum/ammo/ags_shrapnel/on_hit_obj(obj/O, obj/projectile/proj)
- playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
- fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 2, 3, Get_Angle(proj.firer, O) )
-
-/datum/ammo/ags_shrapnel/on_hit_turf(turf/T, obj/projectile/proj)
- playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
- fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 2, 3, Get_Angle(proj.firer, T) )
-
-/datum/ammo/ags_shrapnel/do_at_max_range(turf/T, obj/projectile/proj)
- playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
- fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 2, 3, Get_Angle(proj.firer, get_turf(proj)) )
-
-/datum/ammo/ags_shrapnel/incendiary
- name = "white phosphorous grenade"
- bonus_projectiles_type = /datum/ammo/bullet/ags_spread/incendiary
-
-/datum/ammo/bullet/ags_spread
- name = "Shrapnel"
- icon_state = "flechette"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB
- accuracy_var_low = 15
- accuracy_var_high = 5
- max_range = 6
- damage = 30
- penetration = 20
- sundering = 3
- damage_falloff = 0
-
-/datum/ammo/bullet/ags_spread/incendiary
- name = "White phosphorous shrapnel"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_INCENDIARY
- damage = 20
- penetration = 10
- sundering = 1.5
- damage_falloff = 0
-
-/datum/ammo/bullet/ags_spread/incendiary/on_hit_mob(mob/M, obj/projectile/P)
- drop_flame(get_turf(M))
-
-/datum/ammo/bullet/ags_spread/incendiary/on_hit_obj(obj/O, obj/projectile/P)
- drop_flame(get_turf(O))
-
-/datum/ammo/bullet/ags_spread/incendiary/on_hit_turf(turf/T, obj/projectile/P)
- drop_flame(get_turf(T))
-
-/datum/ammo/bullet/ags_spread/incendiary/do_at_max_range(turf/T, obj/projectile/P)
- drop_flame(get_turf(T))
-
-/datum/ammo/bullet/ags_spread/incendiary/drop_flame(turf/T)
- if(!istype(T))
- return
- T.ignite(5, 10)
-
-
-/datum/ammo/bullet/coilgun
- name = "high-velocity tungsten slug"
- hud_state = "railgun_ap"
- icon_state = "blue_bullet"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOVABLE
- shell_speed = 5
- max_range = 31
- damage = 70
- penetration = 35
- sundering = 5
- bullet_color = COLOR_PULSE_BLUE
- on_pierce_multiplier = 0.85
-
-/datum/ammo/bullet/coilgun/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, weaken = 0.2 SECONDS, slowdown = 1, knockback = 3)
-
-
-/*
-//================================================
- Rocket Ammo
-//================================================
-*/
-
-/datum/ammo/rocket
- name = "high explosive rocket"
- icon_state = "missile"
- hud_state = "rocket_he"
- hud_state_empty = "rocket_empty"
- ping = null //no bounce off.
- sound_bounce = "rocket_bounce"
- flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_SUNDERING
- armor_type = BOMB
- damage_falloff = 0
- shell_speed = 2
- accuracy = 40
- accurate_range = 20
- max_range = 14
- damage = 200
- penetration = 100
- sundering = 100
- bullet_color = LIGHT_COLOR_FIRE
- barricade_clear_distance = 2
-
-/datum/ammo/rocket/drop_nade(turf/T)
- explosion(T, 0, 4, 6, 0, 2)
-
-/datum/ammo/rocket/on_hit_mob(mob/M, obj/projectile/P)
- drop_nade(get_turf(M))
-
-/datum/ammo/rocket/on_hit_obj(obj/O, obj/projectile/P)
- drop_nade(O.density ? P.loc : O.loc)
-
-/datum/ammo/rocket/on_hit_turf(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-/datum/ammo/rocket/do_at_max_range(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-/datum/ammo/rocket/he
- name = "high explosive rocket"
- icon_state = "rocket_he"
- hud_state = "rocket_he"
- accurate_range = 20
- max_range = 14
- damage = 150
- penetration = 100
- sundering = 100
-
-/datum/ammo/rocket/he/drop_nade(turf/T)
- cell_explosion(T, 150, 40)
-
-/datum/ammo/rocket/he/unguided
- damage = 100
- flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING // We want this one to specifically go over onscreen range.
-
-/datum/ammo/rocket/he/unguided/drop_nade(turf/T)
- cell_explosion(T, 200, 50)
-
-/datum/ammo/rocket/ap
- name = "kinetic penetrator"
- icon_state = "rocket_ap"
- hud_state = "rocket_ap"
- damage = 340
- accurate_range = 15
- penetration = 200
- sundering = 0
-
-/datum/ammo/rocket/ap/drop_nade(turf/T)
- explosion(T, flash_range = 1)
-
-/datum/ammo/rocket/ltb
- name = "cannon round"
- icon_state = "ltb"
- flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET
- accurate_range = 15
- max_range = 40
- penetration = 50
- damage = 200
- hud_state = "bigshell_he"
-
-/datum/ammo/rocket/ltb/drop_nade(turf/T)
- cell_explosion(T, 200, 45)
-
-/datum/ammo/rocket/mech
- name = "large high-explosive rocket"
- damage = 75
- penetration = 50
- max_range = 30
-
-/datum/ammo/rocket/mech/drop_nade(turf/T)
- cell_explosion(T, 75, 15)
-
-/datum/ammo/rocket/heavy_isg
- name = "15cm round"
- icon_state = "heavyrr"
- hud_state = "bigshell_he"
- hud_state_empty = "shell_empty"
- flags_ammo_behavior = AMMO_ROCKET|AMMO_EXPLOSIVE
- damage = 50
- penetration = 200
- max_range = 30
- shell_speed = 0.75
- accuracy = 30
- accurate_range = 21
- handful_amount = 1
-
-/datum/ammo/rocket/heavy_isg/drop_nade(turf/T)
- cell_explosion(T, 700, 200) // dodge this
-
-/datum/ammo/rocket/heavy_isg/unguided
- hud_state = "bigshell_he_unguided"
- flags_ammo_behavior = AMMO_ROCKET
-
-/datum/ammo/bullet/heavy_isg_apfds
- name = "15cm APFDS round"
- icon_state = "apfds"
- hud_state = "bigshell_apfds"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_PASS_THROUGH_TURF|AMMO_PASS_THROUGH_MOVABLE
- damage = 200
- penetration = 75
- shell_speed = 7
- accurate_range = 24
- accurate_range_min = 6
- max_range = 35
-
-/datum/ammo/bullet/isg_apfds/on_hit_turf(turf/T, obj/projectile/P)
- P.proj_max_range -= 5
-
-/datum/ammo/bullet/isg_apfds/on_hit_mob(mob/M, obj/projectile/P)
- P.proj_max_range -= 2
- staggerstun(M, P, max_range = 20, slowdown = 0.5)
-
-/datum/ammo/bullet/isg_apfds/on_hit_obj(obj/O, obj/projectile/P)
- P.proj_max_range -= 5
-
-/datum/ammo/rocket/wp
- name = "white phosphorous rocket"
- icon_state = "rocket_wp"
- hud_state = "rocket_fire"
- flags_ammo_behavior = AMMO_ROCKET|AMMO_INCENDIARY|AMMO_EXPLOSIVE|AMMO_SUNDERING
- armor_type = FIRE
- damage_type = BURN
- accuracy_var_low = 7
- accurate_range = 15
- damage = 200
- penetration = 75
- max_range = 20
- sundering = 100
- ///The radius for the non explosion effects
- var/effect_radius = 3
-
-/datum/ammo/rocket/wp/drop_nade(turf/T)
- if(!T || !isturf(T))
- return
- playsound(T, 'sound/weapons/guns/fire/flamethrower2.ogg', 50, 1, 4)
- flame_radius(effect_radius, T, 27, 27, 27, 17)
-
-/datum/ammo/rocket/wp/quad
- name = "thermobaric rocket"
- hud_state = "rocket_thermobaric"
- flags_ammo_behavior = AMMO_ROCKET
- damage = 40
- penetration = 25
- max_range = 30
- sundering = 2
-
- ///The smoke system that the WP gas uses to spread.
- var/datum/effect_system/smoke_spread/smoke_system
-
-/datum/ammo/rocket/wp/quad/set_smoke()
- smoke_system = new /datum/effect_system/smoke_spread/phosphorus()
-
-/datum/ammo/rocket/wp/quad/drop_nade(turf/T)
- set_smoke()
- smoke_system.set_up(effect_radius, T)
- smoke_system.start()
- smoke_system = null
- T.visible_message(span_danger("The rocket explodes into white gas!") )
- playsound(T, 'sound/weapons/guns/fire/flamethrower2.ogg', 50, 1, 4)
- flame_radius(effect_radius, T, 27, 27, 27, 17)
-
-/datum/ammo/rocket/wp/quad/som
- name = "white phosphorous RPG"
- hud_state = "rpg_fire"
- icon_state = "rpg_incendiary"
- flags_ammo_behavior = AMMO_ROCKET
- effect_radius = 5
-
-/datum/ammo/rocket/wp/quad/ds
- name = "super thermobaric rocket"
- hud_state = "rocket_thermobaric"
- flags_ammo_behavior = AMMO_ROCKET
- damage = 200
- penetration = 75
- max_range = 30
- sundering = 100
-
-/datum/ammo/rocket/wp/unguided
- damage = 100
- flags_ammo_behavior = AMMO_ROCKET|AMMO_INCENDIARY|AMMO_SUNDERING
- effect_radius = 5
-
-/datum/ammo/rocket/recoilless
- name = "high explosive shell"
- icon_state = "recoilless_rifle_he"
- hud_state = "shell_he"
- hud_state_empty = "shell_empty"
- flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_SUNDERING
- armor_type = BOMB
- damage_falloff = 0
- shell_speed = 2
- accurate_range = 20
- max_range = 30
- damage = 100
- penetration = 50
- sundering = 50
-
-/datum/ammo/rocket/recoilless/drop_nade(turf/T)
- cell_explosion(T, 150, 75)
-
-/datum/ammo/rocket/recoilless/heat
- name = "HEAT shell"
- icon_state = "recoilless_rifle_heat"
- hud_state = "shell_heat"
- flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING
- damage = 200
- penetration = 100
- sundering = 0
-
-/datum/ammo/rocket/recoilless/heat/drop_nade(turf/T)
- explosion(T, flash_range = 1)
-
-/datum/ammo/rocket/recoilless/heat/mech //for anti mech use in HvH
- name = "HEAM shell"
- accuracy = -10 //Not designed for anti human use
- flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING|AMMO_UNWIELDY
-
-/datum/ammo/rocket/recoilless/heat/mech/on_hit_obj(obj/O, obj/projectile/P)
- drop_nade(get_turf(O))
- if(ismecha(O))
- P.damage *= 3 //this is specifically designed to hurt mechs
-
-/datum/ammo/rocket/recoilless/heat/mech/drop_nade(turf/T)
- cell_explosion(T, 50, 45)
-
-/datum/ammo/rocket/recoilless/light
- name = "light explosive shell"
- icon_state = "recoilless_rifle_le"
- hud_state = "shell_le"
- flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING //We want this to specifically go farther than onscreen range.
- accurate_range = 15
- max_range = 20
- damage = 75
- penetration = 50
- sundering = 25
-
-/datum/ammo/rocket/recoilless/light/drop_nade(turf/T)
- cell_explosion(T, 75, 25)
-
-/datum/ammo/rocket/recoilless/chemical
- name = "low velocity chemical shell"
- icon_state = "recoilless_rifle_smoke"
- hud_state = "shell_le"
- flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING|AMMO_IFF //We want this to specifically go farther than onscreen range and pass through friendlies.
- accurate_range = 21
- max_range = 21
- damage = 10
- penetration = 0
- sundering = 0
- /// Smoke type created when projectile detonates.
- var/datum/effect_system/smoke_spread/smoketype = /datum/effect_system/smoke_spread/bad
- /// Radius this smoke will encompass on detonation.
- var/smokeradius = 7
-
-/datum/ammo/rocket/recoilless/chemical/drop_nade(turf/T)
- var/datum/effect_system/smoke_spread/smoke = new smoketype()
- playsound(T, 'sound/effects/smoke.ogg', 25, 1, 4)
- smoke.set_up(smokeradius, T, rand(5,9))
- smoke.start()
- explosion(T, flash_range = 1)
-
-/datum/ammo/rocket/recoilless/chemical/cloak
- name = "low velocity chemical shell"
- icon_state = "recoilless_rifle_cloak"
- hud_state = "shell_cloak"
- smoketype = /datum/effect_system/smoke_spread/tactical
-
-/datum/ammo/rocket/recoilless/chemical/plasmaloss
- name = "low velocity chemical shell"
- icon_state = "recoilless_rifle_tanglefoot"
- hud_state = "shell_tanglefoot"
- smoketype = /datum/effect_system/smoke_spread/plasmaloss
-
-/datum/ammo/rocket/recoilless/low_impact
- name = "low impact explosive shell"
- icon_state = "recoilless_rifle_le"
- hud_state = "shell_le"
- flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING //We want this to specifically go farther than onscreen range.
- accurate_range = 15
- max_range = 20
- damage = 75
- penetration = 15
- sundering = 25
-
-/datum/ammo/rocket/recoilless/low_impact/drop_nade(turf/T)
- cell_explosion(T, 100, 15)
-
-/datum/ammo/rocket/oneuse
- name = "explosive rocket"
- damage = 100
- penetration = 100
- sundering = 100
- max_range = 30
-
-/datum/ammo/rocket/oneuse/drop_nade(turf/T)
- cell_explosion(T, 115, 45)
-
-/datum/ammo/rocket/som
- name = "high explosive RPG"
- icon_state = "rpg_he"
- hud_state = "rpg_he"
- flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING
- accurate_range = 15
- max_range = 20
- damage = 80
- penetration = 20
- sundering = 20
-
-/datum/ammo/rocket/som/drop_nade(turf/T)
- cell_explosion(T, 175, 35)
-
-/datum/ammo/rocket/som/light
- name = "low impact RPG"
- icon_state = "rpg_le"
- hud_state = "rpg_le"
- flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING
- accurate_range = 15
- damage = 60
- penetration = 10
-
-/datum/ammo/rocket/som/light/drop_nade(turf/T)
- cell_explosion(T, 125, 15)
-
-/datum/ammo/rocket/som/thermobaric
- name = "thermobaric RPG"
- icon_state = "rpg_thermobaric"
- hud_state = "rpg_thermobaric"
- damage = 30
-
-/datum/ammo/rocket/som/thermobaric/drop_nade(turf/T)
- cell_explosion(T, 175, 45)
- flame_radius(4, T)
-
-/datum/ammo/rocket/som/heat //Anti tank, or mech
- name = "HEAT RPG"
- icon_state = "rpg_heat"
- hud_state = "rpg_heat"
- damage = 200
- penetration = 100
- sundering = 0
- accuracy = -10 //Not designed for anti human use
- flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING|AMMO_UNWIELDY
-
-/datum/ammo/rocket/som/heat/on_hit_obj(obj/O, obj/projectile/P)
- drop_nade(get_turf(O))
- if(ismecha(O))
- P.damage *= 3 //this is specifically designed to hurt mechs
-
-/datum/ammo/rocket/som/heat/drop_nade(turf/T)
- cell_explosion(T, 50, 45)
-
-/datum/ammo/rocket/som/rad
- name = "irrad RPG"
- icon_state = "rpg_rad"
- hud_state = "rpg_rad"
- damage = 50
- penetration = 10
- ///Base strength of the rad effects
- var/rad_strength = 25
- ///Range for the maximum rad effects
- var/inner_range = 3
- ///Range for the moderate rad effects
- var/mid_range = 5
- ///Range for the minimal rad effects
- var/outer_range = 8
-
-/datum/ammo/rocket/som/rad/drop_nade(turf/T)
- playsound(T, 'sound/effects/portal_opening.ogg', 50, 1)
- for(var/mob/living/victim in hearers(outer_range, T))
- var/strength
- var/sound_level
- if(get_dist(victim, T) <= inner_range)
- strength = rad_strength
- sound_level = 4
- else if(get_dist(victim, T) <= mid_range)
- strength = rad_strength * 0.7
- sound_level = 3
- else
- strength = rad_strength * 0.3
- sound_level = 2
-
- strength = victim.modify_by_armor(strength, BIO, 25)
- victim.apply_radiation(strength, sound_level)
-
- explosion(T, weak_impact_range = 4)
-
-/datum/ammo/rocket/atgun_shell
- name = "high explosive ballistic cap shell"
- icon_state = "atgun"
- hud_state = "shell_heat"
- hud_state_empty = "shell_empty"
- flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_SUNDERING|AMMO_PASS_THROUGH_TURF
- shell_speed = 2
- damage = 90
- penetration = 30
- sundering = 25
- max_range = 30
- handful_amount = 1
-
-/datum/ammo/rocket/atgun_shell/drop_nade(turf/T)
- cell_explosion(T, 55 , 30)
-
-/datum/ammo/rocket/atgun_shell/on_hit_turf(turf/T, obj/projectile/P) //no explosion every time it hits a turf
- P.proj_max_range -= 10
-
-/datum/ammo/rocket/atgun_shell/apcr
- name = "tungsten penetrator"
- hud_state = "shell_apcr"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_TURF|AMMO_PASS_THROUGH_MOVABLE
- shell_speed = 4
- damage = 200
- penetration = 70
- sundering = 25
-
-/datum/ammo/rocket/atgun_shell/apcr/drop_nade(turf/T)
- explosion(T, flash_range = 1)
-
-/datum/ammo/rocket/atgun_shell/apcr/on_hit_mob(mob/M, obj/projectile/P)
- drop_nade(get_turf(M))
- P.proj_max_range -= 5
- staggerstun(M, P, max_range = 20, stagger = 1 SECONDS, slowdown = 0.5, knockback = 2, hard_size_threshold = 3)
-
-/datum/ammo/rocket/atgun_shell/apcr/on_hit_obj(obj/O, obj/projectile/P)
- P.proj_max_range -= 5
-
-/datum/ammo/rocket/atgun_shell/apcr/on_hit_turf(turf/T, obj/projectile/P)
- P.proj_max_range -= 5
-
-/datum/ammo/rocket/atgun_shell/he
- name = "low velocity high explosive shell"
- hud_state = "shell_he"
- flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_SUNDERING
- damage = 50
- penetration = 50
- sundering = 35
-
-/datum/ammo/rocket/atgun_shell/he/drop_nade(turf/T)
- cell_explosion(T, 90, 30)
-
-/datum/ammo/rocket/atgun_shell/he/on_hit_turf(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-/datum/ammo/rocket/atgun_shell/beehive
- name = "beehive shell"
- hud_state = "shell_le"
- flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_SUNDERING
- shell_speed = 3
- damage = 30
- penetration = 30
- sundering = 5
- bonus_projectiles_type = /datum/ammo/bullet/atgun_spread
- bonus_projectiles_scatter = 8
- var/bonus_projectile_quantity = 10
-
-/datum/ammo/rocket/atgun_shell/beehive/drop_nade(turf/T)
- explosion(T, flash_range = 1)
-
-/datum/ammo/rocket/atgun_shell/beehive/on_hit_mob(mob/M, obj/projectile/proj)
- staggerstun(M, proj, slowdown = 0.2, knockback = 1)
- drop_nade(get_turf(M))
- playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
- fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 5, 3, Get_Angle(proj.firer, M) )
-
-/datum/ammo/rocket/atgun_shell/beehive/on_hit_obj(obj/O, obj/projectile/proj)
- playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
- fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 5, 3, Get_Angle(proj.firer, O) )
-
-/datum/ammo/rocket/atgun_shell/beehive/on_hit_turf(turf/T, obj/projectile/proj)
- playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
- fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 5, 3, Get_Angle(proj.firer, T) )
-
-/datum/ammo/rocket/atgun_shell/beehive/do_at_max_range(turf/T, obj/projectile/proj)
- playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
- fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 5, 3, Get_Angle(proj.firer, get_turf(proj)) )
-
-/datum/ammo/rocket/atgun_shell/beehive/incend
- name = "napalm shell"
- hud_state = "shell_heat"
- flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_SUNDERING
- shell_speed = 3
- bonus_projectiles_type = /datum/ammo/bullet/atgun_spread/incendiary
-
-/datum/ammo/bullet/atgun_spread
- name = "Shrapnel"
- icon_state = "flechette"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB
- accuracy_var_low = 15
- accuracy_var_high = 5
- max_range = 6
- damage = 30
- penetration = 20
- sundering = 3
- damage_falloff = 0
-
-/datum/ammo/bullet/atgun_spread/incendiary
- name = "incendiary flechette"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB|AMMO_INCENDIARY|AMMO_LEAVE_TURF
- damage = 20
- penetration = 10
- sundering = 1.5
-
-/datum/ammo/bullet/atgun_spread/incendiary/on_hit_mob(mob/M, obj/projectile/proj)
- return
-
-/datum/ammo/bullet/atgun_spread/incendiary/drop_flame(turf/T)
- if(!istype(T))
- return
- T.ignite(5, 10)
-
-/datum/ammo/bullet/atgun_spread/incendiary/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
- drop_flame(T)
-
-/datum/ammo/mortar
- name = "80mm shell"
- icon_state = "mortar"
- flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_PASS_THROUGH_TURF|AMMO_PASS_THROUGH_MOVABLE
- shell_speed = 0.75
- damage = 0
- penetration = 0
- sundering = 0
- accuracy = 1000
- max_range = 1000
- ping = null
- bullet_color = COLOR_VERY_SOFT_YELLOW
-
-/datum/ammo/mortar/drop_nade(turf/T)
- cell_explosion(T, 90, 30)
-
-/datum/ammo/mortar/do_at_max_range(turf/T, obj/projectile/P)
- drop_nade(T)
-
-/datum/ammo/mortar/incend/drop_nade(turf/T)
- cell_explosion(T, 45, 20)
- flame_radius(4, T)
- playsound(T, 'sound/weapons/guns/fire/flamethrower2.ogg', 35, 1, 4)
-
-/datum/ammo/mortar/knee
- name = "50mm shell"
- icon_state = "howi"
- shell_speed = 0.75
-
-/datum/ammo/mortar/knee/drop_nade(turf/T)
- cell_explosion(T, 80, 30)
-
-/datum/ammo/mortar/smoke
- ///the smoke effect at the point of detonation
- var/datum/effect_system/smoke_spread/smoketype = /datum/effect_system/smoke_spread/tactical
-
-/datum/ammo/mortar/smoke/drop_nade(turf/T)
- var/datum/effect_system/smoke_spread/smoke = new smoketype()
- explosion(T, 0, 0, 1, 0, 3, throw_range = 0)
- playsound(T, 'sound/effects/smoke.ogg', 25, 1, 4)
- smoke.set_up(10, T, 11)
- smoke.start()
-
-/datum/ammo/mortar/smoke/plasmaloss
- smoketype = /datum/effect_system/smoke_spread/plasmaloss
-
-/datum/ammo/mortar/flare/drop_nade(turf/T)
- new /obj/effect/temp_visual/above_flare(T)
- playsound(T, 'sound/weapons/guns/fire/flare.ogg', 50, 1, 4)
-
-/datum/ammo/mortar/howi
- name = "150mm shell"
- icon_state = "howi"
-
-/datum/ammo/mortar/howi/drop_nade(turf/T)
- cell_explosion(T, 175, 50)
-
-/datum/ammo/mortar/howi/incend/drop_nade(turf/T)
- cell_explosion(T, 45, 30)
- flame_radius(5, T)
- playsound(T, 'sound/weapons/guns/fire/flamethrower2.ogg', 35, 1, 4)
-
-/datum/ammo/mortar/smoke/howi
- name = "150mm shell"
- icon_state = "howi"
-
-/datum/ammo/mortar/smoke/howi/wp
- smoketype = /datum/effect_system/smoke_spread/phosphorus
-
-/datum/ammo/mortar/smoke/howi/wp/drop_nade(turf/T)
- var/datum/effect_system/smoke_spread/smoke = new smoketype()
- explosion(T, 0, 0, 1, 0, 0, throw_range = 0)
- playsound(T, 'sound/effects/smoke.ogg', 25, 1, 4)
- smoke.set_up(6, T, 7)
- smoke.start()
- flame_radius(4, T)
- flame_radius(1, T, burn_intensity = 45, burn_duration = 75, burn_damage = 15, fire_stacks = 75)
-
-/datum/ammo/mortar/smoke/howi/plasmaloss
- smoketype = /datum/effect_system/smoke_spread/plasmaloss
-
-/datum/ammo/mortar/smoke/howi/plasmaloss/drop_nade(turf/T)
- var/datum/effect_system/smoke_spread/smoke = new smoketype()
- explosion(T, 0, 0, 5, 0, 0, throw_range = 0)
- playsound(T, 'sound/effects/smoke.ogg', 25, 1, 4)
- smoke.set_up(10, T, 11)
- smoke.start()
-
-/datum/ammo/mortar/rocket
- name = "rocket"
- icon_state = "rocket"
- shell_speed = 1.5
-
-/datum/ammo/mortar/rocket/drop_nade(turf/T)
- cell_explosion(T, 175, 75)
-
-/datum/ammo/mortar/rocket/incend/drop_nade(turf/T)
- cell_explosion(T, 50, 20)
- flame_radius(5, T)
- playsound(T, 'sound/weapons/guns/fire/flamethrower2.ogg', 35, 1, 4)
-
-/datum/ammo/mortar/rocket/minelayer/drop_nade(turf/T)
- var/obj/item/explosive/mine/mine = new /obj/item/explosive/mine(T)
- mine.deploy_mine(null, TGMC_LOYALIST_IFF)
-
-/datum/ammo/mortar/rocket/smoke
- ///the smoke effect at the point of detonation
- var/datum/effect_system/smoke_spread/smoketype = /datum/effect_system/smoke_spread/tactical
-
-/datum/ammo/mortar/rocket/smoke/drop_nade(turf/T)
- var/datum/effect_system/smoke_spread/smoke = new smoketype()
- explosion(T, 0, 0, 1, 0, 3, throw_range = 0)
- playsound(T, 'sound/effects/smoke.ogg', 25, 1, 4)
- smoke.set_up(10, T, 11)
- smoke.start()
-
-/datum/ammo/mortar/rocket/mlrs
- shell_speed = 2.5
-
-/datum/ammo/mortar/rocket/mlrs/drop_nade(turf/T)
- cell_explosion(T, 70, 25)
-
-/datum/ammo/mortar/rocket/smoke/mlrs
- shell_speed = 2.5
- smoketype = /datum/effect_system/smoke_spread/mustard
-
-/datum/ammo/mortar/rocket/smoke/mlrs/drop_nade(turf/T)
- var/datum/effect_system/smoke_spread/smoke = new smoketype()
- explosion(T, 0, 0, 2, 0, 0, throw_range = 0)
- playsound(T, 'sound/effects/smoke.ogg', 25, 1, 4)
- smoke.set_up(5, T, 6)
- smoke.start()
-
-/*
-//================================================
- Energy Ammo
-//================================================
-*/
-
-/datum/ammo/energy
- ping = "ping_s"
- sound_hit = "energy_hit"
- sound_armor = "ballistic_armor"
- sound_miss = "ballistic_miss"
- sound_bounce = "ballistic_bounce"
-
- damage_type = BURN
- flags_ammo_behavior = AMMO_ENERGY|AMMO_SOUND_PITCH
- armor_type = ENERGY
- accuracy = 15 //lasers fly fairly straight
- bullet_color = COLOR_LASER_RED
- barricade_clear_distance = 2
-
-/datum/ammo/energy/emitter //Damage is determined in emitter.dm
- name = "emitter bolt"
- icon_state = "emitter"
- flags_ammo_behavior = AMMO_ENERGY|AMMO_IGNORE_ARMOR
- accurate_range = 10
- max_range = 10
- bullet_color = COLOR_VIBRANT_LIME
-
-/datum/ammo/energy/taser
- name = "taser bolt"
- icon_state = "stun"
- hud_state = "taser"
- hud_state_empty = "battery_empty"
- damage = 10
- penetration = 100
- damage_type = STAMINA
- flags_ammo_behavior = AMMO_ENERGY|AMMO_SKIPS_ALIENS
- max_range = 15
- accurate_range = 10
- bullet_color = COLOR_VIVID_YELLOW
-/datum/ammo/energy/taser/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, stun = 20 SECONDS)
-
-/datum/ammo/energy/tesla
- name = "energy ball"
- icon_state = "tesla"
- hud_state = "taser"
- hud_state_empty = "battery_empty"
- flags_ammo_behavior = AMMO_ENERGY|AMMO_SPECIAL_PROCESS
- shell_speed = 0.1
- damage = 20
- penetration = 20
- bullet_color = COLOR_TESLA_BLUE
-
-/datum/ammo/energy/tesla/ammo_process(obj/projectile/proj, damage)
- zap_beam(proj, 4, damage)
-
-/datum/ammo/energy/tesla/focused
- flags_ammo_behavior = AMMO_ENERGY|AMMO_SPECIAL_PROCESS|AMMO_IFF
- shell_speed = 0.1
- damage = 10
- penetration = 10
- bullet_color = COLOR_TESLA_BLUE
-
-/datum/ammo/energy/tesla/focused/ammo_process(obj/projectile/proj, damage)
- zap_beam(proj, 3, damage)
-
-
-/datum/ammo/energy/tesla/on_hit_mob(mob/M,obj/projectile/P)
- if(isxeno(M)) //need 1 second more than the actual effect time
- var/mob/living/carbon/xenomorph/X = M
- X.use_plasma(0.3 * X.xeno_caste.plasma_max * X.xeno_caste.plasma_regen_limit) //Drains 30% of max plasma on hit
-
-/datum/ammo/energy/lasgun
- name = "laser bolt"
- icon_state = "laser"
- hud_state = "laser"
- armor_type = LASER
- flags_ammo_behavior = AMMO_ENERGY|AMMO_SUNDERING
- shell_speed = 4
- accurate_range = 15
- damage = 20
- penetration = 10
- max_range = 30
- accuracy_var_low = 3
- accuracy_var_high = 3
- sundering = 2.5
-
-/datum/ammo/energy/lasgun/M43
- icon_state = "laser2"
-
-/datum/ammo/energy/lasgun/M43/overcharge
- name = "overcharged laser bolt"
- icon_state = "overchargedlaser"
- hud_state = "laser_sniper"
- damage = 40
- max_range = 40
- penetration = 50
- sundering = 5
-
-/datum/ammo/energy/lasgun/M43/heat
- name = "microwave heat bolt"
- icon_state = "microwavelaser"
- hud_state = "laser_heat"
- damage = 12 //requires mod with -0.15 multiplier should math out to 10
- penetration = 100 // It's a laser that burns the skin! The fire stacks go threw anyway.
- flags_ammo_behavior = AMMO_ENERGY|AMMO_INCENDIARY|AMMO_SUNDERING
- sundering = 1
-
-/datum/ammo/energy/lasgun/M43/blast
- name = "wide range laser blast"
- icon_state = "heavylaser2"
- hud_state = "laser_spread"
- bonus_projectiles_type = /datum/ammo/energy/lasgun/M43/spread
- bonus_projectiles_amount = 2
- bonus_projectiles_scatter = 10
- accuracy_var_low = 9
- accuracy_var_high = 9
- accurate_range = 5
- max_range = 5
- damage = 42
- damage_falloff = 10
- penetration = 0
- sundering = 5
-
-/datum/ammo/energy/lasgun/M43/spread
- name = "additional laser blast"
- icon_state = "laser2"
- shell_speed = 2
- accuracy_var_low = 9
- accuracy_var_high = 9
- accurate_range = 5
- max_range = 5
- damage = 35
- damage_falloff = 10
- penetration = 0
-
-/datum/ammo/energy/lasgun/M43/disabler
- name = "disabler bolt"
- icon_state = "disablershot"
- hud_state = "laser_disabler"
- damage = 45
- penetration = 0
- damage_type = STAMINA
- bullet_color = COLOR_DISABLER_BLUE
-
-/datum/ammo/energy/lasgun/M43/disabler/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, stagger = 1 SECONDS, slowdown = 0.75)
-
-/datum/ammo/energy/lasgun/pulsebolt
- name = "pulse bolt"
- icon_state = "pulse2"
- hud_state = "pulse"
- damage = 45 // this is gotta hurt...
- max_range = 40
- penetration = 100
- sundering = 100
- bullet_color = COLOR_PULSE_BLUE
-
-/datum/ammo/energy/lasgun/M43/practice
- name = "practice laser bolt"
- icon_state = "disablershot"
- hud_state = "laser_disabler"
- damage = 45
- penetration = 0
- damage_type = STAMINA
- flags_ammo_behavior = AMMO_ENERGY
- bullet_color = COLOR_DISABLER_BLUE
-
-/datum/ammo/energy/lasgun/M43/practice/on_hit_mob(mob/living/carbon/C, obj/projectile/P)
- if(!istype(C) || C.stat == DEAD || C.issamexenohive(P.firer) )
- return
-
- if(isnestedhost(C))
- return
-
- staggerstun(C, P, stagger = 2 SECONDS, slowdown = 1) //Staggers and slows down briefly
-
- return ..()
-
-// TE Lasers //
-
-/datum/ammo/energy/lasgun/marine
- flags_ammo_behavior = AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN
- damage = 20
- penetration = 10
- sundering = 1.5
- max_range = 30
- hitscan_effect_icon = "beam"
-
-/datum/ammo/energy/lasgun/marine/sniper_overcharge
- name = "sniper overcharge bolt"
- icon_state = "overchargedlaser"
- hud_state = "laser_sniper_overcharge"
- shell_speed = 2.5
- damage = 100
- penetration = 80
- accurate_range_min = 6
- flags_ammo_behavior = AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_SNIPER
- sundering = 10
- hitscan_effect_icon = "beam_heavy_charge"
- bullet_color = COLOR_DISABLER_BLUE
-
-/datum/ammo/energy/lasgun/marine/carbine
- sundering = 1
- max_range = 18
-
-/datum/ammo/energy/lasgun/marine/overcharge
- name = "overcharged laser bolt"
- icon_state = "overchargedlaser"
- hud_state = "laser_sniper"
- damage = 40
- penetration = 20
- sundering = 2
- hitscan_effect_icon = "beam_heavy"
-
-/datum/ammo/energy/lasgun/marine/weakening
- name = "weakening laser bolt"
- icon_state = "overchargedlaser"
- hud_state = "laser_sniper"
- damage = 30
- penetration = 10
- sundering = 0
- damage_type = STAMINA
- hitscan_effect_icon = "blue_beam"
- bullet_color = COLOR_DISABLER_BLUE
- ///plasma drained per hit
- var/plasma_drain = 25
-
-/datum/ammo/energy/lasgun/marine/weakening/on_hit_mob(mob/M, obj/projectile/proj)
- staggerstun(M, proj, max_range = 6, slowdown = 1)
-
- if(!isxeno(M))
- return
- var/mob/living/carbon/xenomorph/xeno_victim = M
- xeno_victim.use_plasma(plasma_drain * xeno_victim.xeno_caste.plasma_regen_limit)
-
-/datum/ammo/energy/lasgun/marine/microwave
- name = "microwave laser bolt"
- icon_state = "overchargedlaser"
- hud_state = "laser_sniper"
- damage = 20
- penetration = 20
- sundering = 2
- hitscan_effect_icon = "beam_grass"
- bullet_color = LIGHT_COLOR_GREEN
- ///number of microwave stacks to apply when hitting mobvs
- var/microwave_stacks = 1
-
-/datum/ammo/energy/lasgun/marine/microwave/on_hit_mob(mob/M, obj/projectile/proj)
- if(!isliving(M))
- return
-
- var/mob/living/living_victim = M
- var/datum/status_effect/stacking/microwave/debuff = living_victim.has_status_effect(STATUS_EFFECT_MICROWAVE)
-
- if(debuff)
- debuff.add_stacks(microwave_stacks)
- else
- living_victim.apply_status_effect(STATUS_EFFECT_MICROWAVE, microwave_stacks)
-
-/datum/ammo/energy/lasgun/marine/blast
- name = "wide range laser blast"
- icon_state = "heavylaser2"
- hud_state = "laser_spread"
- bonus_projectiles_type = /datum/ammo/energy/lasgun/marine/blast/spread
- bonus_projectiles_amount = 2
- bonus_projectiles_scatter = 5
- accuracy_var_low = 9
- accuracy_var_high = 9
- accurate_range = 5
- max_range = 8
- damage = 35
- penetration = 20
- sundering = 1
- hitscan_effect_icon = "pu_laser"
- bullet_color = LIGHT_COLOR_PURPLE
-
-/datum/ammo/energy/lasgun/marine/blast/spread
- name = "additional laser blast"
-
-/datum/ammo/energy/lasgun/marine/impact
- name = "impact laser blast"
- icon_state = "overchargedlaser"
- hud_state = "laser_sniper"
- damage = 35
- penetration = 10
- sundering = 0
- hitscan_effect_icon = "pu_laser"
- bullet_color = LIGHT_COLOR_PURPLE
-
-/datum/ammo/energy/lasgun/marine/impact/on_hit_mob(mob/M, obj/projectile/proj)
- var/knockback_dist = round(LERP(3, 1, proj.distance_travelled / 6), 1)
- staggerstun(M, proj, max_range = 6, knockback = knockback_dist)
-
-/datum/ammo/energy/lasgun/marine/cripple
- name = "impact laser blast"
- icon_state = "overchargedlaser"
- hud_state = "laser_sniper"
- damage = 20
- penetration = 10
- sundering = 0
- hitscan_effect_icon = "blue_beam"
- bullet_color = COLOR_DISABLER_BLUE
-
-/datum/ammo/energy/lasgun/marine/cripple/on_hit_mob(mob/M, obj/projectile/proj)
- staggerstun(M, proj, slowdown = 1.5)
-
-/datum/ammo/energy/lasgun/marine/autolaser
- name = "machine laser bolt"
- damage = 18
- penetration = 15
- sundering = 1
-
-/datum/ammo/energy/lasgun/marine/autolaser/burst
- name = "burst machine laser bolt"
- hud_state = "laser_efficiency"
- damage = 12
-
-/datum/ammo/energy/lasgun/marine/autolaser/charge
- name = "charged machine laser bolt"
- hud_state = "laser_efficiency"
- damage = 50
- penetration = 30
- sundering = 3
- hitscan_effect_icon = "beam_heavy"
- flags_ammo_behavior = AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_PASS_THROUGH_MOB
-
-/datum/ammo/energy/lasgun/marine/autolaser/charge/on_hit_turf(turf/T, obj/projectile/proj)
- if(istype(T, /turf/closed/wall))
- var/turf/closed/wall/wall_victim = T
- wall_victim.take_damage(proj.damage, proj.damtype, proj.armor_type)
-
-/datum/ammo/energy/lasgun/marine/autolaser/melting
- name = "melting machine laser bolt"
- hud_state = "laser_efficiency"
- damage = 15
- penetration = 20
- sundering = 0
- hitscan_effect_icon = "beam_solar"
- bullet_color = LIGHT_COLOR_YELLOW
- ///number of melting stacks to apply when hitting mobs
- var/melt_stacks = 2
-
-/datum/ammo/energy/lasgun/marine/autolaser/melting/on_hit_mob(mob/M, obj/projectile/proj)
- if(!isliving(M))
- return
-
- var/mob/living/living_victim = M
- var/datum/status_effect/stacking/melting/debuff = living_victim.has_status_effect(STATUS_EFFECT_MELTING)
-
- if(debuff)
- debuff.add_stacks(melt_stacks)
- else
- living_victim.apply_status_effect(STATUS_EFFECT_MELTING, melt_stacks)
-
-/datum/ammo/energy/lasgun/marine/sniper
- name = "sniper laser bolt"
- hud_state = "laser_sniper"
- damage = 60
- penetration = 30
- accurate_range_min = 5
- flags_ammo_behavior = AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_SNIPER
- sundering = 5
- max_range = 40
- damage_falloff = 0
- hitscan_effect_icon = "beam_heavy"
-
-/datum/ammo/energy/lasgun/marine/sniper_heat
- name = "sniper heat bolt"
- icon_state = "microwavelaser"
- hud_state = "laser_heat"
- damage = 40
- penetration = 30
- accurate_range_min = 5
- flags_ammo_behavior = AMMO_ENERGY|AMMO_INCENDIARY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_SNIPER
- sundering = 1
- hitscan_effect_icon = "beam_incen"
- bullet_color = COLOR_RED_LIGHT
-
-/datum/ammo/energy/lasgun/marine/shatter
- name = "sniper shattering bolt"
- icon_state = "microwavelaser"
- hud_state = "laser_heat"
- damage = 40
- penetration = 30
- accurate_range_min = 5
- sundering = 10
- hitscan_effect_icon = "pu_laser"
- bullet_color = LIGHT_COLOR_PURPLE
- ///shatter effection duration when hitting mobs
- var/shatter_duration = 5 SECONDS
-
-/datum/ammo/energy/lasgun/marine/shatter/on_hit_mob(mob/M, obj/projectile/proj)
- if(!isliving(M))
- return
-
- var/mob/living/living_victim = M
- living_victim.apply_status_effect(STATUS_EFFECT_SHATTER, shatter_duration)
-
-/datum/ammo/energy/lasgun/marine/shatter/heavy_laser
- sundering = 1
- accurate_range_min = 0
-
-/datum/ammo/energy/lasgun/marine/ricochet
- name = "sniper laser bolt"
- icon_state = "microwavelaser"
- hud_state = "laser_heat"
- damage = 100
- penetration = 30
- flags_ammo_behavior = AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_SNIPER
- sundering = 1
- hitscan_effect_icon = "u_laser_beam"
- bonus_projectiles_scatter = 0
- bullet_color = COLOR_DISABLER_BLUE
-
-/datum/ammo/energy/lasgun/marine/ricochet/one
- damage = 80
- bonus_projectiles_type = /datum/ammo/energy/lasgun/marine/ricochet
-
-/datum/ammo/energy/lasgun/marine/ricochet/two
- damage = 65
- bonus_projectiles_type = /datum/ammo/energy/lasgun/marine/ricochet/one
-
-/datum/ammo/energy/lasgun/marine/ricochet/three
- damage = 50
- bonus_projectiles_type = /datum/ammo/energy/lasgun/marine/ricochet/two
-
-/datum/ammo/energy/lasgun/marine/ricochet/four
- damage = 40
- bonus_projectiles_type = /datum/ammo/energy/lasgun/marine/ricochet/three
-
-/datum/ammo/energy/lasgun/marine/ricochet/on_hit_turf(turf/T, obj/projectile/proj)
- reflect(T, proj, 5)
-
-/datum/ammo/energy/lasgun/marine/ricochet/on_hit_obj(obj/O, obj/projectile/proj)
- reflect(get_turf(O), proj, 5)
-
-/datum/ammo/energy/lasgun/marine/pistol
- name = "pistol laser bolt"
- damage = 20
- penetration = 5
- sundering = 1
- hitscan_effect_icon = "beam_particle"
- bullet_color = COLOR_DISABLER_BLUE
-
-/datum/ammo/energy/lasgun/marine/pistol/disabler
- name = "disabler bolt"
- icon_state = "disablershot"
- hud_state = "laser_disabler"
- damage = 70
- penetration = 0
- damage_type = STAMINA
- hitscan_effect_icon = "beam_stun"
- bullet_color = LIGHT_COLOR_YELLOW
-
-/datum/ammo/energy/lasgun/marine/pistol/heat
- name = "microwave heat bolt"
- icon_state = "microwavelaser"
- hud_state = "laser_heat"
- damage = 20
- shell_speed = 2.5
- penetration = 10
- flags_ammo_behavior = AMMO_ENERGY|AMMO_INCENDIARY|AMMO_SUNDERING|AMMO_HITSCAN
- sundering = 0.5
- hitscan_effect_icon = "beam_incen"
- bullet_color = COLOR_LASER_RED
-
-/datum/ammo/energy/lasgun/pistol/disabler/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, stagger = 1 SECONDS, slowdown = 0.75)
-
-/datum/ammo/energy/lasgun/marine/xray
- name = "xray heat bolt"
- hud_state = "laser_xray"
- icon_state = "u_laser"
- flags_ammo_behavior = AMMO_ENERGY|AMMO_INCENDIARY|AMMO_SUNDERING|AMMO_HITSCAN
- damage = 25
- penetration = 5
- sundering = 1
- max_range = 15
- hitscan_effect_icon = "u_laser_beam"
-
-/datum/ammo/energy/lasgun/marine/xray/piercing
- name = "xray piercing bolt"
- icon_state = "xray"
- flags_ammo_behavior = AMMO_ENERGY|AMMO_HITSCAN|AMMO_PASS_THROUGH_TURF|AMMO_PASS_THROUGH_MOVABLE
- damage = 25
- penetration = 100
- max_range = 10
- hitscan_effect_icon = "xray_beam"
-
-/datum/ammo/energy/lasgun/marine/heavy_laser
- flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_INCENDIARY
- hud_state = "laser_overcharge"
- damage = 60
- penetration = 10
- sundering = 1
- max_range = 30
- hitscan_effect_icon = "beam_incen"
-
-/datum/ammo/energy/lasgun/marine/heavy_laser/drop_nade(turf/T, radius = 1)
- if(!T || !isturf(T))
- return
- playsound(T, 'sound/weapons/guns/fire/flamethrower2.ogg', 50, 1, 4)
- flame_radius(radius, T, 3, 3, 3, 3)
-
-/datum/ammo/energy/lasgun/marine/heavy_laser/on_hit_mob(mob/M, obj/projectile/P)
- drop_nade(get_turf(M))
-
-/datum/ammo/energy/lasgun/marine/heavy_laser/on_hit_obj(obj/O, obj/projectile/P)
- drop_nade(O.density ? get_step_towards(O, P) : O, P)
-
-/datum/ammo/energy/lasgun/marine/heavy_laser/on_hit_turf(turf/T, obj/projectile/P)
- drop_nade(T.density ? get_step_towards(T, P) : T)
-
-/datum/ammo/energy/lasgun/marine/heavy_laser/do_at_max_range(turf/T, obj/projectile/P)
- drop_nade(T.density ? get_step_towards(T, P) : T)
-
-
-/datum/ammo/energy/xeno
- barricade_clear_distance = 0
- ///Plasma cost to fire this projectile
- var/ability_cost
- ///Particle type used when this ammo is used
- var/particles/channel_particle
- ///The colour the xeno glows when using this ammo type
- var/glow_color
-
-/datum/ammo/energy/xeno/psy_blast
- name = "psychic blast"
- flags_ammo_behavior = AMMO_XENO|AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_SKIPS_ALIENS
- damage = 35
- penetration = 10
- sundering = 1
- max_range = 7
- accurate_range = 7
- hitscan_effect_icon = "beam_cult"
- icon_state = "psy_blast"
- ability_cost = 230
- channel_particle = /particles/warlock_charge/psy_blast
- glow_color = "#9e1f1f"
- ///The AOE for drop_nade
- var/aoe_range = 2
-
-/datum/ammo/energy/xeno/psy_blast/drop_nade(turf/T, obj/projectile/P)
- if(!T || !isturf(T))
- return
- playsound(T, 'sound/effects/EMPulse.ogg', 50)
- var/aoe_damage = 25
- if(isxeno(P.firer))
- var/mob/living/carbon/xenomorph/xeno_firer = P.firer
- aoe_damage = xeno_firer.xeno_caste.blast_strength
-
- var/list/throw_atoms = list()
- var/list/turf/target_turfs = generate_true_cone(T, aoe_range, -1, 359, 0, air_pass = TRUE)
- for(var/turf/target_turf AS in target_turfs)
- for(var/atom/movable/target AS in target_turf)
- if(isliving(target))
- var/mob/living/living_victim = target
- if(living_victim.stat == DEAD)
- continue
- if(!isxeno(living_victim))
- living_victim.apply_damage(aoe_damage, BURN, null, ENERGY, FALSE, FALSE, TRUE, penetration)
- staggerstun(living_victim, P, 10, slowdown = 1)
- else if(isobj(target))
- var/obj/obj_victim = target
- if(!(obj_victim.resistance_flags & XENO_DAMAGEABLE))
- continue
- obj_victim.take_damage(aoe_damage, BURN, ENERGY, TRUE, armour_penetration = penetration)
- if(target.anchored)
- continue
- throw_atoms += target
-
- for(var/atom/movable/target AS in throw_atoms)
- var/throw_dir = get_dir(T, target)
- if(T == get_turf(target))
- throw_dir = get_dir(P.starting_turf, T)
- target.safe_throw_at(get_ranged_target_turf(T, throw_dir, 5), 3, 1, spin = TRUE)
-
- new /obj/effect/temp_visual/shockwave(T, aoe_range + 2)
-
-/datum/ammo/energy/xeno/psy_blast/on_hit_mob(mob/M, obj/projectile/P)
- drop_nade(get_turf(M), P)
-
-/datum/ammo/energy/xeno/psy_blast/on_hit_obj(obj/O, obj/projectile/P)
- drop_nade(O.density ? get_step_towards(O, P) : O, P)
-
-/datum/ammo/energy/xeno/psy_blast/on_hit_turf(turf/T, obj/projectile/P)
- drop_nade(T.density ? get_step_towards(T, P) : T, P)
-
-/datum/ammo/energy/xeno/psy_blast/do_at_max_range(turf/T, obj/projectile/P)
- drop_nade(T.density ? get_step_towards(T, P) : T, P)
-
-/datum/ammo/energy/xeno/psy_blast/psy_lance
- name = "psychic lance"
- flags_ammo_behavior = AMMO_XENO|AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_PASS_THROUGH_MOVABLE
- damage = 60
- penetration = 50
- accuracy = 100
- sundering = 5
- max_range = 16
- hitscan_effect_icon = "beam_hcult"
- icon_state = "psy_lance"
- ability_cost = 300
- channel_particle = /particles/warlock_charge/psy_blast/psy_lance
- glow_color = "#CB0166"
-
-/datum/ammo/energy/xeno/psy_blast/psy_lance/on_hit_obj(obj/O, obj/projectile/P)
- if(isvehicle(O))
- var/obj/vehicle/veh_victim = O
- veh_victim.take_damage(200, BURN, ENERGY, TRUE, armour_penetration = penetration)
-
-/datum/ammo/energy/xeno/psy_blast/psy_lance/on_hit_mob(mob/M, obj/projectile/P)
- if(isxeno(M))
- return
- staggerstun(M, P, 9, stagger = 4 SECONDS, slowdown = 2, knockback = 1)
-
-/datum/ammo/energy/xeno/psy_blast/psy_lance/on_hit_turf(turf/T, obj/projectile/P)
- return
-
-/datum/ammo/energy/xeno/psy_blast/psy_lance/do_at_max_range(turf/T, obj/projectile/P)
- return
-
-/datum/ammo/energy/lasgun/marine/mech
- name = "superheated laser bolt"
- damage = 45
- penetration = 20
- sundering = 1
- damage_falloff = 0.5
-
-/datum/ammo/energy/lasgun/marine/mech/burst
- damage = 30
- penetration = 10
- sundering = 0.75
- damage_falloff = 0.6
-
-/datum/ammo/energy/lasgun/marine/mech/smg
- name = "superheated pulsed laser bolt"
- damage = 15
- penetration = 10
- hitscan_effect_icon = "beam_particle"
-
-/datum/ammo/energy/lasgun/marine/mech/lance_strike
- name = "particle lance"
- flags_ammo_behavior = AMMO_ENERGY|AMMO_SNIPER|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_PASS_THROUGH_MOVABLE|AMMO_PASS_THROUGH_MOB
- damage_type = BRUTE
- damage = 100
- armor_type = MELEE
- penetration = 25
- sundering = 8
- damage_falloff = -12.5 //damage increases per turf crossed
- max_range = 4
- on_pierce_multiplier = 0.5
- hitscan_effect_icon = "lance"
-
-/datum/ammo/energy/lasgun/marine/mech/lance_strike/super
- damage = 120
- damage_falloff = -8
- max_range = 5
-
-// Plasma //
-/datum/ammo/energy/plasma
- name = "plasma bolt"
- icon_state = "pulse2"
- hud_state = "plasma"
- armor_type = LASER
- shell_speed = 4
- accurate_range = 15
- damage = 40
- penetration = 15
- max_range = 30
- accuracy_var_low = 3
- accuracy_var_high = 3
-
-/datum/ammo/energy/plasma_pistol
- name = "ionized plasma bolt"
- icon_state = "overchargedlaser"
- hud_state = "electrothermal"
- hud_state_empty = "electrothermal_empty"
- damage = 40
- max_range = 14
- penetration = 5
- shell_speed = 1.5
- flags_ammo_behavior = AMMO_ENERGY|AMMO_INCENDIARY|AMMO_EXPLOSIVE
- bullet_color = LIGHT_COLOR_ELECTRIC_GREEN
-
- ///Fire burn time
- var/heat = 12
- ///Fire damage
- var/burn_damage = 9
- ///Fire color
- var/fire_color = "green"
-
-/datum/ammo/energy/plasma_pistol/proc/drop_fire(atom/target, obj/projectile/proj)
- var/turf/target_turf = get_turf(target)
- var/burn_mod = 1
- if(istype(target_turf, /turf/closed/wall))
- burn_mod = 3
- target_turf.ignite(heat, burn_damage * burn_mod, fire_color)
-
- for(var/mob/living/mob_caught in target_turf)
- if(mob_caught.stat == DEAD || mob_caught == target)
- continue
- mob_caught.adjust_fire_stacks(burn_damage)
- mob_caught.IgniteMob()
-
-/datum/ammo/energy/plasma_pistol/on_hit_turf(turf/T, obj/projectile/proj)
- drop_fire(T, proj)
-
-/datum/ammo/energy/plasma_pistol/on_hit_mob(mob/M, obj/projectile/proj)
- drop_fire(M, proj)
-
-/datum/ammo/energy/plasma_pistol/on_hit_obj(obj/O, obj/projectile/proj)
- drop_fire(O, proj)
-
-/datum/ammo/energy/plasma_pistol/do_at_max_range(turf/T, obj/projectile/proj)
- drop_fire(T, proj)
-
-//volkite
-
-/datum/ammo/energy/volkite
- name = "thermal energy bolt"
- icon_state = "overchargedlaser"
- hud_state = "laser_heat"
- hud_state_empty = "battery_empty_flash"
- flags_ammo_behavior = AMMO_ENERGY|AMMO_SUNDERING|AMMO_SOUND_PITCH
- bullet_color = COLOR_TAN_ORANGE
- armor_type = ENERGY
- max_range = 14
- accurate_range = 5 //for charger
- shell_speed = 4
- accuracy_var_low = 5
- accuracy_var_high = 5
- accuracy = 5
- point_blank_range = 2
- damage = 20
- penetration = 10
- sundering = 2
- fire_burst_damage = 15
-
- //inherited, could use some changes
- ping = "ping_s"
- sound_hit = "energy_hit"
- sound_armor = "ballistic_armor"
- sound_miss = "ballistic_miss"
- sound_bounce = "ballistic_bounce"
-
-/datum/ammo/energy/volkite/on_hit_mob(mob/M,obj/projectile/P)
- deflagrate(M, P)
-
-/datum/ammo/energy/volkite/medium
- max_range = 25
- accurate_range = 12
- damage = 30
- accuracy_var_low = 3
- accuracy_var_high = 3
- fire_burst_damage = 20
-
-/datum/ammo/energy/volkite/medium/custom
- deflagrate_multiplier = 2
-
-/datum/ammo/energy/volkite/heavy
- max_range = 35
- accurate_range = 12
- damage = 25
- fire_burst_damage = 20
-
-/datum/ammo/energy/volkite/light
- max_range = 25
- accurate_range = 12
- accuracy_var_low = 3
- accuracy_var_high = 3
- penetration = 5
-
-/*
-//================================================
- Xeno Spits
-//================================================
-*/
-/datum/ammo/xeno
- icon_state = "neurotoxin"
- ping = "ping_x"
- damage_type = TOX
- flags_ammo_behavior = AMMO_XENO
- var/added_spit_delay = 0 //used to make cooldown of the different spits vary.
- var/spit_cost = 5
- armor_type = BIO
- shell_speed = 1
- accuracy = 40
- accurate_range = 15
- max_range = 15
- accuracy_var_low = 3
- accuracy_var_high = 3
- bullet_color = COLOR_LIME
- ///List of reagents transferred upon spit impact if any
- var/list/datum/reagent/spit_reagents
- ///Amount of reagents transferred upon spit impact if any
- var/reagent_transfer_amount
- ///Amount of stagger stacks imposed on impact if any
- var/stagger_stacks
- ///Amount of slowdown stacks imposed on impact if any
- var/slowdown_stacks
- ///These define the reagent transfer strength of the smoke caused by the spit, if any, and its aoe
- var/datum/effect_system/smoke_spread/xeno/smoke_system
- var/smoke_strength
- var/smoke_range
- ///The hivenumber of this ammo
- var/hivenumber = XENO_HIVE_NORMAL
-
-/datum/ammo/xeno/toxin
- name = "neurotoxic spit"
- flags_ammo_behavior = AMMO_XENO|AMMO_EXPLOSIVE|AMMO_SKIPS_ALIENS
- spit_cost = 55
- added_spit_delay = 0
- damage_type = STAMINA
- accurate_range = 5
- max_range = 10
- accuracy_var_low = 3
- accuracy_var_high = 3
- damage = 40
- stagger_stacks = 1.1 SECONDS
- slowdown_stacks = 1.5
- smoke_strength = 0.5
- smoke_range = 0
- reagent_transfer_amount = 4
- bullet_color = COLOR_LIGHT_ORANGE
-
-///Set up the list of reagents the spit transfers upon impact
-/datum/ammo/xeno/toxin/proc/set_reagents()
- spit_reagents = list(/datum/reagent/toxin/xeno_neurotoxin = reagent_transfer_amount)
-
-/datum/ammo/xeno/toxin/on_hit_mob(mob/living/carbon/carbon_victim, obj/projectile/proj)
- drop_neuro_smoke(get_turf(carbon_victim))
-
- if(!istype(carbon_victim) || carbon_victim.stat == DEAD || carbon_victim.issamexenohive(proj.firer) )
- return
-
- if(isnestedhost(carbon_victim))
- return
-
- carbon_victim.adjust_stagger(stagger_stacks)
- carbon_victim.add_slowdown(slowdown_stacks)
-
- set_reagents()
- for(var/reagent_id in spit_reagents)
- spit_reagents[reagent_id] = carbon_victim.modify_by_armor(spit_reagents[reagent_id], armor_type, penetration, proj.def_zone)
-
- carbon_victim.reagents.add_reagent_list(spit_reagents)
-
- return ..()
-
-/datum/ammo/xeno/toxin/on_hit_obj(obj/O, obj/projectile/P)
- var/turf/T = get_turf(O)
- drop_neuro_smoke(T.density ? P.loc : T)
-
-/datum/ammo/xeno/toxin/on_hit_turf(turf/T, obj/projectile/P)
- drop_neuro_smoke(T.density ? P.loc : T)
-
-/datum/ammo/xeno/toxin/do_at_max_range(turf/T, obj/projectile/P)
- drop_neuro_smoke(T.density ? P.loc : T)
-
-/datum/ammo/xeno/toxin/set_smoke()
- smoke_system = new /datum/effect_system/smoke_spread/xeno/neuro/light()
-
-/datum/ammo/xeno/toxin/proc/drop_neuro_smoke(turf/T)
- if(T.density)
- return
-
- set_smoke()
- smoke_system.strength = smoke_strength
- smoke_system.set_up(smoke_range, T)
- smoke_system.start()
- smoke_system = null
-
-/datum/ammo/xeno/toxin/sent //Sentinel
- spit_cost = 70
- icon_state = "xeno_sent_neuro"
-
-/datum/ammo/xeno/toxin/upgrade1
- smoke_strength = 0.6
- reagent_transfer_amount = 5
-
-/datum/ammo/xeno/toxin/upgrade2
- smoke_strength = 0.7
- reagent_transfer_amount = 6
-
-/datum/ammo/xeno/toxin/upgrade3
- smoke_strength = 0.75
- reagent_transfer_amount = 6.5
-
-
-/datum/ammo/xeno/toxin/heavy //Praetorian
- name = "neurotoxic splash"
- added_spit_delay = 0
- spit_cost = 200
- damage = 80
- smoke_strength = 1
- reagent_transfer_amount = 18
- smoke_range = 1
-
-
-/datum/ammo/xeno/sticky
- name = "sticky resin spit"
- icon_state = "sticky"
- ping = null
- flags_ammo_behavior = AMMO_SKIPS_ALIENS|AMMO_EXPLOSIVE|AMMO_XENO
- damage_type = STAMINA
- armor_type = BIO
- spit_cost = 50
- sound_hit = "alien_resin_build2"
- sound_bounce = "alien_resin_build3"
- damage = 20 //minor; this is mostly just to provide confirmation of a hit
- max_range = 40
- bullet_color = COLOR_PURPLE
- stagger_stacks = 2
- slowdown_stacks = 3
-
-
-/datum/ammo/xeno/sticky/on_hit_mob(mob/M, obj/projectile/P)
- drop_resin(get_turf(M))
- if(istype(M,/mob/living/carbon))
- var/mob/living/carbon/C = M
- if(C.issamexenohive(P.firer))
- return
- C.adjust_stagger(stagger_stacks) //stagger briefly; useful for support
- C.add_slowdown(slowdown_stacks) //slow em down
-
-
-/datum/ammo/xeno/sticky/on_hit_obj(obj/O, obj/projectile/P)
- if(isarmoredvehicle(O))
- var/obj/vehicle/sealed/armored/tank = O
- COOLDOWN_START(tank, cooldown_vehicle_move, tank.move_delay)
- var/turf/T = get_turf(O)
- drop_resin(T.density ? P.loc : T)
-
-/datum/ammo/xeno/sticky/on_hit_turf(turf/T, obj/projectile/P)
- drop_resin(T.density ? P.loc : T)
-
-/datum/ammo/xeno/sticky/do_at_max_range(turf/T, obj/projectile/P)
- drop_resin(T.density ? P.loc : T)
-
-/datum/ammo/xeno/sticky/proc/drop_resin(turf/T)
- if(T.density || istype(T, /turf/open/space)) // No structures in space
- return
-
- for(var/obj/O in T.contents)
- if(is_type_in_typecache(O, GLOB.no_sticky_resin))
- return
-
- new /obj/alien/resin/sticky/thin(T)
-
-/datum/ammo/xeno/sticky/turret
- max_range = 9
-
-/datum/ammo/xeno/sticky/globe
- name = "sticky resin globe"
- icon_state = "sticky_globe"
- damage = 40
- max_range = 7
- spit_cost = 200
- added_spit_delay = 8 SECONDS
- bonus_projectiles_type = /datum/ammo/xeno/sticky/mini
- bonus_projectiles_scatter = 22
- var/bonus_projectile_quantity = 16
- var/bonus_projectile_range = 3
- var/bonus_projectile_speed = 1
-
-/datum/ammo/xeno/sticky/mini
- damage = 5
- max_range = 3
-
-/datum/ammo/xeno/sticky/globe/on_hit_obj(obj/O, obj/projectile/P)
- var/turf/initial_turf = O.density ? P.loc : get_turf(O)
- drop_resin(initial_turf)
- fire_directionalburst(P, P.firer, P.shot_from, bonus_projectile_quantity, bonus_projectile_range, bonus_projectile_speed, Get_Angle(P.firer, initial_turf))
-
-/datum/ammo/xeno/sticky/globe/on_hit_turf(turf/T, obj/projectile/P)
- var/turf/initial_turf = T.density ? P.loc : T
- drop_resin(initial_turf)
- fire_directionalburst(P, P.firer, P.shot_from, bonus_projectile_quantity, bonus_projectile_range, bonus_projectile_speed, Get_Angle(P.firer, initial_turf))
-
-/datum/ammo/xeno/sticky/globe/on_hit_mob(mob/M, obj/projectile/P)
- var/turf/initial_turf = get_turf(M)
- drop_resin(initial_turf)
- fire_directionalburst(P, P.firer, P.shot_from, bonus_projectile_quantity, bonus_projectile_range, bonus_projectile_speed, Get_Angle(P.firer, initial_turf))
-
-/datum/ammo/xeno/sticky/globe/do_at_max_range(turf/T, obj/projectile/P)
- var/turf/initial_turf = T.density ? P.loc : T
- drop_resin(initial_turf)
- fire_directionalburst(P, P.firer, P.shot_from, bonus_projectile_quantity, bonus_projectile_range, bonus_projectile_speed, Get_Angle(P.firer, initial_turf))
-
-/datum/ammo/xeno/acid
- name = "acid spit"
- icon_state = "xeno_acid_weak"
- sound_hit = "acid_hit"
- sound_bounce = "acid_bounce"
- damage_type = BURN
- added_spit_delay = 5
- spit_cost = 50
- flags_ammo_behavior = AMMO_XENO|AMMO_EXPLOSIVE
- armor_type = ACID
- damage = 18
- max_range = 8
- bullet_color = COLOR_PALE_GREEN_GRAY
- ///Duration of the acid puddles
- var/puddle_duration = 1 SECONDS //Lasts 1-3 seconds
- ///Damage dealt by acid puddles
- var/puddle_acid_damage = XENO_DEFAULT_ACID_PUDDLE_DAMAGE
-
-/datum/ammo/xeno/acid/on_shield_block(mob/victim, obj/projectile/proj)
- airburst(victim, proj)
-
-/datum/ammo/xeno/acid/drop_nade(turf/T) //Leaves behind an acid pool; defaults to 1-3 seconds.
- if(T.density)
- return
- new /obj/effect/xenomorph/spray/weak(T, puddle_duration, puddle_acid_damage)
-
-/datum/ammo/xeno/acid/medium
- name = "acid spatter"
- damage = 30
- flags_ammo_behavior = AMMO_XENO
- icon_state = "xeno_acid_normal"
- bullet_color = COLOR_VERY_PALE_LIME_GREEN
-
-/datum/ammo/xeno/acid/medium/drop_nade(turf/T) //Leaves behind an acid pool; defaults to 1-3 seconds.
- if(T.density)
- return
- new /obj/effect/xenomorph/spray(T, puddle_duration, puddle_acid_damage)
-
-/datum/ammo/xeno/acid/medium/passthrough //Spitter
- flags_ammo_behavior = AMMO_XENO|AMMO_SKIPS_ALIENS
-
-/datum/ammo/xeno/acid/auto
- name = "light acid spatter"
- damage = 10
- damage_falloff = 0.3
- spit_cost = 25
- added_spit_delay = 0
- flags_ammo_behavior = AMMO_XENO|AMMO_EXPLOSIVE|AMMO_SKIPS_ALIENS
-
-/datum/ammo/xeno/acid/auto/on_hit_mob(mob/M, obj/projectile/P)
- var/turf/T = get_turf(M)
- drop_nade(T.density ? P.loc : T)
-
-/datum/ammo/xeno/acid/auto/on_hit_obj(obj/O, obj/projectile/P)
- drop_nade(O.density ? P.loc : get_turf(O))
-
-/datum/ammo/xeno/acid/auto/on_hit_turf(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-/datum/ammo/xeno/acid/auto/do_at_max_range(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-/datum/ammo/xeno/acid/passthrough
- name = "acid spittle"
- damage = 20
- flags_ammo_behavior = AMMO_XENO|AMMO_SKIPS_ALIENS
-
-/datum/ammo/xeno/acid/heavy
- name = "acid splash"
- added_spit_delay = 2
- spit_cost = 70
- damage = 30
- icon_state = "xeno_acid_strong"
- bullet_color = COLOR_ASSEMBLY_YELLOW
-
-/datum/ammo/xeno/acid/heavy/drop_nade(turf/T) //Leaves behind an acid pool; defaults to 1-3 seconds.
- if(T.density)
- return
- new /obj/effect/xenomorph/spray/strong(T, puddle_duration, puddle_acid_damage)
-
-/datum/ammo/xeno/acid/heavy/passthrough //Praetorian
- flags_ammo_behavior = AMMO_XENO|AMMO_EXPLOSIVE|AMMO_SKIPS_ALIENS
-
-/datum/ammo/xeno/acid/heavy/turret
- damage = 20
- name = "acid turret splash"
- shell_speed = 2
- max_range = 9
- icon_state = "xeno_acid_weak"
- bullet_color = COLOR_PALE_GREEN_GRAY
-
-/datum/ammo/xeno/acid/heavy/turret/drop_nade(turf/T) //Leaves behind an acid pool; defaults to 1-3 seconds.
- if(T.density)
- return
- new /obj/effect/xenomorph/spray/weak(T, puddle_duration, puddle_acid_damage)
-
-
-/datum/ammo/xeno/acid/heavy/on_hit_mob(mob/M, obj/projectile/P)
- var/turf/T = get_turf(M)
- drop_nade(T.density ? P.loc : T)
-
-/datum/ammo/xeno/acid/heavy/on_hit_obj(obj/O, obj/projectile/P)
- drop_nade(O.density ? P.loc : get_turf(O))
-
-/datum/ammo/xeno/acid/heavy/on_hit_turf(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-/datum/ammo/xeno/acid/heavy/do_at_max_range(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-///For the Spitter's Scatterspit ability
-/datum/ammo/xeno/acid/heavy/scatter
- damage = 20
- flags_ammo_behavior = AMMO_XENO|AMMO_EXPLOSIVE|AMMO_SKIPS_ALIENS
- bonus_projectiles_type = /datum/ammo/xeno/acid/heavy/scatter
- bonus_projectiles_amount = 6
- bonus_projectiles_scatter = 2
- max_range = 8
- puddle_duration = 1 SECONDS //Lasts 2-4 seconds
- icon_state = "xeno_acid_normal"
- bullet_color = COLOR_VERY_PALE_LIME_GREEN
-
-/datum/ammo/xeno/acid/heavy/scatter/drop_nade(turf/T) //Leaves behind an acid pool; defaults to 1-3 seconds.
- if(T.density)
- return
- new /obj/effect/xenomorph/spray(T, puddle_duration, puddle_acid_damage)
-
-/datum/ammo/xeno/acid/heavy/scatter/praetorian
- max_range = 5
- damage = 15
- puddle_duration = 0.5 SECONDS
- bonus_projectiles_amount = 3
-
-/datum/ammo/xeno/boiler_gas
- name = "glob of gas"
- icon_state = "boiler_gas2"
- ping = "ping_x"
- ///Key used for icon stuff during bombard ammo selection.
- var/icon_key = BOILER_GLOB_NEURO
- ///This text will show up when a boiler selects this ammo. Span proc should be applied when this var is used.
- var/select_text = "We will now fire neurotoxic gas. This is nonlethal."
- flags_ammo_behavior = AMMO_XENO|AMMO_SKIPS_ALIENS|AMMO_EXPLOSIVE
- var/danger_message = span_danger("A glob of acid lands with a splat and explodes into noxious fumes!")
- armor_type = BIO
- accuracy_var_high = 10
- max_range = 30
- damage = 50
- damage_type = STAMINA
- damage_falloff = 0
- penetration = 40
- bullet_color = BOILER_LUMINOSITY_AMMO_NEUROTOXIN_COLOR
- reagent_transfer_amount = 30
- ///On a direct hit, how long is the target paralyzed?
- var/hit_paralyze_time = 1 SECONDS
- ///On a direct hit, how much do the victim's eyes get blurred?
- var/hit_eye_blur = 11
- ///On a direct hit, how much drowsyness gets added to the target?
- var/hit_drowsyness = 12
- ///Base spread range
- var/fixed_spread_range = 4
- ///Which type is the smoke we leave on passed tiles, provided the projectile has AMMO_LEAVE_TURF enabled?
- var/passed_turf_smoke_type = /datum/effect_system/smoke_spread/xeno/neuro/light
- ///We're going to reuse one smoke spread system repeatedly to cut down on processing.
- var/datum/effect_system/smoke_spread/xeno/trail_spread_system
-
-/datum/ammo/xeno/boiler_gas/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
- if(isxeno(firer))
- var/mob/living/carbon/xenomorph/X = firer
- trail_spread_system.strength = X.xeno_caste.bomb_strength
- trail_spread_system.set_up(0, T)
- trail_spread_system.start()
-
-/**
- * Loads a trap with a gas cloud depending on current glob type
- * Called when something with a boiler glob as current ammo interacts with an empty resin trap.
- * * Args:
- * * trap: The trap being loaded
- * * user_xeno: The xeno interacting with the trap
- * * Returns: TRUE on success, FALSE on failure.
-**/
-/datum/ammo/xeno/boiler_gas/proc/enhance_trap(obj/structure/xeno/trap/trap, mob/living/carbon/xenomorph/user_xeno)
- if(!do_after(user_xeno, 2 SECONDS, NONE, trap))
- return FALSE
- trap.set_trap_type(TRAP_SMOKE_NEURO)
- trap.smoke = new /datum/effect_system/smoke_spread/xeno/neuro/medium
- trap.smoke.set_up(2, get_turf(trap))
- return TRUE
-
-/datum/ammo/xeno/boiler_gas/New()
- . = ..()
- if((flags_ammo_behavior & AMMO_LEAVE_TURF) && passed_turf_smoke_type)
- trail_spread_system = new passed_turf_smoke_type(only_once = FALSE)
-
-/datum/ammo/xeno/boiler_gas/Destroy()
- if(trail_spread_system)
- QDEL_NULL(trail_spread_system)
- return ..()
-
-///Set up the list of reagents the spit transfers upon impact
-/datum/ammo/xeno/boiler_gas/proc/set_reagents()
- spit_reagents = list(/datum/reagent/toxin/xeno_neurotoxin = reagent_transfer_amount)
-
-/datum/ammo/xeno/boiler_gas/on_hit_mob(mob/living/victim, obj/projectile/proj)
- var/turf/target_turf = get_turf(victim)
- drop_nade(target_turf.density ? proj.loc : target_turf, proj.firer)
-
- if(!istype(victim) || victim.stat == DEAD || victim.issamexenohive(proj.firer))
- return
-
- victim.Paralyze(hit_paralyze_time)
- victim.blur_eyes(hit_eye_blur)
- victim.adjustDrowsyness(hit_drowsyness)
-
- if(!reagent_transfer_amount || !iscarbon(victim))
- return
-
- var/mob/living/carbon/carbon_victim = victim
- set_reagents()
- for(var/reagent_id in spit_reagents)
- spit_reagents[reagent_id] = carbon_victim.modify_by_armor(spit_reagents[reagent_id], armor_type, penetration, proj.def_zone)
-
- carbon_victim.reagents.add_reagent_list(spit_reagents)
-
-/datum/ammo/xeno/boiler_gas/on_hit_obj(obj/O, obj/projectile/P)
- if(ismecha(O))
- P.damage *= 7 //Globs deal much higher damage to mechs.
- var/turf/target_turf = get_turf(O)
- drop_nade(O.density ? P.loc : target_turf, P.firer)
-
-/datum/ammo/xeno/boiler_gas/on_hit_turf(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T, P.firer) //we don't want the gas globs to land on dense turfs, they block smoke expansion.
-
-/datum/ammo/xeno/boiler_gas/do_at_max_range(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T, P.firer)
-
-/datum/ammo/xeno/boiler_gas/set_smoke()
- smoke_system = new /datum/effect_system/smoke_spread/xeno/neuro()
-
-/datum/ammo/xeno/boiler_gas/drop_nade(turf/T, atom/firer, range = 1)
- set_smoke()
- if(isxeno(firer))
- var/mob/living/carbon/xenomorph/X = firer
- smoke_system.strength = X.xeno_caste.bomb_strength
- range = fixed_spread_range
- smoke_system.set_up(range, T)
- smoke_system.start()
- smoke_system = null
- T.visible_message(danger_message)
-
-/datum/ammo/xeno/boiler_gas/corrosive
- name = "glob of acid"
- icon_state = "boiler_gas"
- sound_hit = "acid_hit"
- sound_bounce = "acid_bounce"
- icon_key = BOILER_GLOB_ACID
- select_text = "We will now fire corrosive acid. This is lethal!"
- flags_ammo_behavior = AMMO_XENO|AMMO_SKIPS_ALIENS|AMMO_EXPLOSIVE
- armor_type = ACID
- danger_message = span_danger("A glob of acid lands with a splat and explodes into corrosive bile!")
- damage = 50
- damage_type = BURN
- penetration = 40
- bullet_color = BOILER_LUMINOSITY_AMMO_CORROSIVE_COLOR
- hit_paralyze_time = 1 SECONDS
- hit_eye_blur = 1
- hit_drowsyness = 1
- reagent_transfer_amount = 0
-
-/datum/ammo/xeno/boiler_gas/corrosive/enhance_trap(obj/structure/xeno/trap/trap, mob/living/carbon/xenomorph/user_xeno)
- if(!do_after(user_xeno, 3 SECONDS, NONE, trap))
- return FALSE
- trap.set_trap_type(TRAP_SMOKE_ACID)
- trap.smoke = new /datum/effect_system/smoke_spread/xeno/acid
- trap.smoke.set_up(1, get_turf(trap))
- return TRUE
-
-/datum/ammo/xeno/boiler_gas/corrosive/on_shield_block(mob/victim, obj/projectile/proj)
- airburst(victim, proj)
-
-/datum/ammo/xeno/boiler_gas/corrosive/set_smoke()
- smoke_system = new /datum/effect_system/smoke_spread/xeno/acid()
-
-/datum/ammo/xeno/boiler_gas/lance
- name = "pressurized glob of gas"
- icon_key = BOILER_GLOB_NEURO_LANCE
- select_text = "We will now fire a pressurized neurotoxic lance. This is barely nonlethal."
- ///As opposed to normal globs, this will pass by the target tile if they hit nothing.
- flags_ammo_behavior = AMMO_XENO|AMMO_SKIPS_ALIENS|AMMO_LEAVE_TURF
- danger_message = span_danger("A pressurized glob of acid lands with a nasty splat and explodes into noxious fumes!")
- max_range = 40
- damage = 75
- penetration = 60
- reagent_transfer_amount = 55
- passed_turf_smoke_type = /datum/effect_system/smoke_spread/xeno/neuro/light
- hit_paralyze_time = 2 SECONDS
- hit_eye_blur = 16
- hit_drowsyness = 18
- fixed_spread_range = 2
- accuracy = 100
- accurate_range = 30
- shell_speed = 1.5
-
-/datum/ammo/xeno/boiler_gas/corrosive/lance
- name = "pressurized glob of acid"
- icon_key = BOILER_GLOB_ACID_LANCE
- select_text = "We will now fire a pressurized corrosive lance. This lethal!"
- ///As opposed to normal globs, this will pass by the target tile if they hit nothing.
- flags_ammo_behavior = AMMO_XENO|AMMO_SKIPS_ALIENS|AMMO_LEAVE_TURF
- danger_message = span_danger("A pressurized glob of acid lands with a concerning hissing sound and explodes into corrosive bile!")
- max_range = 40
- damage = 75
- penetration = 60
- passed_turf_smoke_type = /datum/effect_system/smoke_spread/xeno/acid/light
- hit_paralyze_time = 1.5 SECONDS
- hit_eye_blur = 4
- hit_drowsyness = 2
- fixed_spread_range = 2
- accuracy = 100
- accurate_range = 30
- shell_speed = 1.5
-
-/datum/ammo/xeno/hugger
- name = "hugger ammo"
- ping = ""
- flags_ammo_behavior = AMMO_XENO
- damage = 0
- max_range = 6
- shell_speed = 1
- bullet_color = ""
- icon_state = "facehugger"
- ///The type of hugger thrown
- var/obj/item/clothing/mask/facehugger/hugger_type = /obj/item/clothing/mask/facehugger
-
-/datum/ammo/xeno/hugger/on_hit_mob(mob/M, obj/projectile/proj)
- var/obj/item/clothing/mask/facehugger/hugger = new hugger_type(get_turf(M), hivenumber)
- hugger.go_idle()
-
-/datum/ammo/xeno/hugger/on_hit_obj(obj/O, obj/projectile/proj)
- var/obj/item/clothing/mask/facehugger/hugger = new hugger_type(get_turf(O), hivenumber)
- hugger.go_idle()
-
-/datum/ammo/xeno/hugger/on_hit_turf(turf/T, obj/projectile/P)
- var/obj/item/clothing/mask/facehugger/hugger = new hugger_type(T.density ? P.loc : T, hivenumber)
- hugger.go_idle()
-
-/datum/ammo/xeno/hugger/do_at_max_range(turf/T, obj/projectile/P)
- var/obj/item/clothing/mask/facehugger/hugger = new hugger_type(T.density ? P.loc : T, hivenumber)
- hugger.go_idle()
-
-/datum/ammo/xeno/hugger/slash
- hugger_type = /obj/item/clothing/mask/facehugger/combat/slash
-
-/datum/ammo/xeno/hugger/neuro
- hugger_type = /obj/item/clothing/mask/facehugger/combat/neuro
-
-/datum/ammo/xeno/hugger/resin
- hugger_type = /obj/item/clothing/mask/facehugger/combat/resin
-
-/datum/ammo/xeno/hugger/acid
- hugger_type = /obj/item/clothing/mask/facehugger/combat/acid
-
-/*
-//================================================
- Misc Ammo
-//================================================
-*/
-
-/datum/ammo/bullet/pepperball
- name = "pepperball"
- hud_state = "pepperball"
- hud_state_empty = "pepperball_empty"
- flags_ammo_behavior = AMMO_BALLISTIC
- accurate_range = 15
- damage_type = STAMINA
- armor_type = BIO
- damage = 1
- damage_falloff = 0
- penetration = 0
- shrapnel_chance = 0
- ///percentage of xenos total plasma to drain when hit by a pepperball
- var/drain_multiplier = 0.05
- ///Flat plasma to drain, unaffected by caste plasma amount.
- var/plasma_drain = 25
-
-/datum/ammo/bullet/pepperball/on_hit_mob(mob/living/victim, obj/projectile/proj)
- if(isxeno(victim))
- var/mob/living/carbon/xenomorph/X = victim
- X.use_plasma(drain_multiplier * X.xeno_caste.plasma_max * X.xeno_caste.plasma_regen_limit)
- X.use_plasma(plasma_drain)
-
-/datum/ammo/bullet/pepperball/pepperball_mini
- damage = 1
- drain_multiplier = 0.03
- plasma_drain = 15
-
-/datum/ammo/alloy_spike
- name = "alloy spike"
- ping = "ping_s"
- icon_state = "MSpearFlight"
- sound_hit = "alloy_hit"
- sound_armor = "alloy_armor"
- sound_bounce = "alloy_bounce"
- armor_type = BULLET
- accuracy = 20
- accurate_range = 15
- max_range = 15
- damage = 40
- penetration = 50
- shrapnel_chance = 75
-
-/datum/ammo/flamethrower
- name = "flame"
- icon_state = "pulse0"
- hud_state = "flame"
- hud_state_empty = "flame_empty"
- damage_type = BURN
- flags_ammo_behavior = AMMO_INCENDIARY|AMMO_FLAME|AMMO_EXPLOSIVE
- armor_type = FIRE
- max_range = 7
- damage = 31
- damage_falloff = 0
- incendiary_strength = 30 //Firestacks cap at 20, but that's after armor.
- bullet_color = LIGHT_COLOR_FIRE
- var/fire_color = "red"
- var/burntime = 17
- var/burnlevel = 31
-
-/datum/ammo/flamethrower/drop_flame(turf/T)
- if(!istype(T))
- return
- T.ignite(burntime, burnlevel, fire_color)
-
-/datum/ammo/flamethrower/on_hit_mob(mob/M, obj/projectile/P)
- drop_flame(get_turf(M))
-
-/datum/ammo/flamethrower/on_hit_obj(obj/O, obj/projectile/P)
- drop_flame(get_turf(O))
-
-/datum/ammo/flamethrower/on_hit_turf(turf/T, obj/projectile/P)
- drop_flame(get_turf(T))
-
-/datum/ammo/flamethrower/do_at_max_range(turf/T, obj/projectile/P)
- drop_flame(get_turf(T))
-
-/datum/ammo/flamethrower/tank_flamer/drop_flame(turf/T)
- if(!istype(T))
- return
- flame_radius(2, T)
-
-/datum/ammo/flamethrower/mech_flamer/drop_flame(turf/T)
- if(!istype(T))
- return
- flame_radius(1, T)
-
-/datum/ammo/flamethrower/blue
- name = "blue flame"
- hud_state = "flame_blue"
- max_range = 7
- fire_color = "blue"
- burntime = 40
- burnlevel = 46
- bullet_color = COLOR_NAVY
-
-/datum/ammo/water
- name = "water"
- icon_state = "pulse1"
- hud_state = "water"
- hud_state_empty = "water_empty"
- damage = 0
- shell_speed = 1
- damage_type = BURN
- flags_ammo_behavior = AMMO_EXPLOSIVE
- bullet_color = null
-
-/datum/ammo/water/proc/splash(turf/extinguished_turf, splash_direction)
- var/obj/flamer_fire/current_fire = locate(/obj/flamer_fire) in extinguished_turf
- if(current_fire)
- qdel(current_fire)
- for(var/mob/living/mob_caught in extinguished_turf)
- mob_caught.ExtinguishMob()
- new /obj/effect/temp_visual/dir_setting/water_splash(extinguished_turf, splash_direction)
-
-/datum/ammo/water/on_hit_mob(mob/M, obj/projectile/P)
- splash(get_turf(M), P.dir)
-
-/datum/ammo/water/on_hit_obj(obj/O, obj/projectile/P)
- splash(get_turf(O), P.dir)
-
-/datum/ammo/water/on_hit_turf(turf/T, obj/projectile/P)
- splash(get_turf(T), P.dir)
-
-/datum/ammo/water/do_at_max_range(turf/T, obj/projectile/P)
- splash(get_turf(T), P.dir)
-
-/datum/ammo/rocket/toy
- name = "\improper toy rocket"
- damage = 1
-
-/datum/ammo/rocket/toy/on_hit_mob(mob/M,obj/projectile/P)
- to_chat(M, "NO BUGS")
-
-/datum/ammo/rocket/toy/on_hit_obj(obj/O,obj/projectile/P)
- return
-
-/datum/ammo/rocket/toy/on_hit_turf(turf/T,obj/projectile/P)
- return
-
-/datum/ammo/rocket/toy/do_at_max_range(turf/T, obj/projectile/P)
- return
-
-/datum/ammo/grenade_container
- name = "grenade shell"
- ping = null
- damage_type = BRUTE
- var/nade_type = /obj/item/explosive/grenade
- icon_state = "grenade"
- armor_type = BOMB
- damage = 15
- accuracy = 15
- max_range = 10
-
-/datum/ammo/grenade_container/on_hit_mob(mob/M, obj/projectile/P)
- drop_nade(get_turf(P))
-
-/datum/ammo/grenade_container/on_hit_obj(obj/O, obj/projectile/P)
- drop_nade(O.density ? P.loc : O.loc)
-
-/datum/ammo/grenade_container/on_hit_turf(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-/datum/ammo/grenade_container/do_at_max_range(turf/T, obj/projectile/P)
- drop_nade(T.density ? P.loc : T)
-
-/datum/ammo/grenade_container/drop_nade(turf/T)
- var/obj/item/explosive/grenade/G = new nade_type(T)
- G.visible_message(span_warning("\A [G] lands on [T]!"))
- G.det_time = 10
- G.activate()
-
-/datum/ammo/grenade_container/smoke
- name = "smoke grenade shell"
- nade_type = /obj/item/explosive/grenade/smokebomb
- icon_state = "smoke_shell"
-
-/datum/ammo/grenade_container/ags_grenade
- name = "grenade shell"
- flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_IFF
- icon_state = "grenade_projectile"
- hud_state = "grenade_he"
- hud_state_empty = "grenade_empty"
- handful_icon_state = "40mm_grenade"
- handful_amount = 1
- max_range = 21
- nade_type = /obj/item/explosive/grenade/ags
-
-/datum/ammo/grenade_container/ags_grenade/flare
- hud_state = "grenade_dummy"
- nade_type = /obj/item/explosive/grenade/flare
-
-/datum/ammo/grenade_container/ags_grenade/cloak
- hud_state = "grenade_hide"
- nade_type = /obj/item/explosive/grenade/smokebomb/cloak/ags
-
-/datum/ammo/grenade_container/ags_grenade/tanglefoot
- hud_state = "grenade_drain"
- nade_type = /obj/item/explosive/grenade/smokebomb/drain/agls
-
-/*
-//================================================
- SH-Q6 AMMO DATUMS
-//================================================
-*/
-
-/datum/ammo/bullet/shotgun/buckshot/shq6
- name = "shotgun buckshot shell"
- handful_icon_state = "shotgun buckshot shell"
- icon_state = "buckshot"
- hud_state = "shotgun_buckshot"
- bonus_projectiles_type = /datum/ammo/bullet/shotgun/spread
- bonus_projectiles_amount = 5
- bonus_projectiles_scatter = 3
- accuracy_var_low = 9
- accuracy_var_high = 9
- accurate_range = 4
- max_range = 10
- damage = 40
- sundering = 2
- damage_falloff = 4
-
-/datum/ammo/bullet/shotgun/buckshot/shq6/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, knockback = 1, slowdown = 1, max_range = 3)
-
-/datum/ammo/bullet/shotgun/slug/shq6
- name = "shotgun slug"
- handful_icon_state = "shotgun slug"
- hud_state = "shotgun_slug"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- shell_speed = 3
- max_range = 15
- damage = 100
- penetration = 30
- sundering = 3
- damage_falloff = 3
-
-/datum/ammo/bullet/shotgun/slug/shq6/on_hit_mob(mob/M,obj/projectile/P)
- staggerstun(M, P, slowdown = 2, max_range = 5)
-
-/datum/ammo/bullet/shotgun/incendiary/shq6
- name = "incendiary slug"
- handful_icon_state = "incendiary slug"
- hud_state = "shotgun_fire"
- damage_type = BRUTE
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY|AMMO_SUNDERING
- max_range = 15
- damage = 70
- penetration = 15
- sundering = 1
- bullet_color = COLOR_TAN_ORANGE
-
-/datum/ammo/bullet/shotgun/incendiary/shq6/on_hit_mob(mob/M, obj/projectile/P)
- staggerstun(M, P, knockback = 1)
-
-/datum/ammo/bullet/shotgun/flechette/shq6
- name = "shotgun flechette shell"
- handful_icon_state = "shotgun flechette shell"
- icon_state = "flechette"
- hud_state = "shotgun_flechette"
- flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
- bonus_projectiles_type = /datum/ammo/bullet/shotgun/flechette/flechette_spread/shq6
- bonus_projectiles_amount = 2
- bonus_projectiles_scatter = 3
- accuracy_var_low = 8
- accuracy_var_high = 8
- max_range = 15
- damage = 50
- damage_falloff = 3
- penetration = 40
- sundering = 4
-
-/datum/ammo/bullet/shotgun/flechette/flechette_spread/shq6
- name = "additional flechette"
- damage = 40
- penetration = 40
- sundering = 2
- damage_falloff = 3
-
-/*
-//================================================
- Yautja
-//================================================
-*/
-/datum/ammo/energy/yautja
- accurate_range = 12
- shell_speed = 2
- bullet_color = COLOR_STRONG_VIOLET
- damage_type = BURN
- flags_ammo_behavior = AMMO_IGNORE_RESIST
-
- hud_state = "plasma"
- hud_state_empty = "electrothermal_empty"
-
-/datum/ammo/energy/yautja/alloy_spike
- name = "alloy spike"
- ping = "ping_s"
- icon_state = "MSpearFlight"
- hud_state = "alloy_spike"
- sound_hit = "alloy_hit"
- sound_armor = "alloy_armor"
- sound_bounce = "alloy_bounce"
- bullet_color = COLOR_MAGENTA
- armor_type = BULLET
- accuracy = 20
- accurate_range = 15
- max_range = 15
- damage = 40
- penetration = 50
- shrapnel_chance = 75
-
-/datum/ammo/energy/yautja/pistol
- name = "plasma pistol bolt"
- icon_state = "ion"
-
- hud_state = "plasma_pistol"
-
- bullet_color = COLOR_MAGENTA
- damage = 40
- shell_speed = 1.5
-
-/datum/ammo/energy/yautja/caster
- name = "root caster bolt"
- icon_state = "ion"
-
-/datum/ammo/energy/yautja/caster/stun
- name = "low power stun bolt"
- var/stun_time = 5 SECONDS
- hud_state = "plasma_pistol"
-
- bullet_color = COLOR_VIOLET
- damage = 0
- flags_ammo_behavior = AMMO_ENERGY|AMMO_IGNORE_RESIST
-
-/datum/ammo/energy/yautja/caster/stun/on_hit_mob(mob/M, obj/projectile/P)
- var/mob/living/carbon/C = M
- if(istype(C))
- if(isyautja(C) || ispredalien(C))
- return
- to_chat(C, span_danger("An electric shock ripples through your body, freezing you in place!"))
- log_attack("[key_name(C)] was stunned by a high power stun bolt from [key_name(P.firer)] at [get_area(P)]")
-
- if(ishuman(C))
- var/mob/living/carbon/human/H = C
- H.apply_effect(stun_time + 10 SECONDS, WEAKEN)
- else
- C.apply_effect(stun_time, WEAKEN)
-
- C.apply_effect(stun_time, STUN)
- ..()
-
-/datum/ammo/energy/yautja/caster/bolt
- name = "plasma bolt"
- icon_state = "pulse1"
- flags_ammo_behavior = AMMO_IGNORE_RESIST
- bullet_color = COLOR_BRIGHT_BLUE
- shell_speed = 3
- damage = 35
-
-/datum/ammo/energy/yautja/caster/bolt/stun
- name = "high power stun bolt"
- icon_state = "pred_stun"
- var/stun_time = 20 SECONDS
- bullet_color = COLOR_MAGENTA
-
- hud_state = "plasma_rifle"
-
- damage = 0
- flags_ammo_behavior = AMMO_ENERGY|AMMO_IGNORE_RESIST
-
-/datum/ammo/energy/yautja/caster/bolt/stun/on_hit_mob(mob/M, obj/projectile/P)
- var/mob/living/carbon/C = M
- if(istype(C))
- if(isyautja(C) || ispredalien(C))
- return
- to_chat(C, span_danger("An electric shock ripples through your body, freezing you in place!"))
- log_attack("[key_name(C)] was stunned by a high power stun bolt from [key_name(P.firer)] at [get_area(P)]")
-
- if(ishuman(C))
- var/mob/living/carbon/human/H = C
- H.apply_effect(stun_time + 10 SECONDS, WEAKEN)
- else
- C.apply_effect(stun_time, WEAKEN)
-
- C.apply_effect(stun_time, STUN)
- ..()
-
-/datum/ammo/energy/yautja/caster/sphere
- name = "plasma eradicator"
- icon_state = "bluespace"
- bullet_color = COLOR_BRIGHT_BLUE
- flags_ammo_behavior = AMMO_EXPLOSIVE
- shell_speed = 2
- accuracy = 40
-
- hud_state = "plasma_sphere"
-
- damage = 55
-
- accurate_range = 8
- max_range = 8
-
-/datum/ammo/energy/yautja/caster/sphere/on_hit_mob(mob/M, obj/projectile/P)
- cell_explosion(get_turf(M), 50, 25)
-
-/datum/ammo/energy/yautja/caster/sphere/on_hit_turf(turf/T, obj/projectile/P)
- cell_explosion(get_turf(T), 50, 25)
-
-/datum/ammo/energy/yautja/caster/sphere/on_hit_obj(obj/O, obj/projectile/P)
- cell_explosion(get_turf(O), 50, 25)
-
-/datum/ammo/energy/yautja/caster/sphere/do_at_max_range(obj/projectile/P)
- cell_explosion(get_turf(P), 50, 25)
-
-
-/datum/ammo/energy/yautja/caster/sphere/stun
- name = "plasma immobilizer"
- bullet_color = COLOR_MAGENTA
- damage = 0
- flags_ammo_behavior = AMMO_ENERGY|AMMO_IGNORE_RESIST
- hud_state = "plasma_rifle_blast"
- accurate_range = 20
- max_range = 20
-
- var/stun_range = 4
- var/stun_time = 6 SECONDS
-
-/datum/ammo/energy/yautja/caster/sphere/stun/on_hit_mob(mob/M, obj/projectile/P)
- do_area_stun(P)
-
-/datum/ammo/energy/yautja/caster/sphere/stun/on_hit_turf(turf/T, obj/projectile/P)
- do_area_stun(P)
-
-/datum/ammo/energy/yautja/caster/sphere/stun/on_hit_obj(obj/O, obj/projectile/P)
- do_area_stun(P)
-
-/datum/ammo/energy/yautja/caster/sphere/stun/do_at_max_range(obj/projectile/P)
- do_area_stun(P)
-
-/datum/ammo/energy/yautja/caster/sphere/stun/proc/do_area_stun(obj/projectile/P)
- playsound(P, 'sound/weapons/wave.ogg', 75, 1, 25)
- for(var/mob/living/carbon/M in view(stun_range, get_turf(P)))
- var/f_stun_time = stun_time
- log_attack("[key_name(M)] was stunned by a plasma immobilizer from [key_name(P.firer)] at [get_area(P)]")
- if(isyautja(M))
- f_stun_time -= 2 SECONDS
- if(ispredalien(M))
- continue
- to_chat(M, span_danger("A powerful electric shock ripples through your body, freezing you in place!"))
- M.apply_effect(f_stun_time, STUN)
-
- if(ishuman(M))
- var/mob/living/carbon/human/H = M
- H.apply_effect(f_stun_time, WEAKEN)
- else
- M.apply_effect(f_stun_time, WEAKEN)
-
-/datum/ammo/energy/yautja/rifle/bolt
- name = "plasma rifle bolt"
- icon_state = "ion"
- damage_type = BURN
- flags_ammo_behavior = AMMO_IGNORE_RESIST
-
- hud_state = "plasma_rifle"
-
- damage = 70
- penetration = 55
-
-//////////////////////////////////////////////////
-////////////////////Shrapnel//////////////////////
-//////////////////////////////////////////////////
-
-/datum/ammo/bullet/shrapnel
- name = "shrapnel"
- icon_state = "buckshot_shrapnel"
- icon = 'icons/obj/items/projectiles.dmi'
- accurate_range_min = 5
- flags_ammo_behavior = AMMO_BALLISTIC
- accuracy = 15
- accurate_range = 32
- max_range = 8
- damage = 25
- damage_falloff = 8
- penetration = 0
- shell_speed = 3
- shrapnel_chance = 15
-
-/datum/ammo/bullet/shrapnel/metal
- name = "metal shrapnel"
- icon_state = "shrapnelshot_bit"
- shell_speed = 1.5
- damage = 30
- shrapnel_chance = 25
- accuracy = 40
- penetration = 0
-
-/datum/ammo/bullet/shrapnel/light // weak shrapnel
- name = "light shrapnel"
- icon_state = "shrapnel_light"
- damage = 10
- penetration = 0
- shell_speed = 2
- shrapnel_chance = 0
-
-/datum/ammo/bullet/shrapnel/light/human
- name = "human bone fragments"
- icon_state = "shrapnel_human"
- shrapnel_chance = 50
- shrapnel_type = /obj/item/shard/shrapnel/bone_chips/human
-
-/datum/ammo/bullet/shrapnel/light/human/var1 // sprite variants
- icon_state = "shrapnel_human1"
-
-/datum/ammo/bullet/shrapnel/light/human/var2 // sprite variants
- icon_state = "shrapnel_human2"
-
-/datum/ammo/bullet/shrapnel/light/xeno
- name = "alien bone fragments"
- icon_state = "shrapnel_xeno"
- shrapnel_chance = 50
- shrapnel_type = /obj/item/shard/shrapnel/bone_chips/xeno
-
-/datum/ammo/bullet/shrapnel/spall // weak shrapnel
- name = "spall"
- icon_state = "shrapnel_light"
- damage = 10
- penetration = 0
- shell_speed = 2
- shrapnel_chance = 0
-
-/datum/ammo/bullet/shrapnel/light/glass
- name = "glass shrapnel"
- icon_state = "shrapnel_glass"
diff --git a/code/modules/projectiles/ammo_datums/_ammo_datums.dm b/code/modules/projectiles/ammo_datums/_ammo_datums.dm
new file mode 100644
index 00000000000..78bc3cee26b
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/_ammo_datums.dm
@@ -0,0 +1,324 @@
+#define DEBUG_STAGGER_SLOWDOWN 0
+
+/datum/ammo
+ var/name = "generic bullet"
+ var/icon = 'icons/obj/items/projectiles.dmi'
+ var/icon_state = "bullet"
+ ///used in icons/obj/items/ammo for use in generating handful sprites
+ var/handful_icon_state = "bullet"
+ ///how much of this ammo you can carry in a handful
+ var/handful_amount = 8
+ ///Bullet type on the Ammo HUD
+ var/hud_state = "unknown"
+ var/hud_state_empty = "unknown"
+ ///The icon that is displayed when the bullet bounces off something.
+ var/ping = "ping_b"
+ ///When it deals damage.
+ var/sound_hit
+ ///When it's blocked by human armor.
+ var/sound_armor
+ ///When it misses someone.
+ var/sound_miss
+ ///When it bounces off something.
+ var/sound_bounce
+
+ ///This is added to the bullet's base accuracy
+ var/accuracy = 0
+ ///How much the accuracy varies when fired
+ var/accuracy_var_low = 1
+ var/accuracy_var_high = 1
+ ///For most guns, this is where the bullet dramatically looses accuracy. Not for snipers though
+ var/accurate_range = 5
+ ///Snipers use this to simulate poor accuracy at close ranges
+ var/accurate_range_min = 0
+ ///Weapons will get a large accuracy buff at this short range
+ var/point_blank_range = 0
+ ///This will de-increment a counter on the bullet
+ var/max_range = 20
+ ///How much the ammo scatters when burst fired, added to gun scatter, along with other mods
+ var/scatter = 0
+ ///This is the base damage of the bullet as it is fired
+ var/damage = 0
+ ///How much damage the bullet loses per turf traveled
+ var/damage_falloff = 1
+ ///BRUTE, BURN, TOX, OXY, CLONE are the only things that should be in here
+ var/damage_type = BRUTE
+ ///How much armor it ignores before calculations take place
+ var/penetration = 0
+ ///How much extra penetration applies to xeno
+ var/additional_xeno_penetration = 0
+ ///The % chance it will imbed in a human
+ var/shrapnel_chance = 0
+ ///How fast the projectile moves
+ var/shell_speed = 2
+ ///Type path of the extra projectiles
+ var/bonus_projectiles_type
+ ///How many extra projectiles it shoots out. Works kind of like firing on burst, but all of the projectiles travel together
+ var/bonus_projectiles_amount = 0
+ ///Degrees scattered per two projectiles, each in a different direction.
+ var/bonus_projectiles_scatter = 8
+ ///How far the bullet can travel before incurring a chance of hitting barricades; normally 1.
+ var/barricade_clear_distance = 1
+ ///Does this have an override for the armor type the ammo should test? Bullet by default
+ var/armor_type = BULLET
+ ///How many stacks of sundering to apply to a mob on hit
+ var/sundering = 0
+ ///how much damage airbursts do to mobs around the target, multiplier of the bullet's damage
+ var/airburst_multiplier = 0.1
+ ///What kind of behavior the ammo has
+ var/flags_ammo_behavior = NONE
+ ///Determines what color our bullet will be when it flies
+ var/bullet_color = COLOR_WHITE
+ ///If this ammo is hitscan, the icon of beam coming out from the gun
+ var/hitscan_effect_icon = "beam"
+ ///A multiplier applied to piercing projectile, that reduces its damage/penetration/sundering on hit
+ var/on_pierce_multiplier = 1
+ ///greyscale config for the bullet items associated with the ammo
+ var/handful_greyscale_config = null
+ ///greyscale color for the bullet items associated with the ammo
+ var/handful_greyscale_colors = null
+ ///greyscale config for the projectile associated with the ammo
+ var/projectile_greyscale_config = null
+ ///greyscale color for the projectile associated with the ammo
+ var/projectile_greyscale_colors = null
+ ///Multiplier for deflagrate chance
+ var/deflagrate_multiplier = 1
+ ///Flat damage caused if fire_burst is triggered by deflagrate
+ var/fire_burst_damage = 10
+ ///Base fire stacks added on hit if the projectile has AMMO_INCENDIARY
+ var/incendiary_strength = 10
+ ///Embeding shrapnel type
+ var/shrapnel_type = /obj/item/shard/shrapnel
+
+/datum/ammo/proc/do_at_max_range(turf/T, obj/projectile/proj)
+ return
+
+///Does it do something special when shield blocked? Ie. a flare or grenade that still blows up.
+/datum/ammo/proc/on_shield_block(mob/M, obj/projectile/proj)
+ return
+
+///Special effects when hitting dense turfs.
+/datum/ammo/proc/on_hit_turf(turf/T, obj/projectile/proj)
+ return
+
+///Special effects when hitting mobs.
+/datum/ammo/proc/on_hit_mob(mob/M, obj/projectile/proj)
+ return
+
+///Special effects when hitting objects.
+/datum/ammo/proc/on_hit_obj(obj/O, obj/projectile/proj)
+ return
+
+///Special effects for leaving a turf. Only called if the projectile has AMMO_LEAVE_TURF enabled
+/datum/ammo/proc/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
+ return
+
+///Handles CC application on the victim
+/datum/ammo/proc/staggerstun(mob/victim, obj/projectile/proj, max_range = 5, stun = 0, weaken = 0, stagger = 0, slowdown = 0, knockback = 0, soft_size_threshold = 3, hard_size_threshold = 2)
+ if(!victim)
+ CRASH("staggerstun called without a mob target")
+ if(!isliving(victim))
+ return
+ if(get_dist_euclidean(proj.starting_turf, victim) > max_range)
+ return
+ var/impact_message = ""
+ if(isxeno(victim))
+ var/mob/living/carbon/xenomorph/xeno_victim = victim
+ if(xeno_victim.fortify) //If we're fortified we don't give a shit about staggerstun.
+ impact_message += span_xenodanger("Your fortified stance braces you against the impact.")
+ return
+
+ if(xeno_victim.endure) //Endure allows us to ignore staggerstun.
+ impact_message += span_xenodanger("You endure the impact from [proj], shrugging off its effects.")
+ return
+
+ if(xeno_victim.crest_defense) //Crest defense halves all effects, and protects us from the stun.
+ impact_message += span_xenodanger("Your crest protects you against some of the impact.")
+ slowdown *= 0.5
+ stagger *= 0.5
+ stun = 0
+
+ //Check for and apply hard CC.
+ if(hard_size_threshold >= victim.mob_size && (stun || weaken || knockback))
+ var/mob/living/living_victim = victim
+ if(living_victim.IsStun() || living_victim.IsParalyzed()) //Prevent chain stunning.
+ stun = 0
+ weaken = 0
+
+ if(stun || weaken)
+ var/list/stunlist = list(stun, weaken, stagger, slowdown)
+ if(SEND_SIGNAL(living_victim, COMSIG_LIVING_PROJECTILE_STUN, stunlist, armor_type, penetration))
+ stun = stunlist[1]
+ weaken = stunlist[2]
+ stagger = stunlist[3]
+ slowdown = stunlist[4]
+ living_victim.apply_effects(stun,weaken)
+
+ if(knockback)
+ if(isxeno(victim))
+ impact_message += span_xenodanger("The blast knocks you off your feet!")
+ else
+ impact_message += span_highdanger("The blast knocks you off your feet!")
+ victim.knockback(proj, knockback, 5)
+
+ //Check for and apply soft CC
+ if(iscarbon(victim))
+ var/mob/living/carbon/carbon_victim = victim
+ #if DEBUG_STAGGER_SLOWDOWN
+ to_chat(world, span_debuginfo("Damage: Initial stagger is: [target.IsStaggered()]"))
+ #endif
+ if(!HAS_TRAIT(carbon_victim, TRAIT_STAGGER_RESISTANT)) //Some mobs like the Queen are immune to projectile stagger
+ carbon_victim.adjust_stagger(stagger)
+ #if DEBUG_STAGGER_SLOWDOWN
+ to_chat(world, span_debuginfo("Damage: Final stagger is: [target.IsStaggered()]"))
+ #endif
+ #if DEBUG_STAGGER_SLOWDOWN
+ to_chat(world, span_debuginfo("Damage: Initial slowdown is: [target.slowdown]"))
+ #endif
+ carbon_victim.add_slowdown(slowdown)
+ #if DEBUG_STAGGER_SLOWDOWN
+ to_chat(world, span_debuginfo("Damage: Final slowdown is: [target.slowdown]"))
+ #endif
+ to_chat(victim, "[impact_message]") //Summarize all the bad shit that happened
+
+/datum/ammo/proc/airburst(atom/target, obj/projectile/proj)
+ if(!target || !proj)
+ CRASH("airburst() error: target [isnull(target) ? "null" : target] | proj [isnull(proj) ? "null" : proj]")
+ for(var/mob/living/carbon/victim in orange(1, target))
+ if(proj.firer == victim)
+ continue
+ victim.visible_message(span_danger("[victim] is hit by backlash from \a [proj.name]!"),
+ isxeno(victim) ? span_xenodanger("We are hit by backlash from \a [proj.name]!") : span_highdanger("You are hit by backlash from \a [proj.name]!"))
+ victim.apply_damage(proj.damage * proj.airburst_multiplier, proj.ammo.damage_type, blocked = armor_type, updating_health = TRUE)
+
+///handles the probability of a projectile hit to trigger fire_burst, based off actual damage done
+/datum/ammo/proc/deflagrate(atom/target, obj/projectile/proj)
+ if(!target || !proj)
+ CRASH("deflagrate() error: target [isnull(target) ? "null" : target] | proj [isnull(proj) ? "null" : proj]")
+ if(!istype(target, /mob/living))
+ return
+
+ var/mob/living/victim = target
+ var/deflagrate_chance = victim.modify_by_armor(proj.damage - (proj.distance_travelled * proj.damage_falloff), FIRE, proj.penetration) * deflagrate_multiplier
+ if(prob(deflagrate_chance))
+ new /obj/effect/temp_visual/shockwave(get_turf(victim), 2)
+ playsound(target, "incendiary_explosion", 40)
+ fire_burst(target, proj)
+
+///the actual fireblast triggered by deflagrate
+/datum/ammo/proc/fire_burst(atom/target, obj/projectile/proj)
+ if(!target || !proj)
+ CRASH("fire_burst() error: target [isnull(target) ? "null" : target] | proj [isnull(proj) ? "null" : proj]")
+ for(var/mob/living/carbon/victim in range(1, target))
+ if(victim == target)
+ victim.visible_message(span_danger("[victim] bursts into flames as they are deflagrated by \a [proj.name]!"))
+ else
+ victim.visible_message(span_danger("[victim] is scorched by [target] as they burst into flames!"),
+ isxeno(victim) ? span_xenodanger("We are scorched by [target] as they burst into flames!") : span_highdanger("you are scorched by [target] as they burst into flames!"))
+ //Damages the victims, inflicts brief stagger+slow, and ignites
+ victim.apply_damage(fire_burst_damage, BURN, blocked = FIRE, updating_health = TRUE)
+
+ staggerstun(victim, proj, 30, stagger = 1 SECONDS, slowdown = 0.5)
+ victim.adjust_fire_stacks(5)
+ victim.IgniteMob()
+
+/datum/ammo/proc/fire_bonus_projectiles(obj/projectile/main_proj, atom/shooter, atom/source, range, speed, angle, target, origin_override)
+ var/effect_icon = ""
+ var/proj_type = /obj/projectile
+ if(istype(main_proj, /obj/projectile/hitscan))
+ proj_type = /obj/projectile/hitscan
+ var/obj/projectile/hitscan/main_proj_hitscan = main_proj
+ effect_icon = main_proj_hitscan.effect_icon
+ for(var/i = 1 to bonus_projectiles_amount) //Want to run this for the number of bonus projectiles.
+ var/obj/projectile/new_proj = new proj_type(main_proj.loc, effect_icon)
+ if(bonus_projectiles_type)
+ new_proj.generate_bullet(bonus_projectiles_type)
+ else //If no bonus type is defined then the extra projectiles are the same as the main one.
+ new_proj.generate_bullet(src)
+
+ if(isgun(source))
+ var/obj/item/weapon/gun/gun = source
+ gun.apply_gun_modifiers(new_proj, target, shooter)
+
+ //Scatter here is how many degrees extra stuff deviate from the main projectile, first two the same amount, one to each side, and from then on the extra pellets keep widening the arc.
+ var/new_angle = angle + (main_proj.ammo.bonus_projectiles_scatter * ((i % 2) ? (-(i + 1) * 0.5) : (i * 0.5)))
+ if(new_angle < 0)
+ new_angle += 360
+ else if(new_angle > 360)
+ new_angle -= 360
+ new_proj.fire_at(target, shooter, source, range, speed, new_angle, TRUE, loc_override = origin_override)
+
+///A variant of Fire_bonus_projectiles without fixed scatter and no link between gun and bonus_projectile accuracy
+/datum/ammo/proc/fire_directionalburst(obj/projectile/main_proj, atom/shooter, atom/source, projectile_amount, range, speed, angle, target)
+ var/effect_icon = ""
+ var/proj_type = /obj/projectile
+ if(istype(main_proj, /obj/projectile/hitscan))
+ proj_type = /obj/projectile/hitscan
+ var/obj/projectile/hitscan/main_proj_hitscan = main_proj
+ effect_icon = main_proj_hitscan.effect_icon
+ for(var/i = 1 to projectile_amount) //Want to run this for the number of bonus projectiles.
+ var/obj/projectile/new_proj = new proj_type(main_proj.loc, effect_icon)
+ if(bonus_projectiles_type)
+ new_proj.generate_bullet(bonus_projectiles_type)
+ else //If no bonus type is defined then the extra projectiles are the same as the main one.
+ new_proj.generate_bullet(src)
+
+ if(isgun(source))
+ var/obj/item/weapon/gun/gun = source
+ gun.apply_gun_modifiers(new_proj, target, shooter)
+
+ //Scatter here is how many degrees extra stuff deviate from the main projectile's firing angle. Fully randomised with no 45 degree cap like normal bullets
+ var/f = (i-1)
+ var/new_angle = angle + (main_proj.ammo.bonus_projectiles_scatter * ((f % 2) ? (-(f + 1) * 0.5) : (f * 0.5)))
+ if(new_angle < 0)
+ new_angle += 360
+ if(new_angle > 360)
+ new_angle -= 360
+ new_proj.fire_at(target, main_proj.loc, source, range, speed, new_angle, TRUE)
+
+/datum/ammo/proc/drop_flame(turf/T)
+ if(!istype(T))
+ return
+ T.ignite(20, 20)
+
+/datum/ammo/proc/set_smoke()
+ return
+
+/datum/ammo/proc/drop_nade(turf/T)
+ return
+
+///called on projectile process() when AMMO_SPECIAL_PROCESS flag is active
+/datum/ammo/proc/ammo_process(obj/projectile/proj, damage)
+ CRASH("ammo_process called with unimplemented process!")
+
+///bounces the projectile by creating a new projectile and calculating an angle of reflection
+/datum/ammo/proc/reflect(turf/T, obj/projectile/proj, scatter_variance)
+ if(!bonus_projectiles_type)
+ return
+
+ var/new_range = proj.proj_max_range - proj.distance_travelled
+ if(new_range <= 0)
+ return
+
+ var/dir_to_proj = get_dir(T, proj)
+ if(ISDIAGONALDIR(dir_to_proj))
+ var/list/cardinals = list(turn(dir_to_proj, 45), turn(dir_to_proj, -45))
+ for(var/direction in cardinals)
+ var/turf/turf_to_check = get_step(T, direction)
+ if(turf_to_check.density)
+ cardinals -= direction
+ dir_to_proj = pick(cardinals)
+
+ var/perpendicular_angle = Get_Angle(T, get_step(T, dir_to_proj))
+ var/new_angle = (perpendicular_angle + (perpendicular_angle - proj.dir_angle - 180) + rand(-scatter_variance, scatter_variance))
+
+ if(new_angle < -360)
+ new_angle += 720 //north is 0 instead of 360
+ else if(new_angle < 0)
+ new_angle += 360
+ else if(new_angle > 360)
+ new_angle -= 360
+
+ bonus_projectiles_amount = 1
+ fire_bonus_projectiles(proj, T, proj.shot_from, new_range, proj.projectile_speed, new_angle, null, get_step(T, dir_to_proj))
+ bonus_projectiles_amount = 0
diff --git a/code/modules/projectiles/ammo_datums/artillery.dm b/code/modules/projectiles/ammo_datums/artillery.dm
new file mode 100644
index 00000000000..d579dcde64e
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/artillery.dm
@@ -0,0 +1,297 @@
+/datum/ammo/mortar
+ name = "80mm shell"
+ icon_state = "mortar"
+ flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_PASS_THROUGH_TURF|AMMO_PASS_THROUGH_MOVABLE
+ shell_speed = 0.75
+ damage = 0
+ penetration = 0
+ sundering = 0
+ accuracy = 1000
+ max_range = 1000
+ ping = null
+ bullet_color = COLOR_VERY_SOFT_YELLOW
+
+/datum/ammo/mortar/drop_nade(turf/T)
+ cell_explosion(T, 90, 30)
+
+/datum/ammo/mortar/do_at_max_range(turf/T, obj/projectile/P)
+ drop_nade(T)
+
+/datum/ammo/mortar/incend/drop_nade(turf/T)
+ cell_explosion(T, 45, 20)
+ flame_radius(4, T)
+ playsound(T, 'sound/weapons/guns/fire/flamethrower2.ogg', 35, 1, 4)
+
+/datum/ammo/mortar/knee
+ name = "50mm shell"
+ icon_state = "howi"
+ shell_speed = 0.75
+
+/datum/ammo/mortar/knee/drop_nade(turf/T)
+ cell_explosion(T, 80, 30)
+
+/datum/ammo/mortar/smoke
+ ///the smoke effect at the point of detonation
+ var/datum/effect_system/smoke_spread/smoketype = /datum/effect_system/smoke_spread/tactical
+
+/datum/ammo/mortar/smoke/drop_nade(turf/T)
+ var/datum/effect_system/smoke_spread/smoke = new smoketype()
+ explosion(T, 0, 0, 1, 0, 3, throw_range = 0)
+ playsound(T, 'sound/effects/smoke.ogg', 25, 1, 4)
+ smoke.set_up(10, T, 11)
+ smoke.start()
+
+/datum/ammo/mortar/smoke/plasmaloss
+ smoketype = /datum/effect_system/smoke_spread/plasmaloss
+
+/datum/ammo/mortar/flare/drop_nade(turf/T)
+ new /obj/effect/temp_visual/above_flare(T)
+ playsound(T, 'sound/weapons/guns/fire/flare.ogg', 50, 1, 4)
+
+/datum/ammo/mortar/howi
+ name = "150mm shell"
+ icon_state = "howi"
+
+/datum/ammo/mortar/howi/drop_nade(turf/T)
+ cell_explosion(T, 175, 50)
+
+/datum/ammo/mortar/howi/incend/drop_nade(turf/T)
+ cell_explosion(T, 45, 30)
+ flame_radius(5, T)
+ playsound(T, 'sound/weapons/guns/fire/flamethrower2.ogg', 35, 1, 4)
+
+/datum/ammo/mortar/smoke/howi
+ name = "150mm shell"
+ icon_state = "howi"
+
+/datum/ammo/mortar/smoke/howi/wp
+ smoketype = /datum/effect_system/smoke_spread/phosphorus
+
+/datum/ammo/mortar/smoke/howi/wp/drop_nade(turf/T)
+ var/datum/effect_system/smoke_spread/smoke = new smoketype()
+ explosion(T, 0, 0, 1, 0, 0, throw_range = 0)
+ playsound(T, 'sound/effects/smoke.ogg', 25, 1, 4)
+ smoke.set_up(6, T, 7)
+ smoke.start()
+ flame_radius(4, T)
+ flame_radius(1, T, burn_intensity = 45, burn_duration = 75, burn_damage = 15, fire_stacks = 75)
+
+/datum/ammo/mortar/smoke/howi/plasmaloss
+ smoketype = /datum/effect_system/smoke_spread/plasmaloss
+
+/datum/ammo/mortar/smoke/howi/plasmaloss/drop_nade(turf/T)
+ var/datum/effect_system/smoke_spread/smoke = new smoketype()
+ explosion(T, 0, 0, 5, 0, 0, throw_range = 0)
+ playsound(T, 'sound/effects/smoke.ogg', 25, 1, 4)
+ smoke.set_up(10, T, 11)
+ smoke.start()
+
+/datum/ammo/mortar/rocket
+ name = "rocket"
+ icon_state = "rocket"
+ shell_speed = 1.5
+
+/datum/ammo/mortar/rocket/drop_nade(turf/T)
+ cell_explosion(T, 175, 75)
+
+/datum/ammo/mortar/rocket/incend/drop_nade(turf/T)
+ cell_explosion(T, 50, 20)
+ flame_radius(5, T)
+ playsound(T, 'sound/weapons/guns/fire/flamethrower2.ogg', 35, 1, 4)
+
+/datum/ammo/mortar/rocket/minelayer/drop_nade(turf/T)
+ var/obj/item/explosive/mine/mine = new /obj/item/explosive/mine(T)
+ mine.deploy_mine(null, TGMC_LOYALIST_IFF)
+
+/datum/ammo/mortar/rocket/smoke
+ ///the smoke effect at the point of detonation
+ var/datum/effect_system/smoke_spread/smoketype = /datum/effect_system/smoke_spread/tactical
+
+/datum/ammo/mortar/rocket/smoke/drop_nade(turf/T)
+ var/datum/effect_system/smoke_spread/smoke = new smoketype()
+ explosion(T, 0, 0, 1, 0, 3, throw_range = 0)
+ playsound(T, 'sound/effects/smoke.ogg', 25, 1, 4)
+ smoke.set_up(10, T, 11)
+ smoke.start()
+
+/datum/ammo/mortar/rocket/mlrs
+ shell_speed = 2.5
+
+/datum/ammo/mortar/rocket/mlrs/drop_nade(turf/T)
+ cell_explosion(T, 70, 25)
+
+/datum/ammo/mortar/rocket/smoke/mlrs
+ shell_speed = 2.5
+ smoketype = /datum/effect_system/smoke_spread/mustard
+
+/datum/ammo/mortar/rocket/smoke/mlrs/drop_nade(turf/T)
+ var/datum/effect_system/smoke_spread/smoke = new smoketype()
+ explosion(T, 0, 0, 2, 0, 0, throw_range = 0)
+ playsound(T, 'sound/effects/smoke.ogg', 25, 1, 4)
+ smoke.set_up(5, T, 6)
+ smoke.start()
+
+/datum/ammo/bullet/atgun_spread
+ name = "Shrapnel"
+ icon_state = "flechette"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB
+ accuracy_var_low = 15
+ accuracy_var_high = 5
+ max_range = 6
+ damage = 30
+ penetration = 20
+ sundering = 3
+ damage_falloff = 0
+
+/datum/ammo/bullet/atgun_spread/incendiary
+ name = "incendiary flechette"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB|AMMO_INCENDIARY|AMMO_LEAVE_TURF
+ damage = 20
+ penetration = 10
+ sundering = 1.5
+
+/datum/ammo/bullet/atgun_spread/incendiary/on_hit_mob(mob/M, obj/projectile/proj)
+ return
+
+/datum/ammo/bullet/atgun_spread/incendiary/drop_flame(turf/T)
+ if(!istype(T))
+ return
+ T.ignite(5, 10)
+
+/datum/ammo/bullet/atgun_spread/incendiary/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
+ drop_flame(T)
+
+/datum/ammo/ags_shrapnel
+ name = "fragmentation grenade"
+ icon_state = "grenade_projectile"
+ hud_state = "grenade_frag"
+ hud_state_empty = "grenade_empty"
+ handful_icon_state = "40mm_grenade"
+ handful_amount = 1
+ ping = null //no bounce off.
+ sound_bounce = "rocket_bounce"
+ flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_IFF
+ armor_type = BOMB
+ damage_falloff = 0.5
+ shell_speed = 2
+ accurate_range = 12
+ max_range = 21
+ damage = 15
+ shrapnel_chance = 0
+ bonus_projectiles_type = /datum/ammo/bullet/ags_spread
+ bonus_projectiles_scatter = 20
+ var/bonus_projectile_quantity = 15
+
+/datum/ammo/ags_shrapnel/on_hit_mob(mob/M, obj/projectile/proj)
+ playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
+ fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 2, 3, Get_Angle(proj.firer, M) )
+
+/datum/ammo/ags_shrapnel/on_hit_obj(obj/O, obj/projectile/proj)
+ playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
+ fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 2, 3, Get_Angle(proj.firer, O) )
+
+/datum/ammo/ags_shrapnel/on_hit_turf(turf/T, obj/projectile/proj)
+ playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
+ fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 2, 3, Get_Angle(proj.firer, T) )
+
+/datum/ammo/ags_shrapnel/do_at_max_range(turf/T, obj/projectile/proj)
+ playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
+ fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 2, 3, Get_Angle(proj.firer, get_turf(proj)) )
+
+/datum/ammo/ags_shrapnel/incendiary
+ name = "white phosphorous grenade"
+ bonus_projectiles_type = /datum/ammo/bullet/ags_spread/incendiary
+
+/datum/ammo/bullet/ags_spread
+ name = "Shrapnel"
+ icon_state = "flechette"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB
+ accuracy_var_low = 15
+ accuracy_var_high = 5
+ max_range = 6
+ damage = 30
+ penetration = 20
+ sundering = 3
+ damage_falloff = 0
+
+/datum/ammo/bullet/ags_spread/incendiary
+ name = "White phosphorous shrapnel"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_INCENDIARY
+ damage = 20
+ penetration = 10
+ sundering = 1.5
+ damage_falloff = 0
+
+/datum/ammo/bullet/ags_spread/incendiary/on_hit_mob(mob/M, obj/projectile/P)
+ drop_flame(get_turf(M))
+
+/datum/ammo/bullet/ags_spread/incendiary/on_hit_obj(obj/O, obj/projectile/P)
+ drop_flame(get_turf(O))
+
+/datum/ammo/bullet/ags_spread/incendiary/on_hit_turf(turf/T, obj/projectile/P)
+ drop_flame(get_turf(T))
+
+/datum/ammo/bullet/ags_spread/incendiary/do_at_max_range(turf/T, obj/projectile/P)
+ drop_flame(get_turf(T))
+
+/datum/ammo/bullet/ags_spread/incendiary/drop_flame(turf/T)
+ if(!istype(T))
+ return
+ T.ignite(5, 10)
+
+/datum/ammo/grenade_container
+ name = "grenade shell"
+ ping = null
+ damage_type = BRUTE
+ var/nade_type = /obj/item/explosive/grenade
+ icon_state = "grenade"
+ armor_type = BOMB
+ damage = 15
+ accuracy = 15
+ max_range = 10
+
+/datum/ammo/grenade_container/on_hit_mob(mob/M, obj/projectile/P)
+ drop_nade(get_turf(P))
+
+/datum/ammo/grenade_container/on_hit_obj(obj/O, obj/projectile/P)
+ drop_nade(O.density ? P.loc : O.loc)
+
+/datum/ammo/grenade_container/on_hit_turf(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+/datum/ammo/grenade_container/do_at_max_range(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+/datum/ammo/grenade_container/drop_nade(turf/T)
+ var/obj/item/explosive/grenade/G = new nade_type(T)
+ G.visible_message(span_warning("\A [G] lands on [T]!"))
+ G.det_time = 10
+ G.activate()
+
+/datum/ammo/grenade_container/smoke
+ name = "smoke grenade shell"
+ nade_type = /obj/item/explosive/grenade/smokebomb
+ icon_state = "smoke_shell"
+
+/datum/ammo/grenade_container/ags_grenade
+ name = "grenade shell"
+ flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_IFF
+ icon_state = "grenade_projectile"
+ hud_state = "grenade_he"
+ hud_state_empty = "grenade_empty"
+ handful_icon_state = "40mm_grenade"
+ handful_amount = 1
+ max_range = 21
+ nade_type = /obj/item/explosive/grenade/ags
+
+/datum/ammo/grenade_container/ags_grenade/flare
+ hud_state = "grenade_dummy"
+ nade_type = /obj/item/explosive/grenade/flare
+
+/datum/ammo/grenade_container/ags_grenade/cloak
+ hud_state = "grenade_hide"
+ nade_type = /obj/item/explosive/grenade/smokebomb/cloak/ags
+
+/datum/ammo/grenade_container/ags_grenade/tanglefoot
+ hud_state = "grenade_drain"
+ nade_type = /obj/item/explosive/grenade/smokebomb/drain/agls
diff --git a/code/modules/projectiles/ammo_datums/bullet/_bullet.dm b/code/modules/projectiles/ammo_datums/bullet/_bullet.dm
new file mode 100644
index 00000000000..2db7435b7ca
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/bullet/_bullet.dm
@@ -0,0 +1,16 @@
+//Only when things screw up do we use this as a placeholder.
+/datum/ammo/bullet
+ name = "default bullet"
+ icon_state = "bullet"
+ flags_ammo_behavior = AMMO_BALLISTIC
+ sound_hit = "ballistic_hit"
+ sound_armor = "ballistic_armor"
+ sound_miss = "ballistic_miss"
+ sound_bounce = "ballistic_bounce"
+ point_blank_range = 2
+ accurate_range_min = 0
+ shell_speed = 3
+ damage = 10
+ shrapnel_chance = 10
+ bullet_color = COLOR_VERY_SOFT_YELLOW
+ barricade_clear_distance = 2
diff --git a/code/modules/projectiles/ammo_datums/bullet/machinegun.dm b/code/modules/projectiles/ammo_datums/bullet/machinegun.dm
new file mode 100644
index 00000000000..29f45123d60
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/bullet/machinegun.dm
@@ -0,0 +1,114 @@
+/datum/ammo/bullet/machinegun //Adding this for the MG Nests (~Art)
+ name = "machinegun bullet"
+ icon_state = "bullet" // Keeping it bog standard with the turret but allows it to be changed.
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ hud_state = "minigun"
+ hud_state_empty = "smartgun_empty"
+ accurate_range = 12
+ damage = 40 //Reduced damage due to vastly increased mobility
+ penetration = 40 //Reduced penetration due to vastly increased mobility
+ accuracy = 5
+ barricade_clear_distance = 2
+ sundering = 5
+
+/datum/ammo/bullet/minigun
+ name = "minigun bullet"
+ hud_state = "minigun"
+ hud_state_empty = "smartgun_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ accuracy_var_low = 3
+ accuracy_var_high = 3
+ accurate_range = 5
+ damage = 25
+ penetration = 15
+ shrapnel_chance = 25
+ sundering = 2.5
+
+/datum/ammo/bullet/minigun/ltaap
+ name = "chaingun bullet"
+ damage = 30
+ penetration = 10
+ sundering = 0
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_IFF
+ damage_falloff = 2
+ accuracy = 80
+
+/datum/ammo/bullet/auto_cannon
+ name = "autocannon high-velocity bullet"
+ hud_state = "minigun"
+ hud_state_empty = "smartgun_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_TURF|AMMO_PASS_THROUGH_MOVABLE
+ accurate_range_min = 6
+ accuracy_var_low = 3
+ accuracy_var_high = 3
+ damage = 30
+ penetration = 50
+ sundering = 1
+ max_range = 35
+ ///Bonus flat damage to walls, balanced around resin walls.
+ var/autocannon_wall_bonus = 20
+
+/datum/ammo/bullet/auto_cannon/on_hit_turf(turf/T, obj/projectile/P)
+ P.proj_max_range -= 20
+
+ if(istype(T, /turf/closed/wall))
+ var/turf/closed/wall/wall_victim = T
+ wall_victim.take_damage(autocannon_wall_bonus, P.damtype, P.armor_type)
+
+/datum/ammo/bullet/auto_cannon/on_hit_mob(mob/M, obj/projectile/P)
+ P.proj_max_range -= 5
+ staggerstun(M, P, max_range = 20, slowdown = 1)
+
+/datum/ammo/bullet/auto_cannon/on_hit_obj(obj/O, obj/projectile/P)
+ P.proj_max_range -= 5
+
+/datum/ammo/bullet/auto_cannon/flak
+ name = "autocannon smart-detonating bullet"
+ hud_state = "sniper_flak"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_EXPLOSIVE
+ damage = 50
+ penetration = 30
+ sundering = 5
+ max_range = 30
+ airburst_multiplier = 1
+ autocannon_wall_bonus = 5
+
+/datum/ammo/bullet/auto_cannon/flak/on_hit_mob(mob/victim, obj/projectile/proj)
+ airburst(victim, proj)
+
+/datum/ammo/bullet/auto_cannon/do_at_max_range(turf/T, obj/projectile/proj)
+ airburst(T, proj)
+
+/datum/ammo/bullet/cupola
+ name = "cupola bullet"
+ bullet_color = COLOR_SOFT_RED //Red bullets to indicate friendly fire restriction
+ hud_state = "smartgun"
+ hud_state_empty = "smartgun_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_IFF
+ accurate_range = 12
+ damage = 30
+ penetration = 10
+ sundering = 1
+
+/datum/ammo/bullet/smartmachinegun
+ name = "smartmachinegun bullet"
+ bullet_color = COLOR_SOFT_RED //Red bullets to indicate friendly fire restriction
+ hud_state = "smartgun"
+ hud_state_empty = "smartgun_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ accurate_range = 12
+ damage = 20
+ penetration = 15
+ sundering = 2
+
+/datum/ammo/bullet/smart_minigun
+ name = "smartminigun bullet"
+ bullet_color = COLOR_SOFT_RED //Red bullets to indicate friendly fire restriction
+ hud_state = "smartgun_minigun"
+ hud_state_empty = "smartgun_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ accurate_range = 12
+ damage = 10
+ penetration = 25
+ sundering = 1
+ damage_falloff = 0.1
diff --git a/code/modules/projectiles/ammo_datums/bullet/pistol.dm b/code/modules/projectiles/ammo_datums/bullet/pistol.dm
new file mode 100644
index 00000000000..6d3c91cb5bb
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/bullet/pistol.dm
@@ -0,0 +1,112 @@
+/datum/ammo/bullet/pistol
+ name = "pistol bullet"
+ hud_state = "pistol"
+ hud_state_empty = "pistol_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ damage = 20
+ penetration = 5
+ accurate_range = 5
+ sundering = 1
+
+/datum/ammo/bullet/pistol/tiny
+ name = "light pistol bullet"
+ hud_state = "pistol_light"
+ damage = 15
+ penetration = 5
+ sundering = 0.5
+
+/datum/ammo/bullet/pistol/tiny/ap
+ name = "light pistol bullet"
+ hud_state = "pistol_lightap"
+ damage = 22.5
+ penetration = 15 //So it can actually hurt something.
+ sundering = 0.5
+ damage_falloff = 1.5
+
+/datum/ammo/bullet/pistol/tranq
+ name = "tranq bullet"
+ hud_state = "pistol_tranq"
+ damage = 25
+ damage_type = STAMINA
+
+/datum/ammo/bullet/pistol/tranq/on_hit_mob(mob/victim, obj/projectile/proj)
+ if(iscarbon(victim))
+ var/mob/living/carbon/carbon_victim = victim
+ carbon_victim.reagents.add_reagent(/datum/reagent/toxin/potassium_chlorophoride, 1)
+
+/datum/ammo/bullet/pistol/hollow
+ name = "hollowpoint pistol bullet"
+ hud_state = "pistol_hollow"
+ accuracy = -10
+ shrapnel_chance = 45
+ sundering = 2
+
+/datum/ammo/bullet/pistol/hollow/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, stagger = 2 SECONDS, slowdown = 0.5, knockback = 1)
+
+/datum/ammo/bullet/pistol/ap
+ name = "armor-piercing pistol bullet"
+ hud_state = "pistol_ap"
+ damage = 20
+ penetration = 12.5
+ shrapnel_chance = 15
+ sundering = 0.5
+
+/datum/ammo/bullet/pistol/heavy
+ name = "heavy pistol bullet"
+ hud_state = "pistol_heavy"
+ damage = 30
+ penetration = 5
+ shrapnel_chance = 25
+ sundering = 2.15
+
+/datum/ammo/bullet/pistol/superheavy
+ name = "high impact pistol bullet"
+ hud_state = "pistol_superheavy"
+ damage = 45
+ penetration = 15
+ sundering = 3
+ damage_falloff = 0.75
+
+/datum/ammo/bullet/pistol/superheavy/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, stagger = 0.5 SECONDS, slowdown = 0.5, knockback = 1)
+
+/datum/ammo/bullet/pistol/superheavy/derringer
+ handful_amount = 2
+ handful_icon_state = "derringer"
+
+/datum/ammo/bullet/pistol/superheavy/derringer/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, slowdown = 0.5)
+
+/datum/ammo/bullet/pistol/incendiary
+ name = "incendiary pistol bullet"
+ hud_state = "pistol_fire"
+ damage_type = BURN
+ shrapnel_chance = 0
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY
+ damage = 20
+
+/datum/ammo/bullet/pistol/squash
+ name = "squash-head pistol bullet"
+ hud_state = "pistol_squash"
+ accuracy = 5
+ damage = 32
+ penetration = 10
+ shrapnel_chance = 25
+ sundering = 2
+
+/datum/ammo/bullet/pistol/mankey
+ name = "live monkey"
+ icon_state = "monkey1"
+ hud_state = "monkey"
+ hud_state_empty = "monkey_empty"
+ ping = null //no bounce off.
+ damage_type = BURN
+ flags_ammo_behavior = AMMO_INCENDIARY|AMMO_IGNORE_ARMOR
+ shell_speed = 2
+ damage = 15
+
+/datum/ammo/bullet/pistol/mankey/on_hit_mob(mob/M, obj/projectile/P)
+ if(!M.stat && !ismonkey(M))
+ P.visible_message(span_danger("The [src] chimpers furiously!"))
+ new /mob/living/carbon/human/species/monkey(P.loc)
diff --git a/code/modules/projectiles/ammo_datums/bullet/revolver.dm b/code/modules/projectiles/ammo_datums/bullet/revolver.dm
new file mode 100644
index 00000000000..864fd82bbb1
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/bullet/revolver.dm
@@ -0,0 +1,139 @@
+/datum/ammo/bullet/revolver
+ name = "revolver bullet"
+ hud_state = "revolver"
+ hud_state_empty = "revolver_empty"
+ handful_amount = 7
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ damage = 45
+ penetration = 10
+ sundering = 3
+
+/datum/ammo/bullet/revolver/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, stagger = 2 SECONDS, slowdown = 0.5, knockback = 1)
+
+/datum/ammo/bullet/revolver/rifle
+ name = ".44 Long Special bullet"
+ hud_state = "revolver_impact"
+ handful_amount = 8
+ damage = 60
+ penetration = 30
+ sundering = 3
+ damage_falloff = 0
+ shell_speed = 3.5
+
+/datum/ammo/bullet/revolver/t500
+ name = ".500 Nigro Express revolver bullet"
+ icon_state = "nigro"
+ icon = 'icons/obj/items/ammo.dmi'
+ handful_amount = 5
+ damage = 100
+ penetration = 40
+ sundering = 0.5
+
+/datum/ammo/bullet/revolver/t500/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, stagger = 0, slowdown = 0, knockback = 1)
+
+/datum/ammo/bullet/revolver/t500/qk
+ name = ".500 'Queen Killer' revolver bullet"
+ icon_state = "nigro_qk"
+ icon = 'icons/obj/items/ammo.dmi'
+ handful_amount = 5
+ damage = 100
+ penetration = 40
+ sundering = 0
+
+/datum/ammo/bullet/revolver/t500/qk/on_hit_mob(mob/M,obj/projectile/P)
+ if(isxenoqueen(M))
+ var/mob/living/carbon/xenomorph/X = M
+ X.apply_damage(40)
+ staggerstun(M, P, stagger = 0, slowdown = 0, knockback = 0)
+ to_chat(X, span_highdanger("Something burn inside you!"))
+ return
+ staggerstun(M, P, stagger = 0, slowdown = 0, knockback = 1)
+
+/datum/ammo/bullet/revolver/tp44
+ name = "standard revolver bullet"
+ damage = 40
+ penetration = 15
+ sundering = 1
+
+/datum/ammo/bullet/revolver/tp44/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, knockback = 1)
+
+/datum/ammo/bullet/revolver/small
+ name = "small revolver bullet"
+ hud_state = "revolver_small"
+ damage = 30
+
+/datum/ammo/bullet/revolver/small/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, slowdown = 0.5)
+
+/datum/ammo/bullet/revolver/marksman
+ name = "slimline revolver bullet"
+ hud_state = "revolver_slim"
+ shrapnel_chance = 0
+ damage_falloff = 0
+ accuracy = 15
+ accurate_range = 15
+ damage = 30
+ penetration = 10
+
+/datum/ammo/bullet/revolver/judge
+ name = "oversized revolver bullet"
+ hud_state = "revolver_slim"
+ shrapnel_chance = 0
+ damage_falloff = 0
+ accuracy = 15
+ accurate_range = 15
+ damage = 70
+ penetration = 10
+
+/datum/ammo/bullet/revolver/heavy
+ name = "heavy revolver bullet"
+ hud_state = "revolver_heavy"
+ damage = 50
+ penetration = 5
+ accuracy = -10
+
+/datum/ammo/bullet/revolver/t76
+ name = "magnum bullet"
+ handful_amount = 5
+ damage = 100
+ penetration = 40
+ sundering = 0.5
+
+/datum/ammo/bullet/revolver/t76/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, weaken = 2 SECONDS, knockback = 1)
+
+/datum/ammo/bullet/revolver/highimpact
+ name = "high-impact revolver bullet"
+ hud_state = "revolver_impact"
+ handful_amount = 6
+ damage = 50
+ penetration = 20
+ sundering = 3
+
+/datum/ammo/bullet/revolver/highimpact/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, weaken = 2 SECONDS, stagger = 2 SECONDS, slowdown = 1, knockback = 1)
+
+/datum/ammo/bullet/revolver/ricochet
+ bonus_projectiles_type = /datum/ammo/bullet/revolver/small
+ bonus_projectiles_scatter = 0
+
+/datum/ammo/bullet/revolver/ricochet/one
+ bonus_projectiles_type = /datum/ammo/bullet/revolver/ricochet
+
+/datum/ammo/bullet/revolver/ricochet/two
+ bonus_projectiles_type = /datum/ammo/bullet/revolver/ricochet/one
+
+/datum/ammo/bullet/revolver/ricochet/three
+ bonus_projectiles_type = /datum/ammo/bullet/revolver/ricochet/two
+
+/datum/ammo/bullet/revolver/ricochet/four
+ bonus_projectiles_type = /datum/ammo/bullet/revolver/ricochet/three
+
+/datum/ammo/bullet/revolver/ricochet/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, slowdown = 0.5)
+
+/datum/ammo/bullet/revolver/ricochet/on_hit_turf(turf/T, obj/projectile/proj)
+ reflect(T, proj, 10)
diff --git a/code/modules/projectiles/ammo_datums/bullet/rifle.dm b/code/modules/projectiles/ammo_datums/bullet/rifle.dm
new file mode 100644
index 00000000000..0eaf59639bc
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/bullet/rifle.dm
@@ -0,0 +1,328 @@
+/datum/ammo/bullet/rifle
+ name = "rifle bullet"
+ hud_state = "rifle"
+ hud_state_empty = "rifle_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ accurate_range = 12
+ damage = 25
+ penetration = 5
+ sundering = 0.5
+
+/datum/ammo/bullet/rifle/T25
+ name = "smartmachinegun bullet"
+ bullet_color = COLOR_SOFT_RED //Red bullets to indicate friendly fire restriction
+ hud_state = "smartgun"
+ hud_state_empty = "smartgun_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ accurate_range = 20
+ damage = 20
+ penetration = 10
+ sundering = 1.5
+
+/datum/ammo/bullet/rifle/ap
+ name = "armor-piercing rifle bullet"
+ hud_state = "rifle_ap"
+ damage = 20
+ penetration = 25
+ sundering = 3
+
+/datum/ammo/bullet/rifle/hv
+ name = "high-velocity rifle bullet"
+ hud_state = "hivelo"
+ damage = 20
+ penetration = 20
+ sundering = 1.25
+
+/datum/ammo/bullet/rifle/heavy
+ name = "heavy rifle bullet"
+ hud_state = "rifle_heavy"
+ damage = 30
+ penetration = 10
+ sundering = 1.25
+
+/datum/ammo/bullet/rifle/heavy/ap
+ name = "heavy rifle bullet"
+ damage = 25
+ penetration = 25
+ sundering = 3.5
+
+/datum/ammo/bullet/rifle/repeater
+ name = "heavy impact rifle bullet"
+ hud_state = "sniper"
+ damage = 70
+ penetration = 20
+ sundering = 1.25
+
+/datum/ammo/bullet/rifle/repeater/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, max_range = 3, slowdown = 2, stagger = 1 SECONDS)
+
+/datum/ammo/bullet/rifle/incendiary
+ name = "incendiary rifle bullet"
+ hud_state = "rifle_fire"
+ damage_type = BURN
+ shrapnel_chance = 0
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY
+ accuracy = -10
+
+/datum/ammo/bullet/rifle/machinegun
+ name = "machinegun bullet"
+ hud_state = "rifle_heavy"
+ damage = 25
+ penetration = 10
+ sundering = 0.75
+
+/datum/ammo/bullet/rifle/som_machinegun
+ name = "machinegun bullet"
+ hud_state = "rifle_heavy"
+ damage = 28
+ penetration = 12.5
+ sundering = 1
+
+/datum/ammo/bullet/rifle/som_machinegun/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, max_range = 20, slowdown = 0.5)
+
+/datum/ammo/bullet/rifle/tx8
+ name = "A19 high velocity bullet"
+ hud_state = "hivelo"
+ hud_state_empty = "hivelo_empty"
+ damage_falloff = 0
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ accurate_range = 15
+ damage = 40
+ penetration = 20
+ sundering = 10
+ bullet_color = COLOR_SOFT_RED
+
+/datum/ammo/bullet/rifle/tx8/incendiary
+ name = "high velocity incendiary bullet"
+ hud_state = "hivelo_fire"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB
+ damage = 25
+ penetration = 20
+ sundering = 2.5
+ bullet_color = LIGHT_COLOR_FIRE
+
+/datum/ammo/bullet/rifle/tx8/impact
+ name = "high velocity impact bullet"
+ hud_state = "hivelo_impact"
+ damage = 30
+ penetration = 10
+ sundering = 12.5
+
+/datum/ammo/bullet/rifle/tx8/impact/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, max_range = 14, slowdown = 1, knockback = 1)
+
+/datum/ammo/bullet/rifle/mpi_km
+ name = "crude heavy rifle bullet"
+ hud_state = "rifle_crude"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ damage = 30
+ penetration = 15
+ sundering = 1.75
+
+/datum/ammo/bullet/rifle/standard_dmr
+ name = "marksman bullet"
+ hud_state = "hivelo"
+ hud_state_empty = "hivelo_empty"
+ damage_falloff = 0.5
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ accurate_range = 25
+ accurate_range_min = 6
+ max_range = 40
+ damage = 65
+ penetration = 15
+ sundering = 2
+
+/datum/ammo/bullet/rifle/garand
+ name = "heavy marksman bullet"
+ hud_state = "sniper"
+ damage = 75
+ penetration = 25
+ sundering = 1.25
+
+/datum/ammo/bullet/rifle/standard_br
+ name = "light marksman bullet"
+ hud_state = "hivelo"
+ hud_state_empty = "hivelo_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ penetration = 15
+ damage = 32.5
+ sundering = 1.25
+
+/datum/ammo/bullet/rifle/standard_br/ap
+ name = "light marksman armor piercing bullet"
+ penetration = 25
+ damage = 27.5
+ sundering = 3.25
+
+/datum/ammo/bullet/rifle/icc_confrontationrifle
+ name = "armor-piercing heavy rifle bullet"
+ hud_state = "rifle_ap"
+ damage = 50
+ penetration = 40
+ sundering = 3.5
+
+/datum/ammo/bullet/smarttargetrifle
+ name = "smart marksman bullet"
+ bullet_color = COLOR_SOFT_RED //Red bullets to indicate friendly fire restriction
+ hud_state = "smartgun"
+ hud_state_empty = "smartgun_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ damage = 40
+ max_range = 40
+ penetration = 30
+ sundering = 3
+ shell_speed = 4
+ damage_falloff = 0.5
+ accurate_range = 25
+ accurate_range_min = 3
+
+/datum/ammo/bullet/spottingrifle
+ name = "smart spotting bullet"
+ bullet_color = COLOR_SOFT_RED //Red bullets to indicate friendly fire restriction
+ hud_state = "spotrifle"
+ hud_state_empty = "smartgun_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ damage = 50
+ penetration = 25
+ sundering = 5
+ shell_speed = 4
+ accurate_range = 12
+ max_range = 12
+
+/datum/ammo/bullet/spottingrifle/highimpact
+ name = "smart high-impact spotting bullet"
+ hud_state = "spotrifle_impact"
+ damage = 10
+ sundering = 0.5
+
+/datum/ammo/bullet/spottingrifle/highimpact/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, stagger = 1 SECONDS, slowdown = 1, max_range = 12)
+
+/datum/ammo/bullet/spottingrifle/heavyrubber
+ name = "smart heavy-rubber spotting bullet"
+ hud_state = "spotrifle_rubber"
+ damage = 10
+ sundering = 0.5
+
+/datum/ammo/bullet/spottingrifle/heavyrubber/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, slowdown = 3, max_range = 12)
+
+/datum/ammo/bullet/spottingrifle/plasmaloss
+ name = "smart tanglefoot spotting bullet"
+ hud_state = "spotrifle_plasmaloss"
+ damage = 10
+ sundering = 0.5
+ var/datum/effect_system/smoke_spread/smoke_system
+
+/datum/ammo/bullet/spottingrifle/plasmaloss/on_hit_mob(mob/living/victim, obj/projectile/proj)
+ if(isxeno(victim))
+ var/mob/living/carbon/xenomorph/X = victim
+ X.use_plasma(20 + 0.2 * X.xeno_caste.plasma_max * X.xeno_caste.plasma_regen_limit) // This is draining 20%+20 flat per hit.
+ var/datum/effect_system/smoke_spread/plasmaloss/S = new
+ S.set_up(0, victim, 3)
+ S.start()
+
+/datum/ammo/bullet/spottingrifle/plasmaloss/on_hit_obj(obj/O, obj/projectile/P)
+ var/turf/T = get_turf(O)
+ drop_tg_smoke(T.density ? P.loc : T)
+
+/datum/ammo/bullet/spottingrifle/plasmaloss/on_hit_turf(turf/T, obj/projectile/P)
+ drop_tg_smoke(T.density ? P.loc : T)
+
+/datum/ammo/bullet/spottingrifle/plasmaloss/do_at_max_range(turf/T, obj/projectile/P)
+ drop_tg_smoke(T.density ? P.loc : T)
+
+/datum/ammo/bullet/spottingrifle/plasmaloss/set_smoke()
+ smoke_system = new /datum/effect_system/smoke_spread/plasmaloss()
+
+/datum/ammo/bullet/spottingrifle/plasmaloss/proc/drop_tg_smoke(turf/T)
+ if(T.density)
+ return
+
+ set_smoke()
+ smoke_system.set_up(0, T, 3)
+ smoke_system.start()
+ smoke_system = null
+
+/datum/ammo/bullet/spottingrifle/tungsten
+ name = "smart tungsten spotting bullet"
+ hud_state = "spotrifle_tungsten"
+ damage = 10
+ sundering = 0.5
+
+/datum/ammo/bullet/spottingrifle/tungsten/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, weaken = 2 SECONDS, stagger = 0.5 SECONDS, knockback = 1, max_range = 12)
+
+/datum/ammo/bullet/spottingrifle/flak
+ name = "smart flak spotting bullet"
+ hud_state = "spotrifle_flak"
+ damage = 60
+ sundering = 0.5
+ airburst_multiplier = 0.5
+
+/datum/ammo/bullet/spottingrifle/flak/on_hit_mob(mob/victim, obj/projectile/proj)
+ airburst(victim, proj)
+
+/datum/ammo/bullet/spottingrifle/incendiary
+ name = "smart incendiary spotting bullet"
+ hud_state = "spotrifle_incend"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY
+ damage_type = BURN
+ damage = 10
+ sundering = 0.5
+
+/datum/ammo/bullet/railgun
+ name = "armor piercing railgun slug"
+ hud_state = "railgun_ap"
+ icon_state = "blue_bullet"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_TURF|AMMO_PASS_THROUGH_MOVABLE
+ shell_speed = 4
+ max_range = 14
+ damage = 150
+ penetration = 100
+ sundering = 20
+ bullet_color = COLOR_PULSE_BLUE
+ on_pierce_multiplier = 0.85
+
+/datum/ammo/bullet/railgun/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, weaken = 2 SECONDS, stagger = 4 SECONDS, slowdown = 2, knockback = 2)
+
+/datum/ammo/bullet/railgun/hvap
+ name = "high velocity railgun slug"
+ hud_state = "railgun_hvap"
+ shell_speed = 5
+ max_range = 21
+ damage = 100
+ penetration = 30
+ sundering = 50
+
+/datum/ammo/bullet/railgun/hvap/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, stagger = 2 SECONDS, knockback = 3)
+
+/datum/ammo/bullet/railgun/smart
+ name = "smart armor piercing railgun slug"
+ hud_state = "railgun_smart"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_TURF|AMMO_PASS_THROUGH_MOVABLE|AMMO_IFF
+ damage = 100
+ penetration = 20
+ sundering = 20
+
+/datum/ammo/bullet/railgun/smart/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, stagger = 3 SECONDS, slowdown = 3)
+
+/datum/ammo/bullet/coilgun
+ name = "high-velocity tungsten slug"
+ hud_state = "railgun_ap"
+ icon_state = "blue_bullet"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOVABLE
+ shell_speed = 5
+ max_range = 31
+ damage = 70
+ penetration = 35
+ sundering = 5
+ bullet_color = COLOR_PULSE_BLUE
+ on_pierce_multiplier = 0.85
+
+/datum/ammo/bullet/coilgun/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, weaken = 0.2 SECONDS, slowdown = 1, knockback = 3)
diff --git a/code/modules/projectiles/ammo_datums/bullet/shotgun.dm b/code/modules/projectiles/ammo_datums/bullet/shotgun.dm
new file mode 100644
index 00000000000..064502edb0c
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/bullet/shotgun.dm
@@ -0,0 +1,339 @@
+/datum/ammo/bullet/shotgun
+ hud_state_empty = "shotgun_empty"
+ shell_speed = 2
+ handful_amount = 5
+
+/datum/ammo/bullet/shotgun/slug
+ name = "shotgun slug"
+ handful_icon_state = "shotgun slug"
+ hud_state = "shotgun_slug"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ shell_speed = 3
+ max_range = 15
+ damage = 100
+ penetration = 20
+ sundering = 7.5
+
+/datum/ammo/bullet/shotgun/slug/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, weaken = 2 SECONDS, stagger = 2 SECONDS, knockback = 1, slowdown = 2)
+
+/datum/ammo/bullet/shotgun/beanbag
+ name = "beanbag slug"
+ handful_icon_state = "beanbag slug"
+ icon_state = "beanbag"
+ hud_state = "shotgun_beanbag"
+ flags_ammo_behavior = AMMO_BALLISTIC
+ damage = 15
+ max_range = 15
+ shrapnel_chance = 0
+ accuracy = 5
+
+/datum/ammo/bullet/shotgun/beanbag/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, weaken = 2 SECONDS, stagger = 4 SECONDS, knockback = 1, slowdown = 2, hard_size_threshold = 1)
+
+/datum/ammo/bullet/shotgun/incendiary
+ name = "incendiary slug"
+ handful_icon_state = "incendiary slug"
+ hud_state = "shotgun_fire"
+ damage_type = BRUTE
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY|AMMO_SUNDERING
+ max_range = 10
+ damage = 100
+ penetration = 15
+ sundering = 0
+ bullet_color = COLOR_TAN_ORANGE
+
+/datum/ammo/bullet/shotgun/incendiary/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, weaken = 1 SECONDS, knockback = 1, slowdown = 1)
+
+/datum/ammo/bullet/shotgun/flechette
+ name = "shotgun flechette shell"
+ handful_icon_state = "shotgun flechette shell"
+ icon_state = "flechette"
+ hud_state = "shotgun_flechette"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ bonus_projectiles_type = /datum/ammo/bullet/shotgun/flechette/flechette_spread
+ bonus_projectiles_amount = 2
+ bonus_projectiles_scatter = 3
+ accuracy_var_low = 8
+ accuracy_var_high = 8
+ max_range = 15
+ damage = 50
+ damage_falloff = 0.5
+ penetration = 15
+ sundering = 7
+
+/datum/ammo/bullet/shotgun/flechette/flechette_spread
+ name = "additional flechette"
+ damage = 40
+ sundering = 5
+
+/datum/ammo/bullet/shotgun/buckshot
+ name = "shotgun buckshot shell"
+ handful_icon_state = "shotgun buckshot shell"
+ icon_state = "buckshot"
+ hud_state = "shotgun_buckshot"
+ bonus_projectiles_type = /datum/ammo/bullet/shotgun/spread
+ bonus_projectiles_amount = 5
+ bonus_projectiles_scatter = 4
+ accuracy_var_low = 9
+ accuracy_var_high = 9
+ accurate_range = 3
+ max_range = 10
+ damage = 40
+ damage_falloff = 4
+
+/datum/ammo/bullet/shotgun/buckshot/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, weaken = 2 SECONDS, stagger = 2 SECONDS, knockback = 2, slowdown = 0.5, max_range = 3)
+
+/datum/ammo/bullet/shotgun/spread
+ name = "additional buckshot"
+ icon_state = "buckshot"
+ accuracy_var_low = 9
+ accuracy_var_high = 9
+ accurate_range = 3
+ max_range = 10
+ damage = 40
+ damage_falloff = 4
+
+/datum/ammo/bullet/shotgun/frag
+ name = "shotgun explosive shell"
+ handful_icon_state = "shotgun tracker shell"
+ hud_state = "shotgun_tracker"
+ flags_ammo_behavior = AMMO_BALLISTIC
+ bonus_projectiles_type = /datum/ammo/bullet/shotgun/frag/frag_spread
+ bonus_projectiles_amount = 2
+ bonus_projectiles_scatter = 6
+ accuracy_var_low = 8
+ accuracy_var_high = 8
+ max_range = 15
+ damage = 10
+ damage_falloff = 0.5
+ penetration = 0
+
+/datum/ammo/bullet/shotgun/frag/drop_nade(turf/T)
+ explosion(T, weak_impact_range = 2)
+
+/datum/ammo/bullet/shotgun/frag/on_hit_mob(mob/M, obj/projectile/P)
+ drop_nade(get_turf(M))
+
+/datum/ammo/bullet/shotgun/frag/on_hit_obj(obj/O, obj/projectile/P)
+ drop_nade(O.density ? P.loc : O.loc)
+
+/datum/ammo/bullet/shotgun/frag/on_hit_turf(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+/datum/ammo/bullet/shotgun/frag/do_at_max_range(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+/datum/ammo/bullet/shotgun/frag/frag_spread
+ name = "additional frag shell"
+ damage = 5
+
+/datum/ammo/bullet/shotgun/sx16_buckshot
+ name = "shotgun buckshot shell" //16 gauge is between 12 and 410 bore.
+ handful_icon_state = "shotgun buckshot shell"
+ icon_state = "buckshot"
+ hud_state = "shotgun_buckshot"
+ bonus_projectiles_type = /datum/ammo/bullet/shotgun/sx16_buckshot/spread
+ bonus_projectiles_amount = 4
+ bonus_projectiles_scatter = 10
+ accuracy_var_low = 10
+ accuracy_var_high = 10
+ max_range = 10
+ damage = 25
+ damage_falloff = 4
+
+/datum/ammo/bullet/shotgun/sx16_buckshot/spread
+ name = "additional buckshot"
+
+/datum/ammo/bullet/shotgun/sx16_flechette
+ name = "shotgun flechette shell"
+ handful_icon_state = "shotgun flechette shell"
+ icon_state = "flechette"
+ hud_state = "shotgun_flechette"
+ bonus_projectiles_type = /datum/ammo/bullet/shotgun/sx16_flechette/spread
+ bonus_projectiles_amount = 4
+ bonus_projectiles_scatter = 8
+ accuracy_var_low = 7
+ accuracy_var_high = 7
+ max_range = 15
+ damage = 15
+ damage_falloff = 0.5
+ penetration = 15
+
+/datum/ammo/bullet/shotgun/sx16_flechette/spread
+ name = "additional flechette"
+
+/datum/ammo/bullet/shotgun/sx16_slug
+ name = "shotgun slug"
+ handful_icon_state = "shotgun slug"
+ hud_state = "shotgun_slug"
+ shell_speed = 3
+ max_range = 15
+ damage = 40
+ penetration = 20
+
+/datum/ammo/bullet/shotgun/sx16_slug/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, slowdown = 1, knockback = 1)
+
+/datum/ammo/bullet/shotgun/tx15_flechette
+ name = "shotgun flechette shell"
+ handful_icon_state = "shotgun flechette shell"
+ icon_state = "flechette"
+ hud_state = "shotgun_flechette"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ bonus_projectiles_type = /datum/ammo/bullet/shotgun/tx15_flechette/spread
+ bonus_projectiles_amount = 4
+ bonus_projectiles_scatter = 2
+ max_range = 15
+ damage = 17
+ damage_falloff = 0.25
+ penetration = 15
+ sundering = 1.5
+
+/datum/ammo/bullet/shotgun/tx15_flechette/spread
+ name = "additional flechette"
+
+/datum/ammo/bullet/shotgun/tx15_slug
+ name = "shotgun slug"
+ handful_icon_state = "shotgun slug"
+ hud_state = "shotgun_slug"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ shell_speed = 3
+ max_range = 15
+ damage = 60
+ penetration = 30
+ sundering = 3.5
+
+/datum/ammo/bullet/shotgun/tx15_slug/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, slowdown = 2, knockback = 1)
+
+/datum/ammo/bullet/shotgun/mbx900_buckshot
+ name = "light shotgun buckshot shell" // If .410 is the smallest shotgun shell, then...
+ handful_icon_state = "light shotgun buckshot shell"
+ icon_state = "buckshot"
+ hud_state = "shotgun_buckshot"
+ bonus_projectiles_type = /datum/ammo/bullet/shotgun/mbx900_buckshot/spread
+ bonus_projectiles_amount = 2
+ bonus_projectiles_scatter = 10
+ accuracy_var_low = 10
+ accuracy_var_high = 10
+ max_range = 10
+ damage = 50
+ damage_falloff = 1
+
+/datum/ammo/bullet/shotgun/mbx900_buckshot/spread
+ name = "additional buckshot"
+ damage = 40
+
+/datum/ammo/bullet/shotgun/mbx900_sabot
+ name = "light shotgun sabot shell"
+ handful_icon_state = "light shotgun sabot shell"
+ icon_state = "shotgun_slug"
+ hud_state = "shotgun_sabot"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ shell_speed = 5
+ max_range = 30
+ damage = 50
+ penetration = 40
+ sundering = 3
+
+/datum/ammo/bullet/shotgun/mbx900_tracker
+ name = "light shotgun tracker round"
+ handful_icon_state = "light shotgun tracker round"
+ icon_state = "shotgun_slug"
+ hud_state = "shotgun_tracker"
+ shell_speed = 4
+ max_range = 30
+ damage = 5
+ penetration = 100
+
+/datum/ammo/bullet/shotgun/mbx900_tracker/on_hit_mob(mob/living/victim, obj/projectile/proj)
+ victim.AddComponent(/datum/component/dripping, DRIP_ON_TIME, 40 SECONDS, 2 SECONDS)
+
+/datum/ammo/bullet/shotgun/tracker
+ name = "shotgun tracker shell"
+ handful_icon_state = "shotgun tracker shell"
+ icon_state = "shotgun_slug"
+ hud_state = "shotgun_tracker"
+ shell_speed = 4
+ max_range = 30
+ damage = 5
+ penetration = 100
+
+/datum/ammo/bullet/shotgun/tracker/on_hit_mob(mob/living/victim, obj/projectile/proj)
+ victim.AddComponent(/datum/component/dripping, DRIP_ON_TIME, 40 SECONDS, 2 SECONDS)
+
+/datum/ammo/bullet/shotgun/buckshot/shq6
+ name = "shotgun buckshot shell"
+ handful_icon_state = "shotgun buckshot shell"
+ icon_state = "buckshot"
+ hud_state = "shotgun_buckshot"
+ bonus_projectiles_type = /datum/ammo/bullet/shotgun/spread
+ bonus_projectiles_amount = 5
+ bonus_projectiles_scatter = 3
+ accuracy_var_low = 9
+ accuracy_var_high = 9
+ accurate_range = 4
+ max_range = 10
+ damage = 40
+ sundering = 2
+ damage_falloff = 4
+
+/datum/ammo/bullet/shotgun/buckshot/shq6/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, knockback = 1, slowdown = 1, max_range = 3)
+
+/datum/ammo/bullet/shotgun/slug/shq6
+ name = "shotgun slug"
+ handful_icon_state = "shotgun slug"
+ hud_state = "shotgun_slug"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ shell_speed = 3
+ max_range = 15
+ damage = 100
+ penetration = 30
+ sundering = 3
+ damage_falloff = 3
+
+/datum/ammo/bullet/shotgun/slug/shq6/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, slowdown = 2, max_range = 5)
+
+/datum/ammo/bullet/shotgun/incendiary/shq6
+ name = "incendiary slug"
+ handful_icon_state = "incendiary slug"
+ hud_state = "shotgun_fire"
+ damage_type = BRUTE
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY|AMMO_SUNDERING
+ max_range = 15
+ damage = 70
+ penetration = 15
+ sundering = 1
+ bullet_color = COLOR_TAN_ORANGE
+
+/datum/ammo/bullet/shotgun/incendiary/shq6/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, knockback = 1)
+
+/datum/ammo/bullet/shotgun/flechette/shq6
+ name = "shotgun flechette shell"
+ handful_icon_state = "shotgun flechette shell"
+ icon_state = "flechette"
+ hud_state = "shotgun_flechette"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ bonus_projectiles_type = /datum/ammo/bullet/shotgun/flechette/flechette_spread/shq6
+ bonus_projectiles_amount = 2
+ bonus_projectiles_scatter = 3
+ accuracy_var_low = 8
+ accuracy_var_high = 8
+ max_range = 15
+ damage = 50
+ damage_falloff = 3
+ penetration = 40
+ sundering = 4
+
+/datum/ammo/bullet/shotgun/flechette/flechette_spread/shq6
+ name = "additional flechette"
+ damage = 40
+ penetration = 40
+ sundering = 2
+ damage_falloff = 3
diff --git a/code/modules/projectiles/ammo_datums/bullet/sniper.dm b/code/modules/projectiles/ammo_datums/bullet/sniper.dm
new file mode 100644
index 00000000000..4e62e85f604
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/bullet/sniper.dm
@@ -0,0 +1,111 @@
+/datum/ammo/bullet/sniper
+ name = "sniper bullet"
+ hud_state = "sniper"
+ hud_state_empty = "sniper_empty"
+ damage_falloff = 0
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SNIPER|AMMO_SUNDERING
+ accurate_range_min = 7
+ shell_speed = 4
+ accurate_range = 30
+ max_range = 40
+ damage = 90
+ penetration = 50
+ sundering = 15
+
+/datum/ammo/bullet/sniper/incendiary
+ name = "incendiary sniper bullet"
+ hud_state = "sniper_fire"
+ accuracy = 0
+ damage_type = BURN
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY|AMMO_SNIPER|AMMO_SUNDERING
+ accuracy_var_high = 7
+ max_range = 20
+ damage = 70
+ penetration = 30
+ sundering = 5
+
+/datum/ammo/bullet/sniper/flak
+ name = "flak sniper bullet"
+ hud_state = "sniper_flak"
+ damage = 90
+ penetration = 0
+ sundering = 15
+ airburst_multiplier = 0.5
+
+/datum/ammo/bullet/sniper/flak/on_hit_mob(mob/victim, obj/projectile/proj)
+ staggerstun(victim, proj, max_range = 30, slowdown = 2)
+ airburst(victim, proj)
+
+/datum/ammo/bullet/sniper/svd
+ name = "crude sniper bullet"
+ handful_icon_state = "crude sniper bullet"
+ hud_state = "sniper_crude"
+ handful_amount = 5
+ damage = 75
+ penetration = 35
+ sundering = 15
+
+/datum/ammo/bullet/sniper/martini
+ name = "crude heavy sniper bullet"
+ handful_icon_state = "crude heavy sniper bullet"
+ hud_state = "sniper_crude"
+ handful_amount = 5
+ flags_ammo_behavior = AMMO_BALLISTIC
+ damage = 120
+ penetration = 40
+ accurate_range_min = 0
+ ///shatter effection duration when hitting mobs
+ var/shatter_duration = 10 SECONDS
+
+/datum/ammo/bullet/sniper/martini/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, weaken = 0.5 SECONDS, stagger = 1 SECONDS, knockback = 2, slowdown = 0.5, max_range = 10)
+
+/datum/ammo/bullet/sniper/elite
+ name = "supersonic sniper bullet"
+ hud_state = "sniper_supersonic"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ accuracy = 20
+ damage = 100
+ penetration = 60
+ sundering = 50
+
+/datum/ammo/bullet/sniper/pfc
+ name = "high caliber rifle bullet"
+ hud_state = "sniper_heavy"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_SNIPER
+ damage = 80
+ penetration = 30
+ sundering = 7.5
+ damage_falloff = 0.25
+
+/datum/ammo/bullet/sniper/pfc/flak
+ name = "high caliber flak rifle bullet"
+ hud_state = "sniper_heavy_flak"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_SNIPER
+ damage = 40
+ penetration = 10
+ sundering = 10
+ damage_falloff = 0.25
+
+/datum/ammo/bullet/sniper/pfc/flak/on_hit_mob(mob/M, obj/projectile/P)
+ staggerstun(M, P, knockback = 4, slowdown = 1.5, stagger = 2 SECONDS, max_range = 17)
+
+/datum/ammo/bullet/sniper/auto
+ name = "high caliber rifle bullet"
+ hud_state = "sniper_auto"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_SNIPER
+ damage = 50
+ penetration = 30
+ sundering = 2
+ damage_falloff = 0.25
+
+/datum/ammo/bullet/sniper/clf_heavyrifle
+ name = "high velocity incendiary sniper bullet"
+ handful_icon_state = "ptrs"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY|AMMO_SNIPER|AMMO_SUNDERING
+ hud_state = "sniper_fire"
+ accurate_range_min = 4
+ shell_speed = 5
+ damage = 120
+ penetration = 60
+ sundering = 20
diff --git a/code/modules/projectiles/ammo_datums/bullet/submachinegun.dm b/code/modules/projectiles/ammo_datums/bullet/submachinegun.dm
new file mode 100644
index 00000000000..b1db15abee8
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/bullet/submachinegun.dm
@@ -0,0 +1,68 @@
+/datum/ammo/bullet/smg
+ name = "submachinegun bullet"
+ hud_state = "smg"
+ hud_state_empty = "smg_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ accuracy_var_low = 7
+ accuracy_var_high = 7
+ damage = 20
+ accurate_range = 4
+ damage_falloff = 1
+ sundering = 0.5
+ penetration = 5
+
+/datum/ammo/bullet/smg/ap
+ name = "armor-piercing submachinegun bullet"
+ hud_state = "smg_ap"
+ damage = 15
+ penetration = 30
+ sundering = 3
+
+/datum/ammo/bullet/smg/acp
+ name = "submachinegun ACP bullet"
+ hud_state = "smg"
+ hud_state_empty = "smg_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING
+ accuracy_var_low = 7
+ accuracy_var_high = 7
+ damage = 20
+ accurate_range = 4
+ damage_falloff = 1
+ sundering = 0.4
+ penetration = 0
+ shrapnel_chance = 25
+
+/datum/ammo/bullet/smg/ap/hv
+ name = "high velocity armor-piercing submachinegun bullet"
+ shell_speed = 4
+
+/datum/ammo/bullet/smg/hollow
+ name = "hollow-point submachinegun bullet"
+ hud_state = "pistol_squash"
+ flags_ammo_behavior = AMMO_BALLISTIC
+ damage = 35
+ penetration = 0
+ damage_falloff = 3
+ shrapnel_chance = 45
+
+/datum/ammo/bullet/smg/incendiary
+ name = "incendiary submachinegun bullet"
+ hud_state = "smg_fire"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_INCENDIARY
+ damage = 18
+ penetration = 0
+
+/datum/ammo/bullet/smg/rad
+ name = "radioactive submachinegun bullet"
+ hud_state = "smg_rad"
+ damage = 15
+ penetration = 15
+ sundering = 1
+
+/datum/ammo/bullet/smg/rad/on_hit_mob(mob/M, obj/projectile/proj)
+ if(!isliving(M))
+ return
+ var/mob/living/living_victim = M
+ if(!prob(living_victim.modify_by_armor(proj.damage, BIO, penetration, proj.def_zone)))
+ return
+ living_victim.apply_radiation(2, 2)
diff --git a/code/modules/projectiles/ammo_datums/energy.dm b/code/modules/projectiles/ammo_datums/energy.dm
new file mode 100644
index 00000000000..5cb94277052
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/energy.dm
@@ -0,0 +1,726 @@
+/datum/ammo/energy
+ ping = "ping_s"
+ sound_hit = "energy_hit"
+ sound_armor = "ballistic_armor"
+ sound_miss = "ballistic_miss"
+ sound_bounce = "ballistic_bounce"
+
+ damage_type = BURN
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_SOUND_PITCH
+ armor_type = ENERGY
+ accuracy = 15 //lasers fly fairly straight
+ bullet_color = COLOR_LASER_RED
+ barricade_clear_distance = 2
+
+/datum/ammo/energy/emitter //Damage is determined in emitter.dm
+ name = "emitter bolt"
+ icon_state = "emitter"
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_IGNORE_ARMOR
+ accurate_range = 10
+ max_range = 10
+ bullet_color = COLOR_VIBRANT_LIME
+
+/datum/ammo/energy/taser
+ name = "taser bolt"
+ icon_state = "stun"
+ hud_state = "taser"
+ hud_state_empty = "battery_empty"
+ damage = 10
+ penetration = 100
+ damage_type = STAMINA
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_SKIPS_ALIENS
+ max_range = 15
+ accurate_range = 10
+ bullet_color = COLOR_VIVID_YELLOW
+/datum/ammo/energy/taser/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, stun = 20 SECONDS)
+
+/datum/ammo/energy/tesla
+ name = "energy ball"
+ icon_state = "tesla"
+ hud_state = "taser"
+ hud_state_empty = "battery_empty"
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_SPECIAL_PROCESS
+ shell_speed = 0.1
+ damage = 20
+ penetration = 20
+ bullet_color = COLOR_TESLA_BLUE
+
+/datum/ammo/energy/tesla/ammo_process(obj/projectile/proj, damage)
+ zap_beam(proj, 4, damage)
+
+/datum/ammo/energy/tesla/focused
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_SPECIAL_PROCESS|AMMO_IFF
+ shell_speed = 0.1
+ damage = 10
+ penetration = 10
+ bullet_color = COLOR_TESLA_BLUE
+
+/datum/ammo/energy/tesla/focused/ammo_process(obj/projectile/proj, damage)
+ zap_beam(proj, 3, damage)
+
+/datum/ammo/energy/tesla/on_hit_mob(mob/M,obj/projectile/P)
+ if(isxeno(M)) //need 1 second more than the actual effect time
+ var/mob/living/carbon/xenomorph/X = M
+ X.use_plasma(0.3 * X.xeno_caste.plasma_max * X.xeno_caste.plasma_regen_limit) //Drains 30% of max plasma on hit
+
+/datum/ammo/energy/lasgun
+ name = "laser bolt"
+ icon_state = "laser"
+ hud_state = "laser"
+ armor_type = LASER
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_SUNDERING
+ shell_speed = 4
+ accurate_range = 15
+ damage = 20
+ penetration = 10
+ max_range = 30
+ accuracy_var_low = 3
+ accuracy_var_high = 3
+ sundering = 2.5
+
+/datum/ammo/energy/lasgun/M43
+ icon_state = "laser2"
+
+/datum/ammo/energy/lasgun/M43/overcharge
+ name = "overcharged laser bolt"
+ icon_state = "overchargedlaser"
+ hud_state = "laser_sniper"
+ damage = 40
+ max_range = 40
+ penetration = 50
+ sundering = 5
+
+/datum/ammo/energy/lasgun/M43/heat
+ name = "microwave heat bolt"
+ icon_state = "microwavelaser"
+ hud_state = "laser_heat"
+ damage = 12 //requires mod with -0.15 multiplier should math out to 10
+ penetration = 100 // It's a laser that burns the skin! The fire stacks go threw anyway.
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_INCENDIARY|AMMO_SUNDERING
+ sundering = 1
+
+/datum/ammo/energy/lasgun/M43/blast
+ name = "wide range laser blast"
+ icon_state = "heavylaser2"
+ hud_state = "laser_spread"
+ bonus_projectiles_type = /datum/ammo/energy/lasgun/M43/spread
+ bonus_projectiles_amount = 2
+ bonus_projectiles_scatter = 10
+ accuracy_var_low = 9
+ accuracy_var_high = 9
+ accurate_range = 5
+ max_range = 5
+ damage = 42
+ damage_falloff = 10
+ penetration = 0
+ sundering = 5
+
+/datum/ammo/energy/lasgun/M43/spread
+ name = "additional laser blast"
+ icon_state = "laser2"
+ shell_speed = 2
+ accuracy_var_low = 9
+ accuracy_var_high = 9
+ accurate_range = 5
+ max_range = 5
+ damage = 35
+ damage_falloff = 10
+ penetration = 0
+
+/datum/ammo/energy/lasgun/M43/disabler
+ name = "disabler bolt"
+ icon_state = "disablershot"
+ hud_state = "laser_disabler"
+ damage = 45
+ penetration = 0
+ damage_type = STAMINA
+ bullet_color = COLOR_DISABLER_BLUE
+
+/datum/ammo/energy/lasgun/M43/disabler/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, stagger = 1 SECONDS, slowdown = 0.75)
+
+/datum/ammo/energy/lasgun/pulsebolt
+ name = "pulse bolt"
+ icon_state = "pulse2"
+ hud_state = "pulse"
+ damage = 45 // this is gotta hurt...
+ max_range = 40
+ penetration = 100
+ sundering = 100
+ bullet_color = COLOR_PULSE_BLUE
+
+/datum/ammo/energy/lasgun/M43/practice
+ name = "practice laser bolt"
+ icon_state = "disablershot"
+ hud_state = "laser_disabler"
+ damage = 45
+ penetration = 0
+ damage_type = STAMINA
+ flags_ammo_behavior = AMMO_ENERGY
+ bullet_color = COLOR_DISABLER_BLUE
+
+/datum/ammo/energy/lasgun/M43/practice/on_hit_mob(mob/living/carbon/C, obj/projectile/P)
+ if(!istype(C) || C.stat == DEAD || C.issamexenohive(P.firer) )
+ return
+
+ if(isnestedhost(C))
+ return
+
+ staggerstun(C, P, stagger = 2 SECONDS, slowdown = 1) //Staggers and slows down briefly
+
+ return ..()
+
+// TE Lasers //
+
+/datum/ammo/energy/lasgun/marine
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN
+ damage = 20
+ penetration = 10
+ sundering = 1.5
+ max_range = 30
+ hitscan_effect_icon = "beam"
+
+/datum/ammo/energy/lasgun/marine/sniper_overcharge
+ name = "sniper overcharge bolt"
+ icon_state = "overchargedlaser"
+ hud_state = "laser_sniper_overcharge"
+ shell_speed = 2.5
+ damage = 100
+ penetration = 80
+ accurate_range_min = 6
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_SNIPER
+ sundering = 10
+ hitscan_effect_icon = "beam_heavy_charge"
+ bullet_color = COLOR_DISABLER_BLUE
+
+/datum/ammo/energy/lasgun/marine/carbine
+ sundering = 1
+ max_range = 18
+
+/datum/ammo/energy/lasgun/marine/overcharge
+ name = "overcharged laser bolt"
+ icon_state = "overchargedlaser"
+ hud_state = "laser_sniper"
+ damage = 40
+ penetration = 20
+ sundering = 2
+ hitscan_effect_icon = "beam_heavy"
+
+/datum/ammo/energy/lasgun/marine/weakening
+ name = "weakening laser bolt"
+ icon_state = "overchargedlaser"
+ hud_state = "laser_sniper"
+ damage = 30
+ penetration = 10
+ sundering = 0
+ damage_type = STAMINA
+ hitscan_effect_icon = "blue_beam"
+ bullet_color = COLOR_DISABLER_BLUE
+ ///plasma drained per hit
+ var/plasma_drain = 25
+
+/datum/ammo/energy/lasgun/marine/weakening/on_hit_mob(mob/M, obj/projectile/proj)
+ staggerstun(M, proj, max_range = 6, slowdown = 1)
+
+ if(!isxeno(M))
+ return
+ var/mob/living/carbon/xenomorph/xeno_victim = M
+ xeno_victim.use_plasma(plasma_drain * xeno_victim.xeno_caste.plasma_regen_limit)
+
+/datum/ammo/energy/lasgun/marine/microwave
+ name = "microwave laser bolt"
+ icon_state = "overchargedlaser"
+ hud_state = "laser_sniper"
+ damage = 20
+ penetration = 20
+ sundering = 2
+ hitscan_effect_icon = "beam_grass"
+ bullet_color = LIGHT_COLOR_GREEN
+ ///number of microwave stacks to apply when hitting mobvs
+ var/microwave_stacks = 1
+
+/datum/ammo/energy/lasgun/marine/microwave/on_hit_mob(mob/M, obj/projectile/proj)
+ if(!isliving(M))
+ return
+
+ var/mob/living/living_victim = M
+ var/datum/status_effect/stacking/microwave/debuff = living_victim.has_status_effect(STATUS_EFFECT_MICROWAVE)
+
+ if(debuff)
+ debuff.add_stacks(microwave_stacks)
+ else
+ living_victim.apply_status_effect(STATUS_EFFECT_MICROWAVE, microwave_stacks)
+
+/datum/ammo/energy/lasgun/marine/blast
+ name = "wide range laser blast"
+ icon_state = "heavylaser2"
+ hud_state = "laser_spread"
+ bonus_projectiles_type = /datum/ammo/energy/lasgun/marine/blast/spread
+ bonus_projectiles_amount = 2
+ bonus_projectiles_scatter = 5
+ accuracy_var_low = 9
+ accuracy_var_high = 9
+ accurate_range = 5
+ max_range = 8
+ damage = 35
+ penetration = 20
+ sundering = 1
+ hitscan_effect_icon = "pu_laser"
+ bullet_color = LIGHT_COLOR_PURPLE
+
+/datum/ammo/energy/lasgun/marine/blast/spread
+ name = "additional laser blast"
+
+/datum/ammo/energy/lasgun/marine/impact
+ name = "impact laser blast"
+ icon_state = "overchargedlaser"
+ hud_state = "laser_sniper"
+ damage = 35
+ penetration = 10
+ sundering = 0
+ hitscan_effect_icon = "pu_laser"
+ bullet_color = LIGHT_COLOR_PURPLE
+
+/datum/ammo/energy/lasgun/marine/impact/on_hit_mob(mob/M, obj/projectile/proj)
+ var/knockback_dist = round(LERP(3, 1, proj.distance_travelled / 6), 1)
+ staggerstun(M, proj, max_range = 6, knockback = knockback_dist)
+
+/datum/ammo/energy/lasgun/marine/cripple
+ name = "impact laser blast"
+ icon_state = "overchargedlaser"
+ hud_state = "laser_sniper"
+ damage = 20
+ penetration = 10
+ sundering = 0
+ hitscan_effect_icon = "blue_beam"
+ bullet_color = COLOR_DISABLER_BLUE
+
+/datum/ammo/energy/lasgun/marine/cripple/on_hit_mob(mob/M, obj/projectile/proj)
+ staggerstun(M, proj, slowdown = 1.5)
+
+/datum/ammo/energy/lasgun/marine/autolaser
+ name = "machine laser bolt"
+ damage = 18
+ penetration = 15
+ sundering = 1
+
+/datum/ammo/energy/lasgun/marine/autolaser/burst
+ name = "burst machine laser bolt"
+ hud_state = "laser_efficiency"
+ damage = 12
+
+/datum/ammo/energy/lasgun/marine/autolaser/charge
+ name = "charged machine laser bolt"
+ hud_state = "laser_efficiency"
+ damage = 50
+ penetration = 30
+ sundering = 3
+ hitscan_effect_icon = "beam_heavy"
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_PASS_THROUGH_MOB
+
+/datum/ammo/energy/lasgun/marine/autolaser/charge/on_hit_turf(turf/T, obj/projectile/proj)
+ if(istype(T, /turf/closed/wall))
+ var/turf/closed/wall/wall_victim = T
+ wall_victim.take_damage(proj.damage, proj.damtype, proj.armor_type)
+
+/datum/ammo/energy/lasgun/marine/autolaser/melting
+ name = "melting machine laser bolt"
+ hud_state = "laser_efficiency"
+ damage = 15
+ penetration = 20
+ sundering = 0
+ hitscan_effect_icon = "beam_solar"
+ bullet_color = LIGHT_COLOR_YELLOW
+ ///number of melting stacks to apply when hitting mobs
+ var/melt_stacks = 2
+
+/datum/ammo/energy/lasgun/marine/autolaser/melting/on_hit_mob(mob/M, obj/projectile/proj)
+ if(!isliving(M))
+ return
+
+ var/mob/living/living_victim = M
+ var/datum/status_effect/stacking/melting/debuff = living_victim.has_status_effect(STATUS_EFFECT_MELTING)
+
+ if(debuff)
+ debuff.add_stacks(melt_stacks)
+ else
+ living_victim.apply_status_effect(STATUS_EFFECT_MELTING, melt_stacks)
+
+/datum/ammo/energy/lasgun/marine/sniper
+ name = "sniper laser bolt"
+ hud_state = "laser_sniper"
+ damage = 60
+ penetration = 30
+ accurate_range_min = 5
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_SNIPER
+ sundering = 5
+ max_range = 40
+ damage_falloff = 0
+ hitscan_effect_icon = "beam_heavy"
+
+/datum/ammo/energy/lasgun/marine/sniper_heat
+ name = "sniper heat bolt"
+ icon_state = "microwavelaser"
+ hud_state = "laser_heat"
+ damage = 40
+ penetration = 30
+ accurate_range_min = 5
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_INCENDIARY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_SNIPER
+ sundering = 1
+ hitscan_effect_icon = "beam_incen"
+ bullet_color = COLOR_RED_LIGHT
+
+/datum/ammo/energy/lasgun/marine/shatter
+ name = "sniper shattering bolt"
+ icon_state = "microwavelaser"
+ hud_state = "laser_heat"
+ damage = 40
+ penetration = 30
+ accurate_range_min = 5
+ sundering = 10
+ hitscan_effect_icon = "pu_laser"
+ bullet_color = LIGHT_COLOR_PURPLE
+ ///shatter effection duration when hitting mobs
+ var/shatter_duration = 5 SECONDS
+
+/datum/ammo/energy/lasgun/marine/shatter/on_hit_mob(mob/M, obj/projectile/proj)
+ if(!isliving(M))
+ return
+
+ var/mob/living/living_victim = M
+ living_victim.apply_status_effect(STATUS_EFFECT_SHATTER, shatter_duration)
+
+/datum/ammo/energy/lasgun/marine/shatter/heavy_laser
+ sundering = 1
+ accurate_range_min = 0
+
+/datum/ammo/energy/lasgun/marine/ricochet
+ name = "sniper laser bolt"
+ icon_state = "microwavelaser"
+ hud_state = "laser_heat"
+ damage = 100
+ penetration = 30
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_SNIPER
+ sundering = 1
+ hitscan_effect_icon = "u_laser_beam"
+ bonus_projectiles_scatter = 0
+ bullet_color = COLOR_DISABLER_BLUE
+
+/datum/ammo/energy/lasgun/marine/ricochet/one
+ damage = 80
+ bonus_projectiles_type = /datum/ammo/energy/lasgun/marine/ricochet
+
+/datum/ammo/energy/lasgun/marine/ricochet/two
+ damage = 65
+ bonus_projectiles_type = /datum/ammo/energy/lasgun/marine/ricochet/one
+
+/datum/ammo/energy/lasgun/marine/ricochet/three
+ damage = 50
+ bonus_projectiles_type = /datum/ammo/energy/lasgun/marine/ricochet/two
+
+/datum/ammo/energy/lasgun/marine/ricochet/four
+ damage = 40
+ bonus_projectiles_type = /datum/ammo/energy/lasgun/marine/ricochet/three
+
+/datum/ammo/energy/lasgun/marine/ricochet/on_hit_turf(turf/T, obj/projectile/proj)
+ reflect(T, proj, 5)
+
+/datum/ammo/energy/lasgun/marine/ricochet/on_hit_obj(obj/O, obj/projectile/proj)
+ reflect(get_turf(O), proj, 5)
+
+/datum/ammo/energy/lasgun/marine/pistol
+ name = "pistol laser bolt"
+ damage = 20
+ penetration = 5
+ sundering = 1
+ hitscan_effect_icon = "beam_particle"
+ bullet_color = COLOR_DISABLER_BLUE
+
+/datum/ammo/energy/lasgun/marine/pistol/disabler
+ name = "disabler bolt"
+ icon_state = "disablershot"
+ hud_state = "laser_disabler"
+ damage = 70
+ penetration = 0
+ damage_type = STAMINA
+ hitscan_effect_icon = "beam_stun"
+ bullet_color = LIGHT_COLOR_YELLOW
+
+/datum/ammo/energy/lasgun/marine/pistol/heat
+ name = "microwave heat bolt"
+ icon_state = "microwavelaser"
+ hud_state = "laser_heat"
+ damage = 20
+ shell_speed = 2.5
+ penetration = 10
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_INCENDIARY|AMMO_SUNDERING|AMMO_HITSCAN
+ sundering = 0.5
+ hitscan_effect_icon = "beam_incen"
+ bullet_color = COLOR_LASER_RED
+
+/datum/ammo/energy/lasgun/pistol/disabler/on_hit_mob(mob/M,obj/projectile/P)
+ staggerstun(M, P, stagger = 1 SECONDS, slowdown = 0.75)
+
+/datum/ammo/energy/lasgun/marine/xray
+ name = "xray heat bolt"
+ hud_state = "laser_xray"
+ icon_state = "u_laser"
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_INCENDIARY|AMMO_SUNDERING|AMMO_HITSCAN
+ damage = 25
+ penetration = 5
+ sundering = 1
+ max_range = 15
+ hitscan_effect_icon = "u_laser_beam"
+
+/datum/ammo/energy/lasgun/marine/xray/piercing
+ name = "xray piercing bolt"
+ icon_state = "xray"
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_HITSCAN|AMMO_PASS_THROUGH_TURF|AMMO_PASS_THROUGH_MOVABLE
+ damage = 25
+ penetration = 100
+ max_range = 10
+ hitscan_effect_icon = "xray_beam"
+
+/datum/ammo/energy/lasgun/marine/heavy_laser
+ flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_INCENDIARY
+ hud_state = "laser_overcharge"
+ damage = 60
+ penetration = 10
+ sundering = 1
+ max_range = 30
+ hitscan_effect_icon = "beam_incen"
+
+/datum/ammo/energy/lasgun/marine/heavy_laser/drop_nade(turf/T, radius = 1)
+ if(!T || !isturf(T))
+ return
+ playsound(T, 'sound/weapons/guns/fire/flamethrower2.ogg', 50, 1, 4)
+ flame_radius(radius, T, 3, 3, 3, 3)
+
+/datum/ammo/energy/lasgun/marine/heavy_laser/on_hit_mob(mob/M, obj/projectile/P)
+ drop_nade(get_turf(M))
+
+/datum/ammo/energy/lasgun/marine/heavy_laser/on_hit_obj(obj/O, obj/projectile/P)
+ drop_nade(O.density ? get_step_towards(O, P) : O, P)
+
+/datum/ammo/energy/lasgun/marine/heavy_laser/on_hit_turf(turf/T, obj/projectile/P)
+ drop_nade(T.density ? get_step_towards(T, P) : T)
+
+/datum/ammo/energy/lasgun/marine/heavy_laser/do_at_max_range(turf/T, obj/projectile/P)
+ drop_nade(T.density ? get_step_towards(T, P) : T)
+
+/datum/ammo/energy/xeno
+ barricade_clear_distance = 0
+ ///Plasma cost to fire this projectile
+ var/ability_cost
+ ///Particle type used when this ammo is used
+ var/particles/channel_particle
+ ///The colour the xeno glows when using this ammo type
+ var/glow_color
+
+/datum/ammo/energy/xeno/psy_blast
+ name = "psychic blast"
+ flags_ammo_behavior = AMMO_XENO|AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_SKIPS_ALIENS
+ damage = 35
+ penetration = 10
+ sundering = 1
+ max_range = 7
+ accurate_range = 7
+ hitscan_effect_icon = "beam_cult"
+ icon_state = "psy_blast"
+ ability_cost = 230
+ channel_particle = /particles/warlock_charge/psy_blast
+ glow_color = "#9e1f1f"
+ ///The AOE for drop_nade
+ var/aoe_range = 2
+
+/datum/ammo/energy/xeno/psy_blast/drop_nade(turf/T, obj/projectile/P)
+ if(!T || !isturf(T))
+ return
+ playsound(T, 'sound/effects/EMPulse.ogg', 50)
+ var/aoe_damage = 25
+ if(isxeno(P.firer))
+ var/mob/living/carbon/xenomorph/xeno_firer = P.firer
+ aoe_damage = xeno_firer.xeno_caste.blast_strength
+
+ var/list/throw_atoms = list()
+ var/list/turf/target_turfs = generate_true_cone(T, aoe_range, -1, 359, 0, air_pass = TRUE)
+ for(var/turf/target_turf AS in target_turfs)
+ for(var/atom/movable/target AS in target_turf)
+ if(isliving(target))
+ var/mob/living/living_victim = target
+ if(living_victim.stat == DEAD)
+ continue
+ if(!isxeno(living_victim))
+ living_victim.apply_damage(aoe_damage, BURN, null, ENERGY, FALSE, FALSE, TRUE, penetration)
+ staggerstun(living_victim, P, 10, slowdown = 1)
+ else if(isobj(target))
+ var/obj/obj_victim = target
+ if(!(obj_victim.resistance_flags & XENO_DAMAGEABLE))
+ continue
+ obj_victim.take_damage(aoe_damage, BURN, ENERGY, TRUE, armour_penetration = penetration)
+ if(target.anchored)
+ continue
+ throw_atoms += target
+
+ for(var/atom/movable/target AS in throw_atoms)
+ var/throw_dir = get_dir(T, target)
+ if(T == get_turf(target))
+ throw_dir = get_dir(P.starting_turf, T)
+ target.safe_throw_at(get_ranged_target_turf(T, throw_dir, 5), 3, 1, spin = TRUE)
+
+ new /obj/effect/temp_visual/shockwave(T, aoe_range + 2)
+
+/datum/ammo/energy/xeno/psy_blast/on_hit_mob(mob/M, obj/projectile/P)
+ drop_nade(get_turf(M), P)
+
+/datum/ammo/energy/xeno/psy_blast/on_hit_obj(obj/O, obj/projectile/P)
+ drop_nade(O.density ? get_step_towards(O, P) : O, P)
+
+/datum/ammo/energy/xeno/psy_blast/on_hit_turf(turf/T, obj/projectile/P)
+ drop_nade(T.density ? get_step_towards(T, P) : T, P)
+
+/datum/ammo/energy/xeno/psy_blast/do_at_max_range(turf/T, obj/projectile/P)
+ drop_nade(T.density ? get_step_towards(T, P) : T, P)
+
+/datum/ammo/energy/xeno/psy_blast/psy_lance
+ name = "psychic lance"
+ flags_ammo_behavior = AMMO_XENO|AMMO_ENERGY|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_PASS_THROUGH_MOVABLE
+ damage = 60
+ penetration = 50
+ accuracy = 100
+ sundering = 5
+ max_range = 16
+ hitscan_effect_icon = "beam_hcult"
+ icon_state = "psy_lance"
+ ability_cost = 300
+ channel_particle = /particles/warlock_charge/psy_blast/psy_lance
+ glow_color = "#CB0166"
+
+/datum/ammo/energy/xeno/psy_blast/psy_lance/on_hit_obj(obj/O, obj/projectile/P)
+ if(isvehicle(O))
+ var/obj/vehicle/veh_victim = O
+ veh_victim.take_damage(200, BURN, ENERGY, TRUE, armour_penetration = penetration)
+
+/datum/ammo/energy/xeno/psy_blast/psy_lance/on_hit_mob(mob/M, obj/projectile/P)
+ if(isxeno(M))
+ return
+ staggerstun(M, P, 9, stagger = 4 SECONDS, slowdown = 2, knockback = 1)
+
+/datum/ammo/energy/xeno/psy_blast/psy_lance/on_hit_turf(turf/T, obj/projectile/P)
+ return
+
+/datum/ammo/energy/xeno/psy_blast/psy_lance/do_at_max_range(turf/T, obj/projectile/P)
+ return
+
+// Plasma //
+/datum/ammo/energy/plasma
+ name = "plasma bolt"
+ icon_state = "pulse2"
+ hud_state = "plasma"
+ armor_type = LASER
+ shell_speed = 4
+ accurate_range = 15
+ damage = 40
+ penetration = 15
+ max_range = 30
+ accuracy_var_low = 3
+ accuracy_var_high = 3
+
+/datum/ammo/energy/plasma_pistol
+ name = "ionized plasma bolt"
+ icon_state = "overchargedlaser"
+ hud_state = "electrothermal"
+ hud_state_empty = "electrothermal_empty"
+ damage = 40
+ max_range = 14
+ penetration = 5
+ shell_speed = 1.5
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_INCENDIARY|AMMO_EXPLOSIVE
+ bullet_color = LIGHT_COLOR_ELECTRIC_GREEN
+ ///Fire burn time
+ var/heat = 12
+ ///Fire damage
+ var/burn_damage = 9
+ ///Fire color
+ var/fire_color = "green"
+
+/datum/ammo/energy/plasma_pistol/proc/drop_fire(atom/target, obj/projectile/proj)
+ var/turf/target_turf = get_turf(target)
+ var/burn_mod = 1
+ if(istype(target_turf, /turf/closed/wall))
+ burn_mod = 3
+ target_turf.ignite(heat, burn_damage * burn_mod, fire_color)
+
+ for(var/mob/living/mob_caught in target_turf)
+ if(mob_caught.stat == DEAD || mob_caught == target)
+ continue
+ mob_caught.adjust_fire_stacks(burn_damage)
+ mob_caught.IgniteMob()
+
+/datum/ammo/energy/plasma_pistol/on_hit_turf(turf/T, obj/projectile/proj)
+ drop_fire(T, proj)
+
+/datum/ammo/energy/plasma_pistol/on_hit_mob(mob/M, obj/projectile/proj)
+ drop_fire(M, proj)
+
+/datum/ammo/energy/plasma_pistol/on_hit_obj(obj/O, obj/projectile/proj)
+ drop_fire(O, proj)
+
+/datum/ammo/energy/plasma_pistol/do_at_max_range(turf/T, obj/projectile/proj)
+ drop_fire(T, proj)
+
+//volkite
+/datum/ammo/energy/volkite
+ name = "thermal energy bolt"
+ icon_state = "overchargedlaser"
+ hud_state = "laser_heat"
+ hud_state_empty = "battery_empty_flash"
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_SUNDERING|AMMO_SOUND_PITCH
+ bullet_color = COLOR_TAN_ORANGE
+ armor_type = ENERGY
+ max_range = 14
+ accurate_range = 5 //for charger
+ shell_speed = 4
+ accuracy_var_low = 5
+ accuracy_var_high = 5
+ accuracy = 5
+ point_blank_range = 2
+ damage = 20
+ penetration = 10
+ sundering = 2
+ fire_burst_damage = 15
+
+ //inherited, could use some changes
+ ping = "ping_s"
+ sound_hit = "energy_hit"
+ sound_armor = "ballistic_armor"
+ sound_miss = "ballistic_miss"
+ sound_bounce = "ballistic_bounce"
+
+/datum/ammo/energy/volkite/on_hit_mob(mob/M,obj/projectile/P)
+ deflagrate(M, P)
+
+/datum/ammo/energy/volkite/medium
+ max_range = 25
+ accurate_range = 12
+ damage = 30
+ accuracy_var_low = 3
+ accuracy_var_high = 3
+ fire_burst_damage = 20
+
+/datum/ammo/energy/volkite/medium/custom
+ deflagrate_multiplier = 2
+
+/datum/ammo/energy/volkite/heavy
+ max_range = 35
+ accurate_range = 12
+ damage = 25
+ fire_burst_damage = 20
+
+/datum/ammo/energy/volkite/light
+ max_range = 25
+ accurate_range = 12
+ accuracy_var_low = 3
+ accuracy_var_high = 3
+ penetration = 5
diff --git a/code/modules/projectiles/ammo_datums/flamethrower.dm b/code/modules/projectiles/ammo_datums/flamethrower.dm
new file mode 100644
index 00000000000..6f10f6e56b5
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/flamethrower.dm
@@ -0,0 +1,79 @@
+
+/datum/ammo/flamethrower
+ name = "flame"
+ icon_state = "pulse0"
+ hud_state = "flame"
+ hud_state_empty = "flame_empty"
+ damage_type = BURN
+ flags_ammo_behavior = AMMO_INCENDIARY|AMMO_FLAME|AMMO_EXPLOSIVE
+ armor_type = FIRE
+ max_range = 7
+ damage = 31
+ damage_falloff = 0
+ incendiary_strength = 30 //Firestacks cap at 20, but that's after armor.
+ bullet_color = LIGHT_COLOR_FIRE
+ var/fire_color = "red"
+ var/burntime = 17
+ var/burnlevel = 31
+
+/datum/ammo/flamethrower/drop_flame(turf/T)
+ if(!istype(T))
+ return
+ T.ignite(burntime, burnlevel, fire_color)
+
+/datum/ammo/flamethrower/on_hit_mob(mob/M, obj/projectile/P)
+ drop_flame(get_turf(M))
+
+/datum/ammo/flamethrower/on_hit_obj(obj/O, obj/projectile/P)
+ drop_flame(get_turf(O))
+
+/datum/ammo/flamethrower/on_hit_turf(turf/T, obj/projectile/P)
+ drop_flame(get_turf(T))
+
+/datum/ammo/flamethrower/do_at_max_range(turf/T, obj/projectile/P)
+ drop_flame(get_turf(T))
+
+/datum/ammo/flamethrower/tank_flamer/drop_flame(turf/T)
+ if(!istype(T))
+ return
+ flame_radius(2, T)
+
+/datum/ammo/flamethrower/blue
+ name = "blue flame"
+ hud_state = "flame_blue"
+ max_range = 7
+ fire_color = "blue"
+ burntime = 40
+ burnlevel = 46
+ bullet_color = COLOR_NAVY
+
+/datum/ammo/water
+ name = "water"
+ icon_state = "pulse1"
+ hud_state = "water"
+ hud_state_empty = "water_empty"
+ damage = 0
+ shell_speed = 1
+ damage_type = BURN
+ flags_ammo_behavior = AMMO_EXPLOSIVE
+ bullet_color = null
+
+/datum/ammo/water/proc/splash(turf/extinguished_turf, splash_direction)
+ var/obj/flamer_fire/current_fire = locate(/obj/flamer_fire) in extinguished_turf
+ if(current_fire)
+ qdel(current_fire)
+ for(var/mob/living/mob_caught in extinguished_turf)
+ mob_caught.ExtinguishMob()
+ new /obj/effect/temp_visual/dir_setting/water_splash(extinguished_turf, splash_direction)
+
+/datum/ammo/water/on_hit_mob(mob/M, obj/projectile/P)
+ splash(get_turf(M), P.dir)
+
+/datum/ammo/water/on_hit_obj(obj/O, obj/projectile/P)
+ splash(get_turf(O), P.dir)
+
+/datum/ammo/water/on_hit_turf(turf/T, obj/projectile/P)
+ splash(get_turf(T), P.dir)
+
+/datum/ammo/water/do_at_max_range(turf/T, obj/projectile/P)
+ splash(get_turf(T), P.dir)
diff --git a/code/modules/projectiles/ammo_datums/mecha.dm b/code/modules/projectiles/ammo_datums/mecha.dm
new file mode 100644
index 00000000000..8507df55b14
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/mecha.dm
@@ -0,0 +1,150 @@
+/datum/ammo/bullet/pistol/mech
+ name = "super-heavy pistol bullet"
+ hud_state = "pistol_superheavy"
+ damage = 45
+ penetration = 20
+ sundering = 1
+
+/datum/ammo/bullet/pistol/mech/burst
+ name = "super-heavy pistol bullet"
+ damage = 35
+ penetration = 10
+ sundering = 0.5
+
+/datum/ammo/bullet/smg/mech
+ name = "super-heavy submachinegun bullet"
+ damage = 20
+ sundering = 0.25
+ penetration = 10
+
+/datum/ammo/bullet/rifle/mech
+ name = "super-heavy rifle bullet"
+ damage = 25
+ penetration = 15
+ sundering = 0.5
+ damage_falloff = 0.8
+
+/datum/ammo/bullet/rifle/mech/burst
+ damage = 35
+ penetration = 10
+
+/datum/ammo/bullet/rifle/mech/lmg
+ damage = 20
+ penetration = 20
+ damage_falloff = 0.7
+
+/datum/ammo/bullet/shotgun/mech
+ name = "super-heavy shotgun buckshot shell"
+ icon_state = "buckshot"
+ hud_state = "shotgun_buckshot"
+ bonus_projectiles_type = /datum/ammo/bullet/shotgun/mech/spread
+ bonus_projectiles_amount = 2
+ bonus_projectiles_scatter = 5
+ accuracy_var_low = 10
+ accuracy_var_high = 10
+ max_range = 10
+ damage = 100
+ damage_falloff = 4
+
+/datum/ammo/bullet/shotgun/mech/spread
+ name = "super-heavy additional buckshot"
+ icon_state = "buckshot"
+ max_range = 10
+ damage = 75
+ damage_falloff = 4
+
+/datum/ammo/bullet/shotgun/mech/on_hit_mob(mob/M, obj/projectile/proj)
+ staggerstun(M, proj, weaken = 2 SECONDS, stagger = 2 SECONDS, knockback = 2, slowdown = 0.5, max_range = 3)
+
+/datum/ammo/tx54/mech
+ name = "30mm fragmentation grenade"
+ bonus_projectiles_type = /datum/ammo/bullet/tx54_spread/mech
+ damage = 15
+ penetration = 10
+ projectile_greyscale_colors = "#4f0303"
+
+/datum/ammo/bullet/tx54_spread/mech
+ damage = 15
+ penetration = 10
+ sundering = 0.5
+
+/datum/ammo/bullet/tx54_spread/mech/on_hit_mob(mob/M, obj/projectile/proj)
+ staggerstun(M, proj, max_range = 3, slowdown = 0.2)
+
+/datum/ammo/energy/lasgun/marine/mech
+ name = "superheated laser bolt"
+ damage = 45
+ penetration = 20
+ sundering = 1
+ damage_falloff = 0.5
+
+/datum/ammo/energy/lasgun/marine/mech/burst
+ damage = 30
+ penetration = 10
+ sundering = 0.75
+ damage_falloff = 0.6
+
+/datum/ammo/energy/lasgun/marine/mech/smg
+ name = "superheated pulsed laser bolt"
+ damage = 15
+ penetration = 10
+ hitscan_effect_icon = "beam_particle"
+
+/datum/ammo/energy/lasgun/marine/mech/lance_strike
+ name = "particle lance"
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_SNIPER|AMMO_SUNDERING|AMMO_HITSCAN|AMMO_PASS_THROUGH_MOVABLE|AMMO_PASS_THROUGH_MOB
+ damage_type = BRUTE
+ damage = 100
+ armor_type = MELEE
+ penetration = 25
+ sundering = 8
+ damage_falloff = -12.5 //damage increases per turf crossed
+ max_range = 4
+ on_pierce_multiplier = 0.5
+ hitscan_effect_icon = "lance"
+
+/datum/ammo/energy/lasgun/marine/mech/lance_strike/super
+ damage = 120
+ damage_falloff = -8
+ max_range = 5
+
+/datum/ammo/bullet/apfsds
+ name = "\improper APFSDS round"
+ hud_state = "alloy_spike"
+ icon_state = "blue_bullet"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOVABLE|AMMO_UNWIELDY
+ shell_speed = 4
+ max_range = 14
+ damage = 150
+ penetration = 100
+ sundering = 0
+ bullet_color = COLOR_PULSE_BLUE
+ on_pierce_multiplier = 0.85
+
+/datum/ammo/bullet/minigun/mech
+ name = "vulcan bullet"
+ damage = 30
+ penetration = 10
+ sundering = 0.5
+
+/datum/ammo/bullet/sniper/mech
+ name = "light anti-tank bullet"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_SNIPER|AMMO_IFF
+ damage = 100
+ penetration = 35
+ sundering = 0
+ damage_falloff = 0.3
+
+/datum/ammo/flamethrower/mech_flamer/drop_flame(turf/T)
+ if(!istype(T))
+ return
+ flame_radius(1, T)
+
+/datum/ammo/rocket/mech
+ name = "large high-explosive rocket"
+ damage = 75
+ penetration = 50
+ max_range = 30
+
+/datum/ammo/rocket/mech/drop_nade(turf/T)
+ cell_explosion(T, 75, 15)
diff --git a/code/modules/projectiles/ammo_datums/misc.dm b/code/modules/projectiles/ammo_datums/misc.dm
new file mode 100644
index 00000000000..72b2b13ecb0
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/misc.dm
@@ -0,0 +1,473 @@
+/*
+//================================================
+ Turret
+//================================================
+*/
+
+/datum/ammo/bullet/turret
+ name = "autocannon bullet"
+ bullet_color = COLOR_SOFT_RED
+ hud_state = "rifle"
+ hud_state_empty = "rifle_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_SENTRY
+ accurate_range = 10
+ damage = 25
+ penetration = 20
+ damage_falloff = 0.25
+
+/datum/ammo/bullet/turret/dumb
+ icon_state = "bullet"
+
+/datum/ammo/bullet/turret/gauss
+ name = "heavy gauss turret slug"
+ hud_state = "rifle_heavy"
+ damage = 60
+
+/datum/ammo/bullet/turret/mini
+ name = "small caliber autocannon bullet"
+ damage = 20
+ penetration = 20
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SENTRY
+
+/*
+//================================================
+ tx54 and etc.
+//================================================
+*/
+
+/datum/ammo/tx54
+ name = "20mm airburst grenade"
+ icon_state = "20mm_flight"
+ hud_state = "grenade_airburst"
+ hud_state_empty = "grenade_empty"
+ handful_icon_state = "20mm_airburst"
+ handful_amount = 3
+ ping = null //no bounce off.
+ sound_bounce = "rocket_bounce"
+ flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_SUNDERING
+ armor_type = BOMB
+ damage_falloff = 0.5
+ shell_speed = 2
+ accurate_range = 12
+ max_range = 15
+ damage = 12 //impact damage from a grenade to the dome
+ penetration = 0
+ sundering = 0
+ shrapnel_chance = 0
+ bonus_projectiles_type = /datum/ammo/bullet/tx54_spread
+ bonus_projectiles_scatter = 10
+ ///How many
+ var/bonus_projectile_quantity = 7
+
+ handful_greyscale_config = /datum/greyscale_config/ammo
+ handful_greyscale_colors = COLOR_AMMO_AIRBURST
+
+ projectile_greyscale_config = /datum/greyscale_config/projectile
+ projectile_greyscale_colors = COLOR_AMMO_AIRBURST
+
+/datum/ammo/tx54/on_hit_mob(mob/M, obj/projectile/proj)
+ staggerstun(M, proj, slowdown = 0.5, knockback = 1)
+ playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
+ fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 4, 3, Get_Angle(proj.firer, M) )
+
+/datum/ammo/tx54/on_hit_obj(obj/O, obj/projectile/proj)
+ playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
+ fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 4, 3, Get_Angle(proj.firer, O) )
+
+/datum/ammo/tx54/on_hit_turf(turf/T, obj/projectile/proj)
+ playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
+ fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 4, 3, Get_Angle(proj.firer, T) )
+
+/datum/ammo/tx54/do_at_max_range(turf/T, obj/projectile/proj)
+ playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
+ fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 4, 3, Get_Angle(proj.firer, get_turf(proj)) )
+
+/datum/ammo/tx54/incendiary
+ name = "20mm incendiary grenade"
+ hud_state = "grenade_fire"
+ bonus_projectiles_type = /datum/ammo/bullet/tx54_spread/incendiary
+ bullet_color = LIGHT_COLOR_FIRE
+ handful_greyscale_colors = COLOR_AMMO_INCENDIARY
+ projectile_greyscale_colors = COLOR_AMMO_INCENDIARY
+
+/datum/ammo/tx54/smoke
+ name = "20mm tactical smoke grenade"
+ hud_state = "grenade_hide"
+ bonus_projectiles_type = /datum/ammo/bullet/tx54_spread/smoke
+ bonus_projectiles_scatter = 24
+ bonus_projectile_quantity = 5
+ handful_greyscale_colors = COLOR_AMMO_TACTICAL_SMOKE
+ projectile_greyscale_colors = COLOR_AMMO_TACTICAL_SMOKE
+
+/datum/ammo/tx54/smoke/dense
+ name = "20mm smoke grenade"
+ hud_state = "grenade_smoke"
+ bonus_projectiles_type = /datum/ammo/bullet/tx54_spread/smoke/dense
+ handful_greyscale_colors = COLOR_AMMO_SMOKE
+ projectile_greyscale_colors = COLOR_AMMO_SMOKE
+
+/datum/ammo/tx54/smoke/tangle
+ name = "20mm tanglefoot grenade"
+ hud_state = "grenade_drain"
+ bonus_projectiles_type = /datum/ammo/bullet/tx54_spread/smoke/tangle
+ handful_greyscale_colors = COLOR_AMMO_TANGLEFOOT
+ projectile_greyscale_colors = COLOR_AMMO_TANGLEFOOT
+
+/datum/ammo/tx54/razor
+ name = "20mm razorburn grenade"
+ hud_state = "grenade_razor"
+ bonus_projectiles_type = /datum/ammo/bullet/tx54_spread/razor
+ bonus_projectiles_scatter = 50
+ bonus_projectile_quantity = 3
+ handful_greyscale_colors = COLOR_AMMO_RAZORBURN
+ projectile_greyscale_colors = COLOR_AMMO_RAZORBURN
+
+/datum/ammo/tx54/he
+ name = "20mm HE grenade"
+ hud_state = "grenade_he"
+ bonus_projectiles_type = null
+ max_range = 12
+ handful_greyscale_colors = COLOR_AMMO_HIGH_EXPLOSIVE
+ projectile_greyscale_colors = COLOR_AMMO_HIGH_EXPLOSIVE
+
+/datum/ammo/tx54/he/drop_nade(turf/T)
+ cell_explosion(T, 45, 25)
+
+/datum/ammo/tx54/he/on_hit_mob(mob/M, obj/projectile/P)
+ drop_nade(get_turf(M))
+
+/datum/ammo/tx54/he/on_hit_obj(obj/O, obj/projectile/P)
+ drop_nade(get_turf(O))
+
+/datum/ammo/tx54/he/on_hit_turf(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+/datum/ammo/tx54/he/do_at_max_range(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+//The secondary projectiles
+/datum/ammo/bullet/tx54_spread
+ name = "Shrapnel"
+ icon_state = "flechette"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB
+ accuracy_var_low = 5
+ accuracy_var_high = 5
+ max_range = 4
+ damage = 20
+ penetration = 20
+ sundering = 3
+ damage_falloff = 0
+
+/datum/ammo/bullet/tx54_spread/on_hit_mob(mob/M, obj/projectile/proj)
+ staggerstun(M, proj, max_range = 3, stagger = 0.6 SECONDS, slowdown = 0.3)
+
+/datum/ammo/bullet/tx54_spread/incendiary
+ name = "incendiary flechette"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB|AMMO_INCENDIARY|AMMO_LEAVE_TURF
+ damage = 15
+ penetration = 10
+ sundering = 1.5
+
+/datum/ammo/bullet/tx54_spread/incendiary/on_hit_mob(mob/M, obj/projectile/proj)
+ return
+
+/datum/ammo/bullet/tx54_spread/incendiary/drop_flame(turf/T)
+ if(!istype(T))
+ return
+ T.ignite(5, 10)
+
+/datum/ammo/bullet/tx54_spread/incendiary/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
+ drop_flame(T)
+
+/datum/ammo/bullet/tx54_spread/smoke
+ name = "chemical bomblet"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_PASS_THROUGH_MOB|AMMO_LEAVE_TURF
+ max_range = 3
+ damage = 5
+ penetration = 0
+ sundering = 0
+ ///The smoke type loaded in this ammo
+ var/datum/effect_system/smoke_spread/trail_spread_system = /datum/effect_system/smoke_spread/tactical
+
+/datum/ammo/bullet/tx54_spread/smoke/New()
+ . = ..()
+
+ trail_spread_system = new trail_spread_system(only_once = FALSE)
+
+/datum/ammo/bullet/tx54_spread/smoke/Destroy()
+ if(trail_spread_system)
+ QDEL_NULL(trail_spread_system)
+ return ..()
+
+/datum/ammo/bullet/tx54_spread/smoke/on_hit_mob(mob/M, obj/projectile/proj)
+ return
+
+/datum/ammo/bullet/tx54_spread/smoke/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
+ trail_spread_system.set_up(0, T)
+ trail_spread_system.start()
+
+/datum/ammo/bullet/tx54_spread/smoke/dense
+ trail_spread_system = /datum/effect_system/smoke_spread/bad
+
+/datum/ammo/bullet/tx54_spread/smoke/tangle
+ trail_spread_system = /datum/effect_system/smoke_spread/plasmaloss
+
+/datum/ammo/bullet/tx54_spread/razor
+ name = "chemical bomblet"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_PASS_THROUGH_MOB|AMMO_LEAVE_TURF
+ max_range = 4
+ damage = 5
+ penetration = 0
+ sundering = 0
+ ///The foam type loaded in this ammo
+ var/datum/effect_system/foam_spread/chemical_payload
+ ///The reagent content of the projectile
+ var/datum/reagents/reagent_list
+
+/datum/ammo/bullet/tx54_spread/razor/New()
+ . = ..()
+
+ chemical_payload = new
+ reagent_list = new
+ reagent_list.add_reagent(/datum/reagent/foaming_agent = 1)
+ reagent_list.add_reagent(/datum/reagent/toxin/nanites = 7)
+
+/datum/ammo/bullet/tx54_spread/razor/Destroy()
+ if(chemical_payload)
+ QDEL_NULL(chemical_payload)
+ return ..()
+
+/datum/ammo/bullet/tx54_spread/razor/on_hit_mob(mob/M, obj/projectile/proj)
+ return
+
+/datum/ammo/bullet/tx54_spread/razor/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
+ chemical_payload.set_up(0, T, reagent_list, RAZOR_FOAM)
+ chemical_payload.start()
+
+//10-gauge Micro rail shells - aka micronades
+/datum/ammo/bullet/micro_rail
+ hud_state_empty = "grenade_empty_flash"
+ handful_icon_state = "micro_grenade_airburst"
+ flags_ammo_behavior = AMMO_BALLISTIC
+ shell_speed = 2
+ handful_amount = 3
+ max_range = 3 //failure to detonate if the target is too close
+ damage = 15
+ bonus_projectiles_scatter = 12
+ ///How many bonus projectiles to generate. New var so it doesn't trigger on firing
+ var/bonus_projectile_quantity = 5
+ ///Max range for the bonus projectiles
+ var/bonus_projectile_range = 7
+ ///projectile speed for the bonus projectiles
+ var/bonus_projectile_speed = 3
+
+/datum/ammo/bullet/micro_rail/do_at_max_range(turf/T, obj/projectile/proj)
+ playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
+ var/datum/effect_system/smoke_spread/smoke = new
+ smoke.set_up(0, get_turf(proj), 1)
+ smoke.start()
+ fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, bonus_projectile_range, bonus_projectile_speed, Get_Angle(proj.firer, get_turf(proj)) )
+
+//piercing scatter shot
+/datum/ammo/bullet/micro_rail/airburst
+ name = "micro grenade"
+ handful_icon_state = "micro_grenade_airburst"
+ hud_state = "grenade_airburst"
+ bonus_projectiles_type = /datum/ammo/bullet/micro_rail_spread
+
+//incendiary piercing scatter shot
+/datum/ammo/bullet/micro_rail/dragonbreath
+ name = "micro grenade"
+ handful_icon_state = "micro_grenade_incendiary"
+ hud_state = "grenade_fire"
+ bonus_projectiles_type = /datum/ammo/bullet/micro_rail_spread/incendiary
+ bonus_projectile_range = 6
+
+//cluster grenade. Bomblets explode in a rough cone pattern
+/datum/ammo/bullet/micro_rail/cluster
+ name = "micro grenade"
+ handful_icon_state = "micro_grenade_cluster"
+ hud_state = "grenade_he"
+ bonus_projectiles_type = /datum/ammo/micro_rail_cluster
+ bonus_projectile_quantity = 7
+ bonus_projectile_range = 6
+ bonus_projectile_speed = 2
+
+//creates a literal smokescreen
+/datum/ammo/bullet/micro_rail/smoke_burst
+ name = "micro grenade"
+ handful_icon_state = "micro_grenade_smoke"
+ hud_state = "grenade_smoke"
+ bonus_projectiles_type = /datum/ammo/smoke_burst
+ bonus_projectiles_scatter = 20
+ bonus_projectile_range = 6
+ bonus_projectile_speed = 2
+
+//submunitions for micro grenades
+/datum/ammo/bullet/micro_rail_spread
+ name = "Shrapnel"
+ icon_state = "flechette"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB
+ accuracy_var_low = 5
+ accuracy_var_high = 5
+ max_range = 7
+ damage = 20
+ penetration = 20
+ sundering = 3
+ damage_falloff = 1
+
+/datum/ammo/bullet/micro_rail_spread/on_hit_mob(mob/M, obj/projectile/proj)
+ staggerstun(M, proj, stagger = 1 SECONDS, slowdown = 0.5)
+
+/datum/ammo/bullet/micro_rail_spread/incendiary
+ name = "incendiary flechette"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_MOB|AMMO_INCENDIARY|AMMO_LEAVE_TURF
+ damage = 15
+ penetration = 5
+ sundering = 1.5
+ max_range = 6
+
+/datum/ammo/bullet/micro_rail_spread/incendiary/on_hit_mob(mob/M, obj/projectile/proj)
+ staggerstun(M, proj, stagger = 0.4 SECONDS, slowdown = 0.2)
+
+/datum/ammo/bullet/micro_rail_spread/incendiary/drop_flame(turf/T)
+ if(!istype(T))
+ return
+ T.ignite(5, 10)
+
+/datum/ammo/bullet/micro_rail_spread/incendiary/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
+ if(prob(40))
+ drop_flame(T)
+
+/datum/ammo/micro_rail_cluster
+ name = "bomblet"
+ icon_state = "bullet"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_LEAVE_TURF
+ sound_hit = "ballistic_hit"
+ sound_armor = "ballistic_armor"
+ sound_miss = "ballistic_miss"
+ sound_bounce = "ballistic_bounce"
+ shell_speed = 2
+ damage = 5
+ accuracy = -60 //stop you from just emptying all the bomblets into one guys face for big damage
+ shrapnel_chance = 0
+ max_range = 6
+ bullet_color = COLOR_VERY_SOFT_YELLOW
+ ///the smoke effect at the point of detonation
+ var/datum/effect_system/smoke_spread/smoketype = /datum/effect_system/smoke_spread
+ ///Total damage applied to victims by the exploding bomblet
+ var/explosion_damage = 20
+ ///Amount of stagger applied by the exploding bomblet
+ var/stagger_amount = 2 SECONDS
+ ///Amount of slowdown applied by the exploding bomblet
+ var/slow_amount = 1
+ ///range of bomblet explosion
+ var/explosion_range = 2
+
+///handles the actual bomblet detonation
+/datum/ammo/micro_rail_cluster/proc/detonate(turf/T, obj/projectile/P)
+ playsound(T, sound(get_sfx("explosion_micro")), 30, falloff = 5)
+ var/datum/effect_system/smoke_spread/smoke = new smoketype()
+ smoke.set_up(0, T, rand(1,2))
+ smoke.start()
+
+ var/list/turf/target_turfs = generate_true_cone(T, explosion_range, -1, 359, 0, air_pass = TRUE)
+ for(var/turf/target_turf AS in target_turfs)
+ for(var/target in target_turf)
+ if(isliving(target))
+ var/mob/living/living_target = target
+ living_target.visible_message(span_danger("[living_target] is hit by the bomblet blast!"),
+ isxeno(living_target) ? span_xenodanger("We are hit by the bomblet blast!") : span_highdanger("you are hit by the bomblet blast!"))
+ living_target.apply_damages(explosion_damage * 0.5, explosion_damage * 0.5, 0, 0, 0, blocked = BOMB, updating_health = TRUE)
+ staggerstun(living_target, P, stagger = stagger_amount, slowdown = slow_amount)
+ else if(isobj(target))
+ var/obj/obj_victim = target
+ obj_victim.take_damage(explosion_damage, BRUTE, BOMB)
+
+/datum/ammo/micro_rail_cluster/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
+ ///chance to detonate early, scales with distance and capped, to avoid lots of immediate detonations, and nothing reach max range respectively.
+ var/detonate_probability = min(proj.distance_travelled * 4, 16)
+ if(prob(detonate_probability))
+ proj.proj_max_range = proj.distance_travelled
+
+/datum/ammo/micro_rail_cluster/on_hit_mob(mob/M, obj/projectile/P)
+ detonate(get_turf(P), P)
+
+/datum/ammo/micro_rail_cluster/on_hit_obj(obj/O, obj/projectile/P)
+ detonate(get_turf(P), P)
+
+/datum/ammo/micro_rail_cluster/on_hit_turf(turf/T, obj/projectile/P)
+ detonate(T.density ? P.loc : T, P)
+
+/datum/ammo/micro_rail_cluster/do_at_max_range(turf/T, obj/projectile/P)
+ detonate(T.density ? P.loc : T, P)
+
+/datum/ammo/smoke_burst
+ name = "micro smoke canister"
+ icon_state = "bullet"
+ flags_ammo_behavior = AMMO_BALLISTIC
+ sound_hit = "ballistic_hit"
+ sound_armor = "ballistic_armor"
+ sound_miss = "ballistic_miss"
+ sound_bounce = "ballistic_bounce"
+ shell_speed = 2
+ damage = 5
+ shrapnel_chance = 0
+ max_range = 6
+ bullet_color = COLOR_VERY_SOFT_YELLOW
+ /// smoke type created when the projectile detonates
+ var/datum/effect_system/smoke_spread/smoketype = /datum/effect_system/smoke_spread/bad
+ ///radius this smoke will encompass
+ var/smokeradius = 1
+
+/datum/ammo/smoke_burst/drop_nade(turf/T)
+ var/datum/effect_system/smoke_spread/smoke = new smoketype()
+ playsound(T, 'sound/effects/smoke.ogg', 25, 1, 4)
+ smoke.set_up(smokeradius, T, rand(5,9))
+ smoke.start()
+
+/datum/ammo/smoke_burst/on_hit_mob(mob/M, obj/projectile/P)
+ drop_nade(get_turf(P))
+
+/datum/ammo/smoke_burst/on_hit_obj(obj/O, obj/projectile/P)
+ drop_nade(get_turf(P))
+
+/datum/ammo/smoke_burst/on_hit_turf(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+/datum/ammo/smoke_burst/do_at_max_range(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+/*
+//================================================
+ pepperball
+//================================================
+*/
+
+/datum/ammo/bullet/pepperball
+ name = "pepperball"
+ hud_state = "pepperball"
+ hud_state_empty = "pepperball_empty"
+ flags_ammo_behavior = AMMO_BALLISTIC
+ accurate_range = 15
+ damage_type = STAMINA
+ armor_type = BIO
+ damage = 1
+ damage_falloff = 0
+ penetration = 0
+ shrapnel_chance = 0
+ ///percentage of xenos total plasma to drain when hit by a pepperball
+ var/drain_multiplier = 0.05
+ ///Flat plasma to drain, unaffected by caste plasma amount.
+ var/plasma_drain = 25
+
+/datum/ammo/bullet/pepperball/on_hit_mob(mob/living/victim, obj/projectile/proj)
+ if(isxeno(victim))
+ var/mob/living/carbon/xenomorph/X = victim
+ X.use_plasma(drain_multiplier * X.xeno_caste.plasma_max * X.xeno_caste.plasma_regen_limit)
+ X.use_plasma(plasma_drain)
+
+/datum/ammo/bullet/pepperball/pepperball_mini
+ damage = 1
+ drain_multiplier = 0.03
+ plasma_drain = 15
diff --git a/code/modules/projectiles/ammo_datums/rocket.dm b/code/modules/projectiles/ammo_datums/rocket.dm
new file mode 100644
index 00000000000..c89d8f0bc8c
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/rocket.dm
@@ -0,0 +1,505 @@
+/datum/ammo/rocket
+ name = "high explosive rocket"
+ icon_state = "missile"
+ hud_state = "rocket_he"
+ hud_state_empty = "rocket_empty"
+ ping = null //no bounce off.
+ sound_bounce = "rocket_bounce"
+ flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_SUNDERING
+ armor_type = BOMB
+ damage_falloff = 0
+ shell_speed = 2
+ accuracy = 40
+ accurate_range = 20
+ max_range = 14
+ damage = 200
+ penetration = 100
+ sundering = 100
+ bullet_color = LIGHT_COLOR_FIRE
+ barricade_clear_distance = 2
+
+/datum/ammo/rocket/drop_nade(turf/T)
+ explosion(T, 0, 4, 6, 0, 2)
+
+/datum/ammo/rocket/on_hit_mob(mob/M, obj/projectile/P)
+ drop_nade(get_turf(M))
+
+/datum/ammo/rocket/on_hit_obj(obj/O, obj/projectile/P)
+ drop_nade(O.density ? P.loc : O.loc)
+
+/datum/ammo/rocket/on_hit_turf(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+/datum/ammo/rocket/do_at_max_range(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+/datum/ammo/rocket/he
+ name = "high explosive rocket"
+ icon_state = "rocket_he"
+ hud_state = "rocket_he"
+ accurate_range = 20
+ max_range = 14
+ damage = 150
+ penetration = 100
+ sundering = 100
+
+/datum/ammo/rocket/he/drop_nade(turf/T)
+ cell_explosion(T, 150, 40)
+
+/datum/ammo/rocket/he/unguided
+ damage = 100
+ flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING // We want this one to specifically go over onscreen range.
+
+/datum/ammo/rocket/he/unguided/drop_nade(turf/T)
+ cell_explosion(T, 200, 50)
+
+/datum/ammo/rocket/ap
+ name = "kinetic penetrator"
+ icon_state = "rocket_ap"
+ hud_state = "rocket_ap"
+ damage = 340
+ accurate_range = 15
+ penetration = 200
+ sundering = 0
+
+/datum/ammo/rocket/ap/drop_nade(turf/T)
+ explosion(T, flash_range = 1)
+
+/datum/ammo/rocket/ltb
+ name = "cannon round"
+ icon_state = "ltb"
+ flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET
+ accurate_range = 15
+ max_range = 40
+ penetration = 50
+ damage = 200
+ hud_state = "bigshell_he"
+
+/datum/ammo/rocket/ltb/drop_nade(turf/T)
+ cell_explosion(T, 200, 45)
+
+/datum/ammo/rocket/heavy_isg
+ name = "15cm round"
+ icon_state = "heavyrr"
+ hud_state = "bigshell_he"
+ hud_state_empty = "shell_empty"
+ flags_ammo_behavior = AMMO_ROCKET|AMMO_EXPLOSIVE
+ damage = 50
+ penetration = 200
+ max_range = 30
+ shell_speed = 0.75
+ accuracy = 30
+ accurate_range = 21
+ handful_amount = 1
+
+/datum/ammo/rocket/heavy_isg/drop_nade(turf/T)
+ cell_explosion(T, 700, 200) // dodge this
+
+/datum/ammo/rocket/heavy_isg/unguided
+ hud_state = "bigshell_he_unguided"
+ flags_ammo_behavior = AMMO_ROCKET
+
+/datum/ammo/bullet/heavy_isg_apfds
+ name = "15cm APFDS round"
+ icon_state = "apfds"
+ hud_state = "bigshell_apfds"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_PASS_THROUGH_TURF|AMMO_PASS_THROUGH_MOVABLE
+ damage = 200
+ penetration = 75
+ shell_speed = 7
+ accurate_range = 24
+ accurate_range_min = 6
+ max_range = 35
+
+/datum/ammo/bullet/isg_apfds/on_hit_turf(turf/T, obj/projectile/P)
+ P.proj_max_range -= 5
+
+/datum/ammo/bullet/isg_apfds/on_hit_mob(mob/M, obj/projectile/P)
+ P.proj_max_range -= 2
+ staggerstun(M, P, max_range = 20, slowdown = 0.5)
+
+/datum/ammo/bullet/isg_apfds/on_hit_obj(obj/O, obj/projectile/P)
+ P.proj_max_range -= 5
+
+/datum/ammo/rocket/wp
+ name = "white phosphorous rocket"
+ icon_state = "rocket_wp"
+ hud_state = "rocket_fire"
+ flags_ammo_behavior = AMMO_ROCKET|AMMO_INCENDIARY|AMMO_EXPLOSIVE|AMMO_SUNDERING
+ armor_type = FIRE
+ damage_type = BURN
+ accuracy_var_low = 7
+ accurate_range = 15
+ damage = 200
+ penetration = 75
+ max_range = 20
+ sundering = 100
+ ///The radius for the non explosion effects
+ var/effect_radius = 3
+
+/datum/ammo/rocket/wp/drop_nade(turf/T)
+ if(!T || !isturf(T))
+ return
+ playsound(T, 'sound/weapons/guns/fire/flamethrower2.ogg', 50, 1, 4)
+ flame_radius(effect_radius, T, 27, 27, 27, 17)
+
+/datum/ammo/rocket/wp/quad
+ name = "thermobaric rocket"
+ hud_state = "rocket_thermobaric"
+ flags_ammo_behavior = AMMO_ROCKET
+ damage = 40
+ penetration = 25
+ max_range = 30
+ sundering = 2
+
+ ///The smoke system that the WP gas uses to spread.
+ var/datum/effect_system/smoke_spread/smoke_system
+
+/datum/ammo/rocket/wp/quad/set_smoke()
+ smoke_system = new /datum/effect_system/smoke_spread/phosphorus()
+
+/datum/ammo/rocket/wp/quad/drop_nade(turf/T)
+ set_smoke()
+ smoke_system.set_up(effect_radius, T)
+ smoke_system.start()
+ smoke_system = null
+ T.visible_message(span_danger("The rocket explodes into white gas!") )
+ playsound(T, 'sound/weapons/guns/fire/flamethrower2.ogg', 50, 1, 4)
+ flame_radius(effect_radius, T, 27, 27, 27, 17)
+
+/datum/ammo/rocket/wp/quad/som
+ name = "white phosphorous RPG"
+ hud_state = "rpg_fire"
+ icon_state = "rpg_incendiary"
+ flags_ammo_behavior = AMMO_ROCKET
+ effect_radius = 5
+
+/datum/ammo/rocket/wp/quad/ds
+ name = "super thermobaric rocket"
+ hud_state = "rocket_thermobaric"
+ flags_ammo_behavior = AMMO_ROCKET
+ damage = 200
+ penetration = 75
+ max_range = 30
+ sundering = 100
+
+/datum/ammo/rocket/wp/unguided
+ damage = 100
+ flags_ammo_behavior = AMMO_ROCKET|AMMO_INCENDIARY|AMMO_SUNDERING
+ effect_radius = 5
+
+/datum/ammo/rocket/recoilless
+ name = "high explosive shell"
+ icon_state = "recoilless_rifle_he"
+ hud_state = "shell_he"
+ hud_state_empty = "shell_empty"
+ flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_SUNDERING
+ armor_type = BOMB
+ damage_falloff = 0
+ shell_speed = 2
+ accurate_range = 20
+ max_range = 30
+ damage = 100
+ penetration = 50
+ sundering = 50
+
+/datum/ammo/rocket/recoilless/drop_nade(turf/T)
+ cell_explosion(T, 150, 75)
+
+/datum/ammo/rocket/recoilless/heat
+ name = "HEAT shell"
+ icon_state = "recoilless_rifle_heat"
+ hud_state = "shell_heat"
+ flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING
+ damage = 200
+ penetration = 100
+ sundering = 0
+
+/datum/ammo/rocket/recoilless/heat/drop_nade(turf/T)
+ explosion(T, flash_range = 1)
+
+/datum/ammo/rocket/recoilless/heat/mech //for anti mech use in HvH
+ name = "HEAM shell"
+ accuracy = -10 //Not designed for anti human use
+ flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING|AMMO_UNWIELDY
+
+/datum/ammo/rocket/recoilless/heat/mech/on_hit_obj(obj/O, obj/projectile/P)
+ drop_nade(get_turf(O))
+ if(ismecha(O))
+ P.damage *= 3 //this is specifically designed to hurt mechs
+
+/datum/ammo/rocket/recoilless/heat/mech/drop_nade(turf/T)
+ cell_explosion(T, 50, 45)
+
+/datum/ammo/rocket/recoilless/light
+ name = "light explosive shell"
+ icon_state = "recoilless_rifle_le"
+ hud_state = "shell_le"
+ flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING //We want this to specifically go farther than onscreen range.
+ accurate_range = 15
+ max_range = 20
+ damage = 75
+ penetration = 50
+ sundering = 25
+
+/datum/ammo/rocket/recoilless/light/drop_nade(turf/T)
+ cell_explosion(T, 75, 25)
+
+/datum/ammo/rocket/recoilless/chemical
+ name = "low velocity chemical shell"
+ icon_state = "recoilless_rifle_smoke"
+ hud_state = "shell_le"
+ flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING|AMMO_IFF //We want this to specifically go farther than onscreen range and pass through friendlies.
+ accurate_range = 21
+ max_range = 21
+ damage = 10
+ penetration = 0
+ sundering = 0
+ /// Smoke type created when projectile detonates.
+ var/datum/effect_system/smoke_spread/smoketype = /datum/effect_system/smoke_spread/bad
+ /// Radius this smoke will encompass on detonation.
+ var/smokeradius = 7
+
+/datum/ammo/rocket/recoilless/chemical/drop_nade(turf/T)
+ var/datum/effect_system/smoke_spread/smoke = new smoketype()
+ playsound(T, 'sound/effects/smoke.ogg', 25, 1, 4)
+ smoke.set_up(smokeradius, T, rand(5,9))
+ smoke.start()
+ explosion(T, flash_range = 1)
+
+/datum/ammo/rocket/recoilless/chemical/cloak
+ name = "low velocity chemical shell"
+ icon_state = "recoilless_rifle_cloak"
+ hud_state = "shell_cloak"
+ smoketype = /datum/effect_system/smoke_spread/tactical
+
+/datum/ammo/rocket/recoilless/chemical/plasmaloss
+ name = "low velocity chemical shell"
+ icon_state = "recoilless_rifle_tanglefoot"
+ hud_state = "shell_tanglefoot"
+ smoketype = /datum/effect_system/smoke_spread/plasmaloss
+
+/datum/ammo/rocket/recoilless/low_impact
+ name = "low impact explosive shell"
+ icon_state = "recoilless_rifle_le"
+ hud_state = "shell_le"
+ flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING //We want this to specifically go farther than onscreen range.
+ accurate_range = 15
+ max_range = 20
+ damage = 75
+ penetration = 15
+ sundering = 25
+
+/datum/ammo/rocket/recoilless/low_impact/drop_nade(turf/T)
+ cell_explosion(T, 100, 15)
+
+/datum/ammo/rocket/oneuse
+ name = "explosive rocket"
+ damage = 100
+ penetration = 100
+ sundering = 100
+ max_range = 30
+
+/datum/ammo/rocket/oneuse/drop_nade(turf/T)
+ cell_explosion(T, 115, 45)
+
+/datum/ammo/rocket/som
+ name = "high explosive RPG"
+ icon_state = "rpg_he"
+ hud_state = "rpg_he"
+ flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING
+ accurate_range = 15
+ max_range = 20
+ damage = 80
+ penetration = 20
+ sundering = 20
+
+/datum/ammo/rocket/som/drop_nade(turf/T)
+ cell_explosion(T, 175, 35)
+
+/datum/ammo/rocket/som/light
+ name = "low impact RPG"
+ icon_state = "rpg_le"
+ hud_state = "rpg_le"
+ flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING
+ accurate_range = 15
+ damage = 60
+ penetration = 10
+
+/datum/ammo/rocket/som/light/drop_nade(turf/T)
+ cell_explosion(T, 125, 15)
+
+/datum/ammo/rocket/som/thermobaric
+ name = "thermobaric RPG"
+ icon_state = "rpg_thermobaric"
+ hud_state = "rpg_thermobaric"
+ damage = 30
+
+/datum/ammo/rocket/som/thermobaric/drop_nade(turf/T)
+ cell_explosion(T, 175, 45)
+ flame_radius(4, T)
+
+/datum/ammo/rocket/som/heat //Anti tank, or mech
+ name = "HEAT RPG"
+ icon_state = "rpg_heat"
+ hud_state = "rpg_heat"
+ damage = 200
+ penetration = 100
+ sundering = 0
+ accuracy = -10 //Not designed for anti human use
+ flags_ammo_behavior = AMMO_ROCKET|AMMO_SUNDERING|AMMO_UNWIELDY
+
+/datum/ammo/rocket/som/heat/on_hit_obj(obj/O, obj/projectile/P)
+ drop_nade(get_turf(O))
+ if(ismecha(O))
+ P.damage *= 3 //this is specifically designed to hurt mechs
+
+/datum/ammo/rocket/som/heat/drop_nade(turf/T)
+ cell_explosion(T, 50, 45)
+
+/datum/ammo/rocket/som/rad
+ name = "irrad RPG"
+ icon_state = "rpg_rad"
+ hud_state = "rpg_rad"
+ damage = 50
+ penetration = 10
+ ///Base strength of the rad effects
+ var/rad_strength = 25
+ ///Range for the maximum rad effects
+ var/inner_range = 3
+ ///Range for the moderate rad effects
+ var/mid_range = 5
+ ///Range for the minimal rad effects
+ var/outer_range = 8
+
+/datum/ammo/rocket/som/rad/drop_nade(turf/T)
+ playsound(T, 'sound/effects/portal_opening.ogg', 50, 1)
+ for(var/mob/living/victim in hearers(outer_range, T))
+ var/strength
+ var/sound_level
+ if(get_dist(victim, T) <= inner_range)
+ strength = rad_strength
+ sound_level = 4
+ else if(get_dist(victim, T) <= mid_range)
+ strength = rad_strength * 0.7
+ sound_level = 3
+ else
+ strength = rad_strength * 0.3
+ sound_level = 2
+
+ strength = victim.modify_by_armor(strength, BIO, 25)
+ victim.apply_radiation(strength, sound_level)
+
+ explosion(T, weak_impact_range = 4)
+
+/datum/ammo/rocket/atgun_shell
+ name = "high explosive ballistic cap shell"
+ icon_state = "atgun"
+ hud_state = "shell_heat"
+ hud_state_empty = "shell_empty"
+ flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_SUNDERING|AMMO_PASS_THROUGH_TURF
+ shell_speed = 2
+ damage = 90
+ penetration = 30
+ sundering = 25
+ max_range = 30
+ handful_amount = 1
+
+/datum/ammo/rocket/atgun_shell/drop_nade(turf/T)
+ cell_explosion(T, 55 , 30)
+
+/datum/ammo/rocket/atgun_shell/on_hit_turf(turf/T, obj/projectile/P) //no explosion every time it hits a turf
+ P.proj_max_range -= 10
+
+/datum/ammo/rocket/atgun_shell/apcr
+ name = "tungsten penetrator"
+ hud_state = "shell_apcr"
+ flags_ammo_behavior = AMMO_BALLISTIC|AMMO_SUNDERING|AMMO_PASS_THROUGH_TURF|AMMO_PASS_THROUGH_MOVABLE
+ shell_speed = 4
+ damage = 200
+ penetration = 70
+ sundering = 25
+
+/datum/ammo/rocket/atgun_shell/apcr/drop_nade(turf/T)
+ explosion(T, flash_range = 1)
+
+/datum/ammo/rocket/atgun_shell/apcr/on_hit_mob(mob/M, obj/projectile/P)
+ drop_nade(get_turf(M))
+ P.proj_max_range -= 5
+ staggerstun(M, P, max_range = 20, stagger = 1 SECONDS, slowdown = 0.5, knockback = 2, hard_size_threshold = 3)
+
+/datum/ammo/rocket/atgun_shell/apcr/on_hit_obj(obj/O, obj/projectile/P)
+ P.proj_max_range -= 5
+
+/datum/ammo/rocket/atgun_shell/apcr/on_hit_turf(turf/T, obj/projectile/P)
+ P.proj_max_range -= 5
+
+/datum/ammo/rocket/atgun_shell/he
+ name = "low velocity high explosive shell"
+ hud_state = "shell_he"
+ flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_SUNDERING
+ damage = 50
+ penetration = 50
+ sundering = 35
+
+/datum/ammo/rocket/atgun_shell/he/drop_nade(turf/T)
+ cell_explosion(T, 90, 30)
+
+/datum/ammo/rocket/atgun_shell/he/on_hit_turf(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+/datum/ammo/rocket/atgun_shell/beehive
+ name = "beehive shell"
+ hud_state = "shell_le"
+ flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_SUNDERING
+ shell_speed = 3
+ damage = 30
+ penetration = 30
+ sundering = 5
+ bonus_projectiles_type = /datum/ammo/bullet/atgun_spread
+ bonus_projectiles_scatter = 8
+ var/bonus_projectile_quantity = 10
+
+/datum/ammo/rocket/atgun_shell/beehive/drop_nade(turf/T)
+ explosion(T, flash_range = 1)
+
+/datum/ammo/rocket/atgun_shell/beehive/on_hit_mob(mob/M, obj/projectile/proj)
+ staggerstun(M, proj, slowdown = 0.2, knockback = 1)
+ drop_nade(get_turf(M))
+ playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
+ fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 5, 3, Get_Angle(proj.firer, M) )
+
+/datum/ammo/rocket/atgun_shell/beehive/on_hit_obj(obj/O, obj/projectile/proj)
+ playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
+ fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 5, 3, Get_Angle(proj.firer, O) )
+
+/datum/ammo/rocket/atgun_shell/beehive/on_hit_turf(turf/T, obj/projectile/proj)
+ playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
+ fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 5, 3, Get_Angle(proj.firer, T) )
+
+/datum/ammo/rocket/atgun_shell/beehive/do_at_max_range(turf/T, obj/projectile/proj)
+ playsound(proj, sound(get_sfx("explosion_micro")), 30, falloff = 5)
+ fire_directionalburst(proj, proj.firer, proj.shot_from, bonus_projectile_quantity, 5, 3, Get_Angle(proj.firer, get_turf(proj)) )
+
+/datum/ammo/rocket/atgun_shell/beehive/incend
+ name = "napalm shell"
+ hud_state = "shell_heat"
+ flags_ammo_behavior = AMMO_EXPLOSIVE|AMMO_ROCKET|AMMO_SUNDERING
+ shell_speed = 3
+ bonus_projectiles_type = /datum/ammo/bullet/atgun_spread/incendiary
+
+/datum/ammo/rocket/toy
+ name = "\improper toy rocket"
+ damage = 1
+
+/datum/ammo/rocket/toy/on_hit_mob(mob/M,obj/projectile/P)
+ to_chat(M, "NO BUGS")
+
+/datum/ammo/rocket/toy/on_hit_obj(obj/O,obj/projectile/P)
+ return
+
+/datum/ammo/rocket/toy/on_hit_turf(turf/T,obj/projectile/P)
+ return
+
+/datum/ammo/rocket/toy/do_at_max_range(turf/T, obj/projectile/P)
+ return
diff --git a/code/modules/projectiles/ammo_datums/shrapnel.dm b/code/modules/projectiles/ammo_datums/shrapnel.dm
new file mode 100644
index 00000000000..51325c41c3f
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/shrapnel.dm
@@ -0,0 +1,61 @@
+/datum/ammo/bullet/shrapnel
+ name = "shrapnel"
+ icon_state = "buckshot_shrapnel"
+ icon = 'icons/obj/items/projectiles.dmi'
+ accurate_range_min = 5
+ flags_ammo_behavior = AMMO_BALLISTIC
+ accuracy = 15
+ accurate_range = 32
+ max_range = 8
+ damage = 25
+ damage_falloff = 8
+ penetration = 0
+ shell_speed = 3
+ shrapnel_chance = 15
+
+/datum/ammo/bullet/shrapnel/metal
+ name = "metal shrapnel"
+ icon_state = "shrapnelshot_bit"
+ shell_speed = 1.5
+ damage = 30
+ shrapnel_chance = 25
+ accuracy = 40
+ penetration = 0
+
+/datum/ammo/bullet/shrapnel/light // weak shrapnel
+ name = "light shrapnel"
+ icon_state = "shrapnel_light"
+ damage = 10
+ penetration = 0
+ shell_speed = 2
+ shrapnel_chance = 0
+
+/datum/ammo/bullet/shrapnel/light/human
+ name = "human bone fragments"
+ icon_state = "shrapnel_human"
+ shrapnel_chance = 50
+ shrapnel_type = /obj/item/shard/shrapnel/bone_chips/human
+
+/datum/ammo/bullet/shrapnel/light/human/var1 // sprite variants
+ icon_state = "shrapnel_human1"
+
+/datum/ammo/bullet/shrapnel/light/human/var2 // sprite variants
+ icon_state = "shrapnel_human2"
+
+/datum/ammo/bullet/shrapnel/light/xeno
+ name = "alien bone fragments"
+ icon_state = "shrapnel_xeno"
+ shrapnel_chance = 50
+ shrapnel_type = /obj/item/shard/shrapnel/bone_chips/xeno
+
+/datum/ammo/bullet/shrapnel/spall // weak shrapnel
+ name = "spall"
+ icon_state = "shrapnel_light"
+ damage = 10
+ penetration = 0
+ shell_speed = 2
+ shrapnel_chance = 0
+
+/datum/ammo/bullet/shrapnel/light/glass
+ name = "glass shrapnel"
+ icon_state = "shrapnel_glass"
diff --git a/code/modules/projectiles/ammo_datums/xeno.dm b/code/modules/projectiles/ammo_datums/xeno.dm
new file mode 100644
index 00000000000..7e7449e3978
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/xeno.dm
@@ -0,0 +1,569 @@
+GLOBAL_LIST_INIT(no_sticky_resin, typecacheof(list(/obj/item/clothing/mask/facehugger, /obj/alien/egg, /obj/structure/mineral_door, /obj/alien/resin, /obj/structure/bed/nest))) //For sticky/acid spit
+
+/datum/ammo/xeno
+ icon_state = "neurotoxin"
+ ping = "ping_x"
+ damage_type = TOX
+ flags_ammo_behavior = AMMO_XENO
+ var/added_spit_delay = 0 //used to make cooldown of the different spits vary.
+ var/spit_cost = 5
+ armor_type = BIO
+ shell_speed = 1
+ accuracy = 40
+ accurate_range = 15
+ max_range = 15
+ accuracy_var_low = 3
+ accuracy_var_high = 3
+ bullet_color = COLOR_LIME
+ ///List of reagents transferred upon spit impact if any
+ var/list/datum/reagent/spit_reagents
+ ///Amount of reagents transferred upon spit impact if any
+ var/reagent_transfer_amount
+ ///Amount of stagger stacks imposed on impact if any
+ var/stagger_stacks
+ ///Amount of slowdown stacks imposed on impact if any
+ var/slowdown_stacks
+ ///These define the reagent transfer strength of the smoke caused by the spit, if any, and its aoe
+ var/datum/effect_system/smoke_spread/xeno/smoke_system
+ var/smoke_strength
+ var/smoke_range
+ ///The hivenumber of this ammo
+ var/hivenumber = XENO_HIVE_NORMAL
+
+/datum/ammo/xeno/toxin
+ name = "neurotoxic spit"
+ flags_ammo_behavior = AMMO_XENO|AMMO_EXPLOSIVE|AMMO_SKIPS_ALIENS
+ spit_cost = 55
+ added_spit_delay = 0
+ damage_type = STAMINA
+ accurate_range = 5
+ max_range = 10
+ accuracy_var_low = 3
+ accuracy_var_high = 3
+ damage = 40
+ stagger_stacks = 1.1 SECONDS
+ slowdown_stacks = 1.5
+ smoke_strength = 0.5
+ smoke_range = 0
+ reagent_transfer_amount = 4
+ bullet_color = COLOR_LIGHT_ORANGE
+
+///Set up the list of reagents the spit transfers upon impact
+/datum/ammo/xeno/toxin/proc/set_reagents()
+ spit_reagents = list(/datum/reagent/toxin/xeno_neurotoxin = reagent_transfer_amount)
+
+/datum/ammo/xeno/toxin/on_hit_mob(mob/living/carbon/carbon_victim, obj/projectile/proj)
+ drop_neuro_smoke(get_turf(carbon_victim))
+
+ if(!istype(carbon_victim) || carbon_victim.stat == DEAD || carbon_victim.issamexenohive(proj.firer) )
+ return
+
+ if(isnestedhost(carbon_victim))
+ return
+
+ carbon_victim.adjust_stagger(stagger_stacks)
+ carbon_victim.add_slowdown(slowdown_stacks)
+
+ set_reagents()
+ for(var/reagent_id in spit_reagents)
+ spit_reagents[reagent_id] = carbon_victim.modify_by_armor(spit_reagents[reagent_id], armor_type, penetration, proj.def_zone)
+
+ carbon_victim.reagents.add_reagent_list(spit_reagents)
+
+ return ..()
+
+/datum/ammo/xeno/toxin/on_hit_obj(obj/O, obj/projectile/P)
+ var/turf/T = get_turf(O)
+ drop_neuro_smoke(T.density ? P.loc : T)
+
+/datum/ammo/xeno/toxin/on_hit_turf(turf/T, obj/projectile/P)
+ drop_neuro_smoke(T.density ? P.loc : T)
+
+/datum/ammo/xeno/toxin/do_at_max_range(turf/T, obj/projectile/P)
+ drop_neuro_smoke(T.density ? P.loc : T)
+
+/datum/ammo/xeno/toxin/set_smoke()
+ smoke_system = new /datum/effect_system/smoke_spread/xeno/neuro/light()
+
+/datum/ammo/xeno/toxin/proc/drop_neuro_smoke(turf/T)
+ if(T.density)
+ return
+
+ set_smoke()
+ smoke_system.strength = smoke_strength
+ smoke_system.set_up(smoke_range, T)
+ smoke_system.start()
+ smoke_system = null
+
+/datum/ammo/xeno/toxin/sent //Sentinel
+ spit_cost = 70
+ icon_state = "xeno_sent_neuro"
+
+/datum/ammo/xeno/toxin/upgrade1
+ smoke_strength = 0.6
+ reagent_transfer_amount = 5
+
+/datum/ammo/xeno/toxin/upgrade2
+ smoke_strength = 0.7
+ reagent_transfer_amount = 6
+
+/datum/ammo/xeno/toxin/upgrade3
+ smoke_strength = 0.75
+ reagent_transfer_amount = 6.5
+
+/datum/ammo/xeno/toxin/heavy //Praetorian
+ name = "neurotoxic splash"
+ added_spit_delay = 0
+ spit_cost = 200
+ damage = 80
+ smoke_strength = 1
+ reagent_transfer_amount = 18
+ smoke_range = 1
+
+/datum/ammo/xeno/sticky
+ name = "sticky resin spit"
+ icon_state = "sticky"
+ ping = null
+ flags_ammo_behavior = AMMO_SKIPS_ALIENS|AMMO_EXPLOSIVE|AMMO_XENO
+ damage_type = STAMINA
+ armor_type = BIO
+ spit_cost = 50
+ sound_hit = "alien_resin_build2"
+ sound_bounce = "alien_resin_build3"
+ damage = 20 //minor; this is mostly just to provide confirmation of a hit
+ max_range = 40
+ bullet_color = COLOR_PURPLE
+ stagger_stacks = 2
+ slowdown_stacks = 3
+
+/datum/ammo/xeno/sticky/on_hit_mob(mob/M, obj/projectile/P)
+ drop_resin(get_turf(M))
+ if(istype(M,/mob/living/carbon))
+ var/mob/living/carbon/C = M
+ if(C.issamexenohive(P.firer))
+ return
+ C.adjust_stagger(stagger_stacks) //stagger briefly; useful for support
+ C.add_slowdown(slowdown_stacks) //slow em down
+
+/datum/ammo/xeno/sticky/on_hit_obj(obj/O, obj/projectile/P)
+ if(isarmoredvehicle(O))
+ var/obj/vehicle/sealed/armored/tank = O
+ COOLDOWN_START(tank, cooldown_vehicle_move, tank.move_delay)
+ var/turf/T = get_turf(O)
+ drop_resin(T.density ? P.loc : T)
+
+/datum/ammo/xeno/sticky/on_hit_turf(turf/T, obj/projectile/P)
+ drop_resin(T.density ? P.loc : T)
+
+/datum/ammo/xeno/sticky/do_at_max_range(turf/T, obj/projectile/P)
+ drop_resin(T.density ? P.loc : T)
+
+/datum/ammo/xeno/sticky/proc/drop_resin(turf/T)
+ if(T.density || istype(T, /turf/open/space)) // No structures in space
+ return
+
+ for(var/obj/O in T.contents)
+ if(is_type_in_typecache(O, GLOB.no_sticky_resin))
+ return
+
+ new /obj/alien/resin/sticky/thin(T)
+
+/datum/ammo/xeno/sticky/turret
+ max_range = 9
+
+/datum/ammo/xeno/sticky/globe
+ name = "sticky resin globe"
+ icon_state = "sticky_globe"
+ damage = 40
+ max_range = 7
+ spit_cost = 200
+ added_spit_delay = 8 SECONDS
+ bonus_projectiles_type = /datum/ammo/xeno/sticky/mini
+ bonus_projectiles_scatter = 22
+ var/bonus_projectile_quantity = 16
+ var/bonus_projectile_range = 3
+ var/bonus_projectile_speed = 1
+
+/datum/ammo/xeno/sticky/mini
+ damage = 5
+ max_range = 3
+
+/datum/ammo/xeno/sticky/globe/on_hit_obj(obj/O, obj/projectile/P)
+ var/turf/initial_turf = O.density ? P.loc : get_turf(O)
+ drop_resin(initial_turf)
+ fire_directionalburst(P, P.firer, P.shot_from, bonus_projectile_quantity, bonus_projectile_range, bonus_projectile_speed, Get_Angle(P.firer, initial_turf))
+
+/datum/ammo/xeno/sticky/globe/on_hit_turf(turf/T, obj/projectile/P)
+ var/turf/initial_turf = T.density ? P.loc : T
+ drop_resin(initial_turf)
+ fire_directionalburst(P, P.firer, P.shot_from, bonus_projectile_quantity, bonus_projectile_range, bonus_projectile_speed, Get_Angle(P.firer, initial_turf))
+
+/datum/ammo/xeno/sticky/globe/on_hit_mob(mob/M, obj/projectile/P)
+ var/turf/initial_turf = get_turf(M)
+ drop_resin(initial_turf)
+ fire_directionalburst(P, P.firer, P.shot_from, bonus_projectile_quantity, bonus_projectile_range, bonus_projectile_speed, Get_Angle(P.firer, initial_turf))
+
+/datum/ammo/xeno/sticky/globe/do_at_max_range(turf/T, obj/projectile/P)
+ var/turf/initial_turf = T.density ? P.loc : T
+ drop_resin(initial_turf)
+ fire_directionalburst(P, P.firer, P.shot_from, bonus_projectile_quantity, bonus_projectile_range, bonus_projectile_speed, Get_Angle(P.firer, initial_turf))
+
+/datum/ammo/xeno/acid
+ name = "acid spit"
+ icon_state = "xeno_acid_weak"
+ sound_hit = "acid_hit"
+ sound_bounce = "acid_bounce"
+ damage_type = BURN
+ added_spit_delay = 5
+ spit_cost = 50
+ flags_ammo_behavior = AMMO_XENO|AMMO_EXPLOSIVE
+ armor_type = ACID
+ damage = 18
+ max_range = 8
+ bullet_color = COLOR_PALE_GREEN_GRAY
+ ///Duration of the acid puddles
+ var/puddle_duration = 1 SECONDS //Lasts 1-3 seconds
+ ///Damage dealt by acid puddles
+ var/puddle_acid_damage = XENO_DEFAULT_ACID_PUDDLE_DAMAGE
+
+/datum/ammo/xeno/acid/on_shield_block(mob/victim, obj/projectile/proj)
+ airburst(victim, proj)
+
+/datum/ammo/xeno/acid/drop_nade(turf/T) //Leaves behind an acid pool; defaults to 1-3 seconds.
+ if(T.density)
+ return
+ new /obj/effect/xenomorph/spray/weak(T, puddle_duration, puddle_acid_damage)
+
+/datum/ammo/xeno/acid/medium
+ name = "acid spatter"
+ damage = 30
+ flags_ammo_behavior = AMMO_XENO
+ icon_state = "xeno_acid_normal"
+ bullet_color = COLOR_VERY_PALE_LIME_GREEN
+
+/datum/ammo/xeno/acid/medium/drop_nade(turf/T) //Leaves behind an acid pool; defaults to 1-3 seconds.
+ if(T.density)
+ return
+ new /obj/effect/xenomorph/spray(T, puddle_duration, puddle_acid_damage)
+
+/datum/ammo/xeno/acid/medium/passthrough //Spitter
+ flags_ammo_behavior = AMMO_XENO|AMMO_SKIPS_ALIENS
+
+/datum/ammo/xeno/acid/auto
+ name = "light acid spatter"
+ damage = 10
+ damage_falloff = 0.3
+ spit_cost = 25
+ added_spit_delay = 0
+ flags_ammo_behavior = AMMO_XENO|AMMO_EXPLOSIVE|AMMO_SKIPS_ALIENS
+
+/datum/ammo/xeno/acid/auto/on_hit_mob(mob/M, obj/projectile/P)
+ var/turf/T = get_turf(M)
+ drop_nade(T.density ? P.loc : T)
+
+/datum/ammo/xeno/acid/auto/on_hit_obj(obj/O, obj/projectile/P)
+ drop_nade(O.density ? P.loc : get_turf(O))
+
+/datum/ammo/xeno/acid/auto/on_hit_turf(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+/datum/ammo/xeno/acid/auto/do_at_max_range(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+/datum/ammo/xeno/acid/passthrough
+ name = "acid spittle"
+ damage = 20
+ flags_ammo_behavior = AMMO_XENO|AMMO_SKIPS_ALIENS
+
+/datum/ammo/xeno/acid/heavy
+ name = "acid splash"
+ added_spit_delay = 2
+ spit_cost = 70
+ damage = 30
+ icon_state = "xeno_acid_strong"
+ bullet_color = COLOR_ASSEMBLY_YELLOW
+
+/datum/ammo/xeno/acid/heavy/drop_nade(turf/T) //Leaves behind an acid pool; defaults to 1-3 seconds.
+ if(T.density)
+ return
+ new /obj/effect/xenomorph/spray/strong(T, puddle_duration, puddle_acid_damage)
+
+/datum/ammo/xeno/acid/heavy/passthrough //Praetorian
+ flags_ammo_behavior = AMMO_XENO|AMMO_EXPLOSIVE|AMMO_SKIPS_ALIENS
+
+/datum/ammo/xeno/acid/heavy/turret
+ damage = 20
+ name = "acid turret splash"
+ shell_speed = 2
+ max_range = 9
+ icon_state = "xeno_acid_weak"
+ bullet_color = COLOR_PALE_GREEN_GRAY
+
+/datum/ammo/xeno/acid/heavy/turret/drop_nade(turf/T) //Leaves behind an acid pool; defaults to 1-3 seconds.
+ if(T.density)
+ return
+ new /obj/effect/xenomorph/spray/weak(T, puddle_duration, puddle_acid_damage)
+
+/datum/ammo/xeno/acid/heavy/on_hit_mob(mob/M, obj/projectile/P)
+ var/turf/T = get_turf(M)
+ drop_nade(T.density ? P.loc : T)
+
+/datum/ammo/xeno/acid/heavy/on_hit_obj(obj/O, obj/projectile/P)
+ drop_nade(O.density ? P.loc : get_turf(O))
+
+/datum/ammo/xeno/acid/heavy/on_hit_turf(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+/datum/ammo/xeno/acid/heavy/do_at_max_range(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T)
+
+///For the Spitter's Scatterspit ability
+/datum/ammo/xeno/acid/heavy/scatter
+ damage = 20
+ flags_ammo_behavior = AMMO_XENO|AMMO_EXPLOSIVE|AMMO_SKIPS_ALIENS
+ bonus_projectiles_type = /datum/ammo/xeno/acid/heavy/scatter
+ bonus_projectiles_amount = 6
+ bonus_projectiles_scatter = 2
+ max_range = 8
+ puddle_duration = 1 SECONDS //Lasts 2-4 seconds
+ icon_state = "xeno_acid_normal"
+ bullet_color = COLOR_VERY_PALE_LIME_GREEN
+
+/datum/ammo/xeno/acid/heavy/scatter/drop_nade(turf/T) //Leaves behind an acid pool; defaults to 1-3 seconds.
+ if(T.density)
+ return
+ new /obj/effect/xenomorph/spray(T, puddle_duration, puddle_acid_damage)
+
+/datum/ammo/xeno/acid/heavy/scatter/praetorian
+ max_range = 5
+ damage = 15
+ puddle_duration = 0.5 SECONDS
+ bonus_projectiles_amount = 3
+
+/datum/ammo/xeno/boiler_gas
+ name = "glob of gas"
+ icon_state = "boiler_gas2"
+ ping = "ping_x"
+ ///Key used for icon stuff during bombard ammo selection.
+ var/icon_key = BOILER_GLOB_NEURO
+ ///This text will show up when a boiler selects this ammo. Span proc should be applied when this var is used.
+ var/select_text = "We will now fire neurotoxic gas. This is nonlethal."
+ flags_ammo_behavior = AMMO_XENO|AMMO_SKIPS_ALIENS|AMMO_EXPLOSIVE
+ var/danger_message = span_danger("A glob of acid lands with a splat and explodes into noxious fumes!")
+ armor_type = BIO
+ accuracy_var_high = 10
+ max_range = 30
+ damage = 50
+ damage_type = STAMINA
+ damage_falloff = 0
+ penetration = 40
+ bullet_color = BOILER_LUMINOSITY_AMMO_NEUROTOXIN_COLOR
+ reagent_transfer_amount = 30
+ ///On a direct hit, how long is the target paralyzed?
+ var/hit_paralyze_time = 1 SECONDS
+ ///On a direct hit, how much do the victim's eyes get blurred?
+ var/hit_eye_blur = 11
+ ///On a direct hit, how much drowsyness gets added to the target?
+ var/hit_drowsyness = 12
+ ///Base spread range
+ var/fixed_spread_range = 4
+ ///Which type is the smoke we leave on passed tiles, provided the projectile has AMMO_LEAVE_TURF enabled?
+ var/passed_turf_smoke_type = /datum/effect_system/smoke_spread/xeno/neuro/light
+ ///We're going to reuse one smoke spread system repeatedly to cut down on processing.
+ var/datum/effect_system/smoke_spread/xeno/trail_spread_system
+
+/datum/ammo/xeno/boiler_gas/on_leave_turf(turf/T, atom/firer, obj/projectile/proj)
+ if(isxeno(firer))
+ var/mob/living/carbon/xenomorph/X = firer
+ trail_spread_system.strength = X.xeno_caste.bomb_strength
+ trail_spread_system.set_up(0, T)
+ trail_spread_system.start()
+
+/**
+ * Loads a trap with a gas cloud depending on current glob type
+ * Called when something with a boiler glob as current ammo interacts with an empty resin trap.
+ * * Args:
+ * * trap: The trap being loaded
+ * * user_xeno: The xeno interacting with the trap
+ * * Returns: TRUE on success, FALSE on failure.
+**/
+/datum/ammo/xeno/boiler_gas/proc/enhance_trap(obj/structure/xeno/trap/trap, mob/living/carbon/xenomorph/user_xeno)
+ if(!do_after(user_xeno, 2 SECONDS, NONE, trap))
+ return FALSE
+ trap.set_trap_type(TRAP_SMOKE_NEURO)
+ trap.smoke = new /datum/effect_system/smoke_spread/xeno/neuro/medium
+ trap.smoke.set_up(2, get_turf(trap))
+ return TRUE
+
+/datum/ammo/xeno/boiler_gas/New()
+ . = ..()
+ if((flags_ammo_behavior & AMMO_LEAVE_TURF) && passed_turf_smoke_type)
+ trail_spread_system = new passed_turf_smoke_type(only_once = FALSE)
+
+/datum/ammo/xeno/boiler_gas/Destroy()
+ if(trail_spread_system)
+ QDEL_NULL(trail_spread_system)
+ return ..()
+
+///Set up the list of reagents the spit transfers upon impact
+/datum/ammo/xeno/boiler_gas/proc/set_reagents()
+ spit_reagents = list(/datum/reagent/toxin/xeno_neurotoxin = reagent_transfer_amount)
+
+/datum/ammo/xeno/boiler_gas/on_hit_mob(mob/living/victim, obj/projectile/proj)
+ var/turf/target_turf = get_turf(victim)
+ drop_nade(target_turf.density ? proj.loc : target_turf, proj.firer)
+
+ if(!istype(victim) || victim.stat == DEAD || victim.issamexenohive(proj.firer))
+ return
+
+ victim.Paralyze(hit_paralyze_time)
+ victim.blur_eyes(hit_eye_blur)
+ victim.adjustDrowsyness(hit_drowsyness)
+
+ if(!reagent_transfer_amount || !iscarbon(victim))
+ return
+
+ var/mob/living/carbon/carbon_victim = victim
+ set_reagents()
+ for(var/reagent_id in spit_reagents)
+ spit_reagents[reagent_id] = carbon_victim.modify_by_armor(spit_reagents[reagent_id], armor_type, penetration, proj.def_zone)
+
+ carbon_victim.reagents.add_reagent_list(spit_reagents)
+
+/datum/ammo/xeno/boiler_gas/on_hit_obj(obj/O, obj/projectile/P)
+ if(ismecha(O))
+ P.damage *= 7 //Globs deal much higher damage to mechs.
+ var/turf/target_turf = get_turf(O)
+ drop_nade(O.density ? P.loc : target_turf, P.firer)
+
+/datum/ammo/xeno/boiler_gas/on_hit_turf(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T, P.firer) //we don't want the gas globs to land on dense turfs, they block smoke expansion.
+
+/datum/ammo/xeno/boiler_gas/do_at_max_range(turf/T, obj/projectile/P)
+ drop_nade(T.density ? P.loc : T, P.firer)
+
+/datum/ammo/xeno/boiler_gas/set_smoke()
+ smoke_system = new /datum/effect_system/smoke_spread/xeno/neuro()
+
+/datum/ammo/xeno/boiler_gas/drop_nade(turf/T, atom/firer, range = 1)
+ set_smoke()
+ if(isxeno(firer))
+ var/mob/living/carbon/xenomorph/X = firer
+ smoke_system.strength = X.xeno_caste.bomb_strength
+ range = fixed_spread_range
+ smoke_system.set_up(range, T)
+ smoke_system.start()
+ smoke_system = null
+ T.visible_message(danger_message)
+
+/datum/ammo/xeno/boiler_gas/corrosive
+ name = "glob of acid"
+ icon_state = "boiler_gas"
+ sound_hit = "acid_hit"
+ sound_bounce = "acid_bounce"
+ icon_key = BOILER_GLOB_ACID
+ select_text = "We will now fire corrosive acid. This is lethal!"
+ flags_ammo_behavior = AMMO_XENO|AMMO_SKIPS_ALIENS|AMMO_EXPLOSIVE
+ armor_type = ACID
+ danger_message = span_danger("A glob of acid lands with a splat and explodes into corrosive bile!")
+ damage = 50
+ damage_type = BURN
+ penetration = 40
+ bullet_color = BOILER_LUMINOSITY_AMMO_CORROSIVE_COLOR
+ hit_paralyze_time = 1 SECONDS
+ hit_eye_blur = 1
+ hit_drowsyness = 1
+ reagent_transfer_amount = 0
+
+/datum/ammo/xeno/boiler_gas/corrosive/enhance_trap(obj/structure/xeno/trap/trap, mob/living/carbon/xenomorph/user_xeno)
+ if(!do_after(user_xeno, 3 SECONDS, NONE, trap))
+ return FALSE
+ trap.set_trap_type(TRAP_SMOKE_ACID)
+ trap.smoke = new /datum/effect_system/smoke_spread/xeno/acid
+ trap.smoke.set_up(1, get_turf(trap))
+ return TRUE
+
+/datum/ammo/xeno/boiler_gas/corrosive/on_shield_block(mob/victim, obj/projectile/proj)
+ airburst(victim, proj)
+
+/datum/ammo/xeno/boiler_gas/corrosive/set_smoke()
+ smoke_system = new /datum/effect_system/smoke_spread/xeno/acid()
+
+/datum/ammo/xeno/boiler_gas/lance
+ name = "pressurized glob of gas"
+ icon_key = BOILER_GLOB_NEURO_LANCE
+ select_text = "We will now fire a pressurized neurotoxic lance. This is barely nonlethal."
+ ///As opposed to normal globs, this will pass by the target tile if they hit nothing.
+ flags_ammo_behavior = AMMO_XENO|AMMO_SKIPS_ALIENS|AMMO_LEAVE_TURF
+ danger_message = span_danger("A pressurized glob of acid lands with a nasty splat and explodes into noxious fumes!")
+ max_range = 40
+ damage = 75
+ penetration = 60
+ reagent_transfer_amount = 55
+ passed_turf_smoke_type = /datum/effect_system/smoke_spread/xeno/neuro/light
+ hit_paralyze_time = 2 SECONDS
+ hit_eye_blur = 16
+ hit_drowsyness = 18
+ fixed_spread_range = 2
+ accuracy = 100
+ accurate_range = 30
+ shell_speed = 1.5
+
+/datum/ammo/xeno/boiler_gas/corrosive/lance
+ name = "pressurized glob of acid"
+ icon_key = BOILER_GLOB_ACID_LANCE
+ select_text = "We will now fire a pressurized corrosive lance. This lethal!"
+ ///As opposed to normal globs, this will pass by the target tile if they hit nothing.
+ flags_ammo_behavior = AMMO_XENO|AMMO_SKIPS_ALIENS|AMMO_LEAVE_TURF
+ danger_message = span_danger("A pressurized glob of acid lands with a concerning hissing sound and explodes into corrosive bile!")
+ max_range = 40
+ damage = 75
+ penetration = 60
+ passed_turf_smoke_type = /datum/effect_system/smoke_spread/xeno/acid/light
+ hit_paralyze_time = 1.5 SECONDS
+ hit_eye_blur = 4
+ hit_drowsyness = 2
+ fixed_spread_range = 2
+ accuracy = 100
+ accurate_range = 30
+ shell_speed = 1.5
+
+/datum/ammo/xeno/hugger
+ name = "hugger ammo"
+ ping = ""
+ flags_ammo_behavior = AMMO_XENO
+ damage = 0
+ max_range = 6
+ shell_speed = 1
+ bullet_color = ""
+ icon_state = "facehugger"
+ ///The type of hugger thrown
+ var/obj/item/clothing/mask/facehugger/hugger_type = /obj/item/clothing/mask/facehugger
+
+/datum/ammo/xeno/hugger/on_hit_mob(mob/M, obj/projectile/proj)
+ var/obj/item/clothing/mask/facehugger/hugger = new hugger_type(get_turf(M), hivenumber)
+ hugger.go_idle()
+
+/datum/ammo/xeno/hugger/on_hit_obj(obj/O, obj/projectile/proj)
+ var/obj/item/clothing/mask/facehugger/hugger = new hugger_type(get_turf(O), hivenumber)
+ hugger.go_idle()
+
+/datum/ammo/xeno/hugger/on_hit_turf(turf/T, obj/projectile/P)
+ var/obj/item/clothing/mask/facehugger/hugger = new hugger_type(T.density ? P.loc : T, hivenumber)
+ hugger.go_idle()
+
+/datum/ammo/xeno/hugger/do_at_max_range(turf/T, obj/projectile/P)
+ var/obj/item/clothing/mask/facehugger/hugger = new hugger_type(T.density ? P.loc : T, hivenumber)
+ hugger.go_idle()
+
+/datum/ammo/xeno/hugger/slash
+ hugger_type = /obj/item/clothing/mask/facehugger/combat/slash
+
+/datum/ammo/xeno/hugger/neuro
+ hugger_type = /obj/item/clothing/mask/facehugger/combat/neuro
+
+/datum/ammo/xeno/hugger/resin
+ hugger_type = /obj/item/clothing/mask/facehugger/combat/resin
+
+/datum/ammo/xeno/hugger/acid
+ hugger_type = /obj/item/clothing/mask/facehugger/combat/acid
diff --git a/code/modules/projectiles/ammo_datums/yautja.dm b/code/modules/projectiles/ammo_datums/yautja.dm
new file mode 100644
index 00000000000..a20f149d079
--- /dev/null
+++ b/code/modules/projectiles/ammo_datums/yautja.dm
@@ -0,0 +1,181 @@
+/datum/ammo/energy/yautja
+ accurate_range = 12
+ shell_speed = 2
+ bullet_color = COLOR_STRONG_VIOLET
+ damage_type = BURN
+ flags_ammo_behavior = AMMO_IGNORE_RESIST
+
+ hud_state = "plasma"
+ hud_state_empty = "electrothermal_empty"
+
+/datum/ammo/energy/yautja/alloy_spike
+ name = "alloy spike"
+ ping = "ping_s"
+ icon_state = "MSpearFlight"
+ hud_state = "alloy_spike"
+ sound_hit = "alloy_hit"
+ sound_armor = "alloy_armor"
+ sound_bounce = "alloy_bounce"
+ bullet_color = COLOR_MAGENTA
+ armor_type = BULLET
+ accuracy = 20
+ accurate_range = 15
+ max_range = 15
+ damage = 40
+ penetration = 50
+ shrapnel_chance = 75
+
+/datum/ammo/energy/yautja/pistol
+ name = "plasma pistol bolt"
+ icon_state = "ion"
+
+ hud_state = "plasma_pistol"
+
+ bullet_color = COLOR_MAGENTA
+ damage = 40
+ shell_speed = 1.5
+
+/datum/ammo/energy/yautja/caster
+ name = "root caster bolt"
+ icon_state = "ion"
+
+/datum/ammo/energy/yautja/caster/stun
+ name = "low power stun bolt"
+ hud_state = "plasma_pistol"
+
+ bullet_color = COLOR_VIOLET
+ damage = 0
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_IGNORE_RESIST
+ var/stun_time = 5 SECONDS
+
+/datum/ammo/energy/yautja/caster/stun/on_hit_mob(mob/M, obj/projectile/P)
+ var/mob/living/carbon/C = M
+ if(istype(C))
+ if(isyautja(C) || ispredalien(C))
+ return
+ to_chat(C, span_danger("An electric shock ripples through your body, freezing you in place!"))
+ log_attack("[key_name(C)] was stunned by a high power stun bolt from [key_name(P.firer)] at [get_area(P)]")
+
+ if(ishuman(C))
+ var/mob/living/carbon/human/H = C
+ H.apply_effect(stun_time + 10 SECONDS, WEAKEN)
+ else
+ C.apply_effect(stun_time, WEAKEN)
+
+ C.apply_effect(stun_time, STUN)
+ ..()
+
+/datum/ammo/energy/yautja/caster/bolt
+ name = "plasma bolt"
+ icon_state = "pulse1"
+ flags_ammo_behavior = AMMO_IGNORE_RESIST
+ bullet_color = COLOR_BRIGHT_BLUE
+ shell_speed = 3
+ damage = 35
+
+/datum/ammo/energy/yautja/caster/bolt/stun
+ name = "high power stun bolt"
+ icon_state = "pred_stun"
+ var/stun_time = 20 SECONDS
+ bullet_color = COLOR_MAGENTA
+
+ hud_state = "plasma_rifle"
+
+ damage = 0
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_IGNORE_RESIST
+
+/datum/ammo/energy/yautja/caster/bolt/stun/on_hit_mob(mob/M, obj/projectile/P)
+ var/mob/living/carbon/C = M
+ if(istype(C))
+ if(isyautja(C) || ispredalien(C))
+ return
+ to_chat(C, span_danger("An electric shock ripples through your body, freezing you in place!"))
+ log_attack("[key_name(C)] was stunned by a high power stun bolt from [key_name(P.firer)] at [get_area(P)]")
+
+ if(ishuman(C))
+ var/mob/living/carbon/human/H = C
+ H.apply_effect(stun_time + 10 SECONDS, WEAKEN)
+ else
+ C.apply_effect(stun_time, WEAKEN)
+
+ C.apply_effect(stun_time, STUN)
+ ..()
+
+/datum/ammo/energy/yautja/caster/sphere
+ name = "plasma eradicator"
+ icon_state = "bluespace"
+ bullet_color = COLOR_BRIGHT_BLUE
+ flags_ammo_behavior = AMMO_EXPLOSIVE
+ shell_speed = 2
+ accuracy = 40
+
+ hud_state = "plasma_sphere"
+
+ damage = 55
+
+ accurate_range = 8
+ max_range = 8
+
+/datum/ammo/energy/yautja/caster/sphere/on_hit_mob(mob/M, obj/projectile/P)
+ cell_explosion(get_turf(M), 50, 25)
+
+/datum/ammo/energy/yautja/caster/sphere/on_hit_turf(turf/T, obj/projectile/P)
+ cell_explosion(get_turf(T), 50, 25)
+
+/datum/ammo/energy/yautja/caster/sphere/on_hit_obj(obj/O, obj/projectile/P)
+ cell_explosion(get_turf(O), 50, 25)
+
+/datum/ammo/energy/yautja/caster/sphere/do_at_max_range(obj/projectile/P)
+ cell_explosion(get_turf(P), 50, 25)
+
+/datum/ammo/energy/yautja/caster/sphere/stun
+ name = "plasma immobilizer"
+ bullet_color = COLOR_MAGENTA
+ damage = 0
+ flags_ammo_behavior = AMMO_ENERGY|AMMO_IGNORE_RESIST
+ hud_state = "plasma_rifle_blast"
+ accurate_range = 20
+ max_range = 20
+ var/stun_range = 4
+ var/stun_time = 6 SECONDS
+
+/datum/ammo/energy/yautja/caster/sphere/stun/on_hit_mob(mob/M, obj/projectile/P)
+ do_area_stun(P)
+
+/datum/ammo/energy/yautja/caster/sphere/stun/on_hit_turf(turf/T, obj/projectile/P)
+ do_area_stun(P)
+
+/datum/ammo/energy/yautja/caster/sphere/stun/on_hit_obj(obj/O, obj/projectile/P)
+ do_area_stun(P)
+
+/datum/ammo/energy/yautja/caster/sphere/stun/do_at_max_range(obj/projectile/P)
+ do_area_stun(P)
+
+/datum/ammo/energy/yautja/caster/sphere/stun/proc/do_area_stun(obj/projectile/P)
+ playsound(P, 'sound/weapons/wave.ogg', 75, 1, 25)
+ for(var/mob/living/carbon/M in view(stun_range, get_turf(P)))
+ var/f_stun_time = stun_time
+ log_attack("[key_name(M)] was stunned by a plasma immobilizer from [key_name(P.firer)] at [get_area(P)]")
+ if(isyautja(M))
+ f_stun_time -= 2 SECONDS
+ if(ispredalien(M))
+ continue
+ to_chat(M, span_danger("A powerful electric shock ripples through your body, freezing you in place!"))
+ M.apply_effect(f_stun_time, STUN)
+
+ if(ishuman(M))
+ var/mob/living/carbon/human/H = M
+ H.apply_effect(f_stun_time, WEAKEN)
+ else
+ M.apply_effect(f_stun_time, WEAKEN)
+
+/datum/ammo/energy/yautja/rifle/bolt
+ name = "plasma rifle bolt"
+ icon_state = "ion"
+ damage_type = BURN
+ flags_ammo_behavior = AMMO_IGNORE_RESIST
+
+ hud_state = "plasma_rifle"
+
+ damage = 70
+ penetration = 55
diff --git a/code/modules/projectiles/attachables/_attachable.dm b/code/modules/projectiles/attachables/_attachable.dm
new file mode 100644
index 00000000000..ec785523bfa
--- /dev/null
+++ b/code/modules/projectiles/attachables/_attachable.dm
@@ -0,0 +1,395 @@
+/** Gun attachable items code. Lets you add various effects to firearms.
+
+Some attachables are hardcoded in the projectile firing system, like grenade launchers, flamethrowers.
+
+When you are adding new guns into the attachment list, or even old guns, make sure that said guns
+properly accept overlays. You can find the proper offsets in the individual gun dms, so make sure
+you set them right. It's a pain to go back to find which guns are set incorrectly.
+To summarize: rail attachments should go on top of the rail. For rifles, this usually means the middle of the gun.
+For handguns, this is usually toward the back of the gun. SMGs usually follow rifles.
+Muzzle attachments should connect to the barrel, not sit under or above it. The only exception is the bayonet.
+Underrail attachments should just fit snugly, that's about it. Stocks are pretty obvious.
+
+All attachment offsets are now in a list, including stocks. Guns that don't take attachments can keep the list null.
+~N
+
+Anything that isn't used as the gun fires should be a flat number, never a percentange. It screws with the calculations,
+and can mean that the order you attach something/detach something will matter in the final number. It's also completely
+inaccurate. Don't worry if force is ever negative, it won't runtime.
+ */
+
+/obj/item/attachable
+ name = "attachable item"
+ desc = "It's an attachment. You should never see this."
+ icon = 'icons/Marine/marine-weapons.dmi'
+ icon_state = null
+ item_state = null
+
+ ///Determines the amount of pixels to move the icon state for the overlay. in the x direction
+ var/pixel_shift_x = 16
+ ///Determines the amount of pixels to move the icon state for the overlay. in the y direction
+ var/pixel_shift_y = 16
+
+ flags_atom = CONDUCT
+ w_class = WEIGHT_CLASS_SMALL
+ force = 1
+ ///ATTACHMENT_SLOT_MUZZLE, ATTACHMENT_SLOT_RAIL, ATTACHMENT_SLOT_UNDER, ATTACHMENT_SLOT_STOCK the particular 'slot' the attachment can attach to. must always be a singular slot.
+ var/slot = null
+
+ ///Modifier to firing accuracy, works off a multiplier.
+ var/accuracy_mod = 0
+ ///Modifier to firing accuracy but for when scoped in, works off a multiplier.
+ var/scoped_accuracy_mod = 0
+ ///Modifier to firing accuracy but for when onehanded.
+ var/accuracy_unwielded_mod = 0
+ ///Modifer to the damage mult, works off a multiplier.
+ var/damage_mod = 0
+ ///Modifier to damage falloff, works off a multiplier.
+ var/damage_falloff_mod = 0
+ ///Flat number that adjusts the amount of mêlée force the weapon this is attached to has.
+ var/melee_mod = 0
+ ///Increases or decreases scatter chance.
+ var/scatter_mod = 0
+ ///Increases or decreases scatter chance but for onehanded firing.
+ var/scatter_unwielded_mod = 0
+ ///Maximum scatter
+ var/max_scatter_mod = 0
+ ///Maximum scatter when unwielded
+ var/max_scatter_unwielded_mod = 0
+ ///How much scatter decays every X seconds
+ var/scatter_decay_mod = 0
+ ///How much scatter decays every X seconds when wielded
+ var/scatter_decay_unwielded_mod = 0
+ ///How much scatter increases per shot
+ var/scatter_increase_mod = 0
+ ///How much scatter increases per shot when wielded
+ var/scatter_increase_unwielded_mod = 0
+ ///Minimum scatter
+ var/min_scatter_mod = 0
+ ///Minimum scatter when unwielded
+ var/min_scatter_unwielded_mod = 0
+ ///If positive, adds recoil, if negative, lowers it. Recoil can't go below 0.
+ var/recoil_mod = 0
+ ///If positive, adds recoil, if negative, lowers it. but for onehanded firing. Recoil can't go below 0.
+ var/recoil_unwielded_mod = 0
+ ///Additive to burst scatter modifier from burst fire, works off a multiplier.
+ var/burst_scatter_mod = 0
+ ///additive modifier to burst fire accuracy.
+ var/burst_accuracy_mod = 0
+ ///Adds silenced to weapon. changing its fire sound, muzzle flash, and volume. TRUE or FALSE
+ var/silence_mod = FALSE
+ ///Adds an x-brightness flashlight to the weapon, which can be toggled on and off.
+ var/light_mod = 0
+ ///Changes firing delay. Cannot go below 0.
+ var/delay_mod = 0
+ ///Changes burst firing delay. Cannot go below 0.
+ var/burst_delay_mod = 0
+ ///Changes amount of shots in a burst
+ var/burst_mod = 0
+ ///Increases the weight class.
+ var/size_mod = 0
+ ///Changes the slowdown amount when wielding a weapon by this value.
+ var/aim_speed_mod = 0
+ ///How long ADS takes (time before firing)
+ var/wield_delay_mod = 0
+ ///Changes the speed of projectiles fired
+ var/attach_shell_speed_mod = 0
+ ///Modifies accuracy/scatter penalty when firing onehanded while moving.
+ var/movement_acc_penalty_mod = 0
+ ///How long in deciseconds it takes to attach a weapon with level 1 firearms training. Default is 1.5 seconds.
+ var/attach_delay = 1.5 SECONDS
+ ///How long in deciseconds it takes to detach a weapon with level 1 firearms training. Default is 1.5 seconds.
+ var/detach_delay = 1.5 SECONDS
+ ///Changes aim mode movement delay multiplicatively
+ var/aim_mode_movement_mult = 0
+ ///Modifies projectile damage by a % when a marine gets passed, but not hit
+ var/shot_marine_damage_falloff = 0
+ ///Modifies aim mode fire rate debuff by a %
+ var/aim_mode_delay_mod = 0
+ ///adds aim mode to the gun
+ var/add_aim_mode = FALSE
+ ///the delay between shots, for attachments that fire stuff
+ var/attachment_firing_delay = 0
+
+ ///The specific sound played when activating this attachment.
+ var/activation_sound = 'sound/machines/click.ogg'
+
+ ///various yes no flags associated with attachments. See defines for these: [ATTACH_REMOVABLE]
+ var/flags_attach_features = ATTACH_REMOVABLE
+
+ ///only used by lace, denotes whether the lace is currently deployed
+ var/lace_deployed = FALSE
+
+
+ ///what ability to give the user when attached to a weapon they are holding.
+ var/attachment_action_type
+ ///used for the codex to denote if a weapon has the ability to zoom in or not.
+ var/scope_zoom_mod = FALSE
+
+ ///what ammo the gun could also fire, different lasers usually.
+ var/ammo_mod = null
+ ///how much charge difference it now costs to shoot. negative means more shots per mag.
+ var/charge_mod = 0
+ ///what firemodes this attachment allows/adds.
+ var/gun_firemode_list_mod = null
+
+ ///lazylist of attachment slot offsets for a gun.
+ var/list/gun_attachment_offset_mod
+
+ ///what gun this attachment is currently attached to, if any.
+ var/obj/item/weapon/gun/master_gun
+
+ ///Skill used to attach src to something.
+ var/attach_skill = SKILL_FIREARMS
+ ///Skill threshold where the time to attach is halved.
+ var/attach_skill_upper_threshold = SKILL_FIREARMS_TRAINED
+ ///Sound played on attach
+ var/attach_sound = 'sound/machines/click.ogg'
+
+ ///Replacement for initial icon that allows for the code to work with multiple variants
+ var/base_icon
+ ///Assoc list that uses the parents type as a key. type = "new_icon_state". This will change the icon state depending on what type the parent is. If the list is empty, or the parent type is not within, it will have no effect.
+ var/list/variants_by_parent_type = list()
+
+/obj/item/attachable/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/attachment, slot, icon, PROC_REF(on_attach), PROC_REF(on_detach), PROC_REF(activate), PROC_REF(can_attach), pixel_shift_x, pixel_shift_y, flags_attach_features, attach_delay, detach_delay, attach_skill, attach_skill_upper_threshold, attach_sound)
+
+///Called when the attachment is attached to something. If it is a gun it will update the guns stats.
+/obj/item/attachable/proc/on_attach(attaching_item, mob/user)
+
+ if(!istype(attaching_item, /obj/item/weapon/gun))
+ return //Guns only
+
+ master_gun = attaching_item
+
+ apply_modifiers(attaching_item, user, TRUE)
+
+ if(attachment_action_type)
+ var/datum/action/action_to_update = new attachment_action_type(src, master_gun)
+ if(isliving(master_gun.loc))
+ var/mob/living/living_user = master_gun.loc
+ if(master_gun == living_user.l_hand || master_gun == living_user.r_hand)
+ action_to_update.give_action(living_user)
+
+ //custom attachment icons for specific guns
+ if(length(variants_by_parent_type))
+ for(var/selection in variants_by_parent_type)
+ if(istype(master_gun, selection))
+ icon_state = variants_by_parent_type[selection]
+
+ update_icon()
+
+///Called when the attachment is detached from something. If the thing is a gun, it returns its stats to what they were before being attached.
+/obj/item/attachable/proc/on_detach(detaching_item, mob/user)
+ if(!isgun(detaching_item))
+ return
+
+ activate(user, TRUE)
+
+ apply_modifiers(detaching_item, user, FALSE)
+
+ for(var/datum/action/action_to_update AS in master_gun.actions)
+ if(action_to_update.target != src)
+ continue
+ qdel(action_to_update)
+ break
+
+ master_gun = null
+ icon_state = initial(icon_state)
+ update_icon()
+
+///Handles the modifiers to the parent gun
+/obj/item/attachable/proc/apply_modifiers(attaching_item, mob/user, attaching)
+ if(attaching)
+ master_gun.accuracy_mult += accuracy_mod
+ master_gun.accuracy_mult_unwielded += accuracy_unwielded_mod
+ master_gun.damage_mult += damage_mod
+ master_gun.damage_falloff_mult += damage_falloff_mod
+ master_gun.w_class += size_mod
+ master_gun.scatter += scatter_mod
+ master_gun.scatter_unwielded += scatter_unwielded_mod
+ master_gun.max_scatter += max_scatter_mod
+ master_gun.max_scatter_unwielded += max_scatter_unwielded_mod
+ master_gun.scatter_decay += scatter_decay_mod
+ master_gun.scatter_decay_unwielded += scatter_decay_unwielded_mod
+ master_gun.scatter_increase += scatter_increase_mod
+ master_gun.scatter_increase_unwielded += scatter_increase_unwielded_mod
+ master_gun.min_scatter += min_scatter_mod
+ master_gun.min_scatter_unwielded += min_scatter_unwielded_mod
+ master_gun.aim_speed_modifier += initial(master_gun.aim_speed_modifier)*aim_mode_movement_mult
+ master_gun.iff_marine_damage_falloff += shot_marine_damage_falloff
+ master_gun.add_aim_mode_fire_delay(name, initial(master_gun.aim_fire_delay) * aim_mode_delay_mod)
+ if(add_aim_mode)
+ var/datum/action/item_action/aim_mode/A = new (master_gun)
+ ///actually gives the user aim_mode if they're holding the gun
+ if(user)
+ A.give_action(user)
+ if(delay_mod)
+ master_gun.modify_fire_delay(delay_mod)
+ if(burst_delay_mod)
+ master_gun.modify_burst_delay(burst_delay_mod)
+ if(burst_mod)
+ master_gun.modify_burst_amount(burst_mod, user)
+ master_gun.recoil += recoil_mod
+ master_gun.recoil_unwielded += recoil_unwielded_mod
+ master_gun.force += melee_mod
+ master_gun.sharp += sharp
+ master_gun.aim_slowdown += aim_speed_mod
+ master_gun.wield_delay += wield_delay_mod
+ master_gun.burst_scatter_mult += burst_scatter_mod
+ master_gun.burst_accuracy_bonus += burst_accuracy_mod
+ master_gun.movement_acc_penalty_mult += movement_acc_penalty_mod
+ master_gun.shell_speed_mod += attach_shell_speed_mod
+ master_gun.scope_zoom += scope_zoom_mod
+ if(ammo_mod)
+ master_gun.add_ammo_mod(ammo_mod)
+ if(charge_mod)
+ master_gun.charge_cost += charge_mod
+ for(var/i in gun_firemode_list_mod)
+ master_gun.add_firemode(i, user)
+ master_gun.update_force_list() //This updates the gun to use proper force verbs.
+
+ if(silence_mod)
+ ADD_TRAIT(master_gun, TRAIT_GUN_SILENCED, GUN_TRAIT)
+ master_gun.muzzle_flash = null
+ //master_gun.fire_sound = "gun_silenced" //ORIGINAL
+ master_gun.fire_sound = master_gun.silenced_sound
+ else
+ master_gun.accuracy_mult -= accuracy_mod
+ master_gun.accuracy_mult_unwielded -= accuracy_unwielded_mod
+ master_gun.damage_mult -= damage_mod
+ master_gun.damage_falloff_mult -= damage_falloff_mod
+ master_gun.w_class -= size_mod
+ master_gun.scatter -= scatter_mod
+ master_gun.scatter_unwielded -= scatter_unwielded_mod
+ master_gun.max_scatter -= max_scatter_mod
+ master_gun.max_scatter_unwielded -= max_scatter_unwielded_mod
+ master_gun.scatter_decay -= scatter_decay_mod
+ master_gun.scatter_decay_unwielded -= scatter_decay_unwielded_mod
+ master_gun.scatter_increase -= scatter_increase_mod
+ master_gun.scatter_increase_unwielded -= scatter_increase_unwielded_mod
+ master_gun.min_scatter -= min_scatter_mod
+ master_gun.min_scatter_unwielded -= min_scatter_unwielded_mod
+ master_gun.aim_speed_modifier -= initial(master_gun.aim_speed_modifier)*aim_mode_movement_mult
+ master_gun.iff_marine_damage_falloff -= shot_marine_damage_falloff
+ master_gun.remove_aim_mode_fire_delay(name)
+ if(add_aim_mode)
+ var/datum/action/item_action/aim_mode/action_to_delete = locate() in master_gun.actions
+ QDEL_NULL(action_to_delete)
+ if(delay_mod)
+ master_gun.modify_fire_delay(-delay_mod)
+ if(burst_delay_mod)
+ master_gun.modify_burst_delay(-burst_delay_mod)
+ if(burst_mod)
+ master_gun.modify_burst_amount(-burst_mod, user)
+ master_gun.recoil -= recoil_mod
+ master_gun.recoil_unwielded -= recoil_unwielded_mod
+ master_gun.force -= melee_mod
+ master_gun.sharp -= sharp
+ master_gun.aim_slowdown -= aim_speed_mod
+ master_gun.wield_delay -= wield_delay_mod
+ master_gun.burst_scatter_mult -= burst_scatter_mod
+ master_gun.burst_accuracy_bonus -= burst_accuracy_mod
+ master_gun.movement_acc_penalty_mult -= movement_acc_penalty_mod
+ master_gun.shell_speed_mod -= attach_shell_speed_mod
+ master_gun.scope_zoom -= scope_zoom_mod
+ if(ammo_mod)
+ master_gun.remove_ammo_mod(ammo_mod)
+ if(master_gun.charge_cost)
+ master_gun.charge_cost -= charge_mod
+ for(var/i in gun_firemode_list_mod)
+ master_gun.remove_firemode(i, user)
+
+ master_gun.update_force_list()
+
+ if(silence_mod) //Built in silencers always come as an attach, so the gun can't be silenced right off the bat.
+ REMOVE_TRAIT(master_gun, TRAIT_GUN_SILENCED, GUN_TRAIT)
+ master_gun.muzzle_flash = initial(master_gun.muzzle_flash)
+ master_gun.fire_sound = initial(master_gun.fire_sound)
+
+/obj/item/attachable/ui_action_click(mob/living/user, datum/action/item_action/action, obj/item/weapon/gun/G)
+ if(G == user.get_active_held_item() || G == user.get_inactive_held_item() || CHECK_BITFIELD(G.flags_item, IS_DEPLOYED))
+ if(activate(user)) //success
+ playsound(user, activation_sound, 15, 1)
+ else
+ to_chat(user, span_warning("[G] must be in our hands to do this."))
+
+///Called when the attachment is activated.
+/obj/item/attachable/proc/activate(mob/user, turn_off) //This is for activating stuff like flamethrowers, or switching weapon modes, or flashlights.
+ return TRUE
+
+///Called when the attachment is trying to be attached. If the attachment is allowed to go through, return TRUE.
+/obj/item/attachable/proc/can_attach(obj/item/attaching_to, mob/attacher)
+ return TRUE
+
+///This is called when an attachment gun (src) attaches to a gun.
+/obj/item/weapon/gun/proc/on_attach(obj/item/attached_to, mob/user)
+ if(!istype(attached_to, /obj/item/weapon/gun))
+ return
+ master_gun = attached_to
+ master_gun.wield_delay += wield_delay_mod
+ if(gun_user)
+ UnregisterSignal(gun_user, list(COMSIG_MOB_MOUSEDOWN, COMSIG_MOB_MOUSEUP, COMSIG_ITEM_ZOOM, COMSIG_ITEM_UNZOOM, COMSIG_MOB_MOUSEDRAG, COMSIG_KB_RAILATTACHMENT, COMSIG_KB_UNDERRAILATTACHMENT, COMSIG_KB_UNLOADGUN, COMSIG_KB_FIREMODE, COMSIG_KB_GUN_SAFETY, COMSIG_KB_AUTOEJECT, COMSIG_KB_UNIQUEACTION, COMSIG_QDELETING, COMSIG_MOB_CLICK_RIGHT))
+ var/datum/action/item_action/toggle/new_action = new /datum/action/item_action/toggle(src, master_gun)
+ if(!isliving(user))
+ return
+ var/mob/living/living_user = user
+ if(master_gun == living_user.get_inactive_held_item() || master_gun == living_user.get_active_held_item())
+ new_action.give_action(living_user)
+ attached_to:gunattachment = src
+ activate(user)
+ new_action.set_toggle(TRUE)
+ new_action.update_button_icon()
+ update_icon()
+ RegisterSignal(master_gun, COMSIG_ITEM_REMOVED_INVENTORY, TYPE_PROC_REF(/obj/item/weapon/gun, drop_connected_mag))
+
+///This is called when an attachment gun (src) detaches from a gun.
+/obj/item/weapon/gun/proc/on_detach(obj/item/attached_to, mob/user)
+ if(!istype(attached_to, /obj/item/weapon/gun))
+ return
+ for(var/datum/action/action_to_delete AS in master_gun.actions)
+ if(action_to_delete.target != src)
+ continue
+ QDEL_NULL(action_to_delete)
+ break
+ icon_state = initial(icon_state)
+ if(master_gun.active_attachable == src)
+ master_gun.active_attachable = null
+ master_gun.wield_delay -= wield_delay_mod
+ UnregisterSignal(master_gun, COMSIG_ITEM_REMOVED_INVENTORY)
+ master_gun = null
+ attached_to:gunattachment = null
+ update_icon()
+
+///This activates the weapon for use.
+/obj/item/weapon/gun/proc/activate(mob/user)
+ if(master_gun.active_attachable)
+ if(master_gun.active_attachable != src)
+ master_gun.active_attachable.activate(user)
+ return TRUE
+ master_gun.active_attachable = null
+ set_gun_user(null)
+ to_chat(user, span_notice("You stop using [src]."))
+ else
+ master_gun.active_attachable = src
+ set_gun_user(null)
+ set_gun_user(master_gun.gun_user)
+ to_chat(user, span_notice("You start using [src]."))
+ for(var/datum/action/item_action/toggle/action AS in master_gun.actions)
+ if(action.target != src )
+ continue
+ action.set_toggle(master_gun.active_attachable == src)
+ action.update_button_icon()
+ return TRUE
+
+///Called when the attachment is trying to be attached. If the attachment is allowed to go through, return TRUE.
+/obj/item/weapon/gun/proc/can_attach(obj/item/attaching_to, mob/attacher)
+ return TRUE
+
+///Called when an attachment is attached to this gun (src).
+/obj/item/weapon/gun/proc/on_attachment_attach(obj/item/attaching_here, mob/attacher)
+ return
+///Called when an attachment is detached from this gun (src).
+/obj/item/weapon/gun/proc/on_attachment_detach(obj/item/detaching_here, mob/attacher)
+ return
diff --git a/code/modules/projectiles/attachables/flamer.dm b/code/modules/projectiles/attachables/flamer.dm
new file mode 100644
index 00000000000..af458858e4c
--- /dev/null
+++ b/code/modules/projectiles/attachables/flamer.dm
@@ -0,0 +1,82 @@
+/obj/item/attachable/flamer_nozzle
+ name = "standard flamer nozzle"
+ desc = "The standard flamer nozzle. This one fires a stream of fire for direct and accurate flames. Though not as area filling as its counterpart, this one excels at directed frontline combat."
+ icon_state = "flame_directional"
+ slot = ATTACHMENT_SLOT_FLAMER_NOZZLE
+ attach_delay = 2 SECONDS
+ detach_delay = 2 SECONDS
+ ///This is pulled when the parent flamer fires, it determins how the parent flamers fire stream acts.
+ var/stream_type = FLAMER_STREAM_STRAIGHT
+ ///Modifier for burn level of attached flamer. Percentage based.
+ var/burn_level_mod = 1
+ ///Modifier for burn time of attached flamer. Percentage based.
+ var/burn_time_mod = 1
+ ///Range modifier of attached flamer. Numerically based.
+ var/range_modifier = 0
+ ///Damage multiplier for mobs caught in the initial stream of fire of the attached flamer.
+ var/mob_flame_damage_mod = 1
+
+/obj/item/attachable/flamer_nozzle/on_attach(attaching_item, mob/user)
+ . = ..()
+ if(!istype(attaching_item, /obj/item/weapon/gun/flamer))
+ return
+ var/obj/item/weapon/gun/flamer/flamer = attaching_item
+ flamer.burn_level_mod *= burn_level_mod
+ flamer.burn_time_mod *= burn_time_mod
+ flamer.flame_max_range += range_modifier
+ flamer.mob_flame_damage_mod *= mob_flame_damage_mod
+
+/obj/item/attachable/flamer_nozzle/on_detach(attaching_item, mob/user)
+ . = ..()
+ if(!istype(attaching_item, /obj/item/weapon/gun/flamer))
+ return
+ var/obj/item/weapon/gun/flamer/flamer = attaching_item
+ flamer.burn_level_mod /= burn_level_mod
+ flamer.burn_time_mod /= burn_time_mod
+ flamer.flame_max_range -= range_modifier
+ flamer.mob_flame_damage_mod /= mob_flame_damage_mod
+
+/obj/item/attachable/flamer_nozzle/unremovable
+ flags_attach_features = NONE
+
+/obj/item/attachable/flamer_nozzle/unremovable/invisible
+ icon_state = null
+
+/obj/item/attachable/flamer_nozzle/wide
+ name = "spray flamer nozzle"
+ desc = "This specialized nozzle sprays the flames of an attached flamer in a much more broad way than the standard nozzle. It serves for wide area denial as opposed to offensive directional flaming."
+ icon_state = "flame_wide"
+ pixel_shift_y = 17
+ stream_type = FLAMER_STREAM_CONE
+ burn_time_mod = 0.3
+
+///Funny red wide nozzle that can fill entire screens with flames. Admeme only.
+/obj/item/attachable/flamer_nozzle/wide/red
+ name = "red spray flamer nozzle"
+ desc = "It is red, therefore its obviously more effective."
+ icon_state = "flame_wide_red"
+ range_modifier = 3
+
+///Flamer ammo is a normal ammo datum, which means we can shoot it if we want
+/obj/item/attachable/flamer_nozzle/long
+ name = "extended flamer nozzle"
+ icon_state = "flame_long"
+ desc = "Rather than spreading the supplied fuel over an area, this nozzle launches a single fireball to ignite a target at range. Reduced volume per shot also means the next is ready quicker."
+ stream_type = FLAMER_STREAM_RANGED
+ delay_mod = -10
+
+/obj/item/attachable/flamer_nozzle/long/on_attach(attaching_item, mob/user)
+ . = ..()
+ if(!istype(attaching_item, /obj/item/weapon/gun/flamer))
+ return
+ var/obj/item/weapon/gun/flamer/flamer = attaching_item
+ //Since we're firing more like a normal gun, we do need to use up rounds after firing
+ flamer.reciever_flags &= ~AMMO_RECIEVER_DO_NOT_EMPTY_ROUNDS_AFTER_FIRE
+
+/obj/item/attachable/flamer_nozzle/long/on_detach(attaching_item, mob/user)
+ . = ..()
+ if(!istype(attaching_item, /obj/item/weapon/gun/flamer))
+ return
+ var/obj/item/weapon/gun/flamer/flamer = attaching_item
+ if(initial(flamer.reciever_flags) & AMMO_RECIEVER_DO_NOT_EMPTY_ROUNDS_AFTER_FIRE)
+ flamer.reciever_flags |= AMMO_RECIEVER_DO_NOT_EMPTY_ROUNDS_AFTER_FIRE
diff --git a/code/modules/projectiles/attachables/foldable.dm b/code/modules/projectiles/attachables/foldable.dm
new file mode 100644
index 00000000000..4f957b0002c
--- /dev/null
+++ b/code/modules/projectiles/attachables/foldable.dm
@@ -0,0 +1,184 @@
+/obj/item/attachable/foldable
+ name = "foldable stock"
+ desc = "A foldable stock. You shouldn't see this."
+ icon_state = ""
+ slot = ATTACHMENT_SLOT_STOCK
+ flags_attach_features = ATTACH_REMOVABLE|ATTACH_ACTIVATION
+ attachment_action_type = /datum/action/item_action/toggle
+ ///How long it takes to fold or unfold
+ var/deploy_time
+ ///whether the attachment is currently folded or not
+ var/folded = TRUE
+
+/obj/item/attachable/foldable/on_attach(attaching_item, mob/user)
+ if(!istype(attaching_item, /obj/item/weapon/gun))
+ return //Guns only
+
+ master_gun = attaching_item
+
+ if(attachment_action_type)
+ var/datum/action/action_to_update = new attachment_action_type(src, master_gun)
+ if(isliving(master_gun.loc))
+ var/mob/living/living_user = master_gun.loc
+ if(master_gun == living_user.l_hand || master_gun == living_user.r_hand)
+ action_to_update.give_action(living_user)
+
+ //custom attachment icons for specific guns
+ if(length(variants_by_parent_type))
+ for(var/selection in variants_by_parent_type)
+ if(istype(master_gun, selection))
+ icon_state = variants_by_parent_type[selection]
+
+ update_icon()
+
+/obj/item/attachable/foldable/on_detach(detaching_item, mob/user)
+ if(!isgun(detaching_item))
+ return
+
+ if(!folded)
+ activate()
+
+ for(var/datum/action/action_to_update AS in master_gun.actions)
+ if(action_to_update.target != src)
+ continue
+ qdel(action_to_update)
+ break
+
+ master_gun = null
+ icon_state = initial(icon_state)
+ update_icon()
+ if(!greyscale_config || !greyscale_colors)
+ return
+ UnregisterSignal(master_gun, COMSIG_ITEM_SECONDARY_COLOR)
+
+/obj/item/attachable/foldable/activate(mob/living/user, turn_off)
+ if(user && deploy_time && !do_after(user, deploy_time, NONE, src, BUSY_ICON_BAR))
+ return FALSE
+
+ folded = !folded
+ playsound(src, 'sound/machines/click.ogg', 20, FALSE, 4)
+ update_icon()
+
+ if(master_gun)
+ apply_modifiers(master_gun, user, !folded)
+ for(var/X in master_gun.actions)
+ var/datum/action/A = X
+ A.update_button_icon()
+
+ return TRUE
+
+/obj/item/attachable/foldable/update_icon_state()
+ . = ..()
+ if(folded)
+ icon_state = initial(icon_state)
+ else
+ icon_state = "[initial(icon_state)]_open"
+
+/obj/item/attachable/foldable/skorpion_stock
+ name = "\improper Skorpion submachinegun wooden stock"
+ desc = "A foldable wire stock for a Skorpion submachinegun"
+ icon = 'icons/Marine/attachments_64.dmi'
+ icon_state = "skorpion"
+ flags_attach_features = ATTACH_ACTIVATION
+ pixel_shift_x = 0
+ pixel_shift_y = 0
+ size_mod = 2
+ wield_delay_mod = 0.1 SECONDS
+ accuracy_mod = 0.25
+ recoil_mod = -2
+ scatter_mod = -6
+ scatter_unwielded_mod = 4
+ accuracy_unwielded_mod = -0.1
+
+/obj/item/attachable/foldable/t19stock
+ name = "\improper MP-19 machinepistol stock"
+ desc = "A submachinegun stock distributed in small numbers to TGMC forces. Compatible with the MP-19, this stock reduces recoil and improves accuracy, but at a reduction to handling and agility. Seemingly a bit more effective in a brawl."
+ flags_attach_features = ATTACH_ACTIVATION
+ wield_delay_mod = 0.1 SECONDS
+ melee_mod = 5
+ size_mod = 1
+ icon_state = "t19stock"
+ accuracy_mod = 0.3
+ recoil_mod = -2
+ scatter_mod = -8
+ accuracy_unwielded_mod = -0.1
+ scatter_unwielded_mod = 4
+
+/obj/item/attachable/foldable/som_carbine
+ name = "\improper V-34 carbine stock"
+ desc = "A side folding stock built into the V-34 carbine. The gun is designed to be fired with the stock deployed, but can be done without, with some difficulty."
+ flags_attach_features = ATTACH_ACTIVATION
+ wield_delay_mod = 0.1 SECONDS
+ melee_mod = 5
+ size_mod = 1
+ icon_state = "v34stock"
+ accuracy_mod = 0.2
+ recoil_mod = -2
+ scatter_mod = -8
+ aim_speed_mod = 0.05
+
+/obj/item/attachable/foldable/icc_machinepistol
+ name = "\improper PL-38 machinepistol stock"
+ desc = "A submachinegun stock found on ICC subguns, this stock reduces recoil and improves accuracy, but at a reduction to handling and agility. Seemingly a bit more effective in a brawl."
+ flags_attach_features = ATTACH_ACTIVATION
+ icon = 'icons/Marine/attachments_64.dmi'
+ wield_delay_mod = 0.1 SECONDS
+ melee_mod = 5
+ size_mod = 1
+ icon_state = "pl38stock"
+ accuracy_mod = 0.3
+ recoil_mod = -2
+ scatter_mod = -8
+ accuracy_unwielded_mod = -0.1
+ scatter_unwielded_mod = 4
+
+/obj/item/attachable/foldable/t35stock
+ name = "\improper SH-35 stock"
+ desc = "A non-standard heavy stock for the SH-35 shotgun. Less quick and more cumbersome than the standard issue stakeout, but reduces recoil and improves accuracy. Allegedly makes a pretty good club in a fight too."
+ icon = 'icons/Marine/attachments_64.dmi'
+ icon_state = "t35stock"
+ flags_attach_features = ATTACH_ACTIVATION
+ wield_delay_mod = 0.2 SECONDS
+ accuracy_mod = 0.15
+ recoil_mod = -3
+ scatter_mod = -2
+
+/obj/item/attachable/foldable/bipod
+ name = "bipod"
+ desc = "A simple set of telescopic poles to keep a weapon stabilized during firing. \nGreatly increases accuracy and reduces recoil and scatter when properly placed, but also increases weapon size."
+ icon_state = "bipod"
+ slot = ATTACHMENT_SLOT_UNDER
+ size_mod = 2
+ deploy_time = 1 SECONDS
+ accuracy_mod = 0.3
+ recoil_mod = -2
+ scatter_mod = -10
+ burst_scatter_mod = -3
+ aim_mode_delay_mod = -0.5
+
+/obj/item/attachable/foldable/bipod/activate(mob/living/user, turn_off)
+ if(folded && !(master_gun.flags_item & WIELDED)) //no one handed bipod use
+ if(user)
+ balloon_alert(user, "Unwielded")
+ return
+
+ . = ..()
+
+ if(folded)
+ UnregisterSignal(master_gun, list(COMSIG_ITEM_DROPPED, COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_UNWIELD))
+ UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
+ to_chat(user, span_notice("You retract [src]."))
+ return
+
+ if(user)
+ RegisterSignals(master_gun, list(COMSIG_ITEM_DROPPED, COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_UNWIELD), PROC_REF(retract_bipod))
+ RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(retract_bipod))
+ to_chat(user, span_notice("You deploy [src]."))
+
+///Signal handler for forced undeployment
+/obj/item/attachable/foldable/bipod/proc/retract_bipod(datum/source, mob/living/user)
+ SIGNAL_HANDLER
+ deploy_time = 0
+ INVOKE_ASYNC(src, PROC_REF(activate), (istype(user) ? user : source), TRUE)
+ deploy_time = initial(deploy_time)
+ to_chat(user, span_warning("Losing support, the bipod retracts!"))
diff --git a/code/modules/projectiles/attachables/muzzle.dm b/code/modules/projectiles/attachables/muzzle.dm
new file mode 100644
index 00000000000..01736e9b2a0
--- /dev/null
+++ b/code/modules/projectiles/attachables/muzzle.dm
@@ -0,0 +1,263 @@
+/obj/item/attachable/suppressor
+ name = "suppressor"
+ desc = "A small tube with exhaust ports to expel noise and gas.\nDoes not completely silence a weapon, but does make it much quieter and a little more accurate and stable."
+ icon_state = "suppressor"
+ slot = ATTACHMENT_SLOT_MUZZLE
+ silence_mod = TRUE
+ pixel_shift_y = 16
+ attach_shell_speed_mod = 0.5
+ accuracy_mod = 0
+ recoil_mod = 0
+ scatter_mod = -2
+ size_mod = 1
+ recoil_unwielded_mod = 0
+ scatter_unwielded_mod = 0
+ damage_falloff_mod = 0
+
+/obj/item/attachable/suppressor/unremovable
+ flags_attach_features = NONE
+
+/obj/item/attachable/suppressor/unremovable/invisible
+ icon_state = ""
+
+/obj/item/attachable/suppressor/unremovable/invisible/Initialize(mapload, ...)
+ . = ..()
+
+/obj/item/attachable/bayonet
+ name = "bayonet"
+ desc = "A sharp blade for mounting on a weapon. It can be used to stab manually on anything but harm intent. Slightly reduces the accuracy of the gun when mounted."
+ icon_state = "bayonet"
+ item_icons = list(
+ slot_l_hand_str = 'icons/mob/inhands/weapons/melee_left.dmi',
+ slot_r_hand_str = 'icons/mob/inhands/weapons/melee_right.dmi',
+ )
+ force = 20
+ throwforce = 10
+ attach_delay = 10 //Bayonets attach/detach quickly.
+ detach_delay = 10
+ attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
+ melee_mod = 25
+ slot = ATTACHMENT_SLOT_MUZZLE
+ pixel_shift_x = 14 //Below the muzzle.
+ pixel_shift_y = 18
+ accuracy_mod = -0.05
+ accuracy_unwielded_mod = -0.1
+ size_mod = 1
+ sharp = IS_SHARP_ITEM_ACCURATE
+ variants_by_parent_type = list(/obj/item/weapon/gun/shotgun/pump/t35 = "bayonet_t35")
+
+/obj/item/attachable/bayonet/screwdriver_act(mob/living/user, obj/item/I)
+ to_chat(user, span_notice("You modify the bayonet back into a combat knife."))
+ if(loc == user)
+ user.dropItemToGround(src)
+ var/obj/item/weapon/combat_knife/knife = new(loc)
+ user.put_in_hands(knife) //This proc tries right, left, then drops it all-in-one.
+ if(knife.loc != user) //It ended up on the floor, put it whereever the old flashlight is.
+ knife.forceMove(loc)
+ qdel(src) //Delete da old bayonet
+
+/obj/item/attachable/bayonetknife
+ name = "M-22 bayonet"
+ desc = "A sharp knife that is the standard issue combat knife of the TerraGov Marine Corps can be attached to a variety of weapons at will or used as a standard knife."
+ icon = 'icons/obj/items/weapons.dmi'
+ icon_state = "bayonetknife"
+ item_icons = list(
+ slot_l_hand_str = 'icons/mob/inhands/weapons/melee_left.dmi',
+ slot_r_hand_str = 'icons/mob/inhands/weapons/melee_right.dmi',
+ )
+ force = 25
+ throwforce = 20
+ throw_speed = 3
+ throw_range = 6
+ attack_speed = 8
+ attach_delay = 10 //Bayonets attach/detach quickly.
+ detach_delay = 10
+ attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
+ melee_mod = 25
+ slot = ATTACHMENT_SLOT_MUZZLE
+ pixel_shift_x = 14 //Below the muzzle.
+ pixel_shift_y = 18
+ accuracy_mod = -0.05
+ accuracy_unwielded_mod = -0.1
+ size_mod = 1
+ sharp = IS_SHARP_ITEM_ACCURATE
+ variants_by_parent_type = list(/obj/item/weapon/gun/shotgun/pump/t35 = "bayonetknife_t35")
+
+/obj/item/attachable/bayonetknife/Initialize(mapload)
+ . = ..()
+ AddElement(/datum/element/scalping)
+ AddElement(/datum/element/shrapnel_removal, 12 SECONDS, 12 SECONDS, 10)
+
+/obj/item/attachable/melee_attack_chain(mob/user, atom/target, params, rightclick)
+ if(target == user && !user.do_self_harm)
+ return
+ return ..()
+
+/obj/item/attachable/bayonetknife/som
+ name = "\improper S20 SOM bayonet"
+ desc = "A large knife that is the standard issue combat knife of the SOM. Can be attached to a variety of weapons at will or used as a standard knife."
+ icon_state = "bayonetknife_som"
+ item_state = "bayonetknife"
+ force = 30
+
+/obj/item/attachable/extended_barrel
+ name = "extended barrel"
+ desc = "A lengthened barrel allows for lessened scatter, greater accuracy and muzzle velocity due to increased stabilization and shockwave exposure."
+ slot = ATTACHMENT_SLOT_MUZZLE
+ icon_state = "ebarrel"
+ attach_shell_speed_mod = 1
+ accuracy_mod = 0.15
+ accuracy_unwielded_mod = 0.1
+ scatter_mod = -1
+ size_mod = 1
+ variants_by_parent_type = list(/obj/item/weapon/gun/rifle/som = "ebarrel_big", /obj/item/weapon/gun/smg/som = "ebarrel_big", /obj/item/weapon/gun/shotgun/pump/t35 = "ebarrel_big")
+
+/obj/item/attachable/heavy_barrel
+ name = "barrel charger"
+ desc = "A fitted barrel extender that goes on the muzzle, with a small shaped charge that propels a bullet much faster.\nGreatly increases projectile speed and reduces damage falloff."
+ slot = ATTACHMENT_SLOT_MUZZLE
+ icon_state = "hbarrel"
+ attach_shell_speed_mod = 2
+ accuracy_mod = -0.05
+ damage_falloff_mod = -0.2
+
+/obj/item/attachable/compensator
+ name = "recoil compensator"
+ desc = "A muzzle attachment that reduces recoil and scatter by diverting expelled gasses upwards. \nSignificantly reduces recoil and scatter, regardless of if the weapon is wielded."
+ slot = ATTACHMENT_SLOT_MUZZLE
+ icon_state = "comp"
+ pixel_shift_x = 17
+ scatter_mod = -3
+ recoil_mod = -2
+ scatter_unwielded_mod = -3
+ recoil_unwielded_mod = -2
+ variants_by_parent_type = list(
+ /obj/item/weapon/gun/rifle/som = "comp_big",
+ /obj/item/weapon/gun/smg/som = "comp_big",
+ /obj/item/weapon/gun/shotgun/som = "comp_big",
+ /obj/item/weapon/gun/shotgun/pump/t35 = "comp_big",
+ /obj/item/weapon/gun/revolver/standard_magnum = "t76comp"
+ )
+
+/obj/item/attachable/sniperbarrel
+ name = "sniper barrel"
+ icon_state = "sniperbarrel"
+ desc = "A heavy barrel. CANNOT BE REMOVED."
+ slot = ATTACHMENT_SLOT_MUZZLE
+ flags_attach_features = NONE
+ accuracy_mod = 0.15
+ scatter_mod = -3
+
+/obj/item/attachable/autosniperbarrel
+ name = "auto sniper barrel"
+ icon_state = "t81barrel"
+ desc = "A heavy barrel. CANNOT BE REMOVED."
+ slot = ATTACHMENT_SLOT_UNDER
+ flags_attach_features = NONE
+ pixel_shift_x = 7
+ pixel_shift_y = 14
+ accuracy_mod = 0
+ scatter_mod = -1
+
+/obj/item/attachable/smartbarrel
+ name = "smartgun barrel"
+ icon_state = "smartbarrel"
+ desc = "A heavy rotating barrel. CANNOT BE REMOVED."
+ slot = ATTACHMENT_SLOT_MUZZLE
+ flags_attach_features = NONE
+
+/obj/item/attachable/focuslens
+ name = "M43 focused lens"
+ desc = "Directs the beam into one specialized lens, allowing the lasgun to use the deadly focused bolts on overcharge, making it more like a high damage sniper."
+ slot = ATTACHMENT_SLOT_MUZZLE
+ icon_state = "focus"
+ pixel_shift_x = 17
+ pixel_shift_y = 13
+ ammo_mod = /datum/ammo/energy/lasgun/M43/overcharge
+ damage_mod = -0.15
+
+/obj/item/attachable/widelens
+ name = "M43 wide lens"
+ desc = "Splits the lens into three, allowing the lasgun to use a deadly close-range blast on overcharge akin to a traditional pellet based shotgun shot."
+ slot = ATTACHMENT_SLOT_MUZZLE
+ icon_state = "wide"
+ pixel_shift_x = 18
+ pixel_shift_y = 15
+ ammo_mod = /datum/ammo/energy/lasgun/M43/blast
+ damage_mod = -0.15
+
+/obj/item/attachable/heatlens
+ name = "M43 heat lens"
+ desc = "Changes the intensity and frequency of the laser. This makes your target be set on fire at a cost of upfront damage and penetration."
+ slot = ATTACHMENT_SLOT_MUZZLE
+ icon_state = "heat"
+ pixel_shift_x = 18
+ pixel_shift_y = 16
+ ammo_mod = /datum/ammo/energy/lasgun/M43/heat
+ damage_mod = -0.15
+
+/obj/item/attachable/efflens
+ name = "M43 efficient lens"
+ desc = "Makes the lens smaller and lighter to use, allowing the lasgun to use its energy much more efficiently. \nDecreases energy output of the lasgun."
+ slot = ATTACHMENT_SLOT_MUZZLE
+ icon_state = "efficient"
+ pixel_shift_x = 18
+ pixel_shift_y = 14
+ charge_mod = -5
+
+/obj/item/attachable/sx16barrel
+ name = "SX-16 barrel"
+ desc = "The standard barrel on the SX-16. CANNOT BE REMOVED."
+ slot = ATTACHMENT_SLOT_MUZZLE
+ icon_state = "sx16barrel"
+ flags_attach_features = NONE
+
+/obj/item/attachable/pulselens
+ name = "M43 pulse lens"
+ desc = "Agitates the lens, allowing the lasgun to discharge at a rapid rate. \nAllows the weapon to be fired automatically."
+ slot = ATTACHMENT_SLOT_MUZZLE
+ icon_state = "pulse"
+ pixel_shift_x = 18
+ pixel_shift_y = 15
+ damage_mod = -0.15
+ gun_firemode_list_mod = list(GUN_FIREMODE_AUTOMATIC)
+
+/obj/item/attachable/sgbarrel
+ name = "SG-29 barrel"
+ icon_state = "sg29barrel"
+ desc = "A heavy barrel. CANNOT BE REMOVED."
+ slot = ATTACHMENT_SLOT_MUZZLE
+ flags_attach_features = NONE
+
+/obj/item/attachable/t500barrel
+ name = "R-500 extended barrel"
+ desc = "Cool barrel for cool revolver"
+ slot = ATTACHMENT_SLOT_MUZZLE
+ delay_mod = -0.4 SECONDS
+ icon = 'icons/Marine/attachments_64.dmi'
+ icon_state = "barrel"
+ attach_shell_speed_mod = 1
+ accuracy_mod = 0.15
+ accuracy_unwielded_mod = 0.1
+ scatter_mod = -3
+ scatter_unwielded_mod = 3
+ recoil_unwielded_mod = 1
+ size_mod = 1
+ pixel_shift_x = 0
+ pixel_shift_y = 0
+
+/obj/item/attachable/t500barrelshort
+ name = "R-500 compensator"
+ desc = "Cool compensator for cool revolver"
+ slot = ATTACHMENT_SLOT_MUZZLE
+ delay_mod = -0.2 SECONDS
+ icon = 'icons/Marine/attachments_64.dmi'
+ icon_state = "shortbarrel"
+ scatter_mod = -2
+ recoil_mod = -0.5
+ scatter_unwielded_mod = -5
+ recoil_unwielded_mod = -1
+ accuracy_unwielded_mod = 0.15
+ size_mod = 0.5
+ pixel_shift_x = 0
+ pixel_shift_y = 0
diff --git a/code/modules/projectiles/attachables/rail.dm b/code/modules/projectiles/attachables/rail.dm
new file mode 100644
index 00000000000..311b64fae5c
--- /dev/null
+++ b/code/modules/projectiles/attachables/rail.dm
@@ -0,0 +1,327 @@
+/obj/item/attachable/reddot
+ name = "red-dot sight"
+ desc = "A red-dot sight for short to medium range. Does not have a zoom feature, but does increase weapon accuracy and fire rate while aiming by a good amount. \nNo drawbacks."
+ icon_state = "reddot"
+ slot = ATTACHMENT_SLOT_RAIL
+ accuracy_mod = 0.15
+ accuracy_unwielded_mod = 0.1
+ aim_mode_delay_mod = -0.5
+ variants_by_parent_type = list(/obj/item/weapon/gun/rifle/som = "", /obj/item/weapon/gun/shotgun/som = "")
+
+/obj/item/attachable/m16sight
+ name = "M16 iron sights"
+ desc = "The iconic carry-handle iron sights for the m16. Usually removed once the user finds something worthwhile to attach to the rail."
+ icon_state = "m16sight"
+ slot = ATTACHMENT_SLOT_RAIL
+ accuracy_mod = 0.1
+ accuracy_unwielded_mod = 0.05
+ movement_acc_penalty_mod = -0.1
+
+/obj/item/attachable/flashlight
+ name = "rail flashlight"
+ desc = "A simple flashlight used for mounting on a firearm. \nHas no drawbacks, but isn't particuraly useful outside of providing a light source."
+ icon_state = "flashlight"
+ light_mod = 6
+ light_system = MOVABLE_LIGHT
+ slot = ATTACHMENT_SLOT_RAIL
+ flags_attach_features = ATTACH_REMOVABLE|ATTACH_ACTIVATION
+ attachment_action_type = /datum/action/item_action/toggle
+ activation_sound = 'sound/items/flashlight.ogg'
+
+/obj/item/attachable/flashlight/activate(mob/living/user, turn_off)
+ turn_light(user, turn_off ? !turn_off : !light_on)
+
+/obj/item/attachable/flashlight/turn_light(mob/user, toggle_on, cooldown, sparks, forced, light_again)
+ . = ..()
+
+ if(. != CHECKS_PASSED)
+ return
+
+ if(ismob(master_gun.loc) && !user)
+ user = master_gun.loc
+
+ if(!toggle_on && light_on)
+ icon_state = initial(icon_state)
+ light_on = FALSE
+ master_gun.set_light_range(master_gun.light_range - light_mod)
+ master_gun.set_light_power(master_gun.light_power - (light_mod * 0.5))
+ if(master_gun.light_range <= 0) //does the gun have another light source
+ master_gun.set_light_on(FALSE)
+ REMOVE_TRAIT(master_gun, TRAIT_GUN_FLASHLIGHT_ON, GUN_TRAIT)
+ else if(toggle_on & !light_on)
+ icon_state = initial(icon_state) +"_on"
+ light_on = TRUE
+ master_gun.set_light_range(master_gun.light_range + light_mod)
+ master_gun.set_light_power(master_gun.light_power + (light_mod * 0.5))
+ if(!HAS_TRAIT(master_gun, TRAIT_GUN_FLASHLIGHT_ON))
+ master_gun.set_light_on(TRUE)
+ ADD_TRAIT(master_gun, TRAIT_GUN_FLASHLIGHT_ON, GUN_TRAIT)
+ else
+ return
+
+ for(var/X in master_gun.actions)
+ var/datum/action/A = X
+ A.update_button_icon()
+
+ update_icon()
+
+/obj/item/attachable/flashlight/attackby(obj/item/I, mob/user, params)
+ . = ..()
+
+ if(istype(I,/obj/item/tool/screwdriver))
+ to_chat(user, span_notice("You modify the rail flashlight back into a normal flashlight."))
+ if(loc == user)
+ user.temporarilyRemoveItemFromInventory(src)
+ var/obj/item/flashlight/F = new(user)
+ user.put_in_hands(F) //This proc tries right, left, then drops it all-in-one.
+ qdel(src) //Delete da old flashlight
+
+/obj/item/attachable/flashlight/under
+ name = "underbarreled flashlight"
+ desc = "A simple flashlight used for mounting on a firearm. \nHas no drawbacks, but isn't particuraly useful outside of providing a light source."
+ icon_state = "uflashlight"
+ slot = ATTACHMENT_SLOT_UNDER
+ flags_attach_features = ATTACH_REMOVABLE|ATTACH_ACTIVATION
+
+/obj/item/attachable/quickfire
+ name = "quickfire adapter"
+ desc = "An enhanced and upgraded autoloading mechanism to fire rounds more quickly. \nHowever, it also reduces accuracy and the number of bullets fired on burst."
+ slot = ATTACHMENT_SLOT_RAIL
+ icon_state = "autoloader"
+ accuracy_mod = -0.10
+ delay_mod = -0.125 SECONDS
+ burst_mod = -1
+ accuracy_unwielded_mod = -0.15
+
+/obj/item/attachable/magnetic_harness
+ name = "magnetic harness"
+ desc = "A magnetically attached harness kit that attaches to the rail mount of a weapon. When dropped, the weapon will sling to a TGMC armor."
+ icon_state = "magnetic"
+ slot = ATTACHMENT_SLOT_RAIL
+ pixel_shift_x = 13
+ ///Handles the harness functionality, created when attached to a gun and removed on detach
+ var/datum/component/reequip_component
+
+/obj/item/attachable/magnetic_harness/on_attach(attaching_item, mob/user)
+ . = ..()
+ if(!master_gun)
+ return
+ reequip_component = master_gun.AddComponent(/datum/component/reequip, list(SLOT_S_STORE, SLOT_BACK))
+
+/obj/item/attachable/magnetic_harness/on_detach(attaching_item, mob/user)
+ . = ..()
+ if(master_gun)
+ return
+ QDEL_NULL(reequip_component)
+
+/obj/item/attachable/buildasentry
+ name = "\improper Build-A-Sentry Attachment System"
+ icon = 'icons/Marine/sentry.dmi'
+ icon_state = "build_a_sentry_attachment"
+ desc = "The Build-A-Sentry is the latest design in cheap, automated, defense. Simple attach it to the rail of a gun and deploy. Its that easy!"
+ slot = ATTACHMENT_SLOT_RAIL
+ size_mod = 1
+ pixel_shift_x = 10
+ pixel_shift_y = 18
+ ///Deploy time for the build-a-sentry
+ var/deploy_time = 2 SECONDS
+ ///Undeploy tim for the build-a-sentry
+ var/undeploy_time = 2 SECONDS
+
+/obj/item/attachable/buildasentry/can_attach(obj/item/attaching_to, mob/attacher)
+ if(!isgun(attaching_to))
+ return FALSE
+ var/obj/item/weapon/gun/attaching_gun = attaching_to
+ if(ispath(attaching_gun.deployable_item, /obj/machinery/deployable/mounted/sentry))
+ to_chat(attacher, span_warning("[attaching_gun] is already a sentry!"))
+ return FALSE
+ return ..()
+
+/obj/item/attachable/buildasentry/on_attach(attaching_item, mob/user)
+ . = ..()
+ ENABLE_BITFIELD(master_gun.flags_item, IS_DEPLOYABLE)
+ master_gun.deployable_item = /obj/machinery/deployable/mounted/sentry/buildasentry
+ master_gun.ignored_terrains = list(
+ /obj/machinery/deployable/mounted,
+ /obj/machinery/miner,
+ )
+ if(master_gun.ammo_datum_type && CHECK_BITFIELD(initial(master_gun.ammo_datum_type.flags_ammo_behavior), AMMO_ENERGY) || istype(master_gun, /obj/item/weapon/gun/energy)) //If the guns ammo is energy, the sentry will shoot at things past windows.
+ master_gun.ignored_terrains += list(
+ /obj/structure/window,
+ /obj/structure/window/reinforced,
+ /obj/machinery/door/window,
+ /obj/structure/window/framed,
+ /obj/structure/window/framed/colony,
+ /obj/structure/window/framed/mainship,
+ /obj/structure/window/framed/prison,
+ )
+ master_gun.turret_flags |= TURRET_HAS_CAMERA|TURRET_SAFETY|TURRET_ALERTS
+ master_gun.AddComponent(/datum/component/deployable_item, master_gun.deployable_item, deploy_time, undeploy_time)
+ update_icon()
+
+/obj/item/attachable/buildasentry/on_detach(detaching_item, mob/user)
+ . = ..()
+ var/obj/item/weapon/gun/detaching_gun = detaching_item
+ DISABLE_BITFIELD(detaching_gun.flags_item, IS_DEPLOYABLE)
+ qdel(detaching_gun.GetComponent(/datum/component/deployable_item))
+ detaching_gun.ignored_terrains = null
+ detaching_gun.deployable_item = null
+ detaching_gun.turret_flags &= ~(TURRET_HAS_CAMERA|TURRET_SAFETY|TURRET_ALERTS)
+
+/obj/item/attachable/shoulder_mount
+ name = "experimental shoulder attachment point"
+ desc = "A brand new advance in combat technology. This device, once attached to a firearm, will allow the firearm to be mounted onto any piece of modular armor. Once attached to the armor and activated, the gun will fire when the user chooses.\nOnce attached to the armor, right clicking the armor with an empty hand will select what click will fire the armor (middle, right, left). Right clicking with ammunition will reload the gun. Using the Unique Action keybind will perform the weapon's unique action only when the gun is active."
+ icon = 'icons/mob/modular/shoulder_gun.dmi'
+ icon_state = "shoulder_gun"
+ slot = ATTACHMENT_SLOT_RAIL
+ pixel_shift_x = 13
+ ///What click the gun will fire on.
+ var/fire_mode = "right"
+ ///Blacklist of item types not allowed to be in the users hand to fire the gun.
+ var/list/in_hand_items_blacklist = list(
+ /obj/item/weapon/gun,
+ /obj/item/weapon/shield,
+ )
+
+/obj/item/attachable/shoulder_mount/on_attach(attaching_item, mob/user)
+ . = ..()
+ var/obj/item/weapon/gun/attaching_gun = attaching_item
+ ENABLE_BITFIELD(flags_attach_features, ATTACH_BYPASS_ALLOWED_LIST|ATTACH_APPLY_ON_MOB)
+ attaching_gun.AddElement(/datum/element/attachment, ATTACHMENT_SLOT_MODULE, icon, null, null, null, null, 0, 0, flags_attach_features, attach_delay, detach_delay, attach_skill, attach_skill_upper_threshold, attach_sound, attachment_layer = COLLAR_LAYER)
+ RegisterSignal(attaching_gun, COMSIG_ATTACHMENT_ATTACHED, PROC_REF(handle_armor_attach))
+ RegisterSignal(attaching_gun, COMSIG_ATTACHMENT_DETACHED, PROC_REF(handle_armor_detach))
+
+/obj/item/attachable/shoulder_mount/on_detach(detaching_item, mob/user)
+ var/obj/item/weapon/gun/detaching_gun = detaching_item
+ detaching_gun.RemoveElement(/datum/element/attachment, ATTACHMENT_SLOT_MODULE, icon, null, null, null, null, 0, 0, flags_attach_features, attach_delay, detach_delay, attach_skill, attach_skill_upper_threshold, attach_sound, attachment_layer = COLLAR_LAYER)
+ DISABLE_BITFIELD(flags_attach_features, ATTACH_BYPASS_ALLOWED_LIST|ATTACH_APPLY_ON_MOB)
+ UnregisterSignal(detaching_gun, list(COMSIG_ATTACHMENT_ATTACHED, COMSIG_ATTACHMENT_DETACHED))
+ return ..()
+
+/obj/item/attachable/shoulder_mount/ui_action_click(mob/living/user, datum/action/item_action/action, obj/item/weapon/gun/G)
+ if(!istype(master_gun.loc, /obj/item/clothing/suit/modular) || master_gun.loc.loc != user)
+ return
+ activate(user)
+
+/obj/item/attachable/shoulder_mount/activate(mob/user, turn_off)
+ . = ..()
+ if(CHECK_BITFIELD(master_gun.flags_item, IS_DEPLOYED))
+ DISABLE_BITFIELD(master_gun.flags_item, IS_DEPLOYED)
+ UnregisterSignal(user, COMSIG_MOB_MOUSEDOWN)
+ master_gun.set_gun_user(null)
+ . = FALSE
+ else if(!turn_off)
+ ENABLE_BITFIELD(master_gun.flags_item, IS_DEPLOYED)
+ update_icon()
+ master_gun.set_gun_user(user)
+ RegisterSignal(user, COMSIG_MOB_MOUSEDOWN, PROC_REF(handle_firing))
+ master_gun.RegisterSignal(user, COMSIG_MOB_MOUSEDRAG, TYPE_PROC_REF(/obj/item/weapon/gun, change_target))
+ . = TRUE
+ for(var/datum/action/item_action/toggle/action_to_update AS in actions)
+ action_to_update.set_toggle(.)
+ action_to_update.update_button_icon()
+
+///Handles the gun attaching to the armor.
+/obj/item/attachable/shoulder_mount/proc/handle_armor_attach(datum/source, attaching_item, mob/user)
+ SIGNAL_HANDLER
+ if(!istype(attaching_item, /obj/item/clothing/suit/modular))
+ return
+ master_gun.set_gun_user(null)
+ RegisterSignal(attaching_item, COMSIG_ITEM_EQUIPPED, PROC_REF(handle_activations))
+ RegisterSignal(attaching_item, COMSIG_ATOM_ATTACK_HAND_ALTERNATE, PROC_REF(switch_mode))
+ RegisterSignal(attaching_item, COMSIG_ATOM_ATTACKBY_ALTERNATE, PROC_REF(reload_gun))
+ RegisterSignal(master_gun, COMSIG_MOB_GUN_FIRED, PROC_REF(after_fire))
+ master_gun.base_gun_icon = master_gun.placed_overlay_iconstate
+ master_gun.update_icon()
+
+///Handles the gun detaching from the armor.
+/obj/item/attachable/shoulder_mount/proc/handle_armor_detach(datum/source, detaching_item, mob/user)
+ SIGNAL_HANDLER
+ if(!istype(detaching_item, /obj/item/clothing/suit/modular))
+ return
+ for(var/datum/action/action_to_delete AS in actions)
+ if(action_to_delete.target != src)
+ continue
+ QDEL_NULL(action_to_delete)
+ break
+ update_icon()
+ master_gun.base_gun_icon = initial(master_gun.icon_state)
+ master_gun.update_icon()
+ UnregisterSignal(detaching_item, list(COMSIG_ITEM_EQUIPPED, COMSIG_ATOM_ATTACK_HAND_ALTERNATE, COMSIG_ATOM_ATTACKBY_ALTERNATE))
+ UnregisterSignal(master_gun, COMSIG_MOB_GUN_FIRED)
+ UnregisterSignal(user, COMSIG_MOB_MOUSEDOWN)
+
+///Sets up the action.
+/obj/item/attachable/shoulder_mount/proc/handle_activations(datum/source, mob/equipper, slot)
+ if(!isliving(equipper))
+ return
+ if(slot != SLOT_WEAR_SUIT)
+ LAZYREMOVE(actions_types, /datum/action/item_action/toggle)
+ var/datum/action/item_action/toggle/old_action = locate(/datum/action/item_action/toggle) in actions
+ if(!old_action)
+ return
+ old_action.remove_action(equipper)
+ actions = null
+ else
+ LAZYADD(actions_types, /datum/action/item_action/toggle)
+ var/datum/action/item_action/toggle/new_action = new(src)
+ new_action.give_action(equipper)
+
+///Performs the firing.
+/obj/item/attachable/shoulder_mount/proc/handle_firing(datum/source, atom/object, turf/location, control, params)
+ SIGNAL_HANDLER
+ var/list/modifiers = params2list(params)
+ if(!modifiers[fire_mode])
+ return
+ if(!istype(master_gun.loc, /obj/item/clothing/suit/modular) || master_gun.loc.loc != source)
+ return
+ if(source.Adjacent(object))
+ return
+ var/mob/living/user = master_gun.gun_user
+ if(user.incapacitated() || user.lying_angle || LAZYACCESS(user.do_actions, src) || !user.dextrous || (!CHECK_BITFIELD(master_gun.flags_gun_features, GUN_ALLOW_SYNTHETIC) && !CONFIG_GET(flag/allow_synthetic_gun_use) && issynth(user)))
+ return
+ var/active_hand = user.get_active_held_item()
+ var/inactive_hand = user.get_inactive_held_item()
+ for(var/item_blacklisted in in_hand_items_blacklist)
+ if(!istype(active_hand, item_blacklisted) && !istype(inactive_hand, item_blacklisted))
+ continue
+ to_chat(user, span_warning("[src] beeps. Guns or shields in your hands are interfering with its targetting. Aborting."))
+ return
+ master_gun.start_fire(source, object, location, control, null, TRUE)
+
+///Switches click fire modes.
+/obj/item/attachable/shoulder_mount/proc/switch_mode(datum/source, mob/living/user)
+ SIGNAL_HANDLER
+ switch(fire_mode)
+ if("right")
+ fire_mode = "middle"
+ to_chat(user, span_notice("[master_gun] will now fire on a 'middle click'."))
+ if("middle")
+ fire_mode = "left"
+ to_chat(user, span_notice("[master_gun] will now fire on a 'left click'."))
+ if("left")
+ fire_mode = "right"
+ to_chat(user, span_notice("[master_gun] will now fire on a 'right click'."))
+
+///Reloads the gun
+/obj/item/attachable/shoulder_mount/proc/reload_gun(datum/source, obj/item/attacking_item, mob/living/user)
+ SIGNAL_HANDLER
+ INVOKE_ASYNC(master_gun, TYPE_PROC_REF(/obj/item/weapon/gun, reload), attacking_item, user)
+
+///Performs the unique action after firing and checks to see if the user is still able to fire.
+/obj/item/attachable/shoulder_mount/proc/after_fire(datum/source, atom/target, obj/item/weapon/gun/fired_gun)
+ SIGNAL_HANDLER
+ if(CHECK_BITFIELD(master_gun.reciever_flags, AMMO_RECIEVER_REQUIRES_UNIQUE_ACTION))
+ INVOKE_ASYNC(master_gun, TYPE_PROC_REF(/obj/item/weapon/gun, do_unique_action), master_gun.gun_user)
+ var/mob/living/user = master_gun.gun_user
+ var/active_hand = user.get_active_held_item()
+ var/inactive_hand = user.get_inactive_held_item()
+ for(var/item_blacklisted in in_hand_items_blacklist)
+ if(!istype(active_hand, item_blacklisted) && !istype(inactive_hand, item_blacklisted))
+ continue
+ to_chat(user, span_warning("[src] beeps. Guns or shields in your hands are interfering with its targetting. Stopping fire."))
+ master_gun.stop_fire()
+ return
+ if(!user.incapacitated() && !user.lying_angle && !LAZYACCESS(user.do_actions, src) && user.dextrous && (CHECK_BITFIELD(master_gun.flags_gun_features, GUN_ALLOW_SYNTHETIC) || CONFIG_GET(flag/allow_synthetic_gun_use) || !issynth(user)))
+ return
+ master_gun.stop_fire()
diff --git a/code/modules/projectiles/attachables/scope.dm b/code/modules/projectiles/attachables/scope.dm
new file mode 100644
index 00000000000..91b36b13c5e
--- /dev/null
+++ b/code/modules/projectiles/attachables/scope.dm
@@ -0,0 +1,239 @@
+/obj/item/attachable/scope
+ name = "rail scope"
+ icon_state = "sniperscope"
+ desc = "A rail mounted zoom sight scope. Allows zoom by activating the attachment."
+ slot = ATTACHMENT_SLOT_RAIL
+ aim_speed_mod = 0.5 //Extra slowdown when aiming
+ wield_delay_mod = 0.4 SECONDS
+ scoped_accuracy_mod = SCOPE_RAIL //accuracy mod of 0.4 when scoped
+ flags_attach_features = ATTACH_REMOVABLE|ATTACH_ACTIVATION
+ attachment_action_type = /datum/action/item_action/toggle
+ scope_zoom_mod = TRUE // codex
+ accuracy_unwielded_mod = -0.05
+ zoom_tile_offset = 11
+ zoom_viewsize = 10
+ zoom_allow_movement = TRUE
+ ///how much slowdown the scope gives when zoomed. You want this to be slowdown you want minus aim_speed_mod
+ var/zoom_slowdown = 1
+ /// scope zoom delay, delay before you can aim.
+ var/scope_delay = 0
+ ///boolean as to whether a scope can apply nightvision
+ var/has_nightvision = FALSE
+ ///boolean as to whether the attachment is currently giving nightvision
+ var/active_nightvision = FALSE
+ ///True if the scope is supposed to reactiveate when a deployed gun is turned.
+ var/deployed_scope_rezoom = FALSE
+
+/obj/item/attachable/scope/marine
+ name = "T-47 rail scope"
+ desc = "A marine standard mounted zoom sight scope. Allows zoom by activating the attachment."
+ icon_state = "marinescope"
+
+/obj/item/attachable/scope/nightvision
+ name = "T-46 Night vision scope"
+ icon_state = "nvscope"
+ desc = "A rail-mounted night vision scope developed by Roh-Easy industries for the TGMC. Allows zoom by activating the attachment."
+ has_nightvision = TRUE
+
+/obj/item/attachable/scope/optical
+ name = "T-49 Optical imaging scope"
+ icon_state = "imagerscope"
+ desc = "A rail-mounted scope designed for the AR-55 and GL-54. Features low light optical imaging capabilities and assists with precision aiming. Allows zoom by activating the attachment."
+ has_nightvision = TRUE
+ aim_speed_mod = 0.3
+ wield_delay_mod = 0.2 SECONDS
+ zoom_tile_offset = 7
+ zoom_viewsize = 5 //RU TGMC EDIT
+ add_aim_mode = TRUE
+
+/obj/item/attachable/scope/mosin
+ name = "Mosin nagant rail scope"
+ icon_state = "mosinscope"
+ desc = "A Mosin specific mounted zoom sight scope. Allows zoom by activating the attachment."
+
+/obj/item/attachable/scope/standard_magnum
+ name = "R-76 rail scope"
+ desc = "A custom rail mounted zoom sight scope designed specifically for the R-76 Magnum. Allows zoom by activating the attachment."
+ icon = 'icons/Marine/attachments_64.dmi'
+ icon_state = "t76scope"
+
+/obj/item/attachable/scope/unremovable
+ flags_attach_features = ATTACH_ACTIVATION
+
+/obj/item/attachable/scope/unremovable/flaregun
+ name = "long range ironsights"
+ desc = "An unremovable set of long range ironsights for a flaregun."
+ aim_speed_mod = 0
+ wield_delay_mod = 0
+ zoom_tile_offset = 5
+ zoom_viewsize = 0
+ scoped_accuracy_mod = SCOPE_RAIL_MINI
+ zoom_slowdown = 0.50
+
+/obj/item/attachable/scope/unremovable/tl127
+ name = "T-45 rail scope"
+ icon_state = "tl127_scope"
+ aim_speed_mod = 0
+ wield_delay_mod = 0
+ desc = "A rail mounted zoom sight scope specialized for the SR-127 sniper rifle. Allows zoom by activating the attachment."
+
+/obj/item/attachable/scope/unremovable/heavymachinegun
+ name = "HMG-08 long range ironsights"
+ desc = "An unremovable set of long range ironsights for an HMG-08 machinegun."
+ icon_state = "sniperscope_invisible"
+ zoom_viewsize = 0
+ zoom_tile_offset = 5
+
+/obj/item/attachable/scope/unremovable/mmg
+ name = "MG-27 rail scope"
+ icon_state = "miniscope"
+ desc = "A small rail mounted zoom sight scope. Allows zoom by activating the attachment."
+ wield_delay_mod = 0.2 SECONDS
+ aim_speed_mod = 0.2
+ scoped_accuracy_mod = SCOPE_RAIL_MINI
+ zoom_slowdown = 0.3
+ zoom_tile_offset = 5
+ zoom_viewsize = 0
+
+/obj/item/attachable/scope/unremovable/standard_atgun
+ name = "AT-36 long range scope"
+ desc = "An unremovable set of long range scopes, very complex to properly range. Requires time to aim.."
+ icon_state = "sniperscope_invisible"
+ scope_delay = 2 SECONDS
+ zoom_tile_offset = 7
+
+/obj/item/attachable/scope/unremovable/tl102
+ name = "HSG-102 smart sight"
+ desc = "An unremovable smart sight built for use with the tl102, it does nearly all the aiming work for the gun's integrated IFF systems."
+ icon_state = "sniperscope_invisible"
+ zoom_viewsize = 0
+ zoom_tile_offset = 5
+ deployed_scope_rezoom = TRUE
+
+//all mounted guns with a nest use this
+/obj/item/attachable/scope/unremovable/tl102/nest
+ scope_delay = 2 SECONDS
+ zoom_tile_offset = 7
+ zoom_viewsize = 5 //RU TGMC EDIT
+ deployed_scope_rezoom = FALSE
+
+/obj/item/attachable/scope/activate(mob/living/carbon/user, turn_off)
+ if(turn_off)
+ if(SEND_SIGNAL(user, COMSIG_ITEM_ZOOM) & COMSIG_ITEM_ALREADY_ZOOMED)
+ zoom(user)
+ return TRUE
+
+ if(!(master_gun.flags_item & WIELDED) && !CHECK_BITFIELD(master_gun.flags_item, IS_DEPLOYED))
+ if(user)
+ to_chat(user, span_warning("You must hold [master_gun] with two hands to use [src]."))
+ return FALSE
+ if(CHECK_BITFIELD(master_gun.flags_item, IS_DEPLOYED) && user.dir != master_gun.loc.dir)
+ user.setDir(master_gun.loc.dir)
+ if(!do_after(user, scope_delay, NONE, src, BUSY_ICON_BAR))
+ return FALSE
+ zoom(user)
+ update_icon()
+ return TRUE
+
+/obj/item/attachable/scope/zoom_item_turnoff(datum/source, mob/living/carbon/user)
+ if(ismob(source))
+ INVOKE_ASYNC(src, PROC_REF(activate), source, TRUE)
+ else
+ INVOKE_ASYNC(src, PROC_REF(activate), user, TRUE)
+
+/obj/item/attachable/scope/onzoom(mob/living/user)
+ if(zoom_allow_movement)
+ user.add_movespeed_modifier(MOVESPEED_ID_SCOPE_SLOWDOWN, TRUE, 0, NONE, TRUE, zoom_slowdown)
+ RegisterSignal(user, COMSIG_CARBON_SWAPPED_HANDS, PROC_REF(zoom_item_turnoff))
+ else
+ RegisterSignals(user, list(COMSIG_MOVABLE_MOVED, COMSIG_CARBON_SWAPPED_HANDS), PROC_REF(zoom_item_turnoff))
+ if(!CHECK_BITFIELD(master_gun.flags_item, IS_DEPLOYED))
+ RegisterSignal(user, COMSIG_MOB_FACE_DIR, PROC_REF(change_zoom_offset))
+ RegisterSignals(master_gun, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_UNWIELD, COMSIG_ITEM_DROPPED), PROC_REF(zoom_item_turnoff))
+ master_gun.accuracy_mult += scoped_accuracy_mod
+ if(has_nightvision)
+ update_remote_sight(user)
+ user.reset_perspective(src)
+ active_nightvision = TRUE
+
+/obj/item/attachable/scope/onunzoom(mob/living/user)
+ if(zoom_allow_movement)
+ user.remove_movespeed_modifier(MOVESPEED_ID_SCOPE_SLOWDOWN)
+ UnregisterSignal(user, list(COMSIG_CARBON_SWAPPED_HANDS, COMSIG_MOB_FACE_DIR))
+ else
+ UnregisterSignal(user, list(COMSIG_MOVABLE_MOVED, COMSIG_CARBON_SWAPPED_HANDS, COMSIG_MOB_FACE_DIR))
+ UnregisterSignal(master_gun, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_UNWIELD, COMSIG_ITEM_DROPPED))
+ master_gun.accuracy_mult -= scoped_accuracy_mod
+ if(has_nightvision)
+ user.update_sight()
+ user.reset_perspective(user)
+ active_nightvision = FALSE
+
+/obj/item/attachable/scope/update_remote_sight(mob/living/user)
+ . = ..()
+ user.see_in_dark = 32
+ user.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
+ user.sync_lighting_plane_alpha()
+ return TRUE
+
+/obj/item/attachable/scope/zoom(mob/living/user, tileoffset, viewsize)
+ . = ..()
+ //Makes the gun zoom align with the attachment, used for projectile procs
+ if(zoom)
+ master_gun.zoom = TRUE
+ else
+ master_gun.zoom = FALSE
+
+/obj/item/attachable/scope/optical/update_remote_sight(mob/living/user)
+ . = ..()
+ user.see_in_dark = 2
+ return TRUE
+
+/obj/item/attachable/scope/unremovable/laser_sniper_scope
+ name = "Terra Experimental laser sniper rifle rail scope"
+ desc = "A marine standard mounted zoom sight scope made for the Terra Experimental laser sniper rifle otherwise known as TE-S abbreviated, allows zoom by activating the attachment. Use F12 if your HUD doesn't come back."
+ icon = 'icons/Marine/marine-weapons.dmi'
+ icon_state = "tes"
+
+/obj/item/attachable/scope/mini
+ name = "mini rail scope"
+ icon_state = "miniscope"
+ desc = "A small rail mounted zoom sight scope. Allows zoom by activating the attachment."
+ slot = ATTACHMENT_SLOT_RAIL
+ wield_delay_mod = 0.2 SECONDS
+ accuracy_unwielded_mod = -0.05
+ aim_speed_mod = 0.2
+ scoped_accuracy_mod = SCOPE_RAIL_MINI
+ scope_zoom_mod = TRUE
+ has_nightvision = FALSE
+ zoom_allow_movement = TRUE
+ zoom_slowdown = 0.3
+ zoom_tile_offset = 5
+ zoom_viewsize = 0
+ variants_by_parent_type = list(/obj/item/weapon/gun/rifle/som = "")
+
+/obj/item/attachable/scope/mini/tx11
+ name = "AR-11 mini rail scope"
+ icon_state = "tx11scope"
+
+/obj/item/attachable/scope/antimaterial
+ name = "antimaterial rail scope"
+ desc = "A rail mounted zoom sight scope specialized for the antimaterial Sniper Rifle . Allows zoom by activating the attachment. Can activate its targeting laser while zoomed to take aim for increased damage and penetration."
+ icon_state = "antimat"
+ scoped_accuracy_mod = SCOPE_RAIL_SNIPER
+ has_nightvision = TRUE
+ zoom_allow_movement = FALSE
+ flags_attach_features = ATTACH_ACTIVATION|ATTACH_REMOVABLE
+ pixel_shift_x = 0
+ pixel_shift_y = 17
+
+/obj/item/attachable/scope/slavic
+ icon_state = "slavicscope"
+
+/obj/item/attachable/scope/pmc
+ icon_state = "pmcscope"
+ flags_attach_features = ATTACH_ACTIVATION
+
+/obj/item/attachable/scope/mini/dmr
+ name = "DMR-37 mini rail scope"
+ icon_state = "t37"
diff --git a/code/modules/projectiles/attachables/stock.dm b/code/modules/projectiles/attachables/stock.dm
new file mode 100644
index 00000000000..b9d12e8ddfa
--- /dev/null
+++ b/code/modules/projectiles/attachables/stock.dm
@@ -0,0 +1,247 @@
+/obj/item/attachable/stock //Generic stock parent and related things.
+ name = "default stock"
+ desc = "Default parent object, not meant for use."
+ slot = ATTACHMENT_SLOT_STOCK
+ flags_attach_features = NONE //most stocks are not removable
+ size_mod = 2
+ pixel_shift_x = 30
+ pixel_shift_y = 14
+
+/obj/item/attachable/stock/mosin
+ name = "mosin wooden stock"
+ desc = "A non-standard long wooden stock for Slavic firearms."
+ icon_state = "mosinstock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/ppsh
+ name = "PPSh-17b submachinegun wooden stock"
+ desc = "A long wooden stock for a PPSh-17b submachinegun"
+ icon_state = "ppshstock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/t27
+ name = "MG-27 Body"
+ desc = "A stock for a MG-27 MMG."
+ icon = 'icons/Marine/marine-mmg.dmi'
+ icon_state = "t27body"
+ pixel_shift_x = 15
+ pixel_shift_y = 0
+
+/obj/item/attachable/stock/pal12
+ name = "Paladin-12 pump shotgun stock"
+ desc = "A standard light stock for the Paladin-12 shotgun."
+ icon_state = "pal12stock"
+
+/obj/item/attachable/stock/mpi_km
+ name = "MPi-KM wooden stock"
+ desc = "A metallic stock with a wooden paint coating, made to fit the MPi-KM."
+ icon_state = "ak47stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/mpi_km/black
+ name = "MPi-KM polymer stock"
+ desc = "A black polymer stock, made to fit the MPi-KM."
+ icon_state = "ak47stock_black"
+
+/obj/item/attachable/stock/lmg_d
+ name = "lMG-D wooden stock"
+ desc = "A metallic stock with a wooden paint coating, made to fit lMG-D."
+ icon_state = "ak47stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/tx15
+ name = "\improper SH-15 stock"
+ desc = "The standard stock for the SH-15. Cannot be removed."
+ icon_state = "tx15stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/sgstock
+ name = "SG-29 stock"
+ desc = "A standard machinegun stock."
+ icon_state = "sg29stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/strstock
+ name = "SG-62 stock"
+ desc = "A standard rifle stock."
+ icon_state = "sg62stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/lasgun
+ name = "\improper M43 Sunfury lasgun stock"
+ desc = "The standard stock for the M43 Sunfury lasgun."
+ icon_state = "laserstock"
+ pixel_shift_x = 41
+ pixel_shift_y = 10
+
+/obj/item/attachable/stock/lasgun/practice
+ name = "\improper M43-P Sunfury lasgun stock"
+ desc = "The standard stock for the M43-P Sunfury lasgun, seems the stock is made out of plastic."
+ icon_state = "laserstock"
+ pixel_shift_x = 41
+ pixel_shift_y = 10
+
+/obj/item/attachable/stock/tl127stock
+ name = "\improper SR-127 stock"
+ desc = "A irremovable SR-127 sniper rifle stock."
+ icon_state = "tl127stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/garand
+ name = "\improper C1 stock"
+ desc = "A irremovable C1 stock."
+ icon_state = "garandstock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/trenchgun
+ name = "\improper L-4043 stock"
+ desc = "A irremovable L-4043 stock."
+ icon_state = "trenchstock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/icc_pdw
+ name = "\improper L-40 stock"
+ desc = "A irremovable L-40 stock."
+ icon_state = "l40stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/icc_sharpshooter
+ name = "\improper L-1 stock"
+ desc = "A irremovable L-11 stock."
+ icon_state = "l11stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/clf_heavyrifle
+ name = "PTR-41/1785 body"
+ desc = "A stock for a PTR-41/1785 A-MR."
+ icon = 'icons/Marine/clf_heavyrifle.dmi'
+ icon_state = "ptrs_stock"
+ pixel_shift_x = 15
+ pixel_shift_y = 0
+
+/obj/item/attachable/stock/dpm
+ name = "\improper DP-27 stock"
+ desc = "A irremovable DP stock."
+ icon_state = "dpstock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/t39stock
+ name = "\improper SH-39 stock"
+ desc = "A specialized stock for the SH-39."
+ icon_state = "t39stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+ size_mod = 1
+ flags_attach_features = ATTACH_REMOVABLE
+ wield_delay_mod = 0.2 SECONDS
+ accuracy_mod = 0.15
+ recoil_mod = -2
+ scatter_mod = -2
+
+/obj/item/attachable/stock/t60stock
+ name = "MG-60 stock"
+ desc = "A irremovable MG-60 general purpose machinegun stock."
+ icon_state = "t60stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/t70stock
+ name = "\improper GL-70 stock"
+ desc = "A irremovable GL-70 grenade launcher stock."
+ icon_state = "t70stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/t84stock
+ name = "\improper FL-84 stock"
+ desc = "A irremovable FL-84 flamer stock."
+ icon_state = "tl84stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/m41a
+ name = "PR-11 stock"
+ icon_state = "m41a"
+
+/obj/item/attachable/stock/tx11
+ name = "AR-11 stock"
+ icon_state = "tx11stock"
+
+/obj/item/attachable/stock/som_mg_stock
+ name = "\improper V-41 stock"
+ desc = "A irremovable V-41 machine gun stock."
+ icon_state = "v41stock"
+ pixel_shift_x = 0
+ pixel_shift_y = 0
+
+/obj/item/attachable/stock/t18stock
+ name = "\improper AR-18 stock"
+ desc = "A specialized stock for the AR-18."
+ icon_state = "t18stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/t12stock
+ name = "\improper AR-12 stock"
+ desc = "A specialized stock for the AR-12."
+ icon_state = "t12stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/t42stock
+ name = "\improper MG-42 stock"
+ desc = "A specialized stock for the MG-42."
+ icon_state = "t42stock"
+ pixel_shift_x = 32
+ pixel_shift_y = 13
+
+/obj/item/attachable/stock/t64stock
+ name = "\improper BR-64 stock"
+ desc = "A specialized stock for the BR-64."
+ icon_state = "t64stock"
+
+//You can remove the stock on the Magnum. So it has stats and is removeable.
+
+/obj/item/attachable/stock/t76
+ name = "T-76 magnum stock"
+ desc = "A R-76 magnum stock. Makes about all your handling better outside of making it harder to wield. Recommended to be kept on the R-76 at all times if you value your shoulder."
+ icon_state = "t76stock"
+ flags_attach_features = ATTACH_REMOVABLE
+ melee_mod = 5
+ scatter_mod = -1
+ size_mod = 2
+ aim_speed_mod = 0.05
+ recoil_mod = -2
+ pixel_shift_x = 30
+ pixel_shift_y = 14
+
+/obj/item/attachable/stock/t500stock
+ name = "R-500 stock"
+ desc = "Cool stock for cool revolver."
+ flags_attach_features = ATTACH_REMOVABLE
+ wield_delay_mod = 0.2 SECONDS
+ delay_mod = -0.4 SECONDS
+ icon = 'icons/Marine/attachments_64.dmi'
+ icon_state = "stock"
+ size_mod = 1
+ accuracy_mod = 0.15
+ recoil_mod = -1
+ recoil_unwielded_mod = 1
+ scatter_mod = -2
+ scatter_unwielded_mod = 5
+ melee_mod = 10
+ pixel_shift_x = 0
+ pixel_shift_y = 0
diff --git a/code/modules/projectiles/attachables/underbarrel.dm b/code/modules/projectiles/attachables/underbarrel.dm
new file mode 100644
index 00000000000..04558ec4879
--- /dev/null
+++ b/code/modules/projectiles/attachables/underbarrel.dm
@@ -0,0 +1,104 @@
+/obj/item/attachable/verticalgrip
+ name = "vertical grip"
+ desc = "A custom-built improved foregrip for better accuracy, moderately faster aimed movement speed, less recoil, and less scatter when wielded especially during burst fire. \nHowever, it also increases weapon size, slightly increases wield delay and makes unwielded fire more cumbersome."
+ icon_state = "verticalgrip"
+ wield_delay_mod = 0.2 SECONDS
+ size_mod = 1
+ slot = ATTACHMENT_SLOT_UNDER
+ pixel_shift_x = 20
+ accuracy_mod = 0.1
+ recoil_mod = -2
+ scatter_mod = -3
+ burst_scatter_mod = -1
+ accuracy_unwielded_mod = -0.05
+ scatter_unwielded_mod = 3
+ aim_speed_mod = -0.1
+ aim_mode_movement_mult = -0.2
+
+/obj/item/attachable/angledgrip
+ name = "angled grip"
+ desc = "A custom-built improved foregrip for less recoil, and faster wielding time. \nHowever, it also increases weapon size, and slightly hinders unwielded firing."
+ icon_state = "angledgrip"
+ wield_delay_mod = -0.3 SECONDS
+ size_mod = 1
+ slot = ATTACHMENT_SLOT_UNDER
+ pixel_shift_x = 20
+ recoil_mod = -1
+ scatter_mod = 2
+ accuracy_unwielded_mod = -0.1
+ scatter_unwielded_mod = 1
+
+/obj/item/attachable/gyro
+ name = "gyroscopic stabilizer"
+ desc = "A set of weights and balances to stabilize the weapon when burst firing or moving, especially while shooting one-handed. Greatly reduces movement penalties to accuracy. Significantly reduces burst scatter, recoil and general scatter. By increasing accuracy while moving, it let you move faster when taking aim."
+ icon_state = "gyro"
+ slot = ATTACHMENT_SLOT_UNDER
+ scatter_mod = -1
+ recoil_mod = -2
+ movement_acc_penalty_mod = -2
+ accuracy_unwielded_mod = 0.1
+ scatter_unwielded_mod = -2
+ recoil_unwielded_mod = -1
+ aim_mode_movement_mult = -0.5
+
+/obj/item/attachable/lasersight
+ name = "laser sight"
+ desc = "A laser sight placed under the barrel. Significantly increases one-handed accuracy and significantly reduces unwielded penalties to accuracy."
+ icon_state = "lasersight"
+ slot = ATTACHMENT_SLOT_UNDER
+ pixel_shift_x = 17
+ pixel_shift_y = 17
+ accuracy_mod = 0.1
+ accuracy_unwielded_mod = 0.15
+
+/obj/item/attachable/lace
+ name = "pistol lace"
+ desc = "A simple lace to wrap around your wrist."
+ icon_state = "lace"
+ slot = ATTACHMENT_SLOT_MUZZLE //so you cannot have this and RC at once aka balance
+ flags_attach_features = ATTACH_REMOVABLE|ATTACH_ACTIVATION
+ attachment_action_type = /datum/action/item_action/toggle
+
+/obj/item/attachable/lace/t500
+ name = "R-500 lace"
+ icon = 'icons/Marine/attachments_64.dmi'
+ slot = ATTACHMENT_SLOT_STOCK
+ pixel_shift_x = 0
+ pixel_shift_y = 0
+
+/obj/item/attachable/lace/activate(mob/living/user, turn_off)
+ if(lace_deployed)
+ REMOVE_TRAIT(master_gun, TRAIT_NODROP, PISTOL_LACE_TRAIT)
+ to_chat(user, span_notice("You feel the [src] loosen around your wrist!"))
+ playsound(user, 'sound/weapons/fistunclamp.ogg', 25, 1, 7)
+ icon_state = "lace"
+ else if(turn_off)
+ return
+ else
+ if(user.do_actions)
+ return
+ if(!do_after(user, 0.5 SECONDS, NONE, src, BUSY_ICON_BAR))
+ return
+ to_chat(user, span_notice("You deploy the [src]."))
+ ADD_TRAIT(master_gun, TRAIT_NODROP, PISTOL_LACE_TRAIT)
+ to_chat(user, span_warning("You feel the [src] shut around your wrist!"))
+ playsound(user, 'sound/weapons/fistclamp.ogg', 25, 1, 7)
+ icon_state = "lace-on"
+
+ lace_deployed = !lace_deployed
+
+ for(var/i in master_gun.actions)
+ var/datum/action/action_to_update = i
+ action_to_update.update_button_icon()
+
+ update_icon()
+ return TRUE
+
+/obj/item/attachable/burstfire_assembly
+ name = "burst fire assembly"
+ desc = "A mechanism re-assembly kit that allows for automatic fire, or more shots per burst if the weapon already has the ability. \nIncreases scatter and decreases accuracy."
+ icon_state = "rapidfire"
+ slot = ATTACHMENT_SLOT_UNDER
+ burst_mod = 2
+ burst_scatter_mod = 1
+ burst_accuracy_mod = -0.1
diff --git a/code/modules/projectiles/gun_attachables.dm b/code/modules/projectiles/gun_attachables.dm
deleted file mode 100644
index ab741a08336..00000000000
--- a/code/modules/projectiles/gun_attachables.dm
+++ /dev/null
@@ -1,1914 +0,0 @@
-
-/** Gun attachable items code. Lets you add various effects to firearms.
-
-Some attachables are hardcoded in the projectile firing system, like grenade launchers, flamethrowers.
-
-When you are adding new guns into the attachment list, or even old guns, make sure that said guns
-properly accept overlays. You can find the proper offsets in the individual gun dms, so make sure
-you set them right. It's a pain to go back to find which guns are set incorrectly.
-To summarize: rail attachments should go on top of the rail. For rifles, this usually means the middle of the gun.
-For handguns, this is usually toward the back of the gun. SMGs usually follow rifles.
-Muzzle attachments should connect to the barrel, not sit under or above it. The only exception is the bayonet.
-Underrail attachments should just fit snugly, that's about it. Stocks are pretty obvious.
-
-All attachment offsets are now in a list, including stocks. Guns that don't take attachments can keep the list null.
-~N
-
-Anything that isn't used as the gun fires should be a flat number, never a percentange. It screws with the calculations,
-and can mean that the order you attach something/detach something will matter in the final number. It's also completely
-inaccurate. Don't worry if force is ever negative, it won't runtime.
- */
-
-/obj/item/attachable
- name = "attachable item"
- desc = "It's an attachment. You should never see this."
- icon = 'icons/Marine/marine-weapons.dmi'
- icon_state = null
- item_state = null
-
- greyscale_config = null
- greyscale_colors = GUN_PALETTE_BLACK
- colorable_colors = GUN_PALETTE_LIST
-
- ///Determines the amount of pixels to move the icon state for the overlay. in the x direction
- var/pixel_shift_x = 16
- ///Determines the amount of pixels to move the icon state for the overlay. in the y direction
- var/pixel_shift_y = 16
-
- flags_atom = CONDUCT
- w_class = WEIGHT_CLASS_SMALL
- force = 1
- ///ATTACHMENT_SLOT_MUZZLE, ATTACHMENT_SLOT_RAIL, ATTACHMENT_SLOT_UNDER, ATTACHMENT_SLOT_STOCK the particular 'slot' the attachment can attach to. must always be a singular slot.
- var/slot = null
-
- ///Modifier to firing accuracy, works off a multiplier.
- var/accuracy_mod = 0
- ///Modifier to firing accuracy but for when scoped in, works off a multiplier.
- var/scoped_accuracy_mod = 0
- ///Modifier to firing accuracy but for when onehanded.
- var/accuracy_unwielded_mod = 0
- ///Modifer to the damage mult, works off a multiplier.
- var/damage_mod = 0
- ///Modifier to damage falloff, works off a multiplier.
- var/damage_falloff_mod = 0
- ///Flat number that adjusts the amount of mêlée force the weapon this is attached to has.
- var/melee_mod = 0
- ///Increases or decreases scatter chance.
- var/scatter_mod = 0
- ///Increases or decreases scatter chance but for onehanded firing.
- var/scatter_unwielded_mod = 0
- ///Maximum scatter
- var/max_scatter_mod = 0
- ///Maximum scatter when unwielded
- var/max_scatter_unwielded_mod = 0
- ///How much scatter decays every X seconds
- var/scatter_decay_mod = 0
- ///How much scatter decays every X seconds when wielded
- var/scatter_decay_unwielded_mod = 0
- ///How much scatter increases per shot
- var/scatter_increase_mod = 0
- ///How much scatter increases per shot when wielded
- var/scatter_increase_unwielded_mod = 0
- ///Minimum scatter
- var/min_scatter_mod = 0
- ///Minimum scatter when unwielded
- var/min_scatter_unwielded_mod = 0
- ///If positive, adds recoil, if negative, lowers it. Recoil can't go below 0.
- var/recoil_mod = 0
- ///If positive, adds recoil, if negative, lowers it. but for onehanded firing. Recoil can't go below 0.
- var/recoil_unwielded_mod = 0
- ///Additive to burst scatter modifier from burst fire, works off a multiplier.
- var/burst_scatter_mod = 0
- ///additive modifier to burst fire accuracy.
- var/burst_accuracy_mod = 0
- ///Adds silenced to weapon. changing its fire sound, muzzle flash, and volume. TRUE or FALSE
- var/silence_mod = FALSE
- ///Adds an x-brightness flashlight to the weapon, which can be toggled on and off.
- var/light_mod = 0
- ///Changes firing delay. Cannot go below 0.
- var/delay_mod = 0
- ///Changes burst firing delay. Cannot go below 0.
- var/burst_delay_mod = 0
- ///Changes amount of shots in a burst
- var/burst_mod = 0
- ///Increases the weight class.
- var/size_mod = 0
- ///Changes the slowdown amount when wielding a weapon by this value.
- var/aim_speed_mod = 0
- ///How long ADS takes (time before firing)
- var/wield_delay_mod = 0
- ///Changes the speed of projectiles fired
- var/attach_shell_speed_mod = 0
- ///Modifies accuracy/scatter penalty when firing onehanded while moving.
- var/movement_acc_penalty_mod = 0
- ///How long in deciseconds it takes to attach a weapon with level 1 firearms training. Default is 1.5 seconds.
- var/attach_delay = 1.5 SECONDS
- ///How long in deciseconds it takes to detach a weapon with level 1 firearms training. Default is 1.5 seconds.
- var/detach_delay = 1.5 SECONDS
- ///Changes aim mode movement delay multiplicatively
- var/aim_mode_movement_mult = 0
- ///Modifies projectile damage by a % when a marine gets passed, but not hit
- var/shot_marine_damage_falloff = 0
- ///Modifies aim mode fire rate debuff by a %
- var/aim_mode_delay_mod = 0
- ///adds aim mode to the gun
- var/add_aim_mode = FALSE
- ///the delay between shots, for attachments that fire stuff
- var/attachment_firing_delay = 0
-
- ///The specific sound played when activating this attachment.
- var/activation_sound = 'sound/machines/click.ogg'
-
- ///various yes no flags associated with attachments. See defines for these: [ATTACH_REMOVABLE]
- var/flags_attach_features = ATTACH_REMOVABLE
-
- ///only used by lace, denotes whether the lace is currently deployed
- var/lace_deployed = FALSE
-
-
- ///what ability to give the user when attached to a weapon they are holding.
- var/attachment_action_type
- ///used for the codex to denote if a weapon has the ability to zoom in or not.
- var/scope_zoom_mod = FALSE
-
- ///what ammo the gun could also fire, different lasers usually.
- var/ammo_mod = null
- ///how much charge difference it now costs to shoot. negative means more shots per mag.
- var/charge_mod = 0
- ///what firemodes this attachment allows/adds.
- var/gun_firemode_list_mod = null
-
- ///lazylist of attachment slot offsets for a gun.
- var/list/gun_attachment_offset_mod
-
- ///what gun this attachment is currently attached to, if any.
- var/obj/item/weapon/gun/master_gun
-
- ///Skill used to attach src to something.
- var/attach_skill = SKILL_FIREARMS
- ///Skill threshold where the time to attach is halved.
- var/attach_skill_upper_threshold = SKILL_FIREARMS_TRAINED
- ///Sound played on attach
- var/attach_sound = 'sound/machines/click.ogg'
-
- ///Replacement for initial icon that allows for the code to work with multiple variants
- var/base_icon
- ///Assoc list that uses the parents type as a key. type = "new_icon_state". This will change the icon state depending on what type the parent is. If the list is empty, or the parent type is not within, it will have no effect.
- var/list/variants_by_parent_type = list()
-
-/obj/item/attachable/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/attachment, slot, icon, PROC_REF(on_attach), PROC_REF(on_detach), PROC_REF(activate), PROC_REF(can_attach), pixel_shift_x, pixel_shift_y, flags_attach_features, attach_delay, detach_delay, attach_skill, attach_skill_upper_threshold, attach_sound)
-
-///Called when the attachment is attached to something. If it is a gun it will update the guns stats.
-/obj/item/attachable/proc/on_attach(attaching_item, mob/user)
-
- if(!istype(attaching_item, /obj/item/weapon/gun))
- return //Guns only
-
- master_gun = attaching_item
-
- apply_modifiers(attaching_item, user, TRUE)
-
- if(attachment_action_type)
- var/datum/action/action_to_update = new attachment_action_type(src, master_gun)
- if(isliving(master_gun.loc))
- var/mob/living/living_user = master_gun.loc
- if(master_gun == living_user.l_hand || master_gun == living_user.r_hand)
- action_to_update.give_action(living_user)
-
- //custom attachment icons for specific guns
- if(length(variants_by_parent_type))
- for(var/selection in variants_by_parent_type)
- if(istype(master_gun, selection))
- icon_state = variants_by_parent_type[selection]
-
- update_icon()
- if(!greyscale_colors || !greyscale_config)
- return
- RegisterSignal(master_gun, COMSIG_ITEM_SECONDARY_COLOR, PROC_REF(handle_color))
-
-///Sends a list of available colored attachments to be colored when the parent is right clicked with paint.
-/obj/item/attachable/proc/handle_color(datum/source, mob/user, list/obj/item/secondaries)
- SIGNAL_HANDLER
- secondaries += src
-
-///Called when the attachment is detached from something. If the thing is a gun, it returns its stats to what they were before being attached.
-/obj/item/attachable/proc/on_detach(detaching_item, mob/user)
- if(!isgun(detaching_item))
- return
-
- activate(user, TRUE)
-
- apply_modifiers(detaching_item, user, FALSE)
-
- for(var/datum/action/action_to_update AS in master_gun.actions)
- if(action_to_update.target != src)
- continue
- qdel(action_to_update)
- break
-
- master_gun = null
- icon_state = initial(icon_state)
- update_icon()
- if(!greyscale_config || !greyscale_colors)
- return
- UnregisterSignal(master_gun, COMSIG_ITEM_SECONDARY_COLOR)
-
-///Handles the modifiers to the parent gun
-/obj/item/attachable/proc/apply_modifiers(attaching_item, mob/user, attaching)
- if(attaching)
- master_gun.accuracy_mult += accuracy_mod
- master_gun.accuracy_mult_unwielded += accuracy_unwielded_mod
- master_gun.damage_mult += damage_mod
- master_gun.damage_falloff_mult += damage_falloff_mod
- master_gun.w_class += size_mod
- master_gun.scatter += scatter_mod
- master_gun.scatter_unwielded += scatter_unwielded_mod
- master_gun.max_scatter += max_scatter_mod
- master_gun.max_scatter_unwielded += max_scatter_unwielded_mod
- master_gun.scatter_decay += scatter_decay_mod
- master_gun.scatter_decay_unwielded += scatter_decay_unwielded_mod
- master_gun.scatter_increase += scatter_increase_mod
- master_gun.scatter_increase_unwielded += scatter_increase_unwielded_mod
- master_gun.min_scatter += min_scatter_mod
- master_gun.min_scatter_unwielded += min_scatter_unwielded_mod
- master_gun.aim_speed_modifier += initial(master_gun.aim_speed_modifier)*aim_mode_movement_mult
- master_gun.iff_marine_damage_falloff += shot_marine_damage_falloff
- master_gun.add_aim_mode_fire_delay(name, initial(master_gun.aim_fire_delay) * aim_mode_delay_mod)
- if(add_aim_mode)
- var/datum/action/item_action/aim_mode/A = new (master_gun)
- ///actually gives the user aim_mode if they're holding the gun
- if(user)
- A.give_action(user)
- if(delay_mod)
- master_gun.modify_fire_delay(delay_mod)
- if(burst_delay_mod)
- master_gun.modify_burst_delay(burst_delay_mod)
- if(burst_mod)
- master_gun.modify_burst_amount(burst_mod, user)
- master_gun.recoil += recoil_mod
- master_gun.recoil_unwielded += recoil_unwielded_mod
- master_gun.force += melee_mod
- master_gun.sharp += sharp
- master_gun.aim_slowdown += aim_speed_mod
- master_gun.wield_delay += wield_delay_mod
- master_gun.burst_scatter_mult += burst_scatter_mod
- master_gun.burst_accuracy_bonus += burst_accuracy_mod
- master_gun.movement_acc_penalty_mult += movement_acc_penalty_mod
- master_gun.shell_speed_mod += attach_shell_speed_mod
- master_gun.scope_zoom += scope_zoom_mod
- if(ammo_mod)
- master_gun.add_ammo_mod(ammo_mod)
- if(charge_mod)
- master_gun.charge_cost += charge_mod
- for(var/i in gun_firemode_list_mod)
- master_gun.add_firemode(i, user)
- master_gun.update_force_list() //This updates the gun to use proper force verbs.
-
- if(silence_mod)
- ADD_TRAIT(master_gun, TRAIT_GUN_SILENCED, GUN_TRAIT)
- master_gun.muzzle_flash = null
- //master_gun.fire_sound = "gun_silenced" //ORIGINAL
- master_gun.fire_sound = master_gun.silenced_sound
- else
- master_gun.accuracy_mult -= accuracy_mod
- master_gun.accuracy_mult_unwielded -= accuracy_unwielded_mod
- master_gun.damage_mult -= damage_mod
- master_gun.damage_falloff_mult -= damage_falloff_mod
- master_gun.w_class -= size_mod
- master_gun.scatter -= scatter_mod
- master_gun.scatter_unwielded -= scatter_unwielded_mod
- master_gun.max_scatter -= max_scatter_mod
- master_gun.max_scatter_unwielded -= max_scatter_unwielded_mod
- master_gun.scatter_decay -= scatter_decay_mod
- master_gun.scatter_decay_unwielded -= scatter_decay_unwielded_mod
- master_gun.scatter_increase -= scatter_increase_mod
- master_gun.scatter_increase_unwielded -= scatter_increase_unwielded_mod
- master_gun.min_scatter -= min_scatter_mod
- master_gun.min_scatter_unwielded -= min_scatter_unwielded_mod
- master_gun.aim_speed_modifier -= initial(master_gun.aim_speed_modifier)*aim_mode_movement_mult
- master_gun.iff_marine_damage_falloff -= shot_marine_damage_falloff
- master_gun.remove_aim_mode_fire_delay(name)
- if(add_aim_mode)
- var/datum/action/item_action/aim_mode/action_to_delete = locate() in master_gun.actions
- QDEL_NULL(action_to_delete)
- if(delay_mod)
- master_gun.modify_fire_delay(-delay_mod)
- if(burst_delay_mod)
- master_gun.modify_burst_delay(-burst_delay_mod)
- if(burst_mod)
- master_gun.modify_burst_amount(-burst_mod, user)
- master_gun.recoil -= recoil_mod
- master_gun.recoil_unwielded -= recoil_unwielded_mod
- master_gun.force -= melee_mod
- master_gun.sharp -= sharp
- master_gun.aim_slowdown -= aim_speed_mod
- master_gun.wield_delay -= wield_delay_mod
- master_gun.burst_scatter_mult -= burst_scatter_mod
- master_gun.burst_accuracy_bonus -= burst_accuracy_mod
- master_gun.movement_acc_penalty_mult -= movement_acc_penalty_mod
- master_gun.shell_speed_mod -= attach_shell_speed_mod
- master_gun.scope_zoom -= scope_zoom_mod
- if(ammo_mod)
- master_gun.remove_ammo_mod(ammo_mod)
- if(master_gun.charge_cost)
- master_gun.charge_cost -= charge_mod
- for(var/i in gun_firemode_list_mod)
- master_gun.remove_firemode(i, user)
-
- master_gun.update_force_list()
-
- if(silence_mod) //Built in silencers always come as an attach, so the gun can't be silenced right off the bat.
- REMOVE_TRAIT(master_gun, TRAIT_GUN_SILENCED, GUN_TRAIT)
- master_gun.muzzle_flash = initial(master_gun.muzzle_flash)
- master_gun.fire_sound = initial(master_gun.fire_sound)
-
-/obj/item/attachable/ui_action_click(mob/living/user, datum/action/item_action/action, obj/item/weapon/gun/G)
- if(G == user.get_active_held_item() || G == user.get_inactive_held_item() || CHECK_BITFIELD(G.flags_item, IS_DEPLOYED))
- if(activate(user)) //success
- playsound(user, activation_sound, 15, 1)
- else
- to_chat(user, span_warning("[G] must be in our hands to do this."))
-
-///Called when the attachment is activated.
-/obj/item/attachable/proc/activate(mob/user, turn_off) //This is for activating stuff like flamethrowers, or switching weapon modes, or flashlights.
- return TRUE
-
-///Called when the attachment is trying to be attached. If the attachment is allowed to go through, return TRUE.
-/obj/item/attachable/proc/can_attach(obj/item/attaching_to, mob/attacher)
- return TRUE
-
-
-/////////// Muzzle Attachments /////////////////////////////////
-
-/obj/item/attachable/suppressor
- name = "suppressor"
- desc = "A small tube with exhaust ports to expel noise and gas.\nDoes not completely silence a weapon, but does make it much quieter and a little more accurate and stable."
- icon_state = "suppressor"
- slot = ATTACHMENT_SLOT_MUZZLE
- silence_mod = TRUE
- pixel_shift_y = 16
- attach_shell_speed_mod = 0.5
- accuracy_mod = 0
- recoil_mod = 0
- scatter_mod = -2
- size_mod = 1
- recoil_unwielded_mod = 0
- scatter_unwielded_mod = 0
- damage_falloff_mod = 0
-
-/obj/item/attachable/suppressor/unremovable
- flags_attach_features = NONE
-
-
-/obj/item/attachable/suppressor/unremovable/invisible
- icon_state = ""
-
-
-/obj/item/attachable/suppressor/unremovable/invisible/Initialize(mapload, ...)
- . = ..()
-
-
-/obj/item/attachable/bayonet
- name = "bayonet"
- desc = "A sharp blade for mounting on a weapon. It can be used to stab manually on anything but harm intent. Slightly reduces the accuracy of the gun when mounted."
- icon_state = "bayonet"
- item_icons = list(
- slot_l_hand_str = 'icons/mob/inhands/weapons/melee_left.dmi',
- slot_r_hand_str = 'icons/mob/inhands/weapons/melee_right.dmi',
- )
- force = 20
- throwforce = 10
- attach_delay = 10 //Bayonets attach/detach quickly.
- detach_delay = 10
- attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
- melee_mod = 25
- slot = ATTACHMENT_SLOT_MUZZLE
- pixel_shift_x = 14 //Below the muzzle.
- pixel_shift_y = 18
- accuracy_mod = -0.05
- accuracy_unwielded_mod = -0.1
- size_mod = 1
- sharp = IS_SHARP_ITEM_ACCURATE
- variants_by_parent_type = list(/obj/item/weapon/gun/shotgun/pump/t35 = "bayonet_t35")
-
-/obj/item/attachable/bayonet/screwdriver_act(mob/living/user, obj/item/I)
- to_chat(user, span_notice("You modify the bayonet back into a combat knife."))
- if(loc == user)
- user.dropItemToGround(src)
- var/obj/item/weapon/combat_knife/knife = new(loc)
- user.put_in_hands(knife) //This proc tries right, left, then drops it all-in-one.
- if(knife.loc != user) //It ended up on the floor, put it whereever the old flashlight is.
- knife.forceMove(loc)
- qdel(src) //Delete da old bayonet
-
-/obj/item/attachable/bayonetknife
- name = "M-22 bayonet"
- desc = "A sharp knife that is the standard issue combat knife of the TerraGov Marine Corps can be attached to a variety of weapons at will or used as a standard knife."
- icon = 'icons/obj/items/weapons.dmi'
- icon_state = "bayonetknife"
- item_icons = list(
- slot_l_hand_str = 'icons/mob/inhands/weapons/melee_left.dmi',
- slot_r_hand_str = 'icons/mob/inhands/weapons/melee_right.dmi',
- )
- force = 25
- throwforce = 20
- throw_speed = 3
- throw_range = 6
- attack_speed = 8
- attach_delay = 10 //Bayonets attach/detach quickly.
- detach_delay = 10
- attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
- melee_mod = 25
- slot = ATTACHMENT_SLOT_MUZZLE
- pixel_shift_x = 14 //Below the muzzle.
- pixel_shift_y = 18
- accuracy_mod = -0.05
- accuracy_unwielded_mod = -0.1
- size_mod = 1
- sharp = IS_SHARP_ITEM_ACCURATE
- variants_by_parent_type = list(/obj/item/weapon/gun/shotgun/pump/t35 = "bayonetknife_t35")
-
-/obj/item/attachable/bayonetknife/Initialize(mapload)
- . = ..()
- AddElement(/datum/element/scalping)
- AddElement(/datum/element/shrapnel_removal, 12 SECONDS, 12 SECONDS, 10)
-
-/obj/item/attachable/melee_attack_chain(mob/user, atom/target, params, rightclick)
- if(target == user && !user.do_self_harm)
- return
- return ..()
-
-/obj/item/attachable/bayonetknife/som
- name = "\improper S20 SOM bayonet"
- desc = "A large knife that is the standard issue combat knife of the SOM. Can be attached to a variety of weapons at will or used as a standard knife."
- icon_state = "bayonetknife_som"
- item_state = "bayonetknife"
- force = 30
-
-/obj/item/attachable/extended_barrel
- name = "extended barrel"
- desc = "A lengthened barrel allows for lessened scatter, greater accuracy and muzzle velocity due to increased stabilization and shockwave exposure."
- slot = ATTACHMENT_SLOT_MUZZLE
- icon_state = "ebarrel"
- attach_shell_speed_mod = 1
- accuracy_mod = 0.15
- accuracy_unwielded_mod = 0.1
- scatter_mod = -1
- size_mod = 1
- variants_by_parent_type = list(/obj/item/weapon/gun/rifle/som = "ebarrel_big", /obj/item/weapon/gun/smg/som = "ebarrel_big", /obj/item/weapon/gun/shotgun/pump/t35 = "ebarrel_big")
-
-
-/obj/item/attachable/heavy_barrel
- name = "barrel charger"
- desc = "A fitted barrel extender that goes on the muzzle, with a small shaped charge that propels a bullet much faster.\nGreatly increases projectile speed and reduces damage falloff."
- slot = ATTACHMENT_SLOT_MUZZLE
- icon_state = "hbarrel"
- attach_shell_speed_mod = 2
- accuracy_mod = -0.05
- damage_falloff_mod = -0.2
-
-
-/obj/item/attachable/compensator
- name = "recoil compensator"
- desc = "A muzzle attachment that reduces recoil and scatter by diverting expelled gasses upwards. \nSignificantly reduces recoil and scatter, regardless of if the weapon is wielded."
- slot = ATTACHMENT_SLOT_MUZZLE
- icon_state = "comp"
- pixel_shift_x = 17
- scatter_mod = -3
- recoil_mod = -2
- scatter_unwielded_mod = -3
- recoil_unwielded_mod = -2
- variants_by_parent_type = list(
- /obj/item/weapon/gun/rifle/som = "comp_big",
- /obj/item/weapon/gun/smg/som = "comp_big",
- /obj/item/weapon/gun/shotgun/som = "comp_big",
- /obj/item/weapon/gun/shotgun/pump/t35 = "comp_big",
- /obj/item/weapon/gun/revolver/standard_magnum = "t76comp"
- )
-
-
-/obj/item/attachable/sniperbarrel
- name = "sniper barrel"
- icon_state = "sniperbarrel"
- desc = "A heavy barrel. CANNOT BE REMOVED."
- slot = ATTACHMENT_SLOT_MUZZLE
- flags_attach_features = NONE
- accuracy_mod = 0.15
- scatter_mod = -3
-
-/obj/item/attachable/autosniperbarrel
- name = "auto sniper barrel"
- icon_state = "t81barrel"
- desc = "A heavy barrel. CANNOT BE REMOVED."
- slot = ATTACHMENT_SLOT_UNDER
- flags_attach_features = NONE
- pixel_shift_x = 7
- pixel_shift_y = 14
- accuracy_mod = 0
- scatter_mod = -1
-
-/obj/item/attachable/smartbarrel
- name = "smartgun barrel"
- icon_state = "smartbarrel"
- desc = "A heavy rotating barrel. CANNOT BE REMOVED."
- slot = ATTACHMENT_SLOT_MUZZLE
- flags_attach_features = NONE
-
-/obj/item/attachable/focuslens
- name = "M43 focused lens"
- desc = "Directs the beam into one specialized lens, allowing the lasgun to use the deadly focused bolts on overcharge, making it more like a high damage sniper."
- slot = ATTACHMENT_SLOT_MUZZLE
- icon_state = "focus"
- pixel_shift_x = 17
- pixel_shift_y = 13
- ammo_mod = /datum/ammo/energy/lasgun/M43/overcharge
- damage_mod = -0.15
-
-/obj/item/attachable/widelens
- name = "M43 wide lens"
- desc = "Splits the lens into three, allowing the lasgun to use a deadly close-range blast on overcharge akin to a traditional pellet based shotgun shot."
- slot = ATTACHMENT_SLOT_MUZZLE
- icon_state = "wide"
- pixel_shift_x = 18
- pixel_shift_y = 15
- ammo_mod = /datum/ammo/energy/lasgun/M43/blast
- damage_mod = -0.15
-
-/obj/item/attachable/heatlens
- name = "M43 heat lens"
- desc = "Changes the intensity and frequency of the laser. This makes your target be set on fire at a cost of upfront damage and penetration."
- slot = ATTACHMENT_SLOT_MUZZLE
- icon_state = "heat"
- pixel_shift_x = 18
- pixel_shift_y = 16
- ammo_mod = /datum/ammo/energy/lasgun/M43/heat
- damage_mod = -0.15
-
-/obj/item/attachable/efflens
- name = "M43 efficient lens"
- desc = "Makes the lens smaller and lighter to use, allowing the lasgun to use its energy much more efficiently. \nDecreases energy output of the lasgun."
- slot = ATTACHMENT_SLOT_MUZZLE
- icon_state = "efficient"
- pixel_shift_x = 18
- pixel_shift_y = 14
- charge_mod = -5
-
-/obj/item/attachable/sx16barrel
- name = "SX-16 barrel"
- desc = "The standard barrel on the SX-16. CANNOT BE REMOVED."
- slot = ATTACHMENT_SLOT_MUZZLE
- icon_state = "sx16barrel"
- flags_attach_features = NONE
-
-/obj/item/attachable/pulselens
- name = "M43 pulse lens"
- desc = "Agitates the lens, allowing the lasgun to discharge at a rapid rate. \nAllows the weapon to be fired automatically."
- slot = ATTACHMENT_SLOT_MUZZLE
- icon_state = "pulse"
- pixel_shift_x = 18
- pixel_shift_y = 15
- damage_mod = -0.15
- gun_firemode_list_mod = list(GUN_FIREMODE_AUTOMATIC)
-
-/obj/item/attachable/sgbarrel
- name = "SG-29 barrel"
- icon_state = "sg29barrel"
- desc = "A heavy barrel. CANNOT BE REMOVED."
- slot = ATTACHMENT_SLOT_MUZZLE
- flags_attach_features = NONE
-
-/obj/item/attachable/t500barrel
- name = "R-500 extended barrel"
- desc = "Cool barrel for cool revolver"
- slot = ATTACHMENT_SLOT_MUZZLE
- delay_mod = -0.4 SECONDS
- icon = 'icons/Marine/attachments_64.dmi'
- icon_state = "barrel"
- attach_shell_speed_mod = 1
- accuracy_mod = 0.15
- accuracy_unwielded_mod = 0.1
- scatter_mod = -3
- scatter_unwielded_mod = 3
- recoil_unwielded_mod = 1
- size_mod = 1
- pixel_shift_x = 0
- pixel_shift_y = 0
-
-/obj/item/attachable/t500barrelshort
- name = "R-500 compensator"
- desc = "Cool compensator for cool revolver"
- slot = ATTACHMENT_SLOT_MUZZLE
- delay_mod = -0.2 SECONDS
- icon = 'icons/Marine/attachments_64.dmi'
- icon_state = "shortbarrel"
- scatter_mod = -2
- recoil_mod = -0.5
- scatter_unwielded_mod = -5
- recoil_unwielded_mod = -1
- accuracy_unwielded_mod = 0.15
- size_mod = 0.5
- pixel_shift_x = 0
- pixel_shift_y = 0
-
-
-///////////// Rail attachments ////////////////////////
-
-/obj/item/attachable/reddot
- name = "red-dot sight"
- desc = "A red-dot sight for short to medium range. Does not have a zoom feature, but does increase weapon accuracy and fire rate while aiming by a good amount. \nNo drawbacks."
- icon_state = "reddot"
- slot = ATTACHMENT_SLOT_RAIL
- accuracy_mod = 0.15
- accuracy_unwielded_mod = 0.1
- aim_mode_delay_mod = -0.5
- variants_by_parent_type = list(/obj/item/weapon/gun/rifle/som = "", /obj/item/weapon/gun/shotgun/som = "")
-
-/obj/item/attachable/m16sight
- name = "M16 iron sights"
- desc = "The iconic carry-handle iron sights for the m16. Usually removed once the user finds something worthwhile to attach to the rail."
- icon_state = "m16sight"
- slot = ATTACHMENT_SLOT_RAIL
- accuracy_mod = 0.1
- accuracy_unwielded_mod = 0.05
- movement_acc_penalty_mod = -0.1
-
-
-/obj/item/attachable/flashlight
- name = "rail flashlight"
- desc = "A simple flashlight used for mounting on a firearm. \nHas no drawbacks, but isn't particuraly useful outside of providing a light source."
- icon_state = "flashlight"
- light_mod = 6
- light_system = MOVABLE_LIGHT
- slot = ATTACHMENT_SLOT_RAIL
- flags_attach_features = ATTACH_REMOVABLE|ATTACH_ACTIVATION
- attachment_action_type = /datum/action/item_action/toggle
- activation_sound = 'sound/items/flashlight.ogg'
-
-/obj/item/attachable/flashlight/activate(mob/living/user, turn_off)
- turn_light(user, turn_off ? !turn_off : !light_on)
-
-/obj/item/attachable/flashlight/turn_light(mob/user, toggle_on, cooldown, sparks, forced, light_again)
- . = ..()
-
- if(. != CHECKS_PASSED)
- return
-
- if(ismob(master_gun.loc) && !user)
- user = master_gun.loc
-
- if(!toggle_on && light_on)
- icon_state = initial(icon_state)
- light_on = FALSE
- master_gun.set_light_range(master_gun.light_range - light_mod)
- master_gun.set_light_power(master_gun.light_power - (light_mod * 0.5))
- if(master_gun.light_range <= 0) //does the gun have another light source
- master_gun.set_light_on(FALSE)
- REMOVE_TRAIT(master_gun, TRAIT_GUN_FLASHLIGHT_ON, GUN_TRAIT)
- else if(toggle_on & !light_on)
- icon_state = initial(icon_state) +"_on"
- light_on = TRUE
- master_gun.set_light_range(master_gun.light_range + light_mod)
- master_gun.set_light_power(master_gun.light_power + (light_mod * 0.5))
- if(!HAS_TRAIT(master_gun, TRAIT_GUN_FLASHLIGHT_ON))
- master_gun.set_light_on(TRUE)
- ADD_TRAIT(master_gun, TRAIT_GUN_FLASHLIGHT_ON, GUN_TRAIT)
- else
- return
-
- for(var/X in master_gun.actions)
- var/datum/action/A = X
- A.update_button_icon()
-
- update_icon()
-
-/obj/item/attachable/flashlight/attackby(obj/item/I, mob/user, params)
- . = ..()
-
- if(istype(I,/obj/item/tool/screwdriver))
- to_chat(user, span_notice("You modify the rail flashlight back into a normal flashlight."))
- if(loc == user)
- user.temporarilyRemoveItemFromInventory(src)
- var/obj/item/flashlight/F = new(user)
- user.put_in_hands(F) //This proc tries right, left, then drops it all-in-one.
- qdel(src) //Delete da old flashlight
-
-/obj/item/attachable/flashlight/under
- name = "underbarreled flashlight"
- desc = "A simple flashlight used for mounting on a firearm. \nHas no drawbacks, but isn't particuraly useful outside of providing a light source."
- icon_state = "uflashlight"
- slot = ATTACHMENT_SLOT_UNDER
- flags_attach_features = ATTACH_REMOVABLE|ATTACH_ACTIVATION
-
-
-
-/obj/item/attachable/quickfire
- name = "quickfire adapter"
- desc = "An enhanced and upgraded autoloading mechanism to fire rounds more quickly. \nHowever, it also reduces accuracy and the number of bullets fired on burst."
- slot = ATTACHMENT_SLOT_RAIL
- icon_state = "autoloader"
- accuracy_mod = -0.10
- delay_mod = -0.125 SECONDS
- burst_mod = -1
- accuracy_unwielded_mod = -0.15
-
-/obj/item/attachable/magnetic_harness
- name = "magnetic harness"
- desc = "A magnetically attached harness kit that attaches to the rail mount of a weapon. When dropped, the weapon will sling to a TGMC armor."
- icon_state = "magnetic"
- slot = ATTACHMENT_SLOT_RAIL
- pixel_shift_x = 13
- ///Handles the harness functionality, created when attached to a gun and removed on detach
- var/datum/component/reequip_component
-
-/obj/item/attachable/magnetic_harness/on_attach(attaching_item, mob/user)
- . = ..()
- if(!master_gun)
- return
- reequip_component = master_gun.AddComponent(/datum/component/reequip, list(SLOT_S_STORE, SLOT_BACK))
-
-/obj/item/attachable/magnetic_harness/on_detach(attaching_item, mob/user)
- . = ..()
- if(master_gun)
- return
- QDEL_NULL(reequip_component)
-
-/obj/item/attachable/scope
- name = "rail scope"
- icon_state = "sniperscope"
- desc = "A rail mounted zoom sight scope. Allows zoom by activating the attachment."
- slot = ATTACHMENT_SLOT_RAIL
- aim_speed_mod = 0.5 //Extra slowdown when aiming
- wield_delay_mod = 0.4 SECONDS
- scoped_accuracy_mod = SCOPE_RAIL //accuracy mod of 0.4 when scoped
- flags_attach_features = ATTACH_REMOVABLE|ATTACH_ACTIVATION
- attachment_action_type = /datum/action/item_action/toggle
- scope_zoom_mod = TRUE // codex
- accuracy_unwielded_mod = -0.05
- zoom_tile_offset = 11
- zoom_viewsize = 10
- zoom_allow_movement = TRUE
- ///how much slowdown the scope gives when zoomed. You want this to be slowdown you want minus aim_speed_mod
- var/zoom_slowdown = 1
- /// scope zoom delay, delay before you can aim.
- var/scope_delay = 0
- ///boolean as to whether a scope can apply nightvision
- var/has_nightvision = FALSE
- ///boolean as to whether the attachment is currently giving nightvision
- var/active_nightvision = FALSE
- ///True if the scope is supposed to reactiveate when a deployed gun is turned.
- var/deployed_scope_rezoom = FALSE
-
-
-/obj/item/attachable/scope/marine
- name = "T-47 rail scope"
- desc = "A marine standard mounted zoom sight scope. Allows zoom by activating the attachment."
- icon_state = "marinescope"
-
-/obj/item/attachable/scope/nightvision
- name = "T-46 Night vision scope"
- icon_state = "nvscope"
- desc = "A rail-mounted night vision scope developed by Roh-Easy industries for the TGMC. Allows zoom by activating the attachment."
- has_nightvision = TRUE
-
-/obj/item/attachable/scope/optical
- name = "T-49 Optical imaging scope"
- icon_state = "imagerscope"
- desc = "A rail-mounted scope designed for the AR-55 and GL-54. Features low light optical imaging capabilities and assists with precision aiming. Allows zoom by activating the attachment."
- has_nightvision = TRUE
- aim_speed_mod = 0.3
- wield_delay_mod = 0.2 SECONDS
- zoom_tile_offset = 7
- zoom_viewsize = 5 //RU TGMC EDIT
- add_aim_mode = TRUE
-
-/obj/item/attachable/scope/mosin
- name = "Mosin nagant rail scope"
- icon_state = "mosinscope"
- desc = "A Mosin specific mounted zoom sight scope. Allows zoom by activating the attachment."
-
-/obj/item/attachable/scope/standard_magnum
- name = "R-76 rail scope"
- desc = "A custom rail mounted zoom sight scope designed specifically for the R-76 Magnum. Allows zoom by activating the attachment."
- icon = 'icons/Marine/attachments_64.dmi'
- icon_state = "t76scope"
-
-/obj/item/attachable/scope/unremovable
- flags_attach_features = ATTACH_ACTIVATION
-
-/obj/item/attachable/scope/unremovable/flaregun
- name = "long range ironsights"
- desc = "An unremovable set of long range ironsights for a flaregun."
- aim_speed_mod = 0
- wield_delay_mod = 0
- zoom_tile_offset = 5
- zoom_viewsize = 0
- scoped_accuracy_mod = SCOPE_RAIL_MINI
- zoom_slowdown = 0.50
-
-/obj/item/attachable/scope/unremovable/tl127
- name = "T-45 rail scope"
- icon_state = "tl127_scope"
- aim_speed_mod = 0
- wield_delay_mod = 0
- desc = "A rail mounted zoom sight scope specialized for the SR-127 sniper rifle. Allows zoom by activating the attachment."
-
-/obj/item/attachable/scope/unremovable/heavymachinegun
- name = "HMG-08 long range ironsights"
- desc = "An unremovable set of long range ironsights for an HMG-08 machinegun."
- icon_state = "sniperscope_invisible"
- zoom_viewsize = 0
- zoom_tile_offset = 5
-
-/obj/item/attachable/scope/unremovable/mmg
- name = "MG-27 rail scope"
- icon_state = "miniscope"
- desc = "A small rail mounted zoom sight scope. Allows zoom by activating the attachment."
- wield_delay_mod = 0.2 SECONDS
- aim_speed_mod = 0.2
- scoped_accuracy_mod = SCOPE_RAIL_MINI
- zoom_slowdown = 0.3
- zoom_tile_offset = 5
- zoom_viewsize = 0
-
-/obj/item/attachable/scope/unremovable/standard_atgun
- name = "AT-36 long range scope"
- desc = "An unremovable set of long range scopes, very complex to properly range. Requires time to aim.."
- icon_state = "sniperscope_invisible"
- scope_delay = 2 SECONDS
- zoom_tile_offset = 7
-
-/obj/item/attachable/scope/unremovable/tl102
- name = "HSG-102 smart sight"
- desc = "An unremovable smart sight built for use with the tl102, it does nearly all the aiming work for the gun's integrated IFF systems."
- icon_state = "sniperscope_invisible"
- zoom_viewsize = 0
- zoom_tile_offset = 5
- deployed_scope_rezoom = TRUE
-
-//all mounted guns with a nest use this
-/obj/item/attachable/scope/unremovable/tl102/nest
- scope_delay = 2 SECONDS
- zoom_tile_offset = 7
- zoom_viewsize = 5 //RU TGMC EDIT
- deployed_scope_rezoom = FALSE
-
-/obj/item/attachable/scope/activate(mob/living/carbon/user, turn_off)
- if(turn_off)
- if(SEND_SIGNAL(user, COMSIG_ITEM_ZOOM) & COMSIG_ITEM_ALREADY_ZOOMED)
- zoom(user)
- return TRUE
-
- if(!(master_gun.flags_item & WIELDED) && !CHECK_BITFIELD(master_gun.flags_item, IS_DEPLOYED))
- if(user)
- to_chat(user, span_warning("You must hold [master_gun] with two hands to use [src]."))
- return FALSE
- if(CHECK_BITFIELD(master_gun.flags_item, IS_DEPLOYED) && user.dir != master_gun.loc.dir)
- user.setDir(master_gun.loc.dir)
- if(!do_after(user, scope_delay, NONE, src, BUSY_ICON_BAR))
- return FALSE
- zoom(user)
- update_icon()
- return TRUE
-
-/obj/item/attachable/scope/zoom_item_turnoff(datum/source, mob/living/carbon/user)
- if(ismob(source))
- INVOKE_ASYNC(src, PROC_REF(activate), source, TRUE)
- else
- INVOKE_ASYNC(src, PROC_REF(activate), user, TRUE)
-
-/obj/item/attachable/scope/onzoom(mob/living/user)
- if(zoom_allow_movement)
- user.add_movespeed_modifier(MOVESPEED_ID_SCOPE_SLOWDOWN, TRUE, 0, NONE, TRUE, zoom_slowdown)
- RegisterSignal(user, COMSIG_CARBON_SWAPPED_HANDS, PROC_REF(zoom_item_turnoff))
- else
- RegisterSignals(user, list(COMSIG_MOVABLE_MOVED, COMSIG_CARBON_SWAPPED_HANDS), PROC_REF(zoom_item_turnoff))
- if(!CHECK_BITFIELD(master_gun.flags_item, IS_DEPLOYED))
- RegisterSignal(user, COMSIG_MOB_FACE_DIR, PROC_REF(change_zoom_offset))
- RegisterSignals(master_gun, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_UNWIELD, COMSIG_ITEM_DROPPED), PROC_REF(zoom_item_turnoff))
- master_gun.accuracy_mult += scoped_accuracy_mod
- if(has_nightvision)
- update_remote_sight(user)
- user.reset_perspective(src)
- active_nightvision = TRUE
-
-/obj/item/attachable/scope/onunzoom(mob/living/user)
- if(zoom_allow_movement)
- user.remove_movespeed_modifier(MOVESPEED_ID_SCOPE_SLOWDOWN)
- UnregisterSignal(user, list(COMSIG_CARBON_SWAPPED_HANDS, COMSIG_MOB_FACE_DIR))
- else
- UnregisterSignal(user, list(COMSIG_MOVABLE_MOVED, COMSIG_CARBON_SWAPPED_HANDS, COMSIG_MOB_FACE_DIR))
- UnregisterSignal(master_gun, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_UNWIELD, COMSIG_ITEM_DROPPED))
- master_gun.accuracy_mult -= scoped_accuracy_mod
- if(has_nightvision)
- user.update_sight()
- user.reset_perspective(user)
- active_nightvision = FALSE
-
-/obj/item/attachable/scope/update_remote_sight(mob/living/user)
- . = ..()
- user.see_in_dark = 32
- user.lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE
- user.sync_lighting_plane_alpha()
- return TRUE
-
-/obj/item/attachable/scope/zoom(mob/living/user, tileoffset, viewsize)
- . = ..()
- //Makes the gun zoom align with the attachment, used for projectile procs
- if(zoom)
- master_gun.zoom = TRUE
- else
- master_gun.zoom = FALSE
-
-/obj/item/attachable/scope/optical/update_remote_sight(mob/living/user)
- . = ..()
- user.see_in_dark = 2
- return TRUE
-
-/obj/item/attachable/scope/unremovable/laser_sniper_scope
- name = "Terra Experimental laser sniper rifle rail scope"
- desc = "A marine standard mounted zoom sight scope made for the Terra Experimental laser sniper rifle otherwise known as TE-S abbreviated, allows zoom by activating the attachment. Use F12 if your HUD doesn't come back."
- icon = 'icons/Marine/marine-weapons.dmi'
- icon_state = "tes"
-
-/obj/item/attachable/scope/mini
- name = "mini rail scope"
- icon_state = "miniscope"
- desc = "A small rail mounted zoom sight scope. Allows zoom by activating the attachment."
- slot = ATTACHMENT_SLOT_RAIL
- wield_delay_mod = 0.2 SECONDS
- accuracy_unwielded_mod = -0.05
- aim_speed_mod = 0.2
- scoped_accuracy_mod = SCOPE_RAIL_MINI
- scope_zoom_mod = TRUE
- has_nightvision = FALSE
- zoom_allow_movement = TRUE
- zoom_slowdown = 0.3
- zoom_tile_offset = 5
- zoom_viewsize = 0
- variants_by_parent_type = list(/obj/item/weapon/gun/rifle/som = "")
-
-/obj/item/attachable/scope/mini/tx11
- name = "AR-11 mini rail scope"
- icon_state = "tx11scope"
-
-/obj/item/attachable/scope/antimaterial
- name = "antimaterial rail scope"
- desc = "A rail mounted zoom sight scope specialized for the antimaterial Sniper Rifle . Allows zoom by activating the attachment. Can activate its targeting laser while zoomed to take aim for increased damage and penetration."
- icon_state = "antimat"
- scoped_accuracy_mod = SCOPE_RAIL_SNIPER
- has_nightvision = TRUE
- zoom_allow_movement = FALSE
- flags_attach_features = ATTACH_ACTIVATION|ATTACH_REMOVABLE
- pixel_shift_x = 0
- pixel_shift_y = 17
-
-
-/obj/item/attachable/scope/slavic
- icon_state = "slavicscope"
-
-/obj/item/attachable/scope/pmc
- icon_state = "pmcscope"
- flags_attach_features = ATTACH_ACTIVATION
-
-/obj/item/attachable/scope/mini/dmr
- name = "DMR-37 mini rail scope"
- icon_state = "t37"
-
-
-//////////// Stock attachments ////////////////////////////
-
-
-/obj/item/attachable/stock //Generic stock parent and related things.
- name = "default stock"
- desc = "Default parent object, not meant for use."
- slot = ATTACHMENT_SLOT_STOCK
- flags_attach_features = NONE //most stocks are not removable
- size_mod = 2
- pixel_shift_x = 30
- pixel_shift_y = 14
-
-/obj/item/attachable/stock/mosin
- name = "mosin wooden stock"
- desc = "A non-standard long wooden stock for Slavic firearms."
- icon_state = "mosinstock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/ppsh
- name = "PPSh-17b submachinegun wooden stock"
- desc = "A long wooden stock for a PPSh-17b submachinegun"
- icon_state = "ppshstock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/t27
- name = "MG-27 Body"
- desc = "A stock for a MG-27 MMG."
- icon = 'icons/Marine/marine-mmg.dmi'
- icon_state = "t27body"
- pixel_shift_x = 15
- pixel_shift_y = 0
-
-/obj/item/attachable/stock/pal12
- name = "Paladin-12 pump shotgun stock"
- desc = "A standard light stock for the Paladin-12 shotgun."
- icon_state = "pal12stock"
-
-/obj/item/attachable/stock/mpi_km
- name = "MPi-KM wooden stock"
- desc = "A metallic stock with a wooden paint coating, made to fit the MPi-KM."
- icon_state = "ak47stock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/mpi_km/black
- name = "MPi-KM polymer stock"
- desc = "A black polymer stock, made to fit the MPi-KM."
- icon_state = "ak47stock_black"
-
-/obj/item/attachable/stock/lmg_d
- name = "lMG-D wooden stock"
- desc = "A metallic stock with a wooden paint coating, made to fit lMG-D."
- icon_state = "ak47stock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/tx15
- name = "\improper SH-15 stock"
- desc = "The standard stock for the SH-15. Cannot be removed."
- icon_state = "tx15stock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/sgstock
- name = "SG-29 stock"
- desc = "A standard machinegun stock."
- icon_state = "sg29stock"
- greyscale_config = null
- colorable_allowed = NONE
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/strstock
- name = "SG-62 stock"
- desc = "A standard rifle stock."
- icon_state = "sg62stock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/lasgun
- name = "\improper M43 Sunfury lasgun stock"
- desc = "The standard stock for the M43 Sunfury lasgun."
- icon_state = "laserstock"
- pixel_shift_x = 41
- pixel_shift_y = 10
-
-/obj/item/attachable/stock/lasgun/practice
- name = "\improper M43-P Sunfury lasgun stock"
- desc = "The standard stock for the M43-P Sunfury lasgun, seems the stock is made out of plastic."
- icon_state = "laserstock"
- pixel_shift_x = 41
- pixel_shift_y = 10
-
-/obj/item/attachable/stock/tl127stock
- name = "\improper SR-127 stock"
- desc = "A irremovable SR-127 sniper rifle stock."
- icon_state = "tl127stock"
- greyscale_config = null
- colorable_allowed = NONE
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/garand
- name = "\improper C1 stock"
- desc = "A irremovable C1 stock."
- icon_state = "garandstock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/trenchgun
- name = "\improper L-4043 stock"
- desc = "A irremovable L-4043 stock."
- icon_state = "trenchstock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/icc_pdw
- name = "\improper L-40 stock"
- desc = "A irremovable L-40 stock."
- icon_state = "l40stock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/icc_sharpshooter
- name = "\improper L-1 stock"
- desc = "A irremovable L-11 stock."
- icon_state = "l11stock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/clf_heavyrifle
- name = "PTR-41/1785 body"
- desc = "A stock for a PTR-41/1785 A-MR."
- icon = 'icons/Marine/clf_heavyrifle.dmi'
- icon_state = "ptrs_stock"
- pixel_shift_x = 15
- pixel_shift_y = 0
-
-/obj/item/attachable/stock/dpm
- name = "\improper DP-27 stock"
- desc = "A irremovable DP stock."
- icon_state = "dpstock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/t39stock
- name = "\improper SH-39 stock"
- desc = "A specialized stock for the SH-39."
- icon_state = "t39stock"
- pixel_shift_x = 32
- pixel_shift_y = 13
- size_mod = 1
- flags_attach_features = ATTACH_REMOVABLE
- wield_delay_mod = 0.2 SECONDS
- accuracy_mod = 0.15
- recoil_mod = -2
- scatter_mod = -2
-
-/obj/item/attachable/stock/t60stock
- name = "MG-60 stock"
- desc = "A irremovable MG-60 general purpose machinegun stock."
- icon_state = "t60stock"
- greyscale_config = null
- colorable_allowed = NONE
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/t70stock
- name = "\improper GL-70 stock"
- desc = "A irremovable GL-70 grenade launcher stock."
- icon_state = "t70stock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/t84stock
- name = "\improper FL-84 stock"
- desc = "A irremovable FL-84 flamer stock."
- icon_state = "tl84stock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/m41a
- name = "PR-11 stock"
- icon_state = "m41a"
-
-/obj/item/attachable/stock/tx11
- name = "AR-11 stock"
- icon_state = "tx11stock"
-
-/obj/item/attachable/stock/som_mg_stock
- name = "\improper V-41 stock"
- desc = "A irremovable V-41 machine gun stock."
- icon_state = "v41stock"
- pixel_shift_x = 0
- pixel_shift_y = 0
-
-/obj/item/attachable/stock/t18stock
- name = "\improper AR-18 stock"
- desc = "A specialized stock for the AR-18."
- icon_state = "t18stock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/t12stock
- name = "\improper AR-12 stock"
- desc = "A specialized stock for the AR-12."
- icon_state = "t12stock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/t42stock
- name = "\improper MG-42 stock"
- desc = "A specialized stock for the MG-42."
- icon_state = "t42stock"
- pixel_shift_x = 32
- pixel_shift_y = 13
-
-/obj/item/attachable/stock/t64stock
- name = "\improper BR-64 stock"
- desc = "A specialized stock for the BR-64."
- icon_state = "t64stock"
-
-//You can remove the stock on the Magnum. So it has stats and is removeable.
-
-/obj/item/attachable/stock/t76
- name = "T-76 magnum stock"
- desc = "A R-76 magnum stock. Makes about all your handling better outside of making it harder to wield. Recommended to be kept on the R-76 at all times if you value your shoulder."
- icon_state = "t76stock"
- flags_attach_features = ATTACH_REMOVABLE
- melee_mod = 5
- scatter_mod = -1
- size_mod = 2
- aim_speed_mod = 0.05
- recoil_mod = -2
- pixel_shift_x = 30
- pixel_shift_y = 14
-
-/obj/item/attachable/stock/t500stock
- name = "R-500 stock"
- desc = "Cool stock for cool revolver."
- flags_attach_features = ATTACH_REMOVABLE
- wield_delay_mod = 0.2 SECONDS
- delay_mod = -0.4 SECONDS
- icon = 'icons/Marine/attachments_64.dmi'
- icon_state = "stock"
- size_mod = 1
- accuracy_mod = 0.15
- recoil_mod = -1
- recoil_unwielded_mod = 1
- scatter_mod = -2
- scatter_unwielded_mod = 5
- melee_mod = 10
- pixel_shift_x = 0
- pixel_shift_y = 0
-
-
-//Underbarrel
-
-/obj/item/attachable/verticalgrip
- name = "vertical grip"
- desc = "A custom-built improved foregrip for better accuracy, moderately faster aimed movement speed, less recoil, and less scatter when wielded especially during burst fire. \nHowever, it also increases weapon size, slightly increases wield delay and makes unwielded fire more cumbersome."
- icon_state = "verticalgrip"
- greyscale_config = null
- colorable_allowed = NONE
- wield_delay_mod = 0.2 SECONDS
- size_mod = 1
- slot = ATTACHMENT_SLOT_UNDER
- pixel_shift_x = 20
- accuracy_mod = 0.1
- recoil_mod = -2
- scatter_mod = -3
- burst_scatter_mod = -1
- accuracy_unwielded_mod = -0.05
- scatter_unwielded_mod = 3
- aim_speed_mod = -0.1
- aim_mode_movement_mult = -0.2
-
-
-/obj/item/attachable/angledgrip
- name = "angled grip"
- desc = "A custom-built improved foregrip for less recoil, and faster wielding time. \nHowever, it also increases weapon size, and slightly hinders unwielded firing."
- icon_state = "angledgrip"
- greyscale_config = /datum/greyscale_config/gun_attachment
- colorable_allowed = PRESET_COLORS_ALLOWED
- wield_delay_mod = -0.3 SECONDS
- size_mod = 1
- slot = ATTACHMENT_SLOT_UNDER
- pixel_shift_x = 20
- recoil_mod = -1
- scatter_mod = 2
- accuracy_unwielded_mod = -0.1
- scatter_unwielded_mod = 1
-
-
-
-/obj/item/attachable/gyro
- name = "gyroscopic stabilizer"
- desc = "A set of weights and balances to stabilize the weapon when burst firing or moving, especially while shooting one-handed. Greatly reduces movement penalties to accuracy. Significantly reduces burst scatter, recoil and general scatter. By increasing accuracy while moving, it let you move faster when taking aim."
- icon_state = "gyro"
- slot = ATTACHMENT_SLOT_UNDER
- scatter_mod = -1
- recoil_mod = -2
- movement_acc_penalty_mod = -2
- accuracy_unwielded_mod = 0.1
- scatter_unwielded_mod = -2
- recoil_unwielded_mod = -1
- aim_mode_movement_mult = -0.5
-
-/obj/item/attachable/lasersight
- name = "laser sight"
- desc = "A laser sight placed under the barrel. Significantly increases one-handed accuracy and significantly reduces unwielded penalties to accuracy."
- icon_state = "lasersight"
- slot = ATTACHMENT_SLOT_UNDER
- pixel_shift_x = 17
- pixel_shift_y = 17
- accuracy_mod = 0.1
- accuracy_unwielded_mod = 0.15
-
-/obj/item/attachable/lace
- name = "pistol lace"
- desc = "A simple lace to wrap around your wrist."
- icon_state = "lace"
- slot = ATTACHMENT_SLOT_MUZZLE //so you cannot have this and RC at once aka balance
- flags_attach_features = ATTACH_REMOVABLE|ATTACH_ACTIVATION
- attachment_action_type = /datum/action/item_action/toggle
-
-/obj/item/attachable/lace/t500
- name = "R-500 lace"
- icon = 'icons/Marine/attachments_64.dmi'
- slot = ATTACHMENT_SLOT_STOCK
- pixel_shift_x = 0
- pixel_shift_y = 0
-
-
-/obj/item/attachable/lace/activate(mob/living/user, turn_off)
- if(lace_deployed)
- REMOVE_TRAIT(master_gun, TRAIT_NODROP, PISTOL_LACE_TRAIT)
- to_chat(user, span_notice("You feel the [src] loosen around your wrist!"))
- playsound(user, 'sound/weapons/fistunclamp.ogg', 25, 1, 7)
- icon_state = "lace"
- else if(turn_off)
- return
- else
- if(user.do_actions)
- return
- if(!do_after(user, 0.5 SECONDS, NONE, src, BUSY_ICON_BAR))
- return
- to_chat(user, span_notice("You deploy the [src]."))
- ADD_TRAIT(master_gun, TRAIT_NODROP, PISTOL_LACE_TRAIT)
- to_chat(user, span_warning("You feel the [src] shut around your wrist!"))
- playsound(user, 'sound/weapons/fistclamp.ogg', 25, 1, 7)
- icon_state = "lace-on"
-
- lace_deployed = !lace_deployed
-
- for(var/i in master_gun.actions)
- var/datum/action/action_to_update = i
- action_to_update.update_button_icon()
-
- update_icon()
- return TRUE
-
-
-
-/obj/item/attachable/burstfire_assembly
- name = "burst fire assembly"
- desc = "A mechanism re-assembly kit that allows for automatic fire, or more shots per burst if the weapon already has the ability. \nIncreases scatter and decreases accuracy."
- icon_state = "rapidfire"
- slot = ATTACHMENT_SLOT_UNDER
- burst_mod = 2
- burst_scatter_mod = 1
- burst_accuracy_mod = -0.1
-
-
-//Foldable/deployable attachments
-/obj/item/attachable/foldable
- name = "foldable stock"
- desc = "A foldable stock. You shouldn't see this."
- icon_state = ""
- slot = ATTACHMENT_SLOT_STOCK
- flags_attach_features = ATTACH_REMOVABLE|ATTACH_ACTIVATION
- attachment_action_type = /datum/action/item_action/toggle
- ///How long it takes to fold or unfold
- var/deploy_time
- ///whether the attachment is currently folded or not
- var/folded = TRUE
-
-/obj/item/attachable/foldable/on_attach(attaching_item, mob/user)
- if(!istype(attaching_item, /obj/item/weapon/gun))
- return //Guns only
-
- master_gun = attaching_item
-
- if(attachment_action_type)
- var/datum/action/action_to_update = new attachment_action_type(src, master_gun)
- if(isliving(master_gun.loc))
- var/mob/living/living_user = master_gun.loc
- if(master_gun == living_user.l_hand || master_gun == living_user.r_hand)
- action_to_update.give_action(living_user)
-
- //custom attachment icons for specific guns
- if(length(variants_by_parent_type))
- for(var/selection in variants_by_parent_type)
- if(istype(master_gun, selection))
- icon_state = variants_by_parent_type[selection]
-
- update_icon()
- if(!greyscale_config || !greyscale_colors)
- return
- RegisterSignal(master_gun, COMSIG_ITEM_SECONDARY_COLOR, PROC_REF(handle_color))
-
-/obj/item/attachable/foldable/on_detach(detaching_item, mob/user)
- if(!isgun(detaching_item))
- return
-
- if(!folded)
- activate()
-
- for(var/datum/action/action_to_update AS in master_gun.actions)
- if(action_to_update.target != src)
- continue
- qdel(action_to_update)
- break
-
- master_gun = null
- icon_state = initial(icon_state)
- update_icon()
- if(!greyscale_config || !greyscale_colors)
- return
- UnregisterSignal(master_gun, COMSIG_ITEM_SECONDARY_COLOR)
-
-/obj/item/attachable/foldable/activate(mob/living/user, turn_off)
- if(user && deploy_time && !do_after(user, deploy_time, NONE, src, BUSY_ICON_BAR))
- return FALSE
-
- folded = !folded
- playsound(src, 'sound/machines/click.ogg', 20, FALSE, 4)
- update_icon()
-
- if(master_gun)
- apply_modifiers(master_gun, user, !folded)
- for(var/X in master_gun.actions)
- var/datum/action/A = X
- A.update_button_icon()
-
- return TRUE
-
-/obj/item/attachable/foldable/update_icon_state()
- . = ..()
- if(folded)
- icon_state = initial(icon_state)
- else
- icon_state = "[initial(icon_state)]_open"
-
-/obj/item/attachable/foldable/skorpion_stock
- name = "\improper Skorpion submachinegun wooden stock"
- desc = "A foldable wire stock for a Skorpion submachinegun"
- icon = 'icons/Marine/attachments_64.dmi'
- icon_state = "skorpion"
- flags_attach_features = ATTACH_ACTIVATION
- pixel_shift_x = 0
- pixel_shift_y = 0
- size_mod = 2
- wield_delay_mod = 0.1 SECONDS
- accuracy_mod = 0.25
- recoil_mod = -2
- scatter_mod = -6
- scatter_unwielded_mod = 4
- accuracy_unwielded_mod = -0.1
-
-/obj/item/attachable/foldable/t19stock
- name = "\improper MP-19 machinepistol stock"
- desc = "A submachinegun stock distributed in small numbers to TGMC forces. Compatible with the MP-19, this stock reduces recoil and improves accuracy, but at a reduction to handling and agility. Seemingly a bit more effective in a brawl."
- flags_attach_features = ATTACH_ACTIVATION
- wield_delay_mod = 0.1 SECONDS
- melee_mod = 5
- size_mod = 1
- icon_state = "t19stock"
- accuracy_mod = 0.3
- recoil_mod = -2
- scatter_mod = -8
- accuracy_unwielded_mod = -0.1
- scatter_unwielded_mod = 4
-
-/obj/item/attachable/foldable/som_carbine
- name = "\improper V-34 carbine stock"
- desc = "A side folding stock built into the V-34 carbine. The gun is designed to be fired with the stock deployed, but can be done without, with some difficulty."
- flags_attach_features = ATTACH_ACTIVATION
- wield_delay_mod = 0.1 SECONDS
- melee_mod = 5
- size_mod = 1
- icon_state = "v34stock"
- accuracy_mod = 0.2
- recoil_mod = -2
- scatter_mod = -8
- aim_speed_mod = 0.05
-
-/obj/item/attachable/foldable/icc_machinepistol
- name = "\improper PL-38 machinepistol stock"
- desc = "A submachinegun stock found on ICC subguns, this stock reduces recoil and improves accuracy, but at a reduction to handling and agility. Seemingly a bit more effective in a brawl."
- flags_attach_features = ATTACH_ACTIVATION
- icon = 'icons/Marine/attachments_64.dmi'
- wield_delay_mod = 0.1 SECONDS
- melee_mod = 5
- size_mod = 1
- icon_state = "pl38stock"
- accuracy_mod = 0.3
- recoil_mod = -2
- scatter_mod = -8
- accuracy_unwielded_mod = -0.1
- scatter_unwielded_mod = 4
-
-/obj/item/attachable/foldable/t35stock
- name = "\improper SH-35 stock"
- desc = "A non-standard heavy stock for the SH-35 shotgun. Less quick and more cumbersome than the standard issue stakeout, but reduces recoil and improves accuracy. Allegedly makes a pretty good club in a fight too."
- icon = 'icons/Marine/attachments_64.dmi'
- icon_state = "t35stock"
- greyscale_config = null
- colorable_allowed = NONE
- flags_attach_features = ATTACH_ACTIVATION
- wield_delay_mod = 0.2 SECONDS
- accuracy_mod = 0.15
- recoil_mod = -3
- scatter_mod = -2
-
-/obj/item/attachable/foldable/bipod
- name = "bipod"
- desc = "A simple set of telescopic poles to keep a weapon stabilized during firing. \nGreatly increases accuracy and reduces recoil and scatter when properly placed, but also increases weapon size."
- icon_state = "bipod"
- slot = ATTACHMENT_SLOT_UNDER
- size_mod = 2
- deploy_time = 1 SECONDS
- accuracy_mod = 0.3
- recoil_mod = -2
- scatter_mod = -10
- burst_scatter_mod = -3
- aim_mode_delay_mod = -0.5
-
-/obj/item/attachable/foldable/bipod/activate(mob/living/user, turn_off)
- if(folded && !(master_gun.flags_item & WIELDED)) //no one handed bipod use
- if(user)
- balloon_alert(user, "Unwielded")
- return
-
- . = ..()
-
- if(folded)
- UnregisterSignal(master_gun, list(COMSIG_ITEM_DROPPED, COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_UNWIELD))
- UnregisterSignal(user, COMSIG_MOVABLE_MOVED)
- to_chat(user, span_notice("You retract [src]."))
- return
-
- if(user)
- RegisterSignals(master_gun, list(COMSIG_ITEM_DROPPED, COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_UNWIELD), PROC_REF(retract_bipod))
- RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(retract_bipod))
- to_chat(user, span_notice("You deploy [src]."))
-
-///Signal handler for forced undeployment
-/obj/item/attachable/foldable/bipod/proc/retract_bipod(datum/source, mob/living/user)
- SIGNAL_HANDLER
- deploy_time = 0
- INVOKE_ASYNC(src, PROC_REF(activate), (istype(user) ? user : source), TRUE)
- deploy_time = initial(deploy_time)
- to_chat(user, span_warning("Losing support, the bipod retracts!"))
-
-/obj/item/attachable/buildasentry
- name = "\improper Build-A-Sentry Attachment System"
- icon = 'icons/Marine/sentry.dmi'
- icon_state = "build_a_sentry_attachment"
- desc = "The Build-A-Sentry is the latest design in cheap, automated, defense. Simple attach it to the rail of a gun and deploy. Its that easy!"
- slot = ATTACHMENT_SLOT_RAIL
- size_mod = 1
- pixel_shift_x = 10
- pixel_shift_y = 18
- ///Deploy time for the build-a-sentry
- var/deploy_time = 2 SECONDS
- ///Undeploy tim for the build-a-sentry
- var/undeploy_time = 2 SECONDS
-
-/obj/item/attachable/buildasentry/can_attach(obj/item/attaching_to, mob/attacher)
- if(!isgun(attaching_to))
- return FALSE
- var/obj/item/weapon/gun/attaching_gun = attaching_to
- if(ispath(attaching_gun.deployable_item, /obj/machinery/deployable/mounted/sentry))
- to_chat(attacher, span_warning("[attaching_gun] is already a sentry!"))
- return FALSE
- return ..()
-
-/obj/item/attachable/buildasentry/on_attach(attaching_item, mob/user)
- . = ..()
- ENABLE_BITFIELD(master_gun.flags_item, IS_DEPLOYABLE)
- master_gun.deployable_item = /obj/machinery/deployable/mounted/sentry/buildasentry
- master_gun.ignored_terrains = list(
- /obj/machinery/deployable/mounted,
- /obj/machinery/miner,
- )
- if(master_gun.ammo_datum_type && CHECK_BITFIELD(initial(master_gun.ammo_datum_type.flags_ammo_behavior), AMMO_ENERGY) || istype(master_gun, /obj/item/weapon/gun/energy)) //If the guns ammo is energy, the sentry will shoot at things past windows.
- master_gun.ignored_terrains += list(
- /obj/structure/window,
- /obj/structure/window/reinforced,
- /obj/machinery/door/window,
- /obj/structure/window/framed,
- /obj/structure/window/framed/colony,
- /obj/structure/window/framed/mainship,
- /obj/structure/window/framed/prison,
- )
- master_gun.turret_flags |= TURRET_HAS_CAMERA|TURRET_SAFETY|TURRET_ALERTS
- master_gun.AddComponent(/datum/component/deployable_item, master_gun.deployable_item, deploy_time, undeploy_time)
- update_icon()
-
-/obj/item/attachable/buildasentry/on_detach(detaching_item, mob/user)
- . = ..()
- var/obj/item/weapon/gun/detaching_gun = detaching_item
- DISABLE_BITFIELD(detaching_gun.flags_item, IS_DEPLOYABLE)
- qdel(detaching_gun.GetComponent(/datum/component/deployable_item))
- detaching_gun.ignored_terrains = null
- detaching_gun.deployable_item = null
- detaching_gun.turret_flags &= ~(TURRET_HAS_CAMERA|TURRET_SAFETY|TURRET_ALERTS)
-
-
-/obj/item/attachable/shoulder_mount
- name = "experimental shoulder attachment point"
- desc = "A brand new advance in combat technology. This device, once attached to a firearm, will allow the firearm to be mounted onto any piece of modular armor. Once attached to the armor and activated, the gun will fire when the user chooses.\nOnce attached to the armor, right clicking the armor with an empty hand will select what click will fire the armor (middle, right, left). Right clicking with ammunition will reload the gun. Using the Unique Action keybind will perform the weapon's unique action only when the gun is active."
- icon = 'icons/mob/modular/shoulder_gun.dmi'
- icon_state = "shoulder_gun"
- slot = ATTACHMENT_SLOT_RAIL
- pixel_shift_x = 13
- ///What click the gun will fire on.
- var/fire_mode = "right"
- ///Blacklist of item types not allowed to be in the users hand to fire the gun.
- var/list/in_hand_items_blacklist = list(
- /obj/item/weapon/gun,
- /obj/item/weapon/shield,
- )
-
-/obj/item/attachable/shoulder_mount/on_attach(attaching_item, mob/user)
- . = ..()
- var/obj/item/weapon/gun/attaching_gun = attaching_item
- ENABLE_BITFIELD(flags_attach_features, ATTACH_BYPASS_ALLOWED_LIST|ATTACH_APPLY_ON_MOB)
- attaching_gun.AddElement(/datum/element/attachment, ATTACHMENT_SLOT_MODULE, icon, null, null, null, null, 0, 0, flags_attach_features, attach_delay, detach_delay, attach_skill, attach_skill_upper_threshold, attach_sound, attachment_layer = COLLAR_LAYER)
- RegisterSignal(attaching_gun, COMSIG_ATTACHMENT_ATTACHED, PROC_REF(handle_armor_attach))
- RegisterSignal(attaching_gun, COMSIG_ATTACHMENT_DETACHED, PROC_REF(handle_armor_detach))
-
-/obj/item/attachable/shoulder_mount/on_detach(detaching_item, mob/user)
- var/obj/item/weapon/gun/detaching_gun = detaching_item
- detaching_gun.RemoveElement(/datum/element/attachment, ATTACHMENT_SLOT_MODULE, icon, null, null, null, null, 0, 0, flags_attach_features, attach_delay, detach_delay, attach_skill, attach_skill_upper_threshold, attach_sound, attachment_layer = COLLAR_LAYER)
- DISABLE_BITFIELD(flags_attach_features, ATTACH_BYPASS_ALLOWED_LIST|ATTACH_APPLY_ON_MOB)
- UnregisterSignal(detaching_gun, list(COMSIG_ATTACHMENT_ATTACHED, COMSIG_ATTACHMENT_DETACHED))
- return ..()
-
-/obj/item/attachable/shoulder_mount/ui_action_click(mob/living/user, datum/action/item_action/action, obj/item/weapon/gun/G)
- if(!istype(master_gun.loc, /obj/item/clothing/suit/modular) || master_gun.loc.loc != user)
- return
- activate(user)
-
-/obj/item/attachable/shoulder_mount/activate(mob/user, turn_off)
- . = ..()
- if(CHECK_BITFIELD(master_gun.flags_item, IS_DEPLOYED))
- DISABLE_BITFIELD(master_gun.flags_item, IS_DEPLOYED)
- UnregisterSignal(user, COMSIG_MOB_MOUSEDOWN)
- master_gun.set_gun_user(null)
- . = FALSE
- else if(!turn_off)
- ENABLE_BITFIELD(master_gun.flags_item, IS_DEPLOYED)
- update_icon()
- master_gun.set_gun_user(user)
- RegisterSignal(user, COMSIG_MOB_MOUSEDOWN, PROC_REF(handle_firing))
- master_gun.RegisterSignal(user, COMSIG_MOB_MOUSEDRAG, TYPE_PROC_REF(/obj/item/weapon/gun, change_target))
- . = TRUE
- for(var/datum/action/item_action/toggle/action_to_update AS in actions)
- action_to_update.set_toggle(.)
- action_to_update.update_button_icon()
-
-///Handles the gun attaching to the armor.
-/obj/item/attachable/shoulder_mount/proc/handle_armor_attach(datum/source, attaching_item, mob/user)
- SIGNAL_HANDLER
- if(!istype(attaching_item, /obj/item/clothing/suit/modular))
- return
- master_gun.set_gun_user(null)
- RegisterSignal(attaching_item, COMSIG_ITEM_EQUIPPED, PROC_REF(handle_activations))
- RegisterSignal(attaching_item, COMSIG_ATOM_ATTACK_HAND_ALTERNATE, PROC_REF(switch_mode))
- RegisterSignal(attaching_item, COMSIG_ATOM_ATTACKBY_ALTERNATE, PROC_REF(reload_gun))
- RegisterSignal(master_gun, COMSIG_MOB_GUN_FIRED, PROC_REF(after_fire))
- master_gun.base_gun_icon = master_gun.placed_overlay_iconstate
- master_gun.update_icon()
-
-///Handles the gun detaching from the armor.
-/obj/item/attachable/shoulder_mount/proc/handle_armor_detach(datum/source, detaching_item, mob/user)
- SIGNAL_HANDLER
- if(!istype(detaching_item, /obj/item/clothing/suit/modular))
- return
- for(var/datum/action/action_to_delete AS in actions)
- if(action_to_delete.target != src)
- continue
- QDEL_NULL(action_to_delete)
- break
- update_icon()
- master_gun.base_gun_icon = initial(master_gun.icon_state)
- master_gun.update_icon()
- UnregisterSignal(detaching_item, list(COMSIG_ITEM_EQUIPPED, COMSIG_ATOM_ATTACK_HAND_ALTERNATE, COMSIG_ATOM_ATTACKBY_ALTERNATE))
- UnregisterSignal(master_gun, COMSIG_MOB_GUN_FIRED)
- UnregisterSignal(user, COMSIG_MOB_MOUSEDOWN)
-
-///Sets up the action.
-/obj/item/attachable/shoulder_mount/proc/handle_activations(datum/source, mob/equipper, slot)
- if(!isliving(equipper))
- return
- if(slot != SLOT_WEAR_SUIT)
- LAZYREMOVE(actions_types, /datum/action/item_action/toggle)
- var/datum/action/item_action/toggle/old_action = locate(/datum/action/item_action/toggle) in actions
- if(!old_action)
- return
- old_action.remove_action(equipper)
- actions = null
- else
- LAZYADD(actions_types, /datum/action/item_action/toggle)
- var/datum/action/item_action/toggle/new_action = new(src)
- new_action.give_action(equipper)
-
-///Performs the firing.
-/obj/item/attachable/shoulder_mount/proc/handle_firing(datum/source, atom/object, turf/location, control, params)
- SIGNAL_HANDLER
- var/list/modifiers = params2list(params)
- if(!modifiers[fire_mode])
- return
- if(!istype(master_gun.loc, /obj/item/clothing/suit/modular) || master_gun.loc.loc != source)
- return
- if(source.Adjacent(object))
- return
- var/mob/living/user = master_gun.gun_user
- if(user.incapacitated() || user.lying_angle || LAZYACCESS(user.do_actions, src) || !user.dextrous || (!CHECK_BITFIELD(master_gun.flags_gun_features, GUN_ALLOW_SYNTHETIC) && !CONFIG_GET(flag/allow_synthetic_gun_use) && issynth(user)))
- return
- var/active_hand = user.get_active_held_item()
- var/inactive_hand = user.get_inactive_held_item()
- for(var/item_blacklisted in in_hand_items_blacklist)
- if(!istype(active_hand, item_blacklisted) && !istype(inactive_hand, item_blacklisted))
- continue
- to_chat(user, span_warning("[src] beeps. Guns or shields in your hands are interfering with its targetting. Aborting."))
- return
- master_gun.start_fire(source, object, location, control, null, TRUE)
-
-///Switches click fire modes.
-/obj/item/attachable/shoulder_mount/proc/switch_mode(datum/source, mob/living/user)
- SIGNAL_HANDLER
- switch(fire_mode)
- if("right")
- fire_mode = "middle"
- to_chat(user, span_notice("[master_gun] will now fire on a 'middle click'."))
- if("middle")
- fire_mode = "left"
- to_chat(user, span_notice("[master_gun] will now fire on a 'left click'."))
- if("left")
- fire_mode = "right"
- to_chat(user, span_notice("[master_gun] will now fire on a 'right click'."))
-
-///Reloads the gun
-/obj/item/attachable/shoulder_mount/proc/reload_gun(datum/source, obj/item/attacking_item, mob/living/user)
- SIGNAL_HANDLER
- INVOKE_ASYNC(master_gun, TYPE_PROC_REF(/obj/item/weapon/gun, reload), attacking_item, user)
-
-///Performs the unique action after firing and checks to see if the user is still able to fire.
-/obj/item/attachable/shoulder_mount/proc/after_fire(datum/source, atom/target, obj/item/weapon/gun/fired_gun)
- SIGNAL_HANDLER
- if(CHECK_BITFIELD(master_gun.reciever_flags, AMMO_RECIEVER_REQUIRES_UNIQUE_ACTION))
- INVOKE_ASYNC(master_gun, TYPE_PROC_REF(/obj/item/weapon/gun, do_unique_action), master_gun.gun_user)
- var/mob/living/user = master_gun.gun_user
- var/active_hand = user.get_active_held_item()
- var/inactive_hand = user.get_inactive_held_item()
- for(var/item_blacklisted in in_hand_items_blacklist)
- if(!istype(active_hand, item_blacklisted) && !istype(inactive_hand, item_blacklisted))
- continue
- to_chat(user, span_warning("[src] beeps. Guns or shields in your hands are interfering with its targetting. Stopping fire."))
- master_gun.stop_fire()
- return
- if(!user.incapacitated() && !user.lying_angle && !LAZYACCESS(user.do_actions, src) && user.dextrous && (CHECK_BITFIELD(master_gun.flags_gun_features, GUN_ALLOW_SYNTHETIC) || CONFIG_GET(flag/allow_synthetic_gun_use) || !issynth(user)))
- return
- master_gun.stop_fire()
-
-/obj/item/attachable/flamer_nozzle
- name = "standard flamer nozzle"
- desc = "The standard flamer nozzle. This one fires a stream of fire for direct and accurate flames. Though not as area filling as its counterpart, this one excels at directed frontline combat."
- icon_state = "flame_directional"
- slot = ATTACHMENT_SLOT_FLAMER_NOZZLE
- attach_delay = 2 SECONDS
- detach_delay = 2 SECONDS
-
- ///This is pulled when the parent flamer fires, it determins how the parent flamers fire stream acts.
- var/stream_type = FLAMER_STREAM_STRAIGHT
-
- ///Modifier for burn level of attached flamer. Percentage based.
- var/burn_level_mod = 1
- ///Modifier for burn time of attached flamer. Percentage based.
- var/burn_time_mod = 1
- ///Range modifier of attached flamer. Numerically based.
- var/range_modifier = 0
- ///Damage multiplier for mobs caught in the initial stream of fire of the attached flamer.
- var/mob_flame_damage_mod = 1
-
-/obj/item/attachable/flamer_nozzle/on_attach(attaching_item, mob/user)
- . = ..()
- if(!istype(attaching_item, /obj/item/weapon/gun/flamer))
- return
- var/obj/item/weapon/gun/flamer/flamer = attaching_item
- flamer.burn_level_mod *= burn_level_mod
- flamer.burn_time_mod *= burn_time_mod
- flamer.flame_max_range += range_modifier
- flamer.mob_flame_damage_mod *= mob_flame_damage_mod
-
-/obj/item/attachable/flamer_nozzle/on_detach(attaching_item, mob/user)
- . = ..()
- if(!istype(attaching_item, /obj/item/weapon/gun/flamer))
- return
- var/obj/item/weapon/gun/flamer/flamer = attaching_item
- flamer.burn_level_mod /= burn_level_mod
- flamer.burn_time_mod /= burn_time_mod
- flamer.flame_max_range -= range_modifier
- flamer.mob_flame_damage_mod /= mob_flame_damage_mod
-
-/obj/item/attachable/flamer_nozzle/unremovable
- flags_attach_features = NONE
-
-/obj/item/attachable/flamer_nozzle/unremovable/invisible
- icon_state = null
-
-/obj/item/attachable/flamer_nozzle/wide
- name = "spray flamer nozzle"
- desc = "This specialized nozzle sprays the flames of an attached flamer in a much more broad way than the standard nozzle. It serves for wide area denial as opposed to offensive directional flaming."
- icon_state = "flame_wide"
- pixel_shift_y = 17
- stream_type = FLAMER_STREAM_CONE
- burn_time_mod = 0.3
-
-///Funny red wide nozzle that can fill entire screens with flames. Admeme only.
-/obj/item/attachable/flamer_nozzle/wide/red
- name = "red spray flamer nozzle"
- desc = "It is red, therefore its obviously more effective."
- icon_state = "flame_wide_red"
- range_modifier = 3
-
-///Flamer ammo is a normal ammo datum, which means we can shoot it if we want
-/obj/item/attachable/flamer_nozzle/long
- name = "extended flamer nozzle"
- icon_state = "flame_long"
- desc = "Rather than spreading the supplied fuel over an area, this nozzle launches a single fireball to ignite a target at range. Reduced volume per shot also means the next is ready quicker."
- stream_type = FLAMER_STREAM_RANGED
- delay_mod = -10
-
-/obj/item/attachable/flamer_nozzle/long/on_attach(attaching_item, mob/user)
- . = ..()
- if(!istype(attaching_item, /obj/item/weapon/gun/flamer))
- return
- var/obj/item/weapon/gun/flamer/flamer = attaching_item
- //Since we're firing more like a normal gun, we do need to use up rounds after firing
- flamer.reciever_flags &= ~AMMO_RECIEVER_DO_NOT_EMPTY_ROUNDS_AFTER_FIRE
-
-/obj/item/attachable/flamer_nozzle/long/on_detach(attaching_item, mob/user)
- . = ..()
- if(!istype(attaching_item, /obj/item/weapon/gun/flamer))
- return
- var/obj/item/weapon/gun/flamer/flamer = attaching_item
- if(initial(flamer.reciever_flags) & AMMO_RECIEVER_DO_NOT_EMPTY_ROUNDS_AFTER_FIRE)
- flamer.reciever_flags |= AMMO_RECIEVER_DO_NOT_EMPTY_ROUNDS_AFTER_FIRE
-
-///This is called when an attachment gun (src) attaches to a gun.
-/obj/item/weapon/gun/proc/on_attach(obj/item/attached_to, mob/user)
- if(!istype(attached_to, /obj/item/weapon/gun))
- return
- master_gun = attached_to
- master_gun.wield_delay += wield_delay_mod
- if(gun_user)
- UnregisterSignal(gun_user, list(COMSIG_MOB_MOUSEDOWN, COMSIG_MOB_MOUSEUP, COMSIG_ITEM_ZOOM, COMSIG_ITEM_UNZOOM, COMSIG_MOB_MOUSEDRAG, COMSIG_KB_RAILATTACHMENT, COMSIG_KB_UNDERRAILATTACHMENT, COMSIG_KB_UNLOADGUN, COMSIG_KB_FIREMODE, COMSIG_KB_GUN_SAFETY, COMSIG_KB_AUTOEJECT, COMSIG_KB_UNIQUEACTION, COMSIG_QDELETING, COMSIG_MOB_CLICK_RIGHT))
- var/datum/action/item_action/toggle/new_action = new /datum/action/item_action/toggle(src, master_gun)
- if(!isliving(user))
- return
- var/mob/living/living_user = user
- if(master_gun == living_user.get_inactive_held_item() || master_gun == living_user.get_active_held_item())
- new_action.give_action(living_user)
- attached_to:gunattachment = src
- activate(user)
- new_action.set_toggle(TRUE)
- new_action.update_button_icon()
- update_icon()
- RegisterSignal(master_gun, COMSIG_ITEM_REMOVED_INVENTORY, TYPE_PROC_REF(/obj/item/weapon/gun, drop_connected_mag))
-
-///This is called when an attachment gun (src) detaches from a gun.
-/obj/item/weapon/gun/proc/on_detach(obj/item/attached_to, mob/user)
- if(!istype(attached_to, /obj/item/weapon/gun))
- return
- for(var/datum/action/action_to_delete AS in master_gun.actions)
- if(action_to_delete.target != src)
- continue
- QDEL_NULL(action_to_delete)
- break
- icon_state = initial(icon_state)
- if(master_gun.active_attachable == src)
- master_gun.active_attachable = null
- master_gun.wield_delay -= wield_delay_mod
- UnregisterSignal(master_gun, COMSIG_ITEM_REMOVED_INVENTORY)
- master_gun = null
- attached_to:gunattachment = null
- update_icon()
-
-///This activates the weapon for use.
-/obj/item/weapon/gun/proc/activate(mob/user)
- if(master_gun.active_attachable)
- if(master_gun.active_attachable != src)
- master_gun.active_attachable.activate(user)
- return TRUE
- master_gun.active_attachable = null
- set_gun_user(null)
- to_chat(user, span_notice("You stop using [src]."))
- else
- master_gun.active_attachable = src
- set_gun_user(null)
- set_gun_user(master_gun.gun_user)
- to_chat(user, span_notice("You start using [src]."))
- for(var/datum/action/item_action/toggle/action AS in master_gun.actions)
- if(action.target != src )
- continue
- action.set_toggle(master_gun.active_attachable == src)
- action.update_button_icon()
- return TRUE
-
-///Called when the attachment is trying to be attached. If the attachment is allowed to go through, return TRUE.
-/obj/item/weapon/gun/proc/can_attach(obj/item/attaching_to, mob/attacher)
- return TRUE
-
-///Called when an attachment is attached to this gun (src).
-/obj/item/weapon/gun/proc/on_attachment_attach(obj/item/attaching_here, mob/attacher)
- return
-///Called when an attachment is detached from this gun (src).
-/obj/item/weapon/gun/proc/on_attachment_detach(obj/item/detaching_here, mob/attacher)
- return
diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm
index 22a0b45a190..f3add14296d 100644
--- a/code/modules/projectiles/guns/energy.dm
+++ b/code/modules/projectiles/guns/energy.dm
@@ -432,8 +432,6 @@
gun_firemode_list = list(GUN_FIREMODE_AUTOMATIC)
turret_flags = TURRET_INACCURATE
ammo_level_icon = "te"
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
@@ -537,16 +535,12 @@
fire_sound = 'sound/weapons/guns/fire/Laser Pistol Standard.ogg'
icon_state = "tep"
item_state = "tep"
- greyscale_config = null
- colorable_allowed = NONE
max_shots = 30 //codex stuff
ammo_datum_type = /datum/ammo/energy/lasgun/marine/pistol
ammo_level_icon = null
rounds_per_shot = 20
gun_firemode = GUN_FIREMODE_SEMIAUTO
gun_firemode_list = list(GUN_FIREMODE_SEMIAUTO)
- greyscale_config = /datum/greyscale_config/gun/pistol/tep
- colorable_allowed = PRESET_COLORS_ALLOWED
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
@@ -632,8 +626,6 @@
gun_firemode = GUN_FIREMODE_SEMIAUTO
gun_firemode_list = list(GUN_FIREMODE_SEMIAUTO)
ammo_level_icon = "te"
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
@@ -769,8 +761,6 @@
ammo_level_icon = "te"
icon_overlay_x_offset = -1
icon_overlay_y_offset = -3
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_64.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_64.dmi',
@@ -897,8 +887,6 @@
gun_firemode = GUN_FIREMODE_AUTOMATIC
gun_firemode_list = list(GUN_FIREMODE_AUTOMATIC)
ammo_level_icon = "te"
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
diff --git a/code/modules/projectiles/guns/pistols.dm b/code/modules/projectiles/guns/pistols.dm
index 71fb589f730..f6deafa5df1 100644
--- a/code/modules/projectiles/guns/pistols.dm
+++ b/code/modules/projectiles/guns/pistols.dm
@@ -53,8 +53,6 @@
max_shells = 21 //codex
fire_sound = 'sound/weapons/guns/fire/tgmc/kinetic/gun_p14.ogg'
reload_sound = 'sound/weapons/guns/interact/tp14_reload.ogg'
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
@@ -88,8 +86,6 @@
allowed_ammo_types = list(/obj/item/ammo_magazine/pistol/plasma_pistol)
type_of_casings = null
attachable_offset = list("muzzle_x" = 29, "muzzle_y" = 20,"rail_x" = 13, "rail_y" = 23, "under_x" = 19, "under_y" = 13, "stock_x" = 21, "stock_y" = 17)
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
@@ -187,8 +183,6 @@
unload_sound = 'sound/weapons/guns/interact/colt_unload.ogg'
reload_sound = 'sound/weapons/guns/interact/colt_reload.ogg'
cocked_sound = 'sound/weapons/guns/interact/colt_cocked.ogg'
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
diff --git a/code/modules/projectiles/guns/revolvers.dm b/code/modules/projectiles/guns/revolvers.dm
index a5bd9ac2bd1..8acc04cb84c 100644
--- a/code/modules/projectiles/guns/revolvers.dm
+++ b/code/modules/projectiles/guns/revolvers.dm
@@ -68,8 +68,6 @@
default_ammo_type = /obj/item/ammo_magazine/revolver/standard_revolver
allowed_ammo_types = list(/obj/item/ammo_magazine/revolver/standard_revolver)
force = 8
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
@@ -410,7 +408,6 @@
icon = 'icons/Marine/gun64.dmi'
icon_state = "coltrifle"
item_state = "coltrifle"
- greyscale_config = null
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
diff --git a/code/modules/projectiles/guns/rifles.dm b/code/modules/projectiles/guns/rifles.dm
index bed91d6f16c..c2276b8e133 100644
--- a/code/modules/projectiles/guns/rifles.dm
+++ b/code/modules/projectiles/guns/rifles.dm
@@ -43,8 +43,6 @@
force = 20
default_ammo_type = /obj/item/ammo_magazine/rifle/standard_carbine
allowed_ammo_types = list(/obj/item/ammo_magazine/rifle/standard_carbine)
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
@@ -137,8 +135,6 @@
force = 20
default_ammo_type = /obj/item/ammo_magazine/rifle/standard_assaultrifle
allowed_ammo_types = list(/obj/item/ammo_magazine/rifle/standard_assaultrifle)
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
@@ -219,8 +215,6 @@
icon = 'icons/Marine/gun64.dmi'
icon_state = "t37"
item_state = "t37"
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_64.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_64.dmi',
@@ -918,8 +912,6 @@
reload_sound = 'sound/weapons/guns/machineguns/MG-42/MG42_clipin.ogg'
default_ammo_type = /obj/item/ammo_magazine/standard_lmg
allowed_ammo_types = list(/obj/item/ammo_magazine/standard_lmg)
- greyscale_config = null
- colorable_allowed = NONE
attachable_allowed = list(
/obj/item/attachable/stock/t42stock,
/obj/item/attachable/reddot,
@@ -979,8 +971,6 @@
icon_state = "t60"
item_state = "t60"
fire_animation = "loaded_fire"
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_64.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_64.dmi',
@@ -1242,8 +1232,6 @@
max_shells = 12 //codex
force = 20
default_ammo_type = /obj/item/ammo_magazine/rifle/tx15_slug
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
@@ -1313,8 +1301,6 @@
dry_fire_sound = 'sound/weapons/guns/fire/m41a_empty.ogg'
unload_sound = 'sound/weapons/guns/interact/T42_unload.ogg'
reload_sound = 'sound/weapons/guns/interact/T42_reload.ogg'
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
@@ -1501,8 +1487,6 @@
icon = 'icons/Marine/gun64.dmi'
icon_state = "tl127"
item_state = "tl127"
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_64.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_64.dmi',
@@ -1587,8 +1571,6 @@
max_shells = 20 //codex
default_ammo_type = /obj/item/ammo_magazine/rifle/autosniper
allowed_ammo_types = list(/obj/item/ammo_magazine/rifle/autosniper)
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
@@ -1642,8 +1624,6 @@
cocked_sound = 'sound/weapons/guns/rifles/AR-11/AR11_boltpull.ogg'
default_ammo_type = /obj/item/ammo_magazine/rifle/tx11
allowed_ammo_types = list(/obj/item/ammo_magazine/rifle/tx11)
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
@@ -1718,8 +1698,6 @@
force = 20
default_ammo_type = /obj/item/ammo_magazine/rifle/standard_skirmishrifle
allowed_ammo_types = list(/obj/item/ammo_magazine/rifle/standard_skirmishrifle)
- greyscale_config = null
- colorable_allowed = NONE
allowed_ammo_types = list(
/obj/item/ammo_magazine/rifle/standard_skirmishrifle,
/obj/item/ammo_magazine/rifle/standard_skirmishrifle/extended,
diff --git a/code/modules/projectiles/guns/shotguns.dm b/code/modules/projectiles/guns/shotguns.dm
index f91d76fe048..8f1d33f5f3a 100644
--- a/code/modules/projectiles/guns/shotguns.dm
+++ b/code/modules/projectiles/guns/shotguns.dm
@@ -686,8 +686,6 @@ RU TGMC EDIT */
cocked_sound = 'sound/weapons/guns/shotgun/SH-35/SH35_pump.ogg'
opened_sound = 'sound/weapons/guns/shotgun/SH-35/SH35_pump.ogg'
max_chamber_items = 8
- greyscale_config = null
- colorable_allowed = NONE
item_icons = list(
slot_l_hand_str = 'icons/mob/items_lefthand_1.dmi',
slot_r_hand_str = 'icons/mob/items_righthand_1.dmi',
diff --git a/code/modules/projectiles/guns/smgs.dm b/code/modules/projectiles/guns/smgs.dm
index 47dcae1828c..b4e8280dfaa 100644
--- a/code/modules/projectiles/guns/smgs.dm
+++ b/code/modules/projectiles/guns/smgs.dm
@@ -125,14 +125,6 @@
type_of_casings = null
default_ammo_type = /obj/item/ammo_magazine/smg/standard_smg
allowed_ammo_types = list(/obj/item/ammo_magazine/smg/standard_smg)
- greyscale_config = null
- colorable_allowed = NONE
- item_icons = list(
- slot_l_hand_str = /datum/greyscale_config/gun_inhand/t90,
- slot_r_hand_str = /datum/greyscale_config/gun_inhand/r_hand/t90,
- slot_back_str = /datum/greyscale_config/worn_gun/t90,
- slot_s_store_str = /datum/greyscale_config/worn_gun/suit/t90,
- )
attachable_allowed = list(
/obj/item/attachable/suppressor,
/obj/item/attachable/reddot,
diff --git a/tgmc.dme b/tgmc.dme
index c6ffa4c1601..538661d656e 100644
--- a/tgmc.dme
+++ b/tgmc.dme
@@ -1863,15 +1863,39 @@
#include "code\modules\predator\yautja\weapons\one_handed.dm"
#include "code\modules\predator\yautja\weapons\ranged.dm"
#include "code\modules\predator\yautja\weapons\two_handed.dm"
-#include "code\modules\projectiles\ammo_datums.dm"
+#include "code\modules\projectiles\ammo_datums\_ammo_datums.dm"
+#include "code\modules\projectiles\ammo_datums\artillery.dm"
+#include "code\modules\projectiles\ammo_datums\energy.dm"
+#include "code\modules\projectiles\ammo_datums\flamethrower.dm"
+#include "code\modules\projectiles\ammo_datums\mecha.dm"
+#include "code\modules\projectiles\ammo_datums\misc.dm"
+#include "code\modules\projectiles\ammo_datums\rocket.dm"
+#include "code\modules\projectiles\ammo_datums\shrapnel.dm"
+#include "code\modules\projectiles\ammo_datums\xeno.dm"
+#include "code\modules\projectiles\ammo_datums\yautja.dm"
+#include "code\modules\projectiles\ammo_datums\bullet/_bullet.dm"
+#include "code\modules\projectiles\ammo_datums\bullet/machinegun.dm"
+#include "code\modules\projectiles\ammo_datums\bullet/pistol.dm"
+#include "code\modules\projectiles\ammo_datums\bullet/revolver.dm"
+#include "code\modules\projectiles\ammo_datums\bullet/rifle.dm"
+#include "code\modules\projectiles\ammo_datums\bullet/shotgun.dm"
+#include "code\modules\projectiles\ammo_datums\bullet/sniper.dm"
+#include "code\modules\projectiles\ammo_datums\bullet/submachinegun.dm"
#include "code\modules\projectiles\ammunition.dm"
-#include "code\modules\projectiles\gun_attachables.dm"
#include "code\modules\projectiles\gun_helpers.dm"
#include "code\modules\projectiles\gun_system.dm"
#include "code\modules\projectiles\mounted.dm"
#include "code\modules\projectiles\projectile.dm"
#include "code\modules\projectiles\sentries.dm"
#include "code\modules\projectiles\tracer.dm"
+#include "code\modules\projectiles\attachables\_attachable.dm"
+#include "code\modules\projectiles\attachables\flamer.dm"
+#include "code\modules\projectiles\attachables\foldable.dm"
+#include "code\modules\projectiles\attachables\muzzle.dm"
+#include "code\modules\projectiles\attachables\rail.dm"
+#include "code\modules\projectiles\attachables\scope.dm"
+#include "code\modules\projectiles\attachables\stock.dm"
+#include "code\modules\projectiles\attachables\underbarrel.dm"
#include "code\modules\projectiles\guns\energy.dm"
#include "code\modules\projectiles\guns\flamer.dm"
#include "code\modules\projectiles\guns\grenade_launchers.dm"