Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Vehicle autofire #4959

Merged
merged 22 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
441 changes: 288 additions & 153 deletions code/modules/vehicles/hardpoints/hardpoint.dm

Large diffs are not rendered by default.

24 changes: 18 additions & 6 deletions code/modules/vehicles/hardpoints/holder/holder.dm
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,21 @@
for(var/obj/item/hardpoint/H in hardpoints)
H.take_damage(damage)

/obj/item/hardpoint/holder/on_install(obj/vehicle/multitile/V)
for(var/obj/item/hardpoint/HP in hardpoints)
HP.owner = V
return
/obj/item/hardpoint/holder/on_install(obj/vehicle/multitile/vehicle)
..()
if(!vehicle) //in loose holder
return
for(var/obj/item/hardpoint/hardpoint in hardpoints)
hardpoint.owner = vehicle
hardpoint.on_install(vehicle)

/obj/item/hardpoint/holder/on_uninstall(obj/vehicle/multitile/vehicle)
if(!vehicle) //in loose holder
return
for(var/obj/item/hardpoint/hardpoint in hardpoints)
hardpoint.on_uninstall(vehicle)
hardpoint.owner = null
..()

/obj/item/hardpoint/holder/proc/can_install(obj/item/hardpoint/H)
// Can only have 1 hardpoint of each slot type
Expand Down Expand Up @@ -121,16 +132,17 @@
H.forceMove(src)
LAZYADD(hardpoints, H)

H.on_install(owner)
H.rotate(turning_angle(H.dir, dir))

/obj/item/hardpoint/holder/proc/remove_hardpoint(obj/item/hardpoint/H, turf/uninstall_to)
if(!hardpoints)
return
hardpoints -= H
H.forceMove(uninstall_to ? uninstall_to : get_turf(src))

H.on_uninstall(owner)
H.reset_rotation()

hardpoints -= H
H.owner = null

if(H.health <= 0)
Expand Down
46 changes: 18 additions & 28 deletions code/modules/vehicles/hardpoints/holder/tank_turret.dm
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@
density = TRUE //come on, it's huge

activatable = TRUE
cooldown = 150
accuracy = 0.8

ammo = new /obj/item/ammo_magazine/hardpoint/turret_smoke
max_clips = 2
Expand Down Expand Up @@ -60,6 +58,15 @@
// Used during the windup
var/rotating = FALSE

scatter = 4
gun_firemode = GUN_FIREMODE_BURSTFIRE
gun_firemode_list = list(
GUN_FIREMODE_BURSTFIRE,
)
burst_amount = 2
burst_delay = 1.0 SECONDS
extra_delay = 13.0 SECONDS

/obj/item/hardpoint/holder/tank_turret/update_icon()
var/broken = (health <= 0)
icon_state = "tank_turret_[broken]"
Expand Down Expand Up @@ -182,12 +189,7 @@
user.client.pixel_x = -1 * AM.view_tile_offset * 32
user.client.pixel_y = 0

/obj/item/hardpoint/holder/tank_turret/fire(mob/user, atom/A)
if(ammo.current_rounds <= 0)
return

next_use = world.time + cooldown

/obj/item/hardpoint/holder/tank_turret/try_fire(atom/target, mob/living/user, params)
var/turf/L
var/turf/R
switch(owner.dir)
Expand All @@ -204,26 +206,14 @@
L = locate(owner.x - 4, owner.y + 2, owner.z)
R = locate(owner.x - 4, owner.y - 2, owner.z)

if(LAZYLEN(activation_sounds))
playsound(get_turf(src), pick(activation_sounds), 60, 1)
fire_projectile(user, L)
if(shots_fired)
target = R
else
target = L

sleep(10)
return ..()

if(LAZYLEN(activation_sounds))
playsound(get_turf(src), pick(activation_sounds), 60, 1)
fire_projectile(user, R)

