Compare commits

..

10 Commits

Author SHA1 Message Date
ddf1bd019b better healthbars and one for the player as well
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 42s
Create tag and build when new code gets to main / Test (push) Successful in 6m13s
Create tag and build when new code gets to main / Export (push) Successful in 7m5s
2026-01-26 18:09:29 +01:00
2fdc9c7ca8 instanciating explosion on slam
Some checks failed
Create tag and build when new code gets to main / BumpTag (push) Has been cancelled
Create tag and build when new code gets to main / Test (push) Has been cancelled
Create tag and build when new code gets to main / Export (push) Has been cancelled
2026-01-26 16:34:18 +01:00
d79ca44972 everything should work fine now
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 26s
Create tag and build when new code gets to main / Test (push) Successful in 8m7s
Create tag and build when new code gets to main / Export (push) Successful in 7m13s
2026-01-26 09:26:54 +01:00
148aea9bb4 trying to remove ad unit addon from build job because it breaks
All checks were successful
Create tag and build when new code gets to main / Export (push) Successful in 6m59s
2026-01-26 09:18:28 +01:00
bdce8b969c reinstalling GDUnit from assetlib
Some checks failed
Create tag and build when new code gets to main / Export (push) Failing after 6m41s
2026-01-26 09:05:55 +01:00
4095f818f6 gdunit addon post import by godot
All checks were successful
Create tag and build when new code gets to main / Export (push) Successful in 7m17s
2026-01-26 08:59:34 +01:00
72bf3d4cc5 making sure the issue comes from GDUnit addon folder
All checks were successful
Create tag and build when new code gets to main / Export (push) Successful in 7m6s
2026-01-26 08:51:14 +01:00
51907a1f01 trying to fix Export
All checks were successful
Create tag and build when new code gets to main / Export (push) Successful in 6m53s
2026-01-26 08:41:48 +01:00
c5c4ceb032 trying to fix Export
Some checks failed
Create tag and build when new code gets to main / Export (push) Failing after 6m47s
2026-01-26 08:30:31 +01:00
64957334de trying to fix Export
Some checks failed
Create tag and build when new code gets to main / BumpTag (push) Successful in 35s
Create tag and build when new code gets to main / Export (push) Has been cancelled
2026-01-26 08:29:43 +01:00
24 changed files with 371 additions and 129 deletions

View File

@@ -37,7 +37,7 @@ jobs:
git config -f $AUTH_FILE http.${{ gitea.server_url }}/${{ gitea.repository }}.git/info/lfs/objects/batch.extraheader "$AUTH"
git lfs pull
- name: Launch Godot
- name: Run tests
uses: godot-gdunit-labs/gdUnit4-action@v1
with:
godot-version: '4.5.1'
@@ -50,9 +50,6 @@ jobs:
timeout: 1
publish-report: false
upload-report: false
- name: Test action
run: echo ${{ github.workspace }}
- name: Upload test report
uses: actions/upload-artifact@v3-node20

View File

