Compare commits

..

5 Commits

Author SHA1 Message Date
eb1c7f78fa flying knockback as well
Some checks failed
Create tag and build when new code gets to main / BumpTag (push) Successful in 19s
Create tag and build when new code gets to main / Export (push) Has been cancelled
2026-01-18 16:58:23 +01:00
35b9ea383c knockback component 2026-01-18 12:39:01 +01:00
9690280cd7 better spawning
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 20s
Create tag and build when new code gets to main / Export (push) Successful in 10m36s
2026-01-18 10:27:21 +01:00
65538495c4 spawning
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 19s
Create tag and build when new code gets to main / Export (push) Successful in 9m59s
2026-01-17 23:18:06 +01:00
561e026834 ok so this should be the way to go
All checks were successful
Create tag and build when new code gets to main / BumpTag (push) Successful in 20s
Create tag and build when new code gets to main / Export (push) Successful in 10m24s
2026-01-17 21:51:57 +01:00
36 changed files with 410 additions and 132 deletions

View File

@@ -0,0 +1,9 @@
using Godot;
namespace Movementtests.interfaces;
public interface IDamageDealer
{
[Export]
RDamage RDamage { get; set; }
}

View File

@@ -1,9 +0,0 @@
using Godot;
namespace Movementtests.interfaces;
public interface IDamageMaker
{
[Export]
RDamage GetDamageDealt { get; set; }
}

View File

@@ -1,8 +1,12 @@
using System; using System;
using Godot;
namespace Movementtests.interfaces; namespace Movementtests.interfaces;
public record DamageRecord(Node3D Source, RDamage Damage);
public interface IDamageable public interface IDamageable
{ {
float TakeDamage(RDamage damage); event Action<IDamageable, DamageRecord> DamageTaken;
DamageRecord TakeDamage(DamageRecord damageRecord);
} }

View File

@@ -1,6 +1,16 @@
using System;
using Godot;
namespace Movementtests.interfaces; namespace Movementtests.interfaces;
public interface IHealthable public interface IHealthable
{ {
void ReduceHealth(float amount); event Action<IHealthable, float> HealthChanged;
event Action<IHealthable> HealthDepleted;
[Export] RHealth RHealth { get; set; }
float CurrentHealth { get; set; }
void ReduceHealth(IDamageable source, DamageRecord damageRecord);
} }

View File

@@ -2,5 +2,5 @@ namespace Movementtests.interfaces;
public interface IKillable public interface IKillable
{ {
void Kill(); void Kill(IHealthable source);
} }

View File

@@ -1,6 +1,11 @@
using Godot;
namespace Movementtests.interfaces; namespace Movementtests.interfaces;
public interface IKnockbackable public interface IKnockbackable
{ {
[Export] RKnockback RKnockback { get; set;}
public void RegisterKnockback(IDamageable source, DamageRecord damageRecord);
public Vector3 ComputeKnockback();
} }

View File

