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)