to_chat(user, SPAN_WARNING("Smoke Screen uses left: <b>[SPAN_HELPFUL(ammo ? ammo.current_rounds / 2 : 0)]/[SPAN_HELPFUL(ammo ? ammo.max_rounds / 2 : 0)]</b> | Mags: <b>[SPAN_HELPFUL(LAZYLEN(backup_clips))]/[SPAN_HELPFUL(max_clips)]</b>"))

/obj/item/hardpoint/holder/tank_turret/fire_projectile(mob/user, atom/A)
set waitfor = 0

var/turf/origin_turf = get_turf(src)
origin_turf = locate(origin_turf.x + origins[1], origin_turf.y + origins[2], origin_turf.z)
/obj/item/hardpoint/holder/tank_turret/get_origin_turf()
var/origin_turf = ..()
origin_turf = get_step(get_step(origin_turf, owner.dir), owner.dir) //this should get us tile in front of tank to prevent grenade being stuck under us.

var/obj/projectile/P = generate_bullet(user, origin_turf)
SEND_SIGNAL(P, COMSIG_BULLET_USER_EFFECTS, owner.seats[VEHICLE_GUNNER])
P.fire_at(A, owner.seats[VEHICLE_GUNNER], src, get_dist(origin_turf, A) + 1, P.ammo.shell_speed)
ammo.current_rounds--
return origin_turf
9 changes: 7 additions & 2 deletions code/modules/vehicles/hardpoints/primary/autocannon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
activation_sounds = list('sound/weapons/vehicles/autocannon_fire.ogg')

health = 500
cooldown = 7
accuracy = 0.98
firing_arc = 60

origins = list(0, -3)
Expand All @@ -23,3 +21,10 @@
"4" = list(32, 0),
"8" = list(-32, 0)
)

scatter = 1
gun_firemode = GUN_FIREMODE_AUTOMATIC
gun_firemode_list = list(
GUN_FIREMODE_AUTOMATIC,
)
fire_delay = 0.7 SECONDS
29 changes: 7 additions & 22 deletions code/modules/vehicles/hardpoints/primary/dual_cannon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@
damage_multiplier = 0.2

health = 500
cooldown = 7
accuracy = 0.98
firing_arc = 60
var/burst_amount = 2

origins = list(0, -2)

Expand All @@ -33,27 +30,15 @@
"8" = list(14, 9)
)

scatter = 1
gun_firemode = GUN_FIREMODE_AUTOMATIC
gun_firemode_list = list(
GUN_FIREMODE_AUTOMATIC,
)
fire_delay = 0.3 SECONDS

/obj/item/hardpoint/primary/dualcannon/set_bullet_traits()
..()
LAZYADD(traits_to_give, list(
BULLET_TRAIT_ENTRY(/datum/element/bullet_trait_iff)
))

/obj/item/hardpoint/primary/dualcannon/fire(mob/user, atom/A)
if(ammo.current_rounds <= 0)
return

next_use = world.time + cooldown * owner.misc_multipliers["cooldown"]

for(var/bullets_fired = 1, bullets_fired <= burst_amount, bullets_fired++)
var/atom/T = A
if(!prob((accuracy * 100) / owner.misc_multipliers["accuracy"]))
T = get_step(get_turf(A), pick(GLOB.cardinals))
if(LAZYLEN(activation_sounds))
playsound(get_turf(src), pick(activation_sounds), 60, 1)
fire_projectile(user, T)
if(ammo.current_rounds <= 0)
break
if(bullets_fired < burst_amount) //we need to sleep only if there are more bullets to shoot in the burst
sleep(3)
to_chat(user, SPAN_WARNING("[src] Ammo: <b>[SPAN_HELPFUL(ammo ? ammo.current_rounds : 0)]/[SPAN_HELPFUL(ammo ? ammo.max_rounds : 0)]</b> | Mags: <b>[SPAN_HELPFUL(LAZYLEN(backup_clips))]/[SPAN_HELPFUL(max_clips)]</b>"))
37 changes: 9 additions & 28 deletions code/modules/vehicles/hardpoints/primary/flamer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
activation_sounds = list('sound/weapons/vehicles/flamethrower.ogg')