@@ -11,5 +11,6 @@ public record MovementInputs(
public interface IMoveable public interface IMoveable
{ {
[Export] RMovement RMovement { get; set; }
Vector3 ComputeVelocity(MovementInputs inputs); Vector3 ComputeVelocity(MovementInputs inputs);
} }

View File

@@ -3,5 +3,5 @@ using Godot;
interface ISpawnable interface ISpawnable
{ {
void TestMethod(); void Initialize();
} }

View File

@@ -1,14 +1,21 @@
[gd_scene load_steps=10 format=3 uid="uid://q7uc1h2jpbd2"] [gd_scene load_steps=20 format=3 uid="uid://q7uc1h2jpbd2"]
[ext_resource type="PackedScene" uid="uid://bei4nhkf8lwdo" path="res://player_controller/PlayerController.tscn" id="1_62kkh"] [ext_resource type="PackedScene" uid="uid://bei4nhkf8lwdo" path="res://player_controller/PlayerController.tscn" id="1_62kkh"]
[ext_resource type="Material" uid="uid://31aulub2nqov" path="res://assets/greybox/m_greybox.tres" id="2_3uydm"] [ext_resource type="Material" uid="uid://31aulub2nqov" path="res://assets/greybox/m_greybox.tres" id="2_3uydm"]
[ext_resource type="Script" uid="uid://jitubgv6judn" path="res://resource_definitions/RDamage.cs" id="2_sysok"] [ext_resource type="Script" uid="uid://jitubgv6judn" path="res://resource_definitions/RDamage.cs" id="2_sysok"]
[ext_resource type="PackedScene" uid="uid://dxt0e2ugmttqq" path="res://scenes/enemies/first_enemy/first_enemy.tscn" id="3_3uydm"] [ext_resource type="PackedScene" uid="uid://dxt0e2ugmttqq" path="res://scenes/enemies/grounded_enemy/grounded_enemy.tscn" id="3_3uydm"]
[ext_resource type="Script" uid="uid://b4cwruitopcee" path="res://resource_definitions/RDeathEffect.cs" id="5_7m3bq"]
[ext_resource type="PackedScene" uid="uid://cmlud1hwkd6sv" path="res://scenes/enemies/flying_enemy/flying_enemy.tscn" id="5_8fd2t"] [ext_resource type="PackedScene" uid="uid://cmlud1hwkd6sv" path="res://scenes/enemies/flying_enemy/flying_enemy.tscn" id="5_8fd2t"]
[ext_resource type="PackedScene" uid="uid://c305mfrtumcyq" path="res://scenes/spawners/spawner.tscn" id="6_7m3bq"]
[ext_resource type="Resource" uid="uid://bqq6uukbdfysr" path="res://scenes/enemies/grounded_enemy/grounded_enemy_movement.tres" id="7_caohq"]
[ext_resource type="Script" uid="uid://baiapod3csndf" path="res://resource_definitions/RHealth.cs" id="9_2e4ci"]
[ext_resource type="Resource" uid="uid://otfc2snh8umc" path="res://scenes/enemies/grounded_enemy/grounded_enemy_damage.tres" id="9_dmw1t"]
[ext_resource type="Resource" uid="uid://dgo65k2ceqfvy" path="res://scenes/enemies/flying_enemy/flying_enemy_damage.tres" id="9_gp7s3"]
[ext_resource type="Resource" uid="uid://bwqjaom4k7rc3" path="res://scenes/enemies/flying_enemy/flying_enemy_movement.tres" id="10_spw1u"]
[ext_resource type="Resource" uid="uid://dg1xbjhyhgnnk" path="res://scenes/enemies/flying_enemy/flying_enemy_health.tres" id="11_2e4ci"]
[sub_resource type="Resource" id="Resource_gp7s3"] [sub_resource type="Resource" id="Resource_2e4ci"]
script = ExtResource("2_sysok") script = ExtResource("2_sysok")
DamageDealt = 3.0
metadata/_custom_type_script = "uid://jitubgv6judn" metadata/_custom_type_script = "uid://jitubgv6judn"
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_0xm2m"] [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_0xm2m"]
@@ -33,12 +40,21 @@ ssil_radius = 8.4
sdfgi_use_occlusion = true sdfgi_use_occlusion = true
glow_enabled = true glow_enabled = true
[sub_resource type="Resource" id="Resource_sysok"]
script = ExtResource("5_7m3bq")
metadata/_custom_type_script = "uid://b4cwruitopcee"
[sub_resource type="Resource" id="Resource_ybosk"]
script = ExtResource("9_2e4ci")
StartingHealth = 1.0
metadata/_custom_type_script = "uid://baiapod3csndf"
[node name="Main" type="Node3D"] [node name="Main" type="Node3D"]
[node name="Player" parent="." instance=ExtResource("1_62kkh")] [node name="Player" parent="." instance=ExtResource("1_62kkh")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 7.5) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 7.5)
TutorialDone = true TutorialDone = true
GetDamageDealt = SubResource("Resource_gp7s3") RDamage = SubResource("Resource_2e4ci")
[node name="WorldEnvironment" type="WorldEnvironment" parent="."] [node name="WorldEnvironment" type="WorldEnvironment" parent="."]
environment = SubResource("Environment_1bvp3") environment = SubResource("Environment_1bvp3")
@@ -103,6 +119,7 @@ material = ExtResource("2_3uydm")
[node name="Enemy" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("3_3uydm")] [node name="Enemy" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("3_3uydm")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -16.83681) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, -16.83681)
Target = NodePath("../Player") Target = NodePath("../Player")
DeathEffects = Array[Object]([SubResource("Resource_sysok")])
[node name="Enemy2" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("3_3uydm")] [node name="Enemy2" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("3_3uydm")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0, -16.83681) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -3, 0, -16.83681)
@@ -119,3 +136,21 @@ Target = NodePath("../Player")
[node name="FlyingEnemy2" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("5_8fd2t")] [node name="FlyingEnemy2" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("5_8fd2t")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 10, 7, -16) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 10, 7, -16)
Target = NodePath("../Player") Target = NodePath("../Player")
[node name="GroundedSpawner" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("6_7m3bq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 12, 2.5, -15)
EnemyToSpawn = ExtResource("3_3uydm")
MovementInputs = ExtResource("7_caohq")
HealthInputs = SubResource("Resource_ybosk")
DamageInputs = ExtResource("9_dmw1t")
Target = NodePath("../Player")
IsActiveOnStart = false
[node name="FlyingSpawner" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("6_7m3bq")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 18, 11, -14)
EnemyToSpawn = ExtResource("5_8fd2t")
MovementInputs = ExtResource("10_spw1u")
HealthInputs = ExtResource("11_2e4ci")
DamageInputs = ExtResource("9_gp7s3")
Target = NodePath("../Player")
IsActiveOnStart = false

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=40 format=3 uid="uid://dmkw8cmalm5k"] [gd_scene load_steps=45 format=3 uid="uid://dmkw8cmalm5k"]
[ext_resource type="PackedScene" uid="uid://bei4nhkf8lwdo" path="res://player_controller/PlayerController.tscn" id="1_2vsi6"] [ext_resource type="PackedScene" uid="uid://bei4nhkf8lwdo" path="res://player_controller/PlayerController.tscn" id="1_2vsi6"]
[ext_resource type="Script" uid="uid://blenis2y55fmg" path="res://tools/city_helpers.gd" id="1_qwuk2"] [ext_resource type="Script" uid="uid://blenis2y55fmg" path="res://tools/city_helpers.gd" id="1_qwuk2"]
@@ -23,6 +23,10 @@
[ext_resource type="Texture2D" uid="uid://cjh5cnvdbq5ku" path="res://assets/ui/input-prompts/Xbox Series/Vector/xbox_button_b_outline.svg" id="19_efsse"] [ext_resource type="Texture2D" uid="uid://cjh5cnvdbq5ku" path="res://assets/ui/input-prompts/Xbox Series/Vector/xbox_button_b_outline.svg" id="19_efsse"]
[ext_resource type="Texture2D" uid="uid://nrhxjdpuje3f" path="res://assets/ui/input-prompts/Xbox Series/Vector/xbox_lt_outline.svg" id="20_crf87"] [ext_resource type="Texture2D" uid="uid://nrhxjdpuje3f" path="res://assets/ui/input-prompts/Xbox Series/Vector/xbox_lt_outline.svg" id="20_crf87"]
[ext_resource type="Texture2D" uid="uid://dyjvbsvbriii4" path="res://assets/ui/input-prompts/Xbox Series/Vector/xbox_rb_outline.svg" id="23_p287n"] [ext_resource type="Texture2D" uid="uid://dyjvbsvbriii4" path="res://assets/ui/input-prompts/Xbox Series/Vector/xbox_rb_outline.svg" id="23_p287n"]
[ext_resource type="PackedScene" uid="uid://c305mfrtumcyq" path="res://scenes/spawners/spawner.tscn" id="24_qwuk2"]
[ext_resource type="PackedScene" uid="uid://dxt0e2ugmttqq" path="res://scenes/enemies/grounded_enemy/grounded_enemy.tscn" id="25_nrosh"]
[ext_resource type="PackedScene" uid="uid://cmlud1hwkd6sv" path="res://scenes/enemies/flying_enemy/flying_enemy.tscn" id="25_x7fl1"]
[ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://resource_definitions/RMovement.cs" id="26_lu3yt"]
[sub_resource type="LabelSettings" id="LabelSettings_2k3fr"] [sub_resource type="LabelSettings" id="LabelSettings_2k3fr"]
font_size = 30 font_size = 30
@@ -89,6 +93,12 @@ adjustment_enabled = true
[sub_resource type="BoxMesh" id="BoxMesh_p287n"] [sub_resource type="BoxMesh" id="BoxMesh_p287n"]
[sub_resource type="Resource" id="Resource_pxspk"]
script = ExtResource("26_lu3yt")
Speed = 7.0
TargetHeight = 15.0
metadata/_custom_type_script = "uid://dtpxijlnb2c5"
[node name="Main" type="Node3D"] [node name="Main" type="Node3D"]
script = ExtResource("1_qwuk2") script = ExtResource("1_qwuk2")
@@ -436,6 +446,17 @@ spot_range = 47.233
spot_angle = 18.85 spot_angle = 18.85
spot_angle_attenuation = 10.556052 spot_angle_attenuation = 10.556052
[node name="Spawner" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("24_qwuk2")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 19, 43, -111.5)
EnemyToSpawn = ExtResource("25_x7fl1")
MovementInputs = SubResource("Resource_pxspk")
Target = NodePath("../Player")
[node name="Spawner2" parent="." node_paths=PackedStringArray("Target") instance=ExtResource("24_qwuk2")]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 31, 7.5, -88)
EnemyToSpawn = ExtResource("25_nrosh")
Target = NodePath("../Player")
[connection signal="timeout" from="TutorialController/WaitToShowBlockingTuto" to="TutorialController" method="_show_weapon_tutorial"] [connection signal="timeout" from="TutorialController/WaitToShowBlockingTuto" to="TutorialController" method="_show_weapon_tutorial"]
[connection signal="body_exited" from="TutoTriggers/TriggerTutoMove" to="TutorialController" method="hide_tutorials"] [connection signal="body_exited" from="TutoTriggers/TriggerTutoMove" to="TutorialController" method="hide_tutorials"]
[connection signal="body_entered" from="TutoTriggers/TriggerTutoMantle" to="TutorialController" method="_on_tuto_mantle_body_entered"] [connection signal="body_entered" from="TutoTriggers/TriggerTutoMantle" to="TutorialController" method="_on_tuto_mantle_body_entered"]

View File

@@ -1,8 +1,7 @@
[gd_scene load_steps=56 format=3 uid="uid://bei4nhkf8lwdo"] [gd_scene load_steps=54 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="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"] [ext_resource type="PackedScene" uid="uid://cf3rrgr1imvv4" path="res://scenes/path/path.tscn" id="2_6lejt"]
[ext_resource type="Script" uid="uid://jitubgv6judn" path="res://resource_definitions/RDamage.cs" id="2_q14ux"]
[ext_resource type="Resource" uid="uid://bl5crtu1gkrtr" path="res://systems/inputs/base_mode/base_mode.tres" id="3_cresl"] [ext_resource type="Resource" uid="uid://bl5crtu1gkrtr" path="res://systems/inputs/base_mode/base_mode.tres" id="3_cresl"]
[ext_resource type="Script" uid="uid://b0u23nkpaimyc" path="res://scenes/damage/CDamageable.cs" id="4_q7bng"] [ext_resource type="Script" uid="uid://b0u23nkpaimyc" path="res://scenes/damage/CDamageable.cs" id="4_q7bng"]
[ext_resource type="Resource" uid="uid://cpdaw41ah5gic" path="res://systems/inputs/base_mode/rotate_y.tres" id="4_rxwoh"] [ext_resource type="Resource" uid="uid://cpdaw41ah5gic" path="res://systems/inputs/base_mode/rotate_y.tres" id="4_rxwoh"]
@@ -46,11 +45,6 @@
[ext_resource type="Texture2D" uid="uid://chvt6g0xn5c2m" path="res://systems/dash/light-ring.jpg" id="32_lgpc8"] [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="Script" uid="uid://b4dwolbvt8our" path="res://addons/godot_state_charts/history_state.gd" id="41_ruloh"]
[sub_resource type="Resource" id="Resource_m8gvy"]
script = ExtResource("2_q14ux")
DamageDealt = 3.0
metadata/_custom_type_script = "uid://jitubgv6judn"
[sub_resource type="Resource" id="Resource_jb43f"] [sub_resource type="Resource" id="Resource_jb43f"]
script = ExtResource("5_q7bng") script = ExtResource("5_q7bng")
Modifier = 3.0 Modifier = 3.0
@@ -88,7 +82,6 @@ blend_mode = 1
[node name="Player" type="CharacterBody3D" node_paths=PackedStringArray("CDamage")] [node name="Player" type="CharacterBody3D" node_paths=PackedStringArray("CDamage")]
collision_mask = 272 collision_mask = 272
script = ExtResource("1_poq2x") script = ExtResource("1_poq2x")
GetDamageDealt = SubResource("Resource_m8gvy")
CDamage = NodePath("CDamageable") CDamage = NodePath("CDamageable")
WalkSpeed = 7.5 WalkSpeed = 7.5
AccelerationFloor = 4.0 AccelerationFloor = 4.0
@@ -335,6 +328,7 @@ offset_left = 1524.0
offset_top = 1.0 offset_top = 1.0
offset_right = -8.0 offset_right = -8.0
offset_bottom = 1.0 offset_bottom = 1.0
enabled = false
initial_node_to_watch = NodePath("../StateChart") initial_node_to_watch = NodePath("../StateChart")
[node name="UI" type="Control" parent="."] [node name="UI" type="Control" parent="."]

View File

@@ -7,7 +7,9 @@ using Movementtests.systems;
using Movementtests.player_controller.Scripts; using Movementtests.player_controller.Scripts;
using RustyOptions; using RustyOptions;
public partial class PlayerController : CharacterBody3D, IDamageable, IKnockbackable, IDamageMaker public partial class PlayerController : CharacterBody3D,
IDamageable,
IDamageDealer
{ {
// Enums // Enums
public enum AllowedInputs public enum AllowedInputs
@@ -33,6 +35,8 @@ public partial class PlayerController : CharacterBody3D, IDamageable, IKnockback
// Signals and events // // Signals and events //
/////////////////////////// ///////////////////////////
public event Action<IDamageable, DamageRecord> DamageTaken;
/////////////////////////// ///////////////////////////
// Public stuff // // Public stuff //
/////////////////////////// ///////////////////////////
@@ -66,7 +70,7 @@ public partial class PlayerController : CharacterBody3D, IDamageable, IKnockback
[ExportCategory("Combat")] [ExportCategory("Combat")]
[ExportGroup("Damage")] [ExportGroup("Damage")]
[Export] [Export]
public RDamage GetDamageDealt { get; set; } public RDamage RDamage { get; set; }
[Export] [Export]
public CDamageable CDamage { get; set; } public CDamageable CDamage { get; set; }
@@ -1733,9 +1737,11 @@ public partial class PlayerController : CharacterBody3D, IDamageable, IKnockback
} }
} }
public float TakeDamage(RDamage damage) public DamageRecord TakeDamage(DamageRecord damageRecord)
{ {
return CDamage.TakeDamage(damage); var finalDamage = CDamage.TakeDamage(damageRecord);
DamageTaken?.Invoke(this, finalDamage);
return finalDamage;
} }
/////////////////////////// ///////////////////////////
@@ -1753,7 +1759,7 @@ public partial class PlayerController : CharacterBody3D, IDamageable, IKnockback
foreach (var body in bodies) foreach (var body in bodies)
{ {
if(body is IDamageable spawnable) if(body is IDamageable spawnable)
spawnable.TakeDamage(GetDamageDealt); spawnable.TakeDamage(new DamageRecord(this, RDamage));
} }
} }
} }

