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

This commit is contained in:
2026-01-26 16:34:18 +01:00
parent d79ca44972
commit 2fdc9c7ca8
13 changed files with 122 additions and 32 deletions

View File

@@ -7,20 +7,20 @@ public partial class CKnockback : Node3D, IKnockbackable
{ {
[Export] public RKnockback RKnockback { get; set;} [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() public Vector3 ComputeKnockback()
{ {
if (_damageRecord == null) return Vector3.Zero; if (_knockbackRecord == null) return Vector3.Zero;
var knockbackDirection = GlobalPosition - _damageRecord.Source.GlobalPosition; var knockbackDirection = GlobalPosition - _knockbackRecord.DamageRecord.SourceLocation;
_damageRecord = null; var finalKnockback = knockbackDirection.Normalized() * RKnockback.Modifier * _knockbackRecord.ForceMultiplier;
var finalKnockback = knockbackDirection.Normalized() * RKnockback.Modifier; _knockbackRecord = null;
return finalKnockback; return finalKnockback;
} }
} }

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=66 format=3 uid="uid://bei4nhkf8lwdo"] [gd_scene load_steps=67 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"]
@@ -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="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="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="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://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="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"] [ext_resource type="Script" uid="uid://cwbvxlfvmocc1" path="res://player_controller/Scripts/StairsSystem.cs" id="7_bmt5a"]
@@ -112,6 +113,7 @@ RDamage = SubResource("Resource_cb2lu")
RKnockback = SubResource("Resource_abfq8") RKnockback = SubResource("Resource_abfq8")
RHealth = SubResource("Resource_ue7xq") RHealth = SubResource("Resource_ue7xq")
TargetingDistance = 5.0 TargetingDistance = 5.0
Explosion = ExtResource("5_ue7xq")
WalkSpeed = 7.5 WalkSpeed = 7.5
AccelerationFloor = 4.0 AccelerationFloor = 4.0
DecelerationFloor = 3.0 DecelerationFloor = 3.0

View File

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

View File

@@ -94,7 +94,7 @@ public partial class Enemy : CharacterBody3D,
{ {
// Anonymous function call to erase return values of ReduceHealth // Anonymous function call to erase return values of ReduceHealth
CDamageable.DamageTaken += (source, record) => ReduceHealth(source, record); CDamageable.DamageTaken += (source, record) => ReduceHealth(source, record);
CDamageable.DamageTaken += RegisterKnockback; CDamageable.DamageTaken += (source, record) => RegisterKnockback(new KnockbackRecord(record));
CHealth.HealthDepleted += Kill; CHealth.HealthDepleted += Kill;
HealthChanged += (source, record) => _healthbar.OnHealthChanged(record); HealthChanged += (source, record) => _healthbar.OnHealthChanged(record);
} }
@@ -127,7 +127,7 @@ public partial class Enemy : CharacterBody3D,
foreach (var body in bodies) foreach (var body in bodies)
{ {
if(body is IDamageable spawnable) if(body is IDamageable spawnable)
spawnable.TakeDamage(new DamageRecord(this, RDamage)); spawnable.TakeDamage(new DamageRecord(GlobalPosition, RDamage));
} }
} }
@@ -184,10 +184,10 @@ public partial class Enemy : CharacterBody3D,
CallDeferred(Node.MethodName.QueueFree); CallDeferred(Node.MethodName.QueueFree);
} }
public void RegisterKnockback(IDamageable source, DamageRecord damageRecord) public void RegisterKnockback(KnockbackRecord knockbackRecord)
{ {
if (CKnockback is null) return; if (CKnockback is null) return;
CKnockback.RegisterKnockback(source, damageRecord); CKnockback.RegisterKnockback(knockbackRecord);
} }
public Vector3 ComputeKnockback() 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

@@ -19,7 +19,8 @@ metadata/_custom_type_script = "uid://b6y3ugfydvch0"
[sub_resource type="Resource" id="Resource_53j1c"] [sub_resource type="Resource" id="Resource_53j1c"]
script = ExtResource("2_1bsgx") script = ExtResource("2_1bsgx")
DamageType = 1 DamageType = 3
Modifier = 1.0
metadata/_custom_type_script = "uid://b6y3ugfydvch0" metadata/_custom_type_script = "uid://b6y3ugfydvch0"
[sub_resource type="Resource" id="Resource_on7rt"] [sub_resource type="Resource" id="Resource_on7rt"]

View File

@@ -1,4 +1,4 @@
[gd_scene load_steps=20 format=3 uid="uid://dxt0e2ugmttqq"] [gd_scene load_steps=21 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/grounded_enemy/grounded_enemy_damage.tres" id="2_bn56u"] [ext_resource type="Resource" uid="uid://otfc2snh8umc" path="res://scenes/enemies/grounded_enemy/grounded_enemy_damage.tres" id="2_bn56u"]
@@ -18,6 +18,12 @@ script = ExtResource("2_r3cnf")
Modifier = 1.0 Modifier = 1.0
metadata/_custom_type_script = "uid://b6y3ugfydvch0" 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"] [sub_resource type="Resource" id="Resource_6d4gl"]
script = ExtResource("8_6d4gl") script = ExtResource("8_6d4gl")
Speed = 5.0 Speed = 5.0
@@ -60,7 +66,7 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2.2, 0)
[node name="CDamageable" type="Node" parent="."] [node name="CDamageable" type="Node" parent="."]
script = ExtResource("7_1tw73") 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" metadata/_custom_type_script = "uid://b0u23nkpaimyc"
[node name="CMovement" parent="." node_paths=PackedStringArray("WallInFrontRayCast") instance=ExtResource("7_qyswd")] [node name="CMovement" parent="." node_paths=PackedStringArray("WallInFrontRayCast") instance=ExtResource("7_qyswd")]
@@ -68,6 +74,7 @@ RMovement = SubResource("Resource_6d4gl")
WallInFrontRayCast = NodePath("../WallInFrontRayCast") WallInFrontRayCast = NodePath("../WallInFrontRayCast")
[node name="CKnockback" parent="." instance=ExtResource("10_jqqi6")] [node name="CKnockback" parent="." instance=ExtResource("10_jqqi6")]
RKnockback = ExtResource("11_8k3xb")
[node name="CTarget" type="Marker3D" parent="."] [node name="CTarget" type="Marker3D" 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)

View File

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