From 7defac68c43b4ebd9c9ac49b2e387c05f8d2348e Mon Sep 17 00:00:00 2001 From: Dominic Masters Date: Sun, 11 Jan 2026 20:08:44 -0600 Subject: [PATCH] Example damage label --- battle/Battle.gd | 6 ++++ battle/BattleScene.tscn | 26 +++++++------- battle/fighter/BattleFighter.gd | 12 +++---- battle/fighter/BattleFighterScene.gd | 15 ++++++-- battle/fighter/BattleFighterScene.tscn | 10 ++++-- battle/fighter/idk/green_dragon.tres | 2 +- battle/fighter/idk/green_dragon_frames.tres | 5 ++- battle/ui/DamageLabel.gd | 40 +++++++++++++++++++++ battle/ui/DamageLabel.gd.uid | 1 + battle/ui/DamageLabel.tscn | 16 +++++++++ party/Party.gd | 1 + 11 files changed, 109 insertions(+), 25 deletions(-) create mode 100644 battle/ui/DamageLabel.gd create mode 100644 battle/ui/DamageLabel.gd.uid create mode 100644 battle/ui/DamageLabel.tscn diff --git a/battle/Battle.gd b/battle/Battle.gd index 3d915d3..a241ba4 100644 --- a/battle/Battle.gd +++ b/battle/Battle.gd @@ -55,5 +55,11 @@ func startBattle(params) -> void: if !battleCutscene.running: battleCutscene.start() + # Wait 3 seconds then simulate damage for testing + var fighter = fighterMap[BattlePosition.RIGHT_TOP_FRONT] + while true: + await get_tree().create_timer(0.3).timeout + fighter.damage(10, false) + func getFighterAtPosition(battlePos:BattlePosition) -> BattleFighter: return fighterMap.get(battlePos, null) diff --git a/battle/BattleScene.tscn b/battle/BattleScene.tscn index d718b10..ccfb796 100644 --- a/battle/BattleScene.tscn +++ b/battle/BattleScene.tscn @@ -29,52 +29,52 @@ text = "Battle" [node name="Fighters" type="Node" parent="."] [node name="LeftTopBack" parent="Fighters" instance=ExtResource("1_abr1f")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 3, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4, 2, 0) battlePosition = 0 [node name="LeftTopFront" parent="Fighters" instance=ExtResource("1_abr1f")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 3, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 2, 0) battlePosition = 1 [node name="LeftMiddleBack" parent="Fighters" instance=ExtResource("1_abr1f")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, 0, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4, 0, 0) battlePosition = 2 [node name="LeftMiddleFront" parent="Fighters" instance=ExtResource("1_abr1f")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2.754, 0, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 0, 0) [node name="LeftBottomBack" parent="Fighters" instance=ExtResource("1_abr1f")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5, -3, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -4, -2, 0) battlePosition = 4 [node name="LeftBottomFront" parent="Fighters" instance=ExtResource("1_abr1f")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, -3, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -2, -2, 0) battlePosition = 5 [node name="RightTopFront" parent="Fighters" instance=ExtResource("1_abr1f")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 3, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 2, 0) battlePosition = 7 [node name="RightTopBack" parent="Fighters" instance=ExtResource("1_abr1f")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5, 3, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 2, 0) battlePosition = 6 [node name="RightMiddleFront" parent="Fighters" instance=ExtResource("1_abr1f")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, 0, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0) battlePosition = 9 [node name="RightMiddleBack" parent="Fighters" instance=ExtResource("1_abr1f")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5, 0, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, 0, 0) battlePosition = 8 [node name="RightBottomFront" parent="Fighters" instance=ExtResource("1_abr1f")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 3, -3, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 2, -2, 0) battlePosition = 11 [node name="RightBottomBack" parent="Fighters" instance=ExtResource("1_abr1f")] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 5, -3, 0) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 4, -2, 0) battlePosition = 10 [node name="Camera3D" type="Camera3D" parent="."] -transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 6.9021) +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 3.79103) current = true diff --git a/battle/fighter/BattleFighter.gd b/battle/fighter/BattleFighter.gd index bdaa191..df47153 100644 --- a/battle/fighter/BattleFighter.gd +++ b/battle/fighter/BattleFighter.gd @@ -36,13 +36,13 @@ var luck:int # Equipment # Signals -signal healthChanged(difference:int) +signal healthChanged(difference:int, crit:bool) signal mpChanged(difference:int) signal statusChanged(oldStatus:Status, newStatus:Status) func _init(params:Dictionary) -> void: - self.maxHealth = params.get('max_health', 100) - self.maxMp = params.get('max_mp', 50) + self.maxHealth = params.get('maxHealth', 100) + self.maxMp = params.get('maxMp', 50) self.attack = params.get('attack', 10) self.defense = params.get('defense', 5) self.speed = params.get('speed', 5) @@ -54,12 +54,12 @@ func _init(params:Dictionary) -> void: self.health = self.maxHealth self.mp = self.maxMp -func damage(amount:int) -> void: +func damage(amount:int, crit:bool) -> void: assert(amount > 0) if status == Status.DEAD: return health = max(health - amount, 0) - healthChanged.emit(-amount) + healthChanged.emit(-amount, crit) if health == 0: var oldStatus = status status = Status.DEAD @@ -70,7 +70,7 @@ func heal(amount:int) -> void: if status == Status.DEAD: return health = min(health + amount, maxHealth) - healthChanged.emit(amount) + healthChanged.emit(amount, false) func revive(health:int) -> void: assert(health > 0) diff --git a/battle/fighter/BattleFighterScene.gd b/battle/fighter/BattleFighterScene.gd index 4777ab0..3216721 100644 --- a/battle/fighter/BattleFighterScene.gd +++ b/battle/fighter/BattleFighterScene.gd @@ -1,18 +1,25 @@ class_name BattleFighterScene extends Node3D @export var battlePosition:BattleSingleton.BattlePosition = BattleSingleton.BattlePosition.LEFT_MIDDLE_FRONT +@export var damageLabels:Node3D +@export var damageLabelPreset:PackedScene + +var currentFighter:BattleFighter = null func _getFighter() -> BattleFighter: return BATTLE.getFighterAtPosition(self.battlePosition) func _updateFighter() -> void: - var fighter = _getFighter() + if currentFighter != null: + currentFighter.healthChanged.disconnect(onDamageTaken) - if fighter == null: + currentFighter = _getFighter() + if currentFighter == null: self.visible = false return # Set up the visual representation of the fighter here + currentFighter.healthChanged.connect(onDamageTaken) self.visible = true func _enter_tree() -> void: @@ -24,3 +31,7 @@ func _exit_tree() -> void: func onFightersChanged() -> void: _updateFighter() + +func onDamageTaken(amount:int, crit:bool) -> void: + var damageLabel = damageLabelPreset.instantiate() as Label3D + damageLabel.showDamage(damageLabels, amount, crit) diff --git a/battle/fighter/BattleFighterScene.tscn b/battle/fighter/BattleFighterScene.tscn index 35fe2a2..6d1c80d 100644 --- a/battle/fighter/BattleFighterScene.tscn +++ b/battle/fighter/BattleFighterScene.tscn @@ -1,15 +1,18 @@ -[gd_scene load_steps=5 format=3 uid="uid://d1xyb0hdf1yeh"] +[gd_scene load_steps=6 format=3 uid="uid://d1xyb0hdf1yeh"] [ext_resource type="Script" uid="uid://bgycdhsouwhwt" path="res://battle/fighter/BattleFighterScene.gd" id="1_veb1i"] [ext_resource type="SpriteFrames" uid="uid://cqqkm34a46ri6" path="res://battle/fighter/idk/green_dragon_frames.tres" id="2_e55p4"] +[ext_resource type="PackedScene" uid="uid://baxswkivvo5rs" path="res://battle/ui/DamageLabel.tscn" id="2_lciku"] [sub_resource type="BoxMesh" id="BoxMesh_veb1i"] [sub_resource type="StandardMaterial3D" id="StandardMaterial3D_e55p4"] shading_mode = 0 -[node name="BattleFighterScene" type="Node3D"] +[node name="BattleFighterScene" type="Node3D" node_paths=PackedStringArray("damageLabels")] script = ExtResource("1_veb1i") +damageLabels = NodePath("Labels") +damageLabelPreset = ExtResource("2_lciku") metadata/_custom_type_script = "uid://bgycdhsouwhwt" [node name="MeshInstance3D" type="MeshInstance3D" parent="."] @@ -18,6 +21,9 @@ mesh = SubResource("BoxMesh_veb1i") surface_material_override/0 = SubResource("StandardMaterial3D_e55p4") [node name="AnimatedSprite3D" type="AnimatedSprite3D" parent="."] +billboard = 2 sprite_frames = ExtResource("2_e55p4") animation = &"idle" frame_progress = 0.746159 + +[node name="Labels" type="Node3D" parent="."] diff --git a/battle/fighter/idk/green_dragon.tres b/battle/fighter/idk/green_dragon.tres index fd2be14..6231eb8 100644 --- a/battle/fighter/idk/green_dragon.tres +++ b/battle/fighter/idk/green_dragon.tres @@ -4,4 +4,4 @@ [resource] atlas = ExtResource("1_s00hx") -region = Rect2(16, 45.6621, 66, 83.3379) +region = Rect2(16, 45, 66, 83) diff --git a/battle/fighter/idk/green_dragon_frames.tres b/battle/fighter/idk/green_dragon_frames.tres index c988382..cd05b2c 100644 --- a/battle/fighter/idk/green_dragon_frames.tres +++ b/battle/fighter/idk/green_dragon_frames.tres @@ -4,7 +4,10 @@ [resource] animations = [{ -"frames": [], +"frames": [{ +"duration": 1.0, +"texture": ExtResource("1_vtgsa") +}], "loop": true, "name": &"attack", "speed": 5.0 diff --git a/battle/ui/DamageLabel.gd b/battle/ui/DamageLabel.gd new file mode 100644 index 0000000..441d99f --- /dev/null +++ b/battle/ui/DamageLabel.gd @@ -0,0 +1,40 @@ +class_name DamageLabel extends Label3D + +@export var timer:Timer +@export var speed:Vector3 = Vector3(0, 1, 0) + +func onTimeout() -> void: + self.visible = false + queue_free() + print("Damage label removed") + +func _process(delta: float) -> void: + self.position += speed * delta + +func showDamage( + parent:Node3D, + amount:int, + isCritical:bool +) -> void: + if amount == 0: + return + + text = str(amount) + + if amount > 0: + # Healing + modulate = Color.GREEN + outline_modulate = Color.TRANSPARENT + elif isCritical: + # Crit + modulate = Color.RED + outline_modulate = Color.BLACK + else: + # DMG + modulate = Color.RED + outline_modulate = Color.TRANSPARENT + + parent.add_child(self) + self.position = Vector3.ZERO + + timer.timeout.connect(onTimeout) diff --git a/battle/ui/DamageLabel.gd.uid b/battle/ui/DamageLabel.gd.uid new file mode 100644 index 0000000..468146e --- /dev/null +++ b/battle/ui/DamageLabel.gd.uid @@ -0,0 +1 @@ +uid://b86wqbqmsrv5b diff --git a/battle/ui/DamageLabel.tscn b/battle/ui/DamageLabel.tscn new file mode 100644 index 0000000..7b8ca69 --- /dev/null +++ b/battle/ui/DamageLabel.tscn @@ -0,0 +1,16 @@ +[gd_scene load_steps=2 format=3 uid="uid://baxswkivvo5rs"] + +[ext_resource type="Script" uid="uid://b86wqbqmsrv5b" path="res://battle/ui/DamageLabel.gd" id="1_6dg8x"] + +[node name="DamageLabel" type="Label3D" node_paths=PackedStringArray("timer")] +billboard = 1 +render_priority = 1 +outline_modulate = Color(1, 0, 0, 1) +text = "-%%%%%" +script = ExtResource("1_6dg8x") +timer = NodePath("Timer") +metadata/_custom_type_script = "uid://b86wqbqmsrv5b" + +[node name="Timer" type="Timer" parent="."] +one_shot = true +autostart = true diff --git a/party/Party.gd b/party/Party.gd index 975f97d..5befbc6 100644 --- a/party/Party.gd +++ b/party/Party.gd @@ -3,6 +3,7 @@ class_name PartySingleton extends Node static var PARTY_JOHN = PartyMember.new({ 'name': "John", 'team': BattleFighter.FighterTeam.PLAYER, + "maxHealth": 9999999999 }) static var BACKPACK = Inventory.new()