View File

@@ -6,6 +6,8 @@ using Movementtests.systems.damage;
[GlobalClass] [GlobalClass]
public partial class RDamageModifier : Resource, IDamageable public partial class RDamageModifier : Resource, IDamageable
{ {
public event Action<IDamageable, DamageRecord> DamageTaken;
[Export] [Export]
public EDamageTypes DamageType = EDamageTypes.Normal; public EDamageTypes DamageType = EDamageTypes.Normal;
[Export] [Export]
@@ -22,10 +24,14 @@ public partial class RDamageModifier : Resource, IDamageable
DamageType = damageType; DamageType = damageType;
} }
public float TakeDamage(RDamage damage) public DamageRecord TakeDamage(DamageRecord damageRecord)
{ {
if (damage.DamageType != DamageType) return 0; if (damageRecord.Damage.DamageType != DamageType)
var finalDamage = damage.DamageDealt * Modifier; return damageRecord with { Damage = new RDamage(0, damageRecord.Damage.DamageType) };
return finalDamage;
var finalDamage = damageRecord.Damage.DamageDealt * Modifier;
var finalDamageRecord = damageRecord with { Damage = new RDamage(finalDamage, damageRecord.Damage.DamageType) };
DamageTaken?.Invoke(this, finalDamageRecord);
return finalDamageRecord;
} }
} }

