feat: Introduce special tile power-up system, managing inventory, levels, cooldowns, and targeted effects like area freeze and block floor.
This commit is contained in:
@@ -380,6 +380,11 @@ func _execute_block_floor(target_pos: Vector2i):
|
||||
|
||||
for n in neighbors:
|
||||
var pos = n.position
|
||||
|
||||
# PHYSICS CHECK
|
||||
if _is_position_blocked_by_stand(pos):
|
||||
continue
|
||||
|
||||
var block_pos = Vector3i(pos.x, 0, pos.y)
|
||||
|
||||
# Check current item first
|
||||
@@ -437,6 +442,10 @@ func spawn_powerups_around(center: Vector2i, force_powerups: bool = true):
|
||||
for x in range(-radius, radius + 1):
|
||||
for y in range(-radius, radius + 1):
|
||||
var pos = center + Vector2i(x, y)
|
||||
|
||||
if _is_position_blocked_by_stand(pos):
|
||||
continue
|
||||
|
||||
if enhanced_gridmap.is_position_valid(pos):
|
||||
# Random chance to spawn ANYTHING at this spot (keep density reasonable)
|
||||
if rng.randf() > 0.5: continue
|
||||
@@ -640,4 +649,24 @@ func _create_unfreeze_timer(target_player: Node3D, duration: float):
|
||||
# Reset visuals
|
||||
if target_player.has_method("sync_modulate"):
|
||||
target_player.rpc("sync_modulate", Color.WHITE)
|
||||
NotificationManager.send_message(target_player, NotificationManager.MESSAGES.UNFROZEN, NotificationManager.MessageType.NORMAL)
|
||||
NotificationManager.send_message(target_player, "You are no longer frozen!", NotificationManager.MessageType.NORMAL)
|
||||
|
||||
func _is_position_blocked_by_stand(target_pos: Vector2i) -> bool:
|
||||
if not player: return false
|
||||
|
||||
# Raycast check for Static Tekton Stand
|
||||
# Check CENTER of tile (x+0.5) at LOW height (0.3)
|
||||
var from = Vector3(target_pos.x + 0.5, 0.3, target_pos.y + 0.5) + Vector3.UP * 2.0
|
||||
var to = Vector3(target_pos.x + 0.5, 0.3, target_pos.y + 0.5) + Vector3.DOWN * 2.0
|
||||
|
||||
var query = PhysicsRayQueryParameters3D.create(from, to)
|
||||
query.collide_with_areas = false
|
||||
query.collide_with_bodies = true
|
||||
|
||||
var space_state = player.get_world_3d().direct_space_state
|
||||
var result = space_state.intersect_ray(query)
|
||||
|
||||
if result:
|
||||
if result.collider != player:
|
||||
return true
|
||||
return false
|
||||
|
||||
@@ -107,6 +107,11 @@ func _find_empty_tile() -> Vector2i:
|
||||
# Check range logic (Euclidean or Manhattan?)
|
||||
if Vector2(x, y).distance_to(Vector2(center.x, center.y)) > throw_range: continue
|
||||
|
||||
# EXPLICITLY EXCLUDE 3x3 BASE AREA (Tekton Stand)
|
||||
# The stand occupies [center-1, center+1]. We must NOT spawn here.
|
||||
if abs(x - center.x) <= 1 and abs(y - center.y) <= 1:
|
||||
continue
|
||||
|
||||
# Check if empty (Layer 1 has no item)
|
||||
if enhanced_gridmap.get_cell_item(Vector3i(x, 1, y)) == -1:
|
||||
# Also check floor exist? (Layer 0)
|
||||
|
||||
@@ -283,6 +283,10 @@ func temporarily_change_floor(center: Vector2i, radius: int, new_id: int, durati
|
||||
for x in range(-radius, radius + 1):
|
||||
for y in range(-radius, radius + 1):
|
||||
var pos = center + Vector2i(x, y)
|
||||
|
||||
if _is_position_blocked_by_stand(pos):
|
||||
continue
|
||||
|
||||
if enhanced_gridmap.is_position_valid(pos):
|
||||
var cell_3d = Vector3i(pos.x, 0, pos.y)
|
||||
var original = enhanced_gridmap.get_cell_item(cell_3d)
|
||||
@@ -355,6 +359,10 @@ func spawn_tiles_around(count: int = 4):
|
||||
# Maybe avoid center.
|
||||
if x == 0 and y == 0: continue
|
||||
|
||||
# PHYSICS CHECK: Block spawning on Static Stands
|
||||
if _is_position_blocked_by_stand(pos):
|
||||
continue
|
||||
|
||||
if enhanced_gridmap.is_position_valid(pos):
|
||||
# 50% chance to spawn something
|
||||
if rng.randf() > 0.5: continue
|
||||
@@ -425,3 +433,24 @@ func play_animation(anim_name: String):
|
||||
print_tree_pretty()
|
||||
else:
|
||||
print("[Tekton] Animation '%s' NOT FOUND in AnimationPlayer!" % anim_name)
|
||||
|
||||
func _is_position_blocked_by_stand(target_pos: Vector2i) -> bool:
|
||||
# Raycast check for Static Tekton Stand (Layer 1, Body)
|
||||
# Check CENTER of tile (x+0.5) at LOW height (0.3)
|
||||
var from = Vector3(target_pos.x + 0.5, 0.3, target_pos.y + 0.5) + Vector3.UP * 2.0
|
||||
var to = Vector3(target_pos.x + 0.5, 0.3, target_pos.y + 0.5) + Vector3.DOWN * 2.0
|
||||
|
||||
# We perform a vertical raycast through the potential stand volume
|
||||
var query = PhysicsRayQueryParameters3D.create(from, to)
|
||||
query.collide_with_areas = false
|
||||
query.collide_with_bodies = true
|
||||
|
||||
var space_state = get_world_3d().direct_space_state
|
||||
var result = space_state.intersect_ray(query)
|
||||
|
||||
if result:
|
||||
# If we hit something not ourselves/player, assume it's a stand/blocker
|
||||
if result.collider != self:
|
||||
return true
|
||||
|
||||
return false
|
||||
|
||||
Reference in New Issue
Block a user