basic healthbars for enemies
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAction_00601_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F7c0f83388bfc4d2c9d09befcec9dd79bc90908_003Fb8_003F4d300c4d_003FAction_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAction_00602_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F7c0f83388bfc4d2c9d09befcec9dd79bc90908_003F87_003Fded27e2d_003FAction_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACharacterBody3D_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fe56b84c3fa498fb86fc1eba376f62f482127e3fe80415c5fb2acde2bf6d89793_003FCharacterBody3D_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AEnemy_005FScriptMethods_002Egenerated_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F8e71dc81611862c01a2cb998a1f327de14747655_003FEnemy_005FScriptMethods_002Egenerated_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANode_002Ecs_002Fl_003AC_0021_003FUsers_003FMinimata_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fdf73a4db74df89d59655c5fb6326406f47fbfa9af1fa81518fe0a07c49d34133_003FNode_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||
|
||||
BIN
assets/ui/white-square-100px.png
(Stored with Git LFS)
Normal file
BIN
assets/ui/white-square-100px.png
(Stored with Git LFS)
Normal file
Binary file not shown.
42
assets/ui/white-square-100px.png.import
Normal file
42
assets/ui/white-square-100px.png.import
Normal file
@@ -0,0 +1,42 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://vpcxswwn1mt6"
|
||||
path.s3tc="res://.godot/imported/white-square-100px.png-45d5a1e60348740b59c87085347e502a.s3tc.ctex"
|
||||
path.etc2="res://.godot/imported/white-square-100px.png-45d5a1e60348740b59c87085347e502a.etc2.ctex"
|
||||
metadata={
|
||||
"imported_formats": ["s3tc_bptc", "etc2_astc"],
|
||||
"vram_texture": true
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://assets/ui/white-square-100px.png"
|
||||
dest_files=["res://.godot/imported/white-square-100px.png-45d5a1e60348740b59c87085347e502a.s3tc.ctex", "res://.godot/imported/white-square-100px.png-45d5a1e60348740b59c87085347e502a.etc2.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=2
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/uastc_level=0
|
||||
compress/rdo_quality_loss=0.0
|
||||
compress/hdr_compression=1
|
||||
compress/normal_map=0
|
||||
compress/channel_pack=0
|
||||
mipmaps/generate=true
|
||||
mipmaps/limit=-1
|
||||
roughness/mode=0
|
||||
roughness/src_normal=""
|
||||
process/channel_remap/red=0
|
||||
process/channel_remap/green=1
|
||||
process/channel_remap/blue=2
|
||||
process/channel_remap/alpha=3
|
||||
process/fix_alpha_border=true
|
||||
process/premult_alpha=false
|
||||
process/normal_map_invert_y=false
|
||||
process/hdr_as_srgb=false
|
||||
process/hdr_clamp_exposure=false
|
||||
process/size_limit=0
|
||||
detect_3d/compress_to=0
|
||||
@@ -5,7 +5,7 @@ using Movementtests.interfaces;
|
||||
[GlobalClass]
|
||||
public partial class CHealth : Node, IHealthable
|
||||
{
|
||||
public event Action<IHealthable, float> HealthChanged;
|
||||
public event Action<IHealthable, HealthChangedRecord> HealthChanged;
|
||||
public event Action<IHealthable> HealthDepleted;
|
||||
|
||||
[Export]
|
||||
@@ -18,15 +18,18 @@ public partial class CHealth : Node, IHealthable
|
||||
CurrentHealth = RHealth.StartingHealth;
|
||||
}
|
||||
|
||||
public void ReduceHealth(IDamageable source, DamageRecord damageRecord)
|
||||
public HealthChangedRecord ReduceHealth(IDamageable source, DamageRecord damageRecord)
|
||||
{
|
||||
var previousHealth = CurrentHealth;
|
||||
CurrentHealth -= damageRecord.Damage.DamageDealt;
|
||||
HealthChanged?.Invoke(this, CurrentHealth);
|
||||
var record = new HealthChangedRecord(CurrentHealth, previousHealth, RHealth.StartingHealth);
|
||||
HealthChanged?.Invoke(this, record);
|
||||
|
||||
if (CurrentHealth <= 0)
|
||||
{
|
||||
CurrentHealth = 0;
|
||||
HealthDepleted?.Invoke(this);
|
||||
}
|
||||
return record;
|
||||
}
|
||||
}
|
||||
|
||||
26
components/health/CHealthbar.cs
Normal file
26
components/health/CHealthbar.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Godot;
|
||||
using System;
|
||||
using Movementtests.interfaces;
|
||||
|
||||
[GlobalClass]
|
||||
public partial class CHealthbar : Node3D
|
||||
{
|
||||
private Sprite3D _currentHealth;
|
||||
private float _initialXScale;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
Visible = false;
|
||||
_currentHealth = GetNode<Sprite3D>("Health");
|
||||
_initialXScale = _currentHealth.Scale.X;
|
||||
}
|
||||
|
||||
public void OnHealthChanged(HealthChangedRecord healthChanged)
|
||||
{
|
||||
if (healthChanged.MaxHealth == 0) return;
|
||||
|
||||
Visible = true;
|
||||
var healthPercentage = healthChanged.CurrentHealth / healthChanged.MaxHealth;
|
||||
_currentHealth.Scale = new Vector3(_initialXScale * healthPercentage, _currentHealth.Scale.Y, _currentHealth.Scale.Z);
|
||||
}
|
||||
}
|
||||
1
components/health/CHealthbar.cs.uid
Normal file
1
components/health/CHealthbar.cs.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://dve6vg6yvg4y8
|
||||
27
components/health/CHealthbar.tscn
Normal file
27
components/health/CHealthbar.tscn
Normal file
@@ -0,0 +1,27 @@
|
||||
[gd_scene load_steps=3 format=3 uid="uid://bwx2um43k0ou4"]
|
||||
|
||||
[ext_resource type="Texture2D" uid="uid://vpcxswwn1mt6" path="res://assets/ui/white-square-100px.png" id="1_jlvej"]
|
||||
[ext_resource type="Script" uid="uid://dve6vg6yvg4y8" path="res://components/health/CHealthbar.cs" id="1_w5itk"]
|
||||
|
||||
[node name="CHealthBar" type="Node3D"]
|
||||
script = ExtResource("1_w5itk")
|
||||
|
||||
[node name="Bar" type="Sprite3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.1, 0, 0, 0, 1, 0, 0, 0)
|
||||
cast_shadow = 0
|
||||
billboard = 1
|
||||
transparent = false
|
||||
double_sided = false
|
||||
no_depth_test = true
|
||||
texture = ExtResource("1_jlvej")
|
||||
|
||||
[node name="Health" type="Sprite3D" parent="."]
|
||||
transform = Transform3D(0.99, 0, 0, 0, 0.09, 0, 0, 0, 1, 0, 0, 0)
|
||||
cast_shadow = 0
|
||||
modulate = Color(0.7191989, 0.19340843, 1.92523e-07, 1)
|
||||
billboard = 1
|
||||
transparent = false
|
||||
double_sided = false
|
||||
no_depth_test = true
|
||||
render_priority = 10
|
||||
texture = ExtResource("1_jlvej")
|
||||
@@ -8,6 +8,7 @@ public record DamageRecord(Node3D Source, RDamage Damage);
|
||||
public interface IDamageable
|
||||
{
|
||||
event Action<IDamageable, DamageRecord> DamageTaken;
|
||||
|
||||
DamageRecord TakeDamage(DamageRecord damageRecord);
|
||||
DamageRecord ComputeDamage(DamageRecord damageRecord);
|
||||
}
|
||||
@@ -3,14 +3,16 @@ using Godot;
|
||||
|
||||
namespace Movementtests.interfaces;
|
||||
|
||||
public record HealthChangedRecord(float CurrentHealth, float PreviousHealth, float MaxHealth);
|
||||
|
||||
public interface IHealthable
|
||||
{
|
||||
event Action<IHealthable, float> HealthChanged;
|
||||
event Action<IHealthable, HealthChangedRecord> HealthChanged;
|
||||
event Action<IHealthable> HealthDepleted;
|
||||
|
||||
[Export] RHealth RHealth { get; set; }
|
||||
|
||||
float CurrentHealth { get; set; }
|
||||
|
||||
void ReduceHealth(IDamageable source, DamageRecord damageRecord);
|
||||
HealthChangedRecord ReduceHealth(IDamageable source, DamageRecord damageRecord);
|
||||
}
|
||||
@@ -41,7 +41,7 @@ public partial class PlayerController : CharacterBody3D,
|
||||
///////////////////////////
|
||||
|
||||
public event Action<IDamageable, DamageRecord> DamageTaken;
|
||||
public event Action<IHealthable, float> HealthChanged;
|
||||
public event Action<IHealthable, HealthChangedRecord> HealthChanged;
|
||||
public event Action<IHealthable> HealthDepleted;
|
||||
|
||||
///////////////////////////
|
||||
@@ -426,7 +426,7 @@ public partial class PlayerController : CharacterBody3D,
|
||||
}
|
||||
if (RKnockback != null) CKnockback!.RKnockback = RKnockback;
|
||||
|
||||
CDamageable.DamageTaken += ReduceHealth;
|
||||
CDamageable.DamageTaken += (source, record) => ReduceHealth(source, record);
|
||||
CDamageable.DamageTaken += RegisterKnockback;
|
||||
CHealth.HealthDepleted += Kill;
|
||||
|
||||
@@ -2042,11 +2042,12 @@ public partial class PlayerController : CharacterBody3D,
|
||||
{
|
||||
ResetTimeScale();
|
||||
}
|
||||
public void ReduceHealth(IDamageable source, DamageRecord damageRecord)
|
||||
public HealthChangedRecord ReduceHealth(IDamageable source, DamageRecord damageRecord)
|
||||
{
|
||||
GD.Print("That's NOT fine");
|
||||
CHealth.ReduceHealth(source, damageRecord);
|
||||
HealthChanged?.Invoke(this, CHealth.CurrentHealth);
|
||||
var record = CHealth.ReduceHealth(source, damageRecord);
|
||||
HealthChanged?.Invoke(this, record);
|
||||
return record;
|
||||
}
|
||||
public void RegisterKnockback(IDamageable source, DamageRecord damageRecord)
|
||||
{
|
||||
|
||||
@@ -16,7 +16,7 @@ public partial class Enemy : CharacterBody3D,
|
||||
{
|
||||
// Signals and events
|
||||
public event Action<IDamageable, DamageRecord> DamageTaken;
|
||||
public event Action<IHealthable, float> HealthChanged;
|
||||
public event Action<IHealthable, HealthChangedRecord> HealthChanged;
|
||||
public event Action<IHealthable> HealthDepleted;
|
||||
|
||||
// Public export components
|
||||
@@ -54,6 +54,7 @@ public partial class Enemy : CharacterBody3D,
|
||||
// Private stuff
|
||||
private Area3D _damageBox;
|
||||
private Node3D _target;
|
||||
private CHealthbar _healthbar;
|
||||
|
||||
public override void _Ready()
|
||||
{
|
||||
@@ -75,6 +76,8 @@ public partial class Enemy : CharacterBody3D,
|
||||
if (CHealth is null) GD.PrintErr("This node needs a 'CHealth' child of type IHealthable!");
|
||||
if (CKnockback is null) GD.PrintErr("This node needs a 'CKnockback' child of type IKnockbackable!");
|
||||
|
||||
_healthbar = GetNode<CHealthbar>("CHealthBar");
|
||||
|
||||
if (RMovement != null) CMovement!.RMovement = RMovement;
|
||||
if (RHealth != null)
|
||||
{
|
||||
@@ -86,9 +89,11 @@ public partial class Enemy : CharacterBody3D,
|
||||
|
||||
public void SetupSignals()
|
||||
{
|
||||
CDamageable.DamageTaken += ReduceHealth;
|
||||
// Anonymous function call to erase return values of ReduceHealth
|
||||
CDamageable.DamageTaken += (source, record) => ReduceHealth(source, record);
|
||||
CDamageable.DamageTaken += RegisterKnockback;
|
||||
CHealth.HealthDepleted += Kill;
|
||||
HealthChanged += (source, record) => _healthbar.OnHealthChanged(record);
|
||||
}
|
||||
|
||||
public override void _PhysicsProcess(double delta)
|
||||
@@ -147,11 +152,12 @@ public partial class Enemy : CharacterBody3D,
|
||||
return CDamageable.ComputeDamage(damageRecord);
|
||||
}
|
||||
|
||||
public void ReduceHealth(IDamageable source, DamageRecord damageRecord)
|
||||
public HealthChangedRecord ReduceHealth(IDamageable source, DamageRecord damageRecord)
|
||||
{
|
||||
if (CHealth is null) return;
|
||||
CHealth.ReduceHealth(source, damageRecord);
|
||||
HealthChanged?.Invoke(this, CHealth.CurrentHealth);
|
||||
if (CHealth is null) return new HealthChangedRecord(0, 0, 0);
|
||||
var record = CHealth.ReduceHealth(source, damageRecord);
|
||||
HealthChanged?.Invoke(this, record);
|
||||
return record;
|
||||
}
|
||||
|
||||
public void Kill(IHealthable source)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=20 format=3 uid="uid://cmlud1hwkd6sv"]
|
||||
[gd_scene load_steps=21 format=3 uid="uid://cmlud1hwkd6sv"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bn7sc6id7n166" path="res://scenes/enemies/Enemy.cs" id="1_q8l7o"]
|
||||
[ext_resource type="Script" uid="uid://b6y3ugfydvch0" path="res://components/damage/RDamageModifier.cs" id="2_1bsgx"]
|
||||
@@ -7,6 +7,7 @@
|
||||
[ext_resource type="Resource" uid="uid://bwqjaom4k7rc3" path="res://scenes/enemies/flying_enemy/flying_enemy_movement.tres" id="4_dejyg"]
|
||||
[ext_resource type="Script" uid="uid://bjwrpv3jpsc1e" path="res://components/health/CHealth.cs" id="4_ys4jv"]
|
||||
[ext_resource type="PackedScene" uid="uid://dmw5ibwrb483f" path="res://components/movement/CFlyingMovement.tscn" id="7_vaeds"]
|
||||
[ext_resource type="PackedScene" uid="uid://bwx2um43k0ou4" path="res://components/health/CHealthbar.tscn" id="7_ykkxn"]
|
||||
[ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://components/movement/RMovement.cs" id="8_on7rt"]
|
||||
[ext_resource type="Script" uid="uid://b0u23nkpaimyc" path="res://components/damage/CDamageable.cs" id="8_uotso"]
|
||||
[ext_resource type="PackedScene" uid="uid://bctpe34ddamg5" path="res://components/knockback/CKnockback.tscn" id="10_dejyg"]
|
||||
@@ -58,6 +59,9 @@ script = ExtResource("4_ys4jv")
|
||||
RHealth = ExtResource("2_ma2bq")
|
||||
metadata/_custom_type_script = "uid://bjwrpv3jpsc1e"
|
||||
|
||||
[node name="CHealthBar" parent="." instance=ExtResource("7_ykkxn")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.2, 0)
|
||||
|
||||
[node name="CDamageable" type="Node" parent="."]
|
||||
script = ExtResource("8_uotso")
|
||||
DamageModifiers = Array[Object]([SubResource("Resource_jnv07"), SubResource("Resource_53j1c")])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[gd_scene load_steps=19 format=3 uid="uid://dxt0e2ugmttqq"]
|
||||
[gd_scene load_steps=20 format=3 uid="uid://dxt0e2ugmttqq"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bn7sc6id7n166" path="res://scenes/enemies/Enemy.cs" id="1_r6506"]
|
||||
[ext_resource type="Resource" uid="uid://otfc2snh8umc" path="res://scenes/enemies/grounded_enemy/grounded_enemy_damage.tres" id="2_bn56u"]
|
||||
@@ -7,6 +7,7 @@
|
||||
[ext_resource type="Resource" uid="uid://bohbojc68j7y1" path="res://scenes/enemies/grounded_enemy/grounded_enemy_health.tres" id="2_w4lm8"]
|
||||
[ext_resource type="Resource" uid="uid://bqq6uukbdfysr" path="res://scenes/enemies/grounded_enemy/grounded_enemy_movement.tres" id="4_na24f"]
|
||||
[ext_resource type="Script" uid="uid://b0u23nkpaimyc" path="res://components/damage/CDamageable.cs" id="7_1tw73"]
|
||||
[ext_resource type="PackedScene" uid="uid://bwx2um43k0ou4" path="res://components/health/CHealthbar.tscn" id="7_18xwy"]
|
||||
[ext_resource type="PackedScene" uid="uid://dbr7ioio158ew" path="res://components/movement/CGroundedMovement.tscn" id="7_qyswd"]
|
||||
[ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://components/movement/RMovement.cs" id="8_6d4gl"]
|
||||
[ext_resource type="PackedScene" uid="uid://bctpe34ddamg5" path="res://components/knockback/CKnockback.tscn" id="10_jqqi6"]
|
||||
@@ -53,6 +54,9 @@ script = ExtResource("2_gsmti")
|
||||
RHealth = ExtResource("2_w4lm8")
|
||||
metadata/_custom_type_script = "uid://bjwrpv3jpsc1e"
|
||||
|
||||
[node name="CHealthBar" parent="." instance=ExtResource("7_18xwy")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.2, 0)
|
||||
|
||||
[node name="CDamageable" type="Node" parent="."]
|
||||
script = ExtResource("7_1tw73")
|
||||
DamageModifiers = Array[Object]([SubResource("Resource_qj0ob")])
|
||||
|
||||
Reference in New Issue
Block a user