From f8977c65af0b2bfb46b4126758d74ab3fd1680b0 Mon Sep 17 00:00:00 2001 From: mwerezak Date: Fri, 13 Feb 2015 21:21:43 -0500 Subject: [PATCH] Much nicer syringe gun implementation Makes syringe guns a type of launcher gun, and removes the hack projectile. Also moves syringe and dart gun source files into the modules/projectile folder. --- baystation12.dme | 4 +- code/defines/obj/weapon.dm | 2 +- .../objects/items/weapons/storage/boxes.dm | 14 +- .../mob/living/carbon/human/human_defense.dm | 21 +-- code/modules/mob/living/living_defense.dm | 19 +-- code/modules/projectiles/guns/alien.dm | 2 +- code/modules/projectiles/guns/energy/stun.dm | 2 +- code/modules/projectiles/guns/launcher.dm | 12 +- .../projectiles/guns/launcher/pneumatic.dm | 2 +- .../projectiles/guns/launcher/syringe_gun.dm | 135 ++++++++++++++++++ code/modules/projectiles/guns/projectile.dm | 18 +-- .../guns/projectile}/dartgun.dm | 0 code/modules/reagents/syringe_gun.dm | 130 ----------------- code/modules/research/designs.dm | 2 +- code/setup.dm | 2 +- icons/obj/ammo.dmi | Bin 4887 -> 4999 bytes maps/exodus-1.dmm | 2 +- 17 files changed, 185 insertions(+), 182 deletions(-) create mode 100644 code/modules/projectiles/guns/launcher/syringe_gun.dm rename code/modules/{reagents => projectiles/guns/projectile}/dartgun.dm (100%) delete mode 100644 code/modules/reagents/syringe_gun.dm diff --git a/baystation12.dme b/baystation12.dme index 0537e357be0..f71ff8f3c59 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1331,7 +1331,9 @@ #include "code\modules\projectiles\guns\launcher\crossbow.dm" #include "code\modules\projectiles\guns\launcher\pneumatic.dm" #include "code\modules\projectiles\guns\launcher\rocket.dm" +#include "code\modules\projectiles\guns\launcher\syringe_gun.dm" #include "code\modules\projectiles\guns\projectile\automatic.dm" +#include "code\modules\projectiles\guns\projectile\dartgun.dm" #include "code\modules\projectiles\guns\projectile\pistol.dm" #include "code\modules\projectiles\guns\projectile\revolver.dm" #include "code\modules\projectiles\guns\projectile\shotgun.dm" @@ -1351,11 +1353,9 @@ #include "code\modules\reagents\Chemistry-Reagents-Antidepressants.dm" #include "code\modules\reagents\Chemistry-Reagents.dm" #include "code\modules\reagents\Chemistry-Recipes.dm" -#include "code\modules\reagents\dartgun.dm" #include "code\modules\reagents\grenade_launcher.dm" #include "code\modules\reagents\reagent_containers.dm" #include "code\modules\reagents\reagent_dispenser.dm" -#include "code\modules\reagents\syringe_gun.dm" #include "code\modules\reagents\reagent_containers\blood_pack.dm" #include "code\modules\reagents\reagent_containers\borghydro.dm" #include "code\modules\reagents\reagent_containers\dropper.dm" diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index 4f424e03154..e513a7db378 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -67,7 +67,7 @@ icon_state = "bike_horn" item_state = "bike_horn" throwforce = 3 - w_class = 1.0 + w_class = 2 throw_speed = 3 throw_range = 15 attack_verb = list("HONKED") diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index ff158590fa7..8f6dd789967 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -99,13 +99,13 @@ New() ..() - new /obj/item/ammo_casing/gas_cartridge( src ) - new /obj/item/ammo_casing/gas_cartridge( src ) - new /obj/item/ammo_casing/gas_cartridge( src ) - new /obj/item/ammo_casing/gas_cartridge( src ) - new /obj/item/ammo_casing/gas_cartridge( src ) - new /obj/item/ammo_casing/gas_cartridge( src ) - new /obj/item/ammo_casing/gas_cartridge( src ) + new /obj/item/weapon/syringe_cartridge( src ) + new /obj/item/weapon/syringe_cartridge( src ) + new /obj/item/weapon/syringe_cartridge( src ) + new /obj/item/weapon/syringe_cartridge( src ) + new /obj/item/weapon/syringe_cartridge( src ) + new /obj/item/weapon/syringe_cartridge( src ) + new /obj/item/weapon/syringe_cartridge( src ) /obj/item/weapon/storage/box/beakers diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 858bee60c17..ac86766bde5 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -304,10 +304,7 @@ emp_act throw_mode_off() return - var/dtype = BRUTE - if(istype(O,/obj/item/weapon)) - var/obj/item/weapon/W = O - dtype = W.damtype + var/dtype = O.damtype var/throw_damage = O.throwforce*(speed/THROWFORCE_SPEED_DIVISOR) var/zone @@ -370,17 +367,21 @@ emp_act affecting.embed(I) // Begin BS12 momentum-transfer code. - if(O.throw_source && speed >= THROWNOBJ_KNOCKBACK_SPEED) - var/obj/item/weapon/W = O - var/momentum = speed/THROWNOBJ_KNOCKBACK_DIVISOR + var/mass = 1.5 + if(istype(O, /obj/item)) + var/obj/item/I = O + mass = I.w_class/THROWNOBJ_KNOCKBACK_DIVISOR + var/momentum = speed*mass + + if(O.throw_source && momentum >= THROWNOBJ_KNOCKBACK_SPEED) var/dir = get_dir(O.throw_source, src) visible_message("\red [src] staggers under the impact!","\red You stagger under the impact!") src.throw_at(get_edge_target_turf(src,dir),1,momentum) + + if(!O || !src) return - if(!W || !src) return - - if(W.loc == src && W.sharp) //Projectile is embedded and suitable for pinning. + if(O.loc == src && O.sharp) //Projectile is embedded and suitable for pinning. var/turf/T = near_wall(dir,2) if(T) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 2fa9cdc4b60..faafc23b2dd 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -103,10 +103,7 @@ /mob/living/hitby(atom/movable/AM as mob|obj,var/speed = THROWFORCE_SPEED_DIVISOR)//Standardization and logging -Sieve if(istype(AM,/obj/)) var/obj/O = AM - var/dtype = BRUTE - if(istype(O,/obj/item/weapon)) - var/obj/item/weapon/W = O - dtype = W.damtype + var/dtype = O.damtype var/throw_damage = O.throwforce*(speed/THROWFORCE_SPEED_DIVISOR) var/miss_chance = 15 @@ -136,17 +133,21 @@ msg_admin_attack("[src.name] ([src.ckey]) was hit by a [O], thrown by [M.name] ([assailant.ckey]) (JMP)") // Begin BS12 momentum-transfer code. - if(O.throw_source && speed >= THROWNOBJ_KNOCKBACK_SPEED) - var/obj/item/weapon/W = O - var/momentum = speed/THROWNOBJ_KNOCKBACK_DIVISOR + var/mass = 1.5 + if(istype(O, /obj/item)) + var/obj/item/I = O + mass = I.w_class/THROWNOBJ_KNOCKBACK_DIVISOR + var/momentum = speed*mass + + if(O.throw_source && momentum >= THROWNOBJ_KNOCKBACK_SPEED) var/dir = get_dir(O.throw_source, src) visible_message("\red [src] staggers under the impact!","\red You stagger under the impact!") src.throw_at(get_edge_target_turf(src,dir),1,momentum) - if(!W || !src) return + if(!O || !src) return - if(W.sharp) //Projectile is suitable for pinning. + if(O.sharp) //Projectile is suitable for pinning. //Handles embedding for non-humans and simple_animals. embed(O) diff --git a/code/modules/projectiles/guns/alien.dm b/code/modules/projectiles/guns/alien.dm index c8048026c3e..d26b1601cc1 100644 --- a/code/modules/projectiles/guns/alien.dm +++ b/code/modules/projectiles/guns/alien.dm @@ -1,6 +1,6 @@ //Vox pinning weapon. /obj/item/weapon/gun/launcher/spikethrower - name = "Vox spike thrower" + name = "vox spike thrower" desc = "A vicious alien projectile weapon. Parts of it quiver gelatinously, as though the thing is insectile and alive." var/last_regen = 0 diff --git a/code/modules/projectiles/guns/energy/stun.dm b/code/modules/projectiles/guns/energy/stun.dm index e4d1b0070a8..6bbc2aed3e6 100644 --- a/code/modules/projectiles/guns/energy/stun.dm +++ b/code/modules/projectiles/guns/energy/stun.dm @@ -49,7 +49,7 @@ projectile_type = /obj/item/projectile/energy/dart /obj/item/weapon/gun/energy/crossbow/largecrossbow - name = "Energy Crossbow" + name = "energy crossbow" desc = "A weapon favored by mercenary infiltration teams." w_class = 4 force = 10 diff --git a/code/modules/projectiles/guns/launcher.dm b/code/modules/projectiles/guns/launcher.dm index 82998ef60ae..ea86814afa8 100644 --- a/code/modules/projectiles/guns/launcher.dm +++ b/code/modules/projectiles/guns/launcher.dm @@ -22,14 +22,10 @@ /obj/item/weapon/gun/launcher/proc/update_release_force(obj/item/projectile) return 0 -/obj/item/weapon/gun/launcher/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)) return 0 - - var/obj/item/I = projectile - - update_release_force(I) - I.loc = get_turf(user) - I.throw_at(target, throw_distance, release_force, user) +/obj/item/weapon/gun/launcher/process_projectile(obj/item/projectile, mob/user, atom/target, var/target_zone, var/params=null, var/pointblank=0, var/reflex=0) + update_release_force(projectile) + 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) diff --git a/code/modules/projectiles/guns/launcher/pneumatic.dm b/code/modules/projectiles/guns/launcher/pneumatic.dm index 3e653bfeeba..712e74e150d 100644 --- a/code/modules/projectiles/guns/launcher/pneumatic.dm +++ b/code/modules/projectiles/guns/launcher/pneumatic.dm @@ -62,7 +62,7 @@ icon_state = "pneumatic-tank" item_state = "pneumatic-tank" user.update_icons() - else if(W.w_class <= max_w_class) + else if(istype(W) && W.w_class <= max_w_class) var/total_stored = 0 for(var/obj/item/O in src.contents) total_stored += O.w_class diff --git a/code/modules/projectiles/guns/launcher/syringe_gun.dm b/code/modules/projectiles/guns/launcher/syringe_gun.dm new file mode 100644 index 00000000000..b0275599dea --- /dev/null +++ b/code/modules/projectiles/guns/launcher/syringe_gun.dm @@ -0,0 +1,135 @@ +/obj/item/weapon/syringe_cartridge + name = "compressed gas cartridge" + desc = "An impact-triggered compressed gas cartridge that can fitted to a syringe for rapid injection." + icon = 'icons/obj/ammo.dmi' + icon_state = "syringe-cartridge" + var/icon_flight = "syringe-cartridge-flight" //so it doesn't look so weird when shot + flags = CONDUCT + slot_flags = SLOT_BELT + throwforce = 3 + force = 3 + w_class = 1 + var/obj/item/weapon/reagent_containers/syringe/syringe + var/primed = 0 + +/obj/item/weapon/syringe_cartridge/update_icon() + underlays.Cut() + if(syringe) + underlays += image(syringe.icon, src, syringe.icon_state) + underlays += syringe.filling + +/obj/item/weapon/syringe_cartridge/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/weapon/reagent_containers/syringe)) + syringe = I + user << "You carefully insert [syringe] into [src]." + user.remove_from_mob(syringe) + syringe.loc = src + sharp = 1 + update_icon() + +/obj/item/weapon/syringe_cartridge/attack_self(mob/user) + if(syringe) + user << "You remove [syringe] from [src]." + user.put_in_hands(syringe) + syringe = null + sharp = initial(sharp) + update_icon() + +/obj/item/weapon/syringe_cartridge/proc/prime() + //the icon state will revert back when update_icon() is called from throw_impact() + icon_state = icon_flight + underlays.Cut() + primed = 1 + +/obj/item/weapon/syringe_cartridge/throw_impact(atom/hit_atom, var/speed) + ..() //handles embedding for us. Should have a decent chance if thrown fast enough + if(syringe) + //check speed to see if we hit hard enough to trigger the rapid injection + //incidentally, this means syringe_cartridges can be used with the pneumatic launcher + if(speed >= 10 && primed && isliving(hit_atom)) + var/mob/living/L = hit_atom + //unfortuately we don't know where the dart will actually hit, since that's done by the parent. + if(L.can_inject()) + if(syringe.reagents) + syringe.reagents.trans_to(L, 15) + + syringe.break_syringe(iscarbon(hit_atom)? hit_atom : null) + syringe.update_icon() + + icon_state = initial(icon_state) //reset icon state + update_icon() + +/obj/item/weapon/gun/launcher/syringe + name = "syringe gun" + desc = "A spring loaded rifle designed to fit syringes, designed to incapacitate unruly patients from a distance." + icon = 'icons/obj/gun.dmi' + icon_state = "syringegun" + item_state = "syringegun" + w_class = 3 + force = 7 + matter = list("metal" = 2000) + slot_flags = SLOT_BELT + + fire_sound = 'sound/weapons/empty.ogg' + fire_sound_text = "a metallic thunk" + recoil = 0 + release_force = 10 + throw_distance = 10 + + var/list/darts = list() + var/max_darts = 1 + var/obj/item/weapon/syringe_cartridge/next + +/obj/item/weapon/gun/launcher/syringe/consume_next_projectile() + if(next) + next.prime() + return next + return null + +/obj/item/weapon/gun/launcher/syringe/handle_post_fire() + ..() + darts -= next + next = null + +/obj/item/weapon/gun/launcher/syringe/attack_self(mob/living/user as mob) + if(next) + user.visible_message("[user] unlatches and carefully relax the bolt on [src].", "You unlatch and carefully relax the bolt on [src], unloading the spring.") + next = null + else if(darts.len) + playsound(src.loc, 'sound/weapons/flipblade.ogg', 50, 1) + user.visible_message("[user] draws back the bolt on [src], clicking it into place.", "You draw back the bolt on the [src], loading the spring!") + next = darts[1] + +/obj/item/weapon/gun/launcher/syringe/attack_hand(mob/living/user as mob) + if(src in user) + if(!darts.len) + user << "[src] is empty." + return + if(next) + user << "The cover on [src] is locked shut." + return + var/obj/item/weapon/syringe_cartridge/C = darts[1] + darts -= C + user.put_in_hands(C) + user.visible_message("[user] removes \a [C] from [src].", "You remove \a [C] from [src].") + else + ..() + +/obj/item/weapon/gun/launcher/syringe/attackby(var/obj/item/A as obj, mob/user as mob) + if(istype(A, /obj/item/weapon/syringe_cartridge)) + var/obj/item/weapon/syringe_cartridge/C = A + if(darts.len >= max_darts) + user << "[src] is full!" + return + user.remove_from_mob(C) + C.loc = src + darts += C //add to the end + user.visible_message("[user] inserts \a [C] into [src].", "You insert \a [C] into [src].") + else + ..() + +/obj/item/weapon/gun/launcher/syringe/rapid + name = "rapid syringe gun" + desc = "A modification of the syringe gun design, using a rotating cylinder to store up to four syringes. The spring still needs to be drawn between shots." + icon_state = "rapidsyringegun" + max_darts = 4 diff --git a/code/modules/projectiles/guns/projectile.dm b/code/modules/projectiles/guns/projectile.dm index 26b42308ad7..128eddccde2 100644 --- a/code/modules/projectiles/guns/projectile.dm +++ b/code/modules/projectiles/guns/projectile.dm @@ -78,12 +78,12 @@ switch(AM.mag_type) if(MAGAZINE) if(ammo_magazine) - user << "[src] already has a magazine loaded!" //already a magazine here + user << "[src] already has a magazine loaded." //already a magazine here return user.remove_from_mob(AM) AM.loc = src ammo_magazine = AM - user.visible_message("[user] inserts [AM] into [src].", "You insert [AM] into [src]!") + user.visible_message("[user] inserts [AM] into [src].", "You insert [AM] into [src].") playsound(src.loc, 'sound/weapons/flipblade.ogg', 50, 1) if(SPEEDLOADER) if(loaded.len >= max_shells) @@ -99,7 +99,7 @@ AM.stored_ammo -= C //should probably go inside an ammo_magazine proc, but I guess less proc calls this way... count++ if(count) - user.visible_message("[user] reloads [src].", "You load [count] round\s into [src]!") + user.visible_message("[user] reloads [src].", "You load [count] round\s into [src].") playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1) AM.update_icon() else if(istype(A, /obj/item/ammo_casing)) @@ -107,13 +107,13 @@ if(!(load_method & SINGLE_CASING) || caliber != C.caliber) return //incompatible if(loaded.len >= max_shells) - user << "[src] is full!" + user << "[src] is full." return user.remove_from_mob(C) C.loc = src loaded.Insert(1, C) //add to the head of the list - user.visible_message("[user] inserts \a [C] into [src].", "You insert \a [C] into [src]!") + user.visible_message("[user] inserts \a [C] into [src].", "You insert \a [C] into [src].") playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1) update_icon() @@ -123,7 +123,7 @@ /obj/item/weapon/gun/projectile/proc/unload_ammo(mob/user, var/allow_dump=1) if(ammo_magazine) user.put_in_hands(ammo_magazine) - user.visible_message("[user] removes [ammo_magazine] from [src].", "You remove [ammo_magazine] from [src]!") + user.visible_message("[user] removes [ammo_magazine] from [src].", "You remove [ammo_magazine] from [src].") playsound(src.loc, 'sound/weapons/empty.ogg', 50, 1) ammo_magazine.update_icon() ammo_magazine = null @@ -138,14 +138,14 @@ count++ loaded.Cut() if(count) - user.visible_message("[user] unloads [src].", "You unload [count] round\s from [src]!") + user.visible_message("[user] unloads [src].", "You unload [count] round\s from [src].") else if(load_method & SINGLE_CASING) var/obj/item/ammo_casing/C = loaded[loaded.len] loaded.len-- user.put_in_hands(C) - user.visible_message("[user] removes \a [C] from [src].", "You remove \a [C] from [src]!") + user.visible_message("[user] removes \a [C] from [src].", "You remove \a [C] from [src].") else - user << "[src] is empty!" + user << "[src] is empty." update_icon() /obj/item/weapon/gun/projectile/attackby(var/obj/item/A as obj, mob/user as mob) diff --git a/code/modules/reagents/dartgun.dm b/code/modules/projectiles/guns/projectile/dartgun.dm similarity index 100% rename from code/modules/reagents/dartgun.dm rename to code/modules/projectiles/guns/projectile/dartgun.dm diff --git a/code/modules/reagents/syringe_gun.dm b/code/modules/reagents/syringe_gun.dm deleted file mode 100644 index 23a9eaa36b0..00000000000 --- a/code/modules/reagents/syringe_gun.dm +++ /dev/null @@ -1,130 +0,0 @@ -/obj/item/ammo_casing/gas_cartridge - name = "compressed gas cartridge" - desc = "An impact-triggered compressed gas cartridge that can fitted to a syringe for rapid injection. It's not very useful until primed though." //i.e. only works when shot out of a syringe gun. - icon_state = "syringe-cartridge" - caliber = "syringe" - projectile_type = /obj/item/projectile/bullet/syringe - w_class = 2 //mainly so that they can be yanked out - var/obj/item/weapon/reagent_containers/syringe/syringe - -/obj/item/ammo_casing/gas_cartridge/update_icon() - underlays.Cut() - if(syringe) - underlays += image(syringe.icon, src, syringe.icon_state) - underlays += syringe.filling - -/obj/item/ammo_casing/gas_cartridge/attackby(obj/item/I, mob/user) - if(istype(I, /obj/item/weapon/reagent_containers/syringe)) - syringe = I - user << "You carefully insert [syringe] into [src]." - user.remove_from_mob(syringe) - syringe.loc = src - var/obj/item/projectile/bullet/syringe/S = BB - if(istype(S)) - S.damage = 1 - S.sharp = 1 - update_icon() - -/obj/item/ammo_casing/gas_cartridge/attack_self(mob/user) - if(syringe) - user << "You remove [syringe] from [src]." - user.put_in_hands(syringe) - syringe = null - var/obj/item/projectile/bullet/syringe/S = BB - if(istype(S)) - S.damage = initial(S.damage) - S.sharp = initial(S.sharp) - update_icon() - -//This was kind of rushed, there may very well be a simpler way to implement this. -//Sort of hacky, though nearly not as bad as the previous implementation: -//Basically the syringe gun is supposed to launch the entire syringe+cartrige assemby, but hitby() isn't powerfull enough to do what we need. -//Instead, we fire a projectile that transfers the reagents, and teleport the cartridge once we impact something. -/obj/item/projectile/bullet/syringe - name = "syringe dart" - icon_state = "cbbolt" - damage = 3 - check_armour = "bullet" - sharp = 0 - embed = 0 //we handle this ourselves - var/obj/item/ammo_casing/gas_cartridge/cartridge - var/embedded = 0 - kill_count = 10 //short range - -/obj/item/projectile/bullet/syringe/New(newloc) - ..() - //ensure that cartridge is always set - cartridge = newloc - if(!istype(cartridge)) - del(src) - -/obj/item/projectile/bullet/syringe/on_hit(var/atom/target, var/blocked = 0, var/def_zone = null) - //..() //not really necessary - if(blocked < 2 && cartridge.syringe && isliving(target)) - var/mob/living/L = target - - //inject - if(L.can_inject(target_zone=def_zone)) - if(cartridge.syringe.reagents) - cartridge.syringe.reagents.trans_to(L, 15) - cartridge.syringe.update_icon() - cartridge.update_icon() - - //embed - L.embed(cartridge, def_zone) - embedded = 1 - -/obj/item/projectile/bullet/syringe/on_impact(atom/A) - if(!embedded) - cartridge.loc = src.loc - if(cartridge.syringe) - cartridge.syringe.break_syringe(iscarbon(A)? A : null) - cartridge.update_icon() - - - -/obj/item/weapon/gun/projectile/syringe - name = "syringe gun" - desc = "A spring loaded rifle designed to fit syringes, designed to incapacitate unruly patients from a distance." - icon = 'icons/obj/gun.dmi' - icon_state = "syringegun" - item_state = "syringegun" - w_class = 3 - force = 7 - matter = list("metal" = 2000) - slot_flags = SLOT_BELT - - caliber = "syringe" - fire_sound = 'sound/weapons/empty.ogg' - fire_sound_text = "a metallic thunk" - recoil = 0 - handle_casings = HOLD_CASINGS - load_method = SINGLE_CASING - max_shells = 1 - var/drawn = 0 - -/obj/item/weapon/gun/projectile/syringe/consume_next_projectile() - if(chambered) - return chambered.BB - return null - -/obj/item/weapon/gun/projectile/syringe/attack_self(mob/living/user as mob) - if(!chambered && loaded.len) - playsound(src.loc, 'sound/weapons/flipblade.ogg', 50, 1) - user.visible_message("[user] draws back the bolt on [src], clicking it into place.", "You draw back the bolt on the [src], loading the spring!") - var/obj/item/ammo_casing/AC = loaded[1] //load next casing. - loaded -= AC //Remove casing from loaded list. - chambered = AC - max_shells -= 1 //to prevent people from storing an extra syringe - update_icon() - -/obj/item/weapon/gun/projectile/syringe/handle_post_fire() - ..() - chambered = null - max_shells = initial(max_shells) - -/obj/item/weapon/gun/projectile/syringe/rapid - name = "rapid syringe gun" - desc = "A modification of the syringe gun design, using a rotating cylinder to store up to four syringes. The spring still needs to be drawn between shots." - icon_state = "rapidsyringegun" - max_shells = 4 diff --git a/code/modules/research/designs.dm b/code/modules/research/designs.dm index faf7e34d98d..9083a47e1c9 100644 --- a/code/modules/research/designs.dm +++ b/code/modules/research/designs.dm @@ -1312,7 +1312,7 @@ datum/design/item/weapon/rapidsyringe id = "rapidsyringe" req_tech = list("combat" = 3, "materials" = 3, "engineering" = 3, "biotech" = 2) materials = list("$metal" = 5000, "$glass" = 1000) - build_path = /obj/item/weapon/gun/projectile/syringe/rapid + build_path = /obj/item/weapon/gun/launcher/syringe/rapid /* datum/design/item/weapon/largecrossbow name = "Energy Crossbow" diff --git a/code/setup.dm b/code/setup.dm index 59cf86f868b..06235da7fc9 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -83,7 +83,7 @@ #define FIRE_MAX_FIRESUIT_STACKS 20 // If the number of stacks goes above this firesuits won't protect you anymore. If not, you can walk around while on fire like a badass. #define THROWFORCE_SPEED_DIVISOR 5 // The throwing speed value at which the throwforce multiplier is exactly 1. -#define THROWNOBJ_KNOCKBACK_SPEED 15 // The minumum speed of a thrown object that will cause living mobs it hits to be knocked back. +#define THROWNOBJ_KNOCKBACK_SPEED 15 // The minumum speed of a w_class 2 thrown object that will cause living mobs it hits to be knocked back. Heavier objects can cause knockback at lower speeds. #define THROWNOBJ_KNOCKBACK_DIVISOR 2 // Affects how much speed the mob is knocked back with. #define PRESSURE_DAMAGE_COEFFICIENT 4 // The amount of pressure damage someone takes is equal to (pressure / HAZARD_HIGH_PRESSURE)*PRESSURE_DAMAGE_COEFFICIENT, with the maximum of MAX_PRESSURE_DAMAGE. diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi index acade2ce1b265ed5f2222160b69622521ccbb9cf..e47e53e736913b7b2e3bcf9dbdfdee5939cff7e5 100644 GIT binary patch delta 4459 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 delta 4328 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 tO10z#1dP!OU|3qKmjB)&(+}