diff --git a/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm new file mode 100644 index 0000000000..cc6e5bd49a --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_atom/signals_atom_movement.dm @@ -0,0 +1,3 @@ +/// Called from /mob/living/PushAM -- Called when this mob is about to push a movable, but before it moves +/// (aotm/movable/being_pushed) +#define COMSIG_LIVING_PUSHING_MOVABLE "living_pushing_movable" diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm new file mode 100644 index 0000000000..5d2a471c0a --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -0,0 +1,2 @@ +///From base of mob/living/MobBump() (mob/living) +#define COMSIG_LIVING_MOB_BUMP "living_mob_bump" diff --git a/code/__DEFINES/movement.dm b/code/__DEFINES/movement.dm index 5bf7de8647..bccbd425dd 100644 --- a/code/__DEFINES/movement.dm +++ b/code/__DEFINES/movement.dm @@ -13,7 +13,7 @@ GLOBAL_VAR_INIT(glide_size_multiplier, 1.0) /// Then that's multiplied by the global glide size multiplier. 1.25 by default feels pretty close to spot on. This is just to try to get byond to behave. /// The whole result is then clamped to within the range above. /// Not very readable but it works -#define DELAY_TO_GLIDE_SIZE(delay) (clamp(((32 / max((delay) / world.tick_lag, 1)) * GLOB.glide_size_multiplier), MIN_GLIDE_SIZE, MAX_GLIDE_SIZE)) +#define DELAY_TO_GLIDE_SIZE(delay) (clamp(((world.icon_size / max((delay) / world.tick_lag, 1)) * GLOB.glide_size_multiplier), MIN_GLIDE_SIZE, MAX_GLIDE_SIZE)) /// Enables smooth movement // #define SMOOTH_MOVEMENT diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 6f394c1135..c36cc7cc7c 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -81,6 +81,7 @@ //Called when we bump onto a mob /mob/living/proc/MobBump(mob/M) + SEND_SIGNAL(src, COMSIG_LIVING_MOB_BUMP, M) //Even if we don't push/swap places, we "touched" them, so spread fire spreadFire(M) @@ -88,6 +89,7 @@ return TRUE var/they_can_move = TRUE + if(isliving(M)) var/mob/living/L = M they_can_move = CHECK_MOBILITY(L, MOBILITY_MOVE) @@ -105,16 +107,16 @@ //Should stop you pushing a restrained person out of the way if(L.pulledby && L.pulledby != src && L.restrained()) if(!(world.time % 5)) - to_chat(src, "[L] is restrained, you cannot push past.") - return 1 + to_chat(src, span_warning("[L] is restrained, you cannot push past.")) + return TRUE if(L.pulling) if(ismob(L.pulling)) var/mob/P = L.pulling if(P.restrained()) if(!(world.time % 5)) - to_chat(src, "[L] is restraining [P], you cannot push past.") - return 1 + to_chat(src, span_warning("[L] is restraining [P], you cannot push past.")) + return TRUE //CIT CHANGES START HERE - makes it so resting stops you from moving through standing folks or over prone bodies without a short delay if(!CHECK_MOBILITY(src, MOBILITY_STAND)) @@ -142,7 +144,7 @@ //END OF CIT CHANGES if(moving_diagonally)//no mob swap during diagonal moves. - return 1 + return TRUE if(!M.buckled && !M.has_buckled_mobs()) var/mob_swap = FALSE @@ -151,7 +153,8 @@ if(!too_strong) mob_swap = TRUE else - if(M.pulledby == src && a_intent == INTENT_GRAB) + //You can swap with the person you are dragging on grab intent, and restrained people in most cases + if(M.pulledby == src && !too_strong) mob_swap = TRUE //restrained people act if they were on 'help' intent to prevent a person being pulled from being separated from their puller else if((M.restrained() || M.a_intent == INTENT_HELP) && (restrained() || a_intent == INTENT_HELP)) @@ -159,8 +162,8 @@ if(mob_swap) //switch our position with M if(loc && !loc.Adjacent(M.loc)) - return 1 - now_pushing = 1 + return TRUE + now_pushing = TRUE var/oldloc = loc var/oldMloc = M.loc @@ -180,27 +183,31 @@ if(!M_passmob) M.pass_flags &= ~PASSMOB - now_pushing = 0 + now_pushing = FALSE if(!move_failed) - return 1 + return TRUE //okay, so we didn't switch. but should we push? //not if he's not CANPUSH of course if(!(M.status_flags & CANPUSH)) - return 1 + return TRUE if(isliving(M)) var/mob/living/L = M if(HAS_TRAIT(L, TRAIT_PUSHIMMUNE)) - return 1 - //If they're a human, and they're not in help intent, block pushing - if(ishuman(M) && (M.a_intent != INTENT_HELP)) - return TRUE + return TRUE + if(M.a_intent != INTENT_HELP) + //If they're a human, and they're not in help intent, block pushing + if(ishuman(M)) + return TRUE + //if they are a cyborg, and they're alive and not in help intent, block pushing + if(iscyborg(M) && M.stat != DEAD) + return TRUE //anti-riot equipment is also anti-push for(var/obj/item/I in M.held_items) if(!istype(M, /obj/item/clothing)) if(prob(I.block_chance*2)) - return 1 + return TRUE /mob/living/get_photo_description(obj/item/camera/camera) var/list/mob_details = list() @@ -231,21 +238,40 @@ if(!client && (mob_size < MOB_SIZE_SMALL)) return now_pushing = TRUE - var/t = get_dir(src, AM) + SEND_SIGNAL(src, COMSIG_LIVING_PUSHING_MOVABLE, AM) + var/dir_to_target = get_dir(src, AM) + + // If there's no dir_to_target then the player is on the same turf as the atom they're trying to push. + // This can happen when a player is stood on the same turf as a directional window. All attempts to push + // the window will fail as get_dir will return 0 and the player will be unable to move the window when + // it should be pushable. + // In this scenario, we will use the facing direction of the /mob/living attempting to push the atom as + // a fallback. + if(!dir_to_target) + dir_to_target = dir + var/push_anchored = FALSE if((AM.move_resist * MOVE_FORCE_CRUSH_RATIO) <= force) - if(move_crush(AM, move_force, t)) + if(move_crush(AM, move_force, dir_to_target)) push_anchored = TRUE - if((AM.move_resist * MOVE_FORCE_FORCEPUSH_RATIO) <= force) //trigger move_crush and/or force_push regardless of if we can push it normally - if(force_push(AM, move_force, t, push_anchored)) + if((AM.move_resist * MOVE_FORCE_FORCEPUSH_RATIO) <= force) //trigger move_crush and/or force_push regardless of if we can push it normally + if(force_push(AM, move_force, dir_to_target, push_anchored)) push_anchored = TRUE + if(ismob(AM)) + var/mob/mob_to_push = AM + var/atom/movable/mob_buckle = mob_to_push.buckled + // If we can't pull them because of what they're buckled to, make sure we can push the thing they're buckled to instead. + // If neither are true, we're not pushing anymore. + if(mob_buckle && (mob_buckle.buckle_prevents_pull || (force < (mob_buckle.move_resist * MOVE_FORCE_PUSH_RATIO)))) + now_pushing = FALSE + return if((AM.anchored && !push_anchored) || (force < (AM.move_resist * MOVE_FORCE_PUSH_RATIO))) now_pushing = FALSE return - if (istype(AM, /obj/structure/window)) + if(istype(AM, /obj/structure/window)) var/obj/structure/window/W = AM if(W.fulltile) - for(var/obj/structure/window/win in get_step(W,t)) + for(var/obj/structure/window/win in get_step(W, dir_to_target)) now_pushing = FALSE return if(pulling == AM) @@ -253,8 +279,9 @@ var/current_dir if(isliving(AM)) current_dir = AM.dir - if(step(AM, t) && Process_Spacemove(t)) - step(src, t) + if(AM.Move(get_step(AM.loc, dir_to_target), dir_to_target, glide_size)) + AM.add_fingerprint(src) + Move(get_step(loc, dir_to_target), dir_to_target) if(current_dir) AM.setDir(current_dir) now_pushing = FALSE diff --git a/tgstation.dme b/tgstation.dme index 73521e0668..c236cb5447 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -154,6 +154,8 @@ #include "code\__DEFINES\dcs\helpers.dm" #include "code\__DEFINES\dcs\signals.dm" #include "code\__DEFINES\dcs\signals\signals_subsystem.dm" +#include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_movement.dm" +#include "code\__DEFINES\dcs\signals\signals_mob\signals_mob_living.dm" #include "code\__DEFINES\mapping\maploader.dm" #include "code\__DEFINES\material\worth.dm" #include "code\__DEFINES\mobs\innate_abilities.dm"