View File

@@ -5,8 +5,8 @@ using Movementtests.interfaces;
[GlobalClass] [GlobalClass]
public partial class RDeathEffect : Resource, IKillable public partial class RDeathEffect : Resource, IKillable
{ {
public void Kill() public void Kill(IHealthable source)
{ {
GD.Print("Death Effect triggered"); GD.Print($"Death Effect triggered on {source}");
} }
} }

View File

@@ -0,0 +1,19 @@
using Godot;
using System;
using Movementtests.interfaces;
[GlobalClass]
public partial class RKnockback : Resource
{
[Export]
public float Modifier = 1.0f;
public RKnockback()
{
Modifier = 1.0f;
}
public RKnockback(float modifier)
{
Modifier = modifier;
}
}

View File

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

View File

@@ -5,19 +5,27 @@ using System;
public partial class RMovement : Resource public partial class RMovement : Resource
{ {
[Export(PropertyHint.Range, "0,10,0.1,or_greater")] [Export(PropertyHint.Range, "0,10,0.1,or_greater")]
public float Speed; public float Speed { get; set;}
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
public float Acceleration { get; set;}
[Export(PropertyHint.Range, "0,10,0.1,or_greater")]
public float GravityModifier { get; set;}
[Export(PropertyHint.Range, "0,20,1,or_greater")] [Export(PropertyHint.Range, "0,20,1,or_greater")]
public float TargetHeight; public float TargetHeight { get; set;}
public RMovement() public RMovement()
{ {
Speed = 3.0f; Speed = 3.0f;
Acceleration = 1.0f;
GravityModifier = 1.0f;
TargetHeight = 10.0f; TargetHeight = 10.0f;
} }
public RMovement(float speed, float targetHeight) public RMovement(float speed, float acceleration, float gravityModifier, float targetHeight)
{ {
Speed = speed; Speed = speed;
Acceleration = acceleration;
GravityModifier = gravityModifier;
TargetHeight = targetHeight; TargetHeight = targetHeight;
} }
} }

View File

@@ -5,18 +5,19 @@ using Movementtests.interfaces;
[GlobalClass] [GlobalClass]
public partial class CDamageable : Node, IDamageable public partial class CDamageable : Node, IDamageable
{ {
[Signal] public event Action<IDamageable, DamageRecord> DamageTaken;
public delegate void DamageTakenEventHandler(float damageTaken);
[Export] [Export]
public RDamageModifier[] DamageModifiers { get; set; } public RDamageModifier[] DamageModifiers { get; set; }
public float TakeDamage(RDamage damage)
public DamageRecord TakeDamage(DamageRecord damageRecord)
{ {
var finalDamage = 0f; var finalDamage = 0f;
foreach (var damageable in DamageModifiers.ToIDamageables()) foreach (var damageable in DamageModifiers.ToIDamageables())
finalDamage += damageable.TakeDamage(damage); finalDamage += damageable.TakeDamage(damageRecord).Damage.DamageDealt;
EmitSignalDamageTaken(finalDamage); var finalDamageRecord = damageRecord with { Damage = new RDamage(finalDamage, damageRecord.Damage.DamageType) };
return finalDamage; DamageTaken?.Invoke(this, finalDamageRecord);
return finalDamageRecord;
} }
} }

View File

@@ -1,36 +1,85 @@
using System;
using Godot; using Godot;
using Movementtests.interfaces; using Movementtests.interfaces;
[GlobalClass] [GlobalClass]
public partial class Enemy : CharacterBody3D, IDamageable, IDamageMaker, IHealthable, IKillable public partial class Enemy : CharacterBody3D,
IDamageable,
IDamageDealer,
IHealthable,
IKillable,
IMoveable,
ISpawnable,
IKnockbackable
{ {
// Signals and events
public event Action<IDamageable, DamageRecord> DamageTaken;
public event Action<IHealthable, float> HealthChanged;
public event Action<IHealthable> HealthDepleted;
// Public export components
[Export] [Export]
public Node3D Target { get; set; } public Node3D Target { get; set; }
[ExportGroup("Health")]
[Export] [Export]
public RDamage GetDamageDealt { get; set; } public Node CHealth { get; set; }
[Export] [Export]
public CHealth CHealth { get; set; } public RHealth RHealth { get; set; }
[Export]
public CDamageable CDamage { get; set; }
[Export]
public Node CMovement { get; set; }
[Export] [Export]
public RDeathEffect[] DeathEffects { get; set; } public RDeathEffect[] DeathEffects { get; set; }
[ExportGroup("Damage")]
[Export]
public Node CDamage { get; set; }
[Export]
public RDamage RDamage { get; set; }
[Export]
public Node CKnockback { get; set; }
[Export]
public RKnockback RKnockback { get; set; }
[ExportGroup("Movement")]
[Export]
public Node CMovement { get; set; }
[Export]
public RMovement RMovement { get; set; }
// Public stuff
public float CurrentHealth { get; set; }
// Private stuff
private Area3D _damageBox; private Area3D _damageBox;
public override void _Ready() public override void _Ready()
{
Initialize();
SetupSignals();
}
public void Initialize()
{ {
_damageBox = GetNode<Area3D>("DamageBox"); _damageBox = GetNode<Area3D>("DamageBox");
if (CMovement is IMoveable moveable && RMovement != null) moveable.RMovement = RMovement;
if (CHealth is IHealthable healthable && RHealth != null)
{
healthable.RHealth = RHealth;
healthable.CurrentHealth = RHealth.StartingHealth;
}
if (CKnockback is IKnockbackable knockbackable && RKnockback != null) knockbackable.RKnockback = RKnockback;
}
public void SetupSignals()
{
_damageBox.BodyEntered += OnDamageBoxTriggered; _damageBox.BodyEntered += OnDamageBoxTriggered;
CDamage.DamageTaken += ReduceHealth; if (CDamage is IDamageable damageable)
CHealth.Dead += Kill; {
damageable.DamageTaken += ReduceHealth;
damageable.DamageTaken += RegisterKnockback;
}
if (CHealth is IHealthable healthable) healthable.HealthDepleted += Kill;
} }
public override void _PhysicsProcess(double delta) public override void _PhysicsProcess(double delta)
@@ -38,8 +87,6 @@ public partial class Enemy : CharacterBody3D, IDamageable, IDamageMaker, IHealth
var targetPlanar = new Vector3(Target.GlobalPosition.X, GlobalPosition.Y, Target.GlobalPosition.Z); var targetPlanar = new Vector3(Target.GlobalPosition.X, GlobalPosition.Y, Target.GlobalPosition.Z);
LookAt(targetPlanar); LookAt(targetPlanar);
if (CMovement is not IMoveable movement) return;
var inputs = new MovementInputs( var inputs = new MovementInputs(
Velocity: Velocity, Velocity: Velocity,
TargetLocation: Target.GlobalPosition, TargetLocation: Target.GlobalPosition,
@@ -47,33 +94,61 @@ public partial class Enemy : CharacterBody3D, IDamageable, IDamageMaker, IHealth
gravity: GetGravity(), gravity: GetGravity(),
delta: delta delta: delta
); );
Velocity = movement!.ComputeVelocity(inputs); Velocity = ComputeVelocity(inputs);
Velocity += ComputeKnockback();
MoveAndSlide(); MoveAndSlide();
} }
public Vector3 ComputeVelocity(MovementInputs inputs)
{
if (CMovement is not IMoveable movement) return Vector3.Zero;
return movement!.ComputeVelocity(inputs);
}
public void OnDamageBoxTriggered(Node3D body) public void OnDamageBoxTriggered(Node3D body)
{ {
GD.Print("Take this!"); if (body is not IDamageable damageable) return;
if(body is IDamageable damageable) damageable.TakeDamage(GetDamageDealt);
var damageRecord = new DamageRecord(this, RDamage);
damageable.TakeDamage(damageRecord);
} }
public float TakeDamage(RDamage damage) public DamageRecord TakeDamage(DamageRecord damageRecord)
{ {
GD.Print("Ouch!"); if (CDamage is not IDamageable damageable)
return CDamage.TakeDamage(damage); return damageRecord with { Damage = new RDamage(0, damageRecord.Damage.DamageType) };
var finalDamage = damageable.TakeDamage(damageRecord);
DamageTaken?.Invoke(this, finalDamage);
GD.Print($"Received damage: {finalDamage.Damage.DamageDealt}");
return finalDamage;
} }
public void ReduceHealth(float amount) public void ReduceHealth(IDamageable source, DamageRecord damageRecord)
{ {
CHealth.ReduceHealth(amount); if (CHealth is not IHealthable healthable) return;
healthable.ReduceHealth(source, damageRecord);
} }
public void Kill() public void Kill(IHealthable source)
{ {
foreach (var killable in DeathEffects.ToIKillables()) foreach (var killable in DeathEffects.ToIKillables())
{ {
killable.Kill(); killable.Kill(source);
} }
QueueFree(); QueueFree();
} }
public void RegisterKnockback(IDamageable source, DamageRecord damageRecord)
{
if (CKnockback is not IKnockbackable knockbackable) return;
knockbackable.RegisterKnockback(source, damageRecord);
}
public Vector3 ComputeKnockback()
{
if (CKnockback is not IKnockbackable knockbackable) return Vector3.Zero;
return knockbackable.ComputeKnockback();
}
} }

