From 2fdc9c7ca8471037d47d650fc4ac964126df9c82 Mon Sep 17 00:00:00 2001 From: Minimata Date: Mon, 26 Jan 2026 16:34:18 +0100 Subject: [PATCH] instanciating explosion on slam --- components/knockback/CKnockback.cs | 14 ++++---- components/knockback/CKnockback.tscn | 1 + interfaces/IDamageable.cs | 2 +- interfaces/IKnockbackable.cs | 4 ++- player_controller/PlayerController.tscn | 4 ++- player_controller/Scripts/PlayerController.cs | 34 ++++++++++-------- scenes/enemies/Enemy.cs | 8 ++--- scenes/enemies/Explosion.cs | 36 +++++++++++++++++++ scenes/enemies/Explosion.cs.uid | 1 + scenes/enemies/explosion.tscn | 34 ++++++++++++++++++ scenes/enemies/flying_enemy/flying_enemy.tscn | 3 +- .../grounded_enemy/grounded_enemy.tscn | 11 ++++-- systems/weapon/WeaponSystem.cs | 2 +- 13 files changed, 122 insertions(+), 32 deletions(-) create mode 100644 scenes/enemies/Explosion.cs create mode 100644 scenes/enemies/Explosion.cs.uid create mode 100644 scenes/enemies/explosion.tscn diff --git a/components/knockback/CKnockback.cs b/components/knockback/CKnockback.cs index 72b62436..dfe7e14e 100644 --- a/components/knockback/CKnockback.cs +++ b/components/knockback/CKnockback.cs @@ -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; } } diff --git a/components/knockback/CKnockback.tscn b/components/knockback/CKnockback.tscn index 62d5871b..16ad40a8 100644 --- a/components/knockback/CKnockback.tscn +++ b/components/knockback/CKnockback.tscn @@ -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"] diff --git a/interfaces/IDamageable.cs b/interfaces/IDamageable.cs index 96729c31..3f13caff 100644 --- a/interfaces/IDamageable.cs +++ b/interfaces/IDamageable.cs @@ -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 { diff --git a/interfaces/IKnockbackable.cs b/interfaces/IKnockbackable.cs index 420c4c4f..c7c43555 100644 --- a/interfaces/IKnockbackable.cs +++ b/interfaces/IKnockbackable.cs @@ -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(); } \ No newline at end of file diff --git a/player_controller/PlayerController.tscn b/player_controller/PlayerController.tscn index 34eb1e71..99263031 100644 --- a/player_controller/PlayerController.tscn +++ b/player_controller/PlayerController.tscn @@ -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="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"] @@ -112,6 +113,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 diff --git a/player_controller/Scripts/PlayerController.cs b/player_controller/Scripts/PlayerController.cs index b667f7ce..55cb7222 100644 --- a/player_controller/Scripts/PlayerController.cs +++ b/player_controller/Scripts/PlayerController.cs @@ -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("SlidingEnemyDetector"); RayCast3D stairsBelowRayCast3D = GetNode("StairsBelowRayCast3D"); RayCast3D stairsAheadRayCast3D = GetNode("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( "HeadCollisionDetectors/HeadCollisionDetector" + i); @@ -428,8 +430,8 @@ public partial class PlayerController : CharacterBody3D, } if (RKnockback != null) CKnockback!.RKnockback = RKnockback; - CDamageable.DamageTaken += (source, record) => ReduceHealth(source, record); - CDamageable.DamageTaken += RegisterKnockback; + CDamageable.DamageTaken += (damageable, record) => ReduceHealth(damageable, record); + CDamageable.DamageTaken += (damageable, record) => RegisterKnockback(new KnockbackRecord(record)); CHealth.HealthDepleted += Kill; // State management @@ -448,7 +450,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 +766,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 +1596,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 +1987,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 +2126,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 +2152,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() diff --git a/scenes/enemies/Enemy.cs b/scenes/enemies/Enemy.cs index ec78c00c..158779d2 100644 --- a/scenes/enemies/Enemy.cs +++ b/scenes/enemies/Enemy.cs @@ -94,7 +94,7 @@ public partial class Enemy : CharacterBody3D, { // 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); } @@ -127,7 +127,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 +184,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() diff --git a/scenes/enemies/Explosion.cs b/scenes/enemies/Explosion.cs new file mode 100644 index 00000000..94670a74 --- /dev/null +++ b/scenes/enemies/Explosion.cs @@ -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").Shape as SphereShape3D; + sphereShape!.Radius = Radius; + var sphereMesh = GetNode("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(); + } +} diff --git a/scenes/enemies/Explosion.cs.uid b/scenes/enemies/Explosion.cs.uid new file mode 100644 index 00000000..13805da8 --- /dev/null +++ b/scenes/enemies/Explosion.cs.uid @@ -0,0 +1 @@ +uid://cnlu64l7oxvv3 diff --git a/scenes/enemies/explosion.tscn b/scenes/enemies/explosion.tscn new file mode 100644 index 00000000..dde01b28 --- /dev/null +++ b/scenes/enemies/explosion.tscn @@ -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") diff --git a/scenes/enemies/flying_enemy/flying_enemy.tscn b/scenes/enemies/flying_enemy/flying_enemy.tscn index a8210f25..4534acc3 100644 --- a/scenes/enemies/flying_enemy/flying_enemy.tscn +++ b/scenes/enemies/flying_enemy/flying_enemy.tscn @@ -19,7 +19,8 @@ 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"] diff --git a/scenes/enemies/grounded_enemy/grounded_enemy.tscn b/scenes/enemies/grounded_enemy/grounded_enemy.tscn index e8606e49..ee48b7cc 100644 --- a/scenes/enemies/grounded_enemy/grounded_enemy.tscn +++ b/scenes/enemies/grounded_enemy/grounded_enemy.tscn @@ -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="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 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 @@ -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="."] 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 +74,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) diff --git a/systems/weapon/WeaponSystem.cs b/systems/weapon/WeaponSystem.cs index 4eb61c32..072b1357 100644 --- a/systems/weapon/WeaponSystem.cs +++ b/systems/weapon/WeaponSystem.cs @@ -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)); } }