diff --git a/code/modules/projectiles/guns/energy/particle.dm b/code/modules/projectiles/guns/energy/particle.dm
index bb50366ec7..ab20585b49 100644
--- a/code/modules/projectiles/guns/energy/particle.dm
+++ b/code/modules/projectiles/guns/energy/particle.dm
@@ -1,11 +1,20 @@
-/obj/item/weapon/gun/energy/particle
- name = "Antiparticle projector gun"
+/obj/item/weapon/gun/energy/particle //base gun, similar stats to an egun
+ name = "Antiparticle projector pistol"
icon = 'icons/obj/gun_vr.dmi'
- icon_state = "particle"
- item_state = "particle"
- desc = "An unconventional firearm, APP guns generate attogram-scale quantities of antimatter which are then launched using an electromagnetic field."
- force = 5
- fire_sound = 'sound/weapons/Laser.ogg'
+ icon_state = "ppistol"
+ item_state = "ppistol_item"
+ icon_override = 'icons/obj/gun_vr.dmi'
+ item_icons = null
+ desc = "A Kawashima Material Technology Model 7 anti-particle projector, housed in a rugged casing."
+ description_info = "An unconventional weapon, APP guns generate attogram-scale quantities of antimatter which \
+ are then launched using an electromagnetic field. They are only suitable for use in depressurised environments, \
+ else the antimatter pellet is liable to strike the air before it reaches the target. This can result in catastrophic \
+ failure, making them unsuitable as military weapons in practical situations as they are prone to backfiring and \
+ jamming, though they perform as adequately as any laser weapon in vacuum. Nonetheless, they have found a niche among \
+ miners and salvage crews, as their lack of usefulness as a firearm in habitable areas means most authorities do not \
+ classify them as dangerous weapons (at least, not dangerous to whoever they're pointed at) - instead, in most \
+ jurisdictions including NT space, APP guns are officially classed as mining equipment rather than firearms."
+ fire_sound = 'sound/weapons/blaster.ogg'
slot_flags = SLOT_BELT
w_class = ITEMSIZE_NORMAL
projectile_type = /obj/item/projectile/bullet/particle
@@ -13,8 +22,45 @@
fire_delay = 10
charge_cost = 240 //same cost as lasers
var/safetycatch = 0 //if 1, won't let you fire in pressurised environment, rather than malfunctioning
+ var/obj/item/pressurelock/attached_safety
+/obj/item/weapon/gun/energy/particle/advanced //particle equivalent of AEG
+ name = "Advanced antiparticle rifle"
+ icon_state = "particle"
+ item_state = "particle_item"
+ desc = "An antiparticle projector gun with an enhanced power-generation unit."
+ slot_flags = SLOT_BELT
+ force = 8 //looks heavier than a pistol
+ w_class = ITEMSIZE_LARGE //bigger than a pistol, too.
+ fire_delay = 6 //This one's not a handgun, it should have the same fire delay as everything else
+ self_recharge = 1
+ modifystate = null
+ battery_lock = 1
+ recharge_time = 15 // every 15 ticks, recharge 2 shots. Rather slower than AEG.
+ charge_delay = 20 //Starts recharging faster after firing than an AEG, but much slower recharge rate. Balances out for a full charge.
+
+/obj/item/weapon/gun/energy/particle/cannon //particle version of laser cannon
+ name = "Anti-particle cannon"
+ desc = "A giant beast of an antimatter gun, packed with an internal reactor to allow for extreme longevity on remote mining expeditions."
+ icon_state = "heavyparticle"
+ item_state = "heavyparticle_item"
+ fire_sound = 'sound/weapons/lasercannonfire.ogg'
+ slot_flags = SLOT_BACK
+ projectile_type = /obj/item/projectile/bullet/particle/heavy
+ battery_lock = 1
+ fire_delay = 20
+ w_class = ITEMSIZE_HUGE // So it can't fit in a backpack.
+ force = 10
+ one_handed_penalty = 6 // The thing's heavy and huge.
+ accuracy = 3
+ charge_cost = 480 // 5 shots
+ self_recharge = 1
+ charge_delay = 20 //won't start charging until it's ready to fire again
+ recharge_time = 20 //100 ticks after that to refill the whole thing.
+
+//special behaviours for particle guns below
+
/obj/item/weapon/gun/energy/particle/special_check(var/mob/user)
if (..())
var/turf/T = get_turf(src)
@@ -32,56 +78,113 @@
return 0
else if (prob(min(pressure, 100))) //pressure% chance of failing
var/severity = rand(pressure)
- if (severity <= 10) // just doesn't fire. 10% chance in 100 atmo.
- user.visible_message("*click*", "\The [src] jams.")
- playsound(src.loc, 'sound/weapons/empty.ogg', 100, 1)
- else if (severity <= 60) //50% chance of fizzling and wasting a shot
- user.visible_message("\The [user] fires \the [src], but the shot fizzles in the air!", "You fire \the [src], but the shot fizzles in the air!")
- power_supply.charge -= charge_cost
- playsound(src.loc, fire_sound, 100, 1)
- var/datum/effect/effect/system/spark_spread/sparks = PoolOrNew(/datum/effect/effect/system/spark_spread)
- sparks.set_up(2, 1, T)
- sparks.start()
- update_icon()
- else if (severity <= 80) //20% chance of shorting out and emptying the cell
- user.visible_message("\The [user] pulls the trigger, but \the [src] shorts out!", "You pull the trigger, but \the [src] shorts out!")
- power_supply.charge = 0
- var/datum/effect/effect/system/spark_spread/sparks = PoolOrNew(/datum/effect/effect/system/spark_spread)
- sparks.set_up(2, 1, T)
- sparks.start()
- update_icon()
- else if (severity <= 90) //10% chance of breaking the gun
- user.visible_message("\The [user] pulls the trigger, but \the [src] erupts in a shower of sparks!", "You pull the trigger, but \the [src] bursts into a shower of sparks!")
- var/datum/effect/effect/system/spark_spread/sparks = PoolOrNew(/datum/effect/effect/system/spark_spread)
- sparks.set_up(2, 1, T)
- sparks.start()
- power_supply.charge = 0
- power_supply.maxcharge = 0
- power_supply.desc += " It seems to be burnt out!"
- desc += " The casing is covered in scorch-marks."
- fire_delay += fire_delay // even if you swap out the cell for a good one, the gun's cluckety-clucked.
- charge_cost += charge_cost
- update_icon()
- else if (severity <= 150) // 10% chance of exploding
- user << "The [src] explodes!"
- explosion(T, -1, -1, 1, 1)
- qdel(src)
- else //can only possibly happen if you're dumb enough to fire it in an OVER pressure environment, over 150kPa
- user << "The [src] explodes catastrophically!"
- explosion(T, -1, 1, 2, 2)
- qdel(src)
+ pressuremalfunction(severity, user, T)
return 0
return 1
return 0
+/obj/item/weapon/gun/energy/particle/proc/pressuremalfunction(severity, var/mob/user, var/turf/T)
+ if (severity <= 10) // just doesn't fire. 10% chance in 100 atmo.
+ user.visible_message("*click*", "\The [src] jams.")
+ playsound(src.loc, 'sound/weapons/empty.ogg', 100, 1)
+ else if (severity <= 60) //50% chance of fizzling and wasting a shot
+ user.visible_message("\The [user] fires \the [src], but the shot fizzles in the air!", "You fire \the [src], but the shot fizzles in the air!")
+ power_supply.charge -= charge_cost
+ playsound(src.loc, fire_sound, 100, 1)
+ var/datum/effect/effect/system/spark_spread/sparks = PoolOrNew(/datum/effect/effect/system/spark_spread)
+ sparks.set_up(2, 1, T)
+ sparks.start()
+ update_icon()
+ else if (severity <= 80) //20% chance of shorting out and emptying the cell
+ user.visible_message("\The [user] pulls the trigger, but \the [src] shorts out!", "You pull the trigger, but \the [src] shorts out!")
+ power_supply.charge = 0
+ var/datum/effect/effect/system/spark_spread/sparks = PoolOrNew(/datum/effect/effect/system/spark_spread)
+ sparks.set_up(2, 1, T)
+ sparks.start()
+ update_icon()
+ else if (severity <= 90) //10% chance of breaking the gun
+ user.visible_message("\The [user] pulls the trigger, but \the [src] erupts in a shower of sparks!", "You pull the trigger, but \the [src] bursts into a shower of sparks!")
+ var/datum/effect/effect/system/spark_spread/sparks = PoolOrNew(/datum/effect/effect/system/spark_spread)
+ sparks.set_up(2, 1, T)
+ sparks.start()
+ power_supply.charge = 0
+ power_supply.maxcharge = 1 //just to avoid div/0 runtimes
+ power_supply.desc += " It seems to be burnt out!"
+ desc += " The casing is covered in scorch-marks."
+ fire_delay += fire_delay // even if you swap out the cell for a good one, the gun's cluckety-clucked.
+ charge_cost += charge_cost
+ update_icon()
+ else if (severity <= 150) // 10% chance of exploding
+ user.visible_message("\The [user] pulls the trigger, but \the [src] explodes!", "The [src] explodes!")
+ log_and_message_admins("blew themself up with a particle gun.", user)
+ explosion(T, -1, -1, 1, 1)
+ qdel(src)
+ else //can only possibly happen if you're dumb enough to fire it in an OVER pressure environment, over 150kPa
+ user.visible_message("\The [user] pulls the trigger, but \the [src] explodes!", "The [src] explodes catastrophically!")
+ log_and_message_admins("blew their dumb ass up with a particle gun.", user)
+ explosion(T, -1, 1, 2, 2)
+ qdel(src)
+
+/obj/item/weapon/gun/energy/particle/cannon/pressuremalfunction(severity, user, T)
+ ..(severity*2, user, T)
+
+
+/obj/item/weapon/gun/energy/particle/attackby(var/obj/item/A as obj, mob/user as mob)
+ if(istype(A, /obj/item/pressurelock))
+ if(safetycatch)
+ user << "\The [src] already has a [attached_safety]."
+ return
+ user << "You insert \the [A] into \the [src]."
+ user.drop_item()
+ A.loc = src
+ attached_safety = A
+ safetycatch = 1
+ return
+
+ if(istype(A, /obj/item/weapon/screwdriver))
+ if(safetycatch && attached_safety)
+ user << "You begin removing \the [attached_safety] from \the [src]."
+ if(do_after(user, 25))
+ user << "You remove \the [attached_safety] from \the [src]."
+ user.put_in_hands(attached_safety)
+ safetycatch = 0
+ attached_safety = null
+ return
+ ..()
+
+
+// accessory
+
+/obj/item/pressurelock
+ name = "Pressure interlock"
+ icon = 'icons/obj/gun_vr.dmi'
+ icon_state = "pressurelock"
+ desc = "A safety interlock that can be installed in an antiparticle projector. It prevents the weapon from discharging in pressurised environments."
+ w_class = ITEMSIZE_TINY
+
// projectiles below
/obj/item/projectile/bullet/particle
- name = "particle"
+ name = "antimatter pellet"
icon = 'icons/obj/projectiles_vr.dmi'
icon_state = "particle"
damage = 40
damage_type = BURN
check_armour = "energy"
embed_chance = 0
+
+/obj/item/projectile/bullet/particle/heavy
+ name = "antimatter slug"
+ icon_state = "particle-heavy"
+ damage = 80 // same as a laser cannon
+ armor_penetration = 25 //it explodes on the surface of things, so less armor pen than the laser cannon
+ light_range = 3
+ light_power = 1
+ light_color = "#CCFFFF"
+
+/turf/simulated/mineral/bullet_act(var/obj/item/projectile/Proj)
+ if(istype(Proj, /obj/item/projectile/bullet/particle))
+ if(prob(Proj.damage))
+ GetDrilled()
+
diff --git a/icons/obj/gun_vr.dmi b/icons/obj/gun_vr.dmi
index 48dbdeb4af..a7acc2cad8 100644
Binary files a/icons/obj/gun_vr.dmi and b/icons/obj/gun_vr.dmi differ
diff --git a/icons/obj/projectiles_vr.dmi b/icons/obj/projectiles_vr.dmi
index e34d3c0c21..0fa44fbec3 100644
Binary files a/icons/obj/projectiles_vr.dmi and b/icons/obj/projectiles_vr.dmi differ