@@ -36,53 +36,53 @@ jobs:
INITIAL_VERSION: 0.1.0
DEFAULT_BUMP: patch
# Test:
# runs-on: ubuntu-latest
# steps:
# - name: Install node, xvfb and curl
# run: |
# apt update && apt -y install curl nodejs xvfb
#
# - name: Checkout
# uses: actions/checkout@v6
# with:
# lfs: false
# persist-credentials: true
#
# - name: Checkout LFS
# run: |
# git lfs install --local
# AUTH=$(git config http.${{ gitea.server_url }}/.extraheader)
# AUTH_FILE=$(git config includeif.gitdir:/workspace/${{ gitea.repository }}/.git.path)
# git config -f $AUTH_FILE --unset http.${{ gitea.server_url }}/.extraheader
# git config -f $AUTH_FILE http.${{ gitea.server_url }}/${{ gitea.repository }}.git/info/lfs/objects/batch.extraheader "$AUTH"
# git lfs pull
#
# - name: Launch Godot
# uses: godot-gdunit-labs/gdUnit4-action@v1
# with:
# godot-version: '4.5.1'
# godot-net: true
# godot-force-mono: true
# dotnet-version: 'net9.0'
# version: 'v6.0.3'
# paths: |
# res://tests/
# timeout: 1
# publish-report: false
# upload-report: false
#
# - name: Upload test report
# uses: actions/upload-artifact@v3-node20
# with:
# name: Test Report
# path: ${{ github.workspace }}/reports/test-result.html
Test:
runs-on: ubuntu-latest
steps:
- name: Install node, xvfb and curl
run: |
apt update && apt -y install curl nodejs xvfb
- name: Checkout
uses: actions/checkout@v6
with:
lfs: false
persist-credentials: true
- name: Checkout LFS
run: |
git lfs install --local
AUTH=$(git config http.${{ gitea.server_url }}/.extraheader)
AUTH_FILE=$(git config includeif.gitdir:/workspace/${{ gitea.repository }}/.git.path)
git config -f $AUTH_FILE --unset http.${{ gitea.server_url }}/.extraheader
git config -f $AUTH_FILE http.${{ gitea.server_url }}/${{ gitea.repository }}.git/info/lfs/objects/batch.extraheader "$AUTH"
git lfs pull
- name: Run tests
uses: godot-gdunit-labs/gdUnit4-action@v1
with:
godot-version: '4.5.1'
godot-net: true
godot-force-mono: true
dotnet-version: 'net9.0'
version: 'v6.0.3'
paths: |
res://tests/
timeout: 1
publish-report: false
upload-report: false
- name: Upload test report
uses: actions/upload-artifact@v3-node20
with:
name: Test Report
path: ${{ github.workspace }}/reports/test-result.html
Export:
runs-on: ubuntu-latest
needs:
- BumpTag
# - Test # Wait for tests to finish
- Test # Wait for tests to finish
container:
image: barichello/godot-ci:mono-4.5
@@ -92,9 +92,23 @@ jobs:
apt update && apt -y install curl zip nodejs
- name: Checkout
uses: https://git.game-dev.space/minimata/checkout-with-lfs.git@main
uses: actions/checkout@v6
with:
checkout-version: 3
lfs: false
persist-credentials: true
- name: Checkout LFS
run: |
git lfs install --local
AUTH=$(git config http.${{ gitea.server_url }}/.extraheader)
AUTH_FILE=$(git config includeif.gitdir:/workspace/${{ gitea.repository }}/.git.path)
git config -f $AUTH_FILE --unset http.${{ gitea.server_url }}/.extraheader
git config -f $AUTH_FILE http.${{ gitea.server_url }}/${{ gitea.repository }}.git/info/lfs/objects/batch.extraheader "$AUTH"
git lfs pull
- name: Remove GDUnit addon folder because it breaks the build
run: |
rm -rf ${{ gitea.workspace }}/addons/gdUnit4
- name: Import resources and build solution
run: |

View File

@@ -1,6 +1,6 @@
<Project Sdk="Godot.NET.Sdk/4.5.0">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<EnableDynamicLoading>true</EnableDynamicLoading>
<RootNamespace>Movementtests</RootNamespace>
</PropertyGroup>

View File

@@ -1,26 +1,14 @@
using Godot;
using System;
using Movementtests.interfaces;
[GlobalClass]
public partial class CHealthbar : Node3D
public partial class CHealthbar : Sprite3D
{
private Sprite3D _currentHealth;
private float _initialXScale;
private Healthbar _healthbar;
public Healthbar Healthbar => _healthbar;
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);
_healthbar = GetNode<Healthbar>("%Healthbar");
}
}

View File

@@ -1 +1 @@
uid://dve6vg6yvg4y8
uid://chfb3cjo6exga

View File