health = 400
cooldown = 20
accuracy = 0.75
firing_arc = 90

origins = list(0, -3)
Expand All @@ -26,36 +24,19 @@

use_muzzle_flash = FALSE

scatter = 5
fire_delay = 2.0 SECONDS

/obj/item/hardpoint/primary/flamer/set_bullet_traits()
..()
LAZYADD(traits_to_give, list(
BULLET_TRAIT_ENTRY(/datum/element/bullet_trait_iff)
))

/obj/item/hardpoint/primary/flamer/can_activate(mob/user, atom/A)
if(!..())
return FALSE

var/turf/origin_turf = get_turf(src)
origin_turf = locate(origin_turf.x + origins[1], origin_turf.y + origins[2], origin_turf.z)
if(origin_turf == get_turf(A))
return FALSE

return TRUE

/obj/item/hardpoint/primary/flamer/fire_projectile(mob/user, atom/A)
set waitfor = 0

var/turf/origin_turf = get_turf(src)
origin_turf = locate(origin_turf.x + origins[1], origin_turf.y + origins[2], origin_turf.z)

var/range = get_dist(origin_turf, A) + 1

var/obj/projectile/P = generate_bullet(user, origin_turf)
SEND_SIGNAL(P, COMSIG_BULLET_USER_EFFECTS, owner.seats[VEHICLE_GUNNER])
P.fire_at(A, owner.seats[VEHICLE_GUNNER], src, range < P.ammo.max_range ? range : P.ammo.max_range, P.ammo.shell_speed)

if(use_muzzle_flash)
muzzle_flash(Get_Angle(owner, A))
/obj/item/hardpoint/primary/flamer/try_fire(target, user, params)
var/turf/origin_turf = get_origin_turf()
if(origin_turf == get_turf(target))
to_chat(user, SPAN_WARNING("The target is too close."))
return NONE

ammo.current_rounds--
return ..()
5 changes: 3 additions & 2 deletions code/modules/vehicles/hardpoints/primary/ltb.dm
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@
activation_sounds = list('sound/weapons/vehicles/cannon_fire1.ogg', 'sound/weapons/vehicles/cannon_fire2.ogg')

health = 500
cooldown = 200
accuracy = 0.97
firing_arc = 60

origins = list(0, -3)
Expand All @@ -30,3 +28,6 @@
"4" = list(89, -4),
"8" = list(-89, -4)
)

scatter = 2
fire_delay = 20.0 SECONDS
86 changes: 48 additions & 38 deletions code/modules/vehicles/hardpoints/primary/minigun.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
disp_icon_state = "ltaaap_minigun"

health = 350
cooldown = 8
accuracy = 0.6
firing_arc = 90

origins = list(0, -3)
Expand All @@ -30,46 +28,58 @@
"8" = list(-77, 0)
)

//changed minigun mechanic so instead of having lowered cooldown with each shot it now has increased burst size.
//While it's still spammy, user doesn't have to click as fast as possible anymore and has margin of 2 seconds before minigun will start slowing down

var/chained_shots = 1 //how many quick succession shots we've fired, 1 by default
var/last_shot_time = 0 //when was last shot fired, after 3 seconds we stop barrel
var/list/chain_bursts = list(1, 1, 2, 2, 3, 3, 3, 4, 4, 4) //how many shots per click we do
scatter = 7
gun_firemode = GUN_FIREMODE_AUTOMATIC
gun_firemode_list = list(
GUN_FIREMODE_AUTOMATIC,
)
fire_delay = 0.8 SECONDS //base fire rate, modified by stage_delay_mult

