Skip to content

Commit

Permalink
Merge branch 'master' into dccbuff
Browse files Browse the repository at this point in the history
  • Loading branch information
HumiliatedGoblin committed Apr 6, 2024
2 parents 8f04aad + 00df7a1 commit 9ff38fe
Show file tree
Hide file tree
Showing 31 changed files with 373 additions and 104 deletions.
2 changes: 2 additions & 0 deletions code/__DEFINES/weapon_stats.dm
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ As such, don't expect any values assigned to common firearms to even consider ho
//How many ticks you have to wait between firing. Burst delay uses the same variable!
*/

#define FIRE_DELAY_TIER_AMR 30
#define FIRE_DELAY_TIER_VULTURE 20
#define FIRE_DELAY_TIER_SNIPER 15
#define FIRE_DELAY_TIER_1 12
#define FIRE_DELAY_TIER_2 10
#define FIRE_DELAY_TIER_3 9
Expand Down
2 changes: 2 additions & 0 deletions code/_globalvars/global_lists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ GLOBAL_LIST_EMPTY(timelocks)
GLOBAL_LIST_INIT(available_specialist_sets, list(
"Scout Set",
"Sniper Set",
"Anti-materiel Sniper Set",
"Demolitionist Set",
"Heavy Grenadier Set",
"Pyro Set"
Expand All @@ -502,6 +503,7 @@ GLOBAL_LIST_INIT(available_specialist_kit_boxes, list(
"Sniper" = 2,
"Scout" = 2,
"Demo" = 2,
"Anti-materiel Sniper" = 2,
))

/proc/init_global_referenced_datums()
Expand Down
1 change: 1 addition & 0 deletions code/datums/ammo/ammo.dm
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@
P.generate_bullet(GLOB.ammo_list[bonus_projectiles_type]) //No bonus damage or anything.
P.accuracy = round(P.accuracy * original_P.accuracy/initial(original_P.accuracy)) //if the gun changes the accuracy of the main projectile, it also affects the bonus ones.
original_P.give_bullet_traits(P)
P.bonus_projectile_check = 2 //It's a bonus projectile!

var/total_scatter_angle = P.scatter
final_angle += rand(-total_scatter_angle, total_scatter_angle)
Expand Down
111 changes: 98 additions & 13 deletions code/datums/ammo/bullet/sniper.dm
Original file line number Diff line number Diff line change
Expand Up @@ -107,19 +107,104 @@
damage = 125
shell_speed = AMMO_SPEED_TIER_6

/datum/ammo/bullet/sniper/anti_materiel/on_hit_mob(mob/M,obj/projectile/P)
if((P.projectile_flags & PROJECTILE_BULLSEYE) && M == P.original)
var/mob/living/L = M
var/size_damage_mod = 0.8
if(isxeno(M))
var/mob/living/carbon/xenomorph/target = M
if(target.mob_size >= MOB_SIZE_XENO)
size_damage_mod += 0.6
if(target.mob_size >= MOB_SIZE_BIG)
size_damage_mod += 0.6
L.apply_armoured_damage(damage*size_damage_mod, ARMOR_BULLET, BRUTE, null, penetration)
// 180% damage to all targets (225), 240% (300) against non-Runner xenos, and 300% against Big xenos (375). -Kaga
to_chat(P.firer, SPAN_WARNING("Bullseye!"))
/datum/ammo/bullet/sniper/anti_materiel/on_hit_mob(mob/target_mob,obj/projectile/aimed_projectile)

var/mob/living/living_target = target_mob

if((aimed_projectile.projectile_flags & PROJECTILE_BULLSEYE) && target_mob == aimed_projectile.original)

var/amr_counter = 0
var/datum/weakref/old_target = null // This is used to let xenos know when they're no longer targeted.

var/mob/living/carbon/human/human_firer
var/image/focused_fire_marker_temp = image('icons/mob/hud/hud.dmi', target_mob, "hudeye")

if(istype(aimed_projectile.firer, /mob/living/carbon/human)) // Preps the Focused Fire marker.
human_firer = aimed_projectile.firer
focused_fire_marker_temp.color = human_firer.assigned_squad?.chat_color

if(target_mob.icon_size > world.icon_size) // Centers marker on their tile.
focused_fire_marker_temp.pixel_x = (target_mob.icon_size / 4)

if(istype(aimed_projectile.shot_from, /obj/item/weapon/gun/rifle/sniper/XM43E1)) // Calculates the Focus Counter.
var/obj/item/weapon/gun/rifle/sniper/XM43E1/amr = aimed_projectile.shot_from

old_target = amr.focused_fire_target

if(target_mob == (amr.focused_fire_target?.resolve()))
if(amr.focused_fire_counter < 2) // Can stack up to twice.
amr.focused_fire_counter += 1
else
amr.focused_fire_counter = 2
else // If it's a new target
amr.focused_fire_counter = 0 // Stacks to 0
if(human_firer && !(target_mob.is_dead()))
human_firer.client?.images -= human_firer.focused_fire_marker // Remove old marker
qdel(human_firer.focused_fire_marker)
human_firer.focused_fire_marker = focused_fire_marker_temp // Store new marker ref
human_firer.client?.images += focused_fire_marker_temp // Add new marker

amr_counter = amr.focused_fire_counter + 1
amr.focused_fire_target = WEAKREF(target_mob)

var/size_damage_mod = 0.8 // 1.8x vs Non-Xenos (225)
var/size_current_health_damage = 0 // % Current Health calculation, only used for Xeno calculations at the moment.
var/focused_fire_active = 0 // Whether to try and use focused fire calculations or not, for that kind of target.

if(isxeno(target_mob))
var/mob/living/carbon/xenomorph/target = target_mob
size_damage_mod -= 0.2 // Down to 1.6x damage, 200.
size_current_health_damage = 0.1 // 1.6x Damage + 10% current health (200 + 10%, 223 vs Runners)

if(target.mob_size >= MOB_SIZE_XENO && (target.caste_type != XENO_CASTE_DEFENDER))
size_current_health_damage += 0.1 // 1.6x Damage + 20% current health
focused_fire_active = 1 // Focus Fire Required. Only deals 50% bonus damage on a first Aimed Shot, then 75%, then 100%. Resets with a successful aimed shot on another target.

if(target.mob_size >= MOB_SIZE_BIG && (target.caste_type != XENO_CASTE_DEFENDER))
size_damage_mod -= 0.6 // Down to 1x Damage.
size_current_health_damage += 0.1 // 1x Damage + 30% current health.
focused_fire_active = 1
// Most T3s have around 650 to 700 HP, meaning the health modifier grants a MAXIMUM of around 195-210 damage for a total max of 320-335. This is fully focused (3 shots) and at max HP.
// Queen takes around 275 at max health and unfocused, 425 fully focused. Defender only takes 200 damage, even while fortified, but still causes falloff like a Big Xeno.
// At low health, does little more than a normal shot. Does WORSE than a normal shot if unfocused and hitting through blockers, all of which stack to reduce it.

var/final_xeno_damage = ((damage * size_damage_mod) + ((target.health + damage) * size_current_health_damage))

if(focused_fire_active && amr_counter) // If this is a target that needs to be focus-fired and the gun supports it, reduce bonus damage to 50%, then 75%, then 100%
// If amr_counter is 0, then the gun likely doesn't have the tracker functions, so skip this and deal normal damage.
final_xeno_damage *= (0.25 + (0.25 * amr_counter))

living_target.apply_armoured_damage((final_xeno_damage), ARMOR_BULLET, BRUTE, null, penetration)

else
living_target.apply_armoured_damage((damage*size_damage_mod), ARMOR_BULLET, BRUTE, null, penetration)

// Base 1.8x damage to non-xeno targets (225), 1.6x + 10% current against Runners and Defenders (223), 1.6x + 20% current health against most non-Runner xenos, and +30% current health against Big xenos. -Kaga
// This applies after pen reductions. After hitting 1 other thing, it deals 80% damage, or 40% after hitting a dense wall or big xeno.

if((focused_fire_active || isxeno(target_mob)) && !(target_mob.is_dead()))
switch(amr_counter)
if(1)
to_chat(aimed_projectile.firer, SPAN_WARNING("One hit! You begin to carefully track the target's movements."))
if(isxeno(target_mob) && isxeno(old_target?.resolve()))
var/mob/living/carbon/xenomorph/old_xeno = old_target.resolve()
var/mob/living/carbon/xenomorph/new_xeno = target_mob
if((old_xeno.hive == new_xeno.hive) && !(old_xeno.stat)) // Must be in same hive and conscious
to_chat(old_xeno,SPAN_XENOLEADER("The feeling of looming danger fades as we sense that another sister has been targeted instead."))
if(2)
to_chat(aimed_projectile.firer, SPAN_WARNING("Two hits! You're starting to get a good read on the target's patterns."))
if(3)
to_chat(aimed_projectile.firer, SPAN_WARNING("Bullseye! You're fully focused on the target."))
else
to_chat(aimed_projectile.firer, SPAN_WARNING("Bullseye!"))
else
to_chat(aimed_projectile.firer, SPAN_WARNING("Bullseye!"))

/datum/ammo/bullet/sniper/anti_materiel/set_bullet_traits()
. = ..()
LAZYADD(traits_to_give, list(
BULLET_TRAIT_ENTRY(/datum/element/bullet_trait_penetrating/weak)
))

/datum/ammo/bullet/sniper/anti_materiel/vulture
damage = 400 // Fully intended to vaporize anything smaller than a mini cooper
Expand Down
50 changes: 25 additions & 25 deletions code/datums/elements/bullet_trait/damage_boost.dm
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,10 @@ GLOBAL_LIST_INIT(damage_boost_vehicles, typecacheof(/obj/vehicle/multitile))
/// A typecache of objs or turfs that, upon being hit, boost the damage of the attached projectile
var/list/damage_boosted_atoms

//vars for dealing with interaction issues with the Penetrating trait
var/boosted_hits
var/last_damage_mult

//allows for nuance in Breaching-Resistant interactions
var/active_damage_mult
var/atom_type

//var for dealing with bonus projectiles
var/bonus_projectile_check

/**
* vars:
* * damage_mult - the damage multiplier to be applied if the bullet hits an atom whose type is in `breaching_objs`
Expand All @@ -51,11 +44,8 @@ GLOBAL_LIST_INIT(damage_boost_vehicles, typecacheof(/obj/vehicle/multitile))

src.damage_mult = damage_mult
src.damage_boosted_atoms = damage_boosted_atoms
src.boosted_hits = 0
src.last_damage_mult = 1
src.active_damage_mult = 1
src.atom_type = 0
src.bonus_projectile_check = 0

RegisterSignal(target, list(
COMSIG_BULLET_PRE_HANDLE_OBJ,
Expand All @@ -68,17 +58,17 @@ GLOBAL_LIST_INIT(damage_boost_vehicles, typecacheof(/obj/vehicle/multitile))
//add more cases for other interactions (switch doesn't seem to work with istype)
else return 0

/datum/element/bullet_trait_damage_boost/proc/handle_bullet(obj/projectile/P, atom/A)
/datum/element/bullet_trait_damage_boost/proc/handle_bullet(obj/projectile/boosted_projectile, atom/hit_atom)
SIGNAL_HANDLER

atom_type = check_type(A)
atom_type = check_type(hit_atom)

switch(atom_type)
if("door")
var/obj/structure/machinery/door/D = A
if(D.masterkey_resist)
if(D.masterkey_mod)
active_damage_mult = damage_mult * D.masterkey_mod
var/obj/structure/machinery/door/hit_door = hit_atom
if(hit_door.masterkey_resist)
if(hit_door.masterkey_mod)
active_damage_mult = damage_mult * hit_door.masterkey_mod
else
active_damage_mult = 1 //no bonus damage
else
Expand All @@ -87,12 +77,22 @@ GLOBAL_LIST_INIT(damage_boost_vehicles, typecacheof(/obj/vehicle/multitile))
else
active_damage_mult = damage_mult

if(boosted_hits > 0)
if(bonus_projectile_check == P.damage)
P.damage = P.damage / last_damage_mult
boosted_hits--
if(damage_boosted_atoms[A.type])
P.damage = round(P.damage * active_damage_mult)
last_damage_mult = active_damage_mult
boosted_hits++
bonus_projectile_check = P.damage

if(boosted_projectile.damage_boosted && ((boosted_projectile.last_atom_signaled?.resolve()) != hit_atom) && (!boosted_projectile.bonus_projectile_check))
//If this is after a boosted hit, the last atom that procced this isn't the same as the current target, and this isn't a bonus projectile sharing the same damage_boost
if(!boosted_projectile.last_damage_mult) //Make sure stored mult isn't 0
boosted_projectile.last_damage_mult = 1

boosted_projectile.damage = boosted_projectile.damage / boosted_projectile.last_damage_mult //Reduce the damage back to normal
boosted_projectile.damage_boosted-- //Mark that damage has been returned to normal.

if(damage_boosted_atoms[hit_atom.type]) //If hitting a valid atom for damage boost
boosted_projectile.damage = round(boosted_projectile.damage * active_damage_mult) //Modify Damage by multiplier

if (active_damage_mult)
boosted_projectile.last_damage_mult = active_damage_mult //Save multiplier for next check
else
boosted_projectile.last_damage_mult = 1

boosted_projectile.damage_boosted++ //Mark that a boosted hit occurred.
boosted_projectile.last_atom_signaled = WEAKREF(hit_atom) //Save the current triggering atom to the projectile
60 changes: 60 additions & 0 deletions code/datums/elements/bullet_trait/penetrating/weak.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/datum/element/bullet_trait_penetrating/weak
// Generic bullet trait vars
element_flags = ELEMENT_DETACH|ELEMENT_BESPOKE
id_arg_index = 4

/// For each thing this hits, how much damage it loses normally. This can be modified by what it penetrates later.
var/damage_percent_lost_per_hit = 20
// XM43E1 AMR: First target takes full damage, each subsequent target takes at least 20% less damage (increased for large mobs and dense turfs), 25 from base 125 damage.

/// For each thing this hits, how much distance it loses normally.
distance_loss_per_hit = 4
// XM43E1 AMR: Hits 7 things at most, at point blank, with no additional modifiers. This greatly increases at actual sniping ranges.

/// How many times more effective turfs are at slowing down the projectile normally, reducing both range and damage.
var/turf_hit_slow_mult = 3
// XM43E1 AMR: Unable to hit anything through more than 2 walls, less at maximum ranges. Pens 2 walls at 8 tiles or less, 1 at 20 tiles or less, and can't wallbang through normal walls at maximum range.
// Also loses 75 damage with each normal wall pen.

/datum/element/bullet_trait_penetrating/weak/Attach(datum/target, distance_loss_per_hit = 4, damage_percent_lost_per_hit = 20, turf_hit_slow_mult = 3)
. = ..()
if(. == ELEMENT_INCOMPATIBLE)
return

src.damage_percent_lost_per_hit = damage_percent_lost_per_hit
src.turf_hit_slow_mult = turf_hit_slow_mult

/datum/element/bullet_trait_penetrating/weak/handle_passthrough_movables(obj/projectile/bullet, atom/movable/hit_movable, did_hit)
if(did_hit)
var/slow_mult = 1
if(ismob(hit_movable))
var/mob/mob = hit_movable
if(mob.mob_size >= MOB_SIZE_BIG) // Big Xenos (including fortified Defender) can soak hits and greatly reduce penetration.
slow_mult = 2 // 8 tiles of range lost per Big hit. At point blank, this comes out to only 3 targets. At sniping ranges, even a single one can stop the bullet dead.

bullet.distance_travelled += (distance_loss_per_hit * slow_mult)

bullet.damage -= (damage_percent_lost_per_hit * slow_mult)

return COMPONENT_BULLET_PASS_THROUGH


/datum/element/bullet_trait_penetrating/weak/handle_passthrough_turf(obj/projectile/bullet, turf/closed/wall/hit_wall)
var/slow_mult = turf_hit_slow_mult

// Better penetration against Membranes to still be able to counter Boilers at most ranges. Still loses 4 tiles of range and 25 damage per.
if(istype(hit_wall, /turf/closed/wall/resin/membrane))
if(istype(hit_wall, /turf/closed/wall/resin/membrane/thick))
slow_mult = 1.5
else
slow_mult = 1

bullet.distance_travelled += (distance_loss_per_hit * slow_mult)

bullet.damage *= (1 - (damage_percent_lost_per_hit * slow_mult * 0.01))

if(!istype(hit_wall))
return COMPONENT_BULLET_PASS_THROUGH

if(!hit_wall.hull)
return COMPONENT_BULLET_PASS_THROUGH
4 changes: 2 additions & 2 deletions code/datums/emergency_calls/cmb.dm
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@

print_backstory(mob)

addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(to_chat), mob, SPAN_BOLD("Objectives:</b> [objectives]")), 1 SECONDS)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), mob, SPAN_BOLD("Objectives:</b> [objectives]")), 1 SECONDS)


/datum/emergency_call/cmb/print_backstory(mob/living/carbon/human/M)
Expand Down Expand Up @@ -160,7 +160,7 @@

print_backstory(mob)

addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(to_chat), mob, SPAN_BOLD("Objectives:</b> [objectives]")), 1 SECONDS)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), mob, SPAN_BOLD("Objectives:</b> [objectives]")), 1 SECONDS)


/datum/emergency_call/cmb/anchorpoint/print_backstory(mob/living/carbon/human/M)
Expand Down
4 changes: 2 additions & 2 deletions code/datums/emergency_calls/inspection.dm
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@

print_backstory(mob)

addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(to_chat), mob, SPAN_BOLD("Objectives:</b> [objectives]")), 1 SECONDS)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), mob, SPAN_BOLD("Objectives:</b> [objectives]")), 1 SECONDS)


/datum/emergency_call/inspection_cmb/print_backstory(mob/living/carbon/human/M)
Expand Down Expand Up @@ -341,4 +341,4 @@

print_backstory(mob)

addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(to_chat), mob, SPAN_BOLD("Objectives:</b> [objectives]")), 1 SECONDS)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), mob, SPAN_BOLD("Objectives:</b> [objectives]")), 1 SECONDS)
2 changes: 1 addition & 1 deletion code/datums/emergency_calls/xeno_cultists.dm
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,4 @@
arm_equipment(H, /datum/equipment_preset/other/xeno_cultist, TRUE, TRUE)
print_backstory(H)

addtimer(CALLBACK(GLOBAL_PROC, PROC_REF(to_chat), H, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(to_chat), H, SPAN_BOLD("Objectives: [objectives]")), 1 SECONDS)
8 changes: 3 additions & 5 deletions code/datums/supply_packs/spec_ammo.dm
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,6 @@
containername = "M42A Incendiary Magazine Crate"
group = "Weapons Specialist Ammo"

//XM43E1 - Disabled during testing per request.
/*
/datum/supply_packs/ammo_amr_marksman
name = "XM43E1 anti-materiel rifle marksman magazines crate (x5)"
contains = list(
Expand All @@ -122,9 +120,9 @@
)
cost = 30
containertype = /obj/structure/closet/crate/ammo
containername = "XM43E1 Anti-Materiel Magazine Crate"
group = "Specialist Ammo"
*/
containername = "XM43E1 Marksman Magazine Crate"
group = "Weapons Specialist Ammo"

//M4RA

/datum/supply_packs/ammo_scout_mix
Expand Down
1 change: 1 addition & 0 deletions code/game/machinery/cryopod.dm
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ GLOBAL_LIST_INIT(frozen_items, list(SQUAD_MARINE_1 = list(), SQUAD_MARINE_2 = li
set_name = "Scout Set"
if(SKILL_SPEC_SNIPER)
set_name = "Sniper Set"
GLOB.available_specialist_sets += "Anti-materiel Sniper Set"

if(set_name && !GLOB.available_specialist_sets.Find(set_name))
GLOB.available_specialist_sets += set_name
Expand Down
5 changes: 5 additions & 0 deletions code/game/machinery/vending/cm_vending.dm
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,11 @@ GLOBAL_LIST_EMPTY(vending_products)
if("Sniper Set")
user.skills.set_skill(SKILL_SPEC_WEAPONS, SKILL_SPEC_SNIPER)
specialist_assignment = "Sniper"
GLOB.available_specialist_sets -= "Anti-materiel Sniper Set"
if("Anti-materiel Sniper Set")
user.skills.set_skill(SKILL_SPEC_WEAPONS, SKILL_SPEC_SNIPER)
specialist_assignment = "Heavy Sniper"
GLOB.available_specialist_sets -= "Sniper Set"
if("Demolitionist Set")
user.skills.set_skill(SKILL_SPEC_WEAPONS, SKILL_SPEC_ROCKET)
specialist_assignment = "Demo"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_spec, list(
list("Pyro Set", 0, /obj/item/storage/box/spec/pyro, MARINE_CAN_BUY_ESSENTIALS, VENDOR_ITEM_REGULAR),
list("Scout Set", 0, /obj/item/storage/box/spec/scout, MARINE_CAN_BUY_ESSENTIALS, VENDOR_ITEM_REGULAR),
list("Sniper Set", 0, /obj/item/storage/box/spec/sniper, MARINE_CAN_BUY_ESSENTIALS, VENDOR_ITEM_RECOMMENDED),
list("Anti-materiel Sniper Set", 0, /obj/item/storage/box/spec/sniper/anti_materiel, MARINE_CAN_BUY_ESSENTIALS, VENDOR_ITEM_RECOMMENDED),

list("EXTRA SCOUT AMMUNITION", 0, null, null, null),
list("A19 High Velocity Impact Magazine (10x24mm)", 40, /obj/item/ammo_magazine/rifle/m4ra/custom/impact, null, VENDOR_ITEM_REGULAR),
Expand All @@ -17,6 +18,7 @@ GLOBAL_LIST_INIT(cm_vending_gear_spec, list(
list("M42A Flak Magazine (10x28mm)", 40, /obj/item/ammo_magazine/sniper/flak, null, VENDOR_ITEM_REGULAR),
list("M42A Incendiary Magazine (10x28mm)", 40, /obj/item/ammo_magazine/sniper/incendiary, null, VENDOR_ITEM_REGULAR),
list("M42A Marksman Magazine (10x28mm Caseless)", 40, /obj/item/ammo_magazine/sniper, null, VENDOR_ITEM_REGULAR),
list("XM43E1 Marksman Magazine (10x99mm Caseless)", 40, /obj/item/ammo_magazine/sniper/anti_materiel, null, VENDOR_ITEM_REGULAR),

list("EXTRA DEMOLITIONIST AMMUNITION", 0, null, null, null),
list("84mm Anti-Armor Rocket", 40, /obj/item/ammo_magazine/rocket/ap, null, VENDOR_ITEM_REGULAR),
Expand Down
Loading

0 comments on commit 9ff38fe

Please sign in to comment.