@@ -1,27 +1,32 @@
[gd_scene load_steps=3 format=3 uid="uid://bwx2um43k0ou4"]
[gd_scene load_steps=4 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"]
[ext_resource type="Script" uid="uid://chfb3cjo6exga" path="res://components/health/CHealthbar.cs" id="1_w5itk"]
[ext_resource type="PackedScene" uid="uid://cyw8p0p6a78tl" path="res://scenes/ui/healthbar.tscn" id="2_w5itk"]
[node name="CHealthBar" type="Node3D"]
[sub_resource type="ViewportTexture" id="ViewportTexture_jkj2g"]
viewport_path = NodePath("SubViewport")
[node name="CHealthBar" type="Sprite3D"]
billboard = 1
double_sided = false
no_depth_test = true
texture = SubResource("ViewportTexture_jkj2g")
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="SubViewport" type="SubViewport" parent="."]
transparent_bg = true
size = Vector2i(520, 20)
[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")
[node name="Healthbar" parent="SubViewport" instance=ExtResource("2_w5itk")]
unique_name_in_owner = true
anchors_preset = 8
anchor_left = 0.5
anchor_top = 0.5
anchor_right = 0.5
anchor_bottom = 0.5
offset_left = -120.0
offset_top = -4.0
offset_right = 120.0
offset_bottom = 4.0
grow_horizontal = 2
grow_vertical = 2

View File

@@ -7,20 +7,20 @@ public partial class CKnockback : Node3D, IKnockbackable
{
[Export] public RKnockback RKnockback { get; set;}
private DamageRecord _damageRecord = null;
private KnockbackRecord _knockbackRecord = null;
public void RegisterKnockback(IDamageable source, DamageRecord damageRecord)
public void RegisterKnockback(KnockbackRecord knockbackRecord)
{
_damageRecord = damageRecord;
_knockbackRecord = knockbackRecord;
}
public Vector3 ComputeKnockback()
{
if (_damageRecord == null) return Vector3.Zero;
if (_knockbackRecord == null) return Vector3.Zero;
var knockbackDirection = GlobalPosition - _damageRecord.Source.GlobalPosition;
_damageRecord = null;
var finalKnockback = knockbackDirection.Normalized() * RKnockback.Modifier;
var knockbackDirection = GlobalPosition - _knockbackRecord.DamageRecord.SourceLocation;
var finalKnockback = knockbackDirection.Normalized() * RKnockback.Modifier * _knockbackRecord.ForceMultiplier;
_knockbackRecord = null;
return finalKnockback;
}
}

View File

@@ -5,6 +5,7 @@
[sub_resource type="Resource" id="Resource_gbu2d"]
script = ExtResource("2_uqiml")
Modifier = 1.0
metadata/_custom_type_script = "uid://b44cse62qru7j"
[node name="CKnockback" type="Node3D"]

View File

@@ -3,7 +3,7 @@ using Godot;
namespace Movementtests.interfaces;
public record DamageRecord(Node3D Source, RDamage Damage);
public record DamageRecord(Vector3 SourceLocation, RDamage Damage);
public interface IDamageable
{

View File

@@ -2,10 +2,12 @@ using Godot;
namespace Movementtests.interfaces;
public record KnockbackRecord(DamageRecord DamageRecord, float ForceMultiplier = 1.0f);
public interface IKnockbackable
{
[Export] RKnockback RKnockback { get; set;}
public void RegisterKnockback(IDamageable source, DamageRecord damageRecord);
public void RegisterKnockback(KnockbackRecord record);
public Vector3 ComputeKnockback();
}

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=66 format=3 uid="uid://bei4nhkf8lwdo"]
[gd_scene load_steps=68 format=3 uid="uid://bei4nhkf8lwdo"]
[ext_resource type="Script" uid="uid://bbbrf5ckydfna" path="res://player_controller/Scripts/PlayerController.cs" id="1_poq2x"]
[ext_resource type="PackedScene" uid="uid://cf3rrgr1imvv4" path="res://scenes/path/path.tscn" id="2_6lejt"]
@@ -12,6 +12,7 @@
[ext_resource type="Resource" uid="uid://ccrb5xsnphc8" path="res://systems/inputs/base_mode/rotate_floorplane.tres" id="5_4u7i3"]
[ext_resource type="PackedScene" uid="uid://hpsg4fqwrx1u" path="res://components/damage/CDamageable.tscn" id="5_jb43f"]
[ext_resource type="Resource" uid="uid://f3vs6l4m623s" path="res://systems/inputs/base_mode/move_left.tres" id="5_q14ux"]
[ext_resource type="PackedScene" uid="uid://duju3atqgltkg" path="res://scenes/enemies/explosion.tscn" id="5_ue7xq"]
[ext_resource type="Resource" uid="uid://dyru7mxo121w6" path="res://player_controller/resources/player_normal_damage_mod.tres" id="6_cmijs"]
[ext_resource type="Resource" uid="uid://t612lts1wi1s" path="res://systems/inputs/base_mode/move_right.tres" id="6_q7bng"]
[ext_resource type="Script" uid="uid://cwbvxlfvmocc1" path="res://player_controller/Scripts/StairsSystem.cs" id="7_bmt5a"]
@@ -51,6 +52,7 @@
[ext_resource type="Texture2D" uid="uid://chvt6g0xn5c2m" path="res://systems/dash/light-ring.jpg" id="32_lgpc8"]
[ext_resource type="Script" uid="uid://b4dwolbvt8our" path="res://addons/godot_state_charts/history_state.gd" id="41_ruloh"]
[ext_resource type="Texture2D" uid="uid://buu21kg4kkhiw" path="res://guide_examples/shared/fireball/fireball.svg" id="42_cmijs"]
[ext_resource type="PackedScene" uid="uid://cyw8p0p6a78tl" path="res://scenes/ui/healthbar.tscn" id="47_76kmc"]
[sub_resource type="Resource" id="Resource_cb2lu"]
script = ExtResource("2_x835q")
@@ -112,6 +114,7 @@ RDamage = SubResource("Resource_cb2lu")
RKnockback = SubResource("Resource_abfq8")
RHealth = SubResource("Resource_ue7xq")
TargetingDistance = 5.0
Explosion = ExtResource("5_ue7xq")
WalkSpeed = 7.5
AccelerationFloor = 4.0
DecelerationFloor = 3.0
@@ -508,6 +511,21 @@ grow_vertical = 2
texture = ExtResource("42_cmijs")
expand_mode = 1
[node name="Healthbar" parent="UI" instance=ExtResource("47_76kmc")]
unique_name_in_owner = true
layout_mode = 1
anchors_preset = 7
anchor_left = 0.5
anchor_top = 1.0
anchor_right = 0.5
anchor_bottom = 1.0
offset_left = -120.0
offset_top = -80.0
offset_right = 119.99963
offset_bottom = -71.99939
grow_horizontal = 2
grow_vertical = 0
[node name="StateChart" type="Node" parent="."]
script = ExtResource("25_wv70j")
metadata/_custom_type_script = "uid://couw105c3bde4"

View File

@@ -1,10 +1,12 @@
using Godot;
using System;
using Movementtests.interfaces;
public partial class PlayerUi : Control
{
private TextureRect[] _dashIcons = new TextureRect[3];
private TextureRect _enemyTarget;
private Healthbar _healthbar;
public enum TargetState
{
@@ -30,6 +32,12 @@ public partial class PlayerUi : Control
_dashIcons[2] = GetNode<TextureRect>("%Dash3");
_enemyTarget = GetNode<TextureRect>("%EnemyTarget");
_healthbar = GetNode<Healthbar>("%Healthbar");
}
public void Initialize(float initialHealth)
{
_healthbar.Initialize(initialHealth);
}
public void SetEnemyTargetProperties(TargetProperties targetProperties)
@@ -59,5 +67,10 @@ public partial class PlayerUi : Control
dashIcon.SetVisible(index <= numberOfDashes);
index++;
}
}
}
public void OnHealthChanged(IHealthable healthable, HealthChangedRecord healthChanged)
{
_healthbar.CurrentHealth = healthChanged.CurrentHealth;
}
}

