Merge remote-tracking branch 'bay12-upstream/master' into development

This commit is contained in:
skull132
2016-10-07 00:58:39 +03:00
1594 changed files with 53994 additions and 48590 deletions

View File

@@ -90,6 +90,7 @@
var/list/ammo_states = list() //values
/obj/item/ammo_magazine/New()
..()
if(multiple_sprites)
initialize_magazine_icondata(src)

View File

@@ -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
*/

View File

@@ -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

View File

@@ -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()

View File

@@ -1,16 +1,9 @@
/datum/firemode/energy
var/projectile_type = null
var/modifystate = null
var/charge_cost = null
var/fire_sound = null
/obj/item/weapon/gun/energy
name = "energy gun"
desc = "A basic energy-based gun."
icon_state = "energy"
fire_sound = 'sound/weapons/Taser.ogg'
fire_sound_text = "laser blast"
firemode_type = /datum/firemode/energy
var/obj/item/weapon/cell/power_supply //What type of power cell this uses
var/charge_cost = 200 //How much energy is needed to fire.
@@ -26,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()

View File

@@ -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'

View File

@@ -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()

View File

@@ -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

View File

@@ -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>")

View File

@@ -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'

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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")

View File

@@ -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)
..()

View File

@@ -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

View File

@@ -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

View File

@@ -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'

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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>"

View 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

View 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

View 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 ..()

View 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)

View 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)