diff --git a/baystation12.dme b/baystation12.dme
index 365ed1718bb..cc76085482a 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -1158,7 +1158,8 @@
#include "code\modules\projectiles\guns\energy\stun.dm"
#include "code\modules\projectiles\guns\energy\temperature.dm"
#include "code\modules\projectiles\guns\projectile\automatic.dm"
-#include "code\modules\projectiles\guns\projectile\bow.dm"
+#include "code\modules\projectiles\guns\projectile\crossbow.dm"
+#include "code\modules\projectiles\guns\projectile\launcher.dm"
#include "code\modules\projectiles\guns\projectile\pistol.dm"
#include "code\modules\projectiles\guns\projectile\pneumatic.dm"
#include "code\modules\projectiles\guns\projectile\revolver.dm"
diff --git a/code/modules/admin/verbs/vox_raiders.dm b/code/modules/admin/verbs/vox_raiders.dm
index d100720102c..9f736e3ae40 100644
--- a/code/modules/admin/verbs/vox_raiders.dm
+++ b/code/modules/admin/verbs/vox_raiders.dm
@@ -18,7 +18,7 @@ var/global/vox_tick = 1
equip_to_slot_or_del(new /obj/item/clothing/glasses/thermal/monocle(src), slot_glasses) // REPLACE WITH CODED VOX ALTERNATIVE.
equip_to_slot_or_del(new /obj/item/device/chameleon(src), slot_l_store)
- var/obj/item/weapon/spikethrower/W = new(src)
+ var/obj/item/weapon/gun/launcher/spikethrower/W = new(src)
equip_to_slot_or_del(W, slot_r_hand)
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index b1b3df0672e..3d4ea67c3ba 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -218,7 +218,7 @@
//Point blank shooting if on harm intent or target we were targeting.
if(user.a_intent == "hurt")
user.visible_message("\red \The [user] fires \the [src] point blank at [M]!")
- in_chamber.damage *= 1.3
+ if(istype(in_chamber)) in_chamber.damage *= 1.3
Fire(M,user)
return
else if(target && M in target)
diff --git a/code/modules/projectiles/guns/alien.dm b/code/modules/projectiles/guns/alien.dm
index f1928730908..855312da7e4 100644
--- a/code/modules/projectiles/guns/alien.dm
+++ b/code/modules/projectiles/guns/alien.dm
@@ -1,19 +1,5 @@
//Vox pinning weapon.
-
-//Ammo.
-/obj/item/weapon/spike
- name = "alloy spike"
- desc = "It's about a foot of weird silver metal with a wicked point."
- sharp = 1
- edge = 0
- throwforce = 5
- w_class = 2
- icon = 'icons/obj/weapons.dmi'
- icon_state = "metal-rod"
- item_state = "bolt"
-
-//Launcher.
-/obj/item/weapon/spikethrower
+/obj/item/weapon/gun/launcher/spikethrower
name = "Vox spike thrower"
desc = "A vicious alien projectile weapon. Parts of it quiver gelatinously, as though the thing is insectile and alive."
@@ -22,97 +8,60 @@
var/spike_gen_time = 100
var/max_spikes = 3
var/spikes = 3
- var/obj/item/weapon/spike/spike
- var/fire_force = 30
-
- //Going to make an effort to get this compatible with the threat targetting system.
- var/tmp/list/mob/living/target
- var/tmp/mob/living/last_moved_mob
-
+ release_force = 30
icon = 'icons/obj/gun.dmi'
icon_state = "spikethrower3"
item_state = "spikethrower"
+ fire_sound_text = "a strange noise"
+ fire_sound = 'sound/weapons/bladeslice.ogg'
-/obj/item/weapon/spikethrower/New()
+/obj/item/weapon/gun/launcher/spikethrower/New()
..()
processing_objects.Add(src)
last_regen = world.time
-/obj/item/weapon/spikethrower/Del()
+/obj/item/weapon/gun/launcher/spikethrower/Del()
processing_objects.Remove(src)
..()
-/obj/item/weapon/spikethrower/process()
+/obj/item/weapon/gun/launcher/spikethrower/process()
if(spikes < max_spikes && world.time > last_regen + spike_gen_time)
spikes++
last_regen = world.time
update_icon()
-/obj/item/weapon/spikethrower/examine()
+/obj/item/weapon/gun/launcher/spikethrower/examine()
..()
usr << "It has [spikes] [spikes == 1 ? "spike" : "spikes"] remaining."
-/obj/item/weapon/spikethrower/update_icon()
+/obj/item/weapon/gun/launcher/spikethrower/update_icon()
icon_state = "spikethrower[spikes]"
-/obj/item/weapon/spikethrower/afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params)
- if(flag) return
- if(user && user.client && user.client.gun_mode && !(A in target))
- //TODO: Make this compatible with targetting (prolly have to actually make it a gun subtype, ugh.)
- //PreFire(A,user,params)
- else
- Fire(A,user,params)
-
-/obj/item/weapon/spikethrower/attack(mob/living/M as mob, mob/living/user as mob, def_zone)
-
- if (M == user && user.zone_sel.selecting == "mouth")
- M.visible_message("\red [user] attempts without success to fit [src] into their mouth.")
- return
-
- if (spikes > 0)
- if(user.a_intent == "hurt")
- user.visible_message("\red \The [user] fires \the [src] point blank at [M]!")
- Fire(M,user)
- return
- else if(target && M in target)
- Fire(M,user)
- return
- else
- return ..()
-
-/obj/item/weapon/spikethrower/proc/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)
-
- add_fingerprint(user)
-
- var/turf/curloc = get_turf(user)
- var/turf/targloc = get_turf(target)
- if (!istype(targloc) || !istype(curloc))
- return
+/obj/item/weapon/gun/launcher/spikethrower/emp_act(severity)
+ return
+/obj/item/weapon/gun/launcher/spikethrower/special_check(user)
if(istype(user,/mob/living/carbon/human))
var/mob/living/carbon/human/H = user
- if(H.species && H.species.name != "Vox")
- user << "\red The weapon does not respond to you!"
- return
- else
- user << "\red The weapon does not respond to you!"
- return
+ if(H.species && H.species.name != "Vox" && H.species.name != "Vox Armalis")
+ user << "\red \The [src] does not respond to you!"
+ return 0
+ return 1
- if(spikes <= 0)
- user << "\red The weapon has nothing to fire!"
- return
+/obj/item/weapon/gun/launcher/spikethrower/update_release_force()
+ return
- if(!spike)
- spike = new(src) //Create a spike.
- spike.add_fingerprint(user)
- spikes--
+/obj/item/weapon/gun/launcher/spikethrower/load_into_chamber()
+ if(in_chamber) return 1
+ if(spikes < 1) return 0
- user.visible_message("\red [user] fires [src]!", "\red You fire [src]!")
- spike.loc = get_turf(src)
- spike.throw_at(target,10,fire_force)
- spike = null
- update_icon()
+ spikes--
+ in_chamber = new /obj/item/weapon/spike(src)
+ return 1
+
+/obj/item/weapon/gun/launcher/spikethrower/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)
+ if(..()) update_icon()
//This gun only functions for armalis. The on-sprite is too huge to render properly on other sprites.
/obj/item/weapon/gun/energy/noisecannon
diff --git a/code/modules/projectiles/guns/projectile/bow.dm b/code/modules/projectiles/guns/projectile/crossbow.dm
similarity index 61%
rename from code/modules/projectiles/guns/projectile/bow.dm
rename to code/modules/projectiles/guns/projectile/crossbow.dm
index 912b5f2f1ee..e9bfb12b84c 100644
--- a/code/modules/projectiles/guns/projectile/bow.dm
+++ b/code/modules/projectiles/guns/projectile/crossbow.dm
@@ -1,3 +1,5 @@
+//AMMUNITION
+
/obj/item/weapon/arrow
name = "bolt"
@@ -14,6 +16,17 @@
/obj/item/weapon/arrow/proc/removed() //Helper for metal rods falling apart.
return
+/obj/item/weapon/spike
+ name = "alloy spike"
+ desc = "It's about a foot of weird silver metal with a wicked point."
+ sharp = 1
+ edge = 0
+ throwforce = 5
+ w_class = 2
+ icon = 'icons/obj/weapons.dmi'
+ icon_state = "metal-rod"
+ item_state = "bolt"
+
/obj/item/weapon/arrow/quill
name = "vox quill"
@@ -36,86 +49,50 @@
S.loc = get_turf(src)
src.Del()
-/obj/item/weapon/crossbow
+/obj/item/weapon/gun/launcher/crossbow
name = "powered crossbow"
desc = "A 2557AD twist on an old classic. Pick up that can."
- icon = 'icons/obj/weapons.dmi'
icon_state = "crossbow"
item_state = "crossbow-solid"
- w_class = 5.0
- flags = FPRINT | TABLEPASS | CONDUCT
- slot_flags = SLOT_BELT | SLOT_BACK
+ fire_sound = 'sound/weapons/punchmiss.ogg' // TODO: Decent THWOK noise.
+ ejectshell = 0 // No spent shells.
+ mouthshoot = 1 // No suiciding with this weapon, causes runtimes.
+ fire_sound_text = "a solid thunk"
+ fire_delay = 25
- w_class = 3.0
+ var/tension = 0 // Current draw on the bow.
+ var/max_tension = 5 // Highest possible tension.
+ var/release_speed = 5 // Speed per unit of tension.
+ var/obj/item/weapon/cell/cell = null // Used for firing superheated rods.
+ var/current_user // Used to check if the crossbow has changed hands since being drawn.
- var/tension = 0 // Current draw on the bow.
- var/max_tension = 5 // Highest possible tension.
- var/release_speed = 5 // Speed per unit of tension.
- var/mob/living/current_user = null // Used to see if the person drawing the bow started drawing it.
- var/obj/item/weapon/arrow = null // Nocked arrow.
- var/obj/item/weapon/cell/cell = null // Used for firing special projectiles like rods.
+/obj/item/weapon/gun/launcher/crossbow/emp_act(severity)
+ if(cell && severity)
+ cell.use(100*severity)
-/obj/item/weapon/crossbow/attackby(obj/item/W as obj, mob/user as mob)
- if(!arrow)
- if (istype(W,/obj/item/weapon/arrow))
- user.drop_item()
- arrow = W
- arrow.loc = src
- user.visible_message("[user] slides [arrow] into [src].","You slide [arrow] into [src].")
- icon_state = "crossbow-nocked"
- return
- else if(istype(W,/obj/item/stack/rods))
- var/obj/item/stack/rods/R = W
- R.use(1)
- arrow = new /obj/item/weapon/arrow/rod(src)
- arrow.fingerprintslast = src.fingerprintslast
- arrow.loc = src
- icon_state = "crossbow-nocked"
- user.visible_message("[user] haphazardly jams [arrow] into [src].","You jam [arrow] into [src].")
- if(cell)
- if(cell.charge >= 500)
- user << "[arrow] plinks and crackles as it begins to glow red-hot."
- arrow.throwforce = 15
- arrow.icon_state = "metal-rod-superheated"
- cell.use(500)
- return
+/obj/item/weapon/gun/launcher/crossbow/special_check(user)
+ if(tension <= 0)
+ user << "\red \The [src] is not drawn back!"
+ return 0
+ return 1
- if(istype(W, /obj/item/weapon/cell))
- if(!cell)
- user.drop_item()
- W.loc = src
- cell = W
- user << "You jam [cell] into [src] and wire it to the firing coil."
- if(arrow)
- if(istype(arrow,/obj/item/weapon/arrow/rod) && arrow.throwforce < 15 && cell.charge >= 500)
- user << "[arrow] plinks and crackles as it begins to glow red-hot."
- arrow.throwforce = 15
- arrow.icon_state = "metal-rod-superheated"
- cell.use(500)
- else
- user << "[src] already has a cell installed."
+/obj/item/weapon/gun/launcher/crossbow/update_release_force()
+ release_force = tension*release_speed
- else if(istype(W, /obj/item/weapon/screwdriver))
- if(cell)
- var/obj/item/C = cell
- C.loc = get_turf(user)
- cell = null
- user << "You jimmy [cell] out of [src] with [W]."
- else
- user << "[src] doesn't have a cell installed."
+/obj/item/weapon/gun/launcher/crossbow/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)
- else
- ..()
+ if(!..()) return //Only do this on a successful shot.
+ icon_state = "crossbow"
-/obj/item/weapon/crossbow/attack_self(mob/living/user as mob)
+/obj/item/weapon/gun/launcher/crossbow/attack_self(mob/living/user as mob)
if(tension)
- if(arrow)
- user.visible_message("[user] relaxes the tension on [src]'s string and removes [arrow].","You relax the tension on [src]'s string and remove [arrow].")
- var/obj/item/weapon/arrow/A = arrow
- A.loc = get_turf(src)
+ if(in_chamber && in_chamber.loc == src) //Just in case they click it the tick after firing.
+ user.visible_message("[user] relaxes the tension on [src]'s string and removes [in_chamber].","You relax the tension on [src]'s string and remove [in_chamber].")
+ in_chamber.loc = get_turf(src)
+ var/obj/item/weapon/arrow/A = in_chamber
+ in_chamber = null
A.removed(user)
- arrow = null
else
user.visible_message("[user] relaxes the tension on [src]'s string.","You relax the tension on [src]'s string.")
tension = 0
@@ -123,9 +100,9 @@
else
draw(user)
-/obj/item/weapon/crossbow/proc/draw(var/mob/user as mob)
+/obj/item/weapon/gun/launcher/crossbow/proc/draw(var/mob/user as mob)
- if(!arrow)
+ if(!in_chamber)
user << "You don't have anything nocked to [src]."
return
@@ -133,14 +110,13 @@
return
current_user = user
-
user.visible_message("[user] begins to draw back the string of [src].","You begin to draw back the string of [src].")
tension = 1
- spawn(25) increase_tension(user)
+ spawn(25) increase_tension(user) //TODO: This needs to be changed to something less shit.
-/obj/item/weapon/crossbow/proc/increase_tension(var/mob/user as mob)
+/obj/item/weapon/gun/launcher/crossbow/proc/increase_tension(var/mob/user as mob)
- if(!arrow || !tension || current_user != user) //Arrow has been fired, bow has been relaxed or user has changed.
+ if(!in_chamber || !tension || current_user != user) //Arrow has been fired, bow has been relaxed or user has changed.
return
tension++
@@ -153,60 +129,62 @@
user.visible_message("[usr] draws back the string of [src]!","You continue drawing back the string of [src]!")
spawn(25) increase_tension(user)
-/obj/item/weapon/crossbow/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag, params)
+/obj/item/weapon/gun/launcher/crossbow/attackby(obj/item/W as obj, mob/user as mob)
+ if(!in_chamber)
+ if (istype(W,/obj/item/weapon/arrow))
+ user.drop_item()
+ in_chamber = W
+ in_chamber.loc = src
+ user.visible_message("[user] slides [in_chamber] into [src].","You slide [in_chamber] into [src].")
+ icon_state = "crossbow-nocked"
+ return
+ else if(istype(W,/obj/item/stack/rods))
+ var/obj/item/stack/rods/R = W
+ R.use(1)
+ in_chamber = new /obj/item/weapon/arrow/rod(src)
+ in_chamber.fingerprintslast = src.fingerprintslast
+ in_chamber.loc = src
+ icon_state = "crossbow-nocked"
+ user.visible_message("[user] jams [in_chamber] into [src].","You jam [in_chamber] into [src].")
+ superheat_rod(user)
+ return
- if (istype(target, /obj/item/weapon/storage/backpack ))
- src.dropped()
- return
+ if(istype(W, /obj/item/weapon/cell))
+ if(!cell)
+ user.drop_item()
+ W.loc = src
+ cell = W
+ user << "You jam [cell] into [src] and wire it to the firing coil."
+ superheat_rod(user)
+ else
+ user << "[src] already has a cell installed."
- else if (target.loc == user.loc)
- return
+ else if(istype(W, /obj/item/weapon/screwdriver))
+ if(cell)
+ var/obj/item/C = cell
+ C.loc = get_turf(user)
+ user << "You jimmy [cell] out of [src] with [W]."
+ cell = null
+ else
+ user << "[src] doesn't have a cell installed."
- else if (locate (/obj/structure/table, src.loc))
- return
-
- else if(target == user)
- return
-
- if(!tension)
- user << "You haven't drawn back the bolt!"
- return 0
-
- if (!arrow)
- user << "You have no arrow nocked to [src]!"
- return 0
else
- spawn(0) Fire(target,user,params)
+ ..()
-/obj/item/weapon/crossbow/proc/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)
+/obj/item/weapon/gun/launcher/crossbow/proc/superheat_rod(var/mob/user)
- add_fingerprint(user)
+ if(!user || !cell || !in_chamber) return
+ if(cell.charge < 500) return
+ if(in_chamber.throwforce >= 15) return
+ if(!istype(in_chamber,/obj/item/weapon/arrow/rod)) return
- var/turf/curloc = get_turf(user)
- var/turf/targloc = get_turf(target)
- if (!istype(targloc) || !istype(curloc))
- return
+ user << "[in_chamber] plinks and crackles as it begins to glow red-hot."
+ in_chamber.throwforce = 15
+ in_chamber.icon_state = "metal-rod-superheated"
+ cell.use(500)
- user.visible_message("[user] releases [src] and sends [arrow] streaking toward [target]!","You release [src] and send [arrow] streaking toward [target]!")
-
- var/obj/item/weapon/arrow/A = arrow
- A.loc = get_turf(user)
- A.throw_at(target,10,tension*release_speed)
- arrow = null
- tension = 0
- icon_state = "crossbow"
-
-/obj/item/weapon/crossbow/dropped(mob/user)
- if(arrow)
- var/obj/item/weapon/arrow/A = arrow
- A.loc = get_turf(src)
- A.removed(user)
- arrow = null
- tension = 0
- icon_state = "crossbow"
// Crossbow construction.
-
/obj/item/weapon/crossbowframe
name = "crossbow frame"
desc = "A half-finished crossbow."
@@ -283,7 +261,7 @@
else if(istype(W,/obj/item/weapon/screwdriver))
if(buildstate == 5)
user << "\blue You secure the crossbow's various parts."
- new /obj/item/weapon/crossbow(get_turf(src))
+ new /obj/item/weapon/gun/launcher/crossbow(get_turf(src))
del(src)
return
else
diff --git a/code/modules/projectiles/guns/projectile/launcher.dm b/code/modules/projectiles/guns/projectile/launcher.dm
new file mode 100644
index 00000000000..c367780a5e8
--- /dev/null
+++ b/code/modules/projectiles/guns/projectile/launcher.dm
@@ -0,0 +1,91 @@
+/obj/item/weapon/gun/launcher
+
+ name = "launcher"
+ desc = "A device that launches things."
+ icon = 'icons/obj/weapons.dmi'
+ w_class = 5.0
+ flags = FPRINT | TABLEPASS | CONDUCT
+ slot_flags = SLOT_BACK
+
+ var/release_force = 0
+ var/fire_sound_text = "a launcher firing"
+
+//Check if we're drawing and if the bow is loaded.
+/obj/item/weapon/gun/launcher/load_into_chamber()
+ return (!isnull(in_chamber))
+
+//This should not fit in a combat belt or holster.
+/obj/item/weapon/gun/launcher/isHandgun()
+ return 0
+
+//Launchers are mechanical, no other impact.
+/obj/item/weapon/gun/launcher/emp_act(severity)
+ return
+
+//This normally uses a proc on projectiles and our ammo is not strictly speaking a projectile.
+/obj/item/weapon/gun/launcher/can_hit(var/mob/living/target as mob, var/mob/living/user as mob)
+ return
+
+//Override this to avoid a runtime with suicide handling.
+/obj/item/weapon/gun/launcher/attack(mob/living/M as mob, mob/living/user as mob, def_zone)
+ if (M == user && user.zone_sel.selecting == "mouth")
+ user << "\red Shooting yourself with \a [src] is pretty tricky. You can't seem to manage it."
+ return
+ ..()
+
+/obj/item/weapon/gun/launcher/proc/update_release_force()
+ return 0
+
+/obj/item/weapon/gun/launcher/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)
+
+ if (!user.IsAdvancedToolUser())
+ user << "\red You don't have the dexterity to do this!"
+ return 0
+
+ add_fingerprint(user)
+
+ //Make sure target turfs both exist.
+ var/turf/curloc = get_turf(user)
+ var/turf/targloc = get_turf(target)
+ if (!istype(targloc) || !istype(curloc))
+ return 0
+
+ if(!special_check(user))
+ return 0
+
+ if (!ready_to_fire())
+ if (world.time % 3) //to prevent spam
+ user << "[src] is not ready to fire again!"
+ return 0
+
+ if(!load_into_chamber()) //CHECK
+ return click_empty(user)
+
+ if(!in_chamber)
+ return 0
+
+ update_release_force()
+
+ playsound(user, fire_sound, 50, 1)
+ user.visible_message("[user] fires [src][reflex ? " by reflex":""]!", \
+ "You fire [src][reflex ? "by reflex":""]!", \
+ "You hear [fire_sound_text]!")
+
+ in_chamber.loc = get_turf(user)
+ in_chamber.throw_at(target,10,release_force)
+
+ sleep(1)
+
+ in_chamber = null
+
+ update_icon()
+
+ if(user.hand)
+ user.update_inv_l_hand()
+ else
+ user.update_inv_r_hand()
+
+ return 1
+
+/obj/item/weapon/gun/launcher/attack_self(mob/living/user as mob)
+ return
\ No newline at end of file
diff --git a/code/modules/projectiles/guns/projectile/pneumatic.dm b/code/modules/projectiles/guns/projectile/pneumatic.dm
index 43c1fed24aa..6d1855b8a7d 100644
--- a/code/modules/projectiles/guns/projectile/pneumatic.dm
+++ b/code/modules/projectiles/guns/projectile/pneumatic.dm
@@ -1,4 +1,4 @@
-/obj/item/weapon/storage/pneumatic
+/obj/item/weapon/gun/launcher/pneumatic
name = "pneumatic cannon"
desc = "A large gas-powered cannon."
icon = 'icons/obj/gun.dmi'
@@ -6,27 +6,28 @@
item_state = "pneumatic"
w_class = 5.0
flags = FPRINT | TABLEPASS | CONDUCT
- slot_flags = SLOT_BELT
- max_w_class = 3
- max_combined_w_class = 20
+ fire_sound_text = "a loud whoosh of moving air"
+ fire_delay = 50
+ fire_sound = 'sound/weapons/tablehit1.ogg'
+ var/fire_pressure // Used in fire checks/pressure checks.
+ var/max_w_class = 3 // Hopper intake size.
+ var/max_combined_w_class = 20 // Total internal storage size.
var/obj/item/weapon/tank/tank = null // Tank of gas for use in firing the cannon.
var/obj/item/weapon/storage/tank_container = new() // Something to hold the tank item so we don't accidentally fire it.
var/pressure_setting = 10 // Percentage of the gas in the tank used to fire the projectile.
var/possible_pressure_amounts = list(5,10,20,25,50) // Possible pressure settings.
var/minimum_tank_pressure = 10 // Minimum pressure to fire the gun.
- var/cooldown = 0 // Whether or not we're cooling down.
- var/cooldown_time = 50 // Time between shots.
var/force_divisor = 400 // Force equates to speed. Speed/5 equates to a damage multiplier for whoever you hit.
// For reference, a fully pressurized oxy tank at 50% gas release firing a health
// analyzer with a force_divisor of 10 hit with a damage multiplier of 3000+.
-/obj/item/weapon/storage/pneumatic/New()
+/obj/item/weapon/gun/launcher/pneumatic/New()
..()
tank_container.tag = "gas_tank_holder"
-/obj/item/weapon/storage/pneumatic/verb/set_pressure() //set amount of tank pressure.
+/obj/item/weapon/gun/launcher/pneumatic/verb/set_pressure() //set amount of tank pressure.
- set name = "Set valve pressure"
+ set name = "Set Valve Pressure"
set category = "Object"
set src in range(0)
var/N = input("Percentage of tank used per shot:","[src]") as null|anything in possible_pressure_amounts
@@ -34,9 +35,9 @@
pressure_setting = N
usr << "You dial the pressure valve to [pressure_setting]%."
-/obj/item/weapon/storage/pneumatic/verb/eject_tank() //Remove the tank.
+/obj/item/weapon/gun/launcher/pneumatic/verb/eject_tank() //Remove the tank.
- set name = "Eject tank"
+ set name = "Eject Tank"
set category = "Object"
set src in range(0)
@@ -50,7 +51,7 @@
else
usr << "There's no tank in [src]."
-/obj/item/weapon/storage/pneumatic/attackby(obj/item/W as obj, mob/user as mob)
+/obj/item/weapon/gun/launcher/pneumatic/attackby(obj/item/W as obj, mob/user as mob)
if(!tank && istype(W,/obj/item/weapon/tank))
user.drop_item()
tank = W
@@ -59,10 +60,43 @@
icon_state = "pneumatic-tank"
item_state = "pneumatic-tank"
user.update_icons()
- else
- ..()
+ else if(W.w_class <= max_w_class)
-/obj/item/weapon/storage/pneumatic/examine()
+ var/total_stored = 0
+ for(var/obj/item/O in src.contents)
+ total_stored += O.w_class
+ if(total_stored + W.w_class <= max_combined_w_class)
+ user.drop_item(W)
+ W.loc = src
+ user << "You shove [W] into the hopper."
+ else
+ user << "That won't fit into the hopper - it's full."
+ return
+ else
+ user << "That won't fit into the hopper."
+
+/obj/item/weapon/gun/launcher/pneumatic/attack_self(mob/user as mob)
+
+ if(contents.len > 0)
+ var/obj/item/removing = contents[contents.len]
+ if(removing == in_chamber)
+ in_chamber = null
+
+ removing.loc = get_turf(src)
+ user.put_in_hands(removing)
+ user << "You remove [removing] from the hopper."
+ else
+ user << "There is nothing to remove in \the [src]."
+ return
+
+/obj/item/weapon/gun/launcher/pneumatic/load_into_chamber()
+ if(!contents.len)
+ return 0
+
+ in_chamber = contents[1]
+ return !isnull(in_chamber)
+
+/obj/item/weapon/gun/launcher/pneumatic/examine()
set src in view()
..()
if (!(usr in view(2)) && usr!=src.loc) return
@@ -72,76 +106,32 @@
else
usr << "Nothing is attached to the tank valve!"
-/obj/item/weapon/storage/pneumatic/afterattack(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, flag, params)
- if (istype(target, /obj/item/weapon/storage/backpack ))
- return
-
- else if (target.loc == user.loc)
- return
-
- else if (locate (/obj/structure/table, src.loc))
- return
-
- else if(target == user)
- return
-
- if (length(contents) == 0)
- user << "There's nothing in [src] to fire!"
- return 0
- else
- spawn(0) Fire(target,user,params)
-
-/obj/item/weapon/storage/pneumatic/attack(mob/living/M as mob, mob/living/user as mob, def_zone)
- if (length(contents) > 0)
- if(user.a_intent == "hurt")
- user.visible_message("\red \The [user] fires \the [src] point blank at [M]!")
- Fire(M,user)
- return
- else
- Fire(M,user)
- return
-
-/obj/item/weapon/storage/pneumatic/proc/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)
+/obj/item/weapon/gun/launcher/pneumatic/special_check(user)
if (!tank)
user << "There is no gas tank in [src]!"
return 0
- if (cooldown)
- user << "The chamber hasn't built up enough pressure yet!"
- return 0
-
- add_fingerprint(user)
-
- var/turf/curloc = get_turf(user)
- var/turf/targloc = get_turf(target)
- if (!istype(targloc) || !istype(curloc))
- return
-
- var/fire_pressure = (tank.air_contents.return_pressure()/100)*pressure_setting
-
+ fire_pressure = (tank.air_contents.return_pressure()/100)*pressure_setting
if (fire_pressure < minimum_tank_pressure)
user << "There isn't enough gas in the tank to fire [src]."
return 0
- var/obj/item/object = contents[1]
- var/speed = ((fire_pressure*tank.volume)/object.w_class)/force_divisor //projectile speed.
- if(speed>80) speed = 80 //damage cap.
+ return 1
- user.visible_message("[user] fires [src] and launches [object] at [target]!","You fire [src] and launch [object] at [target]!")
+/obj/item/weapon/gun/launcher/pneumatic/update_release_force()
+ if(!in_chamber) return
+ release_force = ((fire_pressure*tank.volume)/in_chamber.w_class)/force_divisor //projectile speed.
+ if(release_force >80) release_force = 80 //damage cap.
- src.remove_from_storage(object,user.loc)
- object.throw_at(target,10,speed)
+/obj/item/weapon/gun/launcher/pneumatic/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)
+
+ if(!tank || !..()) return //Only do this on a successful shot.
var/lost_gas_amount = tank.air_contents.total_moles*(pressure_setting/100)
var/datum/gas_mixture/removed = tank.air_contents.remove(lost_gas_amount)
user.loc.assume_air(removed)
- cooldown = 1
- spawn(cooldown_time)
- cooldown = 0
- user << "[src]'s gauge informs you it's ready to be fired again."
-
//Constructable pneumatic cannon.
/obj/item/weapon/cannonframe
@@ -215,7 +205,7 @@
if(!src || !T.isOn()) return
playsound(src.loc, 'sound/items/Welder2.ogg', 100, 1)
user << "\blue You weld the valve into place."
- new /obj/item/weapon/storage/pneumatic(get_turf(src))
+ new /obj/item/weapon/gun/launcher/pneumatic(get_turf(src))
del(src)
return
else
diff --git a/icons/mob/back.dmi b/icons/mob/back.dmi
index ba5a2bc5406..95df7c430f8 100644
Binary files a/icons/mob/back.dmi and b/icons/mob/back.dmi differ
diff --git a/maps/tgstation2.dmm b/maps/tgstation2.dmm
index 326235cfabb..cb80167098f 100644
--- a/maps/tgstation2.dmm
+++ b/maps/tgstation2.dmm
@@ -8604,7 +8604,7 @@
"djx" = (/obj/item/clothing/head/bearpelt,/obj/item/xenos_claw,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station)
"djy" = (/obj/item/clothing/head/bowler,/obj/item/weapon/broken_bottle,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station)
"djz" = (/obj/structure/rack,/obj/item/clothing/tie/storage/black_vest,/obj/item/clothing/suit/space/vox/pressure,/obj/item/clothing/head/helmet/space/vox/pressure,/obj/item/clothing/mask/breath,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station)
-"djA" = (/obj/structure/rack,/obj/item/weapon/spikethrower,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station)
+"djA" = (/obj/structure/rack,/obj/item/weapon/gun/launcher/spikethrower,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station)
"djB" = (/obj/structure/rack,/obj/item/clothing/tie/storage/black_vest,/obj/item/clothing/suit/space/vox/stealth,/obj/item/clothing/head/helmet/space/vox/stealth,/obj/item/clothing/mask/breath,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station)
"djC" = (/obj/structure/cable{icon_state = "0-4"; d2 = 4},/obj/machinery/power/apc{dir = 1; name = "north bump"; pixel_x = 0; pixel_y = 24},/turf/simulated/floor{icon_state = "warningcorner"; dir = 4},/area/turret_protected/tcomfoyer)
"djD" = (/obj/structure/stool/bed/chair{dir = 4},/obj/item/clothing/mask/breath,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station)
@@ -8643,7 +8643,7 @@
"dkk" = (/obj/machinery/portable_atmospherics/canister/nitrogen,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station)
"dkl" = (/obj/machinery/portable_atmospherics/canister/phoron,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station)
"dkm" = (/obj/structure/shuttle/engine/heater,/turf/simulated/shuttle/plating/vox,/area/shuttle/vox/station)
-"dkn" = (/obj/structure/rack,/obj/item/weapon/storage/pneumatic,/obj/item/weapon/harpoon,/obj/item/weapon/harpoon,/obj/item/weapon/harpoon,/obj/item/weapon/harpoon,/obj/item/weapon/tank/nitrogen,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station)
+"dkn" = (/obj/structure/rack,/obj/item/weapon/gun/launcher/pneumatic,/obj/item/weapon/harpoon,/obj/item/weapon/harpoon,/obj/item/weapon/harpoon,/obj/item/weapon/harpoon,/obj/item/weapon/tank/nitrogen,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station)
"dko" = (/obj/structure/rack,/obj/item/clothing/tie/storage/black_vest,/obj/item/clothing/suit/space/vox/medic,/obj/item/clothing/head/helmet/space/vox/medic,/obj/item/clothing/mask/breath,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station)
"dkp" = (/obj/machinery/atmospherics/pipe/simple/visible,/turf/simulated/shuttle/floor4/vox,/area/shuttle/vox/station)
"dkq" = (/obj/structure/grille,/obj/structure/window/reinforced{dir = 4},/obj/structure/window/reinforced{dir = 8},/obj/machinery/door/poddoor{id = "skipjack"; name = "Skipjack Blast Shielding"},/turf/simulated/shuttle/plating/vox,/area/shuttle/vox/station)