diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 46241823383..0b7280021ce 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -169,6 +169,7 @@ glide_for(movetime) if(!(direct & (direct - 1))) //Cardinal move . = ..(newloc, direct) // don't pass up movetime + setDir(direct) else //Diagonal move, split it into cardinal moves moving_diagonally = FIRST_DIAG_STEP var/first_step_dir @@ -217,6 +218,7 @@ if(moving_diagonally == SECOND_DIAG_STEP) if(!.) setDir(first_step_dir) + Moved(oldloc, first_step_dir) else if(!inertia_moving) inertia_next_move = world.time + inertia_move_delay newtonian_move(direct) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 050d4eb4fab..20f7d90f3d8 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -577,7 +577,6 @@ if(.) step_count++ pull_pulled(old_loc, pullee, movetime) - pull_grabbed(old_loc, direct, movetime) if(pulledby && moving_diagonally != FIRST_DIAG_STEP && get_dist(src, pulledby) > 1) //seperated from our puller and not in the middle of a diagonal move pulledby.stop_pulling() @@ -601,61 +600,6 @@ if(pulling && get_dist(src, pulling) > 1) // the pullee couldn't keep up stop_pulling() -/mob/living/proc/pull_grabbed(turf/old_turf, direct, movetime) - if(!Adjacent(old_turf)) - return - // We might not actually be grab pulled, but we are pretending that we are, so as to - // hackily work around issues arising from mutual grabs. - var/old_being_pulled = currently_grab_pulled - currently_grab_pulled = TRUE - // yes, this is four distinct `for` loops. No, they can't be merged. - var/list/grabbing = list() - for(var/mob/M in ret_grab()) - if(src == M) - continue - if(M.currently_grab_pulled) - // Being already pulled by something else up the call stack. - continue - grabbing |= M - for(var/mob/M in grabbing) - M.currently_grab_pulled = TRUE - M.animate_movement = SYNC_STEPS - for(var/i in 1 to length(grabbing)) - var/mob/M = grabbing[i] - if(QDELETED(M)) // old code warned me that M could go missing during a move, so I'm cargo-culting it here - continue - // compile a list of turfs we can maybe move them towards - // importantly, this should happen before actually trying to move them to either of those - // otherwise they can be moved twice (since `Move` returns TRUE only if it managed to - // *fully* move where you wanted it to; it can still move partially and return FALSE) - var/possible_dest = list() - for(var/turf/dest in orange(src, 1)) - if(dest.Adjacent(M)) - possible_dest |= dest - if(i == 1) // at least one of them should try to trail behind us, for aesthetics purposes - if(M.Move(old_turf, get_dir(M, old_turf), movetime)) - continue - // By this time the `old_turf` is definitely occupied by something immovable. - // So try to move them into some other adjacent turf, in a believable way - if(Adjacent(M)) - continue // they are already adjacent - for(var/turf/dest in possible_dest) - if(M.Move(dest, get_dir(M, dest), movetime)) - break - for(var/mob/M in grabbing) - M.currently_grab_pulled = null - M.animate_movement = SLIDE_STEPS - - for(var/obj/item/grab/G in src) - if(G.state == GRAB_NECK) - setDir(angle2dir((dir2angle(direct) + 202.5) % 365)) - G.adjust_position() - for(var/obj/item/grab/G in grabbed_by) - G.adjust_position() - - currently_grab_pulled = old_being_pulled - - /mob/living/proc/makeTrail(turf/turf_to_trail_on) if(!has_gravity(src)) return diff --git a/code/modules/mob/mob_grab.dm b/code/modules/mob/mob_grab.dm index 8848d66c45c..5baa6c1f92a 100644 --- a/code/modules/mob/mob_grab.dm +++ b/code/modules/mob/mob_grab.dm @@ -45,6 +45,8 @@ return affecting.grabbed_by += src + RegisterSignal(affecting, COMSIG_MOVABLE_MOVED, PROC_REF(grab_moved)) + RegisterSignal(assailant, COMSIG_MOVABLE_MOVED, PROC_REF(pull_grabbed)) hud = new /obj/screen/grab(src) hud.icon_state = "reinforce" @@ -62,6 +64,92 @@ clean_grabbed_by(assailant, affecting) adjust_position() +/obj/item/grab/Destroy() + if(affecting) + UnregisterSignal(affecting, COMSIG_MOVABLE_MOVED) + if(!affecting.buckled) + affecting.pixel_x = 0 + affecting.pixel_y = 0 //used to be an animate, not quick enough for qdel'ing + affecting.layer = initial(affecting.layer) + affecting.grabbed_by -= src + affecting = null + if(assailant) + UnregisterSignal(assailant, COMSIG_MOVABLE_MOVED) + if(assailant.client) + assailant.client.screen -= hud + assailant = null + QDEL_NULL(hud) + return ..() + +/obj/item/grab/proc/pull_grabbed(mob/user, turf/old_turf, direct, forced) + SIGNAL_HANDLER + if(assailant.moving_diagonally == FIRST_DIAG_STEP) //we dont want to do anything in the middle of diagonal step + return + if(!assailant.Adjacent(old_turf)) + qdel(src) + return + var/list/grab_states_not_moving = list(GRAB_KILL, GRAB_NECK) //states of grab when we dont need affecting to be moved by himself + var/assailant_glide_speed = TICKS2DS(world.icon_size / assailant.glide_size) + if(state in grab_states_not_moving) + affecting.glide_for(assailant_glide_speed) + else if(get_turf(affecting) != old_turf) + var/possible_dest = list() + var/list/mobs_do_not_move = list() // those are mobs we shouldnt move while we're going to new position + var/list/dest_1_sort = list() // just better dest to be picked first + var/list/dest_2_sort = list() + if(old_turf.Adjacent(affecting)) + possible_dest |= old_turf + for(var/turf/dest in orange(1, assailant)) + if(assailant.loc == dest) // orange(1) is broken and returning central turf + continue + if(!dest.Adjacent(affecting)) + continue + if(dest.Adjacent(old_turf)) + dest_1_sort |= dest + continue + dest_2_sort |= dest + possible_dest |= dest_1_sort + possible_dest |= dest_2_sort + if(istype(assailant.l_hand, /obj/item/grab)) + var/obj/item/grab/grab = assailant.l_hand + mobs_do_not_move |= grab.affecting + if(istype(assailant.r_hand, /obj/item/grab)) + var/obj/item/grab/grab = assailant.r_hand + mobs_do_not_move |= grab.affecting + mobs_do_not_move |= assailant + mobs_do_not_move -= affecting + if(assailant.pulling) + possible_dest -= old_turf // pull code just WANTS THAT old_loc and wont allow anyone else in it + mobs_do_not_move |= assailant.pulling + for(var/mob/mob as anything in mobs_do_not_move) + possible_dest -= get_turf(mob) + affecting.grab_do_not_move = mobs_do_not_move + var/success_move = FALSE + for(var/turf/dest as anything in possible_dest) + if(QDELETED(src)) + return + if(get_turf(affecting) == dest) + success_move = TRUE + continue + if(affecting.Move(dest, get_dir(affecting, dest), assailant_glide_speed)) + success_move = TRUE + break + continue + affecting.grab_do_not_move = initial(affecting.grab_do_not_move) + if(!success_move) + qdel(src) + return + if(state == GRAB_NECK) + assailant.setDir(turn(direct, 180)) + adjust_position() + +/obj/item/grab/proc/grab_moved() + SIGNAL_HANDLER + if(affecting.moving_diagonally == FIRST_DIAG_STEP) //we dont want to do anything in the middle of diagonal step + return + if(!assailant.Adjacent(affecting)) + qdel(src) + /obj/item/grab/proc/clean_grabbed_by(mob/user, mob/victim) //Cleans up any nulls in the grabbed_by list. if(istype(user)) @@ -169,11 +257,6 @@ return if(!assailant.Adjacent(affecting)) // To prevent teleportation via grab return - if(IS_HORIZONTAL(affecting) && state != GRAB_KILL) - animate(affecting, pixel_x = 0, pixel_y = 0, 5, 1, LINEAR_EASING) - return //KJK - /* if(force_down) //THIS GOES ABOVE THE RETURN LABELED KJK - affecting.setDir(SOUTH)*///This shows how you can apply special directions based on a variable. //face up var/shift = 0 var/adir = get_dir(assailant, affecting) @@ -417,22 +500,6 @@ return EAT_TIME_FAT //if it doesn't fit into the above, it's probably a fat guy, take EAT_TIME_FAT to do it -/obj/item/grab/Destroy() - if(affecting) - if(!affecting.buckled) - affecting.pixel_x = 0 - affecting.pixel_y = 0 //used to be an animate, not quick enough for qdel'ing - affecting.layer = initial(affecting.layer) - affecting.grabbed_by -= src - affecting = null - if(assailant) - if(assailant.client) - assailant.client.screen -= hud - assailant = null - QDEL_NULL(hud) - return ..() - - #undef EAT_TIME_XENO #undef EAT_TIME_FAT diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 7b23d1f7b69..5d77f2031a6 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -16,8 +16,8 @@ return TRUE if(ismob(mover)) var/mob/moving_mob = mover - if((currently_grab_pulled && moving_mob.currently_grab_pulled)) - return FALSE + if(src in moving_mob.grab_do_not_move) + return TRUE if(mover in buckled_mobs) return TRUE return (!mover.density || !density || horizontal) @@ -180,8 +180,6 @@ if(prev_pulling_loc && mob.pulling?.face_while_pulling && (mob.pulling.loc != prev_pulling_loc)) mob.setDir(get_dir(mob, mob.pulling)) // Face welding tanks and stuff when pulling - else - mob.setDir(direct) moving = 0 if(mob && .) diff --git a/code/modules/mob/mob_vars.dm b/code/modules/mob/mob_vars.dm index dabd5e3f49f..f20d80240b2 100644 --- a/code/modules/mob/mob_vars.dm +++ b/code/modules/mob/mob_vars.dm @@ -40,7 +40,7 @@ var/last_log = 0 var/obj/machinery/machine = null - var/currently_grab_pulled = null /// only set while the move is ongoing, to prevent shuffling between pullees + var/list/grab_do_not_move = list() /// other mobs we wont move when we're grab pulled. Not empty only when being grab pulled var/memory = "" var/notransform = FALSE //Carbon /// True for left hand active, otherwise for right hand active