activation_sounds = list('sound/weapons/gun_minigun.ogg')
/// Active firing time to reach max spin_stage.
var/spinup_time = 8 SECONDS
/// Grace period before losing spin_stage.
var/spindown_grace_time = 2 SECONDS
COOLDOWN_DECLARE(spindown_grace_cooldown)
/// Cooldown time to reach min spin_stage.
var/spindown_time = 3 SECONDS
/// Index of stage_rate.
var/spin_stage = 1
/// Shots fired per fire_delay at a particular spin_stage.
var/list/stage_rate = list(1, 1, 2, 2, 3, 3, 3, 4, 4, 4, 5)
/// Fire delay multiplier for current spin_stage.
var/stage_delay_mult = 1
/// When it was last fired, related to world.time.
var/last_fired = 0

/obj/item/hardpoint/primary/minigun/fire(mob/user, atom/A)
/obj/item/hardpoint/primary/minigun/set_fire_delay(value)
fire_delay = value
SEND_SIGNAL(src, COMSIG_GUN_AUTOFIREDELAY_MODIFIED, fire_delay * stage_delay_mult)

var/S = 'sound/weapons/vehicles/minigun_stop.ogg'
//check how much time since last shot. 2 seconds are grace period before minigun starts to lose rotation momentum
var/t = world.time - last_shot_time - 2 SECONDS
t = round(t / 10)
if(t > 0)
chained_shots = max(chained_shots - t * 3, 1) //we lose 3 chained_shots per second
else
if(chained_shots < 11)
chained_shots++
S = 'sound/weapons/vehicles/minigun_loop.ogg'
/obj/item/hardpoint/primary/minigun/set_fire_cooldown()
calculate_stage_delay_mult() //needs to check grace_cooldown before refreshed
last_fired = world.time
COOLDOWN_START(src, spindown_grace_cooldown, spindown_grace_time)
COOLDOWN_START(src, fire_cooldown, fire_delay * stage_delay_mult)

if(chained_shots == 1)
playsound(get_turf(src), 'sound/weapons/vehicles/minigun_start.ogg', 40, 1)
/obj/item/hardpoint/primary/minigun/proc/calculate_stage_delay_mult()
var/stage_rate_len = stage_rate.len
var/delta_time = world.time - last_fired

next_use = world.time + cooldown * owner.misc_multipliers["cooldown"]

//how many rounds we will shoot in this burst
if(chained_shots > LAZYLEN(chain_bursts)) //5 shots at maximum rotation
t = 5
var/old_spin_stage = spin_stage
if(auto_firing || burst_firing) //spinup if continuing fire
var/delta_stage = delta_time * (stage_rate_len - 1)
spin_stage += delta_stage / spinup_time
else if(COOLDOWN_FINISHED(src, spindown_grace_cooldown)) //spindown if initiating fire after grace
var/delta_stage = (delta_time - spindown_grace_time) * (stage_rate_len - 1)
spin_stage -= delta_stage / spindown_time
else
t = LAZYACCESS(chain_bursts, chained_shots)
for(var/i = 1; i <= t; i++)
var/atom/T = A
if(!prob((accuracy * 100) / owner.misc_multipliers["accuracy"]))
T = get_step(get_turf(T), pick(GLOB.cardinals))
fire_projectile(user, T)
if(ammo.current_rounds <= 0)
break
sleep(2)
to_chat(user, SPAN_WARNING("[src] Ammo: <b>[SPAN_HELPFUL(ammo ? ammo.current_rounds : 0)]/[SPAN_HELPFUL(ammo ? ammo.max_rounds : 0)]</b> | Mags: <b>[SPAN_HELPFUL(LAZYLEN(backup_clips))]/[SPAN_HELPFUL(max_clips)]</b>"))
return
spin_stage = Clamp(spin_stage, 1, stage_rate_len)

var/old_stage_rate = stage_rate[Floor(old_spin_stage)]
var/new_stage_rate = stage_rate[Floor(spin_stage)]

playsound(get_turf(src), S, 40, 1)
last_shot_time = world.time
if(old_stage_rate != new_stage_rate)
stage_delay_mult = 1 / new_stage_rate
SEND_SIGNAL(src, COMSIG_GUN_AUTOFIREDELAY_MODIFIED, fire_delay * stage_delay_mult)
Loading