Adds fragmentation grenades

Adds a fragmentation grenade item that launches a shower of projectiles
in all directions when detonated.
This commit is contained in:
mwerezak
2015-08-11 02:42:25 -04:00
parent 8cbd14c1a5
commit cb2a094553
5 changed files with 119 additions and 7 deletions

View File

@@ -699,6 +699,7 @@
#include "code\game\objects\items\weapons\grenades\chem_grenade.dm" #include "code\game\objects\items\weapons\grenades\chem_grenade.dm"
#include "code\game\objects\items\weapons\grenades\emgrenade.dm" #include "code\game\objects\items\weapons\grenades\emgrenade.dm"
#include "code\game\objects\items\weapons\grenades\flashbang.dm" #include "code\game\objects\items\weapons\grenades\flashbang.dm"
#include "code\game\objects\items\weapons\grenades\fragmentation.dm"
#include "code\game\objects\items\weapons\grenades\grenade.dm" #include "code\game\objects\items\weapons\grenades\grenade.dm"
#include "code\game\objects\items\weapons\grenades\smokebomb.dm" #include "code\game\objects\items\weapons\grenades\smokebomb.dm"
#include "code\game\objects\items\weapons\grenades\spawnergrenade.dm" #include "code\game\objects\items\weapons\grenades\spawnergrenade.dm"

View File

@@ -48,7 +48,7 @@
/obj/item/mecha_parts/mecha_equipment/weapon/proc/Fire(atom/A, atom/target, turf/aimloc) /obj/item/mecha_parts/mecha_equipment/weapon/proc/Fire(atom/A, atom/target, turf/aimloc)
var/obj/item/projectile/P = A var/obj/item/projectile/P = A
P.shot_from = src P.shot_from = src.name
P.original = target P.original = target
P.starting = P.loc P.starting = P.loc
P.current = P.loc P.current = P.loc

View File

@@ -0,0 +1,109 @@
//Fragmentation grenade projectile
/obj/item/projectile/bullet/pellet/fragment
damage = 6
range_step = 2
base_spread = 0 //hit any target zone randomly
spread_step = 0
//step_delay = 10
silenced = 1
//hitscan = 1
muzzle_type = null
/obj/item/projectile/bullet/pellet/fragment/Move()
. = ..()
//Allow mobs that are prone close to the starting turf a chance to get hit, too
if(. && isturf(loc))
var/distance = get_dist(loc, starting)
var/chance = max(100 - (distance - 1)*20, 0)
if(prob(chance))
for(var/mob/living/M in loc)
if(Bump(M)) //Bump will make sure we don't hit a mob multiple times
return
/obj/item/weapon/grenade/frag
name = "fragmentation grenade"
desc = "A military fragmentation grenade, designed to explode in a deadly shower of fragments."
var/num_fragments = 7 //fragments per projectile
var/fragment_damage = 15
var/damage_step = 1 //projectiles lose a fragment each time they travel this distance. Can be a non-integer.
var/silenced = 0
//Higher values means projectile spread is more even but more projectiles are created.
//The actual number of projectile objects is spread_range*8
var/spread_range = 4 //32 projectiles. With spread_range=4 and num_fragments=7, a frag grenade produces 224 fragments.
#define LOCATE_COORDS(X, Y, Z) locate(between(1, X, world.maxx), between(1, Y, world.maxy), Z)
/obj/item/weapon/grenade/frag/prime()
..()
var/turf/O = get_turf(src)
if(!O) return
explosion(O, -1, 1, 2, 1, 0)
for(var/i in -spread_range to spread_range)
var/turf/T1 = LOCATE_COORDS(O.x+i, O.y+spread_range, O.z)
launch_projectile(O, T1)
var/turf/T2 = LOCATE_COORDS(O.x+i, O.y-spread_range, O.z)
launch_projectile(O, T2)
for(var/j in 1-spread_range to spread_range-1)
var/turf/T1 = LOCATE_COORDS(O.x+spread_range, O.y+j, O.z)
launch_projectile(O, T1)
var/turf/T2 = LOCATE_COORDS(O.x-spread_range, O.y+j, O.z)
launch_projectile(O, T2)
qdel(src)
/obj/item/weapon/grenade/frag/proc/launch_projectile(var/turf/source, var/turf/target)
var/obj/item/projectile/bullet/pellet/fragment/P = new(src)
P.damage = fragment_damage
P.pellets = num_fragments
P.range_step = damage_step
P.silenced = silenced
P.shot_from = src.name
var/location = loc //store our current loc since qdel will move the grenade to nullspace
spawn(0)
P.launch(target)
if(!isturf(location))
P.Bump(location)
for(var/atom/movable/AM in source)
P.Bump(AM)
/*
//the vector system doesn't play well with very large angle offsets, so generate projectiles along each of the 8 directions
var/subarc_width = 45/(num_projectiles*2)
var/fragments_per_projectile = round(num_fragments / (num_projectiles*8))
for(var/launch_dir in alldirs)
var/turf/target = get_edge_target_turf(T, launch_dir)
for(var/i in 1 to num_projectiles)
//keep the trajectory centered in the 45 deg arc
var/launch_angle = (i-0.5)*subarc_width - 22.5
var/obj/item/projectile/bullet/pellet/fragment/P = new(src)
if(dispersion)
P.dispersion = (subarc_width)/9 //randomly disperse within the projectile arc, so that there aren't any predictable blind spots
P.damage = fragment_damage
P.pellets = fragments_per_projectile
P.range_step = damage_step
P.silenced = silenced
P.shot_from = src.name
spawn(0)
P.Move(T) //so that we hit people in the starting turf
P.launch(target, ran_zone(), angle_offset = launch_angle)
*/
qdel(src)

