mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-11 18:53:06 +00:00
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.
This commit is contained in:
@@ -1,197 +0,0 @@
|
||||
/obj/item/projectile/bullet/chemdart
|
||||
name = "dart"
|
||||
icon_state = "cbbolt"
|
||||
damage = 3
|
||||
sharp = 1
|
||||
embed = 1
|
||||
var/reagent_amount = 15
|
||||
kill_count = 10 //short range
|
||||
|
||||
/obj/item/projectile/bullet/chemdart/New()
|
||||
reagents = new/datum/reagents(reagent_amount)
|
||||
reagents.my_atom = src
|
||||
|
||||
/obj/item/projectile/bullet/chemdart/on_hit(var/atom/target, var/blocked = 0, var/def_zone = null)
|
||||
if(blocked < 2 && isliving(target))
|
||||
var/mob/living/L = target
|
||||
if(L.can_inject(target_zone=def_zone))
|
||||
reagents.trans_to(L, reagent_amount)
|
||||
|
||||
/obj/item/ammo_casing/chemdart
|
||||
name = "chemical dart"
|
||||
desc = "A small hollow dart."
|
||||
icon_state = "dart"
|
||||
caliber = "dart"
|
||||
projectile_type = /obj/item/projectile/bullet/chemdart
|
||||
|
||||
/obj/item/ammo_magazine/chemdart
|
||||
name = "dart cartridge"
|
||||
desc = "A rack of hollow darts."
|
||||
icon_state = "darts"
|
||||
item_state = "rcdammo"
|
||||
origin_tech = "materials=2"
|
||||
mag_type = MAGAZINE
|
||||
caliber = "dart"
|
||||
max_ammo = 5
|
||||
multiple_sprites = 1
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun
|
||||
name = "dart gun"
|
||||
desc = "A small gas-powered dartgun, capable of delivering chemical cocktails swiftly across short distances."
|
||||
icon_state = "dartgun-empty"
|
||||
|
||||
caliber = "dart"
|
||||
fire_sound = 'sound/weapons/empty.ogg'
|
||||
fire_sound_text = "a metallic click"
|
||||
recoil = 0
|
||||
silenced = 1
|
||||
load_method = MAGAZINE
|
||||
magazine_type = /obj/item/ammo_magazine/chemdart
|
||||
auto_eject = 0
|
||||
|
||||
var/list/beakers = list() //All containers inside the gun.
|
||||
var/list/mixing = list() //Containers being used for mixing.
|
||||
var/max_beakers = 3
|
||||
var/dart_reagent_amount = 15
|
||||
var/container_type = /obj/item/weapon/reagent_containers/glass/beaker
|
||||
var/list/starting_chems = null
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/dartgun/New()
|
||||
..()
|
||||
if(starting_chems)
|
||||
for(var/chem in starting_chems)
|
||||
var/obj/B = new container_type(src)
|
||||
B.reagents.add_reagent(chem, 60)
|
||||
beakers += B
|
||||
update_icon()
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/update_icon()
|
||||
if(!ammo_magazine)
|
||||
icon_state = "dartgun-empty"
|
||||
return 1
|
||||
|
||||
if(!ammo_magazine.stored_ammo || ammo_magazine.stored_ammo.len)
|
||||
icon_state = "dartgun-0"
|
||||
else if(ammo_magazine.stored_ammo.len > 5)
|
||||
icon_state = "dartgun-5"
|
||||
else
|
||||
icon_state = "dartgun-[ammo_magazine.stored_ammo.len]"
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/consume_next_projectile()
|
||||
. = ..()
|
||||
var/obj/item/projectile/bullet/chemdart/dart = .
|
||||
if(istype(dart))
|
||||
fill_dart(dart)
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/examine(mob/user)
|
||||
//update_icon()
|
||||
//if (!..(user, 2))
|
||||
// return
|
||||
..()
|
||||
if (beakers.len)
|
||||
user << "\blue [src] contains:"
|
||||
for(var/obj/item/weapon/reagent_containers/glass/beaker/B in beakers)
|
||||
if(B.reagents && B.reagents.reagent_list.len)
|
||||
for(var/datum/reagent/R in B.reagents.reagent_list)
|
||||
user << "\blue [R.volume] units of [R.name]"
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/attackby(obj/item/I as obj, mob/user as mob)
|
||||
if(istype(I, /obj/item/weapon/reagent_containers/glass))
|
||||
if(!istype(I, container_type))
|
||||
user << "\blue [I] doesn't seem to fit into [src]."
|
||||
return
|
||||
if(beakers.len >= max_beakers)
|
||||
user << "\blue [src] already has [max_beakers] beakers in it - another one isn't going to fit!"
|
||||
return
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B = I
|
||||
user.drop_item()
|
||||
B.loc = src
|
||||
beakers += B
|
||||
user << "\blue You slot [B] into [src]."
|
||||
src.updateUsrDialog()
|
||||
..()
|
||||
|
||||
//fills the given dart with reagents
|
||||
/obj/item/weapon/gun/projectile/dartgun/proc/fill_dart(var/obj/item/projectile/bullet/chemdart/dart)
|
||||
if(mixing.len)
|
||||
var/mix_amount = dart.reagent_amount/mixing.len
|
||||
for(var/obj/item/weapon/reagent_containers/glass/beaker/B in mixing)
|
||||
B.reagents.trans_to(dart, mix_amount)
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/attack_self(mob/user)
|
||||
user.set_machine(src)
|
||||
var/dat = "<b>[src] mixing control:</b><br><br>"
|
||||
|
||||
if (beakers.len)
|
||||
var/i = 1
|
||||
for(var/obj/item/weapon/reagent_containers/glass/beaker/B in beakers)
|
||||
dat += "Beaker [i] contains: "
|
||||
if(B.reagents && B.reagents.reagent_list.len)
|
||||
for(var/datum/reagent/R in B.reagents.reagent_list)
|
||||
dat += "<br> [R.volume] units of [R.name], "
|
||||
if (check_beaker_mixing(B))
|
||||
dat += text("<A href='?src=\ref[src];stop_mix=[i]'><font color='green'>Mixing</font></A> ")
|
||||
else
|
||||
dat += text("<A href='?src=\ref[src];mix=[i]'><font color='red'>Not mixing</font></A> ")
|
||||
else
|
||||
dat += "nothing."
|
||||
dat += " \[<A href='?src=\ref[src];eject=[i]'>Eject</A>\]<br>"
|
||||
i++
|
||||
else
|
||||
dat += "There are no beakers inserted!<br><br>"
|
||||
|
||||
if(ammo_magazine)
|
||||
if(ammo_magazine.stored_ammo && ammo_magazine.stored_ammo.len)
|
||||
dat += "The dart cartridge has [ammo_magazine.stored_ammo.len] shots remaining."
|
||||
else
|
||||
dat += "<font color='red'>The dart cartridge is empty!</font>"
|
||||
dat += " \[<A href='?src=\ref[src];eject_cart=1'>Eject</A>\]"
|
||||
|
||||
user << browse(dat, "window=dartgun")
|
||||
onclose(user, "dartgun", src)
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/proc/check_beaker_mixing(var/obj/item/B)
|
||||
if(!mixing || !beakers)
|
||||
return 0
|
||||
for(var/obj/item/M in mixing)
|
||||
if(M == B)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/Topic(href, href_list)
|
||||
src.add_fingerprint(usr)
|
||||
if(href_list["stop_mix"])
|
||||
var/index = text2num(href_list["stop_mix"])
|
||||
if(index <= beakers.len)
|
||||
for(var/obj/item/M in mixing)
|
||||
if(M == beakers[index])
|
||||
mixing -= M
|
||||
break
|
||||
else if (href_list["mix"])
|
||||
var/index = text2num(href_list["mix"])
|
||||
if(index <= beakers.len)
|
||||
mixing += beakers[index]
|
||||
else if (href_list["eject"])
|
||||
var/index = text2num(href_list["eject"])
|
||||
if(index <= beakers.len)
|
||||
if(beakers[index])
|
||||
var/obj/item/weapon/reagent_containers/glass/beaker/B = beakers[index]
|
||||
usr << "You remove [B] from [src]."
|
||||
mixing -= B
|
||||
beakers -= B
|
||||
B.loc = get_turf(src)
|
||||
else if (href_list["eject_cart"])
|
||||
unload_ammo(usr)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/vox
|
||||
name = "alien dart gun"
|
||||
desc = "A small gas-powered dartgun, fitted for nonhuman hands."
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/vox/medical
|
||||
starting_chems = list("kelotane","bicaridine","anti_toxin")
|
||||
|
||||
/obj/item/weapon/gun/projectile/dartgun/vox/raider
|
||||
starting_chems = list("space_drugs","stoxin","impedrezene")
|
||||
@@ -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 << "<span class='notice'>You carefully insert [syringe] into [src].</span>"
|
||||
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 << "<span class='notice'>You remove [syringe] from [src].</span>"
|
||||
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.", "<span class='warning'>You draw back the bolt on the [src], loading the spring!</span>")
|
||||
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
|
||||
Reference in New Issue
Block a user