Merge pull request #12173 from kevinz000/projectiles_2

Refactors projectile speed to pixels per second
This commit is contained in:
Lin
2020-05-24 21:21:41 +00:00
committed by GitHub
25 changed files with 178 additions and 99 deletions

View File

@@ -209,3 +209,5 @@
/// Make sure something is a boolean TRUE/FALSE 1/0 value, since things like bitfield & bitflag doesn't always give 1s and 0s.
#define FORCE_BOOLEAN(x) ((x)? TRUE : FALSE)
#define TILES_TO_PIXELS(tiles) (tiles * PIXELS)

View File

@@ -9,6 +9,9 @@
#define TEXT_EAST "[EAST]"
#define TEXT_WEST "[WEST]"
/// world.icon_size
#define PIXELS 32
//These get to go at the top, because they're special
//You can use these defines to get the typepath of the currently running proc/verb (yes procs + verbs are objects)
/* eg:

View File

@@ -26,4 +26,4 @@
#define PROFILE_ITEM_LEN 2
#define PROFILE_ITEM_TIME 1
#define PROFILE_ITEM_COUNT 2
#define PROFILE_ITEM_COUNT 2

View File

@@ -117,6 +117,7 @@
#define FIRE_PRIORITY_NPC 80
#define FIRE_PRIORITY_MOBS 100
#define FIRE_PRIORITY_TGUI 110
#define FIRE_PRIORITY_PROJECTILES 200
#define FIRE_PRIORITY_TICKER 200
#define FIRE_PRIORITY_ATMOS_ADJACENCY 300
#define FIRE_PRIORITY_CHAT 400

39
code/__HELPERS/angles.dm Normal file
View File

@@ -0,0 +1,39 @@
/proc/get_projectile_angle(atom/source, atom/target)
var/sx = source.x * world.icon_size
var/sy = source.y * world.icon_size
var/tx = target.x * world.icon_size
var/ty = target.y * world.icon_size
var/atom/movable/AM
if(ismovable(source))
AM = source
sx += AM.step_x
sy += AM.step_y
if(ismovable(target))
AM = target
tx += AM.step_x
ty += AM.step_y
return SIMPLIFY_DEGREES(arctan(ty - sy, tx - sx))
/proc/Get_Angle(atom/movable/start,atom/movable/end)//For beams.
if(!start || !end)
return 0
var/dy
var/dx
dy=(32*end.y+end.pixel_y)-(32*start.y+start.pixel_y)
dx=(32*end.x+end.pixel_x)-(32*start.x+start.pixel_x)
if(!dy)
return (dx>=0)?90:270
.=arctan(dx/dy)
if(dy<0)
.+=180
else if(dx<0)
.+=360
/proc/Get_Pixel_Angle(var/y, var/x)//for getting the angle when animating something's pixel_x and pixel_y
if(!y)
return (x>=0)?90:270
.=arctan(x/y)
if(y<0)
.+=180
else if(x<0)
.+=360

View File

@@ -15,30 +15,6 @@
var/textb = copytext(HTMLstring, 6, 8)
return rgb(255 - hex2num(textr), 255 - hex2num(textg), 255 - hex2num(textb))
/proc/Get_Angle(atom/movable/start,atom/movable/end)//For beams.
if(!start || !end)
return 0
var/dy
var/dx
dy=(32*end.y+end.pixel_y)-(32*start.y+start.pixel_y)
dx=(32*end.x+end.pixel_x)-(32*start.x+start.pixel_x)
if(!dy)
return (dx>=0)?90:270
.=arctan(dx/dy)
if(dy<0)
.+=180
else if(dx<0)
.+=360
/proc/Get_Pixel_Angle(var/y, var/x)//for getting the angle when animating something's pixel_x and pixel_y
if(!y)
return (x>=0)?90:270
.=arctan(x/y)
if(y<0)
.+=180
else if(x<0)
.+=360
//Returns location. Returns null if no location was found.
/proc/get_teleport_loc(turf/location,mob/target,distance = 1, density = FALSE, errorx = 0, errory = 0, eoffsetx = 0, eoffsety = 0)
/*

View File

@@ -1,21 +1,22 @@
PROCESSING_SUBSYSTEM_DEF(projectiles)
name = "Projectiles"
priority = FIRE_PRIORITY_PROJECTILES
wait = 1
stat_tag = "PP"
flags = SS_NO_INIT|SS_TICKER
var/global_pixel_speed = 2
var/global_iterations_per_move = 16
var/global_pixel_increment_amount = 4
var/global_projectile_speed_multiplier = 1
/datum/controller/subsystem/processing/projectiles/proc/set_pixel_speed(new_speed)
global_pixel_speed = new_speed
global_pixel_increment_amount = new_speed
for(var/i in processing)
var/obj/item/projectile/P = i
if(istype(P)) //there's non projectiles on this too.
P.set_pixel_speed(new_speed)
P.set_pixel_increment_amount(new_speed)
/datum/controller/subsystem/processing/projectiles/vv_edit_var(var_name, var_value)
switch(var_name)
if(NAMEOF(src, global_pixel_speed))
if(NAMEOF(src, global_pixel_increment_amount))
set_pixel_speed(var_value)
return TRUE
else

View File

@@ -189,6 +189,12 @@
x += mpx * (multiplier)
y += mpy * (multiplier)
/datum/point/vector/proc/pixel_increment(pixels = 32, update_iteration = TRUE, realistic_iteration = FALSE)
if(update_iteration)
iteration += realistic_iteration? round(pixels / speed) : 1
x += sin(angle) * pixels
y += cos(angle) * pixels
/datum/point/vector/proc/return_vector_after_increments(amount = 7, multiplier = 1, force_simulate = FALSE)
var/datum/point/vector/v = copy_to()
if(force_simulate)

View File

@@ -419,7 +419,7 @@
A.BB.damage = hitdamage
if(hitdamage)
A.BB.nodamage = FALSE
A.BB.speed = 0.5
A.BB.pixels_per_second = TILES_TO_PIXELS(20)
playsound(src.loc, 'sound/machines/click.ogg', 50, 1)
A.fire_casing(target, user, params, 0, 0, null, 0, src)
user.visible_message("<span class='warning'>[user] blasts a flying lollipop at [target]!</span>")
@@ -434,7 +434,7 @@
A.BB.damage = hitdamage
if(hitdamage)
A.BB.nodamage = FALSE
A.BB.speed = 0.5
A.BB.pixels_per_second = TILES_TO_PIXELS(20)
A.BB.color = rgb(rand(0, 255), rand(0, 255), rand(0, 255))
playsound(src.loc, 'sound/weapons/bulletflyby3.ogg', 50, 1)
A.fire_casing(target, user, params, 0, 0, null, 0, src)
@@ -671,13 +671,13 @@
if(track_projectile)
tracked[P] = P.damage
P.damage *= projectile_damage_coefficient
P.speed *= projectile_speed_coefficient
P.pixels_per_second *= projectile_speed_coefficient
P.add_overlay(projectile_effect)
/obj/item/borg/projectile_dampen/proc/restore_projectile(obj/item/projectile/P)
tracked -= P
P.damage *= (1/projectile_damage_coefficient)
P.speed *= (1/projectile_speed_coefficient)
P.pixels_per_second *= (1/projectile_speed_coefficient)
P.cut_overlay(projectile_effect)
/**********************************************************************

View File

@@ -417,7 +417,7 @@
marker.icon_state = "chronobolt"
marker.damage = bonus_value
marker.nodamage = FALSE
marker.speed = 2
marker.pixels_per_second = TILES_TO_PIXELS(5)
deadly_shot = FALSE
/obj/item/crusher_trophy/blaster_tubes/on_mark_detonation(mob/living/target, mob/living/user)

View File

@@ -75,7 +75,7 @@ Difficulty: Medium
/obj/item/projectile/kinetic/miner
damage = 40
speed = 0.9
pixels_per_second = TILES_TO_PIXELS(11.111)
icon_state = "ka_tracer"
range = MINER_DASH_RANGE

View File

@@ -212,7 +212,7 @@ Difficulty: Very Hard
icon_state= "chronobolt"
damage = 25
armour_penetration = 100
speed = 2
pixels_per_second = TILES_TO_PIXELS(5)
eyeblur = 0
damage_type = BRUTE
pass_flags = PASSTABLE

View File

@@ -71,7 +71,10 @@ Difficulty: Extremely Hard
/mob/living/simple_animal/hostile/megafauna/demonic_frost_miner/OpenFire()
check_enraged()
projectile_speed_multiplier = 1 - enraged * 0.25
if(enraged)
projectile_speed_multiplier = 1.33
else
projectile_speed_multiplier = 1
SetRecoveryTime(100, 100)
if(client)
@@ -109,7 +112,7 @@ Difficulty: Extremely Hard
icon_state = "ice_1"
damage = 20
armour_penetration = 100
speed = 10
pixels_per_second = TILES_TO_PIXELS(1)
homing_turn_speed = 30
damage_type = BURN
@@ -123,7 +126,7 @@ Difficulty: Extremely Hard
icon_state = "nuclear_particle"
damage = 5
armour_penetration = 100
speed = 4
pixels_per_second = TILES_TO_PIXELS(2.5)
damage_type = BRUTE
/obj/item/projectile/ice_blast
@@ -131,7 +134,7 @@ Difficulty: Extremely Hard
icon_state = "ice_2"
damage = 15
armour_penetration = 100
speed = 4
pixels_per_second = TILES_TO_PIXELS(2.5)
damage_type = BRUTE
/obj/item/projectile/ice_blast/on_hit(atom/target, blocked = FALSE)
@@ -185,7 +188,7 @@ Difficulty: Extremely Hard
if(!startloc || !endloc)
break
var/obj/item/projectile/ice_blast/P = new(startloc)
P.speed *= projectile_speed_multiplier
P.pixels_per_second *= projectile_speed_multiplier
P.preparePixelProjectile(endloc, startloc, null, angle + rand(-10, 10))
P.firer = firer
if(original)
@@ -201,7 +204,7 @@ Difficulty: Extremely Hard
if(!endloc)
break
var/obj/item/projectile/P = new /obj/item/projectile/snowball(startloc)
P.speed *= projectile_speed_multiplier
P.pixels_per_second *= projectile_speed_multiplier
P.preparePixelProjectile(endloc, startloc, null, rand(-spread, spread))
P.firer = src
if(target)
@@ -220,7 +223,7 @@ Difficulty: Extremely Hard
if(!endloc)
break
var/obj/item/projectile/P = new /obj/item/projectile/ice_blast(startloc)
P.speed *= projectile_speed_multiplier
P.pixels_per_second *= projectile_speed_multiplier
P.preparePixelProjectile(endloc, startloc, null, spread)
P.firer = src
if(target)

View File

@@ -145,6 +145,7 @@
/mob/living/simple_animal/hostile/megafauna/proc/SetRecoveryTime(buffer_time)
recovery_time = world.time + buffer_time
ranged_cooldown = max(ranged_cooldown, world.time + buffer_time) // CITADEL BANDAID FIX FOR MEGAFAUNA NOT RESPECTING RECOVERY TIME.
/mob/living/simple_animal/hostile/megafauna/proc/grant_achievement(medaltype, scoretype, crusher_kill)
if(!medal_type || (flags_1 & ADMIN_SPAWNED_1)) //Don't award medals if the medal type isn't set

View File

@@ -217,7 +217,7 @@
icon_state= "chronobolt"
damage = 15
armour_penetration = 60
speed = 2
pixels_per_second = TILES_TO_PIXELS(5)
eyeblur = 0
damage_type = BRUTE
pass_flags = PASSTABLE

View File

@@ -1,6 +1,10 @@
#define MOVES_HITSCAN -1 //Not actually hitscan but close as we get without actual hitscan.
#define MUZZLE_EFFECT_PIXEL_INCREMENT 17 //How many pixels to move the muzzle flash up so your character doesn't look like they're shitting out lasers.
/// Minimum projectile pixels to move before it animate()S, below this it's a direct set.
#define MINIMUM_PIXELS_TO_ANIMATE 4
/// Pixels to instantly travel on firing.
#define PROJECTILE_FIRING_INSTANT_TRAVEL_AMOUNT 16
/obj/item/projectile
name = "projectile"
@@ -12,7 +16,9 @@
pass_flags = PASSTABLE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
movement_type = FLYING
animate_movement = NO_STEPS
hitsound = 'sound/weapons/pierce.ogg'
appearance_flags = PIXEL_SCALE
var/hitsound_wall = ""
resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
@@ -32,14 +38,19 @@
//Fired processing vars
var/fired = FALSE //Have we been fired yet
var/paused = FALSE //for suspending the projectile midair
var/last_projectile_move = 0
var/time_offset = 0
var/datum/point/vector/trajectory
var/trajectory_ignore_forcemove = FALSE //instructs forceMove to NOT reset our trajectory to the new location!
/// "leftover" pixels for Range() calculation as pixel_move() was moved to simulated semi-pixel movement and Range() is in tiles.
var/pixels_range_leftover = 0
/// "leftover" tick pixels and stuff yeah, so we don't round off things and introducing tracing inaccuracy.
var/pixels_tick_leftover = 0
/// Pixels moved per second.
var/pixels_per_second = TILES_TO_PIXELS(12.5)
/// The number of pixels we increment by. THIS IS NOT SPEED, DO NOT TOUCH THIS UNLESS YOU KNOW WHAT YOU ARE DOING. In general, lower values means more linetrace accuracy up to a point at cost of performance.
var/pixel_increment_amount
var/speed = 0.8 //Amount of deciseconds it takes for projectile to travel
/// "leftover" ticks and stuff yeah. hey when are we rewriting projectiles for the eighth time to do something smarter like incrementing x pixels until it meets a goal instead of for(var/i in 1 to required_moves)?
var/tick_moves_leftover = 0
var/Angle = 0
var/original_angle = 0 //Angle at firing
var/nondirectional_sprite = FALSE //Set TRUE to prevent projectiles from having their sprites rotated based on firing angle
@@ -75,12 +86,16 @@
//Homing
var/homing = FALSE
var/atom/homing_target
var/homing_turn_speed = 10 //Angle per tick.
/// How fast the projectile turns towards its homing targets, in angle per second.
var/homing_turn_speed = 100
var/homing_inaccuracy_min = 0 //in pixels for these. offsets are set once when setting target.
var/homing_inaccuracy_max = 0
var/homing_offset_x = 0
var/homing_offset_y = 0
/// How many deciseconds are each hitscan movement considered. Used for homing and other things that use seconds for timing rather than ticks.
var/hitscan_movement_decisecond_equivalency = 0.1
var/ignore_source_check = FALSE
var/damage = 10
@@ -88,7 +103,8 @@
var/nodamage = 0 //Determines if the projectile will skip any damage inflictions
var/flag = "bullet" //Defines what armor to use when it hits things. Must be set to bullet, laser, energy,or bomb
var/projectile_type = /obj/item/projectile
var/range = 50 //This will de-increment every step. When 0, it will deletze the projectile.
/// Range of the projectile, de-incrementing every step. The projectile deletes itself at 0. This is in tiles.
var/range = 50
var/decayedRange //stores original range
var/reflect_range_decrease = 5 //amount of original range that falls off when reflecting, so it doesn't go forever
var/is_reflectable = FALSE // Can it be reflected or not?
@@ -120,6 +136,10 @@
permutated = list()
decayedRange = range
/**
* Artificially modified to be called at around every world.icon_size pixels of movement.
* WARNING: Range() can only be called once per pixel_increment_amount pixels.
*/
/obj/item/projectile/proc/Range()
range--
if(range <= 0 && loc)
@@ -334,14 +354,15 @@
return TRUE
return FALSE
/// one move is a tile.
/obj/item/projectile/proc/return_predicted_turf_after_moves(moves, forced_angle) //I say predicted because there's no telling that the projectile won't change direction/location in flight.
if(!trajectory && isnull(forced_angle) && isnull(Angle))
return FALSE
var/datum/point/vector/current = trajectory
if(!current)
var/turf/T = get_turf(src)
current = new(T.x, T.y, T.z, pixel_x, pixel_y, isnull(forced_angle)? Angle : forced_angle, SSprojectiles.global_pixel_speed)
var/datum/point/vector/v = current.return_vector_after_increments(moves * SSprojectiles.global_iterations_per_move)
current = new(T.x, T.y, T.z, pixel_x, pixel_y, isnull(forced_angle)? Angle : forced_angle, pixel_increment_amount || SSprojectiles.global_pixel_increment_amount)
var/datum/point/vector/v = current.return_vector_after_increments(TILES_TO_PIXELS(moves) / (pixel_increment_amount || SSprojectiles.global_pixel_increment_amount))
return v.return_turf()
/obj/item/projectile/proc/return_pathing_turfs_in_moves(moves, forced_angle)
@@ -358,16 +379,14 @@
return PROCESS_KILL
if(paused || !isturf(loc))
return
var/ds = (SSprojectiles.flags & SS_TICKER)? (wait * world.tick_lag) : wait
var/required_moves = ds / speed
var/leftover = MODULUS(required_moves, 1)
tick_moves_leftover += leftover
required_moves = round(required_moves)
if(tick_moves_leftover > 1)
required_moves += round(tick_moves_leftover)
tick_moves_leftover = MODULUS(tick_moves_leftover, 1)
for(var/i in 1 to required_moves)
pixel_move(1, FALSE)
var/required_pixels = (pixels_per_second * ds * 0.1) + pixels_tick_leftover
if(required_pixels >= pixel_increment_amount)
pixels_tick_leftover = MODULUS(required_pixels, pixel_increment_amount)
pixel_move(FLOOR(required_pixels / pixel_increment_amount, 1), FALSE, ds, SSprojectiles.global_projectile_speed_multiplier)
else
pixels_tick_leftover = required_pixels
/obj/item/projectile/proc/fire(angle, atom/direct_target)
if(fired_from)
@@ -390,7 +409,7 @@
qdel(src)
return
var/turf/target = locate(clamp(starting + xo, 1, world.maxx), clamp(starting + yo, 1, world.maxy), starting.z)
setAngle(Get_Angle(src, target))
setAngle(get_projectile_angle(src, target))
original_angle = Angle
if(!nondirectional_sprite)
var/matrix/M = new
@@ -399,14 +418,16 @@
trajectory_ignore_forcemove = TRUE
forceMove(starting)
trajectory_ignore_forcemove = FALSE
trajectory = new(starting.x, starting.y, starting.z, pixel_x, pixel_y, Angle, SSprojectiles.global_pixel_speed)
last_projectile_move = world.time
if(isnull(pixel_increment_amount))
pixel_increment_amount = SSprojectiles.global_pixel_increment_amount
trajectory = new(starting.x, starting.y, starting.z, pixel_x, pixel_y, Angle, pixel_increment_amount)
fired = TRUE
if(hitscan)
process_hitscan()
return
if(!(datum_flags & DF_ISPROCESSING))
START_PROCESSING(SSprojectiles, src)
pixel_move(1, FALSE) //move it now!
pixel_move(round(PROJECTILE_FIRING_INSTANT_TRAVEL_AMOUNT / pixel_increment_amount), FALSE, allow_animation = FALSE) //move it now!
/obj/item/projectile/proc/setAngle(new_angle, hitscan_store_segment = TRUE) //wrapper for overrides.
Angle = new_angle
@@ -451,7 +472,8 @@
else
return ..()
/obj/item/projectile/proc/set_pixel_speed(new_speed)
/obj/item/projectile/proc/set_pixel_increment_amount(new_speed)
pixel_increment_amount = new_speed
if(trajectory)
trajectory.set_speed(new_speed)
return TRUE
@@ -464,6 +486,7 @@
beam_segments[beam_index] = null //record start.
/obj/item/projectile/proc/process_hitscan()
var/ttm = round(world.icon_size / pixel_increment_amount, 1)
var/safety = range * 10
record_hitscan_start(RETURN_POINT_VECTOR_INCREMENT(src, Angle, MUZZLE_EFFECT_PIXEL_INCREMENT, 1))
while(loc && !QDELETED(src))
@@ -476,20 +499,33 @@
if(!QDELETED(src))
qdel(src)
return //Kill!
pixel_move(1, TRUE)
pixel_move(ttm, TRUE, hitscan_movement_decisecond_equivalency)
/obj/item/projectile/proc/pixel_move(trajectory_multiplier, hitscanning = FALSE)
/**
* The proc to make the projectile go, using a simulated pixel movement line trace.
* Note: deciseconds_equivalent is currently only used for homing, times is the number of times to move pixel_increment_amount.
* Trajectory multiplier directly modifies the factor of pixel_increment_amount to go per time.
* It's complicated, so probably just don'ot mess with this unless you know what you're doing.
*/
/obj/item/projectile/proc/pixel_move(times, hitscanning = FALSE, deciseconds_equivalent = world.tick_lag, trajectory_multiplier = 1, allow_animation = TRUE)
if(!loc || !trajectory)
return
last_projectile_move = world.time
if(!nondirectional_sprite && !hitscanning)
var/matrix/M = new
M.Turn(Angle)
transform = M
if(homing)
process_homing()
var/forcemoved = FALSE
for(var/i in 1 to SSprojectiles.global_iterations_per_move)
var/turf/oldloc = loc
var/old_px = pixel_x
var/old_py = pixel_y
for(var/i in 1 to times)
// HOMING START - Too expensive to proccall at this point.
if(homing_target)
// No datum/points, too expensive.
var/angle = closer_angle_difference(Angle, get_projectile_angle(src, homing_target))
var/max_turn = homing_turn_speed * deciseconds_equivalent * 0.1
setAngle(Angle + clamp(angle, -max_turn, max_turn))
// HOMING END
trajectory.increment(trajectory_multiplier)
var/turf/T = trajectory.return_turf()
if(!istype(T))
@@ -509,23 +545,29 @@
pixel_x = trajectory.return_px()
pixel_y = trajectory.return_py()
else if(T != loc)
step_towards(src, T)
var/safety = CEILING(pixel_increment_amount / world.icon_size, 1) * 2 + 1
while(T != loc)
if(!--safety)
CRASH("Projectile took more than pixel incrememnt speed times 2 to get to its location, this is probably something seriously scuffed going on.")
step_towards(src, T)
if(QDELETED(src))
return
pixels_range_leftover += pixel_increment_amount
if(pixels_range_leftover > world.icon_size)
Range()
if(QDELETED(src))
return
pixels_range_leftover -= world.icon_size
if(!hitscanning && !forcemoved)
pixel_x = trajectory.return_px() - trajectory.mpx * trajectory_multiplier * SSprojectiles.global_iterations_per_move
pixel_y = trajectory.return_py() - trajectory.mpy * trajectory_multiplier * SSprojectiles.global_iterations_per_move
animate(src, pixel_x = trajectory.return_px(), pixel_y = trajectory.return_py(), time = 1, flags = ANIMATION_END_NOW)
Range()
/obj/item/projectile/proc/process_homing() //may need speeding up in the future performance wise.
if(!homing_target)
return FALSE
var/datum/point/PT = RETURN_PRECISE_POINT(homing_target)
PT.x += clamp(homing_offset_x, 1, world.maxx)
PT.y += clamp(homing_offset_y, 1, world.maxy)
var/angle = closer_angle_difference(Angle, angle_between_points(RETURN_PRECISE_POINT(src), PT))
setAngle(Angle + clamp(angle, -homing_turn_speed, homing_turn_speed))
var/traj_px = round(trajectory.return_px(), 1)
var/traj_py = round(trajectory.return_py(), 1)
if(allow_animation && (pixel_increment_amount * times > MINIMUM_PIXELS_TO_ANIMATE))
pixel_x = ((oldloc.x - x) * world.icon_size) + old_px
pixel_y = ((oldloc.y - y) * world.icon_size) + old_py
animate(src, pixel_x = traj_px, pixel_y = traj_py, time = 1, flags = ANIMATION_END_NOW)
else
pixel_x = traj_px
pixel_y = traj_py
/obj/item/projectile/proc/set_homing_target(atom/A)
if(!A || (!isturf(A) && !isturf(A.loc)))
@@ -575,7 +617,7 @@
if(targloc || !params)
yo = targloc.y - curloc.y
xo = targloc.x - curloc.x
setAngle(Get_Angle(src, targloc) + spread)
setAngle(get_projectile_angle(src, targloc) + spread)
if(isliving(source) && params)
var/list/calculated = calculate_projectile_angle_and_pixel_offsets(source, params)
@@ -586,7 +628,7 @@
else if(targloc)
yo = targloc.y - curloc.y
xo = targloc.x - curloc.x
setAngle(Get_Angle(src, targloc) + spread)
setAngle(get_projectile_angle(src, targloc) + spread)
else
stack_trace("WARNING: Projectile [type] fired without either mouse parameters, or a target atom to aim at!")
qdel(src)
@@ -698,3 +740,7 @@
/proc/is_energy_reflectable_projectile(atom/A)
var/obj/item/projectile/P = A
return istype(P) && P.is_reflectable
#undef MOVES_HITSCAN
#undef MINIMUM_PIXELS_TO_ANIMATE
#undef MUZZLE_EFFECT_PIXEL_INCREMENT

