MultiplayerFighter
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

113 lines
3.1 KiB

extends BaseEnemy
class_name PracticeDummy
## A stationary practice dummy for testing combat
## Cannot move or attack - just takes damage and shows health
## Visual mesh reference
@onready var _mesh: MeshInstance3D = null
## Health label above dummy
@onready var _health_label: Label3D = null
## Original material for hit flash effect
var _original_material: Material = null
## Hit flash effect
var _hit_flash_timer: float = 0.0
const HIT_FLASH_DURATION: float = 0.2
func _ready():
super._ready()
# Practice dummy should not be aggressive
is_aggressive = false
# Auto-find mesh and health label
_mesh = get_node_or_null("Mesh")
_health_label = get_node_or_null("HealthLabel")
# Store original material for flash effect
if _mesh:
_original_material = _mesh.get_surface_override_material(0)
if not _original_material and _mesh.mesh:
_original_material = _mesh.mesh.surface_get_material(0)
# Update initial health display
_update_health_display()
# Connect health change to update display
health_changed.connect(_on_health_display_changed)
func _process(delta):
# Handle hit flash timer
if _hit_flash_timer > 0:
_hit_flash_timer -= delta
if _hit_flash_timer <= 0:
_reset_material()
func _physics_process(delta):
# Don't call super._physics_process since we don't move
# Just apply gravity
if not is_on_floor():
velocity.y -= ProjectSettings.get_setting("physics/3d/default_gravity") * delta
move_and_slide()
## Update health display
func _update_health_display():
if _health_label:
_health_label.text = "HP: %d/%d" % [int(current_health), int(max_health)]
func _on_health_display_changed(_old_health: float, _new_health: float):
_update_health_display()
## Override hurt animation to flash red
@rpc("any_peer", "call_local", "reliable")
func _play_hurt_animation():
if _mesh:
_flash_red()
## Flash the dummy red when hit
func _flash_red():
if not _mesh:
return
_hit_flash_timer = HIT_FLASH_DURATION
# Create red material
var red_material = StandardMaterial3D.new()
red_material.albedo_color = Color(1.5, 0.3, 0.3) # Bright red
# Copy properties from original if it exists
if _original_material and _original_material is StandardMaterial3D:
var orig = _original_material as StandardMaterial3D
red_material.metallic = orig.metallic
red_material.roughness = orig.roughness
red_material.albedo_texture = orig.albedo_texture
_mesh.set_surface_override_material(0, red_material)
## Reset to original material
func _reset_material():
if _mesh and _original_material:
_mesh.set_surface_override_material(0, _original_material.duplicate())
## Override death to just hide the mesh
func _on_enemy_died(killer_id: int):
super._on_enemy_died(killer_id)
# Hide mesh when dead
if _mesh:
_mesh.visible = false
print("[PracticeDummy] Killed by player ", killer_id, ". Respawning in ", respawn_delay, " seconds...")
## Override respawn to show mesh again
func _on_enemy_respawned():
super._on_enemy_respawned()
# Show mesh when respawned
if _mesh:
_mesh.visible = true
_reset_material()
_update_health_display()
print("[PracticeDummy] Respawned!")