replace with multiplayer-coop files

This commit is contained in:
2026-01-08 16:47:52 +01:00
parent 1725c615ce
commit 22c7025ac4
1230 changed files with 20555 additions and 17232 deletions

158
src/scripts/enemy_bat.gd Normal file
View File

@@ -0,0 +1,158 @@
extends "res://scripts/enemy_base.gd"
# Bat Enemy - Flies around, stationary when idle
enum BatState { IDLE, FLYING }
var state: BatState = BatState.IDLE
var state_timer: float = 0.0
var idle_duration: float = 2.0 # How long to stay idle
var fly_duration: float = 3.0 # How long to fly around
var detection_range: float = 80.0 # Range to detect players (much smaller)
var fly_height: float = 8.0 # Z position when flying
func _ready():
super._ready()
max_health = 30.0
current_health = max_health
move_speed = 40.0 # Reasonable speed for bats
damage = 5.0
state_timer = idle_duration
func _physics_process(delta):
# Always update animation (even when dead, and on clients)
_update_animation(delta)
# Always update Z position and shadow (even on clients)
_update_z_position(delta)
# Call parent physics process (handles dead state, authority checks, etc.)
super._physics_process(delta)
func _ai_behavior(delta):
# Update state timer
state_timer -= delta
# Find nearest player within detection range
target_player = _find_nearest_player_in_range(detection_range)
# State machine
match state:
BatState.IDLE:
_idle_behavior(delta)
BatState.FLYING:
_flying_behavior(delta)
# Animation and Z position are updated in _physics_process (always, even on clients)
func _idle_behavior(_delta):
velocity = Vector2.ZERO
position_z = 0.0
# Show idle frame (frame 2)
anim_frame = 2
# Check if player is nearby
if target_player:
var dist = global_position.distance_to(target_player.global_position)
if dist < detection_range:
# Start flying
state = BatState.FLYING
state_timer = fly_duration
return
# Switch to flying after idle duration
if state_timer <= 0:
state = BatState.FLYING
state_timer = fly_duration
func _flying_behavior(_delta):
position_z = fly_height
# Fly towards player if found
if target_player and is_instance_valid(target_player):
var direction = (target_player.global_position - global_position).normalized()
velocity = direction * move_speed
current_direction = _get_direction_from_vector(direction)
else:
# Wander randomly
if randf() < 0.02: # Small chance to change direction
var random_dir = Vector2(randf() - 0.5, randf() - 0.5).normalized()
velocity = random_dir * move_speed
current_direction = _get_direction_from_vector(random_dir)
# Switch back to idle after flying duration
if state_timer <= 0:
state = BatState.IDLE
state_timer = idle_duration
func _update_animation(delta):
if state == BatState.IDLE:
# Show idle frame
anim_frame = 2
else:
# Animate flying (frames 0, 1, 2)
anim_time += delta
if anim_time >= anim_speed:
anim_time = 0.0
anim_frame = (anim_frame + 1) % 3
# Map 8 directions to 4 sprite directions
var sprite_dir = _get_sprite_direction()
# Set sprite frame
if sprite:
sprite.frame = anim_frame + (sprite_dir * 3) # 3 frames per direction
func _get_sprite_direction() -> int:
# Map 8 directions to 4 sprite rows
match current_direction:
Direction.DOWN, Direction.DOWN_LEFT, Direction.DOWN_RIGHT:
return 0 # Down row
Direction.LEFT, Direction.UP_LEFT:
return 1 # Left row
Direction.RIGHT, Direction.UP_RIGHT:
return 2 # Right row
Direction.UP:
return 3 # Up row
return 0
func _update_z_position(_delta):
# Update sprite Y offset based on height
if sprite:
sprite.position.y = -position_z * 0.5
# Update shadow based on height
if shadow:
var shadow_scale = 1.0 - (position_z / 50.0) * 0.5
shadow.scale = Vector2.ONE * max(0.3, shadow_scale) * Vector2(0.8, 0.4)
shadow.modulate.a = 0.5 - (position_z / 50.0) * 0.2
func _update_client_visuals():
# Update visuals on clients based on synced state
super._update_client_visuals()
# Update animation based on synced state
_update_animation(0.0) # Update animation immediately when state changes
# Update sprite frame based on synced anim_frame and direction
if sprite:
var sprite_dir = _get_sprite_direction()
sprite.frame = anim_frame + (sprite_dir * 3) # 3 frames per direction
func _play_death_animation():
# Fall to ground
var fall_tween = create_tween()
fall_tween.tween_property(self, "position_z", 0.0, 0.3)
await fall_tween.finished
# Fade out
var fade_tween = create_tween()
fade_tween.tween_property(sprite, "modulate:a", 0.0, 0.3)
await fade_tween.finished
queue_free()