View File

@@ -25,7 +25,7 @@
var/yo = null var/yo = null
var/xo = null var/xo = null
var/current = null var/current = null
var/obj/shot_from = null // the object which shot us var/shot_from = "" // name of the object which shot us
var/atom/original = null // the target clicked (not necessarily where the projectile is headed). Should probably be renamed to 'target' or something. var/atom/original = null // the target clicked (not necessarily where the projectile is headed). Should probably be renamed to 'target' or something.
var/turf/starting = null // the projectile's starting turf var/turf/starting = null // the projectile's starting turf
var/list/permutated = list() // we've passed through these atoms, don't try to hit them again var/list/permutated = list() // we've passed through these atoms, don't try to hit them again
@@ -111,7 +111,7 @@
p_y = between(0, p_y + rand(-radius, radius), world.icon_size) p_y = between(0, p_y + rand(-radius, radius), world.icon_size)
//called to launch a projectile //called to launch a projectile
/obj/item/projectile/proc/launch(atom/target, var/target_zone, var/x_offset=0, var/y_offset=0) /obj/item/projectile/proc/launch(atom/target, var/target_zone, var/x_offset=0, var/y_offset=0, var/angle_offset=0)
var/turf/curloc = get_turf(src) var/turf/curloc = get_turf(src)
var/turf/targloc = get_turf(target) var/turf/targloc = get_turf(target)
if (!istype(targloc) || !istype(curloc)) if (!istype(targloc) || !istype(curloc))
@@ -127,7 +127,7 @@
def_zone = target_zone def_zone = target_zone
spawn() spawn()
setup_trajectory(curloc, targloc, x_offset, y_offset) //plot the initial trajectory setup_trajectory(curloc, targloc, x_offset, y_offset, angle_offset) //plot the initial trajectory
process() process()
return 0 return 0
@@ -143,7 +143,7 @@
loc = get_turf(user) //move the projectile out into the world loc = get_turf(user) //move the projectile out into the world
firer = user firer = user
shot_from = launcher shot_from = launcher.name
silenced = launcher.silenced silenced = launcher.silenced
return launch(target, target_zone, x_offset, y_offset) return launch(target, target_zone, x_offset, y_offset)
@@ -173,7 +173,8 @@
result = target_mob.bullet_act(src, def_zone) result = target_mob.bullet_act(src, def_zone)
if(result == PROJECTILE_FORCE_MISS) if(result == PROJECTILE_FORCE_MISS)
visible_message("<span class='notice'>\The [src] misses [target_mob] narrowly!</span>") if(!silenced)
visible_message("<span class='notice'>\The [src] misses [target_mob] narrowly!</span>")
return 0 return 0
//hit messages //hit messages

View File

@@ -69,7 +69,7 @@
damage = 20 damage = 20
//icon_state = "bullet" //TODO: would be nice to have it's own icon state //icon_state = "bullet" //TODO: would be nice to have it's own icon state
var/pellets = 4 //number of pellets var/pellets = 4 //number of pellets
var/range_step = 2 //effective pellet count decreases every few tiles var/range_step = 2 //projectile will lose a fragment each time it travels this distance. Can be a non-integer.
var/base_spread = 90 //lower means the pellets spread more across body parts var/base_spread = 90 //lower means the pellets spread more across body parts
var/spread_step = 10 //higher means the pellets spread more across body parts with distance var/spread_step = 10 //higher means the pellets spread more across body parts with distance
@@ -92,6 +92,7 @@
if (..()) hits++ if (..()) hits++
def_zone = old_zone //restore the original zone the projectile was aimed at def_zone = old_zone //restore the original zone the projectile was aimed at
//world << "[src]: hitting [target_mob], [hits] of [pellets] hits."
pellets -= hits //each hit reduces the number of pellets left pellets -= hits //each hit reduces the number of pellets left
if (hits >= total_pellets || pellets <= 0) if (hits >= total_pellets || pellets <= 0)
return 1 return 1