mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-01-17 04:42:06 +00:00
Refactored the projectile code, mostly in line with TG's now. Refactored various procs that are used or depends on it. Projectiles can now ricochet if enabled to. Damage falloffs with distance. Homing projectiles can now have accuracy falloff with distance. Projectiles have a maximum range. Muzzle flash is configurable per projectile. Impact effect of the projectile is configurable per projectile. Accuracy decreases with distance. Projectiles work with signals and emits them, for easy hooking up from other parts of the code. Meatshielding is now less effective . Impact sound is now configurable per projectile. High risk.
304 lines
8.2 KiB
Plaintext
304 lines
8.2 KiB
Plaintext
/*
|
|
adds a dizziness amount to a mob
|
|
use this rather than directly changing var/dizziness
|
|
since this ensures that the dizzy_process proc is started
|
|
currently only humans get dizzy
|
|
|
|
value of dizziness ranges from 0 to 1000
|
|
below 100 is not dizzy
|
|
*/
|
|
|
|
/mob/var/dizziness = 0//Carbon
|
|
/mob/var/is_dizzy = 0
|
|
|
|
/mob/proc/make_dizzy(var/amount)
|
|
if(!istype(src, /mob/living/carbon/human)) // for the moment, only humans get dizzy
|
|
return
|
|
|
|
dizziness = min(1000, dizziness + amount) // store what will be new value
|
|
// clamped to max 1000
|
|
if(dizziness > 100 && !is_dizzy)
|
|
spawn(0)
|
|
dizzy_process()
|
|
|
|
|
|
/*
|
|
dizzy process - wiggles the client's pixel offset over time
|
|
spawned from make_dizzy(), will terminate automatically when dizziness gets <100
|
|
note dizziness decrements automatically in the mob's Life() proc.
|
|
*/
|
|
/mob/proc/dizzy_process()
|
|
is_dizzy = 1
|
|
while(dizziness > 100)
|
|
if(client)
|
|
var/amplitude = dizziness*(sin(dizziness * 0.044 * world.time) + 1) / 70
|
|
client.pixel_x = amplitude * sin(0.008 * dizziness * world.time)
|
|
client.pixel_y = amplitude * cos(0.008 * dizziness * world.time)
|
|
|
|
sleep(1)
|
|
//endwhile - reset the pixel offsets to zero
|
|
is_dizzy = 0
|
|
if(client)
|
|
client.pixel_x = 0
|
|
client.pixel_y = 0
|
|
|
|
// jitteriness - copy+paste of dizziness
|
|
/mob/var/is_jittery = 0
|
|
/mob/var/jitteriness = 0//Carbon
|
|
/mob/proc/make_jittery(var/amount)
|
|
return
|
|
|
|
/mob/living/carbon/human/make_jittery(amount)
|
|
jitteriness = min(1000, jitteriness + amount) // store what will be new value
|
|
// clamped to max 1000
|
|
if(jitteriness > 100 && !is_jittery && stat != DEAD && !(status_flags & FAKEDEATH))
|
|
spawn(0)
|
|
jittery_process()
|
|
|
|
/mob/proc/jittery_process()
|
|
is_jittery = TRUE
|
|
while(jitteriness > 100)
|
|
var/amplitude = min(4, jitteriness / 100)
|
|
pixel_x = old_x + rand(-amplitude, amplitude)
|
|
pixel_y = old_y + rand(-amplitude/3, amplitude/3)
|
|
if(stat == DEAD || (status_flags & FAKEDEATH))
|
|
break
|
|
sleep(1)
|
|
//endwhile - reset the pixel offsets to zero
|
|
is_jittery = FALSE
|
|
pixel_x = old_x
|
|
pixel_y = old_y
|
|
|
|
|
|
//handles up-down floaty effect in space and zero-gravity
|
|
/mob/var/is_floating = FALSE
|
|
|
|
/mob/proc/update_floating()
|
|
if(anchored || buckled_to)
|
|
set_floating(FALSE)
|
|
return
|
|
|
|
var/turf/turf = get_turf(src)
|
|
if(!turf?.is_hole)
|
|
var/area/A = turf.loc
|
|
if(istype(A) && A.has_gravity())
|
|
set_floating(FALSE)
|
|
return
|
|
else
|
|
var/shoegrip = Check_Shoegrip()
|
|
if(shoegrip)
|
|
set_floating(FALSE)
|
|
return
|
|
else
|
|
if(CanAvoidGravity())
|
|
set_floating(TRUE)
|
|
return
|
|
else
|
|
set_floating(FALSE)
|
|
return
|
|
|
|
set_floating(TRUE)
|
|
|
|
/mob/proc/set_floating(var/floating_state)
|
|
if(buckled_to && is_floating)
|
|
stop_floating()
|
|
return
|
|
|
|
if(floating_state && !is_floating)
|
|
start_floating()
|
|
else if(!floating_state && is_floating)
|
|
stop_floating()
|
|
|
|
/mob/proc/start_floating()
|
|
is_floating = TRUE
|
|
|
|
var/amplitude = 2 //maximum displacement from original position
|
|
var/period = 36 //time taken for the mob to go up >> down >> original position, in deciseconds. Should be multiple of 4
|
|
|
|
var/top = old_y + amplitude
|
|
var/bottom = old_y - amplitude
|
|
var/half_period = period / 2
|
|
var/quarter_period = period / 4
|
|
|
|
animate(src, pixel_y = top, time = quarter_period, easing = SINE_EASING | EASE_OUT, loop = -1) //up
|
|
animate(pixel_y = bottom, time = half_period, easing = SINE_EASING, loop = -1) //down
|
|
animate(pixel_y = old_y, time = quarter_period, easing = SINE_EASING | EASE_IN, loop = -1) //back
|
|
|
|
/mob/proc/stop_floating()
|
|
animate(src, pixel_y = get_standard_pixel_y(), time = 5, easing = SINE_EASING | EASE_IN) //halt animation
|
|
//reset the pixel offsets to defaults
|
|
is_floating = FALSE
|
|
|
|
/atom/movable/proc/do_attack_animation(atom/A, atom/movable/weapon, var/image/attack_image, var/initial_pixel_x = 0, var/initial_pixel_y = 0)
|
|
var/pixel_x_diff = 0
|
|
var/pixel_y_diff = 0
|
|
var/turn_dir = 1
|
|
|
|
var/direction = get_dir(src, A)
|
|
switch(direction)
|
|
if(NORTH)
|
|
pixel_y_diff = 8
|
|
if(SOUTH)
|
|
pixel_y_diff = -8
|
|
if(EAST)
|
|
pixel_x_diff = 8
|
|
if(WEST)
|
|
pixel_x_diff = -8
|
|
if(NORTHEAST)
|
|
pixel_x_diff = 8
|
|
pixel_y_diff = 8
|
|
if(NORTHWEST)
|
|
pixel_x_diff = -8
|
|
pixel_y_diff = 8
|
|
if(SOUTHEAST)
|
|
pixel_x_diff = 8
|
|
pixel_y_diff = -8
|
|
if(SOUTHWEST)
|
|
pixel_x_diff = -8
|
|
pixel_y_diff = -8
|
|
if(direction & NORTH)
|
|
pixel_y_diff = 8
|
|
turn_dir = rand(50) ? -1 : 1
|
|
else if(direction & SOUTH)
|
|
pixel_y_diff = -8
|
|
turn_dir = rand(50) ? -1 : 1
|
|
|
|
if(direction & EAST)
|
|
pixel_x_diff = 8
|
|
else if(direction & WEST)
|
|
pixel_x_diff = -8
|
|
turn_dir = -1
|
|
|
|
if(!initial_pixel_x)
|
|
initial_pixel_x = initial(pixel_x)
|
|
if(!initial_pixel_y)
|
|
initial_pixel_y = initial(pixel_y)
|
|
|
|
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, time = 2)
|
|
animate(pixel_x = initial_pixel_x, pixel_y = initial_pixel_y, time = 2)
|
|
var/matrix/initial_transform = matrix(transform)
|
|
var/matrix/rotated_transform = transform.Turn(15 * turn_dir)
|
|
|
|
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform = rotated_transform, time = 2, easing = BACK_EASING | EASE_IN)
|
|
animate(pixel_x = initial_pixel_x, pixel_y = initial_pixel_y, transform = initial_transform, time = 2, easing = SINE_EASING)
|
|
|
|
// either attack_item OR attack_image should be used. if both are used, attack_image will be the one chosen
|
|
/mob/do_attack_animation(atom/A, var/atom/attack_item, var/image/attack_image)
|
|
set waitfor = FALSE
|
|
|
|
var/initial_pixel_x = get_standard_pixel_x()
|
|
var/initial_pixel_y = get_standard_pixel_y()
|
|
..(A, attack_item, attack_image, initial_pixel_x, initial_pixel_y)
|
|
|
|
if(is_floating)
|
|
addtimer(CALLBACK(src, PROC_REF(start_floating)), 4)
|
|
|
|
if(attack_item == FIST_ATTACK_ANIMATION) // only play the physical movement
|
|
return
|
|
// What icon do we use for the attack?
|
|
var/image/I
|
|
if(attack_image)
|
|
I = attack_image
|
|
else if(attack_item)
|
|
I = image(attack_item.icon, A, attack_item.icon_state, A.layer + 1)
|
|
else
|
|
if(hand && l_hand) // Attacked with item in left hand.
|
|
I = image(l_hand.icon, A, l_hand.icon_state, A.layer + 1)
|
|
else if (!hand && r_hand) // Attacked with item in right hand.
|
|
I = image(r_hand.icon, A, r_hand.icon_state, A.layer + 1)
|
|
else // Attacked with a fist?
|
|
return
|
|
|
|
// Who can see the attack?
|
|
var/list/viewing = list()
|
|
for (var/mob/M in viewers(A))
|
|
if (M.client)
|
|
viewing |= M.client
|
|
flick_overlay(I, viewing, 5) // 5 ticks/half a second
|
|
|
|
// Scale the icon.
|
|
I.transform *= 0.75
|
|
// Set the direction of the icon animation.
|
|
var/direction = get_dir(src, A)
|
|
if(direction & NORTH)
|
|
I.pixel_y = -16
|
|
else if(direction & SOUTH)
|
|
I.pixel_y = 16
|
|
|
|
if(direction & EAST)
|
|
I.pixel_x = -16
|
|
else if(direction & WEST)
|
|
I.pixel_x = 16
|
|
|
|
if(!direction) // Attacked self?!
|
|
I.pixel_z = 16
|
|
|
|
var/matrix/M = new
|
|
M.Turn(pick(-20, 20))
|
|
// And animate the attack!
|
|
animate(I, alpha = 175, pixel_x = initial_pixel_x, pixel_y = initial_pixel_y, pixel_z = 0, time = 2, easing = CUBIC_EASING)
|
|
sleep(2)
|
|
animate(I, transform = M, time = 1) // apply the fancy matrix
|
|
sleep(1)
|
|
animate(I, transform = matrix(), time = 1) // back to a default matrix
|
|
sleep(1)
|
|
animate(I, alpha = 0, time = 1)
|
|
|
|
/mob/proc/spin(spintime, speed)
|
|
spawn()
|
|
var/D = dir
|
|
while(spintime >= speed)
|
|
sleep(speed)
|
|
switch(D)
|
|
if(NORTH)
|
|
D = EAST
|
|
if(SOUTH)
|
|
D = WEST
|
|
if(EAST)
|
|
D = SOUTH
|
|
if(WEST)
|
|
D = NORTH
|
|
set_dir(D)
|
|
spintime -= speed
|
|
return
|
|
|
|
// Mob Throwing Animation
|
|
/mob/proc/animate_throw()
|
|
var/ipx = pixel_x
|
|
var/ipy = pixel_y
|
|
var/mpx = 0
|
|
var/mpy = 0
|
|
|
|
if(dir & NORTH)
|
|
mpy += 3
|
|
else if(dir & SOUTH)
|
|
mpy -= 3
|
|
if(dir & EAST)
|
|
mpx += 3
|
|
else if(dir & WEST)
|
|
mpx -= 3
|
|
|
|
var/new_x = mpx + ipx
|
|
var/new_y = mpy + ipy
|
|
|
|
animate(src, pixel_x = new_x, pixel_y = new_y, time = 0.6, easing = EASE_OUT)
|
|
|
|
var/matrix/M = matrix(transform)
|
|
animate(transform = turn(transform, (mpx - mpy) * 4), time = 0.6, easing = EASE_OUT)
|
|
animate(pixel_x = ipx, pixel_y = ipy, time = 0.6, easing = EASE_IN)
|
|
animate(transform = M, time = 0.6, easing = EASE_IN)
|
|
|
|
if(is_floating)
|
|
addtimer(CALLBACK(src, PROC_REF(start_floating)), 2.4)
|
|
|
|
/atom/proc/quick_jitter(var/jitter_time = 5)
|
|
set waitfor = 0
|
|
|
|
jitter_time--
|
|
|
|
pixel_x = jitter_time ? get_standard_pixel_x() + rand(-3, 3) : get_standard_pixel_x()
|
|
pixel_y = jitter_time ? get_standard_pixel_y() + rand(-1, 1) : get_standard_pixel_y()
|
|
|
|
if(jitter_time)
|
|
addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, quick_jitter), jitter_time), 1)
|