mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-01-02 05:22:40 +00:00
Merge remote-tracking branch 'bay12-upstream/master' into development
This commit is contained in:
@@ -90,6 +90,7 @@
|
||||
var/list/ammo_states = list() //values
|
||||
|
||||
/obj/item/ammo_magazine/New()
|
||||
..()
|
||||
if(multiple_sprites)
|
||||
initialize_magazine_icondata(src)
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
/obj/item/ammo_magazine/mc9mm
|
||||
name = "magazine (9mm)"
|
||||
icon_state = "9x19p"
|
||||
origin_tech = "combat=2"
|
||||
origin_tech = list(TECH_COMBAT = 2)
|
||||
mag_type = MAGAZINE
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 600)
|
||||
caliber = "9mm"
|
||||
@@ -68,7 +68,7 @@
|
||||
/obj/item/ammo_magazine/c9mm
|
||||
name = "ammunition Box (9mm)"
|
||||
icon_state = "9mm"
|
||||
origin_tech = "combat=2"
|
||||
origin_tech = list(TECH_COMBAT = 2)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 1800)
|
||||
caliber = "9mm"
|
||||
ammo_type = /obj/item/ammo_casing/c9mm
|
||||
@@ -101,7 +101,7 @@
|
||||
/obj/item/ammo_magazine/c45
|
||||
name = "ammunition Box (.45)"
|
||||
icon_state = "9mm"
|
||||
origin_tech = "combat=2"
|
||||
origin_tech = list(TECH_COMBAT = 2)
|
||||
caliber = ".45"
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 2250)
|
||||
ammo_type = /obj/item/ammo_casing/c45
|
||||
@@ -110,24 +110,24 @@
|
||||
/obj/item/ammo_magazine/c9mm/empty
|
||||
initial_ammo = 0
|
||||
|
||||
/obj/item/ammo_magazine/a12mm
|
||||
name = "magazine (12mm)"
|
||||
/obj/item/ammo_magazine/a10mm
|
||||
name = "magazine (10mm)"
|
||||
icon_state = "12mm"
|
||||
origin_tech = "combat=2"
|
||||
origin_tech = list(TECH_COMBAT = 2)
|
||||
mag_type = MAGAZINE
|
||||
caliber = "12mm"
|
||||
caliber = "10mm"
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 1500)
|
||||
ammo_type = "/obj/item/ammo_casing/a12mm"
|
||||
ammo_type = /obj/item/ammo_casing/a10mm
|
||||
max_ammo = 20
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_magazine/a12mm/empty
|
||||
/obj/item/ammo_magazine/a10mm/empty
|
||||
initial_ammo = 0
|
||||
|
||||
/obj/item/ammo_magazine/a556
|
||||
name = "magazine (5.56mm)"
|
||||
icon_state = "5.56"
|
||||
origin_tech = "combat=2"
|
||||
origin_tech = list(TECH_COMBAT = 2)
|
||||
mag_type = MAGAZINE
|
||||
caliber = "a556"
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 1800)
|
||||
@@ -145,7 +145,7 @@
|
||||
/obj/item/ammo_magazine/a50
|
||||
name = "magazine (.50)"
|
||||
icon_state = "50ae"
|
||||
origin_tech = "combat=2"
|
||||
origin_tech = list(TECH_COMBAT = 2)
|
||||
mag_type = MAGAZINE
|
||||
caliber = ".50"
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 1260)
|
||||
@@ -184,7 +184,7 @@
|
||||
/obj/item/ammo_magazine/a762
|
||||
name = "magazine box (7.62mm)"
|
||||
icon_state = "a762"
|
||||
origin_tech = "combat=2"
|
||||
origin_tech = list(TECH_COMBAT = 2)
|
||||
mag_type = MAGAZINE
|
||||
caliber = "a762"
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 4500)
|
||||
@@ -239,7 +239,7 @@
|
||||
|
||||
/obj/item/ammo_magazine/c45uzi/empty
|
||||
initial_ammo = 0
|
||||
|
||||
|
||||
/obj/item/ammo_magazine/tommymag
|
||||
name = "tommygun magazine (.45)"
|
||||
icon_state = "tommy-mag"
|
||||
@@ -262,20 +262,13 @@
|
||||
caliber = ".45"
|
||||
max_ammo = 50
|
||||
|
||||
/*
|
||||
//unused garbage
|
||||
|
||||
/obj/item/ammo_magazine/a418
|
||||
name = "ammo box (.418)"
|
||||
icon_state = "418"
|
||||
ammo_type = "/obj/item/ammo_casing/a418"
|
||||
/obj/item/ammo_magazine/caps
|
||||
name = "speed loader (caps)"
|
||||
icon_state = "T38"
|
||||
caliber = "caps"
|
||||
color = "#FF0000"
|
||||
ammo_type = /obj/item/ammo_casing/cap
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 600)
|
||||
max_ammo = 7
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/ammo_magazine/a666
|
||||
name = "ammo box (.666)"
|
||||
icon_state = "666"
|
||||
ammo_type = "/obj/item/ammo_casing/a666"
|
||||
max_ammo = 4
|
||||
multiple_sprites = 1
|
||||
*/
|
||||
|
||||
@@ -70,9 +70,9 @@
|
||||
caliber = ".45"
|
||||
projectile_type = /obj/item/projectile/energy/flash
|
||||
|
||||
/obj/item/ammo_casing/a12mm
|
||||
desc = "A 12mm bullet casing."
|
||||
caliber = "12mm"
|
||||
/obj/item/ammo_casing/a10mm
|
||||
desc = "A 10mm bullet casing."
|
||||
caliber = "10mm"
|
||||
projectile_type = /obj/item/projectile/bullet/pistol/medium
|
||||
|
||||
/obj/item/ammo_casing/shotgun
|
||||
@@ -164,20 +164,9 @@
|
||||
projectile_type = /obj/item/missile
|
||||
caliber = "rocket"
|
||||
|
||||
/obj/item/ammo_casing/chameleon
|
||||
name = "chameleon bullets"
|
||||
desc = "A set of bullets for the Chameleon Gun."
|
||||
projectile_type = /obj/item/projectile/bullet/chameleon
|
||||
caliber = ".45"
|
||||
|
||||
/*
|
||||
/obj/item/ammo_casing/a418
|
||||
desc = "A .418 bullet casing."
|
||||
caliber = "357"
|
||||
projectile_type = /obj/item/projectile/bullet/suffocationbullet
|
||||
|
||||
/obj/item/ammo_casing/a666
|
||||
desc = "A .666 bullet casing."
|
||||
caliber = "357"
|
||||
projectile_type = /obj/item/projectile/bullet/cyanideround
|
||||
*/
|
||||
/obj/item/ammo_casing/cap
|
||||
name = "cap"
|
||||
desc = "A cap for children toys."
|
||||
caliber = "caps"
|
||||
color = "#FF0000"
|
||||
projectile_type = /obj/item/projectile/bullet/pistol/cap
|
||||
|
||||
@@ -1,32 +1,31 @@
|
||||
/*
|
||||
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(propname == "mode_name")
|
||||
name = propvalue
|
||||
else 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
|
||||
@@ -47,12 +46,14 @@
|
||||
throw_speed = 4
|
||||
throw_range = 5
|
||||
force = 5
|
||||
origin_tech = "combat=1"
|
||||
origin_tech = list(TECH_COMBAT = 1)
|
||||
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 +61,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
|
||||
|
||||
//wielding information
|
||||
var/fire_delay_wielded = 0
|
||||
@@ -85,11 +87,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
|
||||
@@ -114,7 +113,7 @@
|
||||
if(process_projectile(P, user, user, pick("l_foot", "r_foot")))
|
||||
handle_post_fire(user, user)
|
||||
user.visible_message(
|
||||
"<span class='danger'>[user] shoots \himself in the foot with \the [src]!</span>",
|
||||
"<span class='danger'>\The [user] shoots \himself in the foot with \the [src]!</span>",
|
||||
"<span class='danger'>You shoot yourself in the foot with \the [src]!</span>"
|
||||
)
|
||||
M.drop_item()
|
||||
@@ -130,14 +129,17 @@
|
||||
/obj/item/weapon/gun/afterattack(atom/A, mob/living/user, adjacent, params)
|
||||
if(adjacent) return //A is adjacent, is the user, or is on the user's person
|
||||
|
||||
//decide whether to aim or shoot normally
|
||||
var/aiming = 0
|
||||
if(user && user.client && !(A in aim_targets))
|
||||
if(user.client.gun_mode)
|
||||
aiming = PreFire(A,user,params) //They're using the new gun system, locate what they're aiming at.
|
||||
if(!user.aiming)
|
||||
user.aiming = new(user)
|
||||
|
||||
if (!aiming)
|
||||
Fire(A,user,params) //Fire normally and always.
|
||||
if(user && user.client && user.aiming && user.aiming.active && user.aiming.aiming_at != A)
|
||||
PreFire(A,user,params) //They're using the new gun system, locate what they're aiming at.
|
||||
return
|
||||
|
||||
if(user && user.a_intent == I_HELP) //regardless of what happens, refuse to shoot if help intent is on
|
||||
user << "<span class='warning'>You refrain from firing your [src] as your intent is set to help.</span>"
|
||||
else
|
||||
Fire(A,user,params) //Otherwise, fire normally.
|
||||
|
||||
/obj/item/weapon/gun/attack(atom/A, mob/living/user, def_zone)
|
||||
if (A == user && user.zone_sel.selecting == "mouth" && !mouthshoot)
|
||||
@@ -160,30 +162,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
|
||||
if(can_wield() && !wielded && firemode.fire_delay)
|
||||
_fire_delay += initial(fire_delay) / 2
|
||||
var/_move_delay = firemode.move_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
|
||||
var/shoot_time = (burst - 1)* burst_delay
|
||||
user.setClickCooldown(shoot_time) //no clicking on things while shooting
|
||||
user.setMoveCooldown(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)
|
||||
@@ -193,8 +186,8 @@
|
||||
handle_post_fire(user, target, pointblank, reflex, i == _burst)
|
||||
update_icon()
|
||||
|
||||
if(i < _burst)
|
||||
sleep(_burst_delay)
|
||||
if(i < burst)
|
||||
sleep(burst_delay)
|
||||
|
||||
if(!(target && target.loc))
|
||||
target = targloc
|
||||
@@ -203,9 +196,9 @@
|
||||
update_held_icon()
|
||||
|
||||
//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
|
||||
user.setClickCooldown(DEFAULT_QUICK_COOLDOWN)
|
||||
user.setMoveCooldown(move_delay)
|
||||
next_fire_time = world.time + fire_delay
|
||||
|
||||
if(muzzle_flash)
|
||||
set_light(0)
|
||||
@@ -345,20 +338,19 @@
|
||||
playsound(user, fire_sound, 10, 1)
|
||||
else
|
||||
playsound(user, fire_sound, 50, 1)
|
||||
|
||||
in_chamber.on_hit(M)
|
||||
|
||||
if (in_chamber.damage == 0)
|
||||
if(istype(in_chamber, /obj/item/projectile/beam/lastertag))
|
||||
user.show_message("<span class = 'warning'>You feel rather silly, trying to commit suicide with a toy.</span>")
|
||||
mouthshoot = 0
|
||||
return
|
||||
else if (in_chamber.damage_type == HALLOSS)
|
||||
user << "<span class = 'notice'>Ow...</span>"
|
||||
user.apply_effect(110,AGONY,0)
|
||||
else
|
||||
|
||||
in_chamber.on_hit(M)
|
||||
if (in_chamber.damage_type != HALLOSS)
|
||||
log_and_message_admins("[key_name(user)] commited suicide using \a [src]")
|
||||
user.apply_damage(in_chamber.damage*2.5, in_chamber.damage_type, "head", used_weapon = "Point blank shot in the mouth with \a [in_chamber]", sharp=1)
|
||||
user.death()
|
||||
else
|
||||
user << "<span class = 'notice'>Ow...</span>"
|
||||
user.apply_effect(110,AGONY,0)
|
||||
qdel(in_chamber)
|
||||
mouthshoot = 0
|
||||
return
|
||||
@@ -403,16 +395,22 @@
|
||||
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>"
|
||||
|
||||
//Handling of rifles and two-handed weapons.
|
||||
/obj/item/weapon/gun/proc/can_wield()
|
||||
|
||||
@@ -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,17 +19,10 @@
|
||||
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()
|
||||
update_held_icon()
|
||||
|
||||
/obj/item/weapon/gun/energy/emp_act(severity)
|
||||
..()
|
||||
@@ -115,4 +101,4 @@
|
||||
icon_state = "[modifystate][ratio]"
|
||||
else
|
||||
icon_state = "[initial(icon_state)][ratio]"
|
||||
|
||||
update_held_icon()
|
||||
|
||||
@@ -1,31 +1,30 @@
|
||||
/obj/item/weapon/gun/energy/laser
|
||||
name = "laser carbine"
|
||||
desc = "A common laser weapon, designed to kill with concentrated energy blasts."
|
||||
desc = "An Hesphaistos Industries G40E carbine, designed to kill with concentrated energy blasts."
|
||||
icon_state = "laser"
|
||||
item_state = "laser"
|
||||
fire_sound = 'sound/weapons/Laser.ogg'
|
||||
slot_flags = SLOT_BELT|SLOT_BACK
|
||||
w_class = 3
|
||||
force = 10
|
||||
origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 2)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 2000)
|
||||
origin_tech = "combat=3;magnets=2"
|
||||
projectile_type = /obj/item/projectile/beam
|
||||
fire_delay = 1 //rapid fire
|
||||
projectile_type = /obj/item/projectile/beam/midlaser
|
||||
|
||||
/obj/item/weapon/gun/energy/laser/mounted
|
||||
self_recharge = 1
|
||||
use_external_power = 1
|
||||
|
||||
/obj/item/weapon/gun/energy/laser/practice
|
||||
name = "practice laser gun"
|
||||
desc = "A modified version of the basic laser gun, this one fires less concentrated energy bolts designed for target practice."
|
||||
name = "practice laser carbine"
|
||||
desc = "A modified version of the HI G40E, this one fires less concentrated energy bolts designed for target practice."
|
||||
projectile_type = /obj/item/projectile/beam/practice
|
||||
|
||||
obj/item/weapon/gun/energy/retro
|
||||
name = "retro laser"
|
||||
icon_state = "retro"
|
||||
item_state = "retro"
|
||||
desc = "An older model of the basic lasergun, no longer used by Nanotrasen's security or military forces. Nevertheless, it is still quite deadly and easy to maintain, making it a favorite amongst pirates and other outlaws."
|
||||
desc = "An older model of the basic lasergun. Nevertheless, it is still quite deadly and easy to maintain, making it a favorite amongst pirates and other outlaws."
|
||||
fire_sound = 'sound/weapons/Laser.ogg'
|
||||
slot_flags = SLOT_BELT
|
||||
w_class = 3
|
||||
@@ -36,7 +35,7 @@ obj/item/weapon/gun/energy/retro
|
||||
name = "antique laser gun"
|
||||
icon_state = "caplaser"
|
||||
item_state = "caplaser"
|
||||
desc = "This is an antique laser gun. All craftsmanship is of the highest quality. It is decorated with assistant leather and chrome. The object menaces with spikes of energy. On the item is an image of Space Station 13. The station is exploding."
|
||||
desc = "A rare weapon, handcrafted by a now defunct specialty manufacturer on Luna for a small fortune. It's certainly aged well."
|
||||
force = 5
|
||||
fire_sound = 'sound/weapons/Laser.ogg'
|
||||
slot_flags = SLOT_BELT
|
||||
@@ -52,7 +51,7 @@ obj/item/weapon/gun/energy/retro
|
||||
icon_state = "lasercannon"
|
||||
item_state = null
|
||||
fire_sound = 'sound/weapons/lasercannonfire.ogg'
|
||||
origin_tech = "combat=4;materials=3;powerstorage=3"
|
||||
origin_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 3, TECH_POWER = 3)
|
||||
slot_flags = SLOT_BELT|SLOT_BACK
|
||||
projectile_type = /obj/item/projectile/beam/heavylaser
|
||||
charge_cost = 400
|
||||
@@ -71,19 +70,19 @@ obj/item/weapon/gun/energy/retro
|
||||
icon_state = "xray"
|
||||
item_state = "xray"
|
||||
fire_sound = 'sound/weapons/laser3.ogg'
|
||||
origin_tech = "combat=5;materials=3;magnets=2;syndicate=2"
|
||||
origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 3, TECH_MAGNET = 2, TECH_ILLEGAL = 2)
|
||||
projectile_type = /obj/item/projectile/beam/xray
|
||||
charge_cost = 100
|
||||
max_shots = 20
|
||||
fire_delay = 1
|
||||
|
||||
/obj/item/weapon/gun/energy/sniperrifle
|
||||
name = "\improper L.W.A.P. sniper rifle"
|
||||
desc = "A high-power laser rifle fitted with a SMART aiming-system scope."
|
||||
name = "marksman energy rifle"
|
||||
desc = "The HI DMR 9E is an older design of Hesphaistos Industries. A designated marksman rifle capable of shooting powerful ionized beams, this is a weapon to kill from a distance."
|
||||
icon_state = "sniper"
|
||||
item_state = "sniper"
|
||||
fire_sound = 'sound/weapons/marauder.ogg'
|
||||
origin_tech = "combat=6;materials=5;powerstorage=4"
|
||||
origin_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 5, TECH_POWER = 4)
|
||||
projectile_type = /obj/item/projectile/beam/sniper
|
||||
slot_flags = SLOT_BACK
|
||||
charge_cost = 400
|
||||
@@ -124,7 +123,7 @@ obj/item/weapon/gun/energy/retro
|
||||
name = "laser tag gun"
|
||||
item_state = "laser"
|
||||
desc = "Standard issue weapon of the Imperial Guard"
|
||||
origin_tech = "combat=1;magnets=2"
|
||||
origin_tech = list(TECH_COMBAT = 1, TECH_MAGNET = 2)
|
||||
self_recharge = 1
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 2000)
|
||||
fire_sound = 'sound/weapons/Laser.ogg'
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
/obj/item/weapon/gun/energy/gun
|
||||
name = "energy gun"
|
||||
desc = "An energy-based gun with two settings: Stun and kill."
|
||||
desc = "Another bestseller of Lawson Arms and the FTU, the LAEP90 Perun is a versatile energy based sidearm, capable of switching between low and high capacity projectile settings. In other words: Stun or Kill."
|
||||
icon_state = "energystun100"
|
||||
item_state = null //so the human update icon uses the icon_state instead.
|
||||
fire_sound = 'sound/weapons/Taser.ogg'
|
||||
max_shots = 10
|
||||
|
||||
projectile_type = /obj/item/projectile/beam/stun
|
||||
origin_tech = "combat=3;magnets=2"
|
||||
origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 2)
|
||||
modifystate = "energystun"
|
||||
|
||||
firemodes = list(
|
||||
list(name="stun", projectile_type=/obj/item/projectile/beam/stun, modifystate="energystun", fire_sound='sound/weapons/Taser.ogg'),
|
||||
list(name="lethal", projectile_type=/obj/item/projectile/beam, modifystate="energykill", fire_sound='sound/weapons/Laser.ogg'),
|
||||
list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun, modifystate="energystun", fire_sound='sound/weapons/Taser.ogg'),
|
||||
list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, modifystate="energykill", fire_sound='sound/weapons/Laser.ogg'),
|
||||
)
|
||||
|
||||
/obj/item/weapon/gun/energy/gun/mounted
|
||||
@@ -24,17 +24,17 @@
|
||||
name = "advanced energy gun"
|
||||
desc = "An energy gun with an experimental miniaturized reactor."
|
||||
icon_state = "nucgun"
|
||||
origin_tech = "combat=3;materials=5;powerstorage=3"
|
||||
origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 5, TECH_POWER = 3)
|
||||
slot_flags = SLOT_BELT
|
||||
force = 8 //looks heavier than a pistol
|
||||
force = 8 //looks heavier than a pistol
|
||||
self_recharge = 1
|
||||
modifystate = null
|
||||
|
||||
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(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun, fire_sound='sound/weapons/Taser.ogg'),
|
||||
list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, fire_sound='sound/weapons/Laser.ogg'),
|
||||
)
|
||||
|
||||
|
||||
var/lightfail = 0
|
||||
|
||||
//override for failcheck behaviour
|
||||
@@ -44,46 +44,16 @@
|
||||
charge_tick = 0
|
||||
if(!power_supply) return 0
|
||||
if((power_supply.charge / power_supply.maxcharge) != 1)
|
||||
if(!failcheck()) return 0
|
||||
power_supply.give(charge_cost)
|
||||
update_icon()
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/gun/energy/gun/nuclear/proc/failcheck()
|
||||
lightfail = 0
|
||||
if (prob(src.reliability)) return 1 //No failure
|
||||
if (prob(src.reliability))
|
||||
for (var/mob/living/M in range(0,src)) //Only a minor failure, enjoy your radiation if you're in the same tile or carrying it
|
||||
if (src in M.contents)
|
||||
M << "<span class='warning'>Your gun feels pleasantly warm for a moment.</span>"
|
||||
else
|
||||
M << "<span class='warning'>You feel a warm sensation.</span>"
|
||||
M.apply_effect(rand(3,120), IRRADIATE)
|
||||
lightfail = 1
|
||||
else
|
||||
for (var/mob/living/M in range(rand(1,4),src)) //Big failure, TIME FOR RADIATION BITCHES
|
||||
if (src in M.contents)
|
||||
M << "<span class='danger'>Your gun's reactor overloads!</span>"
|
||||
M << "<span class='warning'>You feel a wave of heat wash over you.</span>"
|
||||
M.apply_effect(300, IRRADIATE)
|
||||
crit_fail = 1 //break the gun so it stops recharging
|
||||
processing_objects.Remove(src)
|
||||
update_icon()
|
||||
return 0
|
||||
|
||||
|
||||
/obj/item/weapon/gun/energy/gun/nuclear/proc/update_charge()
|
||||
if (crit_fail)
|
||||
overlays += "nucgun-whee"
|
||||
return
|
||||
var/ratio = power_supply.charge / power_supply.maxcharge
|
||||
ratio = round(ratio, 0.25) * 100
|
||||
overlays += "nucgun-[ratio]"
|
||||
|
||||
/obj/item/weapon/gun/energy/gun/nuclear/proc/update_reactor()
|
||||
if(crit_fail)
|
||||
overlays += "nucgun-crit"
|
||||
return
|
||||
if(lightfail)
|
||||
overlays += "nucgun-medium"
|
||||
else if ((power_supply.charge/power_supply.maxcharge) <= 0.5)
|
||||
@@ -97,10 +67,6 @@
|
||||
if("stun") overlays += "nucgun-stun"
|
||||
if("lethal") overlays += "nucgun-kill"
|
||||
|
||||
/obj/item/weapon/gun/energy/gun/nuclear/emp_act(severity)
|
||||
..()
|
||||
reliability -= round(15/severity)
|
||||
|
||||
/obj/item/weapon/gun/energy/gun/nuclear/update_icon()
|
||||
overlays.Cut()
|
||||
update_charge()
|
||||
|
||||
@@ -11,9 +11,9 @@
|
||||
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="DESTROY", projectile_type=/obj/item/projectile/beam/pulse, fire_sound='sound/weapons/pulse.ogg', fire_delay=25, charge_cost=400),
|
||||
list(mode_name="stun", projectile_type=/obj/item/projectile/beam/stun, fire_sound='sound/weapons/Taser.ogg', fire_delay=null, charge_cost=null),
|
||||
list(mode_name="lethal", projectile_type=/obj/item/projectile/beam, fire_sound='sound/weapons/Laser.ogg', fire_delay=null, charge_cost=null),
|
||||
list(mode_name="DESTROY", projectile_type=/obj/item/projectile/beam/pulse, fire_sound='sound/weapons/pulse.ogg', fire_delay=25, charge_cost=400),
|
||||
)
|
||||
|
||||
/obj/item/weapon/gun/energy/pulse_rifle/mounted
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/obj/item/weapon/gun/energy/ionrifle
|
||||
name = "ion rifle"
|
||||
desc = "A man portable anti-armor weapon designed to disable mechanical threats"
|
||||
desc = "The NT Mk60 EW Halicon is a man portable anti-armor weapon designed to disable mechanical threats, produced by NT. Not the best of its type."
|
||||
icon_state = "ionrifle"
|
||||
item_state = "ionrifle"
|
||||
fire_sound = 'sound/weapons/Laser.ogg'
|
||||
origin_tech = "combat=2;magnets=4"
|
||||
origin_tech = list(TECH_COMBAT = 2, TECH_MAGNET = 4)
|
||||
w_class = 4
|
||||
force = 10
|
||||
flags = CONDUCT
|
||||
@@ -29,7 +29,7 @@
|
||||
icon_state = "decloner"
|
||||
item_state = "decloner"
|
||||
fire_sound = 'sound/weapons/pulse3.ogg'
|
||||
origin_tech = "combat=5;materials=4;powerstorage=3"
|
||||
origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 4, TECH_POWER = 3)
|
||||
max_shots = 10
|
||||
projectile_type = /obj/item/projectile/energy/declone
|
||||
|
||||
@@ -42,13 +42,13 @@
|
||||
charge_cost = 100
|
||||
max_shots = 10
|
||||
projectile_type = /obj/item/projectile/energy/floramut
|
||||
origin_tech = "materials=2;biotech=3;powerstorage=3"
|
||||
origin_tech = list(TECH_MATERIAL = 2, TECH_BIO = 3, TECH_POWER = 3)
|
||||
modifystate = "floramut"
|
||||
self_recharge = 1
|
||||
|
||||
firemodes = list(
|
||||
list(name="induce mutations", projectile_type=/obj/item/projectile/energy/floramut, modifystate="floramut"),
|
||||
list(name="increase yield", projectile_type=/obj/item/projectile/energy/florayield, modifystate="florayield"),
|
||||
list(mode_name="induce mutations", projectile_type=/obj/item/projectile/energy/floramut, modifystate="floramut"),
|
||||
list(mode_name="increase yield", projectile_type=/obj/item/projectile/energy/florayield, modifystate="florayield"),
|
||||
)
|
||||
|
||||
/obj/item/weapon/gun/energy/floragun/afterattack(obj/target, mob/user, adjacent_flag)
|
||||
@@ -95,7 +95,7 @@
|
||||
icon_state = "toxgun"
|
||||
fire_sound = 'sound/effects/stealthoff.ogg'
|
||||
w_class = 3.0
|
||||
origin_tech = "combat=5;phorontech=4"
|
||||
origin_tech = list(TECH_COMBAT = 5, TECH_PHORON = 4)
|
||||
projectile_type = /obj/item/projectile/energy/phoron
|
||||
|
||||
/* Vaurca Weapons */
|
||||
@@ -196,6 +196,13 @@
|
||||
self_recharge = 1
|
||||
charge_meter = 0
|
||||
|
||||
/obj/item/weapon/gun/energy/staff/special_check(var/mob/user)
|
||||
if((user.mind && !wizards.is_antagonist(user.mind)))
|
||||
usr << "<span class='warning'>You focus your mind on \the [src], but nothing happens!</span>"
|
||||
return 0
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/gun/energy/staff/handle_click_empty(mob/user = null)
|
||||
if (user)
|
||||
user.visible_message("*fizzle*", "<span class='danger'>*fizzle*</span>")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/obj/item/weapon/gun/energy/taser
|
||||
name = "taser gun"
|
||||
desc = "A small, low capacity gun used for non-lethal takedowns."
|
||||
desc = "The NT Mk30 NL is a small, low capacity gun used for non-lethal takedowns. Produced by NT, it's actually a licensed version of a W-T design."
|
||||
icon_state = "taser"
|
||||
item_state = null //so the human update icon uses the icon_state instead.
|
||||
fire_sound = 'sound/weapons/Taser.ogg'
|
||||
@@ -20,11 +20,11 @@
|
||||
|
||||
/obj/item/weapon/gun/energy/stunrevolver
|
||||
name = "stun revolver"
|
||||
desc = "A high-tech revolver that fires stun cartridges. The stun cartridges can be recharged using a conventional energy weapon recharger."
|
||||
desc = "A LAEP20 Zeus. Designed by Lawson Arms and produced under the wing of the FTU, several TSCs have been trying to get a hold of the blueprints for half a decade."
|
||||
icon_state = "stunrevolver"
|
||||
item_state = "stunrevolver"
|
||||
fire_sound = 'sound/weapons/Gunshot.ogg'
|
||||
origin_tech = "combat=3;materials=3;powerstorage=2"
|
||||
origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 3, TECH_POWER = 2)
|
||||
projectile_type = /obj/item/projectile/energy/electrode
|
||||
max_shots = 8
|
||||
|
||||
@@ -35,8 +35,8 @@
|
||||
icon_state = "crossbow"
|
||||
w_class = 2.0
|
||||
item_state = "crossbow"
|
||||
origin_tech = list(TECH_COMBAT = 2, TECH_MAGNET = 2, TECH_ILLEGAL = 5)
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 2000)
|
||||
origin_tech = "combat=2;magnets=2;syndicate=5"
|
||||
slot_flags = SLOT_BELT
|
||||
silenced = 1
|
||||
fire_sound = 'sound/weapons/Genhit.ogg'
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
name = "freeze ray"
|
||||
icon_state = "freezegun"
|
||||
fire_sound = 'sound/weapons/pulse3.ogg'
|
||||
desc = "For when somebody won't let it go."
|
||||
//var/temperature = T20C
|
||||
//var/current_temperature = T20C
|
||||
charge_cost = 25 //20 shots, exact replica of old code (WAS 100)
|
||||
origin_tech = "combat=3;materials=4;powerstorage=3;magnets=2"
|
||||
desc = "A gun that changes temperatures. It has a small label on the side, 'More extreme temperatures will cost more charge!'"
|
||||
var/temperature = T20C
|
||||
var/current_temperature = T20C
|
||||
charge_cost = 100
|
||||
origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 4, TECH_POWER = 3, TECH_MAGNET = 2)
|
||||
slot_flags = SLOT_BELT|SLOT_BACK
|
||||
|
||||
projectile_type = /obj/item/projectile/temp
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
throw_speed = 2
|
||||
throw_range = 10
|
||||
force = 5.0
|
||||
flags = CONDUCT | USEDELAY
|
||||
flags = CONDUCT
|
||||
slot_flags = 0
|
||||
origin_tech = "combat=8;materials=5"
|
||||
origin_tech = list(TECH_COMBAT = 8, TECH_MATERIAL = 5)
|
||||
fire_sound = 'sound/effects/bang.ogg'
|
||||
|
||||
release_force = 15
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
name = "gun"
|
||||
desc = "A gun that fires bullets."
|
||||
icon_state = "revolver"
|
||||
origin_tech = "combat=2;materials=2"
|
||||
origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2)
|
||||
w_class = 3
|
||||
matter = list(DEFAULT_WALL_MATERIAL = 1000)
|
||||
recoil = 1
|
||||
@@ -176,7 +176,7 @@
|
||||
|
||||
/obj/item/weapon/gun/projectile/attack_self(mob/user as mob)
|
||||
if(firemodes.len > 1)
|
||||
switch_firemodes(user)
|
||||
..()
|
||||
else
|
||||
unload_ammo(user)
|
||||
|
||||
|
||||
@@ -1,49 +1,50 @@
|
||||
/obj/item/weapon/gun/projectile/automatic //Hopefully someone will find a way to make these fire in bursts or something. --Superxpdude
|
||||
name = "submachine gun"
|
||||
desc = "A lightweight, fast firing gun. Uses 9mm rounds."
|
||||
name = "prototype SMG"
|
||||
desc = "A protoype lightweight, fast firing gun. Uses 9mm rounds."
|
||||
icon_state = "saber" //ugly
|
||||
w_class = 3
|
||||
load_method = SPEEDLOADER //yup. until someone sprites a magazine for it.
|
||||
max_shells = 22
|
||||
caliber = "9mm"
|
||||
origin_tech = "combat=4;materials=2"
|
||||
origin_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 2)
|
||||
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(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, burst_accuracy=null, dispersion=null),
|
||||
list(mode_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(mode_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)),
|
||||
)
|
||||
|
||||
//Submachine guns and personal defence weapons, go.
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/mini_uzi
|
||||
name = "\improper Uzi"
|
||||
desc = "A lightweight, fast firing gun, for when you want someone dead. Uses .45 rounds."
|
||||
desc = "The UZI is a lightweight, fast firing gun. For when you want someone dead. Uses .45 rounds."
|
||||
icon_state = "mini-uzi"
|
||||
w_class = 3
|
||||
load_method = MAGAZINE
|
||||
magazine_type = /obj/item/ammo_magazine/c45uzi
|
||||
max_shells = 16
|
||||
caliber = ".45"
|
||||
origin_tech = "combat=5;materials=2;syndicate=8"
|
||||
origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 2, TECH_ILLEGAL = 8)
|
||||
ammo_type = /obj/item/ammo_casing/c45
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/c20r
|
||||
name = "\improper C-20r SMG"
|
||||
desc = "A lightweight, fast firing gun, for when you REALLY need someone dead. Uses 12mm pistol rounds. Has a 'Scarborough Arms - Per falcis, per pravitas' buttstamp"
|
||||
name = "submachine gun"
|
||||
desc = "The C-20r is a lightweight and rapid firing SMG, for when you REALLY need someone dead. Uses 10mm rounds. Has a 'Scarborough Arms - Per falcis, per pravitas' buttstamp."
|
||||
icon_state = "c20r"
|
||||
item_state = "c20r"
|
||||
w_class = 3
|
||||
force = 10
|
||||
caliber = "12mm"
|
||||
origin_tech = "combat=5;materials=2;syndicate=8"
|
||||
caliber = "10mm"
|
||||
origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 2, TECH_ILLEGAL = 8)
|
||||
slot_flags = SLOT_BELT|SLOT_BACK
|
||||
fire_sound = 'sound/weapons/Gunshot_light.ogg'
|
||||
load_method = MAGAZINE
|
||||
magazine_type = /obj/item/ammo_magazine/a12mm
|
||||
magazine_type = /obj/item/ammo_magazine/a10mm
|
||||
auto_eject = 1
|
||||
auto_eject_sound = 'sound/weapons/smg_empty_alarm.ogg'
|
||||
|
||||
@@ -56,13 +57,13 @@
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/wt550
|
||||
name = "\improper W-T 550 Saber"
|
||||
desc = "A cheap, mass produced Ward-Takahashi PDW. Uses 9mm rounds."
|
||||
name = "machine pistol"
|
||||
desc = "The W-T 550 Saber is a cheap self-defense weapon, mass-produced by Ward-Takahashi for paramilitary and private use. Uses 9mm rounds."
|
||||
icon_state = "wt550"
|
||||
item_state = "wt550"
|
||||
w_class = 3
|
||||
caliber = "9mm"
|
||||
origin_tech = "combat=5;materials=2"
|
||||
origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 2)
|
||||
slot_flags = SLOT_BELT
|
||||
ammo_type = "/obj/item/ammo_casing/c9mmr"
|
||||
fire_sound = 'sound/weapons/Gunshot_light.ogg'
|
||||
@@ -144,7 +145,7 @@
|
||||
w_class = 4
|
||||
force = 10
|
||||
caliber = "a556"
|
||||
origin_tech = "combat=8;materials=3"
|
||||
origin_tech = list(TECH_COMBAT = 8, TECH_MATERIAL = 3)
|
||||
ammo_type = "/obj/item/ammo_casing/a556"
|
||||
fire_sound = 'sound/weapons/Gunshot.ogg'
|
||||
slot_flags = SLOT_BACK
|
||||
@@ -154,13 +155,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(mode_name="semiauto", burst=1, fire_delay=0, move_delay=null, use_launcher=null, burst_accuracy=null, dispersion=null),
|
||||
list(mode_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(mode_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/rifle/z8/New()
|
||||
@@ -174,15 +175,13 @@
|
||||
..()
|
||||
|
||||
/obj/item/weapon/gun/projectile/automatic/rifle/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/rifle/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
|
||||
@@ -214,7 +213,7 @@
|
||||
slot_flags = 0
|
||||
max_shells = 50
|
||||
caliber = "a762"
|
||||
origin_tech = "combat=6;materials=1;syndicate=2"
|
||||
origin_tech = list(TECH_COMBAT = 6, TECH_MATERIAL = 1, TECH_ILLEGAL = 2)
|
||||
slot_flags = SLOT_BACK
|
||||
ammo_type = "/obj/item/ammo_casing/a762"
|
||||
fire_sound = 'sound/weapons/Gunshot_light.ogg'
|
||||
@@ -222,8 +221,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(mode_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(mode_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
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
desc = "A rack of hollow darts."
|
||||
icon_state = "darts"
|
||||
item_state = "rcdammo"
|
||||
origin_tech = "materials=2"
|
||||
origin_tech = list(TECH_MATERIAL = 2)
|
||||
mag_type = MAGAZINE
|
||||
caliber = "dart"
|
||||
ammo_type = /obj/item/ammo_casing/chemdart
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun
|
||||
name = "dart gun"
|
||||
desc = "A small gas-powered dartgun, capable of delivering chemical cocktails swiftly across short distances."
|
||||
desc = "Zeng-Hu Pharmaceutical's entry into the arms market, the Z-H P Artemis is a gas-powered dart gun capable of delivering chemical cocktails swiftly across short distances."
|
||||
icon_state = "dartgun-empty"
|
||||
item_state = null
|
||||
|
||||
@@ -203,4 +203,4 @@
|
||||
starting_chems = list("kelotane","bicaridine","anti_toxin")
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/vox/raider
|
||||
starting_chems = list("space_drugs","stoxin","impedrezene")
|
||||
starting_chems = list("space_drugs","stoxin","impedrezene")
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
/obj/item/weapon/gun/projectile/colt
|
||||
name = "\improper Colt M1911"
|
||||
desc = "A cheap Martian knock-off of a Colt M1911."
|
||||
name = "vintage .45 pistol"
|
||||
desc = "A cheap Martian knock-off of a Colt M1911. Uses .45 rounds."
|
||||
magazine_type = /obj/item/ammo_magazine/c45m
|
||||
icon_state = "colt"
|
||||
caliber = ".45"
|
||||
origin_tech = "combat=2;materials=2"
|
||||
origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2)
|
||||
fire_sound = 'sound/weapons/Gunshot_light.ogg'
|
||||
load_method = MAGAZINE
|
||||
|
||||
/obj/item/weapon/gun/projectile/colt/detective
|
||||
desc = "A cheap Martian knock-off of a Colt M1911. Uses .45 rounds."
|
||||
magazine_type = /obj/item/ammo_magazine/c45m/rubber
|
||||
magazine_type = /obj/item/ammo_magazine/c45m/flash
|
||||
|
||||
/obj/item/weapon/gun/projectile/colt/detective/verb/rename_gun()
|
||||
set name = "Name Gun"
|
||||
@@ -31,22 +30,21 @@
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/gun/projectile/sec
|
||||
desc = "A NanoTrasen designed sidearm, found pretty much everywhere humans are. Uses .45 rounds."
|
||||
name = "\improper NT Mk58"
|
||||
name = ".45 pistol"
|
||||
desc = "The NT Mk58 is a cheap, ubiquitous sidearm, produced by a NanoTrasen subsidiary. Found pretty much everywhere humans are. Uses .45 rounds."
|
||||
icon_state = "secguncomp"
|
||||
magazine_type = /obj/item/ammo_magazine/c45m/rubber
|
||||
magazine_type = /obj/item/ammo_magazine/c45m/flash
|
||||
caliber = ".45"
|
||||
origin_tech = "combat=2;materials=2"
|
||||
origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2)
|
||||
fire_sound = 'sound/weapons/Gunshot_light.ogg'
|
||||
load_method = MAGAZINE
|
||||
|
||||
/obj/item/weapon/gun/projectile/sec/flash
|
||||
name = "\improper NT Mk58 signal pistol"
|
||||
magazine_type = /obj/item/ammo_magazine/c45m/flash
|
||||
name = ".45 signal pistol"
|
||||
|
||||
/obj/item/weapon/gun/projectile/sec/wood
|
||||
desc = "A Nanotrasen designed sidearm, this one has a sweet wooden grip. Uses .45 rounds."
|
||||
name = "\improper Custom NT Mk58"
|
||||
desc = "The NT Mk58 is a cheap, ubiquitous sidearm, produced by a NanoTrasen subsidiary. This one has a sweet wooden grip. Uses .45 rounds."
|
||||
name = "custom .45 Pistol"
|
||||
icon_state = "secgundark"
|
||||
|
||||
/obj/item/weapon/gun/projectile/silenced
|
||||
@@ -56,7 +54,7 @@
|
||||
w_class = 3
|
||||
caliber = ".45"
|
||||
silenced = 1
|
||||
origin_tech = "combat=2;materials=2;syndicate=8"
|
||||
origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2, TECH_ILLEGAL = 8)
|
||||
load_method = MAGAZINE
|
||||
magazine_type = /obj/item/ammo_magazine/c45m
|
||||
|
||||
@@ -91,7 +89,7 @@
|
||||
max_shells = 8
|
||||
caliber = "75"
|
||||
fire_sound = 'sound/effects/Explosion1.ogg'
|
||||
origin_tech = "combat=3"
|
||||
origin_tech = list(TECH_COMBAT = 3)
|
||||
ammo_type = "/obj/item/ammo_casing/a75"
|
||||
load_method = MAGAZINE
|
||||
magazine_type = /obj/item/ammo_magazine/a75
|
||||
@@ -106,21 +104,20 @@
|
||||
icon_state = "gyropistol"
|
||||
|
||||
/obj/item/weapon/gun/projectile/pistol
|
||||
name = "\improper Stechtkin pistol"
|
||||
desc = "A small, easily concealable gun. Uses 9mm rounds."
|
||||
name = "holdout pistol"
|
||||
desc = "The Lumoco Arms P3 Whisper. A small, easily concealable gun. Uses 9mm rounds."
|
||||
icon_state = "pistol"
|
||||
item_state = null
|
||||
w_class = 2
|
||||
caliber = "9mm"
|
||||
silenced = 0
|
||||
origin_tech = "combat=2;materials=2;syndicate=2"
|
||||
origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2, TECH_ILLEGAL = 2)
|
||||
fire_sound = 'sound/weapons/Gunshot_light.ogg'
|
||||
load_method = MAGAZINE
|
||||
magazine_type = /obj/item/ammo_magazine/mc9mm
|
||||
|
||||
/obj/item/weapon/gun/projectile/pistol/flash
|
||||
name = "\improper Stechtkin signal pistol"
|
||||
desc = "A small, easily concealable gun. Uses 9mm rounds."
|
||||
name = "holdout signal pistol"
|
||||
magazine_type = /obj/item/ammo_magazine/mc9mm/flash
|
||||
|
||||
/obj/item/weapon/gun/projectile/pistol/attack_hand(mob/user as mob)
|
||||
@@ -166,17 +163,17 @@
|
||||
w_class = 2
|
||||
|
||||
/obj/item/weapon/gun/projectile/pirate
|
||||
name = "zipgun"
|
||||
name = "zip gun"
|
||||
desc = "Little more than a barrel, handle, and firing mechanism, cheap makeshift firearms like this one are not uncommon in frontier systems."
|
||||
icon_state = "sawnshotgun"
|
||||
item_state = "sawnshotgun"
|
||||
handle_casings = CYCLE_CASINGS //player has to take the old casing out manually before reloading
|
||||
load_method = SINGLE_CASING
|
||||
max_shells = 1 //literally just a barrel
|
||||
|
||||
|
||||
var/global/list/ammo_types = list(
|
||||
/obj/item/ammo_casing/a357 = ".357",
|
||||
/obj/item/ammo_casing/a12mm = "12mm",
|
||||
/obj/item/ammo_casing/a10mm = "10mm",
|
||||
/obj/item/ammo_casing/shotgun = "12 gauge",
|
||||
/obj/item/ammo_casing/shotgun = "12 gauge",
|
||||
/obj/item/ammo_casing/shotgun/pellet = "12 gauge",
|
||||
@@ -190,7 +187,7 @@
|
||||
/obj/item/weapon/gun/projectile/pirate/New()
|
||||
ammo_type = pick(ammo_types)
|
||||
desc += " Uses [ammo_types[ammo_type]] rounds."
|
||||
|
||||
|
||||
var/obj/item/ammo_casing/ammo = ammo_type
|
||||
caliber = initial(ammo.caliber)
|
||||
..()
|
||||
|
||||
@@ -1,19 +1,42 @@
|
||||
/obj/item/weapon/gun/projectile/revolver
|
||||
name = "revolver"
|
||||
desc = "A classic revolver. Uses .357 ammo"
|
||||
desc = "The Lumoco Arms HE Colt is a choice revolver for when you absolutely, positively need to put a hole in the other guy. Uses .357 ammo."
|
||||
icon_state = "revolver"
|
||||
item_state = "revolver"
|
||||
caliber = "357"
|
||||
origin_tech = "combat=2;materials=2"
|
||||
origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2)
|
||||
handle_casings = CYCLE_CASINGS
|
||||
max_shells = 7
|
||||
ammo_type = /obj/item/ammo_casing/a357
|
||||
var/chamber_offset = 0 //how many empty chambers in the cylinder until you hit a round
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/verb/spin_cylinder()
|
||||
set name = "Spin cylinder"
|
||||
set desc = "Fun when you're bored out of your skull."
|
||||
set category = "Object"
|
||||
|
||||
chamber_offset = 0
|
||||
visible_message("<span class='warning'>\The [usr] spins the cylinder of \the [src]!</span>", \
|
||||
"<span class='notice'>You hear something metallic spin and click.</span>")
|
||||
playsound(src.loc, 'sound/weapons/revolver_spin.ogg', 100, 1)
|
||||
loaded = shuffle(loaded)
|
||||
if(rand(1,max_shells) > loaded.len)
|
||||
chamber_offset = rand(0,max_shells - loaded.len)
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/consume_next_projectile()
|
||||
if(chamber_offset)
|
||||
chamber_offset--
|
||||
return
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/load_ammo(var/obj/item/A, mob/user)
|
||||
chamber_offset = 0
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/mateba
|
||||
name = "mateba"
|
||||
desc = "When you absolutely, positively need a 10mm hole in the other guy. Uses .357 ammo." //>10mm hole >.357
|
||||
icon_state = "mateba"
|
||||
origin_tech = "combat=2;materials=2"
|
||||
origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2)
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/detective
|
||||
name = "revolver"
|
||||
@@ -21,7 +44,7 @@
|
||||
icon_state = "detective"
|
||||
max_shells = 6
|
||||
caliber = "38"
|
||||
origin_tech = "combat=2;materials=2"
|
||||
origin_tech = list(TECH_COMBAT = 2, TECH_MATERIAL = 2)
|
||||
fire_sound = 'sound/weapons/Gunshot_light.ogg'
|
||||
ammo_type = /obj/item/ammo_casing/c38
|
||||
|
||||
@@ -73,3 +96,14 @@
|
||||
load_method = SINGLE_CASING
|
||||
max_shells = 2
|
||||
ammo_type = /obj/item/ammo_casing/a357
|
||||
|
||||
/obj/item/weapon/gun/projectile/revolver/capgun
|
||||
name = "cap gun"
|
||||
desc = "Looks almost like the real thing! Ages 8 and up."
|
||||
icon_state = "revolver"
|
||||
item_state = "revolver"
|
||||
caliber = "caps"
|
||||
origin_tech = list(TECH_COMBAT = 1, TECH_MATERIAL = 1)
|
||||
handle_casings = CYCLE_CASINGS
|
||||
max_shells = 7
|
||||
ammo_type = /obj/item/ammo_casing/cap
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/obj/item/weapon/gun/projectile/shotgun/pump
|
||||
name = "shotgun"
|
||||
desc = "Useful for sweeping alleys."
|
||||
desc = "The mass-produced W-T Remmington 29x shotgun is a favourite of police and security forces on many worlds. Useful for sweeping alleys."
|
||||
icon_state = "shotgun"
|
||||
item_state = "shotgun"
|
||||
max_shells = 4
|
||||
@@ -9,7 +9,7 @@
|
||||
flags = CONDUCT
|
||||
slot_flags = SLOT_BACK
|
||||
caliber = "shotgun"
|
||||
origin_tech = "combat=4;materials=2"
|
||||
origin_tech = list(TECH_COMBAT = 4, TECH_MATERIAL = 2)
|
||||
load_method = SINGLE_CASING
|
||||
ammo_type = /obj/item/ammo_casing/shotgun/beanbag
|
||||
handle_casings = HOLD_CASINGS
|
||||
@@ -62,9 +62,10 @@
|
||||
|
||||
/obj/item/weapon/gun/projectile/shotgun/pump/combat
|
||||
name = "combat shotgun"
|
||||
desc = "Built for close quarters combat, the Hesphaistos Industries KS-40 is widely regarded as a weapon of choice for repelling boarders."
|
||||
icon_state = "cshotgun"
|
||||
item_state = "cshotgun"
|
||||
origin_tech = "combat=5;materials=2"
|
||||
origin_tech = list(TECH_COMBAT = 5, TECH_MATERIAL = 2)
|
||||
max_shells = 7 //match the ammo box capacity, also it can hold a round in the chamber anyways, for a total of 8.
|
||||
ammo_type = /obj/item/ammo_casing/shotgun
|
||||
|
||||
@@ -83,13 +84,13 @@
|
||||
flags = CONDUCT
|
||||
slot_flags = SLOT_BACK
|
||||
caliber = "shotgun"
|
||||
origin_tech = "combat=3;materials=1"
|
||||
origin_tech = list(TECH_COMBAT = 3, TECH_MATERIAL = 1)
|
||||
ammo_type = /obj/item/ammo_casing/shotgun/beanbag
|
||||
|
||||
burst_delay = 0
|
||||
firemodes = list(
|
||||
list(name="fire one barrel at a time", burst=1),
|
||||
list(name="fire both barrels at once", burst=2),
|
||||
list(mode_name="fire one barrel at a time", burst=1),
|
||||
list(mode_name="fire both barrels at once", burst=2),
|
||||
)
|
||||
|
||||
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/obj/item/weapon/gun/projectile/heavysniper
|
||||
name = "\improper PTR-7 rifle"
|
||||
desc = "A portable anti-armour rifle fitted with a scope. Originally designed to used against armoured exosuits, it is capable of punching through windows and non-reinforced walls with ease. Fires armor piercing 14.5mm shells."
|
||||
name = "anti-materiel rifle"
|
||||
desc = "A portable anti-armour rifle fitted with a scope, the HI PTR-7 Rifle was originally designed to used against armoured exosuits. It is capable of punching through windows and non-reinforced walls with ease. Fires armor piercing 14.5mm shells."
|
||||
icon_state = "heavysniper"
|
||||
item_state = "heavysniper"
|
||||
w_class = 4
|
||||
force = 10
|
||||
slot_flags = SLOT_BACK
|
||||
origin_tech = "combat=8;materials=2;syndicate=8"
|
||||
origin_tech = list(TECH_COMBAT = 8, TECH_MATERIAL = 2, TECH_ILLEGAL = 8)
|
||||
caliber = "14.5mm"
|
||||
recoil = 4 //extra kickback
|
||||
//fire_sound = 'sound/weapons/sniper.ogg'
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
var/yo = null
|
||||
var/xo = null
|
||||
var/current = null
|
||||
var/obj/shot_from = null // the object which shot us
|
||||
var/atom/original = null // the original target clicked
|
||||
var/shot_from = "" // name of the object which shot us
|
||||
var/atom/original = null // the target clicked (not necessarily where the projectile is headed). Should probably be renamed to 'target' or something.
|
||||
var/turf/starting = null // the projectile's starting turf
|
||||
var/list/permutated = list() // we've passed through these atoms, don't try to hit them again
|
||||
|
||||
@@ -93,6 +93,11 @@
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/obj/item/projectile/proc/get_structure_damage()
|
||||
if(damage_type == BRUTE || damage_type == BURN)
|
||||
return damage
|
||||
return 0
|
||||
|
||||
//return 1 if the projectile should be allowed to pass through after all, 0 if not.
|
||||
/obj/item/projectile/proc/check_penetrate(var/atom/A)
|
||||
return 1
|
||||
@@ -175,16 +180,16 @@
|
||||
def_zone = hit_zone //set def_zone, so if the projectile ends up hitting someone else later (to be implemented), it is more likely to hit the same part
|
||||
result = target_mob.bullet_act(src, def_zone)
|
||||
|
||||
if(result == PROJECTILE_FORCE_MISS && (can_miss == 0)) //if you're shooting at point blank you can't miss.
|
||||
if(result == PROJECTILE_FORCE_MISS)
|
||||
if(!silenced)
|
||||
target_mob.visible_message("<span class='notice'>\The [src] misses [target_mob] narrowly!</span>")
|
||||
visible_message("<span class='notice'>\The [src] misses [target_mob] narrowly!</span>")
|
||||
return 0
|
||||
|
||||
//hit messages
|
||||
if(silenced)
|
||||
target_mob << "<span class='danger'>You've been hit in the [parse_zone(def_zone)] by \the [src]!</span>"
|
||||
else
|
||||
target_mob.visible_message("<span class='danger'>\The [target_mob] is hit by \the [src] in the [parse_zone(def_zone)]!</span>")//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter
|
||||
visible_message("<span class='danger'>\The [target_mob] is hit by \the [src] in the [parse_zone(def_zone)]!</span>")//X has fired Y is now given by the guns so you cant tell who shot you if you could not see the shooter
|
||||
|
||||
//admin logs
|
||||
if(!no_attack_log)
|
||||
|
||||
@@ -24,10 +24,15 @@
|
||||
check_armour = "laser"
|
||||
eyeblur = 2
|
||||
|
||||
/obj/item/projectile/beam/midlaser
|
||||
damage = 40
|
||||
armor_penetration = 10
|
||||
|
||||
/obj/item/projectile/beam/heavylaser
|
||||
name = "heavy laser"
|
||||
icon_state = "heavylaser"
|
||||
damage = 60
|
||||
armor_penetration = 30
|
||||
|
||||
muzzle_type = /obj/effect/projectile/laser_heavy/muzzle
|
||||
tracer_type = /obj/effect/projectile/laser_heavy/tracer
|
||||
@@ -36,7 +41,8 @@
|
||||
/obj/item/projectile/beam/xray
|
||||
name = "xray beam"
|
||||
icon_state = "xray"
|
||||
damage = 30
|
||||
damage = 25
|
||||
armor_penetration = 50
|
||||
|
||||
muzzle_type = /obj/effect/projectile/xray/muzzle
|
||||
tracer_type = /obj/effect/projectile/xray/tracer
|
||||
@@ -46,6 +52,7 @@
|
||||
name = "pulse"
|
||||
icon_state = "u_laser"
|
||||
damage = 50
|
||||
armor_penetration = 30
|
||||
|
||||
muzzle_type = /obj/effect/projectile/laser_pulse/muzzle
|
||||
tracer_type = /obj/effect/projectile/laser_pulse/tracer
|
||||
@@ -123,7 +130,8 @@
|
||||
/obj/item/projectile/beam/sniper
|
||||
name = "sniper beam"
|
||||
icon_state = "xray"
|
||||
damage = 60
|
||||
damage = 50
|
||||
armor_penetration = 10
|
||||
stun = 3
|
||||
weaken = 3
|
||||
stutter = 3
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
if(prob(chance))
|
||||
if(A.opacity)
|
||||
//display a message so that people on the other side aren't so confused
|
||||
A.visible_message("<span class='warning'>\The [src] pierces through \the [A]!")
|
||||
A.visible_message("<span class='warning'>\The [src] pierces through \the [A]!</span>")
|
||||
return 1
|
||||
|
||||
return 0
|
||||
@@ -69,22 +69,34 @@
|
||||
damage = 20
|
||||
//icon_state = "bullet" //TODO: would be nice to have it's own icon state
|
||||
var/pellets = 4 //number of pellets
|
||||
var/range_step = 2 //effective pellet count decreases every few tiles
|
||||
var/base_spread = 90 //lower means the pellets spread more across body parts
|
||||
var/range_step = 2 //projectile will lose a fragment each time it travels this distance. Can be a non-integer.
|
||||
var/base_spread = 90 //lower means the pellets spread more across body parts. If zero then this is considered a shrapnel explosion instead of a shrapnel cone
|
||||
var/spread_step = 10 //higher means the pellets spread more across body parts with distance
|
||||
|
||||
/obj/item/projectile/bullet/pellet/Bumped()
|
||||
. = ..()
|
||||
bumped = 0 //can hit all mobs in a tile. pellets is decremented inside attack_mob so this should be fine.
|
||||
|
||||
/obj/item/projectile/bullet/pellet/attack_mob(var/mob/living/target_mob, var/distance)
|
||||
/obj/item/projectile/bullet/pellet/proc/get_pellets(var/distance)
|
||||
var/pellet_loss = round((distance - 1)/range_step) //pellets lost due to distance
|
||||
return max(pellets - pellet_loss, 1)
|
||||
|
||||
/obj/item/projectile/bullet/pellet/attack_mob(var/mob/living/target_mob, var/distance, var/miss_modifier)
|
||||
if (pellets < 0) return 1
|
||||
|
||||
var/pellet_loss = round((distance - 1)/range_step) //pellets lost due to distance
|
||||
var/total_pellets = max(pellets - pellet_loss, 1)
|
||||
var/total_pellets = get_pellets(distance)
|
||||
var/spread = max(base_spread - (spread_step*distance), 0)
|
||||
|
||||
//shrapnel explosions miss prone mobs with a chance that increases with distance
|
||||
var/prone_chance = 0
|
||||
if(!base_spread)
|
||||
prone_chance = max(spread_step*(distance - 2), 0)
|
||||
|
||||
var/hits = 0
|
||||
for (var/i in 1 to total_pellets)
|
||||
if(target_mob.lying && target_mob != original && prob(prone_chance))
|
||||
continue
|
||||
|
||||
//pellet hits spread out across different zones, but 'aim at' the targeted zone with higher probability
|
||||
//whether the pellet actually hits the def_zone or a different zone should still be determined by the parent using get_zone_with_miss_chance().
|
||||
var/old_zone = def_zone
|
||||
@@ -97,6 +109,20 @@
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/projectile/bullet/pellet/get_structure_damage()
|
||||
var/distance = get_dist(loc, starting)
|
||||
return ..() * get_pellets(distance)
|
||||
|
||||
/obj/item/projectile/bullet/pellet/Move()
|
||||
. = ..()
|
||||
|
||||
//If this is a shrapnel explosion, allow mobs that are prone to get hit, too
|
||||
if(. && !base_spread && isturf(loc))
|
||||
for(var/mob/living/M in loc)
|
||||
if(M.lying || !M.CanPass(src, loc)) //Bump if lying or if we would normally Bump.
|
||||
if(Bump(M)) //Bump will make sure we don't hit a mob multiple times
|
||||
return
|
||||
|
||||
/* short-casing projectiles, like the kind used in pistols or SMGs */
|
||||
|
||||
/obj/item/projectile/bullet/pistol
|
||||
@@ -111,8 +137,8 @@
|
||||
/obj/item/projectile/bullet/pistol/rubber //"rubber" bullets
|
||||
name = "rubber bullet"
|
||||
check_armour = "melee"
|
||||
damage = 10
|
||||
agony = 40
|
||||
damage = 5
|
||||
agony = 25
|
||||
embed = 0
|
||||
sharp = 0
|
||||
|
||||
@@ -120,7 +146,8 @@
|
||||
|
||||
/obj/item/projectile/bullet/shotgun
|
||||
name = "slug"
|
||||
damage = 60
|
||||
damage = 50
|
||||
armor_penetration = 15
|
||||
|
||||
/obj/item/projectile/bullet/shotgun/beanbag //because beanbags are not bullets
|
||||
name = "beanbag"
|
||||
@@ -150,21 +177,24 @@
|
||||
|
||||
/* "Rifle" rounds */
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a762
|
||||
damage = 30
|
||||
/obj/item/projectile/bullet/rifle
|
||||
armor_penetration = 20
|
||||
penetrating = 1
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a762
|
||||
damage = 25
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a556
|
||||
damage = 35
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a145
|
||||
damage = 80
|
||||
stun = 3
|
||||
weaken = 3
|
||||
penetrating = 5
|
||||
armor_penetration = 80
|
||||
hitscan = 1 //so the PTR isn't useless as a sniper weapon
|
||||
|
||||
/obj/item/projectile/bullet/rifle/a556
|
||||
damage = 40
|
||||
penetrating = 1
|
||||
|
||||
/* Miscellaneous */
|
||||
|
||||
/obj/item/projectile/bullet/suffocationbullet//How does this even work?
|
||||
@@ -193,10 +223,6 @@
|
||||
damage = 1
|
||||
embed = 0
|
||||
|
||||
/obj/item/projectile/bullet/chameleon
|
||||
damage = 1 // stop trying to murderbone with a fake gun dumbass!!!
|
||||
embed = 0 // nope
|
||||
|
||||
/* Practice */
|
||||
|
||||
/obj/item/projectile/bullet/pistol/practice
|
||||
@@ -208,3 +234,15 @@
|
||||
/obj/item/projectile/bullet/shotgun/practice
|
||||
name = "practice"
|
||||
damage = 5
|
||||
|
||||
/obj/item/projectile/bullet/pistol/cap
|
||||
name = "cap"
|
||||
damage_type = HALLOSS
|
||||
damage = 0
|
||||
nodamage = 1
|
||||
embed = 0
|
||||
sharp = 0
|
||||
|
||||
/obj/item/projectile/bullet/pistol/cap/process()
|
||||
loc = null
|
||||
qdel(src)
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
/obj/item/projectile/change/proc/wabbajack(var/mob/M)
|
||||
if(istype(M, /mob/living) && M.stat != DEAD)
|
||||
if(M.monkeyizing)
|
||||
if(M.transforming)
|
||||
return
|
||||
if(M.has_brain_worms())
|
||||
return //Borer stuff - RR
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
name = "chemical shell"
|
||||
icon_state = "bullet"
|
||||
damage = 5
|
||||
agony = 10
|
||||
kill_count = 15 //if the shell hasn't hit anything after travelling this far it just explodes.
|
||||
var/flash_range = 0
|
||||
var/brightness = 7
|
||||
@@ -22,7 +23,7 @@
|
||||
|
||||
//blind adjacent people
|
||||
for (var/mob/living/carbon/M in viewers(T, flash_range))
|
||||
if(M.eyecheck() < 1)
|
||||
if(M.eyecheck() < FLASH_PROTECTION_MODERATE)
|
||||
flick("e_flash", M.flash)
|
||||
|
||||
//snap pop
|
||||
@@ -30,7 +31,7 @@
|
||||
src.visible_message("<span class='warning'>\The [src] explodes in a bright flash!</span>")
|
||||
|
||||
new /obj/effect/decal/cleanable/ash(src.loc) //always use src.loc so that ash doesn't end up inside windows
|
||||
new /obj/effect/effect/sparks(T)
|
||||
new /obj/effect/sparks(T)
|
||||
new /obj/effect/effect/smoke/illumination(T, brightness=max(flash_range*2, brightness), lifetime=light_duration)
|
||||
|
||||
//blinds people like the flash round, but can also be used for temporary illumination
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
if(src)//Do not add to this if() statement, otherwise the meteor won't delete them
|
||||
if(A)
|
||||
|
||||
A.meteorhit(src)
|
||||
A.ex_act(2)
|
||||
playsound(src.loc, 'sound/effects/meteorimpact.ogg', 40, 1)
|
||||
|
||||
for(var/mob/M in range(10, src))
|
||||
@@ -162,3 +162,12 @@
|
||||
on_hit(var/atom/target, var/blocked = 0)
|
||||
explosion(target, 0, 0, 4)
|
||||
return 1
|
||||
|
||||
/obj/item/projectile/chameleon
|
||||
name = "bullet"
|
||||
icon_state = "bullet"
|
||||
damage = 1 // stop trying to murderbone with a fake gun dumbass!!!
|
||||
embed = 0 // nope
|
||||
nodamage = 1
|
||||
damage_type = HALLOSS
|
||||
muzzle_type = /obj/effect/projectile/bullet/muzzle
|
||||
|
||||
@@ -1,406 +0,0 @@
|
||||
/obj/item/weapon/gun/verb/toggle_firerate()
|
||||
set name = "Toggle Continue Aiming"
|
||||
set category = "Object"
|
||||
|
||||
keep_aim = !keep_aim
|
||||
|
||||
if (keep_aim)
|
||||
loc << "You will now continue firing when your target moves."
|
||||
else
|
||||
loc << "You will now only fire once, then lower your aim, when your target moves."
|
||||
|
||||
/obj/item/weapon/gun/verb/lower_aim()
|
||||
set name = "Lower Aim"
|
||||
set category = "Object"
|
||||
if(aim_targets)
|
||||
stop_aim()
|
||||
usr.visible_message("<span class='notice'> \The [usr] lowers \the [src]...</span>")
|
||||
|
||||
//Removing the lock and the buttons.
|
||||
/obj/item/weapon/gun/dropped(mob/user as mob)
|
||||
stop_aim()
|
||||
if(user && user.client)
|
||||
user.client.remove_gun_icons()
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/gun/equipped(var/mob/user, var/slot)
|
||||
if (slot != slot_l_hand && slot != slot_r_hand)
|
||||
stop_aim()
|
||||
if (user.client)
|
||||
user.client.remove_gun_icons()
|
||||
return ..()
|
||||
|
||||
//Removes lock from all targets
|
||||
/obj/item/weapon/gun/proc/stop_aim()
|
||||
if(aim_targets)
|
||||
for(var/mob/living/M in aim_targets)
|
||||
if(M)
|
||||
M.NotTargeted(src) //Untargeting people.
|
||||
qdel(aim_targets)
|
||||
|
||||
//Compute how to fire.....
|
||||
//Return 1 if a target was found, 0 otherwise.
|
||||
/obj/item/weapon/gun/proc/PreFire(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, params)
|
||||
//Lets not spam it.
|
||||
if(lock_time > world.time - 2) return
|
||||
|
||||
user.set_dir(get_cardinal_dir(src, A))
|
||||
if(isliving(A) && !(A in aim_targets))
|
||||
Aim(A) //Clicked a mob, aim at them
|
||||
return 1
|
||||
|
||||
//Didn't click someone, check if there is anyone along that guntrace
|
||||
var/mob/living/M = GunTrace(usr.x,usr.y,A.x,A.y,usr.z,usr) //Find dat mob.
|
||||
if(isliving(M) && (M in view(user)) && !(M in aim_targets))
|
||||
Aim(M) //Aha! Aim at them!
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
//Aiming at the target mob.
|
||||
/obj/item/weapon/gun/proc/Aim(var/mob/living/M)
|
||||
if(!aim_targets || !(M in aim_targets))
|
||||
lock_time = world.time
|
||||
if(aim_targets && !multi_aim) //If they're targeting someone and they have a non multi_aim weapon.
|
||||
for(var/mob/living/L in aim_targets)
|
||||
if(L)
|
||||
L.NotTargeted(src)
|
||||
qdel(aim_targets)
|
||||
usr.visible_message("<span class='danger'><b>[usr] turns \the [src] on [M]!</b></span>")
|
||||
else
|
||||
usr.visible_message("<span class='danger'><b>[usr] aims \a [src] at [M]!</b></span>")
|
||||
M.Targeted(src)
|
||||
|
||||
//HE MOVED, SHOOT HIM!
|
||||
/obj/item/weapon/gun/proc/TargetActed(var/mob/living/T)
|
||||
var/mob/living/M = loc
|
||||
if(M == T) return
|
||||
if(!istype(M)) return
|
||||
if(src != M.get_active_hand())
|
||||
stop_aim()
|
||||
return
|
||||
|
||||
//reflex firing is disabled when help intent is set
|
||||
if (M.a_intent == I_HELP)
|
||||
M << "<span class='danger'>You refrain from firing your [src] as your intent is set to help.</span>"
|
||||
return
|
||||
|
||||
M.last_move_intent = world.time
|
||||
var/firing_check = can_hit(T,usr) //0 if it cannot hit them, 1 if it is capable of hitting, and 2 if a special check is preventing it from firing.
|
||||
if(firing_check > 0)
|
||||
if(firing_check == 1)
|
||||
Fire(T,usr, reflex = 1)
|
||||
else if(!told_cant_shoot)
|
||||
M << "<span class='danger'>They can't be hit from here!</span>"
|
||||
told_cant_shoot = 1
|
||||
spawn(30)
|
||||
told_cant_shoot = 0
|
||||
|
||||
usr.set_dir(get_cardinal_dir(src, T))
|
||||
|
||||
if (!keep_aim) // If keep_aim is set to lower aim after one shot, untarget the target
|
||||
T.NotTargeted(src)
|
||||
|
||||
//Yay, math!
|
||||
|
||||
#define SIGN(X) ((X<0)?-1:1)
|
||||
|
||||
/proc/GunTrace(X1,Y1,X2,Y2,Z=1,exc_obj,PX1=16,PY1=16,PX2=16,PY2=16)
|
||||
//bluh << "Tracin' [X1],[Y1] to [X2],[Y2] on floor [Z]."
|
||||
var/turf/T
|
||||
var/mob/living/M
|
||||
if(X1==X2)
|
||||
if(Y1==Y2) return 0 //Light cannot be blocked on same tile
|
||||
else
|
||||
var/s = SIGN(Y2-Y1)
|
||||
Y1+=s
|
||||
while(1)
|
||||
T = locate(X1,Y1,Z)
|
||||
if(!T) return 0
|
||||
M = locate() in T
|
||||
if(M) return M
|
||||
M = locate() in orange(1,T)-exc_obj
|
||||
if(M) return M
|
||||
Y1+=s
|
||||
else
|
||||
var
|
||||
m=(32*(Y2-Y1)+(PY2-PY1))/(32*(X2-X1)+(PX2-PX1))
|
||||
b=(Y1+PY1/32-0.015625)-m*(X1+PX1/32-0.015625) //In tiles
|
||||
signX = SIGN(X2-X1)
|
||||
signY = SIGN(Y2-Y1)
|
||||
if(X1<X2) b+=m
|
||||
while(1)
|
||||
var/xvert = round(m*X1+b-Y1)
|
||||
if(xvert) Y1+=signY //Line exits tile vertically
|
||||
else X1+=signX //Line exits tile horizontally
|
||||
T = locate(X1,Y1,Z)
|
||||
if(!T) return 0
|
||||
M = locate() in T
|
||||
if(M) return M
|
||||
M = locate() in orange(1,T)-exc_obj
|
||||
if(M) return M
|
||||
return 0
|
||||
|
||||
|
||||
//Targeting management procs
|
||||
/mob/var
|
||||
list/targeted_by
|
||||
target_time = -100
|
||||
last_move_intent = -100
|
||||
last_target_click = -5
|
||||
target_locked = null
|
||||
last_target_radio = -5;
|
||||
|
||||
/mob/living/proc/Targeted(var/obj/item/weapon/gun/I) //Self explanitory.
|
||||
if(!I.aim_targets)
|
||||
I.aim_targets = list(src)
|
||||
else if(I.multi_aim && I.aim_targets.len < 5) //multi_aim weapon, they can hold down a room.
|
||||
I.aim_targets += src
|
||||
else if(I.aim_targets.len >= 5)
|
||||
if(ismob(I.loc))
|
||||
I.loc << "You can only target 5 people at once!"
|
||||
return
|
||||
else
|
||||
return
|
||||
for(var/mob/living/K in viewers(usr))
|
||||
K << 'sound/weapons/TargetOn.ogg'
|
||||
|
||||
if(!targeted_by) targeted_by = list()
|
||||
targeted_by += I
|
||||
I.lock_time = world.time + 20 //Target has 2 second to realize they're targeted and stop (or target the opponent).
|
||||
src << "((<span class='danger'><b>Your character is being targeted. They have 2 seconds to stop any click or move actions.</b></span> While targeted, they may \
|
||||
drag and drop items in or into the map, speak, and click on interface buttons. Clicking on the map objects (floors and walls are fine), their items \
|
||||
(other than a weapon to de-target), moving, or talking into a radio will result in being fired upon. <span class='danger'>The aggressor may also fire manually, \
|
||||
so try not to get on their bad side.</span>))"
|
||||
|
||||
if(targeted_by.len == 1)
|
||||
spawn(0)
|
||||
target_locked = image("icon" = 'icons/effects/Targeted.dmi', "icon_state" = "locking")
|
||||
overlays += target_locked
|
||||
spawn(0)
|
||||
sleep(20)
|
||||
if(target_locked)
|
||||
target_locked = image("icon" = 'icons/effects/Targeted.dmi', "icon_state" = "locked")
|
||||
update_targeted()
|
||||
|
||||
//Adding the buttons to the controller person
|
||||
var/mob/living/T = I.loc
|
||||
if(T)
|
||||
if(T.client)
|
||||
T.client.add_gun_icons()
|
||||
else
|
||||
I.lower_aim()
|
||||
return
|
||||
if(iscarbon(src) && m_intent == "run" && T.client.target_can_move == 1 && T.client.target_can_run == 0)
|
||||
src << "<span class='danger'>Your move intent is now set to walk, as your targeter permits it.</span>" //Self explanitory.
|
||||
set_m_intent("walk")
|
||||
|
||||
//Processing the aiming. Should be probably in separate object with process() but lasy.
|
||||
while(targeted_by && T.client)
|
||||
if(last_move_intent > I.lock_time + 10 && !T.client.target_can_move) //If target moved when not allowed to
|
||||
I.TargetActed(src)
|
||||
if(I.last_moved_mob == src) //If they were the last ones to move, give them more of a grace period, so that an automatic weapon can hold down a room better.
|
||||
I.lock_time = world.time + 5
|
||||
I.lock_time = world.time + 5
|
||||
I.last_moved_mob = src
|
||||
else if(last_move_intent > I.lock_time + 10 && !T.client.target_can_run && m_intent == "run") //If the target ran while targeted
|
||||
I.TargetActed(src)
|
||||
if(I.last_moved_mob == src) //If they were the last ones to move, give them more of a grace period, so that an automatic weapon can hold down a room better.
|
||||
I.lock_time = world.time + 5
|
||||
I.lock_time = world.time + 5
|
||||
I.last_moved_mob = src
|
||||
if(last_target_click > I.lock_time + 10 && !T.client.target_can_click) //If the target clicked the map to pick something up/shoot/etc
|
||||
I.TargetActed(src)
|
||||
if(I.last_moved_mob == src) //If they were the last ones to move, give them more of a grace period, so that an automatic weapon can hold down a room better.
|
||||
I.lock_time = world.time + 5
|
||||
I.lock_time = world.time + 5
|
||||
I.last_moved_mob = src
|
||||
if(last_target_radio > I.lock_time + 10 && !T.client.target_can_radio)
|
||||
I.TargetActed(src)
|
||||
if(I.last_moved_mob == src) //If they were the last ones to move, give them more of a grace period, so that an automatic weapon can hold down a room better.
|
||||
I.lock_time = world.time + 5
|
||||
I.lock_time = world.time + 5
|
||||
I.last_moved_mob = src
|
||||
sleep(1)
|
||||
|
||||
/mob/living/proc/NotTargeted(var/obj/item/weapon/gun/I)
|
||||
if(!I.silenced)
|
||||
for(var/mob/living/M in viewers(src))
|
||||
M << 'sound/weapons/TargetOff.ogg'
|
||||
targeted_by -= I
|
||||
I.aim_targets.Remove(src) //De-target them
|
||||
if(!I.aim_targets.len)
|
||||
qdel(I.aim_targets)
|
||||
var/mob/living/T = I.loc //Remove the targeting icons
|
||||
if(T && ismob(T) && !I.aim_targets && T.client)
|
||||
T.client.remove_gun_icons()
|
||||
if(!targeted_by.len)
|
||||
qdel(target_locked) //Remove the overlay
|
||||
qdel(targeted_by)
|
||||
spawn(1) update_targeted()
|
||||
|
||||
/mob/living/Move()
|
||||
. = ..()
|
||||
for(var/obj/item/weapon/gun/G in targeted_by) //Handle moving out of the gunner's view.
|
||||
var/mob/living/M = G.loc
|
||||
if(!(M in view(src)))
|
||||
NotTargeted(G)
|
||||
for(var/obj/item/weapon/gun/G in src) //Handle the gunner loosing sight of their target/s
|
||||
if(G.aim_targets)
|
||||
for(var/mob/living/M in G.aim_targets)
|
||||
if(M && !(M in view(src)))
|
||||
M.NotTargeted(G)
|
||||
|
||||
//If you move out of range, it isn't going to still stay locked on you any more.
|
||||
/client/var
|
||||
target_can_move = 0
|
||||
target_can_run = 0
|
||||
target_can_click = 0
|
||||
target_can_radio = 0
|
||||
gun_mode = 0
|
||||
|
||||
//These are called by the on-screen buttons, adjusting what the victim can and cannot do.
|
||||
/client/proc/add_gun_icons()
|
||||
if(!usr) return 1 // This can runtime if someone manages to throw a gun out of their hand before the proc is called.
|
||||
screen += usr.item_use_icon
|
||||
screen += usr.gun_move_icon
|
||||
screen += usr.radio_use_icon
|
||||
if (target_can_move)
|
||||
screen += usr.gun_run_icon
|
||||
|
||||
|
||||
|
||||
/client/proc/remove_gun_icons()
|
||||
if(!usr) return 1 // Runtime prevention on N00k agents spawning with SMG
|
||||
screen -= usr.item_use_icon
|
||||
screen -= usr.gun_move_icon
|
||||
screen -= usr.radio_use_icon
|
||||
if (target_can_move)
|
||||
screen -= usr.gun_run_icon
|
||||
|
||||
/client/verb/ToggleGunMode()
|
||||
set name = "Toggle Gun Mode"
|
||||
set hidden = 1
|
||||
gun_mode = !gun_mode
|
||||
if(gun_mode)
|
||||
usr << "You will now take people captive."
|
||||
else
|
||||
usr << "You will now shoot where you target."
|
||||
for(var/obj/item/weapon/gun/G in usr)
|
||||
G.stop_aim()
|
||||
remove_gun_icons()
|
||||
if(usr.gun_setting_icon)
|
||||
usr.gun_setting_icon.icon_state = "gun[gun_mode]"
|
||||
|
||||
|
||||
/client/verb/AllowTargetMove()
|
||||
set hidden=1
|
||||
|
||||
//Changing client's permissions
|
||||
target_can_move = !target_can_move
|
||||
if(target_can_move)
|
||||
usr << "Target may now walk."
|
||||
//usr.gun_run_icon = new /obj/screen/gun/run(null) //adding icon for running permission
|
||||
screen += usr.gun_run_icon
|
||||
else
|
||||
usr << "Target may no longer move."
|
||||
target_can_run = 0
|
||||
qdel(usr.gun_run_icon) //no need for icon for running permission
|
||||
|
||||
//Updating walking permission button
|
||||
if(usr.gun_move_icon)
|
||||
usr.gun_move_icon.icon_state = "no_walk[target_can_move]"
|
||||
usr.gun_move_icon.name = "[target_can_move ? "Disallow" : "Allow"] Walking"
|
||||
|
||||
//Handling change for all the guns on client
|
||||
for(var/obj/item/weapon/gun/G in usr)
|
||||
G.lock_time = world.time + 5
|
||||
if(G.aim_targets)
|
||||
for(var/mob/living/M in G.aim_targets)
|
||||
if(target_can_move)
|
||||
M << "Your character may now <b>walk</b> at the discretion of their targeter."
|
||||
if(!target_can_run)
|
||||
M << "<span class='danger'>Your move intent is now set to walk, as your targeter permits it.</span>"
|
||||
M.set_m_intent("walk")
|
||||
else
|
||||
M << "<span class='danger'><b>Your character will now be shot if they move.</b></span>"
|
||||
|
||||
/mob/living/proc/set_m_intent(var/intent)
|
||||
if (intent != "walk" && intent != "run")
|
||||
return 0
|
||||
m_intent = intent
|
||||
if(hud_used)
|
||||
if (hud_used.move_intent)
|
||||
hud_used.move_intent.icon_state = intent == "walk" ? "walking" : "running"
|
||||
|
||||
client/verb/AllowTargetRun()
|
||||
set hidden=1
|
||||
|
||||
//Changing client's permissions
|
||||
target_can_run = !target_can_run
|
||||
if(target_can_run)
|
||||
usr << "Target may now run."
|
||||
else
|
||||
usr << "Target may no longer run."
|
||||
|
||||
//Updating running permission button
|
||||
if(usr.gun_run_icon)
|
||||
usr.gun_run_icon.icon_state = "no_run[target_can_run]"
|
||||
usr.gun_run_icon.name = "[target_can_run ? "Disallow" : "Allow"] Running"
|
||||
|
||||
//Handling change for all the guns on client
|
||||
for(var/obj/item/weapon/gun/G in src)
|
||||
G.lock_time = world.time + 5
|
||||
if(G.aim_targets)
|
||||
for(var/mob/living/M in G.aim_targets)
|
||||
if(target_can_run)
|
||||
M << "Your character may now <b>run</b> at the discretion of their targeter."
|
||||
else
|
||||
M << "<span class='danger'><b>Your character will now be shot if they run.</b></span>"
|
||||
|
||||
/client/verb/AllowTargetClick()
|
||||
set hidden=1
|
||||
|
||||
//Changing client's permissions
|
||||
target_can_click = !target_can_click
|
||||
if(target_can_click)
|
||||
usr << "Target may now use items."
|
||||
else
|
||||
usr << "Target may no longer use items."
|
||||
|
||||
if(usr.item_use_icon)
|
||||
usr.item_use_icon.icon_state = "no_item[target_can_click]"
|
||||
usr.item_use_icon.name = "[target_can_click ? "Disallow" : "Allow"] Item Use"
|
||||
|
||||
//Handling change for all the guns on client
|
||||
for(var/obj/item/weapon/gun/G in src)
|
||||
G.lock_time = world.time + 5
|
||||
if(G.aim_targets)
|
||||
for(var/mob/living/M in G.aim_targets)
|
||||
if(target_can_click)
|
||||
M << "Your character may now <b>use items</b> at the discretion of their targeter."
|
||||
else
|
||||
M << "<span class='danger'><b>Your character will now be shot if they use items.</b></span>"
|
||||
|
||||
/client/verb/AllowTargetRadio()
|
||||
set hidden=1
|
||||
|
||||
target_can_radio = !target_can_radio
|
||||
if(target_can_radio)
|
||||
usr << "Target may now use radio."
|
||||
else
|
||||
usr << "Target may no longer use radio."
|
||||
|
||||
if(usr.radio_use_icon)
|
||||
usr.radio_use_icon.icon_state = "no_radio[target_can_radio]"
|
||||
usr.radio_use_icon.name = "[target_can_radio ? "Disallow" : "Allow"] Radio Use"
|
||||
|
||||
//Handling change for all the guns on client
|
||||
for(var/obj/item/weapon/gun/G in src)
|
||||
G.lock_time = world.time + 5
|
||||
if(G.aim_targets)
|
||||
for(var/mob/living/M in G.aim_targets)
|
||||
if(target_can_radio)
|
||||
M << "Your character may now <b>use the radio</b> at the discretion of their targeter."
|
||||
else
|
||||
M << "<span class='danger'><b>Your character will now be shot if they use the radio.</b></span>"
|
||||
12
code/modules/projectiles/targeting/targeting_client.dm
Normal file
12
code/modules/projectiles/targeting/targeting_client.dm
Normal file
@@ -0,0 +1,12 @@
|
||||
//These are called by the on-screen buttons, adjusting what the victim can and cannot do.
|
||||
/client/proc/add_gun_icons()
|
||||
if(!usr) return 1 // This can runtime if someone manages to throw a gun out of their hand before the proc is called.
|
||||
screen |= usr.item_use_icon
|
||||
screen |= usr.gun_move_icon
|
||||
screen |= usr.radio_use_icon
|
||||
|
||||
/client/proc/remove_gun_icons()
|
||||
if(!usr) return 1 // Runtime prevention on N00k agents spawning with SMG
|
||||
screen -= usr.item_use_icon
|
||||
screen -= usr.gun_move_icon
|
||||
screen -= usr.radio_use_icon
|
||||
21
code/modules/projectiles/targeting/targeting_gun.dm
Normal file
21
code/modules/projectiles/targeting/targeting_gun.dm
Normal file
@@ -0,0 +1,21 @@
|
||||
//Removing the lock and the buttons.
|
||||
/obj/item/weapon/gun/dropped(var/mob/living/user)
|
||||
if(istype(user))
|
||||
user.stop_aiming(src)
|
||||
return ..()
|
||||
|
||||
/obj/item/weapon/gun/equipped(var/mob/living/user, var/slot)
|
||||
if(istype(user) && (slot != slot_l_hand && slot != slot_r_hand))
|
||||
user.stop_aiming(src)
|
||||
return ..()
|
||||
|
||||
//Compute how to fire.....
|
||||
//Return 1 if a target was found, 0 otherwise.
|
||||
/obj/item/weapon/gun/proc/PreFire(var/atom/A, var/mob/living/user, var/params)
|
||||
if(!user.aiming)
|
||||
user.aiming = new(user)
|
||||
user.face_atom(A)
|
||||
if(ismob(A) && user.aiming)
|
||||
user.aiming.aim_at(A, src)
|
||||
return 1
|
||||
return 0
|
||||
44
code/modules/projectiles/targeting/targeting_mob.dm
Normal file
44
code/modules/projectiles/targeting/targeting_mob.dm
Normal file
@@ -0,0 +1,44 @@
|
||||
/mob/living/var/obj/aiming_overlay/aiming
|
||||
/mob/living/var/list/aimed = list()
|
||||
|
||||
/mob/verb/toggle_gun_mode()
|
||||
set name = "Toggle Gun Mode"
|
||||
set desc = "Begin or stop aiming."
|
||||
set category = "IC"
|
||||
|
||||
if(isliving(src))
|
||||
var/mob/living/M = src
|
||||
if(!M.aiming)
|
||||
M.aiming = new(src)
|
||||
M.aiming.toggle_active()
|
||||
else
|
||||
src << "<span class='warning'>This verb may only be used by living mobs, sorry.</span>"
|
||||
return
|
||||
|
||||
/mob/living/proc/stop_aiming(var/obj/item/thing, var/no_message = 0)
|
||||
if(!aiming)
|
||||
aiming = new(src)
|
||||
if(thing && aiming.aiming_with != thing)
|
||||
return
|
||||
aiming.cancel_aiming(no_message)
|
||||
|
||||
/mob/living/death(gibbed,deathmessage="seizes up and falls limp...")
|
||||
if(..())
|
||||
stop_aiming(no_message=1)
|
||||
|
||||
/mob/living/update_canmove()
|
||||
..()
|
||||
if(lying)
|
||||
stop_aiming(no_message=1)
|
||||
|
||||
/mob/living/Weaken(amount)
|
||||
stop_aiming(no_message=1)
|
||||
..()
|
||||
|
||||
/mob/living/Destroy()
|
||||
if(aiming)
|
||||
qdel(aiming)
|
||||
aiming = null
|
||||
aimed.Cut()
|
||||
return ..()
|
||||
|
||||
224
code/modules/projectiles/targeting/targeting_overlay.dm
Normal file
224
code/modules/projectiles/targeting/targeting_overlay.dm
Normal file
@@ -0,0 +1,224 @@
|
||||
/obj/aiming_overlay
|
||||
name = ""
|
||||
desc = "Stick 'em up!"
|
||||
icon = 'icons/effects/Targeted.dmi'
|
||||
icon_state = "locking"
|
||||
anchored = 1
|
||||
density = 0
|
||||
opacity = 0
|
||||
layer = FLY_LAYER
|
||||
simulated = 0
|
||||
mouse_opacity = 0
|
||||
|
||||
var/mob/living/aiming_at // Who are we currently targeting, if anyone?
|
||||
var/obj/item/aiming_with // What are we targeting with?
|
||||
var/mob/living/owner // Who do we belong to?
|
||||
var/locked = 0 // Have we locked on?
|
||||
var/lock_time = 0 // When -will- we lock on?
|
||||
var/active = 0 // Is our owner intending to take hostages?
|
||||
var/target_permissions = 0 // Permission bitflags.
|
||||
|
||||
/obj/aiming_overlay/New(var/newowner)
|
||||
..()
|
||||
owner = newowner
|
||||
loc = null
|
||||
verbs.Cut()
|
||||
|
||||
/obj/aiming_overlay/proc/toggle_permission(var/perm)
|
||||
|
||||
if(target_permissions & perm)
|
||||
target_permissions &= ~perm
|
||||
else
|
||||
target_permissions |= perm
|
||||
|
||||
// Update HUD icons.
|
||||
if(owner.gun_move_icon)
|
||||
if(!(target_permissions & TARGET_CAN_MOVE))
|
||||
owner.gun_move_icon.icon_state = "no_walk0"
|
||||
owner.gun_move_icon.name = "Allow Movement"
|
||||
else
|
||||
owner.gun_move_icon.icon_state = "no_walk1"
|
||||
owner.gun_move_icon.name = "Disallow Movement"
|
||||
|
||||
if(owner.item_use_icon)
|
||||
if(!(target_permissions & TARGET_CAN_CLICK))
|
||||
owner.item_use_icon.icon_state = "no_item0"
|
||||
owner.item_use_icon.name = "Allow Item Use"
|
||||
else
|
||||
owner.item_use_icon.icon_state = "no_item1"
|
||||
owner.item_use_icon.name = "Disallow Item Use"
|
||||
|
||||
if(owner.radio_use_icon)
|
||||
if(!(target_permissions & TARGET_CAN_RADIO))
|
||||
owner.radio_use_icon.icon_state = "no_radio0"
|
||||
owner.radio_use_icon.name = "Allow Radio Use"
|
||||
else
|
||||
owner.radio_use_icon.icon_state = "no_radio1"
|
||||
owner.radio_use_icon.name = "Disallow Radio Use"
|
||||
|
||||
var/message = "no longer permitted to "
|
||||
var/use_span = "warning"
|
||||
if(target_permissions & perm)
|
||||
message = "now permitted to "
|
||||
use_span = "notice"
|
||||
|
||||
switch(perm)
|
||||
if(TARGET_CAN_MOVE)
|
||||
message += "move"
|
||||
if(TARGET_CAN_CLICK)
|
||||
message += "use items"
|
||||
if(TARGET_CAN_RADIO)
|
||||
message += "use a radio"
|
||||
else
|
||||
return
|
||||
|
||||
owner << "<span class='[use_span]'>[aiming_at ? "\The [aiming_at] is" : "Your targets are"] [message].</span>"
|
||||
if(aiming_at)
|
||||
aiming_at << "<span class='[use_span]'>You are [message].</span>"
|
||||
|
||||
/obj/aiming_overlay/process()
|
||||
if(!owner)
|
||||
qdel(src)
|
||||
return
|
||||
..()
|
||||
update_aiming()
|
||||
|
||||
/obj/aiming_overlay/Destroy()
|
||||
cancel_aiming(1)
|
||||
owner = null
|
||||
return ..()
|
||||
|
||||
obj/aiming_overlay/proc/update_aiming_deferred()
|
||||
set waitfor = 0
|
||||
sleep(0)
|
||||
update_aiming()
|
||||
|
||||
/obj/aiming_overlay/proc/update_aiming()
|
||||
|
||||
if(!owner)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
if(!aiming_at)
|
||||
cancel_aiming()
|
||||
return
|
||||
|
||||
if(!locked && lock_time >= world.time)
|
||||
locked = 1
|
||||
update_icon()
|
||||
|
||||
var/cancel_aim = 1
|
||||
|
||||
if(!(aiming_with in owner) || (istype(owner, /mob/living/carbon/human) && (owner.l_hand != aiming_with && owner.r_hand != aiming_with)))
|
||||
owner << "<span class='warning'>You must keep hold of your weapon!</span>"
|
||||
else if(!aiming_at || !istype(aiming_at.loc, /turf))
|
||||
owner << "<span class='warning'>You have lost sight of your target!</span>"
|
||||
else if(owner.incapacitated() || owner.lying || owner.restrained())
|
||||
owner << "<span class='warning'>You must be conscious and standing to keep track of your target!</span>"
|
||||
else if(aiming_at.alpha == 0 || (aiming_at.invisibility > owner.see_invisible))
|
||||
owner << "<span class='warning'>Your target has become invisible!</span>"
|
||||
else if(!(aiming_at in view(owner)))
|
||||
owner << "<span class='warning'>Your target is too far away to track!</span>"
|
||||
else
|
||||
cancel_aim = 0
|
||||
|
||||
forceMove(get_turf(aiming_at))
|
||||
|
||||
if(cancel_aim)
|
||||
cancel_aiming()
|
||||
return
|
||||
|
||||
if(!owner.incapacitated() && owner.client)
|
||||
spawn(0)
|
||||
owner.set_dir(get_dir(get_turf(owner), get_turf(src)))
|
||||
|
||||
/obj/aiming_overlay/proc/aim_at(var/mob/target, var/obj/thing)
|
||||
|
||||
if(!owner)
|
||||
return
|
||||
|
||||
if(owner.incapacitated())
|
||||
owner << "<span class='warning'>You cannot aim a gun in your current state.</span>"
|
||||
return
|
||||
if(owner.lying)
|
||||
owner << "<span class='warning'>You cannot aim a gun while prone.</span>"
|
||||
return
|
||||
if(owner.restrained())
|
||||
owner << "<span class='warning'>You cannot aim a gun while handcuffed.</span>"
|
||||
return
|
||||
|
||||
if(aiming_at)
|
||||
if(aiming_at == target)
|
||||
return
|
||||
cancel_aiming(1)
|
||||
owner.visible_message("<span class='danger'>\The [owner] turns \the [thing] on \the [target]!</span>")
|
||||
else
|
||||
owner.visible_message("<span class='danger'>\The [owner] aims \the [thing] at \the [target]!</span>")
|
||||
|
||||
if(owner.client)
|
||||
owner.client.add_gun_icons()
|
||||
target << "<span class='danger'>You now have a gun pointed at you. No sudden moves!</span>"
|
||||
aiming_with = thing
|
||||
aiming_at = target
|
||||
if(istype(aiming_with, /obj/item/weapon/gun))
|
||||
playsound(get_turf(owner), 'sound/weapons/TargetOn.ogg', 50,1)
|
||||
|
||||
forceMove(get_turf(target))
|
||||
processing_objects |= src
|
||||
|
||||
aiming_at.aimed |= src
|
||||
toggle_active(1)
|
||||
locked = 0
|
||||
update_icon()
|
||||
lock_time = world.time + 35
|
||||
moved_event.register(owner, src, /obj/aiming_overlay/proc/update_aiming)
|
||||
moved_event.register(aiming_at, src, /obj/aiming_overlay/proc/target_moved)
|
||||
destroyed_event.register(aiming_at, src, /obj/aiming_overlay/proc/cancel_aiming)
|
||||
|
||||
/obj/aiming_overlay/update_icon()
|
||||
if(locked)
|
||||
icon_state = "locked"
|
||||
else
|
||||
icon_state = "locking"
|
||||
|
||||
/obj/aiming_overlay/proc/toggle_active(var/force_state = null)
|
||||
if(!isnull(force_state))
|
||||
if(active == force_state)
|
||||
return
|
||||
active = force_state
|
||||
else
|
||||
active = !active
|
||||
|
||||
if(!active)
|
||||
cancel_aiming()
|
||||
|
||||
if(owner.client)
|
||||
if(active)
|
||||
owner << "<span class='notice'>You will now aim rather than fire.</span>"
|
||||
owner.client.add_gun_icons()
|
||||
else
|
||||
owner << "<span class='notice'>You will no longer aim rather than fire.</span>"
|
||||
owner.client.remove_gun_icons()
|
||||
|
||||
/obj/aiming_overlay/proc/cancel_aiming(var/no_message = 0)
|
||||
if(!aiming_with || !aiming_at)
|
||||
return
|
||||
if(istype(aiming_with, /obj/item/weapon/gun))
|
||||
playsound(get_turf(owner), 'sound/weapons/TargetOff.ogg', 50,1)
|
||||
if(!no_message)
|
||||
owner.visible_message("<span class='notice'>\The [owner] lowers \the [aiming_with].</span>")
|
||||
|
||||
moved_event.unregister(owner, src)
|
||||
if(aiming_at)
|
||||
moved_event.unregister(aiming_at, src)
|
||||
destroyed_event.unregister(aiming_at, src)
|
||||
aiming_at.aimed -= src
|
||||
aiming_at = null
|
||||
|
||||
aiming_with = null
|
||||
loc = null
|
||||
processing_objects -= src
|
||||
|
||||
/obj/aiming_overlay/proc/target_moved()
|
||||
update_aiming()
|
||||
trigger(TARGET_CAN_MOVE)
|
||||
29
code/modules/projectiles/targeting/targeting_triggers.dm
Normal file
29
code/modules/projectiles/targeting/targeting_triggers.dm
Normal file
@@ -0,0 +1,29 @@
|
||||
/mob/living/proc/trigger_aiming(var/trigger_type)
|
||||
if(!aimed.len)
|
||||
return
|
||||
for(var/obj/aiming_overlay/AO in aimed)
|
||||
if(AO.aiming_at == src)
|
||||
AO.update_aiming()
|
||||
if(AO.aiming_at == src)
|
||||
AO.trigger(trigger_type)
|
||||
AO.update_aiming_deferred()
|
||||
|
||||
/obj/aiming_overlay/proc/trigger(var/perm)
|
||||
if(!owner || !aiming_with || !aiming_at || !locked)
|
||||
return
|
||||
if(perm && (target_permissions & perm))
|
||||
return
|
||||
if(!owner.canClick())
|
||||
return
|
||||
owner.setClickCooldown(5) // Spam prevention, essentially.
|
||||
if(owner.a_intent == I_HELP)
|
||||
owner << "<span class='warning'>You refrain from firing \the [aiming_with] as your intent is set to help.</span>"
|
||||
return
|
||||
owner.visible_message("<span class='danger'>\The [owner] pulls the trigger reflexively!</span>")
|
||||
var/obj/item/weapon/gun/G = aiming_with
|
||||
if(istype(G))
|
||||
G.Fire(aiming_at, owner)
|
||||
|
||||
/mob/living/ClickOn(var/atom/A, var/params)
|
||||
. = ..()
|
||||
trigger_aiming(TARGET_CAN_CLICK)
|
||||
Reference in New Issue
Block a user