View File

@@ -1,13 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Godot;
using GodotStateCharts;
using Movementtests.addons.godot_state_charts.csharp;
using Movementtests.interfaces;
using Movementtests.systems;
using Movementtests.player_controller.Scripts;
using Movementtests.systems.damage;
using RustyOptions;
public partial class PlayerController : CharacterBody3D,
@@ -82,12 +80,16 @@ public partial class PlayerController : CharacterBody3D,
[Export] public RKnockback RKnockback { get; set; }
[Export] public RHealth RHealth { get; set; }
[ExportGroup("Targeting")]
[Export(PropertyHint.Range, "0,20,0.1,or_greater")]
public float TargetingDistance { get; set; } = 10.0f;
[Export(PropertyHint.Range, "0,20,0.1,or_greater")]
public float TargetInRangeDistance { get; set; } = 5.0f;
[ExportGroup("Instantiation")]
[Export]
public PackedScene Explosion { get; set; }
// Movement stuff
[ExportCategory("Movement")]
[ExportGroup("Ground")]
@@ -231,7 +233,7 @@ public partial class PlayerController : CharacterBody3D,
///////////////////////////
// Stairs and shit
private float _lastFrameWasOnFloor = -Mathf.Inf;
private const int NUM_OF_HEAD_COLLISION_DETECTORS = 4;
private const int NumOfHeadCollisionDetectors = 4;
private RayCast3D[] _headCollisionDetectors;
private AudioStreamPlaybackInteractive _audioStream;
@@ -398,8 +400,8 @@ public partial class PlayerController : CharacterBody3D,
SlidingEnemyDetector = GetNode<Area3D>("SlidingEnemyDetector");
RayCast3D stairsBelowRayCast3D = GetNode<RayCast3D>("StairsBelowRayCast3D");
RayCast3D stairsAheadRayCast3D = GetNode<RayCast3D>("StairsAheadRayCast3D");
_headCollisionDetectors = new RayCast3D[NUM_OF_HEAD_COLLISION_DETECTORS];
for (int i = 0; i < NUM_OF_HEAD_COLLISION_DETECTORS; i++)
_headCollisionDetectors = new RayCast3D[NumOfHeadCollisionDetectors];
for (int i = 0; i < NumOfHeadCollisionDetectors; i++)
{
_headCollisionDetectors[i] = GetNode<RayCast3D>(
"HeadCollisionDetectors/HeadCollisionDetector" + i);
@@ -428,8 +430,10 @@ public partial class PlayerController : CharacterBody3D,
}
if (RKnockback != null) CKnockback!.RKnockback = RKnockback;
CDamageable.DamageTaken += (source, record) => ReduceHealth(source, record);
CDamageable.DamageTaken += RegisterKnockback;
PlayerUi.Initialize(CHealth.CurrentHealth);
CDamageable.DamageTaken += (damageable, record) => ReduceHealth(damageable, record);
CDamageable.DamageTaken += (damageable, record) => RegisterKnockback(new KnockbackRecord(record));
CHealth.HealthChanged += PlayerUi.OnHealthChanged;
CHealth.HealthDepleted += Kill;
// State management
@@ -448,7 +452,6 @@ public partial class PlayerController : CharacterBody3D,
_airGlidingDoubleJump = StateChartState.Of(GetNode("StateChart/Root/Movement/Sliding/AirGlideDoubleJumpEnabled"));
_onGroundSlideJump = Transition.Of(GetNode("StateChart/Root/Movement/Sliding/GroundSlide/OnJump"));
_onAirGlideDoubleJump = Transition.Of(GetNode("StateChart/Root/Movement/Sliding/AirGlideDoubleJumpEnabled/OnJump"));
// _actionHanging = StateChartState.Of(GetNode("StateChart/Root/Actions/Hanging"));
_powerExpired = StateChartState.Of(GetNode("StateChart/Root/PowerReserve/Expired"));
_powerRecharging = StateChartState.Of(GetNode("StateChart/Root/PowerReserve/AtLeastOneCharge"));
@@ -765,7 +768,7 @@ public partial class PlayerController : CharacterBody3D,
}
private bool IsHeadTouchingCeiling()
{
for (int i = 0; i < NUM_OF_HEAD_COLLISION_DETECTORS; i++)
for (int i = 0; i < NumOfHeadCollisionDetectors; i++)
{
if (_headCollisionDetectors[i].IsColliding())
{
@@ -1595,6 +1598,11 @@ public partial class PlayerController : CharacterBody3D,
{
HeadSystem.OnGetHit();
_audioStream!.SwitchToClipByName("slam");
if (Explosion.Instantiate() is not Explosion explosion) return;
explosion.Radius = 10f;
GetTree().GetRoot().AddChild(explosion);
explosion.GlobalPosition = GlobalPosition;
}
///////////////////////////
@@ -1981,7 +1989,7 @@ public partial class PlayerController : CharacterBody3D,
enemyTargetState = PlayerUi.TargetState.TargetDashThrough;
if (_targetObject is IDamageable damageable and IHealthable healthable)
{
var wouldBeDamage = damageable.ComputeDamage(new DamageRecord(this, RDamage));
var wouldBeDamage = damageable.ComputeDamage(new DamageRecord(GlobalPosition, RDamage));
if (wouldBeDamage.Damage.DamageDealt < healthable.CurrentHealth)
enemyTargetState = PlayerUi.TargetState.TargetInRange;
}
@@ -2120,7 +2128,7 @@ public partial class PlayerController : CharacterBody3D,
if (_hitEnemies.Count == 0) return;
foreach (var damageable in _hitEnemies)
damageable.TakeDamage(new DamageRecord(this, RDamage));
damageable.TakeDamage(new DamageRecord(GlobalPosition, RDamage));
_hitEnemies.Clear();
HeadSystem.OnHitTarget();
@@ -2146,9 +2154,9 @@ public partial class PlayerController : CharacterBody3D,
HealthChanged?.Invoke(this, record);
return record;
}
public void RegisterKnockback(IDamageable source, DamageRecord damageRecord)
public void RegisterKnockback(KnockbackRecord knockbackRecord)
{
CKnockback.RegisterKnockback(source, damageRecord);
CKnockback.RegisterKnockback(knockbackRecord);
}
public Vector3 ComputeKnockback()

View File

@@ -43,7 +43,7 @@ movie_writer/movie_file="D:/Godot/Projects/movement-tests/communication/movie.av
[editor_plugins]
enabled=PackedStringArray("res://addons/godot_state_charts/plugin.cfg", "res://addons/guide/plugin.cfg", "res://addons/maaacks_game_template/plugin.cfg", "res://addons/shaker/plugin.cfg")
enabled=PackedStringArray("res://addons/godot_state_charts/plugin.cfg", "res://addons/guide/plugin.cfg", "res://addons/maaacks_game_template/plugin.cfg", "res://addons/shaker/plugin.cfg", "res://addons/gdUnit4/plugin.cfg")
[gui]

View File

@@ -57,7 +57,7 @@ public partial class Enemy : CharacterBody3D,
// Private stuff
private Area3D _damageBox;
private Node3D _target;
private CHealthbar _healthbar;
private Healthbar _healthbar;
public override void _Ready()
{
@@ -79,7 +79,7 @@ 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");
_healthbar = GetNode<CHealthbar>("CHealthBar").Healthbar;
if (RMovement != null) CMovement!.RMovement = RMovement;
if (RHealth != null)
@@ -88,15 +88,16 @@ public partial class Enemy : CharacterBody3D,
CHealth.CurrentHealth = RHealth.StartingHealth;
}
if (RKnockback != null) CKnockback!.RKnockback = RKnockback;
_healthbar.Initialize(CHealth!.CurrentHealth);
}
public void SetupSignals()
{
// Anonymous function call to erase return values of ReduceHealth
CDamageable.DamageTaken += (source, record) => ReduceHealth(source, record);
CDamageable.DamageTaken += RegisterKnockback;
CDamageable.DamageTaken += (source, record) => RegisterKnockback(new KnockbackRecord(record));
CHealth.HealthDepleted += Kill;
HealthChanged += (source, record) => _healthbar.OnHealthChanged(record);
HealthChanged += (source, record) => _healthbar.SetHealth(record.CurrentHealth);
}
public override void _PhysicsProcess(double delta)
@@ -127,7 +128,7 @@ public partial class Enemy : CharacterBody3D,
foreach (var body in bodies)
{
if(body is IDamageable spawnable)
spawnable.TakeDamage(new DamageRecord(this, RDamage));
spawnable.TakeDamage(new DamageRecord(GlobalPosition, RDamage));
}
}
@@ -184,10 +185,10 @@ public partial class Enemy : CharacterBody3D,
CallDeferred(Node.MethodName.QueueFree);
}
public void RegisterKnockback(IDamageable source, DamageRecord damageRecord)
public void RegisterKnockback(KnockbackRecord knockbackRecord)
{
if (CKnockback is null) return;
CKnockback.RegisterKnockback(source, damageRecord);
CKnockback.RegisterKnockback(knockbackRecord);
}
public Vector3 ComputeKnockback()

