Damage numbers and knockback
This commit is contained in:
@@ -26,7 +26,7 @@ func _enter_tree():
|
||||
## Take damage from an attacker
|
||||
## Should only be called on the server for authority
|
||||
@rpc("any_peer", "reliable")
|
||||
func take_damage(amount: float, attacker_id: int = -1):
|
||||
func take_damage(amount: float, attacker_id: int = -1, knockback: float = 0.0, attacker_pos: Vector3 = Vector3.ZERO):
|
||||
# Only server can process damage
|
||||
if not multiplayer.is_server():
|
||||
return
|
||||
@@ -36,10 +36,14 @@ func take_damage(amount: float, attacker_id: int = -1):
|
||||
|
||||
# Apply blocking reduction if applicable (duck typing - check if method exists)
|
||||
var final_damage = amount
|
||||
var final_knockback = knockback
|
||||
var was_blocked = false
|
||||
if has_method("get_block_reduction"):
|
||||
var block_reduction = call("get_block_reduction")
|
||||
if block_reduction > 0.0:
|
||||
final_damage = amount * (1.0 - block_reduction)
|
||||
final_knockback = knockback * (1.0 - block_reduction) # Reduce knockback too
|
||||
was_blocked = true
|
||||
print("Blocked! Damage reduced from ", amount, " to ", final_damage, " (", block_reduction * 100, "% reduction)")
|
||||
|
||||
var old_health = current_health
|
||||
@@ -49,6 +53,18 @@ func take_damage(amount: float, attacker_id: int = -1):
|
||||
rpc("sync_health", current_health)
|
||||
health_changed.emit(old_health, current_health)
|
||||
|
||||
# Show damage number on all clients
|
||||
rpc("_show_damage_number", final_damage, was_blocked)
|
||||
|
||||
# Play hurt animation on all clients
|
||||
rpc("_play_hurt_animation")
|
||||
|
||||
# Apply knockback if applicable
|
||||
if final_knockback > 0.0 and attacker_pos != Vector3.ZERO:
|
||||
var knockback_dir = (global_position - attacker_pos).normalized()
|
||||
knockback_dir.y = 0.3 # Slight upward component
|
||||
rpc("_apply_knockback", knockback_dir * final_knockback)
|
||||
|
||||
if current_health <= 0:
|
||||
_die(attacker_id)
|
||||
|
||||
@@ -123,3 +139,36 @@ func set_respawn_point(point: Vector3):
|
||||
## Get health percentage (0.0 to 1.0)
|
||||
func get_health_percent() -> float:
|
||||
return current_health / max_health if max_health > 0 else 0.0
|
||||
|
||||
## Show floating damage number
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
func _show_damage_number(damage: float, was_blocked: bool):
|
||||
print("Spawning damage number: ", damage, " blocked: ", was_blocked, " on peer: ", multiplayer.get_unique_id())
|
||||
|
||||
# Create damage number label
|
||||
var damage_label = Label3D.new()
|
||||
var damage_script = load("res://level/scripts/damage_number.gd")
|
||||
damage_label.set_script(damage_script)
|
||||
|
||||
# Position above the character
|
||||
damage_label.position = global_position + Vector3(0, 2.5, 0)
|
||||
|
||||
# Add to scene (not as child of this node, so it doesn't get affected by player movement)
|
||||
get_tree().get_current_scene().add_child(damage_label)
|
||||
|
||||
# Set damage value and color
|
||||
damage_label.call("set_damage", damage, was_blocked)
|
||||
|
||||
## Apply knockback force
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
func _apply_knockback(knockback_velocity: Vector3):
|
||||
# Only applies to CharacterBody3D (players)
|
||||
if self is CharacterBody3D:
|
||||
velocity += knockback_velocity
|
||||
print("Applied knockback: ", knockback_velocity)
|
||||
|
||||
## Play hurt animation (override in subclasses)
|
||||
@rpc("any_peer", "call_local", "reliable")
|
||||
func _play_hurt_animation():
|
||||
# Subclasses should implement this
|
||||
pass
|
||||
|
||||
Reference in New Issue
Block a user