feat: implement damage dummy system, floating UI numbers, and double-barrel shotgun mechanics

This commit is contained in:
DottsGit
2026-06-04 13:15:26 -04:00
parent d8cb91e593
commit a8b3619f2e
7 changed files with 206 additions and 0 deletions
+85
View File
@@ -0,0 +1,85 @@
extends StaticBody3D
class_name TargetDummy
var mesh_instance: MeshInstance3D
var dps_label: Label3D
# Array of dictionaries: { "time": float, "amount": float }
var damage_history: Array = []
func _ready() -> void:
add_to_group("enemies") # Just in case we need to filter
# Collision Shape
var shape = CollisionShape3D.new()
shape.shape = CapsuleShape3D.new()
shape.shape.radius = 0.5
shape.shape.height = 2.0
shape.position = Vector3(0, 1.0, 0)
add_child(shape)
# Mesh
mesh_instance = MeshInstance3D.new()
var mesh = CapsuleMesh.new()
mesh.radius = 0.5
mesh.height = 2.0
mesh_instance.mesh = mesh
var mat = StandardMaterial3D.new()
mat.albedo_color = Color(0.8, 0.2, 0.2) # Red dummy
mat.roughness = 0.7
mesh.material = mat
mesh_instance.position = Vector3(0, 1.0, 0)
add_child(mesh_instance)
# DPS Label
dps_label = Label3D.new()
dps_label.text = "DPS: 0"
dps_label.pixel_size = 0.01
dps_label.billboard = BaseMaterial3D.BILLBOARD_ENABLED
dps_label.position = Vector3(0, 2.3, 0)
dps_label.modulate = Color(1, 0.8, 0)
add_child(dps_label)
func take_damage(amount: float, hit_position: Vector3, source: Node = null) -> void:
var now = Time.get_ticks_msec() / 1000.0
damage_history.append({"time": now, "amount": amount})
if source and source.has_method("spawn_damage_number"):
source.spawn_damage_number(amount, hit_position)
_wiggle()
func _process(_delta: float) -> void:
_update_dps()
func _update_dps() -> void:
var now = Time.get_ticks_msec() / 1000.0
var total_damage: float = 0.0
# Keep only last 5 seconds
var valid_history = []
for dmg in damage_history:
if now - dmg["time"] <= 5.0:
valid_history.append(dmg)
total_damage += dmg["amount"]
damage_history = valid_history
if damage_history.size() > 0:
var dps = total_damage / 5.0
dps_label.text = "DPS: %.1f" % dps
else:
dps_label.text = "DPS: 0"
func _wiggle() -> void:
# Small tween to shake the dummy
var tween = create_tween()
var orig_pos = Vector3(0, 1.0, 0)
var wiggle_dir = Vector3(randf_range(-0.1, 0.1), 0, randf_range(-0.1, 0.1))
tween.tween_property(mesh_instance, "position", orig_pos + wiggle_dir, 0.05)
tween.tween_property(mesh_instance, "position", orig_pos - wiggle_dir, 0.05)
tween.tween_property(mesh_instance, "position", orig_pos, 0.05)