Merge branch 'master' into revenant_TK

This commit is contained in:
Artur
2021-01-20 18:27:11 +02:00
414 changed files with 6097 additions and 2811 deletions
+199 -111
View File
@@ -1,5 +1,7 @@
/atom/movable
layer = OBJ_LAYER
glide_size = 8
SET_APPEARANCE_FLAGS(TILE_BOUND | PIXEL_SCALE)
var/last_move = null
var/last_move_time = 0
var/anchored = FALSE
@@ -28,8 +30,6 @@
var/atom/movable/moving_from_pull //attempt to resume grab after moving instead of before.
var/list/client_mobs_in_contents // This contains all the client mobs within this container
var/list/acted_explosions //for explosion dodging
glide_size = 8
appearance_flags = TILE_BOUND|PIXEL_SCALE
var/datum/forced_movement/force_moving = null //handled soley by forced_movement.dm
var/movement_type = GROUND //Incase you have multiple types, you automatically use the most useful one. IE: Skating on ice, flippers on water, flying over chasm/space, etc.
var/atom/movable/pulling
@@ -59,6 +59,42 @@
em_block = new(src, render_target)
vis_contents += em_block
/atom/movable/Destroy(force)
QDEL_NULL(proximity_monitor)
QDEL_NULL(language_holder)
QDEL_NULL(em_block)
unbuckle_all_mobs(force = TRUE)
if(loc)
//Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary)
if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc))
CanAtmosPass = ATMOS_PASS_YES
air_update_turf(TRUE)
loc.handle_atom_del(src)
// if(opacity)
// RemoveElement(/datum/element/light_blocking)
invisibility = INVISIBILITY_ABSTRACT
if(pulledby)
pulledby.stop_pulling()
if(orbiting)
orbiting.end_orbit(src)
orbiting = null
. = ..()
for(var/movable_content in contents)
qdel(movable_content)
LAZYCLEARLIST(client_mobs_in_contents)
moveToNullspace()
/atom/movable/proc/update_emissive_block()
if(blocks_emissive != EMISSIVE_BLOCK_GENERIC)
return
@@ -113,40 +149,52 @@
return FALSE
return T.zPassOut(src, direction, destination) && destination.zPassIn(src, direction, T)
/atom/movable/vv_edit_var(var_name, var_value)
var/static/list/banned_edits = list("step_x", "step_y", "step_size")
var/static/list/careful_edits = list("bound_x", "bound_y", "bound_width", "bound_height")
if(var_name in banned_edits)
/atom/movable/vv_edit_var(var_name, var_value, massedit)
var/static/list/banned_edits = list("step_x" = TRUE, "step_y" = TRUE, "step_size" = TRUE, "bounds" = TRUE)
var/static/list/careful_edits = list("bound_x" = TRUE, "bound_y" = TRUE, "bound_width" = TRUE, "bound_height" = TRUE)
if(banned_edits[var_name])
return FALSE //PLEASE no.
if((var_name in careful_edits) && (var_value % world.icon_size) != 0)
if((careful_edits[var_name]) && (var_value % world.icon_size) != 0)
return FALSE
switch(var_name)
if(NAMEOF(src, x))
var/turf/T = locate(var_value, y, z)
if(T)
forceMove(T)
admin_teleport(T, !massedit)
return TRUE
return FALSE
if(NAMEOF(src, y))
var/turf/T = locate(x, var_value, z)
if(T)
forceMove(T)
admin_teleport(T, !massedit)
return TRUE
return FALSE
if(NAMEOF(src, z))
var/turf/T = locate(x, y, var_value)
if(T)
forceMove(T)
admin_teleport(T, !massedit)
return TRUE
return FALSE
if(NAMEOF(src, loc))
if(istype(var_value, /atom))
forceMove(var_value)
return TRUE
else if(isnull(var_value))
moveToNullspace()
if(isatom(var_value) || isnull(var_value))
admin_teleport(var_value, !massedit)
return TRUE
return FALSE
if(NAMEOF(src, anchored))
set_anchored(var_value)
. = TRUE
if(NAMEOF(src, pulledby))
set_pulledby(var_value)
. = TRUE
if(NAMEOF(src, glide_size))
set_glide_size(var_value)
. = TRUE
if(!isnull(.))
datum_flags |= DF_VAR_EDITED
return
return ..()
/atom/movable/proc/start_pulling(atom/movable/AM, state, force = move_force, supress_message = FALSE)
@@ -168,48 +216,73 @@
AMob.grabbedby(src)
return TRUE
stop_pulling()
// SEND_SIGNAL(src, COMSIG_ATOM_START_PULL, AM, state, force)
if(AM.pulledby)
log_combat(AM, AM.pulledby, "pulled from", src)
AM.pulledby.stop_pulling() //an object can't be pulled by two mobs at once.
pulling = AM
AM.pulledby = src
AM.set_pulledby(src)
setGrabState(state)
if(ismob(AM))
var/mob/M = AM
log_combat(src, M, "grabbed", addition="passive grab")
if(!supress_message)
visible_message("<span class='warning'>[src] has grabbed [M] passively!</span>")
M.visible_message("<span class='warning'>[src] grabs [M] passively.</span>", \
"<span class='danger'>[src] grabs you passively.</span>")
return TRUE
/atom/movable/proc/stop_pulling()
if(!pulling)
return
pulling.pulledby = null
pulling.set_pulledby(null)
var/mob/living/ex_pulled = pulling
setGrabState(GRAB_PASSIVE)
pulling = null
setGrabState(0)
if(isliving(ex_pulled))
var/mob/living/L = ex_pulled
L.update_mobility()// mob gets up if it was lyng down in a chokehold
///Reports the event of the change in value of the pulledby variable.
/atom/movable/proc/set_pulledby(new_pulledby)
if(new_pulledby == pulledby)
return FALSE //null signals there was a change, be sure to return FALSE if none happened here.
. = pulledby
pulledby = new_pulledby
/atom/movable/proc/Move_Pulled(atom/A)
if(!pulling)
return
return FALSE
if(pulling.anchored || pulling.move_resist > move_force || !pulling.Adjacent(src))
stop_pulling()
return
return FALSE
if(isliving(pulling))
var/mob/living/L = pulling
if(L.buckled && L.buckled.buckle_prevents_pull) //if they're buckled to something that disallows pulling, prevent it
stop_pulling()
return
return FALSE
if(A == loc && pulling.density)
return
if(!Process_Spacemove(get_dir(pulling.loc, A)))
return
step(pulling, get_dir(pulling.loc, A))
return FALSE
var/move_dir = get_dir(pulling.loc, A)
if(!Process_Spacemove(move_dir))
return FALSE
pulling.Move(get_step(pulling.loc, move_dir), move_dir, glide_size)
return TRUE
/**
* Recursively set glide size for atom's pulled things
*/
/atom/movable/proc/recursive_pulled_glidesize_update()
var/list/ran = list()
var/atom/movable/updating = pulling
while(updating)
if(ran[updating])
return
updating.set_glide_size(glide_size, FALSE)
ran[updating] = TRUE
updating = updating.pulling
/atom/movable/proc/check_pulling()
if(pulling)
var/atom/movable/pullee = pulling
@@ -229,54 +302,57 @@
if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1) //separated from our puller and not in the middle of a diagonal move.
pulledby.stop_pulling()
/atom/movable/Destroy(force)
QDEL_NULL(proximity_monitor)
QDEL_NULL(language_holder)
QDEL_NULL(em_block)
/atom/movable/proc/set_glide_size(target = 8, recursive = TRUE)
#ifdef SMOOTH_MOVEMENT
// SEND_SIGNAL(src, COMSIG_MOVABLE_UPDATE_GLIDE_SIZE, target)
glide_size = target
unbuckle_all_mobs(force=1)
for(var/m in buckled_mobs)
var/mob/buckled_mob = m
buckled_mob.set_glide_size(target)
. = ..()
if(recursive)
recursive_pulled_glidesize_update()
#else
return
#endif
if(loc)
//Restore air flow if we were blocking it (movables with ATMOS_PASS_PROC will need to do this manually if necessary)
if(((CanAtmosPass == ATMOS_PASS_DENSITY && density) || CanAtmosPass == ATMOS_PASS_NO) && isturf(loc))
CanAtmosPass = ATMOS_PASS_YES
air_update_turf(TRUE)
loc.handle_atom_del(src)
for(var/atom/movable/AM in contents)
qdel(AM)
moveToNullspace()
invisibility = INVISIBILITY_ABSTRACT
if(pulledby)
pulledby.stop_pulling()
if(orbiting)
orbiting.end_orbit(src)
orbiting = null
///Sets the anchored var and returns if it was sucessfully changed or not.
/atom/movable/proc/set_anchored(anchorvalue)
SHOULD_CALL_PARENT(TRUE)
if(anchored == anchorvalue)
return
. = anchored
anchored = anchorvalue
// SEND_SIGNAL(src, COMSIG_MOVABLE_SET_ANCHORED, anchorvalue)
/atom/movable/proc/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
set waitfor = 0
set waitfor = FALSE
var/hitpush = TRUE
var/impact_signal = SEND_SIGNAL(src, COMSIG_MOVABLE_IMPACT, hit_atom, throwingdatum)
if(impact_signal & COMPONENT_MOVABLE_IMPACT_FLIP_HITPUSH)
hitpush = FALSE // hacky, tie this to something else or a proper workaround later
if(impact_signal & ~COMPONENT_MOVABLE_IMPACT_NEVERMIND) // in case a signal interceptor broke or deleted the thing before we could process our hit
return hit_atom.hitby(src, throwingdatum = throwingdatum, hitpush = hitpush)
if(!(impact_signal && (impact_signal & COMPONENT_MOVABLE_IMPACT_NEVERMIND))) // in case a signal interceptor broke or deleted the thing before we could process our hit
return hit_atom.hitby(src, throwingdatum=throwingdatum, hitpush=hitpush)
/atom/movable/hitby(atom/movable/AM, skipcatch, hitpush = TRUE, blocked, datum/thrownthing/throwingdatum)
if(!anchored && hitpush && (!throwingdatum || (throwingdatum.force >= (move_resist * MOVE_FORCE_PUSH_RATIO))))
step(src, AM.dir)
..()
/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY, messy_throw = TRUE)
/atom/movable/proc/safe_throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE)
if((force < (move_resist * MOVE_FORCE_THROW_RATIO)) || (move_resist == INFINITY))
return
return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force, messy_throw)
return throw_at(target, range, speed, thrower, spin, diagonals_first, callback, force, gentle)
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = INFINITY, messy_throw = TRUE) //If this returns FALSE then callback will not be called.
///If this returns FALSE then callback will not be called.
/atom/movable/proc/throw_at(atom/target, range, speed, mob/thrower, spin = TRUE, diagonals_first = FALSE, datum/callback/callback, force = MOVE_FORCE_STRONG, gentle = FALSE, quickstart = TRUE)
. = FALSE
if(QDELETED(src))
CRASH("Qdeleted thing being thrown around.")
if (!target || speed <= 0)
return
@@ -288,7 +364,7 @@
//They are moving! Wouldn't it be cool if we calculated their momentum and added it to the throw?
if (thrower && thrower.last_move && thrower.client && thrower.client.move_delay >= world.time + world.tick_lag*2)
var/user_momentum = thrower.movement_delay()
var/user_momentum = thrower.movement_delay() //cached_multiplicative_slowdown
if (!user_momentum) //no movement_delay, this means they move once per byond tick, lets calculate from that instead.
user_momentum = world.tick_lag
@@ -312,19 +388,13 @@
. = TRUE // No failure conditions past this point.
var/datum/thrownthing/TT = new()
TT.thrownthing = src
TT.target = target
TT.target_turf = get_turf(target)
TT.init_dir = get_dir(src, target)
TT.maxrange = range
TT.speed = speed
TT.thrower = thrower
TT.diagonals_first = diagonals_first
TT.force = force
TT.callback = callback
if(!QDELETED(thrower))
TT.target_zone = thrower.zone_selected
var/target_zone
if(QDELETED(thrower))
thrower = null //Let's not pass a qdeleting reference if any.
else
target_zone = thrower.zone_selected
var/datum/thrownthing/TT = new(src, target, get_turf(target), get_dir(src, target), range, speed, thrower, diagonals_first, force, gentle, callback, target_zone)
var/dist_x = abs(target.x - src.x)
var/dist_y = abs(target.y - src.y)
@@ -359,7 +429,8 @@
SSthrowing.processing[src] = TT
if (SSthrowing.state == SS_PAUSED && length(SSthrowing.currentrun))
SSthrowing.currentrun[src] = TT
TT.tick()
if (quickstart)
TT.tick()
/atom/movable/proc/force_pushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction)
return FALSE
@@ -382,13 +453,13 @@
return TRUE
return ..()
// called when this atom is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called.
/atom/movable/proc/on_exit_storage(datum/component/storage/concrete/S)
return
/// called when this atom is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called.
/atom/movable/proc/on_exit_storage(datum/component/storage/concrete/S) // rename S to master_storage
// SEND_SIGNAL(src, COMSIG_STORAGE_EXITED, master_storage)
// called when this atom is added into a storage item, which is passed on as S. The loc variable is already set to the storage item.
/// called when this atom is added into a storage item, which is passed on as S. The loc variable is already set to the storage item.
/atom/movable/proc/on_enter_storage(datum/component/storage/concrete/S)
return
// SEND_SIGNAL(src, COMSIG_STORAGE_ENTERED, master_storage)
/atom/movable/proc/get_spacemove_backup()
var/atom/movable/dense_object_backup
@@ -422,24 +493,26 @@
return //don't do an animation if attacking self
var/pixel_x_diff = 0
var/pixel_y_diff = 0
var/turn_dir = 1
var/direction = get_dir(src, A)
if(direction & NORTH)
pixel_y_diff = 8
turn_dir = prob(50) ? -1 : 1
else if(direction & SOUTH)
pixel_y_diff = -8
turn_dir = prob(50) ? -1 : 1
if(direction & EAST)
pixel_x_diff = 8
else if(direction & WEST)
pixel_x_diff = -8
turn_dir = -1
var/matrix/OM = matrix(transform)
var/matrix/M = matrix(transform)
M.Turn(pixel_x_diff ? pixel_x_diff*2 : pick(-16, 16))
animate(src, pixel_x = pixel_x + pixel_x_diff, pixel_y = pixel_y + pixel_y_diff, transform = M, time = 2)
animate(src, pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform = OM, 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 = 1, easing=BACK_EASING|EASE_IN)
animate(pixel_x = pixel_x - pixel_x_diff, pixel_y = pixel_y - pixel_y_diff, transform=initial_transform, time = 2, easing=SINE_EASING)
/atom/movable/proc/do_item_attack_animation(atom/A, visual_effect_icon, obj/item/used_item)
var/image/I
@@ -450,21 +523,21 @@
I.plane = GAME_PLANE
// Scale the icon.
I.transform *= 0.75
I.transform *= 0.4
// The icon should not rotate.
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
// Set the direction of the icon animation.
var/direction = get_dir(src, A)
if(direction & NORTH)
I.pixel_y = -16
I.pixel_y = -12
else if(direction & SOUTH)
I.pixel_y = 16
I.pixel_y = 12
if(direction & EAST)
I.pixel_x = -16
I.pixel_x = -14
else if(direction & WEST)
I.pixel_x = 16
I.pixel_x = 14
if(!direction) // Attacked self?!
I.pixel_z = 16
@@ -472,10 +545,12 @@
if(!I)
return
flick_overlay(I, GLOB.clients, 5) // 5 ticks/half a second
flick_overlay(I, GLOB.clients, 10)
// And animate the attack!
animate(I, alpha = 175, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3)
animate(I, alpha = 175, transform = matrix() * 0.75, pixel_x = 0, pixel_y = 0, pixel_z = 0, time = 3)
animate(time = 1)
animate(alpha = 0, time = 3, easing = CIRCULAR_EASING|EASE_OUT)
/atom/movable/vv_get_dropdown()
. = ..()
@@ -495,16 +570,14 @@
/atom/movable/proc/float(on, throw_override)
if(throwing || !throw_override)
return
if(on && (!(movement_type & FLOATING) || floating_need_update))
animate(src, pixel_y = pixel_y + 2, time = 10, loop = -1)
sleep(10)
animate(src, pixel_y = pixel_y - 2, time = 10, loop = -1)
if(!(movement_type & FLOATING))
setMovetype(movement_type | FLOATING)
else if (!on && movement_type & FLOATING)
if(on && !(movement_type & FLOATING))
animate(src, pixel_y = 2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
animate(pixel_y = -2, time = 10, loop = -1, flags = ANIMATION_RELATIVE)
setMovetype(movement_type | FLOATING)
else if (!on && (movement_type & FLOATING))
animate(src, pixel_y = initial(pixel_y), time = 10)
setMovetype(movement_type & ~FLOATING)
floating_need_update = FALSE
floating_need_update = FALSE // assume it's done
/* Language procs
* Unless you are doing something very specific, these are the ones you want to use.
@@ -611,10 +684,32 @@
return FALSE
return TRUE
/// Updates the grab state of the movable
/// This exists to act as a hook for behaviour
/**
* Updates the grab state of the movable
*
* This exists to act as a hook for behaviour
*/
/atom/movable/proc/setGrabState(newstate)
if(newstate == grab_state)
return
// SEND_SIGNAL(src, COMSIG_MOVABLE_SET_GRAB_STATE, newstate)
. = grab_state
grab_state = newstate
// switch(grab_state) // Current state.
// if(GRAB_PASSIVE)
// REMOVE_TRAIT(pulling, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT)
// REMOVE_TRAIT(pulling, TRAIT_HANDS_BLOCKED, CHOKEHOLD_TRAIT)
// if(. >= GRAB_NECK) // Previous state was a a neck-grab or higher.
// REMOVE_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT)
// if(GRAB_AGGRESSIVE)
// if(. >= GRAB_NECK) // Grab got downgraded.
// REMOVE_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT)
// else // Grab got upgraded from a passive one.
// ADD_TRAIT(pulling, TRAIT_IMMOBILIZED, CHOKEHOLD_TRAIT)
// ADD_TRAIT(pulling, TRAIT_HANDS_BLOCKED, CHOKEHOLD_TRAIT)
// if(GRAB_NECK, GRAB_KILL)
// if(. <= GRAB_AGGRESSIVE)
// ADD_TRAIT(pulling, TRAIT_FLOORED, CHOKEHOLD_TRAIT)
/obj/item/proc/do_pickup_animation(atom/target)
set waitfor = FALSE
@@ -626,31 +721,24 @@
I.appearance_flags = APPEARANCE_UI_IGNORE_ALPHA
var/turf/T = get_turf(src)
var/direction
var/to_x = 0
var/to_y = 0
var/to_x = initial(target.pixel_x)
var/to_y = initial(target.pixel_y)
if(!QDELETED(T) && !QDELETED(target))
direction = get_dir(T, target)
if(direction & NORTH)
to_y = 32
to_y += 32
else if(direction & SOUTH)
to_y = -32
to_y -= 32
if(direction & EAST)
to_x = 32
to_x += 32
else if(direction & WEST)
to_x = -32
to_x -= 32
if(!direction)
to_y = 16
to_y += 16
flick_overlay(I, GLOB.clients, 6)
var/matrix/M = new
M.Turn(pick(-30, 30))
animate(I, alpha = 175, pixel_x = to_x, pixel_y = to_y, time = 3, transform = M, easing = CUBIC_EASING)
sleep(1)
animate(I, alpha = 0, transform = matrix(), time = 1)
/atom/movable/proc/set_anchored(anchorvalue) //literally only for plumbing ran
SHOULD_CALL_PARENT(TRUE)
if(anchored == anchorvalue)
return
. = anchored
anchored = anchorvalue