feat: Add PlayerMovementManager to centralize player movement logic and implement a 'SUPER PUSH' attack mechanic.
This commit is contained in:
@@ -78,24 +78,7 @@ func simple_move_to(grid_position: Vector2i) -> bool:
|
|||||||
return false
|
return false
|
||||||
|
|
||||||
# PHYSICS CHECK: Ensure no static obstacles (like Stands) are blocking the path
|
# PHYSICS CHECK: Ensure no static obstacles (like Stands) are blocking the path
|
||||||
# GridMap logic handles cells, but Objects/Bodies might be placed on top (like StaticTektonStand)
|
if _is_position_blocked_by_physics(grid_position):
|
||||||
var space_state = player.get_world_3d().direct_space_state
|
|
||||||
# RAYCAST HEIGHT: 0.3 (Center of the 0.6m tall stand)
|
|
||||||
# Check from CENTER using +0.5
|
|
||||||
var from = Vector3(player.current_position.x + 0.5, 0.3, player.current_position.y + 0.5)
|
|
||||||
var to = Vector3(grid_position.x + 0.5, 0.3, grid_position.y + 0.5)
|
|
||||||
|
|
||||||
# Check center of target tile
|
|
||||||
var query = PhysicsRayQueryParameters3D.create(from, to)
|
|
||||||
query.collide_with_areas = false
|
|
||||||
query.collide_with_bodies = true
|
|
||||||
# query.collision_mask = 1 # Default mask usually covers static bodies
|
|
||||||
|
|
||||||
var result = space_state.intersect_ray(query)
|
|
||||||
if result:
|
|
||||||
# If we hit something static that isn't ourselves
|
|
||||||
if result.collider != player:
|
|
||||||
print("Movement Blocked by Physics Body: ", result.collider.name)
|
|
||||||
return false
|
return false
|
||||||
|
|
||||||
if player.is_position_occupied(grid_position):
|
if player.is_position_occupied(grid_position):
|
||||||
@@ -158,9 +141,11 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
|
|||||||
# 3. Knockback / Stagger
|
# 3. Knockback / Stagger
|
||||||
# Push them away
|
# Push them away
|
||||||
var pushed_to_pos = target_pos + direction
|
var pushed_to_pos = target_pos + direction
|
||||||
if enhanced_gridmap.is_position_valid(pushed_to_pos) and \
|
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 \
|
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):
|
not player.is_position_occupied(pushed_to_pos) and \
|
||||||
|
not _is_position_blocked_by_physics(pushed_to_pos):
|
||||||
# Valid push
|
# Valid push
|
||||||
var push_path = [Vector2(pushed_to_pos.x, pushed_to_pos.y)]
|
var push_path = [Vector2(pushed_to_pos.x, pushed_to_pos.y)]
|
||||||
other_player.rpc("start_movement_along_path", push_path, false)
|
other_player.rpc("start_movement_along_path", push_path, false)
|
||||||
@@ -404,3 +389,47 @@ func highlight_adjacent_cells():
|
|||||||
cells_to_highlight.append(cell_pos)
|
cells_to_highlight.append(cell_pos)
|
||||||
|
|
||||||
player.highlight_cells_if_authorized(cells_to_highlight)
|
player.highlight_cells_if_authorized(cells_to_highlight)
|
||||||
|
|
||||||
|
func _is_position_in_static_stand_area(pos: Vector2i) -> bool:
|
||||||
|
# Check against all known Static Tekton Stands (3x3 areas)
|
||||||
|
var stands = player.get_tree().get_nodes_in_group("StaticTektonStands")
|
||||||
|
print("[Debug] Checking Push Prevention for %s. Found %d stands." % [pos, stands.size()])
|
||||||
|
|
||||||
|
for stand in stands:
|
||||||
|
if not enhanced_gridmap: continue
|
||||||
|
|
||||||
|
# Convert world to grid. Use global_position just to be safe.
|
||||||
|
var local_pos = enhanced_gridmap.to_local(stand.global_position)
|
||||||
|
var stand_grid_pos = enhanced_gridmap.local_to_map(local_pos)
|
||||||
|
|
||||||
|
# Stand is centered, so key check is 3x3 around it
|
||||||
|
var center = Vector2i(stand_grid_pos.x, stand_grid_pos.z)
|
||||||
|
|
||||||
|
# Check if pos is right on top of stand (distance 0) or adjacent (distance 1)
|
||||||
|
# Chebyshev distance <= 1 means 3x3 square
|
||||||
|
if abs(pos.x - center.x) <= 1 and abs(pos.y - center.y) <= 1:
|
||||||
|
print(" - BLOCKED by Stand at %s (Center: %s)" % [stand.name, center])
|
||||||
|
return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
|
||||||
|
func _is_position_blocked_by_physics(target_pos: Vector2i) -> bool:
|
||||||
|
if not player.is_inside_tree(): return false
|
||||||
|
|
||||||
|
var space_state = player.get_world_3d().direct_space_state
|
||||||
|
var center_x = target_pos.x + 0.5
|
||||||
|
var center_z = target_pos.y + 0.5
|
||||||
|
var from = Vector3(center_x, 1.0, center_z)
|
||||||
|
var to = Vector3(center_x, 0.1, center_z)
|
||||||
|
|
||||||
|
var query = PhysicsRayQueryParameters3D.create(from, to)
|
||||||
|
query.collide_with_areas = false
|
||||||
|
query.collide_with_bodies = true
|
||||||
|
|
||||||
|
var result = space_state.intersect_ray(query)
|
||||||
|
if result:
|
||||||
|
if result.collider != player:
|
||||||
|
# print("Movement Blocked by Physics Body: ", result.collider.name)
|
||||||
|
return true
|
||||||
|
|
||||||
|
return false
|
||||||
|
|||||||
@@ -10,6 +10,8 @@ extends StaticBody3D
|
|||||||
_update_mesh_from_index()
|
_update_mesh_from_index()
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
|
add_to_group("StaticTektonStands")
|
||||||
|
print("Static Stand Ready: ", name)
|
||||||
if multiplayer.is_server():
|
if multiplayer.is_server():
|
||||||
# Only randomize if not already set (Main.gd sets it now)
|
# Only randomize if not already set (Main.gd sets it now)
|
||||||
if shape_index == -1:
|
if shape_index == -1:
|
||||||
|
|||||||
Reference in New Issue
Block a user