View File

@@ -74,7 +74,7 @@
flag = "energy"
hitsound = 'sound/weapons/tap.ogg'
eyeblur = 0
speed = 0.6
pixels_per_second = TILES_TO_PIXELS(16.667)
impact_effect_type = /obj/effect/temp_visual/impact_effect/blue_laser
light_color = LIGHT_COLOR_BLUE
tracer_type = /obj/effect/projectile/tracer/disabler

View File

@@ -3,7 +3,7 @@
damage = 20
armour_penetration = 20
light_range = 3
speed = 0.6
pixels_per_second = TILES_TO_PIXELS(16.667)
range = 35
light_color = LIGHT_COLOR_RED
@@ -39,7 +39,7 @@
armour_penetration = 20
movement_type = FLYING | UNSTOPPABLE
range = 20
speed = 0.8
pixels_per_second = TILES_TO_PIXELS(12.5)
light_range = 4
light_color = LIGHT_COLOR_RED

View File

@@ -2,7 +2,7 @@
/obj/item/projectile/bullet/p50
name =".50 bullet"
speed = 0.4
pixels_per_second = TILES_TO_PIXELS(25)
damage = 70
knockdown = 100
dismemberment = 50
@@ -43,5 +43,5 @@
/obj/item/projectile/bullet/p50/penetrator/shuttle //Nukeop Shuttle Variety
icon_state = "gaussstrong"
damage = 25
speed = 0.3
pixels_per_second = TILES_TO_PIXELS(33.33)
range = 16

