feat: implement damage dummy system, floating UI numbers, and double-barrel shotgun mechanics
This commit is contained in:
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user