diff --git a/code/ZAS/Connection.dm b/code/ZAS/Connection.dm
index f63837a5ffc..ab479450cf1 100644
--- a/code/ZAS/Connection.dm
+++ b/code/ZAS/Connection.dm
@@ -158,51 +158,53 @@ connection
if(!istype(zone_1) || !istype(zone_2))
return
- //Handle disconnection of indirectly or directly connected zones.
- if( (zone_1 in zone_2.connected_zones) || (zone_2 in zone_1.connected_zones) )
+ if(indirect != CONNECTION_CLOSED)
+ //Handle disconnection of indirectly or directly connected zones.
+ if( (zone_1 in zone_2.connected_zones) || (zone_2 in zone_1.connected_zones) )
- //If there are more than one connection, decrement the number of connections
- //Otherwise, remove all connections between the zones.
- if(zone_2 in zone_1.connected_zones)
- if(zone_1.connected_zones[zone_2] > 1)
- zone_1.connected_zones[zone_2]--
- else
- zone_1.connected_zones -= zone_2
- //remove the list if it is empty
- if(!zone_1.connected_zones.len)
- zone_1.connected_zones = null
+ //If there are more than one connection, decrement the number of connections
+ //Otherwise, remove all connections between the zones.
+ if(zone_2 in zone_1.connected_zones)
+ if(zone_1.connected_zones[zone_2] > 1)
+ zone_1.connected_zones[zone_2]--
+ else
+ zone_1.connected_zones -= zone_2
+ //remove the list if it is empty
+ if(!zone_1.connected_zones.len)
+ zone_1.connected_zones = null
- //Then do the same for the other zone.
- if(zone_1 in zone_2.connected_zones)
- if(zone_2.connected_zones[zone_1] > 1)
- zone_2.connected_zones[zone_1]--
- else
- zone_2.connected_zones -= zone_1
- if(!zone_2.connected_zones.len)
- zone_2.connected_zones = null
+ //Then do the same for the other zone.
+ if(zone_1 in zone_2.connected_zones)
+ if(zone_2.connected_zones[zone_1] > 1)
+ zone_2.connected_zones[zone_1]--
+ else
+ zone_2.connected_zones -= zone_1
+ if(!zone_2.connected_zones.len)
+ zone_2.connected_zones = null
- //Handle disconnection of closed zones.
- if( (zone_1 in zone_2.closed_connection_zones) || (zone_2 in zone_1.closed_connection_zones) )
+ else
+ //Handle disconnection of closed zones.
+ if( (zone_1 in zone_2.closed_connection_zones) || (zone_2 in zone_1.closed_connection_zones) )
- //If there are more than one connection, decrement the number of connections
- //Otherwise, remove all connections between the zones.
- if(zone_2 in zone_1.connected_zones)
- if(zone_1.closed_connection_zones[zone_2] > 1)
- zone_1.closed_connection_zones[zone_2]--
- else
- zone_1.closed_connection_zones -= zone_2
- //remove the list if it is empty
- if(!zone_1.closed_connection_zones.len)
- zone_1.closed_connection_zones = null
+ //If there are more than one connection, decrement the number of connections
+ //Otherwise, remove all connections between the zones.
+ if(zone_2 in zone_1.connected_zones)
+ if(zone_1.closed_connection_zones[zone_2] > 1)
+ zone_1.closed_connection_zones[zone_2]--
+ else
+ zone_1.closed_connection_zones -= zone_2
+ //remove the list if it is empty
+ if(!zone_1.closed_connection_zones.len)
+ zone_1.closed_connection_zones = null
- //Then do the same for the other zone.
- if(zone_1 in zone_2.connected_zones)
- if(zone_2.closed_connection_zones[zone_1] > 1)
- zone_2.closed_connection_zones[zone_1]--
- else
- zone_2.closed_connection_zones -= zone_1
- if(!zone_2.closed_connection_zones.len)
- zone_2.closed_connection_zones = null
+ //Then do the same for the other zone.
+ if(zone_1 in zone_2.connected_zones)
+ if(zone_2.closed_connection_zones[zone_1] > 1)
+ zone_2.closed_connection_zones[zone_1]--
+ else
+ zone_2.closed_connection_zones -= zone_1
+ if(!zone_2.closed_connection_zones.len)
+ zone_2.closed_connection_zones = null
proc/Cleanup()
@@ -259,9 +261,8 @@ connection
//The door is instead closed.
else if(indirect > CONNECTION_CLOSED)
- indirect = CONNECTION_CLOSED
-
DisconnectZones(A.zone, B.zone)
+ indirect = CONNECTION_CLOSED
ConnectZones(A.zone, B.zone)
//If I can no longer pass air, better delete
@@ -381,7 +382,7 @@ connection
//Handle diconnection and reconnection of zones.
if(zone_A && zone_B)
DisconnectZones(zone_A, zone_B)
- ConnectZones(A.zone, B.zone, indirect)
+ ConnectZones(A.zone, B.zone, indirect)
#undef CONNECTION_DIRECT
diff --git a/code/game/machinery/iv_drip.dm b/code/game/machinery/iv_drip.dm
index da6f8f90c89..40f5a3b9593 100644
--- a/code/game/machinery/iv_drip.dm
+++ b/code/game/machinery/iv_drip.dm
@@ -112,7 +112,8 @@
if (B)
beaker.reagents.reagent_list |= B
- beaker.reagents.update_total()
+ beaker.reagents.del_reagent("clonexadone") //Fix for infinite meat spawning when taking blood from human
+ beaker.reagents.update_total() //to an IV drip full of clonex
beaker.on_reagent_change()
beaker.reagents.handle_reactions()
update_icon()
diff --git a/code/modules/reagents/syringe_gun.dm b/code/modules/reagents/syringe_gun.dm
index eaa372bd45d..2bb818c3737 100644
--- a/code/modules/reagents/syringe_gun.dm
+++ b/code/modules/reagents/syringe_gun.dm
@@ -128,4 +128,279 @@
New()
var/datum/reagents/R = new/datum/reagents(15)
reagents = R
- R.my_atom = src
\ No newline at end of file
+ R.my_atom = src
+
+/obj/item/weapon/dart_cartridge
+ name = "dart cartridge"
+ desc = "A rack of hollow darts."
+ icon = 'icons/obj/ammo.dmi'
+ icon_state = "darts-5"
+ item_state = "rcdammo"
+ opacity = 0
+ density = 0
+ anchored = 0.0
+ origin_tech = "materials=2"
+ var/darts = 5
+
+/obj/item/weapon/dart_cartridge/update_icon()
+ if(!darts)
+ icon_state = "darts-0"
+ else if(darts > 5)
+ icon_state = "darts-5"
+ else
+ icon_state = "darts-[darts]"
+ return 1
+
+/obj/item/weapon/gun/dartgun
+ name = "dart gun"
+ desc = "A small gas-powered dartgun, capable of delivering chemical cocktails swiftly across short distances."
+ icon_state = "dartgun-empty"
+
+ var/list/beakers = list() //All containers inside the gun.
+ var/list/mixing = list() //Containers being used for mixing.
+ var/obj/item/weapon/dart_cartridge/cartridge = null //Container of darts.
+ var/max_beakers = 3
+
+/obj/item/weapon/gun/dartgun/update_icon()
+
+ if(!cartridge)
+ icon_state = "dartgun-empty"
+ return 1
+
+ if(!cartridge.darts)
+ icon_state = "dartgun-0"
+ else if(cartridge.darts > 5)
+ icon_state = "dartgun-5"
+ else
+ icon_state = "dartgun-[cartridge.darts]"
+ return 1
+
+/obj/item/weapon/gun/dartgun/New()
+
+ if(beakers.len)
+ return
+
+ // The dartgun has one beaker by default.
+ var/obj/item/weapon/reagent_containers/glass/beaker/B = new(src)
+ beakers += B
+
+ ..()
+
+/obj/item/weapon/gun/dartgun/examine()
+ set src in view()
+ update_icon()
+ ..()
+ if (!(usr in view(2)) && usr!=src.loc)
+ return
+ if (beakers.len)
+ usr << "\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)
+ usr << "\blue [R.volume] units of [R.name]"
+
+/obj/item/weapon/gun/dartgun/attackby(obj/item/I as obj, mob/user as mob)
+ if(istype(I, /obj/item/weapon/dart_cartridge))
+
+ var/obj/item/weapon/dart_cartridge/D = I
+
+ if(!D.darts)
+ user << "\blue [D] is empty."
+ return 0
+
+ if(cartridge)
+ if(cartridge.darts <= 0)
+ src.remove_cartridge()
+ else
+ user << "\blue There's already a cartridge in [src]."
+ return 0
+
+ user.drop_item()
+ cartridge = D
+ D.loc = src
+ user << "\blue You slot [D] into [src]."
+ update_icon()
+ return
+ if(istype(I, /obj/item/weapon/reagent_containers/glass/beaker))
+ 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()
+
+/obj/item/weapon/gun/dartgun/can_fire()
+ if(!cartridge)
+ return 0
+ else
+ return cartridge.darts
+
+/obj/item/weapon/gun/dartgun/proc/has_selected_beaker_reagents()
+ return 0
+
+/obj/item/weapon/gun/dartgun/proc/remove_cartridge()
+ if(cartridge)
+ usr << "\blue You pop the cartridge out of [src]."
+ var/obj/item/weapon/dart_cartridge/C = cartridge
+ C.loc = get_turf(src)
+ C.update_icon()
+ cartridge = null
+ src.update_icon()
+
+/obj/item/weapon/gun/dartgun/proc/get_mixed_syringe()
+ if (!cartridge)
+ return 0
+ if(!cartridge.darts)
+ return 0
+
+ var/obj/item/weapon/reagent_containers/syringe/dart = new(src)
+
+ if(mixing.len)
+ var/mix_amount = 10/mixing.len
+ for(var/obj/item/weapon/reagent_containers/glass/beaker/B in mixing)
+ B.reagents.trans_to(dart,mix_amount)
+
+ return dart
+
+/obj/item/weapon/gun/dartgun/proc/fire_dart(atom/target, mob/user)
+ if (locate (/obj/structure/table, src.loc))
+ return
+ else
+ var/turf/trg = get_turf(target)
+ var/obj/effect/syringe_gun_dummy/D = new/obj/effect/syringe_gun_dummy(get_turf(src))
+ var/obj/item/weapon/reagent_containers/syringe/S = get_mixed_syringe()
+ if(!S)
+ user << "\red There are no darts in [src]!"
+ return
+ if(!S.reagents)
+ user << "\red There are no reagents available!"
+ return
+ cartridge.darts--
+ src.update_icon()
+ S.reagents.trans_to(D, S.reagents.total_volume)
+ del(S)
+ D.icon_state = "syringeproj"
+ D.name = "syringe"
+ playsound(user.loc, 'sound/items/syringeproj.ogg', 50, 1)
+
+ for(var/i=0, i<6, i++)
+ if(!D) break
+ if(D.loc == trg) break
+ step_towards(D,trg)
+
+ if(D)
+ for(var/mob/living/carbon/M in D.loc)
+ if(!istype(M,/mob/living/carbon)) continue
+ if(M == user) continue
+ //Syringe gun attack logging by Yvarov
+ var/R
+ if(D.reagents)
+ for(var/datum/reagent/A in D.reagents.reagent_list)
+ R += A.id + " ("
+ R += num2text(A.volume) + "),"
+ if (istype(M, /mob))
+ M.attack_log += "\[[time_stamp()]\] [user]/[user.ckey] shot [M]/[M.ckey] with a syringegun ([R])"
+ user.attack_log += "\[[time_stamp()]\] [user]/[user.ckey] shot [M]/[M.ckey] with a syringegun ([R])"
+ log_attack("[user] ([user.ckey]) shot [M] ([M.ckey]) with a syringegun ([R])")
+
+ else
+ M.attack_log += "\[[time_stamp()]\] UNKNOWN SUBJECT (No longer exists) shot [M]/[M.ckey] with a syringegun ([R])"
+ log_attack("UNKNOWN shot [M] ([M.ckey]) with a syringegun ([R])")
+
+ if(D.reagents)
+ D.reagents.trans_to(M, 15)
+ M << "You feel a slight prick."
+
+ del(D)
+ break
+ if(D)
+ for(var/atom/A in D.loc)
+ if(A == user) continue
+ if(A.density) del(D)
+
+ sleep(1)
+
+ if (D) spawn(10) del(D)
+
+ return
+
+/obj/item/weapon/gun/dartgun/afterattack(obj/target, mob/user , flag)
+ if(!isturf(target.loc) || target == user) return
+ ..()
+
+/obj/item/weapon/gun/dartgun/can_hit(var/mob/living/target as mob, var/mob/living/user as mob)
+ return 1
+
+/obj/item/weapon/gun/dartgun/attack_self(user as mob)
+ var/dat = "[src] mixing control:
"
+
+ 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 += "
[R.volume] units of [R.name], "
+ if (check_beaker_mixing(B))
+ dat += text("Mixing ")
+ else
+ dat += text("Not mixing ")
+ else
+ dat += "nothing."
+ dat += " \[Eject\]
"
+ i++
+ else
+ dat += "There are no beakers inserted!
"
+
+ if(cartridge)
+ if(cartridge.darts)
+ dat += "The dart cartridge has [cartridge.darts] shots remaining."
+ else
+ dat += "The dart cartridge is empty!"
+ dat += " \[Eject\]"
+
+ user << browse("[dat]", "window=dartgun_mixing_window")
+
+/obj/item/weapon/gun/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/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"])
+ remove_cartridge()
+ src.updateUsrDialog()
+ return
+
+/obj/item/weapon/gun/dartgun/Fire(atom/target as mob|obj|turf|area, mob/living/user as mob|obj, params, reflex = 0)
+ if(cartridge)
+ spawn(0) fire_dart(target,user)
+ else
+ usr << "\red [src] is empty."
\ No newline at end of file
diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi
index 8ca8da77f74..86d6829d138 100644
Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ
diff --git a/icons/obj/gun.dmi b/icons/obj/gun.dmi
index 5a0eab2d2a6..2ad4316d4a0 100644
Binary files a/icons/obj/gun.dmi and b/icons/obj/gun.dmi differ