View File

@@ -5,7 +5,7 @@
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE
flag = "rad"
irradiate = 5000
speed = 0.4
pixels_per_second = TILES_TO_PIXELS(25)
hitsound = 'sound/weapons/emitter2.ogg'
impact_type = /obj/effect/projectile/impact/xray
var/static/list/particle_colors = list(

View File

@@ -10,7 +10,7 @@
jitter = 20
hitsound = 'sound/weapons/taserhit.ogg'
range = 14
speed = 0.6
pixels_per_second = TILES_TO_PIXELS(16.667)
tracer_type = /obj/effect/projectile/tracer/stun
muzzle_type = /obj/effect/projectile/muzzle/stun
impact_type = /obj/effect/projectile/impact/stun

View File

@@ -434,7 +434,7 @@
damage = 15
damage_type = BURN
nodamage = 0
speed = 0.3
pixels_per_second = TILES_TO_PIXELS(33.33)
flag = "magic"
var/zap_power = 20000

View File

@@ -10,7 +10,7 @@
damage_type = BURN
damage = 10
knockdown = 20
speed = 2
pixels_per_second = TILES_TO_PIXELS(5)
range = 16
movement_type = FLYING | UNSTOPPABLE
var/datum/beam/arm

View File

@@ -178,7 +178,7 @@
name = "positron blast"
damage = 80
range = 14
speed = 0.6
pixels_per_second = TILES_TO_PIXELS(16.667)
icon_state = "disablerslug"
/obj/item/projectile/beam/pump

View File

@@ -137,6 +137,7 @@
#include "code\__HELPERS\_lists.dm"
#include "code\__HELPERS\_logging.dm"
#include "code\__HELPERS\_string_lists.dm"
#include "code\__HELPERS\angles.dm"
#include "code\__HELPERS\areas.dm"
#include "code\__HELPERS\AStar.dm"
#include "code\__HELPERS\cmp.dm"