Movements outside grab range stops grab, grab pull refactor (#21956)

* grab target move signal checker

* moved grab proc into grab class, changed pulling grabbed person handling into signals from assailant, added movetime to SEND_SIGNAL on COMSIG_MOVABLE_MOVED as 4-th argument

* refactor p1

* changed pull_grabbed proc, removed unused variable

* Empty-Commit

* Update code/modules/mob/mob_grab.dm

Co-authored-by: Farie82 <farie82@users.noreply.github.com>

* neck grab facing back works again

* directionals on move again

* fixed direction works again

* glide speed good now, flips working again

* death

* fixing neck grab issue

* Update code/modules/mob/mob_grab.dm

Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>

* Update code/modules/mob/mob_grab.dm

Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>

* dead code gone

* I HATE DIAGONAL MOVEMENT

* signal handlers added

* pull support, best pull turfs only today

---------

Co-authored-by: S34N <12197162+S34NW@users.noreply.github.com>
Co-authored-by: Farie82 <farie82@users.noreply.github.com>
Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
This commit is contained in:
HMBGERDO
2023-12-11 18:31:56 +01:00
committed by GitHub
parent 42de9cede7
commit 7a1e8e8f97
5 changed files with 93 additions and 82 deletions
-56
View File
@@ -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
+88 -21
View File
@@ -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
+2 -4
View File
@@ -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 && .)
+1 -1
View File
@@ -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