diff --git a/code/game/machinery/portable_turret.dm b/code/game/machinery/portable_turret.dm
index 31a3a74d63..12343bb343 100644
--- a/code/game/machinery/portable_turret.dm
+++ b/code/game/machinery/portable_turret.dm
@@ -840,8 +840,7 @@
//Shooting Code:
A.firer = src
A.old_style_target(target)
- A.def_zone = def_zone
- A.fire()
+ A.launch_projectile_from_turf(target, def_zone, src)
// Reset the time needed to go back down, since we just tried to shoot at someone.
timeout = 10
diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm
index bbc13e381e..e657876b7d 100644
--- a/code/modules/projectiles/gun.dm
+++ b/code/modules/projectiles/gun.dm
@@ -180,15 +180,15 @@
if(dna_lock && attached_lock.stored_dna)
if(!authorized_user(user))
if(attached_lock.safety_level == 0)
- to_chat(M, "\The [src] buzzes in dissapoint and displays an invalid DNA symbol.")
+ to_chat(M, "\The [src] buzzes in dissapointment and displays an invalid DNA symbol.")
return 0
if(!attached_lock.exploding)
if(attached_lock.safety_level == 1)
to_chat(M, "\The [src] hisses in dissapointment.")
visible_message("\The [src] announces, \"Self-destruct occurring in ten seconds.\"", "\The [src] announces, \"Self-destruct occurring in ten seconds.\"")
+ attached_lock.exploding = 1
spawn(100)
explosion(src, 0, 0, 3, 4)
- attached_lock.exploding = 1
sleep(1)
qdel(src)
return 0
diff --git a/code/modules/projectiles/guns/energy/laser.dm b/code/modules/projectiles/guns/energy/laser.dm
index 6d7bdfef7a..266df1f358 100644
--- a/code/modules/projectiles/guns/energy/laser.dm
+++ b/code/modules/projectiles/guns/energy/laser.dm
@@ -245,3 +245,17 @@
item_state = "redtag"
projectile_type = /obj/item/projectile/beam/lastertag/red
required_vest = /obj/item/clothing/suit/redtag
+
+/*
+ * Laser scattergun, proof of concept.
+ */
+
+/obj/item/weapon/gun/energy/lasershotgun
+ name = "laser scattergun"
+ icon = 'icons/obj/energygun.dmi'
+ item_state = "laser"
+ icon_state = "scatter"
+ desc = "A strange Almachi weapon, utilizing a refracting prism to turn a single laser blast into a diverging cluster."
+ origin_tech = list(TECH_COMBAT = 3, TECH_MAGNET = 1, TECH_MATERIAL = 4)
+
+ projectile_type = /obj/item/projectile/scatter/laser
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index d74bfb9caf..0eaf2d2f42 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -84,8 +84,17 @@
var/accuracy = 0
var/dispersion = 0.0
+ // Sub-munitions. Basically, multi-projectile shotgun, rather than pellets.
+ var/use_submunitions = FALSE
+ var/only_submunitions = FALSE // Will the projectile delete itself after firing the submunitions?
+ var/list/submunitions = list() // Assoc list of the paths of any submunitions, and how many they are. [projectilepath] = [projectilecount].
+ var/submunition_spread_max = 30 // Divided by 10 to get the percentile dispersion.
+ var/submunition_spread_min = 5 // Above.
+ var/force_max_submunition_spread = FALSE // Do we just force the maximum?
+ var/spread_submunition_damage = FALSE // Do we assign damage to our sub projectiles based on our main projectile damage?
+
var/damage = 10
- var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE, HALLOSS are the only things that should be in here
+ var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE, HALLOSS, ELECTROCUTE, BIOACID are the only things that should be in here
var/SA_bonus_damage = 0 // Some bullets inflict extra damage on simple animals.
var/SA_vulnerability = null // What kind of simple animal the above bonus damage should be applied to. Set to null to apply to all SAs.
var/nodamage = 0 //Determines if the projectile will skip any damage inflictions
@@ -649,6 +658,37 @@
if(get_turf(target) == get_turf(src))
direct_target = target
+ if(use_submunitions && submunitions.len)
+ var/temp_min_spread = 0
+ if(force_max_submunition_spread)
+ temp_min_spread = submunition_spread_max
+ else
+ temp_min_spread = submunition_spread_min
+
+ var/damage_override = null
+
+ if(spread_submunition_damage)
+ damage_override = damage
+ if(nodamage)
+ damage_override = 0
+
+ var/projectile_count = 0
+
+ for(var/proj in submunitions)
+ projectile_count += submunitions[proj]
+
+ damage_override = round(damage_override / max(1, projectile_count))
+
+ for(var/path in submunitions)
+ for(var/count = 1 to submunitions[path])
+ var/obj/item/projectile/SM = new path(get_turf(loc))
+ SM.shot_from = shot_from
+ SM.silenced = silenced
+ SM.dispersion = rand(temp_min_spread, submunition_spread_max) / 10
+ if(!isnull(damage_override))
+ SM.damage = damage_override
+ SM.launch_projectile(target, target_zone, user, params, angle_override)
+
preparePixelProjectile(target, user? user : get_turf(src), params, forced_spread)
return fire(angle_override, direct_target)
@@ -668,5 +708,36 @@
if(get_turf(target) == get_turf(src))
direct_target = target
+ if(use_submunitions && submunitions.len)
+ var/temp_min_spread = 0
+ if(force_max_submunition_spread)
+ temp_min_spread = submunition_spread_max
+ else
+ temp_min_spread = submunition_spread_min
+
+ var/damage_override = null
+
+ if(spread_submunition_damage)
+ damage_override = damage
+ if(nodamage)
+ damage_override = 0
+
+ var/projectile_count = 0
+
+ for(var/proj in submunitions)
+ projectile_count += submunitions[proj]
+
+ damage_override = round(damage_override / max(1, projectile_count))
+
+ for(var/path in submunitions)
+ for(var/count = 1 to submunitions[path])
+ var/obj/item/projectile/SM = new path(get_turf(loc))
+ SM.shot_from = shot_from
+ SM.silenced = silenced
+ SM.dispersion = rand(temp_min_spread, submunition_spread_max) / 10
+ if(!isnull(damage_override))
+ SM.damage = damage_override
+ SM.launch_projectile_from_turf(target, target_zone, user, params, angle_override)
+
preparePixelProjectile(target, get_turf(src), params, forced_spread)
return fire(angle_override, direct_target)
diff --git a/code/modules/projectiles/projectile/scatter.dm b/code/modules/projectiles/projectile/scatter.dm
new file mode 100644
index 0000000000..0aa6ad5719
--- /dev/null
+++ b/code/modules/projectiles/projectile/scatter.dm
@@ -0,0 +1,62 @@
+
+/*
+ * Home of the purely submunition projectiles.
+ */
+
+/obj/item/projectile/scatter
+ name = "scatter projectile"
+ icon = 'icons/obj/projectiles.dmi'
+ icon_state = "bullet"
+ density = FALSE
+ anchored = TRUE
+ unacidable = TRUE
+ pass_flags = PASSTABLE
+ mouse_opacity = 0
+
+ use_submunitions = TRUE
+
+ damage = 8
+ spread_submunition_damage = TRUE
+ only_submunitions = TRUE
+ range = 0 // Immediately deletes itself after firing, as its only job is to fire other projectiles.
+
+ submunition_spread_max = 30
+ submunition_spread_min = 2
+
+ submunitions = list(
+ /obj/item/projectile/bullet/pellet/shotgun/flak = 3
+ )
+
+/obj/item/projectile/scatter/laser
+ damage = 40
+
+ submunition_spread_max = 40
+ submunition_spread_min = 10
+
+ submunitions = list(
+ /obj/item/projectile/beam/prismatic = 4
+ )
+
+/obj/item/projectile/beam/prismatic
+ name = "prismatic beam"
+ icon_state = "omnilaser"
+ damage = 10
+ damage_type = BURN
+ check_armour = "laser"
+ light_color = "#00C6FF"
+
+ stutter = 2
+
+ muzzle_type = /obj/effect/projectile/muzzle/laser_omni
+ tracer_type = /obj/effect/projectile/tracer/laser_omni
+ impact_type = /obj/effect/projectile/impact/laser_omni
+
+/obj/item/projectile/scatter/ion
+ damage = 20
+
+ submunition_spread_max = 40
+ submunition_spread_min = 10
+
+ submunitions = list(
+ /obj/item/projectile/bullet/shotgun/ion = 3
+ )
diff --git a/icons/obj/energygun.dmi b/icons/obj/energygun.dmi
new file mode 100644
index 0000000000..157c3c11f6
Binary files /dev/null and b/icons/obj/energygun.dmi differ
diff --git a/vorestation.dme b/vorestation.dme
index 943cc3f515..9452c0963d 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -2791,6 +2791,7 @@
#include "code\modules\projectiles\projectile\hook.dm"
#include "code\modules\projectiles\projectile\magnetic.dm"
#include "code\modules\projectiles\projectile\pellets.dm"
+#include "code\modules\projectiles\projectile\scatter.dm"
#include "code\modules\projectiles\projectile\special.dm"
#include "code\modules\projectiles\projectile\trace.dm"
#include "code\modules\projectiles\targeting\targeting_client.dm"