Files
SurvivalOfTheSnippest/level/scripts/hurt_box.gd
T
Scottlg 1562b37563 Gladiator arena: gold economy, outfitting shop, permadeath runs
Turns the sandbox into a survival roguelike loop: outfit your gladiator
with banked gold, enter the arena, earn gold from kills and wave clears,
die, keep 10% of your total value (floored at the 500 fresh-start).

Economy (GameState autoload):
- banked_gold, owned items, and loadout persist to user://save.cfg
- Kill gold (basic 10g, armed 25g) credited server-side to the killer
- Wave-clear bonus (25 + 5/wave) for all players; wave synced to peers
- Death settlement liquidates gear, guarded against double-fire

Character creation / shop:
- Menu reframed: armory shop + live Character Sheet loadout preview
- Character Sheet gains preview mode (renders from loadout, no player)
- Buy/Equip with hand rules; two-handers and off-hands displace each
  other symmetrically (shop and in-game pickups)
- Chosen loadout auto-equips on spawn via existing RPC path

Combat feel:
- Attacks snap to camera facing and lock direction for the swing
- Dash commits to its direction for the full duration
- Weapon slots show name text when no icon is set
- Hitbox/hurtbox debug meshes hidden by default (H toggles)

Death is final: players no longer respawn; a results screen shows waves,
time, kills, and the settlement, then returns to camp. Armed enemies no
longer respawn (were an infinite gold farm and respawned invisible).
2026-07-01 23:38:59 +01:00

95 lines
3.2 KiB
GDScript

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
## Global debug visibility toggle (press H in-game to toggle)
static var debug_visible: bool = false
## 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):
# Update debug visibility
if _debug_mesh:
_debug_mesh.visible = HurtBox.debug_visible
# 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
_debug_mesh.visible = HurtBox.debug_visible
# 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