extends StaticBody3D class_name TargetDummy var visual_node: Node3D 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) # Humanoid Model visual_node = load("res://characters/humanoid_model.gd").new() visual_node.name = "HumanoidModel" visual_node.color = Color(0.8, 0.2, 0.2) add_child(visual_node) # 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, _impulse: Vector3 = Vector3.ZERO) -> 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.ZERO var wiggle_dir = Vector3(randf_range(-0.1, 0.1), 0, randf_range(-0.1, 0.1)) tween.tween_property(visual_node, "position", orig_pos + wiggle_dir, 0.05) tween.tween_property(visual_node, "position", orig_pos - wiggle_dir, 0.05) tween.tween_property(visual_node, "position", orig_pos, 0.05)