From 92cc4f0264bc69e60c4d2b20a7957ff5ea9392d1 Mon Sep 17 00:00:00 2001 From: Minimata Date: Sat, 24 Jan 2026 23:29:22 +0100 Subject: [PATCH] sooooo coded a feature first try? weird --- maps/GYMs/enemies.tscn | 9 ++- player_controller/PlayerController.tscn | 22 +++--- player_controller/Scripts/PlayerController.cs | 68 ++++++++++++------- 3 files changed, 64 insertions(+), 35 deletions(-) diff --git a/maps/GYMs/enemies.tscn b/maps/GYMs/enemies.tscn index 17db11a0..f4974cd5 100644 --- a/maps/GYMs/enemies.tscn +++ b/maps/GYMs/enemies.tscn @@ -1,7 +1,8 @@ -[gd_scene load_steps=21 format=3 uid="uid://q7uc1h2jpbd2"] +[gd_scene load_steps=23 format=3 uid="uid://q7uc1h2jpbd2"] [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="Script" uid="uid://jitubgv6judn" path="res://components/damage/RDamage.cs" id="2_5fa36"] [ext_resource type="PackedScene" uid="uid://dxt0e2ugmttqq" path="res://scenes/enemies/grounded_enemy/grounded_enemy.tscn" id="3_3uydm"] [ext_resource type="PackedScene" uid="uid://cmlud1hwkd6sv" path="res://scenes/enemies/flying_enemy/flying_enemy.tscn" id="5_8fd2t"] [ext_resource type="Script" uid="uid://dtpxijlnb2c5" path="res://components/movement/RMovement.cs" id="5_ybosk"] @@ -15,6 +16,11 @@ [ext_resource type="Resource" uid="uid://dg1xbjhyhgnnk" path="res://scenes/enemies/flying_enemy/flying_enemy_health.tres" id="11_2e4ci"] [ext_resource type="PackedScene" uid="uid://qup00a7x2sji" path="res://scenes/FixedDashTarget/fixed_dashthrough_target.tscn" id="15_5fa36"] +[sub_resource type="Resource" id="Resource_1hrkh"] +script = ExtResource("2_5fa36") +DamageDealt = 1.0 +metadata/_custom_type_script = "uid://jitubgv6judn" + [sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_0xm2m"] sky_horizon_color = Color(0.662243, 0.671743, 0.686743, 1) ground_horizon_color = Color(0.662243, 0.671743, 0.686743, 1) @@ -56,6 +62,7 @@ metadata/_custom_type_script = "uid://baiapod3csndf" [node name="Player" parent="." instance=ExtResource("1_62kkh")] transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 7.5) TutorialDone = true +RDamage = SubResource("Resource_1hrkh") [node name="WorldEnvironment" type="WorldEnvironment" parent="."] environment = SubResource("Environment_1bvp3") diff --git a/player_controller/PlayerController.tscn b/player_controller/PlayerController.tscn index b12d8f84..7f16f62b 100644 --- a/player_controller/PlayerController.tscn +++ b/player_controller/PlayerController.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=64 format=3 uid="uid://bei4nhkf8lwdo"] +[gd_scene load_steps=65 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"] @@ -86,6 +86,9 @@ top_radius = 0.2 bottom_radius = 0.2 height = 1.0 +[sub_resource type="SphereShape3D" id="SphereShape3D_abfq8"] +radius = 2.0 + [sub_resource type="SphereShape3D" id="SphereShape3D_cmijs"] radius = 1.0 @@ -322,6 +325,14 @@ visible = false transform = Transform3D(1, 0, 0, 0, -4.371139e-08, 1, 0, -1, -4.371139e-08, 0, 0, -1) mesh = SubResource("CylinderMesh_nodcl") +[node name="DashDamage" type="ShapeCast3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0) +enabled = false +shape = SubResource("SphereShape3D_abfq8") +target_position = Vector3(0, 0, 0) +max_results = 512 +collision_mask = 16 + [node name="CloseEnemyDetector" type="ShapeCast3D" parent="."] unique_name_in_owner = true transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.6, 0) @@ -628,12 +639,6 @@ to = NodePath("../OnWall/Hanging") event = &"dash_to_planted" delay_in_seconds = "0.0" -[node name="OnPoweredDash" type="Node" parent="StateChart/Root/Movement"] -script = ExtResource("28_n7qhm") -to = NodePath("../Dashing/PoweredDash") -event = &"powered_dash" -delay_in_seconds = "0.0" - [node name="OnAimedDash" type="Node" parent="StateChart/Root/Movement"] script = ExtResource("28_n7qhm") to = NodePath("../Dashing/AimedDash") @@ -774,9 +779,6 @@ delay_in_seconds = "0.0" [node name="Dash" type="Node" parent="StateChart/Root/Movement/Dashing"] script = ExtResource("27_34snm") -[node name="PoweredDash" type="Node" parent="StateChart/Root/Movement/Dashing"] -script = ExtResource("27_34snm") - [node name="AimedDash" type="Node" parent="StateChart/Root/Movement/Dashing"] script = ExtResource("27_34snm") diff --git a/player_controller/Scripts/PlayerController.cs b/player_controller/Scripts/PlayerController.cs index 9efc30b2..b1c51a3c 100644 --- a/player_controller/Scripts/PlayerController.cs +++ b/player_controller/Scripts/PlayerController.cs @@ -66,7 +66,8 @@ public partial class PlayerController : CharacterBody3D, public ShapeCast3D CeilingDetector; public RayCast3D DirectGroundDetector; public Area3D WeaponHitbox; - public AudioStreamPlayer3D SFXPlayer; + public AudioStreamPlayer3D SfxPlayer; + public ShapeCast3D DashDamageDetector; // Inspector stuff [Export] public Marker3D TutorialWeaponTarget; @@ -325,13 +326,9 @@ public partial class PlayerController : CharacterBody3D, private StateChartState _onWallHanging; private StateChartState _onWallRunning; - private StateChartState _attack; - private StateChartState _attackReady; private StateChartState _attackStandard; private StateChartState _attackDash; - private Transition _onDashEnded; - private Transition _onJumpFromWall; private Transition _onJumpFromWallFalling; private Transition _onLeaveWallFromRun; @@ -375,8 +372,8 @@ public partial class PlayerController : CharacterBody3D, DashIndicatorMeshCylinder = DashIndicatorMesh.Mesh as CylinderMesh; DashIndicatorMesh.Visible = false; - SFXPlayer = GetNode("SFXPlayer"); - _audioStream = SFXPlayer.GetStreamPlayback() as AudioStreamPlaybackInteractive; + SfxPlayer = GetNode("SFXPlayer"); + _audioStream = SfxPlayer.GetStreamPlayback() as AudioStreamPlaybackInteractive; // Camera stuff HeadSystem = GetNode("HeadSystem"); @@ -395,6 +392,7 @@ public partial class PlayerController : CharacterBody3D, GroundDetector = GetNode("GroundDetector"); CeilingDetector = GetNode("CeilingDetector"); DirectGroundDetector = GetNode("DirectGroundDetector"); + DashDamageDetector = GetNode("DashDamage"); RayCast3D stairsBelowRayCast3D = GetNode("StairsBelowRayCast3D"); RayCast3D stairsAheadRayCast3D = GetNode("StairsAheadRayCast3D"); _headCollisionDetectors = new RayCast3D[NUM_OF_HEAD_COLLISION_DETECTORS]; @@ -447,7 +445,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")); - _onDashEnded = Transition.Of(GetNode("StateChart/Root/Movement/Dashing/OnDashEnded")); // _actionHanging = StateChartState.Of(GetNode("StateChart/Root/Actions/Hanging")); _powerExpired = StateChartState.Of(GetNode("StateChart/Root/PowerReserve/Expired")); @@ -472,8 +469,6 @@ public partial class PlayerController : CharacterBody3D, _onAirborneToGrounded = Transition.Of(GetNode("StateChart/Root/Movement/Airborne/OnGrounded")); // Attack states - _attack = StateChartState.Of(GetNode("StateChart/Root/Attack")); - _attackReady = StateChartState.Of(GetNode("StateChart/Root/Attack/Ready")); _attackStandard = StateChartState.Of(GetNode("StateChart/Root/Attack/StandardAttack")); _attackDash = StateChartState.Of(GetNode("StateChart/Root/Attack/DashAttack")); @@ -1364,7 +1359,7 @@ public partial class PlayerController : CharacterBody3D, // Slide management // /////////////////////////// - private bool _isSlideInputDown = false; + private bool _isSlideInputDown; public void OnInputSlideStarted() { @@ -1381,7 +1376,6 @@ public partial class PlayerController : CharacterBody3D, public record SlopeRecord( Vector3 Position, - Vector3 Normal, Vector3 Direction, float AngleRadians ); @@ -1400,7 +1394,7 @@ public partial class PlayerController : CharacterBody3D, var angle = normal.AngleTo(Vector3.Up); var vectorInPlane = normal.Cross(Vector3.Up).Normalized(); var direction = normal.Cross(vectorInPlane).Normalized(); - return new SlopeRecord(position, normal, direction, angle); + return new SlopeRecord(position, direction, angle); } public void SetupSlideCollision() @@ -1445,7 +1439,7 @@ public partial class PlayerController : CharacterBody3D, var finalSpeed = Mathf.Max(currentVelocity * speedLossRate, minimumVelocity); // Going down a slope? - var (position, _, slopeDirection, slopeAngleRadians) = GetSlope(); + var (position, slopeDirection, slopeAngleRadians) = GetSlope(); // Change velocity based on Input var horizontalVelocity = ComputeHVelocity(delta, AccelerationGroundSlide, DecelerationGroundSlide); @@ -1707,11 +1701,13 @@ public partial class PlayerController : CharacterBody3D, if (DashSystem.CanDashThroughTarget && DashSystem.CollidedObject is ITargetable targetable) correctedLocation = ComputePositionAfterTargetedDash(targetable.GetTargetGlobalPosition(), DashSystem.CollisionPoint); + // Start invincibility timer for the duration of the dash and a bit more afterwards OnHitInvincibility(); _preDashVelocity = Velocity; _dashDirection = (correctedLocation - GlobalPosition).Normalized(); + SetupDashDamageDetector(correctedLocation); var dashTween = CreatePositionTween(correctedLocation, AimedDashTime); // dashTween.TweenMethod(Callable.From(AimedDashTweenOngoing), 0.0f, 1.0f, AimedDashTime); @@ -1721,6 +1717,28 @@ public partial class PlayerController : CharacterBody3D, _customMantleCurve = DashSystem.MantleSystem.MantleCurve; _customMantleStartTransform = DashSystem.MantleSystem.GlobalTransform; } + + public void SetupDashDamageDetector(Vector3 endDashLocation) + { + RemoveChildNode(DashDamageDetector); + DashDamageDetector.SetTargetPosition(DashDamageDetector.ToLocal(endDashLocation)); + DashDamageDetector.Enabled = true; + } + + public void ComputeDashDamage() + { + for (var i = 0; i < DashDamageDetector.GetCollisionCount(); i++) + { + var collidedObject = DashDamageDetector.GetCollider(i); + if (collidedObject is not IDamageable damageable) continue; + _hitEnemies.Add(damageable); + } + TriggerDamage(); + + RecoverChildNode(DashDamageDetector); + DashDamageDetector.Enabled = false; + } + public void AimedDashTweenEnded() { var dashEvent = isOnFloorCustom() ? "grounded" : "dash_finished"; @@ -1730,6 +1748,7 @@ public partial class PlayerController : CharacterBody3D, { ManageAttackedEnemyPostDash(DashSystem.CollidedObject as Node); DashSystem.CollidedObject = null; + ComputeDashDamage(); if (_customMantle) { @@ -1775,6 +1794,8 @@ public partial class PlayerController : CharacterBody3D, _audioStream.SwitchToClipByName("dash"); // Start invincibility timer for the duration of the dash and a bit more afterwards OnHitInvincibility(); + + SetupDashDamageDetector(WeaponSystem.GlobalPosition); DashSystem.ShouldMantle = false; _dashDirection = (WeaponSystem.GlobalPosition - GlobalPosition).Normalized(); @@ -1785,6 +1806,7 @@ public partial class PlayerController : CharacterBody3D, public void DashToFlyingWeaponTweenEnded() { RecoverWeapon(); + ComputeDashDamage(); var vel = _dashDirection * PostDashSpeed; SetVelocity(vel); @@ -1815,6 +1837,8 @@ public partial class PlayerController : CharacterBody3D, _wallHugStartLocation = dashLocation; _wallHugStartProjectedVelocity = Velocity.Slide(_wallHugStartNormal); + SetupDashDamageDetector(dashLocation); + var dashTween = CreatePositionTween(dashLocation, AimedDashTime); dashTween.Finished += DashToPlantedWeaponTweenEnded; } @@ -1828,7 +1852,7 @@ public partial class PlayerController : CharacterBody3D, var resultingEvent = shouldDashToHanging ? "dash_to_planted" : "dash_finished"; if (!shouldDashToHanging) RecoverWeapon(); // Manually recover weapon before enemy is freed in case it owns the weapon object - if (WeaponSystem.PlantObject is ITargetable targetable) + if (WeaponSystem.PlantObject is ITargetable) { HeadSystem.OnMantle(); // Recycle mantle animation SetVerticalVelocity(PostDashSpeed); @@ -1836,6 +1860,7 @@ public partial class PlayerController : CharacterBody3D, ManageAttackedEnemyPostDash(WeaponSystem.PlantObject); WeaponSystem.PlantObject = null; + ComputeDashDamage(); _playerState.SendEvent(resultingEvent); } @@ -1929,14 +1954,14 @@ public partial class PlayerController : CharacterBody3D, } _targetLocation = target.GetTargetGlobalPosition(); - var targetDistance = _targetLocation.DistanceTo(GlobalPosition); + // var targetDistance = _targetLocation.DistanceTo(GlobalPosition); positionOnScreen = _camera.UnprojectPosition(_targetLocation); _isEnemyInDashAttackRange = true; //targetDistance < TargetInRangeDistance; // Removing the "almost dash" UI if (_isEnemyInDashAttackRange) { enemyTargetState = PlayerUi.TargetState.TargetDashThrough; - if (_targetObject is IDamageable damageable && _targetObject is IHealthable healthable) + if (_targetObject is IDamageable damageable and IHealthable healthable) { var wouldBeDamage = damageable.ComputeDamage(new DamageRecord(this, RDamage)); if (wouldBeDamage.Damage.DamageDealt < healthable.CurrentHealth) @@ -2018,12 +2043,7 @@ public partial class PlayerController : CharacterBody3D, stunnable.Stun(); } - var shouldKnockback = false; - if (_targetObject is IHealthable healthable) - { - if (healthable.CurrentHealth > 0) shouldKnockback = true; - } - + var shouldKnockback = _targetObject is IHealthable { CurrentHealth: > 0 }; if (shouldKnockback) { Velocity = -_dashDirection*RKnockback.Modifier; @@ -2038,7 +2058,7 @@ public partial class PlayerController : CharacterBody3D, _playerState.SendEvent("attack_finished"); } - public Vector3 ComputePositionAfterTargetedDash(Vector3 targetLocation, Vector3 targetHitLocation) + public static Vector3 ComputePositionAfterTargetedDash(Vector3 targetLocation, Vector3 targetHitLocation) { return targetLocation + (targetLocation - targetHitLocation); }