Updates frag grenades to use bresenham, tweaks

This commit is contained in:
mwerezak
2015-08-15 02:41:32 -04:00
parent da58494275
commit 4092b40ae5
3 changed files with 64 additions and 76 deletions
+27
View File
@@ -223,6 +223,33 @@ Turf and target are seperate in case you want to teleport some distance from a t
line+=locate(px,py,M.z)
return line
#define LOCATE_COORDS(X, Y, Z) locate(between(1, X, world.maxx), between(1, Y, world.maxy), Z)
/proc/getcircle(turf/center, var/radius) //Uses a fast Bresenham rasterization algorithm to return the turfs in a thin circle.
if(!radius) return list(center)
var/x = 0
var/y = radius
var/p = 3 - 2 * radius
. = list()
while(y >= x) // only formulate 1/8 of circle
. += LOCATE_COORDS(center.x - x, center.y - y, center.z) //upper left left
. += LOCATE_COORDS(center.x - y, center.y - x, center.z) //upper upper left
. += LOCATE_COORDS(center.x + y, center.y - x, center.z) //upper upper right
. += LOCATE_COORDS(center.x + x, center.y - y, center.z) //upper right right
. += LOCATE_COORDS(center.x - x, center.y + y, center.z) //lower left left
. += LOCATE_COORDS(center.x - y, center.y + x, center.z) //lower lower left
. += LOCATE_COORDS(center.x + y, center.y + x, center.z) //lower lower right
. += LOCATE_COORDS(center.x + x, center.y + y, center.z) //lower right right
if(p < 0)
p += 4*x++ + 6;
else
p += 4*(x++ - y--) + 10;
#undef LOCATE_COORDS
//Returns whether or not a player is a guest using their ckey as an input
/proc/IsGuestKey(key)
if (findtext(key, "Guest-", 1, 7) != 1) //was findtextEx
@@ -1,95 +1,57 @@
//Fragmentation grenade projectile
/obj/item/projectile/bullet/pellet/fragment
damage = 6
damage = 15
range_step = 2
base_spread = 0 //hit any target zone randomly
spread_step = 0
silenced = 1
base_spread = 0 //causes it to be treated as a shrapnel explosion instead of cone
spread_step = 20
//silenced = 1 //embedding messages are still produced so it's kind of weird when enabled.
move_delay = 10
muzzle_type = null
/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/num_fragments = 120 //total number of fragments produced by the grenade
var/fragment_damage = 15
var/damage_step = 1 //projectiles lose a fragment each time they travel this distance. Can be a non-integer.
var/damage_step = 2 //projectiles lose a fragment each time they travel this distance. Can be a non-integer.
var/explosion_size = 2 //size of the center explosion
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.
//The radius of the circle used to launch projectiles. Lower values mean less projectiles are used but if set too low gaps may appear in the spread pattern
var/spread_range = 7
#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)
if(explosion_size)
explosion(O, -1, round(explosion_size/2), explosion_size, round(explosion_size/2), 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)
var/list/target_turfs = getcircle(O, spread_range)
var/fragments_per_projectile = round(num_fragments/target_turfs.len)
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)
for(var/turf/T in target_turfs)
var/obj/item/projectile/bullet/pellet/fragment/P = new (O)
/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)
*/
P.damage = fragment_damage
P.pellets = fragments_per_projectile
P.range_step = damage_step
P.shot_from = src.name
P.launch(T)
var/cone = new /obj/item/weapon/caution/cone (T)
spawn(100) qdel(cone)
//Make sure to hit any mobs in the source turf
for(var/mob/living/M in O)
if(M.lying)
P.attack_mob(M, 0, 0) //lying on a frag grenade causes you to tank most of it.
else
P.attack_mob(M, 0, 100) //otherwise, allow a decent amount of fragments to pass
/*
//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)
@@ -77,7 +77,7 @@
. = ..()
bumped = 0 //can hit all mobs in a tile. pellets is decremented inside attack_mob so this should be fine.
/obj/item/projectile/bullet/pellet/attack_mob(var/mob/living/target_mob, var/distance, var/prone = 0)
/obj/item/projectile/bullet/pellet/attack_mob(var/mob/living/target_mob, var/distance, var/miss_modifier)
if (pellets < 0) return 1
var/pellet_loss = round((distance - 1)/range_step) //pellets lost due to distance
@@ -89,8 +89,6 @@
if(!base_spread)
prone_chance = max(spread_step*(distance - 2), 0)
world << "[src]: attacking [target_mob] > target_mob.lying = [target_mob.lying], original = [original], prone_chance = [prone_chance]"
var/hits = 0
for (var/i in 1 to total_pellets)
if(target_mob.lying && target_mob != original && prob(prone_chance))
@@ -114,8 +112,9 @@
//If this is a shrapnel explosion, allow mobs that are prone to get hit, too
if(. && !base_spread && isturf(loc))
for(var/mob/living/M in loc)
if(M.lying && Bump(M)) //Bump will make sure we don't hit a mob multiple times
return
if(M.lying || !M.CanPass(src, loc)) //Bump if lying or if we would normally Bump.
if(Bump(M)) //Bump will make sure we don't hit a mob multiple times
return
/* short-casing projectiles, like the kind used in pistols or SMGs */