Merge resolution.

This commit is contained in:
Zuhayr
2015-05-11 11:47:24 +09:30
777 changed files with 22019 additions and 21336 deletions
@@ -40,6 +40,10 @@
name = "magazine (.45 rubber)"
ammo_type = /obj/item/ammo_casing/c45r
/obj/item/ammo_magazine/c45m/practice
name = "magazine (.45 practice)"
ammo_type = /obj/item/ammo_casing/c45p
/obj/item/ammo_magazine/c45m/flash
name = "magazine (.45 flash)"
ammo_type = "/obj/item/ammo_casing/c45f"
@@ -90,6 +94,10 @@
name = "top mounted magazine (9mm rubber)"
ammo_type = /obj/item/ammo_casing/c9mmr
/obj/item/ammo_magazine/mc9mmt/practice
name = "top mounted magazine (9mm practice)"
ammo_type = /obj/item/ammo_casing/c9mmp
/obj/item/ammo_magazine/c45
name = "ammunition Box (.45)"
icon_state = "9mm"
@@ -130,6 +138,10 @@
/obj/item/ammo_magazine/a556/empty
initial_ammo = 0
/obj/item/ammo_magazine/a556/practice
name = "magazine (5.56mm practice)"
ammo_type = /obj/item/ammo_casing/a556p
/obj/item/ammo_magazine/a50
name = "magazine (.50)"
icon_state = "50ae"
@@ -38,12 +38,22 @@
caliber = "9mm"
projectile_type = /obj/item/projectile/bullet/pistol/rubber
/obj/item/ammo_casing/c9mmp
desc = "A 9mm practice bullet casing."
caliber = "9mm"
projectile_type = /obj/item/projectile/bullet/pistol/practice
/obj/item/ammo_casing/c45
desc = "A .45 bullet casing."
caliber = ".45"
projectile_type = /obj/item/projectile/bullet/pistol/medium
/obj/item/ammo_casing/c45p
desc = "A .45 practice bullet casing."
caliber = ".45"
projectile_type = /obj/item/projectile/bullet/pistol/practice
/obj/item/ammo_casing/c45r
desc = "A .45 rubber bullet casing."
caliber = ".45"
@@ -82,6 +92,13 @@
projectile_type = /obj/item/projectile/bullet/blank
matter = list("steel" = 90)
/obj/item/ammo_casing/shotgun/practice
name = "shotgun shell"
desc = "A practice shell."
icon_state = "pshell"
projectile_type = /obj/item/projectile/bullet/shotgun/practice
matter = list("metal" = 90)
/obj/item/ammo_casing/shotgun/beanbag
name = "beanbag shell"
desc = "A beanbag shell."
@@ -130,6 +147,11 @@
caliber = "a556"
projectile_type = /obj/item/projectile/bullet/rifle/a556
/obj/item/ammo_casing/a556p
desc = "A 5.56mm practice bullet casing."
caliber = "a556"
projectile_type = /obj/item/projectile/bullet/rifle/a556/practice
/obj/item/ammo_casing/rocket
name = "rocket shell"
desc = "A high explosive designed to be fired from a launcher."
+4 -4
View File
@@ -13,7 +13,7 @@
/obj/effect/projectile/proc/activate()
spawn(3)
delete() //see effect_system.dm - sets loc to null and lets GC handle removing these effects
qdel(src) //see effect_system.dm - sets loc to null and lets GC handle removing these effects
return
@@ -100,13 +100,13 @@
//----------------------------
/obj/effect/projectile/emitter/tracer
icon_state = "emitter"
/obj/effect/projectile/emitter/muzzle
icon_state = "muzzle_emitter"
/obj/effect/projectile/emitter/impact
icon_state = "impact_emitter"
//----------------------------
// Stun beam
//----------------------------
+161 -53
View File
@@ -1,11 +1,41 @@
/*
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.
*/
/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)
//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)
..()
if(!properties) return
for(var/propname in vars)
if(!isnull(properties[propname]))
src.vars[propname] = properties[propname]
//Parent gun type. Guns are weapons that can be aimed at mobs and act over a distance
/obj/item/weapon/gun
name = "gun"
desc = "Its a gun. It's pretty terrible, though."
icon = 'icons/obj/gun.dmi'
item_icons = list(
icon_l_hand = 'icons/mob/items/lefthand_guns.dmi',
icon_r_hand = 'icons/mob/items/righthand_guns.dmi',
slot_l_hand_str = 'icons/mob/items/lefthand_guns.dmi',
slot_r_hand_str = 'icons/mob/items/righthand_guns.dmi',
)
icon_state = "detective"
item_state = "gun"
@@ -21,15 +51,21 @@
attack_verb = list("struck", "hit", "bashed")
zoomdevicename = "scope"
var/fire_delay = 6
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/fire_sound = 'sound/weapons/Gunshot.ogg'
var/fire_sound_text = "gunshot"
var/recoil = 0 //screen shake
var/silenced = 0
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/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/last_fired = 0
var/next_fire_time = 0
var/sel_mode = 1 //index of the currently selected mode
var/list/firemodes = list()
var/firemode_type = /datum/firemode //for subtypes that need custom firemode data
//aiming system stuff
var/keep_aim = 1 //1 for keep shooting until aim is lowered
@@ -42,17 +78,15 @@
/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])
if(isnull(scoped_accuracy))
scoped_accuracy = accuracy
//Returns 1 if the gun is able to be fired
/obj/item/weapon/gun/proc/ready_to_fire()
if(world.time >= last_fired + fire_delay)
last_fired = world.time
return 1
else
return 0
//Checks whether a given mob can use the gun
//Any checks that shouldn't result in handle_click_empty() being called if they fail should go here.
//Otherwise, if you want handle_click_empty() to be called, check in consume_next_projectile() and return null there.
@@ -114,7 +148,7 @@
else
return ..() //Pistolwhippin'
/obj/item/weapon/gun/proc/Fire(atom/target, mob/living/user, params, pointblank=0, reflex=0)
/obj/item/weapon/gun/proc/Fire(atom/target, mob/living/user, clickparams, pointblank=0, reflex=0)
if(!user || !target) return
add_fingerprint(user)
@@ -122,24 +156,55 @@
if(!special_check(user))
return
if (!ready_to_fire())
if(world.time < next_fire_time)
if (world.time % 3) //to prevent spam
user << "<span class='warning'>[src] is not ready to fire again!"
user << "<span class='warning'>[src] is not ready to fire again!</span>"
return
var/obj/projectile = consume_next_projectile(user)
if(!projectile)
handle_click_empty(user)
return
//unpack firemode data
var/datum/firemode/firemode = firemodes[sel_mode]
var/_burst = firemode.burst
var/_burst_delay = isnull(firemode.burst_delay)? src.burst_delay : firemode.burst_delay
var/_fire_delay = isnull(firemode.fire_delay)? src.fire_delay : firemode.fire_delay
var/_move_delay = firemode.move_delay
var/shoot_time = (_burst - 1)*_burst_delay
user.next_move = world.time + shoot_time //no clicking on things while shooting
if(user.client) user.client.move_delay = world.time + shoot_time //no moving while shooting either
next_fire_time = world.time + shoot_time
//actually attempt to shoot
var/turf/targloc = get_turf(target) //cache this in case target gets deleted during shooting, e.g. if it was a securitron that got destroyed.
for(var/i in 1 to _burst)
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)]
process_accuracy(projectile, user, target, acc, disp)
if(pointblank)
process_point_blank(projectile, user, target)
if(process_projectile(projectile, user, target, user.zone_sel.selecting, clickparams))
handle_post_fire(user, target, pointblank, reflex)
update_icon()
if(i < _burst)
sleep(_burst_delay)
if(!(target && target.loc))
target = targloc
pointblank = 0
update_held_icon()
//update timing
user.next_move = world.time + 4
if(process_projectile(projectile, user, target, user.zone_sel.selecting, params, pointblank, reflex))
handle_post_fire(user, target, pointblank, reflex)
update_icon()
update_held_icon()
if(user.client) user.client.move_delay = world.time + _move_delay
next_fire_time = world.time + _fire_delay
//obtains the next projectile to fire
/obj/item/weapon/gun/proc/consume_next_projectile()
@@ -181,17 +246,63 @@
"You hear a [fire_sound_text]!"
)
if(muzzle_flash)
var/turf/T_user = get_turf(user)
var/turf/T_target = get_turf(target)
var/obj/effect/effect/smoke/illumination/I = new /obj/effect/effect/smoke/illumination(get_step(T_user, get_dir(T_user,T_target)), brightness=muzzle_flash, lifetime=8)
I.alpha = 0
if(recoil)
spawn()
shake_camera(user, recoil+1, recoil)
update_icon()
//does the actual shooting
/obj/item/weapon/gun/proc/process_projectile(obj/projectile, mob/user, atom/target, var/target_zone, var/params=null, var/pointblank=0, var/reflex=0)
if(!istype(projectile, /obj/item/projectile))
/obj/item/weapon/gun/proc/process_point_blank(obj/projectile, mob/user, atom/target)
var/obj/item/projectile/P = projectile
if(!istype(P))
return //default behaviour only applies to true projectiles
//default point blank multiplier
var/damage_mult = 1.3
//determine multiplier due to the target being grabbed
if(ismob(target))
var/mob/M = target
if(M.grabbed_by.len)
var/grabstate = 0
for(var/obj/item/weapon/grab/G in M.grabbed_by)
grabstate = max(grabstate, G.state)
if(grabstate >= GRAB_NECK)
damage_mult = 3.0
else if(grabstate >= GRAB_AGGRESSIVE)
damage_mult = 1.5
P.damage *= damage_mult
/obj/item/weapon/gun/proc/process_accuracy(obj/projectile, mob/user, atom/target, acc_mod, dispersion)
var/obj/item/projectile/P = projectile
if(!istype(P))
return //default behaviour only applies to true projectiles
//Accuracy modifiers
P.accuracy = accuracy + acc_mod
P.dispersion = dispersion
//accuracy bonus from aiming
if (aim_targets && (target in aim_targets))
//If you aim at someone beforehead, it'll hit more often.
//Kinda balanced by fact you need like 2 seconds to aim
//As opposed to no-delay pew pew
P.accuracy += 2
//does the actual launching of the projectile
/obj/item/weapon/gun/proc/process_projectile(obj/projectile, mob/user, atom/target, var/target_zone, var/params=null)
var/obj/item/projectile/P = projectile
if(!istype(P))
return 0 //default behaviour only applies to true projectiles
var/obj/item/projectile/P = projectile
if(params)
P.set_clickpoint(params)
//shooting while in shock
var/x_offset = 0
@@ -205,27 +316,6 @@
y_offset = rand(-1,1)
x_offset = rand(-1,1)
//Point blank bonus
if(pointblank)
var/damage_mult = 1.3 //default point blank multiplier
//determine multiplier due to the target being grabbed
if(ismob(target))
var/mob/M = target
if(M.grabbed_by.len)
var/grabstate = 0
for(var/obj/item/weapon/grab/G in M.grabbed_by)
grabstate = max(grabstate, G.state)
if(grabstate >= GRAB_NECK)
damage_mult = 3.0
else if (grabstate >= GRAB_AGGRESSIVE)
damage_mult = 1.5
P.damage *= damage_mult
if(params)
P.set_clickpoint(params)
return !P.launch(target, user, src, target_zone, x_offset, y_offset)
//Suicide handling.
@@ -260,7 +350,7 @@
else
user << "<span class = 'notice'>Ow...</span>"
user.apply_effect(110,AGONY,0)
del(in_chamber)
qdel(in_chamber)
mouthshoot = 0
return
else
@@ -287,3 +377,21 @@
if(!zoom)
accuracy = initial(accuracy)
recoil = initial(recoil)
/obj/item/weapon/gun/examine(mob/user)
..()
if(firemodes.len > 1)
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)
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>"
/obj/item/weapon/gun/attack_self(mob/user)
if(firemodes.len > 1)
switch_firemodes(user)
+1 -1
View File
@@ -20,7 +20,7 @@
processing_objects.Add(src)
last_regen = world.time
/obj/item/weapon/gun/launcher/spikethrower/Del()
/obj/item/weapon/gun/launcher/spikethrower/Destroy()
processing_objects.Remove(src)
..()
+32 -7
View File
@@ -1,9 +1,16 @@
/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 = 100 //How much energy is needed to fire.
@@ -11,13 +18,25 @@
var/projectile_type = /obj/item/projectile/beam/practice
var/modifystate
var/charge_meter = 1 //if set, the icon state will be chosen based on the current charge
//self-recharging
var/self_recharge = 0 //if set, the weapon will recharge itself
var/use_external_power = 0 //if set, the weapon will look for an external power source to draw from, otherwise it recharges magically
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
update_icon()
update_held_icon()
/obj/item/weapon/gun/energy/emp_act(severity)
..()
update_icon()
@@ -31,7 +50,7 @@
processing_objects.Add(src)
update_icon()
/obj/item/weapon/gun/energy/Del()
/obj/item/weapon/gun/energy/Destroy()
if(self_recharge)
processing_objects.Remove(src)
..()
@@ -41,15 +60,15 @@
charge_tick++
if(charge_tick < recharge_time) return 0
charge_tick = 0
if(!power_supply || power_supply.charge >= power_supply.maxcharge)
return 0 // check if we actually need to recharge
if(use_external_power)
var/obj/item/weapon/cell/external = get_external_power_supply()
if(!external || !external.use(charge_cost)) //Take power from the borg...
return 0
power_supply.give(charge_cost) //... to recharge the shot
update_icon()
return 1
@@ -74,16 +93,22 @@
return suit.cell
return null
/obj/item/weapon/gun/energy/examine(mob/user)
..(user)
var/shots_remaining = round(power_supply.charge / charge_cost)
user << "Has [shots_remaining] shot\s remaining."
return
/obj/item/weapon/gun/energy/update_icon()
if(charge_meter)
var/ratio = power_supply.charge / power_supply.maxcharge
//make sure that rounding down will not give us the empty state even if we have charge for a shot left.
if(power_supply.charge < charge_cost)
ratio = 0
else
ratio = max(round(ratio, 0.25) * 100, 25)
if(modifystate)
icon_state = "[modifystate][ratio]"
else
+16 -25
View File
@@ -10,26 +10,10 @@
origin_tech = "combat=3;magnets=2"
modifystate = "energystun"
var/mode = 0 //0 = stun, 1 = kill
/obj/item/weapon/gun/energy/gun/attack_self(mob/living/user as mob)
switch(mode)
if(0)
mode = 1
charge_cost = 100
fire_sound = 'sound/weapons/Laser.ogg'
user << "<span class='warning'>[src.name] is now set to kill.</span>"
projectile_type = /obj/item/projectile/beam
modifystate = "energykill"
if(1)
mode = 0
charge_cost = 100
fire_sound = 'sound/weapons/Taser.ogg'
user << "<span class='warning'>[src.name] is now set to stun.</span>"
projectile_type = /obj/item/projectile/beam/stun
modifystate = "energystun"
update_icon()
update_held_icon()
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'),
)
/obj/item/weapon/gun/energy/gun/mounted
name = "mounted energy gun"
@@ -43,7 +27,14 @@
origin_tech = "combat=3;materials=5;powerstorage=3"
slot_flags = SLOT_BELT
force = 8 //looks heavier than a pistol
self_recharge = 1
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'),
)
var/lightfail = 0
//override for failcheck behaviour
@@ -101,10 +92,10 @@
overlays += "nucgun-clean"
/obj/item/weapon/gun/energy/gun/nuclear/proc/update_mode()
if (mode == 0)
overlays += "nucgun-stun"
else if (mode == 1)
overlays += "nucgun-kill"
var/datum/firemode/current_mode = firemodes[sel_mode]
switch(current_mode.name)
if("stun") overlays += "nucgun-stun"
if("lethal") overlays += "nucgun-kill"
/obj/item/weapon/gun/energy/gun/nuclear/emp_act(severity)
..()
+16 -33
View File
@@ -5,33 +5,16 @@
item_state = null //so the human update icon uses the icon_state instead.
slot_flags = SLOT_BELT|SLOT_BACK
force = 10
fire_sound = 'sound/weapons/pulse.ogg'
charge_cost = 200
projectile_type = /obj/item/projectile/beam/pulse
cell_type = /obj/item/weapon/cell/super
var/mode = 2
fire_delay = 25
/obj/item/weapon/gun/energy/pulse_rifle/attack_self(mob/living/user as mob)
switch(mode)
if(2)
mode = 0
charge_cost = 100
fire_sound = 'sound/weapons/Taser.ogg'
user << "<span class='warning'>[src.name] is now set to stun.</span>"
projectile_type = /obj/item/projectile/beam/stun
if(0)
mode = 1
charge_cost = 100
fire_sound = 'sound/weapons/Laser.ogg'
user << "<span class='warning'>[src.name] is now set to kill.</span>"
projectile_type = /obj/item/projectile/beam
if(1)
mode = 2
charge_cost = 200
fire_sound = 'sound/weapons/pulse.ogg'
user << "<span class='warning'>[src.name] is now set to DESTROY.</span>"
projectile_type = /obj/item/projectile/beam/pulse
fire_sound='sound/weapons/Laser.ogg'
charge_cost = 50
projectile_type = /obj/item/projectile/beam
sel_mode = 2
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=100),
)
/obj/item/weapon/gun/energy/pulse_rifle/mounted
self_recharge = 1
@@ -40,12 +23,13 @@
/obj/item/weapon/gun/energy/pulse_rifle/destroyer
name = "pulse destroyer"
desc = "A heavy-duty, pulse-based energy weapon. Because of its complexity and cost, it is rarely seen in use except by specialists."
cell_type = /obj/item/weapon/cell/infinite
fire_delay = 10
cell_type = /obj/item/weapon/cell/super
fire_delay = 25
fire_sound='sound/weapons/pulse.ogg'
projectile_type=/obj/item/projectile/beam/pulse
/obj/item/weapon/gun/energy/pulse_rifle/destroyer/attack_self(mob/living/user as mob)
user << "<span class='warning'>[src.name] has three settings, and they are all DESTROY.</span>"
user << "<span class='warning'>[src.name] has three settings, and they are all DESTROY.</span>"
//WHY?
/obj/item/weapon/gun/energy/pulse_rifle/M1911
@@ -53,5 +37,4 @@
desc = "It's not the size of the gun, it's the size of the hole it puts through people."
slot_flags = SLOT_BELT|SLOT_HOLSTER
icon_state = "m1911-p"
cell_type = /obj/item/weapon/cell/infinite
fire_delay = 10
cell_type = /obj/item/weapon/cell/crap
@@ -43,24 +43,11 @@
origin_tech = "materials=2;biotech=3;powerstorage=3"
modifystate = "floramut"
self_recharge = 1
var/mode = 0 //0 = mutate, 1 = yield boost
/obj/item/weapon/gun/energy/floragun/attack_self(mob/living/user as mob)
switch(mode)
if(0)
mode = 1
charge_cost = 100
user << "<span class='warning'>The [src.name] is now set to increase yield.</span>"
projectile_type = /obj/item/projectile/energy/florayield
modifystate = "florayield"
if(1)
mode = 0
charge_cost = 100
user << "<span class='warning'>The [src.name] is now set to induce mutations.</span>"
projectile_type = /obj/item/projectile/energy/floramut
modifystate = "floramut"
update_icon()
update_held_icon()
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"),
)
/obj/item/weapon/gun/energy/floragun/afterattack(obj/target, mob/user, adjacent_flag)
//allow shooting into adjacent hydrotrays regardless of intent
@@ -18,7 +18,7 @@
processing_objects.Add(src)
/obj/item/weapon/gun/energy/temperature/Del()
/obj/item/weapon/gun/energy/temperature/Destroy()
processing_objects.Remove(src)
..()
+1 -3
View File
@@ -7,6 +7,7 @@
var/release_force = 0
var/throw_distance = 10
muzzle_flash = 0
fire_sound_text = "a launcher firing"
//This normally uses a proc on projectiles and our ammo is not strictly speaking a projectile.
@@ -26,6 +27,3 @@
projectile.loc = get_turf(user)
projectile.throw_at(target, throw_distance, release_force, user)
return 1
/obj/item/weapon/gun/launcher/attack_self(mob/living/user as mob)
return
@@ -43,7 +43,7 @@
user << "[src] shatters into a scattering of overstressed metal shards as it leaves the crossbow."
var/obj/item/weapon/shard/shrapnel/S = new()
S.loc = get_turf(src)
src.Del()
qdel(src)
/obj/item/weapon/gun/launcher/crossbow
name = "powered crossbow"
@@ -257,7 +257,7 @@
if(buildstate == 5)
user << "\blue You secure the crossbow's various parts."
new /obj/item/weapon/gun/launcher/crossbow(get_turf(src))
del(src)
qdel(src)
return
else
..()
@@ -150,7 +150,7 @@
if(istype(W,/obj/item/pipe))
if(buildstate == 0)
user.drop_item()
del(W)
qdel(W)
user << "\blue You secure the piping inside the frame."
buildstate++
update_icon()
@@ -168,7 +168,7 @@
else if(istype(W,/obj/item/device/transfer_valve))
if(buildstate == 4)
user.drop_item()
del(W)
qdel(W)
user << "\blue You install the transfer valve and connect it to the piping."
buildstate++
update_icon()
@@ -197,7 +197,7 @@
playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
user << "\blue You weld the valve into place."
new /obj/item/weapon/gun/launcher/pneumatic(get_turf(src))
del(src)
qdel(src)
return
else
..()
+17 -2
View File
@@ -165,7 +165,10 @@
load_ammo(A, user)
/obj/item/weapon/gun/projectile/attack_self(mob/user as mob)
unload_ammo(user)
if(firemodes.len > 1)
switch_firemodes(user)
else
unload_ammo(user)
/obj/item/weapon/gun/projectile/attack_hand(mob/user as mob)
if(user.get_inactive_hand() == src)
@@ -189,9 +192,9 @@
/obj/item/weapon/gun/projectile/examine(mob/user)
..(user)
user << "Has [getAmmo()] round\s remaining."
if(ammo_magazine)
user << "It has \a [ammo_magazine] loaded."
user << "Has [getAmmo()] round\s remaining."
return
/obj/item/weapon/gun/projectile/proc/getAmmo()
@@ -203,3 +206,15 @@
if(chambered)
bullets += 1
return bullets
/* Unneeded -- so far.
//in case the weapon has firemodes and can't unload using attack_hand()
/obj/item/weapon/gun/projectile/verb/unload_gun()
set name = "Unload Ammo"
set category = "Object"
set src in usr
if(usr.stat || usr.restrained()) return
unload_ammo(usr)
*/
@@ -10,7 +10,12 @@
slot_flags = SLOT_BELT
ammo_type = /obj/item/ammo_casing/c9mm
multi_aim = 1
fire_delay = 0
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)),
)
/obj/item/weapon/gun/projectile/automatic/mini_uzi
name = "\improper Uzi"
@@ -59,6 +64,12 @@
slot_flags = SLOT_BACK
load_method = MAGAZINE
magazine_type = /obj/item/ammo_magazine/c762
firemodes = list(
list(name="semiauto", burst=1, fire_delay=0),
list(name="3-round bursts", burst=3, move_delay=6, accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.0, 0.6, 0.6)),
list(name="short bursts", burst=5, move_delay=6, accuracy = list(0,-1,-1,-2,-2), dispersion = list(0.6, 1.0, 1.0, 1.0, 1.2)),
)
/obj/item/weapon/gun/projectile/automatic/sts35/update_icon()
..()
@@ -87,6 +98,9 @@
icon_state = "wt550"
return
/datum/firemode/z8
var/use_launcher = 0
/obj/item/weapon/gun/projectile/automatic/z8
name = "\improper Z8 Bulldog"
desc = "An older model bullpup carbine, made by the now defunct Zendai Foundries. Uses armor piercing 5.56mm rounds. Makes you feel like a space marine when you hold it."
@@ -104,17 +118,20 @@
auto_eject = 1
auto_eject_sound = 'sound/weapons/smg_empty_alarm.ogg'
var/use_launcher = 0
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)
)
var/obj/item/weapon/gun/launcher/grenade/underslung/launcher
/obj/item/weapon/gun/projectile/automatic/z8/New()
..()
launcher = new(src)
/obj/item/weapon/gun/projectile/automatic/z8/attack_self(mob/user)
use_launcher = !use_launcher
user << "<span class='notice'>You switch to [use_launcher? "\the [launcher]" : "firing normally"].</span>"
/obj/item/weapon/gun/projectile/automatic/z8/attackby(obj/item/I, mob/user)
if((istype(I, /obj/item/weapon/grenade)))
launcher.load(I, user)
@@ -122,16 +139,18 @@
..()
/obj/item/weapon/gun/projectile/automatic/z8/attack_hand(mob/user)
if(user.get_inactive_hand() == src && use_launcher)
var/datum/firemode/z8/current_mode = firemodes[sel_mode]
if(user.get_inactive_hand() == src && current_mode.use_launcher)
launcher.unload(user)
else
..()
/obj/item/weapon/gun/projectile/automatic/z8/Fire(atom/target, mob/living/user, params, pointblank=0, reflex=0)
if(use_launcher)
var/datum/firemode/z8/current_mode = firemodes[sel_mode]
if(current_mode.use_launcher)
launcher.Fire(target, user, params, pointblank, reflex)
if(!launcher.chambered)
use_launcher = 0 //switch back automatically
switch_firemodes() //switch back automatically
else
..()
@@ -166,22 +185,40 @@
fire_sound = 'sound/weapons/Gunshot_smg.ogg'
load_method = MAGAZINE
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)),
)
var/cover_open = 0
/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_self(mob/user as mob)
cover_open = !cover_open
user << "<span class='notice'>You [cover_open ? "open" : "close"] [src]'s cover.</span>"
update_icon()
/obj/item/weapon/gun/projectile/automatic/l6_saw/update_icon()
icon_state = "l6[cover_open ? "open" : "closed"][ammo_magazine ? round(ammo_magazine.stored_ammo.len, 25) : "-empty"]"
/obj/item/weapon/gun/projectile/automatic/l6_saw/special_check(mob/user)
if(cover_open)
user << "<span class='warning'>[src]'s cover is open! Close it before firing!</span>"
return 0
return ..()
/obj/item/weapon/gun/projectile/automatic/l6_saw/proc/toggle_cover(mob/user)
cover_open = !cover_open
user << "<span class='notice'>You [cover_open ? "open" : "close"] [src]'s cover.</span>"
update_icon()
/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_self(mob/user as mob)
if(cover_open)
toggle_cover(user) //close the cover
else
return ..() //once closed, behave like normal
/obj/item/weapon/gun/projectile/automatic/l6_saw/attack_hand(mob/user as mob)
if(!cover_open && user.get_inactive_hand() == src)
toggle_cover(user) //open the cover
else
return ..() //once open, behave like normal
/obj/item/weapon/gun/projectile/automatic/l6_saw/update_icon()
icon_state = "l6[cover_open ? "open" : "closed"][ammo_magazine ? round(ammo_magazine.stored_ammo.len, 25) : "-empty"]"
/obj/item/weapon/gun/projectile/automatic/l6_saw/load_ammo(var/obj/item/A, mob/user)
if(!cover_open)
user << "<span class='warning'>You need to open the cover to load [src].</span>"
@@ -190,5 +227,6 @@
/obj/item/weapon/gun/projectile/automatic/l6_saw/unload_ammo(mob/user, var/allow_dump=1)
if(!cover_open)
user << "<span class='warning'>You need to open the cover to unload [src].</span>"
return
..()
@@ -27,7 +27,7 @@
projectile_type = /obj/item/projectile/bullet/chemdart
/obj/item/ammo_casing/chemdart/expend()
del(src)
qdel(src)
/obj/item/ammo_magazine/chemdart
name = "dart cartridge"
@@ -65,12 +65,24 @@
caliber = "shotgun"
origin_tech = "combat=3;materials=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),
)
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/pellet
ammo_type = /obj/item/ammo_casing/shotgun/pellet
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/flare
name = "signal shotgun"
desc = "A double-barreled shotgun meant to fire signal flash shells."
ammo_type = /obj/item/ammo_casing/shotgun/flash
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/unload_ammo(user, allow_dump)
..(user, allow_dump=1)
//this is largely hacky and bad :( -Pete
/obj/item/weapon/gun/projectile/shotgun/doublebarrel/attackby(var/obj/item/A as obj, mob/user as mob)
if(istype(A, /obj/item/weapon/circular_saw) || istype(A, /obj/item/weapon/melee/energy) || istype(A, /obj/item/weapon/pickaxe/plasmacutter))
+23 -15
View File
@@ -33,6 +33,9 @@
var/p_x = 16
var/p_y = 16 // the pixel location of the tile that the player clicked. Default is the center
var/accuracy = 0
var/dispersion = 0.0
var/damage = 10
var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE are the only things that should be in here
var/nodamage = 0 //Determines if the projectile will skip any damage inflictions
@@ -101,6 +104,12 @@
if(mouse_control["icon-y"])
p_y = text2num(mouse_control["icon-y"])
//randomize clickpoint a bit based on dispersion
if(dispersion)
var/radius = round((dispersion*0.443)*world.icon_size*0.8) //0.443 = sqrt(pi)/4 = 2a, where a is the side length of a square that shares the same area as a circle with diameter = dispersion
p_x = between(0, p_x + rand(-radius, radius), world.icon_size)
p_y = between(0, p_y + rand(-radius, radius), world.icon_size)
//called to launch a projectile from a gun
/obj/item/projectile/proc/launch(atom/target, mob/user, obj/item/weapon/gun/launcher, var/target_zone, var/x_offset=0, var/y_offset=0)
var/turf/curloc = get_turf(user)
@@ -147,24 +156,15 @@
yo = new_y - starting_loc.y
xo = new_x - starting_loc.x
setup_trajectory()
//Called when the projectile intercepts a mob. Returns 1 if the projectile hit the mob, 0 if it missed and should keep flying.
/obj/item/projectile/proc/attack_mob(var/mob/living/target_mob, var/distance, var/miss_modifier=0)
if(!istype(target_mob))
return
//accuracy bonus from aiming
if (istype(shot_from, /obj/item/weapon/gun))
var/obj/item/weapon/gun/daddy = shot_from
miss_modifier -= round(15*daddy.accuracy)
//If you aim at someone beforehead, it'll hit more often.
//Kinda balanced by fact you need like 2 seconds to aim
//As opposed to no-delay pew pew
if (daddy.aim_targets && original in daddy.aim_targets)
miss_modifier += -30
//roll to-hit
miss_modifier = max(miss_modifier + 15*(distance-2), 0)
miss_modifier = max(15*(distance-2) - round(15*accuracy) + miss_modifier, 0)
var/hit_zone = get_zone_with_miss_chance(def_zone, target_mob, miss_modifier, ranged_attack=(distance > 1))
if(!hit_zone)
visible_message("<span class='notice'>\The [src] misses [target_mob] narrowly!</span>")
@@ -274,10 +274,11 @@
//plot the initial trajectory
setup_trajectory()
spawn while(src)
spawn while(src && src.loc)
if(kill_count-- < 1)
on_impact(src.loc) //for any final impact behaviours
qdel(src)
return
if((!( current ) || loc == current))
current = locate(min(max(x + xo, 1), world.maxx), min(max(y + yo, 1), world.maxy), z)
if((x == 1 || x == world.maxx || y == 1 || y == world.maxy))
@@ -289,6 +290,7 @@
if(!location)
qdel(src) // if it's left the world... kill it
return
before_move()
Move(location.return_turf())
@@ -302,8 +304,8 @@
if(!bumped && !isturf(original))
if(loc == get_turf(original))
if(!(original in permutated))
Bump(original)
if(Bump(original))
return
if(!hitscan)
sleep(step_delay) //add delay between movement iterations if it's not a hitscan weapon
@@ -314,9 +316,15 @@
/obj/item/projectile/proc/before_move()
/obj/item/projectile/proc/setup_trajectory()
// trajectory dispersion
var/offset = 0
if(dispersion)
var/radius = round(dispersion*9, 1)
offset = rand(-radius, radius)
// plot the initial trajectory
trajectory = new()
trajectory.setup(starting, original, pixel_x, pixel_y)
trajectory.setup(starting, original, pixel_x, pixel_y, angle_offset=offset)
// generate this now since all visual effects the projectile makes can use it
effect_transform = new()
@@ -148,6 +148,7 @@
stun = 3
weaken = 3
penetrating = 5
hitscan = 1 //so the PTR isn't useless as a sniper weapon
/obj/item/projectile/bullet/rifle/a556
damage = 40
@@ -184,3 +185,15 @@
/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
damage = 5
/obj/item/projectile/bullet/rifle/a556/practice
damage = 5
/obj/item/projectile/bullet/shotgun/practice
name = "practice"
damage = 5
@@ -19,11 +19,11 @@
if(istype(M, /mob/living/silicon/robot))
var/mob/living/silicon/robot/Robot = M
if(Robot.mmi)
del(Robot.mmi)
qdel(Robot.mmi)
else
for(var/obj/item/W in M)
if(istype(W, /obj/item/weapon/implant)) //TODO: Carn. give implants a dropped() or something
del(W)
qdel(W)
continue
M.drop_from_inventory(W)
@@ -90,7 +90,7 @@
new_mob << "<span class='warning'>Your form morphs into that of \a [lowertext(randomize)].</span>"
del(M)
qdel(M)
return
else
M << "<span class='warning'>Your form morphs into that of \a [lowertext(randomize)].</span>"
@@ -65,7 +65,7 @@
for(var/mob/M in range(10, src))
if(!M.stat && !istype(M, /mob/living/silicon/ai))\
shake_camera(M, 3, 1)
del(src)
qdel(src)
return 1
else
return 0
@@ -141,12 +141,12 @@
/obj/item/projectile/icarus/pointdefense/process()
Icarus_FireLaser(get_turf(original))
spawn
del src
qdel(src)
return
/obj/item/projectile/icarus/guns/process()
Icarus_FireCannon(get_turf(original))
spawn
del src
qdel(src)
return
+6 -10
View File
@@ -16,10 +16,6 @@
stop_aim()
usr.visible_message("<span class='notice'> \The [usr] lowers \the [src]...</span>")
//Clicking gun will still lower aim for guns that don't overwrite this
/obj/item/weapon/gun/attack_self()
lower_aim()
//Removing the lock and the buttons.
/obj/item/weapon/gun/dropped(mob/user as mob)
stop_aim()
@@ -40,7 +36,7 @@
for(var/mob/living/M in aim_targets)
if(M)
M.NotTargeted(src) //Untargeting people.
del(aim_targets)
qdel(aim_targets)
//Compute how to fire.....
//Return 1 if a target was found, 0 otherwise.
@@ -69,7 +65,7 @@
for(var/mob/living/L in aim_targets)
if(L)
L.NotTargeted(src)
del(aim_targets)
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>")
@@ -234,13 +230,13 @@
targeted_by -= I
I.aim_targets.Remove(src) //De-target them
if(!I.aim_targets.len)
del(I.aim_targets)
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)
del target_locked //Remove the overlay
del targeted_by
qdel(target_locked) //Remove the overlay
qdel(targeted_by)
spawn(1) update_targeted()
/mob/living/Move()
@@ -308,7 +304,7 @@
else
usr << "Target may no longer move."
target_can_run = 0
del(usr.gun_run_icon) //no need for icon for running permission
qdel(usr.gun_run_icon) //no need for icon for running permission
//Updating walking permission button
if(usr.gun_move_icon)