Merge pull request #10473 from mwerezak/firemode-cleanup

Streamlines gun fire modes
This commit is contained in:
Chinsky
2015-08-13 07:22:28 +03:00
4 changed files with 58 additions and 81 deletions
+39 -44
View File
@@ -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>"
+2 -16
View File
@@ -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