feat: Add PlayerMovementManager for grid-based movement, rotation, and player-to-player push mechanics.
This commit is contained in:
@@ -176,11 +176,27 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
|
||||
# 3. Knockback / Stagger
|
||||
# Push them away
|
||||
var pushed_to_pos = target_pos + direction
|
||||
if not _is_position_in_static_stand_area(pushed_to_pos) and \
|
||||
enhanced_gridmap.is_position_valid(pushed_to_pos) and \
|
||||
enhanced_gridmap.get_cell_item(Vector3i(pushed_to_pos.x, 0, pushed_to_pos.y)) != -1 and \
|
||||
not player.is_position_occupied(pushed_to_pos) and \
|
||||
not _is_position_blocked_by_physics(pushed_to_pos):
|
||||
|
||||
# IMPROVED: Check if destination is valid and walkable to prevent being stuck on 'blocks'
|
||||
var is_dest_valid = _can_push_to(pushed_to_pos)
|
||||
|
||||
# DEFLECTION LOGIC: If direct path is blocked, try diagonal deflection
|
||||
if not is_dest_valid:
|
||||
var alts = []
|
||||
if direction.x != 0 and direction.y == 0: # Horizontal push -> try diagonal North/South
|
||||
alts = [pushed_to_pos + Vector2i(0, 1), pushed_to_pos + Vector2i(0, -1)]
|
||||
elif direction.y != 0 and direction.x == 0: # Vertical push -> try diagonal East/West
|
||||
alts = [pushed_to_pos + Vector2i(1, 0), pushed_to_pos + Vector2i(-1, 0)]
|
||||
elif direction.x != 0 and direction.y != 0: # Diagonal push -> try horizontal/vertical components
|
||||
alts = [pushed_to_pos - Vector2i(direction.x, 0), pushed_to_pos - Vector2i(0, direction.y)]
|
||||
|
||||
for alt in alts:
|
||||
if _can_push_to(alt):
|
||||
pushed_to_pos = alt
|
||||
is_dest_valid = true
|
||||
break
|
||||
|
||||
if is_dest_valid:
|
||||
# Valid push
|
||||
var push_path = [Vector2(pushed_to_pos.x, pushed_to_pos.y)]
|
||||
if _can_rpc():
|
||||
@@ -192,7 +208,7 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
|
||||
other_player.rpc("apply_stagger", 1.5)
|
||||
|
||||
else:
|
||||
# Wall/Blocked -> Stagger in place
|
||||
# Wall/Blocked -> Stagger in place (Only if no alternatives found)
|
||||
if _can_rpc():
|
||||
other_player.rpc("apply_stagger", 1.5)
|
||||
|
||||
@@ -460,6 +476,27 @@ func _is_position_in_static_stand_area(pos: Vector2i) -> bool:
|
||||
|
||||
return false
|
||||
|
||||
func _can_push_to(pos: Vector2i) -> bool:
|
||||
"""Helper to validate if a grid position is a safe landing spot for a push."""
|
||||
if not enhanced_gridmap or not enhanced_gridmap.is_position_valid(pos):
|
||||
return false
|
||||
|
||||
var cell_item = enhanced_gridmap.get_cell_item(Vector3i(pos.x, 0, pos.y))
|
||||
# Must be walkable and NOT in non_walkable_items (to prevent getting stuck on walls/blocks)
|
||||
if cell_item == -1 or cell_item in enhanced_gridmap.non_walkable_items:
|
||||
return false
|
||||
|
||||
if player.is_position_occupied(pos):
|
||||
return false
|
||||
|
||||
if _is_position_in_static_stand_area(pos):
|
||||
return false
|
||||
|
||||
if _is_position_blocked_by_physics(pos):
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
func _is_position_blocked_by_physics(target_pos: Vector2i) -> bool:
|
||||
if not player.is_inside_tree(): return false
|
||||
|
||||
|
||||
Reference in New Issue
Block a user