mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-23 20:17:15 +01:00
Updates frag grenades to use bresenham, tweaks
This commit is contained in:
@@ -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 */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user