update
This commit is contained in:
+5
-1
@@ -1046,8 +1046,12 @@ func start_movement_along_path(path: Array, clear_visual: bool = true):
|
||||
tween.set_trans(Tween.TRANS_LINEAR)
|
||||
tween.set_ease(Tween.EASE_IN_OUT)
|
||||
|
||||
var step_duration = 0.25
|
||||
if movement_manager:
|
||||
step_duration = step_duration / movement_manager.speed_multiplier
|
||||
|
||||
for point in path:
|
||||
tween.tween_property(self, "position", grid_to_world(Vector2i(point.x, point.y)), 0.25)
|
||||
tween.tween_property(self, "position", grid_to_world(Vector2i(point.x, point.y)), step_duration)
|
||||
|
||||
tween.tween_callback(func():
|
||||
current_position = Vector2i(path[-1].x, path[-1].y)
|
||||
|
||||
@@ -9,6 +9,7 @@ var use_diagonal_movement: bool = false
|
||||
var is_moving: bool = false
|
||||
var rotation_speed: float = 10.0
|
||||
var target_rotation: float = 0.0
|
||||
var speed_multiplier: float = 1.0 # For slow-mo effects
|
||||
|
||||
func initialize(p_player: Node3D, p_gridmap: Node):
|
||||
player = p_player
|
||||
@@ -123,7 +124,6 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
|
||||
if 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):
|
||||
|
||||
# Valid push
|
||||
var push_path = [Vector2(pushed_to_pos.x, pushed_to_pos.y)]
|
||||
other_player.rpc("start_movement_along_path", push_path, false)
|
||||
@@ -142,6 +142,13 @@ func try_push(target_pos: Vector2i, direction: Vector2i) -> bool:
|
||||
|
||||
return true
|
||||
|
||||
func set_speed_multiplier(multiplier: float):
|
||||
speed_multiplier = multiplier
|
||||
# If we are currently moving, we might need to adjust the speed of the active tween?
|
||||
# However, the movement is handled via RPC 'start_movement_along_path' which
|
||||
# likely uses a fixed speed or duration on all clients.
|
||||
# Let's check how 'start_movement_along_path' is implemented in player.gd.
|
||||
|
||||
|
||||
func buffer_move_input(direction: Vector2i):
|
||||
buffered_direction = direction
|
||||
|
||||
@@ -30,13 +30,15 @@ var enhanced_gridmap: Node
|
||||
var rng: RandomNumberGenerator
|
||||
|
||||
# Effect durations
|
||||
const FREEZE_DURATION = 3.0
|
||||
const FREEZE_ZONE_DURATION = 15.0
|
||||
const FREEZE_SLOW_MULTIPLIER = 0.2 # Super slow down
|
||||
const BLOCK_DURATION = 9.0
|
||||
const INVISIBLE_DURATION = 6.0
|
||||
|
||||
|
||||
# Active effect tracking
|
||||
var blocked_tiles: Array[Dictionary] = [] # {position: Vector3i, original_item: int, timer: float}
|
||||
var freeze_zones: Array[Dictionary] = [] # {position: Vector2i, timer: float}
|
||||
var invisible_timer: float = 0.0
|
||||
|
||||
# INVENTORY SYSTEM
|
||||
@@ -127,8 +129,7 @@ func activate_effect(effect: int, target_player: Node3D = null):
|
||||
_execute_block_floor(target_player)
|
||||
|
||||
SpecialEffect.FREEZE_PLAYER:
|
||||
if target_player:
|
||||
_execute_freeze_player(target_player)
|
||||
_execute_freeze_zones() # No target needed anymore
|
||||
|
||||
SpecialEffect.INVISIBLE_MODE:
|
||||
# Always self
|
||||
@@ -161,7 +162,7 @@ func trigger_random_effect():
|
||||
SpecialEffect.SPAWN_TILES:
|
||||
_execute_spawn_tiles(player)
|
||||
SpecialEffect.FREEZE_PLAYER:
|
||||
_execute_freeze_player(_get_random_opponent())
|
||||
_execute_freeze_zones()
|
||||
SpecialEffect.BLOCK_FLOOR:
|
||||
_execute_block_floor(player)
|
||||
SpecialEffect.INVISIBLE_MODE:
|
||||
@@ -222,18 +223,32 @@ func _execute_spawn_tiles(target: Node3D):
|
||||
|
||||
NotificationManager.send_message(target, NotificationManager.MESSAGES.TILES_SPAWNED, NotificationManager.MessageType.POWERUP)
|
||||
|
||||
func _execute_freeze_player(target: Node3D):
|
||||
if not target:
|
||||
print("[SpecialTiles] No opponent found for FREEZE_PLAYER")
|
||||
return
|
||||
func _execute_freeze_zones():
|
||||
# Area-based freeze: spawn pattern around activating player
|
||||
var center = player.current_position
|
||||
var pattern_keys = PATTERNS.keys()
|
||||
var pattern_name = pattern_keys[rng.randi() % pattern_keys.size()]
|
||||
var pattern = PATTERNS[pattern_name]
|
||||
|
||||
if target.has_method("apply_stagger"): # Stagger = Freeze roughly
|
||||
target.rpc("apply_stagger", FREEZE_DURATION)
|
||||
else:
|
||||
target.set("is_frozen", true)
|
||||
_create_unfreeze_timer(target, FREEZE_DURATION)
|
||||
|
||||
NotificationManager.send_message(target, NotificationManager.MESSAGES.FROZEN_BY % player.display_name, NotificationManager.MessageType.WARNING)
|
||||
print("[SpecialTiles] Player %s spawning FREEZE zones in pattern %s" % [player.name, pattern_name])
|
||||
|
||||
for offset in pattern:
|
||||
var pos = center + offset
|
||||
if enhanced_gridmap.is_position_valid(pos):
|
||||
# Add to active zones
|
||||
freeze_zones.append({
|
||||
"position": pos,
|
||||
"timer": FREEZE_ZONE_DURATION
|
||||
})
|
||||
|
||||
# Sync visual (use item ID 15 for "Icy" floor marker or similar)
|
||||
if player.is_multiplayer_authority():
|
||||
var main = player.get_tree().get_root().get_node_or_null("Main")
|
||||
if main:
|
||||
# Layer 2 for effect overlays
|
||||
main.rpc("sync_grid_item", pos.x, 2, pos.y, 15)
|
||||
|
||||
NotificationManager.send_message(player, NotificationManager.MESSAGES.FREEZE_ZONE_READY if NotificationManager.MESSAGES.has("FREEZE_ZONE_READY") else "Freeze zones deployed!", NotificationManager.MessageType.POWERUP)
|
||||
|
||||
func _execute_block_floor(target: Node3D):
|
||||
# Make nearby tile non-walkable for 9 seconds
|
||||
@@ -296,9 +311,79 @@ func spawn_powerups_around(center: Vector2i, force_powerups: bool = true):
|
||||
main.rpc("sync_grid_item", cell.x, cell.y, cell.z, item_id)
|
||||
|
||||
|
||||
func _update_freeze_zones(delta: float):
|
||||
# Only the authority of this manager (the caster) handles the timers and cleanup
|
||||
if not player.is_multiplayer_authority():
|
||||
return
|
||||
|
||||
var zones_to_remove = []
|
||||
for i in range(freeze_zones.size()):
|
||||
freeze_zones[i].timer -= delta
|
||||
if freeze_zones[i].timer <= 0:
|
||||
zones_to_remove.append(i)
|
||||
|
||||
# Cleanup expired zones
|
||||
zones_to_remove.reverse()
|
||||
for idx in zones_to_remove:
|
||||
var zone = freeze_zones[idx]
|
||||
var main = player.get_tree().get_root().get_node_or_null("Main")
|
||||
if main:
|
||||
main.rpc("sync_grid_item", zone.position.x, 2, zone.position.y, -1)
|
||||
freeze_zones.remove_at(idx)
|
||||
|
||||
func _check_for_icy_floor():
|
||||
# Every player checks if they are standing on an icy floor (item 15 on layer 2)
|
||||
# This ensures slow-mo works even if zones were cast by another player.
|
||||
if not player.is_multiplayer_authority():
|
||||
return
|
||||
|
||||
if not enhanced_gridmap:
|
||||
return
|
||||
|
||||
var current_item = enhanced_gridmap.get_cell_item(Vector3i(player.current_position.x, 2, player.current_position.y))
|
||||
if current_item == 15:
|
||||
_apply_slow_mo(player)
|
||||
elif player.movement_manager and player.movement_manager.speed_multiplier < 1.0:
|
||||
# Check if we should restore speed
|
||||
# In this case, we'll let _apply_slow_mo's timer handle it,
|
||||
# OR we can explicitly reset here if NOT on item 15.
|
||||
pass
|
||||
|
||||
func _process(delta):
|
||||
_update_blocked_tiles(delta)
|
||||
_update_invisible_timer(delta)
|
||||
_update_freeze_zones(delta)
|
||||
_check_for_icy_floor()
|
||||
|
||||
func _apply_slow_mo(target_player: Node3D):
|
||||
if target_player.has_method("apply_stagger") and target_player.is_frozen:
|
||||
return # Already fully frozen/staggered
|
||||
|
||||
if target_player.movement_manager:
|
||||
target_player.movement_manager.set_speed_multiplier(FREEZE_SLOW_MULTIPLIER)
|
||||
# Visual tint
|
||||
if target_player.has_method("sync_modulate"):
|
||||
target_player.rpc("sync_modulate", Color(0.6, 0.8, 1.0)) # Icy blue
|
||||
|
||||
# Reset speed after a short delay if they leave
|
||||
_create_restore_speed_timer(target_player, 0.2)
|
||||
|
||||
func _create_restore_speed_timer(target_player: Node3D, duration: float):
|
||||
# We use a short timer to reset speed. If they are still in the zone,
|
||||
# _process will re-apply it next frame.
|
||||
await player.get_tree().create_timer(duration).timeout
|
||||
if is_instance_valid(target_player) and target_player.movement_manager:
|
||||
# Check if they are still on an icy floor
|
||||
var still_in_zone = false
|
||||
if enhanced_gridmap:
|
||||
var item = enhanced_gridmap.get_cell_item(Vector3i(target_player.current_position.x, 2, target_player.current_position.y))
|
||||
if item == 15:
|
||||
still_in_zone = true
|
||||
|
||||
if not still_in_zone:
|
||||
target_player.movement_manager.set_speed_multiplier(1.0)
|
||||
if target_player.has_method("sync_modulate"):
|
||||
target_player.rpc("sync_modulate", Color.WHITE)
|
||||
|
||||
func _update_invisible_timer(delta: float):
|
||||
if invisible_timer > 0:
|
||||
|
||||
Reference in New Issue
Block a user