Files
Aurora.3/code/modules/mob/animations.dm
Fluffy c24b4c7097 Projectile refactoring madness (#19878)
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.
2024-09-23 10:12:57 +00:00

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)