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.
86 lines
3.0 KiB
86 lines
3.0 KiB
extends Area3D |
|
class_name HurtBox |
|
|
|
## A component that receives damage from HitBoxes |
|
## Attach to any entity that can be damaged (players, enemies, destructibles) |
|
## NOTE: This is a passive detection zone - HitBox handles the collision detection |
|
|
|
## The entity that owns this hurtbox (should be a BaseUnit or similar) |
|
@export var owner_entity: Node = null |
|
## Debug mesh for visualization |
|
var _debug_mesh: MeshInstance3D = null |
|
var _debug_material: StandardMaterial3D = null |
|
var _hit_flash_timer: float = 0.0 |
|
const HIT_FLASH_DURATION: float = 0.3 # seconds |
|
|
|
func _ready(): |
|
# Auto-find owner if not set (traverse up to find BaseUnit) |
|
if owner_entity == null: |
|
var parent = get_parent() |
|
while parent: |
|
if parent is BaseUnit: |
|
owner_entity = parent |
|
break |
|
parent = parent.get_parent() |
|
|
|
# Configure collision - hurtboxes are on layer 5, detect nothing (passive) |
|
collision_layer = 16 # Layer 5 (hurtbox) |
|
collision_mask = 0 # Don't detect anything - hitboxes detect us |
|
|
|
# Ensure we can be detected but don't detect others |
|
monitorable = true |
|
monitoring = false |
|
|
|
# Add debug visualization |
|
_create_debug_visualization() |
|
|
|
func _process(delta): |
|
# Handle hit flash timer |
|
if _hit_flash_timer > 0.0: |
|
_hit_flash_timer -= delta |
|
if _hit_flash_timer <= 0.0: |
|
# Flash finished, return to green |
|
if _debug_material: |
|
_debug_material.albedo_color = Color(0.0, 1.0, 0.0, 0.3) # Green |
|
|
|
func _create_debug_visualization(): |
|
# Find the collision shape to visualize |
|
for child in get_children(): |
|
if child is CollisionShape3D and child.shape: |
|
# Create a semi-transparent green mesh to visualize the hurtbox |
|
_debug_mesh = MeshInstance3D.new() |
|
_debug_material = StandardMaterial3D.new() |
|
_debug_material.albedo_color = Color(0.0, 1.0, 0.0, 0.3) # Green, semi-transparent |
|
_debug_material.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA |
|
_debug_material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED |
|
_debug_material.cull_mode = BaseMaterial3D.CULL_DISABLED # Visible from both sides |
|
|
|
# Create mesh matching the collision shape |
|
var mesh: Mesh = null |
|
if child.shape is BoxShape3D: |
|
var box_mesh = BoxMesh.new() |
|
box_mesh.size = child.shape.size |
|
mesh = box_mesh |
|
elif child.shape is SphereShape3D: |
|
var sphere_mesh = SphereMesh.new() |
|
sphere_mesh.radius = child.shape.radius |
|
sphere_mesh.height = child.shape.radius * 2 |
|
mesh = sphere_mesh |
|
elif child.shape is CapsuleShape3D: |
|
var capsule_mesh = CapsuleMesh.new() |
|
capsule_mesh.radius = child.shape.radius |
|
capsule_mesh.height = child.shape.height |
|
mesh = capsule_mesh |
|
|
|
if mesh: |
|
_debug_mesh.mesh = mesh |
|
_debug_mesh.material_override = _debug_material |
|
# Don't set transform - it inherits from parent CollisionShape3D |
|
child.add_child(_debug_mesh) |
|
break |
|
|
|
## Call this when the hurtbox is hit to flash red |
|
func flash_hit(): |
|
_hit_flash_timer = HIT_FLASH_DURATION |
|
if _debug_material: |
|
_debug_material.albedo_color = Color(1.0, 0.0, 0.0, 0.5) # Red, semi-transparent
|
|
|