mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-18 18:46:24 +01:00
Merge pull request #10473 from mwerezak/firemode-cleanup
Streamlines gun fire modes
This commit is contained in:
@@ -1,32 +1,28 @@
|
||||
/*
|
||||
Defines a firing mode for a gun.
|
||||
|
||||
burst number of shots fired when the gun is used
|
||||
burst_delay tick delay between shots in a burst
|
||||
fire_delay tick delay after the last shot before the gun may be used again
|
||||
move_delay tick delay after the last shot before the player may move
|
||||
dispersion dispersion of each shot in the burst measured in tiles per 7 tiles angle ratio
|
||||
accuracy accuracy modifier applied to each shot in tiles.
|
||||
applied on top of the base weapon accuracy.
|
||||
A firemode is created from a list of fire mode settings. Each setting modifies the value of the gun var with the same name.
|
||||
If the fire mode value for a setting is null, it will be replaced with the initial value of that gun's variable when the firemode is created.
|
||||
Obviously not compatible with variables that take a null value. If a setting is not present, then the corresponding var will not be modified.
|
||||
*/
|
||||
/datum/firemode
|
||||
var/name = "default"
|
||||
var/burst = 1
|
||||
var/burst_delay = null
|
||||
var/fire_delay = null
|
||||
var/move_delay = 1
|
||||
var/list/accuracy = list(0)
|
||||
var/list/dispersion = list(0)
|
||||
var/list/settings = list()
|
||||
|
||||
//using a list makes defining fire modes for new guns much nicer,
|
||||
//however we convert the lists to datums in part so that firemodes can be VVed if necessary.
|
||||
/datum/firemode/New(list/properties = null)
|
||||
/datum/firemode/New(obj/item/weapon/gun/gun, list/properties = null)
|
||||
..()
|
||||
if(!properties) return
|
||||
|
||||
for(var/propname in vars)
|
||||
if(!isnull(properties[propname]))
|
||||
src.vars[propname] = properties[propname]
|
||||
for(var/propname in properties)
|
||||
var/propvalue = properties[propname]
|
||||
if(isnull(propvalue))
|
||||
settings[propname] = gun.vars[propname] //better than initial() as it handles list vars like burst_accuracy
|
||||
else
|
||||
settings[propname] = propvalue
|
||||
|
||||
/datum/firemode/proc/apply_to(obj/item/weapon/gun/gun)
|
||||
for(var/propname in settings)
|
||||
gun.vars[propname] = settings[propname]
|
||||
|
||||
//Parent gun type. Guns are weapons that can be aimed at mobs and act over a distance
|
||||
/obj/item/weapon/gun
|
||||
@@ -51,8 +47,10 @@
|
||||
attack_verb = list("struck", "hit", "bashed")
|
||||
zoomdevicename = "scope"
|
||||
|
||||
var/burst = 1
|
||||
var/fire_delay = 6 //delay after shooting before the gun can be used again
|
||||
var/burst_delay = 2 //delay between shots, if firing in bursts
|
||||
var/move_delay = 1
|
||||
var/fire_sound = 'sound/weapons/Gunshot.ogg'
|
||||
var/fire_sound_text = "gunshot"
|
||||
var/recoil = 0 //screen shake
|
||||
@@ -60,12 +58,13 @@
|
||||
var/muzzle_flash = 3
|
||||
var/accuracy = 0 //accuracy is measured in tiles. +1 accuracy means that everything is effectively one tile closer for the purpose of miss chance, -1 means the opposite. launchers are not supported, at the moment.
|
||||
var/scoped_accuracy = null
|
||||
var/list/burst_accuracy = list(0) //allows for different accuracies for each shot in a burst. Applied on top of accuracy
|
||||
var/list/dispersion = list(0)
|
||||
|
||||
var/next_fire_time = 0
|
||||
|
||||
var/sel_mode = 1 //index of the currently selected mode
|
||||
var/list/firemodes = list()
|
||||
var/firemode_type = /datum/firemode //for subtypes that need custom firemode data
|
||||
|
||||
//aiming system stuff
|
||||
var/keep_aim = 1 //1 for keep shooting until aim is lowered
|
||||
@@ -78,11 +77,8 @@
|
||||
|
||||
/obj/item/weapon/gun/New()
|
||||
..()
|
||||
if(!firemodes.len)
|
||||
firemodes += new firemode_type
|
||||
else
|
||||
for(var/i in 1 to firemodes.len)
|
||||
firemodes[i] = new firemode_type(firemodes[i])
|
||||
for(var/i in 1 to firemodes.len)
|
||||
firemodes[i] = new /datum/firemode(src, firemodes[i])
|
||||
|
||||
if(isnull(scoped_accuracy))
|
||||
scoped_accuracy = accuracy
|
||||
@@ -156,28 +152,21 @@
|
||||
user << "<span class='warning'>[src] is not ready to fire again!</span>"
|
||||
return
|
||||
|
||||
//unpack firemode data
|
||||
var/datum/firemode/firemode = firemodes[sel_mode]
|
||||
var/_burst = firemode.burst
|
||||
var/_burst_delay = isnull(firemode.burst_delay)? src.burst_delay : firemode.burst_delay
|
||||
var/_fire_delay = isnull(firemode.fire_delay)? src.fire_delay : firemode.fire_delay
|
||||
var/_move_delay = firemode.move_delay
|
||||
|
||||
var/shoot_time = (_burst - 1)*_burst_delay
|
||||
var/shoot_time = (burst - 1)* burst_delay
|
||||
user.next_move = world.time + shoot_time //no clicking on things while shooting
|
||||
if(user.client) user.client.move_delay = world.time + shoot_time //no moving while shooting either
|
||||
next_fire_time = world.time + shoot_time
|
||||
|
||||
//actually attempt to shoot
|
||||
var/turf/targloc = get_turf(target) //cache this in case target gets deleted during shooting, e.g. if it was a securitron that got destroyed.
|
||||
for(var/i in 1 to _burst)
|
||||
for(var/i in 1 to burst)
|
||||
var/obj/projectile = consume_next_projectile(user)
|
||||
if(!projectile)
|
||||
handle_click_empty(user)
|
||||
break
|
||||
|
||||
var/acc = firemode.accuracy[min(i, firemode.accuracy.len)]
|
||||
var/disp = firemode.dispersion[min(i, firemode.dispersion.len)]
|
||||
var/acc = burst_accuracy[min(i, burst_accuracy.len)]
|
||||
var/disp = dispersion[min(i, dispersion.len)]
|
||||
process_accuracy(projectile, user, target, acc, disp)
|
||||
|
||||
if(pointblank)
|
||||
@@ -187,8 +176,8 @@
|
||||
handle_post_fire(user, target, pointblank, reflex)
|
||||
update_icon()
|
||||
|
||||
if(i < _burst)
|
||||
sleep(_burst_delay)
|
||||
if(i < burst)
|
||||
sleep(burst_delay)
|
||||
|
||||
if(!(target && target.loc))
|
||||
target = targloc
|
||||
@@ -198,8 +187,8 @@
|
||||
|
||||
//update timing
|
||||
user.next_move = world.time + 4
|
||||
if(user.client) user.client.move_delay = world.time + _move_delay
|
||||
next_fire_time = world.time + _fire_delay
|
||||
if(user.client) user.client.move_delay = world.time + move_delay
|
||||
next_fire_time = world.time + fire_delay
|
||||
|
||||
if(muzzle_flash)
|
||||
set_light(0)
|
||||
@@ -379,14 +368,20 @@
|
||||
var/datum/firemode/current_mode = firemodes[sel_mode]
|
||||
user << "The fire selector is set to [current_mode.name]."
|
||||
|
||||
/obj/item/weapon/gun/proc/switch_firemodes(mob/user=null)
|
||||
/obj/item/weapon/gun/proc/switch_firemodes()
|
||||
if(firemodes.len <= 1)
|
||||
return null
|
||||
|
||||
sel_mode++
|
||||
if(sel_mode > firemodes.len)
|
||||
sel_mode = 1
|
||||
var/datum/firemode/new_mode = firemodes[sel_mode]
|
||||
user << "<span class='notice'>\The [src] is now set to [new_mode.name].</span>"
|
||||
new_mode.apply_to(src)
|
||||
|
||||
return new_mode
|
||||
|
||||
/obj/item/weapon/gun/attack_self(mob/user)
|
||||
if(firemodes.len > 1)
|
||||
switch_firemodes(user)
|
||||
var/datum/firemode/new_mode = switch_firemodes(user)
|
||||
if(new_mode)
|
||||
user << "<span class='notice'>\The [src] is now set to [new_mode.name].</span>"
|
||||
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
/datum/firemode/energy
|
||||
var/projectile_type = null
|
||||
var/modifystate = null
|
||||
var/charge_cost = null
|
||||
var/fire_sound = null
|
||||
|
||||
/obj/item/weapon/gun/energy
|
||||
name = "energy gun"
|
||||
desc = "A basic energy-based gun."
|
||||
icon_state = "energy"
|
||||
fire_sound = 'sound/weapons/Taser.ogg'
|
||||
fire_sound_text = "laser blast"
|
||||
firemode_type = /datum/firemode/energy
|
||||
|
||||
var/obj/item/weapon/cell/power_supply //What type of power cell this uses
|
||||
var/charge_cost = 200 //How much energy is needed to fire.
|
||||
@@ -26,15 +19,8 @@
|
||||
var/recharge_time = 4
|
||||
var/charge_tick = 0
|
||||
|
||||
/obj/item/weapon/gun/energy/switch_firemodes(mob/user=null)
|
||||
..()
|
||||
var/datum/firemode/energy/current_mode = firemodes[sel_mode]
|
||||
if(istype(current_mode))
|
||||
projectile_type = isnull(current_mode.projectile_type)? initial(projectile_type) : current_mode.projectile_type
|
||||
modifystate = isnull(current_mode.modifystate)? initial(modifystate) : current_mode.modifystate
|
||||
charge_cost = isnull(current_mode.charge_cost)? initial(charge_cost) : current_mode.charge_cost
|
||||
fire_sound = isnull(current_mode.fire_sound)? initial(fire_sound) : current_mode.fire_sound
|
||||
|
||||
/obj/item/weapon/gun/energy/switch_firemodes()
|
||||
if(..())
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/gun/energy/emp_act(severity)
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
max_shots = 10
|
||||
|
||||
firemodes = list(
|
||||
list(name="stun", projectile_type=/obj/item/projectile/beam/stun, fire_sound='sound/weapons/Taser.ogg'),
|
||||
list(name="lethal", projectile_type=/obj/item/projectile/beam, fire_sound='sound/weapons/Laser.ogg'),
|
||||
list(name="stun", projectile_type=/obj/item/projectile/beam/stun, fire_sound='sound/weapons/Taser.ogg', fire_delay=null, charge_cost=null),
|
||||
list(name="lethal", projectile_type=/obj/item/projectile/beam, fire_sound='sound/weapons/Laser.ogg', fire_delay=null, charge_cost=null),
|
||||
list(name="DESTROY", projectile_type=/obj/item/projectile/beam/pulse, fire_sound='sound/weapons/pulse.ogg', fire_delay=25, charge_cost=400),
|
||||
)
|
||||
|
||||
|
||||
@@ -10,11 +10,12 @@
|
||||
slot_flags = SLOT_BELT
|
||||
ammo_type = /obj/item/ammo_casing/c9mm
|
||||
multi_aim = 1
|
||||
burst_delay = 2
|
||||
|
||||
firemodes = list(
|
||||
list(name="semiauto", burst=1, fire_delay=0),
|
||||
list(name="3-round bursts", burst=3, move_delay=4, accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.0, 0.6, 1.0)),
|
||||
list(name="short bursts", burst=5, move_delay=4, accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)),
|
||||
list(name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null),
|
||||
list(name="3-round bursts", burst=3, fire_delay=null, move_delay=4, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 1.0)),
|
||||
list(name="short bursts", burst=5, fire_delay=null, move_delay=4, burst_accuracy=list(0,-1,-1,-2,-2), dispersion=list(0.6, 1.0, 1.0, 1.0, 1.2)),
|
||||
)
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/mini_uzi
|
||||
@@ -66,9 +67,9 @@
|
||||
magazine_type = /obj/item/ammo_magazine/c762
|
||||
|
||||
firemodes = list(
|
||||
list(name="semiauto", burst=1, fire_delay=0),
|
||||
list(name="3-round bursts", burst=3, move_delay=6, accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.0, 0.6, 0.6)),
|
||||
list(name="short bursts", burst=5, move_delay=6, accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)),
|
||||
list(name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null),
|
||||
list(name="3-round bursts", burst=3, fire_delay=null, move_delay=6, burst_accuracy=list(0,-1,-2), dispersion=list(0.0, 0.6, 0.6)),
|
||||
list(name="short bursts", burst=5, fire_delay=null, move_delay=6, burst_accuracy=list(0,-1,-2,-2,-3), dispersion=list(0.6, 1.0, 1.0, 1.0, 1.2)),
|
||||
)
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/sts35/update_icon()
|
||||
@@ -98,9 +99,6 @@
|
||||
icon_state = "wt550"
|
||||
return
|
||||
|
||||
/datum/firemode/z8
|
||||
var/use_launcher = 0
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/z8
|
||||
name = "\improper Z8 Bulldog"
|
||||
desc = "An older model bullpup carbine, made by the now defunct Zendai Foundries. Uses armor piercing 5.56mm rounds. Makes you feel like a space marine when you hold it."
|
||||
@@ -119,13 +117,13 @@
|
||||
auto_eject_sound = 'sound/weapons/smg_empty_alarm.ogg'
|
||||
|
||||
burst_delay = 4
|
||||
firemode_type = /datum/firemode/z8
|
||||
firemodes = list(
|
||||
list(name="semiauto", burst=1, fire_delay=0),
|
||||
list(name="3-round bursts", burst=3, move_delay=6, accuracy = list(0,-1,-1), dispersion = list(0.0, 0.6, 0.6)),
|
||||
list(name="fire grenades", use_launcher=1)
|
||||
list(name="semiauto", burst=1, fire_delay=0, move_delay=null, use_launcher=null, burst_accuracy=null, dispersion=null),
|
||||
list(name="3-round bursts", burst=3, fire_delay=null, move_delay=6, use_launcher=null, burst_accuracy=list(0,-1,-1), dispersion=list(0.0, 0.6, 0.6)),
|
||||
list(name="fire grenades", burst=null, fire_delay=null, move_delay=null, use_launcher=1, burst_accuracy=null, dispersion=null)
|
||||
)
|
||||
|
||||
var/use_launcher = 0
|
||||
var/obj/item/weapon/gun/launcher/grenade/underslung/launcher
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/z8/New()
|
||||
@@ -139,15 +137,13 @@
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/z8/attack_hand(mob/user)
|
||||
var/datum/firemode/z8/current_mode = firemodes[sel_mode]
|
||||
if(user.get_inactive_hand() == src && current_mode.use_launcher)
|
||||
if(user.get_inactive_hand() == src && use_launcher)
|
||||
launcher.unload(user)
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/z8/Fire(atom/target, mob/living/user, params, pointblank=0, reflex=0)
|
||||
var/datum/firemode/z8/current_mode = firemodes[sel_mode]
|
||||
if(current_mode.use_launcher)
|
||||
if(use_launcher)
|
||||
launcher.Fire(target, user, params, pointblank, reflex)
|
||||
if(!launcher.chambered)
|
||||
switch_firemodes() //switch back automatically
|
||||
@@ -187,8 +183,8 @@
|
||||
magazine_type = /obj/item/ammo_magazine/a762
|
||||
|
||||
firemodes = list(
|
||||
list(name="short bursts", burst=5, move_delay=6, accuracy = list(0,-1,-1,-2,-2,-2,-3,-3), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)),
|
||||
list(name="long bursts", burst=8, move_delay=8, accuracy = list(0,-1,-1,-2,-2,-2,-3,-3), dispersion = list(1.0, 1.0, 1.0, 1.0, 1.2)),
|
||||
list(name="short bursts", burst=5, move_delay=6, burst_accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)),
|
||||
list(name="long bursts", burst=8, move_delay=8, burst_accuracy = list(0,-1,-1,-2,-2,-2,-3,-3), dispersion = list(1.0, 1.0, 1.0, 1.0, 1.2)),
|
||||
)
|
||||
|
||||
var/cover_open = 0
|
||||
|
||||
Reference in New Issue
Block a user