View File

@@ -1,18 +1,16 @@
[gd_scene load_steps=18 format=3 uid="uid://cmlud1hwkd6sv"] [gd_scene load_steps=20 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://bn7sc6id7n166" path="res://scenes/enemies/Enemy.cs" id="1_q8l7o"]
[ext_resource type="Script" uid="uid://b6y3ugfydvch0" path="res://resource_definitions/RDamageModifier.cs" id="2_1bsgx"] [ext_resource type="Script" uid="uid://b6y3ugfydvch0" path="res://resource_definitions/RDamageModifier.cs" id="2_1bsgx"]
[ext_resource type="Resource" uid="uid://dg1xbjhyhgnnk" path="res://scenes/enemies/flying_enemy/flying_enemy_health.tres" id="2_ma2bq"]
[ext_resource type="Resource" uid="uid://dgo65k2ceqfvy" path="res://scenes/enemies/flying_enemy/flying_enemy_damage.tres" id="2_on7rt"] [ext_resource type="Resource" uid="uid://dgo65k2ceqfvy" path="res://scenes/enemies/flying_enemy/flying_enemy_damage.tres" id="2_on7rt"]
[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://scenes/health/CHealth.cs" id="4_ys4jv"] [ext_resource type="Script" uid="uid://bjwrpv3jpsc1e" path="res://scenes/health/CHealth.cs" id="4_ys4jv"]
[ext_resource type="Script" uid="uid://baiapod3csndf" path="res://resource_definitions/RHealth.cs" id="5_irbqc"]
[ext_resource type="PackedScene" uid="uid://dmw5ibwrb483f" path="res://scenes/movement/CFlyingMovement.tscn" id="7_vaeds"] [ext_resource type="PackedScene" uid="uid://dmw5ibwrb483f" path="res://scenes/movement/CFlyingMovement.tscn" id="7_vaeds"]
[ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://resource_definitions/RMovement.cs" id="8_on7rt"] [ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://resource_definitions/RMovement.cs" id="8_on7rt"]
[ext_resource type="Script" uid="uid://b0u23nkpaimyc" path="res://scenes/damage/CDamageable.cs" id="8_uotso"] [ext_resource type="Script" uid="uid://b0u23nkpaimyc" path="res://scenes/damage/CDamageable.cs" id="8_uotso"]
[ext_resource type="PackedScene" uid="uid://bctpe34ddamg5" path="res://scenes/knockback/CKnockback.tscn" id="10_dejyg"]
[sub_resource type="Resource" id="Resource_aarbi"] [ext_resource type="Resource" uid="uid://dt7a1io5o0b8s" path="res://scenes/enemies/flying_enemy/flying_enemy_knockback.tres" id="11_mpa2u"]
script = ExtResource("5_irbqc")
StartingHealth = 50.0
metadata/_custom_type_script = "uid://baiapod3csndf"
[sub_resource type="Resource" id="Resource_jnv07"] [sub_resource type="Resource" id="Resource_jnv07"]
script = ExtResource("2_1bsgx") script = ExtResource("2_1bsgx")
@@ -23,9 +21,9 @@ script = ExtResource("2_1bsgx")
DamageType = 1 DamageType = 1
metadata/_custom_type_script = "uid://b6y3ugfydvch0" metadata/_custom_type_script = "uid://b6y3ugfydvch0"
[sub_resource type="Resource" id="Resource_ma2bq"] [sub_resource type="Resource" id="Resource_on7rt"]
script = ExtResource("8_on7rt") script = ExtResource("8_on7rt")
Speed = 2.0 Speed = 3.0
TargetHeight = 10.0 TargetHeight = 10.0
metadata/_custom_type_script = "uid://dtpxijlnb2c5" metadata/_custom_type_script = "uid://dtpxijlnb2c5"
@@ -45,20 +43,24 @@ albedo_color = Color(0.06469653, 0.06469653, 0.06469653, 1)
[sub_resource type="BoxShape3D" id="BoxShape3D_4yfjf"] [sub_resource type="BoxShape3D" id="BoxShape3D_4yfjf"]
size = Vector3(1, 1, 1.5) size = Vector3(1, 1, 1.5)
[node name="FlyingEnemy" type="CharacterBody3D" node_paths=PackedStringArray("CHealth", "CDamage", "CMovement")] [node name="FlyingEnemy" type="CharacterBody3D" node_paths=PackedStringArray("CHealth", "CDamage", "CKnockback", "CMovement")]
collision_layer = 16 collision_layer = 16
collision_mask = 273 collision_mask = 273
motion_mode = 1 motion_mode = 1
script = ExtResource("1_q8l7o") script = ExtResource("1_q8l7o")
GetDamageDealt = ExtResource("2_on7rt")
CHealth = NodePath("CHealth") CHealth = NodePath("CHealth")
CDamage = NodePath("CDamageable") RHealth = ExtResource("2_ma2bq")
CMovement = NodePath("CFlyingMovement")
DeathEffects = Array[Object]([]) DeathEffects = Array[Object]([])
CDamage = NodePath("CDamageable")
RDamage = ExtResource("2_on7rt")
CKnockback = NodePath("CKnockback")
RKnockback = ExtResource("11_mpa2u")
CMovement = NodePath("CFlyingMovement")
RMovement = ExtResource("4_dejyg")
[node name="CHealth" type="Node" parent="."] [node name="CHealth" type="Node" parent="."]
script = ExtResource("4_ys4jv") script = ExtResource("4_ys4jv")
HealthResource = SubResource("Resource_aarbi") RHealth = ExtResource("2_ma2bq")
metadata/_custom_type_script = "uid://bjwrpv3jpsc1e" metadata/_custom_type_script = "uid://bjwrpv3jpsc1e"
[node name="CDamageable" type="Node" parent="."] [node name="CDamageable" type="Node" parent="."]
@@ -67,9 +69,12 @@ DamageModifiers = Array[Object]([SubResource("Resource_jnv07"), SubResource("Res
metadata/_custom_type_script = "uid://b0u23nkpaimyc" metadata/_custom_type_script = "uid://b0u23nkpaimyc"
[node name="CFlyingMovement" parent="." instance=ExtResource("7_vaeds")] [node name="CFlyingMovement" parent="." instance=ExtResource("7_vaeds")]
RMovement = SubResource("Resource_ma2bq") RMovement = SubResource("Resource_on7rt")
TerrainCollision = 256 TerrainCollision = 256
[node name="CKnockback" parent="." instance=ExtResource("10_dejyg")]
RKnockback = ExtResource("11_mpa2u")
[node name="CollisionShape3D" type="CollisionShape3D" parent="."] [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
shape = SubResource("SphereShape3D_b46rq") shape = SubResource("SphereShape3D_b46rq")

View File

@@ -0,0 +1,8 @@
[gd_resource type="Resource" script_class="RKnockback" load_steps=2 format=3 uid="uid://dt7a1io5o0b8s"]
[ext_resource type="Script" uid="uid://b44cse62qru7j" path="res://resource_definitions/RKnockback.cs" id="1_yq03x"]
[resource]
script = ExtResource("1_yq03x")
Modifier = 10.0
metadata/_custom_type_script = "uid://b44cse62qru7j"

View File

@@ -0,0 +1,10 @@
[gd_resource type="Resource" script_class="RMovement" load_steps=2 format=3 uid="uid://bwqjaom4k7rc3"]
[ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://resource_definitions/RMovement.cs" id="1_3yq0a"]
[resource]
script = ExtResource("1_3yq0a")
Speed = 3.0
Acceleration = 5.0
TargetHeight = 10.0
metadata/_custom_type_script = "uid://dtpxijlnb2c5"

View File

@@ -1,25 +1,25 @@
[gd_scene load_steps=17 format=3 uid="uid://dxt0e2ugmttqq"] [gd_scene load_steps=19 format=3 uid="uid://dxt0e2ugmttqq"]
[ext_resource type="Script" uid="uid://bn7sc6id7n166" path="res://scenes/enemies/Enemy.cs" id="1_r6506"] [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/first_enemy/first_enemy_damage.tres" id="2_6d4gl"] [ext_resource type="Resource" uid="uid://otfc2snh8umc" path="res://scenes/enemies/grounded_enemy/grounded_enemy_damage.tres" id="2_bn56u"]
[ext_resource type="Script" uid="uid://bjwrpv3jpsc1e" path="res://scenes/health/CHealth.cs" id="2_gsmti"] [ext_resource type="Script" uid="uid://bjwrpv3jpsc1e" path="res://scenes/health/CHealth.cs" id="2_gsmti"]
[ext_resource type="Script" uid="uid://b6y3ugfydvch0" path="res://resource_definitions/RDamageModifier.cs" id="2_r3cnf"] [ext_resource type="Script" uid="uid://b6y3ugfydvch0" path="res://resource_definitions/RDamageModifier.cs" id="2_r3cnf"]
[ext_resource type="Script" uid="uid://baiapod3csndf" path="res://resource_definitions/RHealth.cs" id="3_pvbr4"] [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://scenes/damage/CDamageable.cs" id="7_1tw73"] [ext_resource type="Script" uid="uid://b0u23nkpaimyc" path="res://scenes/damage/CDamageable.cs" id="7_1tw73"]
[ext_resource type="PackedScene" uid="uid://dbr7ioio158ew" path="res://scenes/movement/CGroundedMovement.tscn" id="7_qyswd"] [ext_resource type="PackedScene" uid="uid://dbr7ioio158ew" path="res://scenes/movement/CGroundedMovement.tscn" id="7_qyswd"]
[ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://resource_definitions/RMovement.cs" id="8_6d4gl"] [ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://resource_definitions/RMovement.cs" id="8_6d4gl"]
[ext_resource type="PackedScene" uid="uid://bctpe34ddamg5" path="res://scenes/knockback/CKnockback.tscn" id="10_jqqi6"]
[sub_resource type="Resource" id="Resource_r3cnf"] [ext_resource type="Resource" uid="uid://cektf6waf4s04" path="res://scenes/enemies/grounded_enemy/grounded_enemy_knockback.tres" id="11_8k3xb"]
script = ExtResource("3_pvbr4")
metadata/_custom_type_script = "uid://baiapod3csndf"
[sub_resource type="Resource" id="Resource_qj0ob"] [sub_resource type="Resource" id="Resource_qj0ob"]
script = ExtResource("2_r3cnf") script = ExtResource("2_r3cnf")
Modifier = 3.0
metadata/_custom_type_script = "uid://b6y3ugfydvch0" metadata/_custom_type_script = "uid://b6y3ugfydvch0"
[sub_resource type="Resource" id="Resource_s01ng"] [sub_resource type="Resource" id="Resource_6d4gl"]
script = ExtResource("8_6d4gl") script = ExtResource("8_6d4gl")
Speed = 3.0 Speed = 5.0
metadata/_custom_type_script = "uid://dtpxijlnb2c5" metadata/_custom_type_script = "uid://dtpxijlnb2c5"
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_62kkh"] [sub_resource type="CapsuleShape3D" id="CapsuleShape3D_62kkh"]
@@ -38,19 +38,23 @@ albedo_color = Color(0.06469653, 0.06469653, 0.06469653, 1)
[sub_resource type="BoxShape3D" id="BoxShape3D_4yfjf"] [sub_resource type="BoxShape3D" id="BoxShape3D_4yfjf"]
size = Vector3(1, 2, 2) size = Vector3(1, 2, 2)
[node name="FirstEnemy" type="CharacterBody3D" node_paths=PackedStringArray("CHealth", "CDamage", "CMovement")] [node name="GroundedEnemy" type="CharacterBody3D" node_paths=PackedStringArray("CHealth", "CDamage", "CKnockback", "CMovement")]
collision_layer = 16 collision_layer = 16
collision_mask = 273 collision_mask = 273
script = ExtResource("1_r6506") script = ExtResource("1_r6506")
GetDamageDealt = ExtResource("2_6d4gl")
CHealth = NodePath("CHealth") CHealth = NodePath("CHealth")
CDamage = NodePath("CDamageable") RHealth = ExtResource("2_w4lm8")
CMovement = NodePath("CGroundedMovement")
DeathEffects = Array[Object]([]) DeathEffects = Array[Object]([])
CDamage = NodePath("CDamageable")
RDamage = ExtResource("2_bn56u")
CKnockback = NodePath("CKnockback")
RKnockback = ExtResource("11_8k3xb")
CMovement = NodePath("CGroundedMovement")
RMovement = ExtResource("4_na24f")
[node name="CHealth" type="Node" parent="."] [node name="CHealth" type="Node" parent="."]
script = ExtResource("2_gsmti") script = ExtResource("2_gsmti")
HealthResource = SubResource("Resource_r3cnf") RHealth = ExtResource("2_w4lm8")
metadata/_custom_type_script = "uid://bjwrpv3jpsc1e" metadata/_custom_type_script = "uid://bjwrpv3jpsc1e"
[node name="CDamageable" type="Node" parent="."] [node name="CDamageable" type="Node" parent="."]
@@ -59,9 +63,11 @@ DamageModifiers = Array[Object]([SubResource("Resource_qj0ob")])
metadata/_custom_type_script = "uid://b0u23nkpaimyc" metadata/_custom_type_script = "uid://b0u23nkpaimyc"
[node name="CGroundedMovement" parent="." node_paths=PackedStringArray("WallInFrontRayCast") instance=ExtResource("7_qyswd")] [node name="CGroundedMovement" parent="." node_paths=PackedStringArray("WallInFrontRayCast") instance=ExtResource("7_qyswd")]
RMovement = SubResource("Resource_s01ng") RMovement = SubResource("Resource_6d4gl")
WallInFrontRayCast = NodePath("../WallInFrontRayCast") WallInFrontRayCast = NodePath("../WallInFrontRayCast")
[node name="CKnockback" parent="." instance=ExtResource("10_jqqi6")]
[node name="CollisionShape3D" type="CollisionShape3D" parent="."] [node name="CollisionShape3D" type="CollisionShape3D" parent="."]
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0)
shape = SubResource("CapsuleShape3D_62kkh") shape = SubResource("CapsuleShape3D_62kkh")

View File

@@ -0,0 +1,8 @@
[gd_resource type="Resource" script_class="RKnockback" load_steps=2 format=3 uid="uid://cektf6waf4s04"]
[ext_resource type="Script" uid="uid://b44cse62qru7j" path="res://resource_definitions/RKnockback.cs" id="1_vdia8"]
[resource]
script = ExtResource("1_vdia8")
Modifier = 10.0
metadata/_custom_type_script = "uid://b44cse62qru7j"

View File

@@ -0,0 +1,10 @@
[gd_resource type="Resource" script_class="RMovement" load_steps=2 format=3 uid="uid://bqq6uukbdfysr"]
[ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://resource_definitions/RMovement.cs" id="1_hsy8g"]
[resource]
script = ExtResource("1_hsy8g")
Speed = 5.0
Acceleration = 3.0
GravityModifier = 5.0
metadata/_custom_type_script = "uid://dtpxijlnb2c5"

View File

@@ -5,30 +5,29 @@ using Movementtests.interfaces;
[GlobalClass] [GlobalClass]
public partial class CHealth : Node, IHealthable public partial class CHealth : Node, IHealthable
{ {
[Signal] public event Action<IHealthable, float> HealthChanged;
public delegate void HealthChangedEventHandler(float health); public event Action<IHealthable> HealthDepleted;
[Signal]
public delegate void DeadEventHandler();
[Export] [Export]
public RHealth HealthResource; public RHealth RHealth { get; set; }
public float CurrentHealth { get; set; } public float CurrentHealth { get; set; }
public override void _Ready() public override void _Ready()
{ {
CurrentHealth = HealthResource.StartingHealth; CurrentHealth = RHealth.StartingHealth;
} }
public void ReduceHealth(float amount) public void ReduceHealth(IDamageable source, DamageRecord damageRecord)
{ {
CurrentHealth -= amount; GD.Print(CurrentHealth);
EmitSignalHealthChanged(CurrentHealth); CurrentHealth -= damageRecord.Damage.DamageDealt;
HealthChanged?.Invoke(this, CurrentHealth);
if (CurrentHealth <= 0) if (CurrentHealth <= 0)
{ {
CurrentHealth = 0; CurrentHealth = 0;
EmitSignalDead(); HealthDepleted?.Invoke(this);
} }
} }
} }

View File

@@ -0,0 +1,25 @@
using Godot;
using System;
using Movementtests.interfaces;
[GlobalClass]
public partial class CKnockback : Node3D, IKnockbackable
{
[Export] public RKnockback RKnockback { get; set;}
private DamageRecord _damageRecord = null;
public void RegisterKnockback(IDamageable source, DamageRecord damageRecord)
{
_damageRecord = damageRecord;
}
public Vector3 ComputeKnockback()
{
if (_damageRecord == null) return Vector3.Zero;
var knockbackDirection = GlobalPosition - _damageRecord.Source.GlobalPosition;
_damageRecord = null;
return knockbackDirection.Normalized() * RKnockback.Modifier;
}
}

View File

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

View File

@@ -0,0 +1,12 @@
[gd_scene load_steps=4 format=3 uid="uid://bctpe34ddamg5"]
[ext_resource type="Script" uid="uid://b8dprpcjeac7e" path="res://scenes/knockback/CKnockback.cs" id="1_ix2yg"]
[ext_resource type="Script" uid="uid://b44cse62qru7j" path="res://resource_definitions/RKnockback.cs" id="2_uqiml"]
[sub_resource type="Resource" id="Resource_gbu2d"]
script = ExtResource("2_uqiml")
metadata/_custom_type_script = "uid://b44cse62qru7j"
[node name="CKnockback" type="Node3D"]
script = ExtResource("1_ix2yg")
RKnockback = SubResource("Resource_gbu2d")

View File

@@ -5,7 +5,7 @@ namespace Movementtests.scenes.movement;
public partial class CFlyingMovement : Node3D, IMoveable public partial class CFlyingMovement : Node3D, IMoveable
{ {
[Export] public RMovement RMovement; [Export] public RMovement RMovement { get; set; }
[Export(PropertyHint.Layers3DPhysics)] [Export(PropertyHint.Layers3DPhysics)]
public uint TerrainCollision { get; set; } = 1; public uint TerrainCollision { get; set; } = 1;
@@ -15,11 +15,10 @@ public partial class CFlyingMovement : Node3D, IMoveable
public override void _Ready() public override void _Ready()
{ {
_randomDirection = new Vector3(GD.RandRange(-1, 1), 1, GD.RandRange(-1, 1)).Normalized(); _randomDirection = new Vector3(GD.RandRange(-1, 1), 1, GD.RandRange(-1, 1)).Normalized();
} }
public new Vector3 ComputeVelocity(MovementInputs inputs) public Vector3 ComputeVelocity(MovementInputs inputs)
{ {
var velocity = inputs.Velocity; var velocity = inputs.Velocity;
var spaceState = GetWorld3D().DirectSpaceState; var spaceState = GetWorld3D().DirectSpaceState;
@@ -28,7 +27,7 @@ public partial class CFlyingMovement : Node3D, IMoveable
// Check if we have a direct line of sight to the player // Check if we have a direct line of sight to the player
if (!_movingToDesiredHeight) if (!_movingToDesiredHeight)
{ {
velocity = direction * RMovement.Speed; velocity = velocity.Lerp(direction * RMovement.Speed, (float) inputs.delta * RMovement.Acceleration);
var query = PhysicsRayQueryParameters3D.Create(GlobalPosition, target, TerrainCollision); var query = PhysicsRayQueryParameters3D.Create(GlobalPosition, target, TerrainCollision);
var result = spaceState.IntersectRay(query); var result = spaceState.IntersectRay(query);
@@ -40,7 +39,7 @@ public partial class CFlyingMovement : Node3D, IMoveable
} }
else else
{ {
velocity = _randomDirection * RMovement.Speed; velocity = velocity.Lerp(_randomDirection * RMovement.Speed, (float) inputs.delta * RMovement.Acceleration);
var groundQuery = PhysicsRayQueryParameters3D.Create(GlobalPosition, GlobalPosition+Vector3.Down*RMovement.TargetHeight, TerrainCollision); var groundQuery = PhysicsRayQueryParameters3D.Create(GlobalPosition, GlobalPosition+Vector3.Down*RMovement.TargetHeight, TerrainCollision);
var groundResult = spaceState.IntersectRay(groundQuery); var groundResult = spaceState.IntersectRay(groundQuery);

View File

@@ -5,13 +5,13 @@ namespace Movementtests.scenes.movement;
public partial class CGroundedMovement : Node3D, IMoveable public partial class CGroundedMovement : Node3D, IMoveable
{ {
[Export] public RMovement RMovement; [Export] public RMovement RMovement { get; set; }
[Export] [Export]
public RayCast3D WallInFrontRayCast { get; set; } public RayCast3D WallInFrontRayCast { get; set; }
public new Vector3 ComputeVelocity(MovementInputs inputs) public Vector3 ComputeVelocity(MovementInputs inputs)
{ {
var velocity = inputs.Velocity; var velocity = inputs.Velocity;
var target = inputs.TargetLocation; var target = inputs.TargetLocation;
@@ -19,14 +19,15 @@ public partial class CGroundedMovement : Node3D, IMoveable
var targetPlane = new Vector3(target.X, GlobalPosition.Y, target.Z); var targetPlane = new Vector3(target.X, GlobalPosition.Y, target.Z);
LookAt(targetPlane); LookAt(targetPlane);
float xAcc = (float) Mathf.Lerp(velocity.X, direction.X * RMovement.Speed, inputs.delta * RMovement.Acceleration);
velocity.X = direction.X * RMovement.Speed; float zAcc = (float) Mathf.Lerp(velocity.Z, direction.Z * RMovement.Speed, inputs.delta * RMovement.Acceleration);
velocity.Z = direction.Z * RMovement.Speed; velocity.X = xAcc;
velocity.Z = zAcc;
if (WallInFrontRayCast.IsColliding()) if (WallInFrontRayCast.IsColliding())
velocity.Y = RMovement.Speed; velocity.Y = RMovement.Speed;
else if (!inputs.isOnFloor) else if (!inputs.isOnFloor)
velocity += inputs.gravity * (float)inputs.delta; velocity += inputs.gravity * (float)inputs.delta * RMovement.GravityModifier;
return velocity; return velocity;
} }

View File

@@ -4,10 +4,15 @@ using System;
public partial class Spawner : Node3D public partial class Spawner : Node3D
{ {
[Export(PropertyHint.NodeType)] [Export(PropertyHint.NodeType)]
public PackedScene SceneToSpawn { get; set; } public PackedScene EnemyToSpawn { get; set; }
[Export] [Export]
public Resource Inputs; public RMovement MovementInputs { get; set; }
[Export]
public RHealth HealthInputs { get; set; }
[Export]
public RDamage DamageInputs { get; set; }
[Export] [Export]
public Node3D Target { get; set; } public Node3D Target { get; set; }
@@ -35,13 +40,16 @@ public partial class Spawner : Node3D
public void Spawn() public void Spawn()
{ {
if (SceneToSpawn == null || !SceneToSpawn.CanInstantiate()) return; if (EnemyToSpawn == null || !EnemyToSpawn.CanInstantiate()) return;
var spawnedInstance = SceneToSpawn.Instantiate() as Enemy; if (EnemyToSpawn.Instantiate() is not Enemy spawnedInstance) return;
if (spawnedInstance == null) return;
// spawnedInstance.Inputs = Inputs as EnemyInitInputs;
spawnedInstance.Target = Target; spawnedInstance.Target = Target;
spawnedInstance.RMovement = MovementInputs;
spawnedInstance.RDamage = DamageInputs;
spawnedInstance.RHealth = HealthInputs;
spawnedInstance.Initialize();
GetTree().GetCurrentScene().AddChild(spawnedInstance); GetTree().GetCurrentScene().AddChild(spawnedInstance);
spawnedInstance.GlobalPosition = GlobalPosition; spawnedInstance.GlobalPosition = GlobalPosition;

View File

@@ -1,7 +1,7 @@
[gd_scene load_steps=3 format=3 uid="uid://c305mfrtumcyq"] [gd_scene load_steps=3 format=3 uid="uid://c305mfrtumcyq"]
[ext_resource type="Script" uid="uid://djyspwixi01j5" path="res://scenes/spawners/Spawner.cs" id="1_2otbo"] [ext_resource type="Script" uid="uid://djyspwixi01j5" path="res://scenes/spawners/Spawner.cs" id="1_2otbo"]
[ext_resource type="PackedScene" uid="uid://dxt0e2ugmttqq" path="res://scenes/enemies/first_enemy/first_enemy.tscn" id="2_2otbo"] [ext_resource type="PackedScene" uid="uid://dxt0e2ugmttqq" path="res://scenes/enemies/grounded_enemy/grounded_enemy.tscn" id="2_2otbo"]
[node name="Spawner" type="Node3D"] [node name="Spawner" type="Node3D"]
script = ExtResource("1_2otbo") script = ExtResource("1_2otbo")