View File

@@ -0,0 +1,36 @@
using Godot;
using System;
using Movementtests.interfaces;
[GlobalClass]
public partial class Explosion : Area3D, IDamageDealer
{
[Export] public RDamage RDamage { get; set;}
[Export] public float Radius { get; set;}
[Export] public float ExplosionTime { get; set; } = 0.2f;
public override void _Ready()
{
var sphereShape = GetNode<CollisionShape3D>("CollisionShape3D").Shape as SphereShape3D;
sphereShape!.Radius = Radius;
var sphereMesh = GetNode<MeshInstance3D>("MeshInstance3D").Mesh as SphereMesh;
sphereMesh!.Radius = Radius;
sphereMesh!.Height = Radius*2f;
GetTree().CreateTimer(ExplosionTime).Timeout += TriggerExplosion;
}
public void TriggerExplosion()
{
var bodies = GetOverlappingBodies();
foreach (var body in bodies)
{
if (body is IDamageable damageable)
damageable.TakeDamage(new DamageRecord(GlobalPosition, RDamage));
if (body is IStunnable stunnable)
stunnable.Stun();
}
QueueFree();
}
}

View File

@@ -0,0 +1 @@
uid://cnlu64l7oxvv3

View File

@@ -0,0 +1,34 @@
[gd_scene load_steps=7 format=3 uid="uid://duju3atqgltkg"]
[ext_resource type="Script" uid="uid://cnlu64l7oxvv3" path="res://scenes/enemies/Explosion.cs" id="1_82hkh"]
[ext_resource type="Script" uid="uid://jitubgv6judn" path="res://components/damage/RDamage.cs" id="2_hys74"]
[sub_resource type="Resource" id="Resource_ffdh3"]
script = ExtResource("2_hys74")
DamageDealt = 5.0
DamageType = 3
metadata/_custom_type_script = "uid://jitubgv6judn"
[sub_resource type="SphereShape3D" id="SphereShape3D_82hkh"]
radius = 1.0
[sub_resource type="SphereMesh" id="SphereMesh_82hkh"]
[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_hys74"]
transparency = 1
cull_mode = 2
albedo_color = Color(0.9607843, 0.27058825, 0, 0.7176471)
[node name="Explosion" type="Area3D"]
collision_layer = 0
collision_mask = 16
monitorable = false
script = ExtResource("1_82hkh")
RDamage = SubResource("Resource_ffdh3")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("SphereShape3D_82hkh")
[node name="MeshInstance3D" type="MeshInstance3D" parent="."]
mesh = SubResource("SphereMesh_82hkh")
surface_material_override/0 = SubResource("StandardMaterial3D_hys74")

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=21 format=3 uid="uid://cmlud1hwkd6sv"]
[gd_scene load_steps=22 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"]
@@ -13,13 +13,17 @@
[ext_resource type="PackedScene" uid="uid://bctpe34ddamg5" path="res://components/knockback/CKnockback.tscn" id="10_dejyg"]
[ext_resource type="Resource" uid="uid://dt7a1io5o0b8s" path="res://scenes/enemies/flying_enemy/flying_enemy_knockback.tres" id="11_mpa2u"]
[sub_resource type="ViewportTexture" id="ViewportTexture_ykkxn"]
viewport_path = NodePath("SubViewport")
[sub_resource type="Resource" id="Resource_jnv07"]
script = ExtResource("2_1bsgx")
metadata/_custom_type_script = "uid://b6y3ugfydvch0"
[sub_resource type="Resource" id="Resource_53j1c"]
script = ExtResource("2_1bsgx")
DamageType = 1
DamageType = 3
Modifier = 1.0
metadata/_custom_type_script = "uid://b6y3ugfydvch0"
[sub_resource type="Resource" id="Resource_on7rt"]
@@ -61,7 +65,8 @@ 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, 0.70000005, 0)
transform = Transform3D(0.3, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.70000005, 0)
texture = SubResource("ViewportTexture_ykkxn")
[node name="CDamageable" type="Node" parent="."]
script = ExtResource("8_uotso")

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=20 format=3 uid="uid://dxt0e2ugmttqq"]
[gd_scene load_steps=22 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"]
@@ -13,11 +13,20 @@
[ext_resource type="PackedScene" uid="uid://bctpe34ddamg5" path="res://components/knockback/CKnockback.tscn" id="10_jqqi6"]
[ext_resource type="Resource" uid="uid://cektf6waf4s04" path="res://scenes/enemies/grounded_enemy/grounded_enemy_knockback.tres" id="11_8k3xb"]
[sub_resource type="ViewportTexture" id="ViewportTexture_18xwy"]
viewport_path = NodePath("SubViewport")
[sub_resource type="Resource" id="Resource_qj0ob"]
script = ExtResource("2_r3cnf")
Modifier = 1.0
metadata/_custom_type_script = "uid://b6y3ugfydvch0"
[sub_resource type="Resource" id="Resource_18xwy"]
script = ExtResource("2_r3cnf")
DamageType = 3
Modifier = 1.0
metadata/_custom_type_script = "uid://b6y3ugfydvch0"
[sub_resource type="Resource" id="Resource_6d4gl"]
script = ExtResource("8_6d4gl")
Speed = 5.0
@@ -56,11 +65,12 @@ 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)
transform = Transform3D(0.4, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.2, 0)
texture = SubResource("ViewportTexture_18xwy")
[node name="CDamageable" type="Node" parent="."]
script = ExtResource("7_1tw73")
DamageModifiers = Array[Object]([SubResource("Resource_qj0ob")])
DamageModifiers = Array[Object]([SubResource("Resource_qj0ob"), SubResource("Resource_18xwy")])
metadata/_custom_type_script = "uid://b0u23nkpaimyc"
[node name="CMovement" parent="." node_paths=PackedStringArray("WallInFrontRayCast") instance=ExtResource("7_qyswd")]
@@ -68,6 +78,7 @@ RMovement = SubResource("Resource_6d4gl")
WallInFrontRayCast = NodePath("../WallInFrontRayCast")
[node name="CKnockback" parent="." instance=ExtResource("10_jqqi6")]
RKnockback = ExtResource("11_8k3xb")
[node name="CTarget" type="Marker3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)

58
scenes/ui/Healthbar.cs Normal file
View File

@@ -0,0 +1,58 @@
using Godot;
using System;
[GlobalClass]
public partial class Healthbar : ProgressBar
{
private Timer _damageCatchUpTimer;
private ProgressBar _damagedHealth;
private float _currentHealth;
public float CurrentHealth
{
get => _currentHealth;
set => SetHealth(value);
}
public override void _Ready()
{
_damageCatchUpTimer = GetNode<Timer>("DamageCatchUp");
_damagedHealth = GetNode<ProgressBar>("Damagebar");
_damageCatchUpTimer.Timeout += OnDamageCatchUp;
Visible = false;
}
public void Initialize(float initialHealth)
{
_currentHealth = initialHealth;
MaxValue = initialHealth;
Value = initialHealth;
_damagedHealth.MaxValue = initialHealth;
_damagedHealth.Value = initialHealth;
}
public void SetHealth(float newHealth)
{
var previousHealth = _currentHealth;
_currentHealth = Mathf.Min(newHealth, (float) MaxValue);
_currentHealth = newHealth;
Value = _currentHealth;
Visible = _currentHealth < MaxValue;
if (_currentHealth < previousHealth)
{
_damageCatchUpTimer.Start();
}
else
{
_damagedHealth.Value = _currentHealth;
}
}
public void OnDamageCatchUp()
{
_damagedHealth.Value = _currentHealth;
}
}

View File

@@ -0,0 +1 @@
uid://l5cjcaehyssk

49
scenes/ui/healthbar.tscn Normal file
View File

@@ -0,0 +1,49 @@
[gd_scene load_steps=6 format=3 uid="uid://cyw8p0p6a78tl"]
[ext_resource type="Script" uid="uid://l5cjcaehyssk" path="res://scenes/ui/Healthbar.cs" id="1_0k5hr"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_0sgot"]
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_0k5hr"]
bg_color = Color(0.698864, 0.047356047, 0, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_0sgot"]
bg_color = Color(0.14767182, 0.14767182, 0.14767176, 1)
expand_margin_left = 2.0
expand_margin_top = 2.0
expand_margin_right = 2.0
expand_margin_bottom = 2.0
shadow_color = Color(0, 0, 0, 0.27450982)
shadow_offset = Vector2(0, 1)
[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_kl70x"]
bg_color = Color(0.8862616, 0.88626146, 0.8862615, 1)
[node name="Healthbar" type="ProgressBar"]
z_index = 10
custom_minimum_size = Vector2(512, 12)
offset_right = 512.0
offset_bottom = 12.0
theme_override_styles/background = SubResource("StyleBoxEmpty_0sgot")
theme_override_styles/fill = SubResource("StyleBoxFlat_0k5hr")
value = 60.0
show_percentage = false
script = ExtResource("1_0k5hr")
[node name="Damagebar" type="ProgressBar" parent="."]
z_index = -10
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_styles/background = SubResource("StyleBoxFlat_0sgot")
theme_override_styles/fill = SubResource("StyleBoxFlat_kl70x")
value = 80.0
show_percentage = false
[node name="DamageCatchUp" type="Timer" parent="."]
wait_time = 0.8
one_shot = true
ignore_time_scale = true

View File

@@ -118,7 +118,7 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer
if (enemy is IDamageable damageable)
{
damageable.TakeDamage(new DamageRecord(this, RDamage));
damageable.TakeDamage(new DamageRecord(GlobalPosition, RDamage));
}
}