From 5da2aa31abffc07590c37ee904f8362e5830cc30 Mon Sep 17 00:00:00 2001 From: Minimata Date: Tue, 24 Feb 2026 10:27:57 +0100 Subject: [PATCH] basic forge setup and refactored for some warning --- Movement tests.csproj | 1 + Movement tests.sln.DotSettings.user | 1 + interfaces/IHealthable.cs | 2 +- interfaces/IKnockbackable.cs | 2 +- project.godot | 1 + .../components/dash/DashSystem.cs | 93 ++---- .../components/weapon/WeaponSystem.cs | 24 +- .../scripts/PlayerAttributeSet.cs | 20 ++ .../scripts/PlayerAttributeSet.cs.uid | 1 + .../scripts/PlayerController.cs | 303 ++++++++++-------- tests/player/DashSystemUnitTest.cs | 28 +- tests/player/PlayerControllerUnitTest.cs | 8 +- tools/ForgeManager.cs | 27 ++ tools/ForgeManager.cs.uid | 1 + 14 files changed, 284 insertions(+), 228 deletions(-) create mode 100644 scenes/player_controller/scripts/PlayerAttributeSet.cs create mode 100644 scenes/player_controller/scripts/PlayerAttributeSet.cs.uid create mode 100644 tools/ForgeManager.cs create mode 100644 tools/ForgeManager.cs.uid diff --git a/Movement tests.csproj b/Movement tests.csproj index 3351515b..5ad057f8 100644 --- a/Movement tests.csproj +++ b/Movement tests.csproj @@ -156,4 +156,5 @@ runtime; build; native; contentfiles; analyzers; buildtransitive + \ No newline at end of file diff --git a/Movement tests.sln.DotSettings.user b/Movement tests.sln.DotSettings.user index f6ec7833..24317e8e 100644 --- a/Movement tests.sln.DotSettings.user +++ b/Movement tests.sln.DotSettings.user @@ -1,4 +1,5 @@  + ForceIncluded ForceIncluded ForceIncluded ForceIncluded diff --git a/interfaces/IHealthable.cs b/interfaces/IHealthable.cs index 1c3927ca..ac39d609 100644 --- a/interfaces/IHealthable.cs +++ b/interfaces/IHealthable.cs @@ -10,7 +10,7 @@ public interface IHealthable event Action HealthChanged; event Action HealthDepleted; - [Export] RHealth RHealth { get; set; } + [Export] RHealth? RHealth { get; set; } float CurrentHealth { get; set; } diff --git a/interfaces/IKnockbackable.cs b/interfaces/IKnockbackable.cs index c7c43555..e328b026 100644 --- a/interfaces/IKnockbackable.cs +++ b/interfaces/IKnockbackable.cs @@ -6,7 +6,7 @@ public record KnockbackRecord(DamageRecord DamageRecord, float ForceMultiplier = public interface IKnockbackable { - [Export] RKnockback RKnockback { get; set;} + [Export] RKnockback? RKnockback { get; set;} public void RegisterKnockback(KnockbackRecord record); public Vector3 ComputeKnockback(); diff --git a/project.godot b/project.godot index 50e56ae6..bb278d24 100644 --- a/project.godot +++ b/project.godot @@ -30,6 +30,7 @@ Shaker="*uid://c7flmumgr5w3u" CsgToolkitAutoload="*uid://w8ad8q4lneis" "Forge Bootstrap"="*uid://ba8fquhtwu5mu" GlobalHelpers="*uid://dqcm83o8e66a2" +ForgeManager="*uid://c75tpswl62eew" [display] diff --git a/scenes/player_controller/components/dash/DashSystem.cs b/scenes/player_controller/components/dash/DashSystem.cs index 686c0125..87d4d587 100644 --- a/scenes/player_controller/components/dash/DashSystem.cs +++ b/scenes/player_controller/components/dash/DashSystem.cs @@ -19,28 +19,26 @@ public partial class DashSystem: Node3D public Vector3 TargetLocation { get; set; } public Vector3 CollisionPoint { get; set; } public Vector3 CollisionNormal { get; set; } - public GodotObject CollidedObject { get; set; } + public GodotObject? CollidedObject { get; set; } public Vector3 PlannedLocation { get; set; } public bool ShouldMantle { get; set; } public Vector3 PlannedMantleLocation { get; set; } - public MantleSystem MantleSystem { get; set; } + public MantleSystem MantleSystem { get; set; } = null!; - internal HeadSystem _head; - public ShapeCast3D DashCast3D; - internal Camera3D _camera; - internal Vector3 _dashDirection = Vector3.Zero; + internal HeadSystem Head = null!; + public ShapeCast3D DashCast3D = null!; + internal Camera3D Camera = null!; + internal Vector3 DashDirection = Vector3.Zero; - internal ShapeCast3D _dashCastDrop; - internal MeshInstance3D _dashDropIndicator; - internal MeshInstance3D _dashDropLocationIndicator; + internal ShapeCast3D DashCastDrop = null!; + internal MeshInstance3D DashDropIndicator = null!; + internal MeshInstance3D DashDropLocationIndicator = null!; + internal MeshInstance3D DashTarget = null!; + internal CpuParticles3D DashIndicator = null!; + internal AnimationPlayer DashIndicatorAnim = null!; - internal MeshInstance3D _dashTarget; - internal CpuParticles3D _dashIndicator; - internal AnimationPlayer _dashIndicatorAnim; - - [Export] - public PackedScene DashIndicatorScene { get; set; } + [Export] public PackedScene DashIndicatorScene { get; set; } = null!; [Signal] public delegate void DashStartedEventHandler(); @@ -59,22 +57,22 @@ public partial class DashSystem: Node3D var dashShape = DashCast3D.GetShape() as SphereShape3D; DashCastRadius = dashShape!.Radius; - _dashCastDrop = GetNode("DashCastDrop"); - _dashDropIndicator = GetNode("DashDropIndicator"); - _dashDropIndicator.Visible = false; - _dashDropLocationIndicator = GetNode("DashDropLocationIndicator"); - _dashDropLocationIndicator.Visible = false; + DashCastDrop = GetNode("DashCastDrop"); + DashDropIndicator = GetNode("DashDropIndicator"); + DashDropIndicator.Visible = false; + DashDropLocationIndicator = GetNode("DashDropLocationIndicator"); + DashDropLocationIndicator.Visible = false; - _head = head; - _camera = camera; + Head = head; + Camera = camera; MantleSystem = GetNode("MantleSystem"); MantleSystem.Init(); - _dashTarget = GetNode("DashTarget"); - _dashTarget.SetVisible(false); - _dashIndicator = GetNode("DashIndicator"); - _dashIndicatorAnim = GetNode("DashIndicator/AnimationPlayer"); + DashTarget = GetNode("DashTarget"); + DashTarget.SetVisible(false); + DashIndicator = GetNode("DashIndicator"); + DashIndicatorAnim = GetNode("DashIndicator/AnimationPlayer"); } internal DashLocation ComputeDashLocation() @@ -98,13 +96,13 @@ public partial class DashSystem: Node3D public void PrepareDash() { - DashCast3D.SetRotation(_head.GetGlobalLookRotation()); + DashCast3D.SetRotation(Head.GetGlobalLookRotation()); (HasHit, PlannedLocation, CollisionPoint, CollisionNormal, CollidedObject) = ComputeDashLocation(); CanDashThroughTarget = false; - if (CollidedObject is ITargetable targetable) + if (CollidedObject is ITargetable) { - _dashTarget.SetVisible(false); + DashTarget.SetVisible(false); CanDashThroughTarget = true; return; } @@ -112,7 +110,7 @@ public partial class DashSystem: Node3D MantleSystem.SetGlobalPosition(PlannedLocation); MantleSystem.SetRotation(new Vector3( MantleSystem.Rotation.X, - _head.Rotation.Y, + Head.Rotation.Y, MantleSystem.Rotation.Z)); MantleSystem.ProcessMantle(false); ShouldMantle = MantleSystem.IsMantlePossible; @@ -120,41 +118,18 @@ public partial class DashSystem: Node3D // Setup dash target var targetColor = HasHit ? new Color(1f, 0.2f, 0.2f) : new Color(1f, 1f, 1f); targetColor = ShouldMantle ? new Color(0.2f, 0.2f, 1f) : targetColor; - var targetMaterial = (StandardMaterial3D) _dashTarget.GetSurfaceOverrideMaterial(0); + var targetMaterial = (StandardMaterial3D) DashTarget.GetSurfaceOverrideMaterial(0); targetMaterial.SetAlbedo(targetColor); - _dashTarget.SetVisible(true); + DashTarget.SetVisible(true); var targetLocation = ShouldMantle ? MantleSystem.FirstMantleProfilePoint : PlannedLocation; - _dashTarget.SetGlobalPosition(targetLocation); - return; - - var shouldShowDropIndicator = !HasHit && !ShouldMantle; - _dashDropIndicator.SetVisible(shouldShowDropIndicator); - _dashDropLocationIndicator.SetVisible(shouldShowDropIndicator); - if (shouldShowDropIndicator) - { - _dashCastDrop.GlobalPosition = targetLocation; // Place drop indication cast at dash location - var startDropLocation = targetLocation; // Start of the drop is the dash target location - - // End of the drop is either max cast distance or first collision - var hasDropLocationHit = _dashCastDrop.IsColliding(); - var endDropLocation = hasDropLocationHit ? _dashCastDrop.GetCollisionPoint(0) : _dashCastDrop.ToGlobal(DashCast3D.TargetPosition); - - // Only show drop location indicator if drop cast has hit - _dashDropLocationIndicator.SetVisible(hasDropLocationHit); - _dashDropLocationIndicator.SetGlobalPosition(endDropLocation); - - var dropLength = (endDropLocation - startDropLocation).Length(); - var dropDirection = (endDropLocation - startDropLocation).Normalized(); - _dashDropIndicator.SetScale(new Vector3(1, dropLength, 1)); - _dashDropIndicator.SetGlobalPosition(startDropLocation + dropDirection * dropLength * 0.5f); - } + DashTarget.SetGlobalPosition(targetLocation); } public void StopPreparingDash() { CanDashThroughTarget = false; - _dashTarget.SetVisible(false); - _dashDropIndicator.SetVisible(false); - _dashDropLocationIndicator.SetVisible(false); + DashTarget.SetVisible(false); + DashDropIndicator.SetVisible(false); + DashDropLocationIndicator.SetVisible(false); } } diff --git a/scenes/player_controller/components/weapon/WeaponSystem.cs b/scenes/player_controller/components/weapon/WeaponSystem.cs index da5e3418..e9590a0e 100644 --- a/scenes/player_controller/components/weapon/WeaponSystem.cs +++ b/scenes/player_controller/components/weapon/WeaponSystem.cs @@ -22,12 +22,11 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer [Export(PropertyHint.Range, "0,0.2,0.01,or_greater")] public float StraightThrowDuration { get; set; } = 0.1f; - private StateChart _weaponState; - public StateChartState InHandState; - public StateChartState FlyingState; - public StateChartState PlantedState; - - private ShapeCast3D _dashCast3D; + private StateChart _weaponState = null!; + public StateChartState InHandState = null!; + public StateChartState FlyingState = null!; + public StateChartState PlantedState = null!; + private ShapeCast3D _dashCast3D = null!; private Transform3D _startTransform; private Vector3 _startMeshRotation; @@ -35,11 +34,11 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer private Vector3 _throwDirection; public Vector3 PlantLocation { get; set; } public Vector3 PlantNormal { get; set; } - public Node PlantObject { get; set; } - - public MeshInstance3D WeaponLocationIndicator { get; set; } - public StandardMaterial3D WeaponLocationIndicatorMaterial { get; set; } - public MeshInstance3D WeaponMesh { get; set; } + public Node? PlantObject { get; set; } + + public MeshInstance3D WeaponLocationIndicator { get; set; } = null!; + public StandardMaterial3D WeaponLocationIndicatorMaterial { get; set; } = null!; + public MeshInstance3D WeaponMesh { get; set; } = null!; public void Init() { @@ -50,7 +49,7 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer WeaponLocationIndicator = GetNode("WeaponLocationIndicator"); WeaponLocationIndicator.Visible = false; - WeaponLocationIndicatorMaterial = WeaponLocationIndicator.GetActiveMaterial(0) as StandardMaterial3D; + WeaponLocationIndicatorMaterial = (WeaponLocationIndicator.GetActiveMaterial(0) as StandardMaterial3D)!; WeaponMesh = GetNode("Weapon"); _startMeshRotation = WeaponMesh.Rotation; @@ -100,7 +99,6 @@ public partial class WeaponSystem : RigidBody3D, IDamageDealer var tween = GetTree().CreateTween(); - tween.SetParallel(true); tween.TweenProperty(this, "global_position", end, StraightThrowDuration); if (hasHit) { diff --git a/scenes/player_controller/scripts/PlayerAttributeSet.cs b/scenes/player_controller/scripts/PlayerAttributeSet.cs new file mode 100644 index 00000000..66502bdc --- /dev/null +++ b/scenes/player_controller/scripts/PlayerAttributeSet.cs @@ -0,0 +1,20 @@ +using Gamesmiths.Forge.Attributes; + +namespace Movementtests.scenes.player_controller.scripts; + +public class PlayerAttributeSet : AttributeSet +{ + public EntityAttribute Health { get; } + public EntityAttribute Mana { get; } + public EntityAttribute Strength { get; } + public EntityAttribute Speed { get; } + + public PlayerAttributeSet() + { + // Initialize the attributes with the current, min and max values. + Health = InitializeAttribute(nameof(Health), 100, 0, 150); + Mana = InitializeAttribute(nameof(Mana), 100, 0, 100); + Strength = InitializeAttribute(nameof(Strength), 10, 0, 99); + Speed = InitializeAttribute(nameof(Speed), 5, 0, 10); + } +} \ No newline at end of file diff --git a/scenes/player_controller/scripts/PlayerAttributeSet.cs.uid b/scenes/player_controller/scripts/PlayerAttributeSet.cs.uid new file mode 100644 index 00000000..cb5d5b44 --- /dev/null +++ b/scenes/player_controller/scripts/PlayerAttributeSet.cs.uid @@ -0,0 +1 @@ +uid://budtqogrwod6w diff --git a/scenes/player_controller/scripts/PlayerController.cs b/scenes/player_controller/scripts/PlayerController.cs index abfe61b6..eb353c52 100644 --- a/scenes/player_controller/scripts/PlayerController.cs +++ b/scenes/player_controller/scripts/PlayerController.cs @@ -1,11 +1,17 @@ using System; using System.Collections.Generic; +using Gamesmiths.Forge.Core; +using Gamesmiths.Forge.Effects; +using Gamesmiths.Forge.Events; +using Gamesmiths.Forge.Tags; using Godot; using GodotStateCharts; using Movementtests.addons.godot_state_charts.csharp; using Movementtests.interfaces; using Movementtests.systems; using Movementtests.player_controller.Scripts; +using Movementtests.scenes.player_controller.scripts; +using Movementtests.tools; using RustyOptions; [GlobalClass, Icon("res://assets/ui/IconGodotNode/node_3D/icon_character.png")] @@ -13,7 +19,8 @@ public partial class PlayerController : CharacterBody3D, IDamageable, IDamageDealer, IHealthable, - IKnockbackable + IKnockbackable, + IForgeEntity { // Enums public enum AllowedInputs @@ -42,39 +49,45 @@ public partial class PlayerController : CharacterBody3D, [Signal] public delegate void PlayerDiedEventHandler(); - public event Action DamageTaken; - public event Action HealthChanged; - public event Action HealthDepleted; + public event Action DamageTaken = null!; + public event Action HealthChanged = null!; + public event Action HealthDepleted = null!; /////////////////////////// // Public stuff // /////////////////////////// - public HeadSystem HeadSystem; - public StairsSystem StairsSystem; - public MantleSystem MantleSystem; - public DashSystem DashSystem; - public CollisionShape3D StandingCollider; - public CollisionShape3D SlideCollider; - public WeaponSystem WeaponSystem; - public WallHugSystem WallHugSystem; - public PlayerUi PlayerUi; - public TextureRect DashIndicator; - public ColorRect PowerCooldownIndicator; - public Node3D DashIndicatorNode; - public MeshInstance3D DashIndicatorMesh; - public CylinderMesh DashIndicatorMeshCylinder; - public RayCast3D WallRunSnapper; - public ShapeCast3D GroundDetector; - public ShapeCast3D CeilingDetector; - public RayCast3D DirectGroundDetector; - public Area3D WeaponHitbox; - public AudioStreamPlayer3D SfxPlayer; + public HeadSystem HeadSystem = null!; + public StairsSystem StairsSystem = null!; + public MantleSystem MantleSystem = null!; + public DashSystem DashSystem = null!; + public CollisionShape3D StandingCollider = null!; + public CollisionShape3D SlideCollider = null!; + public WeaponSystem WeaponSystem = null!; + public WallHugSystem WallHugSystem = null!; + public PlayerUi PlayerUi = null!; + public TextureRect DashIndicator = null!; + public ColorRect PowerCooldownIndicator = null!; + public Node3D DashIndicatorNode = null!; + public MeshInstance3D DashIndicatorMesh = null!; + public CylinderMesh DashIndicatorMeshCylinder = null!; + public RayCast3D WallRunSnapper = null!; + public ShapeCast3D GroundDetector = null!; + public ShapeCast3D CeilingDetector = null!; + public RayCast3D DirectGroundDetector = null!; + public Area3D WeaponHitbox = null!; + public AudioStreamPlayer3D SfxPlayer = null!; - public ShapeCast3D DashDamageDetector; - public Area3D SlidingEnemyDetector; + public ShapeCast3D DashDamageDetector = null!; + public Area3D SlidingEnemyDetector = null!; + + public EntityAttributes Attributes { get; set; } = null!; + public EntityTags Tags { get; set; } = null!; + public EffectsManager EffectsManager { get; set; } = null!; + public EntityAbilities Abilities { get; set; } = null!; + public EventManager Events { get; set; } = null!; // Inspector stuff - [Export] public Marker3D TutorialWeaponTarget; + [Export] public Marker3D TutorialWeaponTarget = null!; [Export] public bool TutorialDone { get; set; } [Export] public bool HasSword { get; set; } = true; [Export] public bool HasParry { get; set; } = true; @@ -88,11 +101,10 @@ public partial class PlayerController : CharacterBody3D, public float AimAssistReductionWhenCloseToTarget { get; set; } = 0.3f; [Export(PropertyHint.Range, "0,10f,0.1,or_greater")] public float AimAssistReductionStartDistance { get; set; } = 10f; - - [ExportGroup("Damage")] - [Export] public RDamage RDamage { get; set; } - [Export] public RKnockback RKnockback { get; set; } - [Export] public RHealth RHealth { get; set; } + + [ExportGroup("Damage")] [Export] public RDamage RDamage { get; set; } = null!; + [Export] public RKnockback? RKnockback { get; set; } = null!; + [Export] public RHealth? RHealth { get; set; } = null!; [ExportGroup("Targeting")] [Export(PropertyHint.Range, "0,20,0.1,or_greater")] @@ -102,7 +114,7 @@ public partial class PlayerController : CharacterBody3D, [ExportGroup("Instantiation")] [Export] - public PackedScene Explosion { get; set; } + public PackedScene Explosion { get; set; } = null!; // Movement stuff [ExportCategory("Movement")] @@ -129,7 +141,7 @@ public partial class PlayerController : CharacterBody3D, [Export(PropertyHint.Range, "0,1,0.01,or_greater")] public float MantleTime { get; set; } = 0.1f; [Export] - public PackedScene MantlePath { get; set; } + public PackedScene MantlePath { get; set; } = null!; [Export(PropertyHint.Range, "0,50,0.1")] public float MantleDashStrength { get; set; } = 15f; @@ -254,8 +266,8 @@ public partial class PlayerController : CharacterBody3D, // Stairs and shit private float _lastFrameWasOnFloor = -Mathf.Inf; private const int NumOfHeadCollisionDetectors = 4; - private RayCast3D[] _headCollisionDetectors; - private AudioStreamPlaybackInteractive _audioStream; + private RayCast3D[] _headCollisionDetectors = null!; + private AudioStreamPlaybackInteractive _audioStream = null!; // Basic movement private bool _movementEnabled = true; @@ -265,8 +277,8 @@ public partial class PlayerController : CharacterBody3D, private float _inputRotateFloorplane; // Basic falling - internal float _targetSpeed; - internal float _gravity; + internal float TargetSpeed; + internal float Gravity; // Jump stuff private int _currentInputBufferFrames; @@ -276,10 +288,10 @@ public partial class PlayerController : CharacterBody3D, // Mantle stuff private bool _shouldMantleOnDashEnded; - private Path _mantlePath; + private Path? _mantlePath; private bool _customMantle; private Transform3D _customMantleStartTransform; - private Curve3D _customMantleCurve; + private Curve3D _customMantleCurve = null!; private Vector3 _mantleStartPosition; private Vector3 _velocityOnMantleStarted = Vector3.Zero; @@ -290,7 +302,7 @@ public partial class PlayerController : CharacterBody3D, private Vector3 _currentWallContactPoint = Vector3.Zero; // Dash stuff - internal bool _canDash = true; + internal bool CanDash = true; private bool _canDashAirborne = true; private float _playerHeight; private float _playerRadius; @@ -316,61 +328,61 @@ public partial class PlayerController : CharacterBody3D, private float _aimAssistMultiplier = 1.0f; // Timers - private Timer _timeScaleAimInAirTimer; - private Timer _weaponThrowUncatchableTimer; - private Timer _simpleDashCooldownTimer; - private Timer _airborneDashCooldownTimer; - private Timer _powerCooldownTimer; - private Timer _invincibilityTimer; - private Timer _attackCooldown; + private Timer _timeScaleAimInAirTimer = null!; + private Timer _weaponThrowUncatchableTimer = null!; + private Timer _simpleDashCooldownTimer = null!; + private Timer _airborneDashCooldownTimer = null!; + private Timer _powerCooldownTimer = null!; + private Timer _invincibilityTimer = null!; + private Timer _attackCooldown = null!; // State chart - private StateChart _playerState; + private StateChart _playerState = null!; - private StateChartState _aiming; - private StateChartState _powerExpired; - private StateChartState _powerRecharging; - private StateChartState _powerFull; + private StateChartState _aiming = null!; + private StateChartState _powerExpired = null!; + private StateChartState _powerRecharging = null!; + private StateChartState _powerFull = null!; - private StateChartState _grounded; - private StateChartState _airborne; - private StateChartState _coyoteEnabled; - private StateChartState _jumping; - private StateChartState _simpleJump; - private StateChartState _doubleJump; - private StateChartState _mantling; - private StateChartState _simpleDash; - private StateChartState _aimedDash; - private StateChartState _weaponDash; - private StateChartState _sliding; - private StateChartState _groundSliding; - private StateChartState _airGliding; - private StateChartState _airGlidingDoubleJump; - private StateChartState _slideCanceled; - private StateChartState _slamming; - private StateChartState _onWall; - private StateChartState _onWallHugging; - private StateChartState _onWallHanging; - private StateChartState _onWallRunning; + private StateChartState _grounded = null!; + private StateChartState _airborne = null!; + private StateChartState _coyoteEnabled = null!; + private StateChartState _jumping = null!; + private StateChartState _simpleJump = null!; + private StateChartState _doubleJump = null!; + private StateChartState _mantling = null!; + private StateChartState _simpleDash = null!; + private StateChartState _aimedDash = null!; + private StateChartState _weaponDash = null!; + private StateChartState _sliding = null!; + private StateChartState _groundSliding = null!; + private StateChartState _airGliding = null!; + private StateChartState _airGlidingDoubleJump = null!; + private StateChartState _slideCanceled = null!; + private StateChartState _slamming = null!; + private StateChartState _onWall = null!; + private StateChartState _onWallHugging = null!; + private StateChartState _onWallHanging = null!; + private StateChartState _onWallRunning = null!; - private StateChartState _attackStandard; - private StateChartState _attackDash; - private StateChartState _parryStandard; - private StateChartState _parryDash; + private StateChartState _attackStandard = null!; + private StateChartState _attackDash = null!; + private StateChartState _parryStandard = null!; + private StateChartState _parryDash = null!; - private Transition _onJumpFromWall; - private Transition _onJumpFromWallFalling; - private Transition _onJumpFromWallRunning; - private Transition _onLeaveWallFromRun; - private Transition _onAirborneToGrounded; + private Transition _onJumpFromWall = null!; + private Transition _onJumpFromWallFalling = null!; + private Transition _onJumpFromWallRunning = null!; + private Transition _onLeaveWallFromRun = null!; + private Transition _onAirborneToGrounded = null!; - private Transition _onGroundSlideJump; - private Transition _onAirGlideDoubleJump; + private Transition _onGroundSlideJump = null!; + private Transition _onAirGlideDoubleJump = null!; // Damage - public CDamageable CDamageable { get; set; } - public CHealth CHealth { get; set; } - public CKnockback CKnockback { get; set; } + public CDamageable? CDamageable { get; set; } + public CHealth? CHealth { get; set; } + public CKnockback? CKnockback { get; set; } public float CurrentHealth { get; set; } private bool _isInvincible; @@ -383,9 +395,9 @@ public partial class PlayerController : CharacterBody3D, private readonly List _hitEnemies = new List(); - private ShapeCast3D _closeEnemyDetector; - private RayCast3D _aimAssisRayCast; - private Camera3D _camera; + private ShapeCast3D _closeEnemyDetector = null!; + private RayCast3D _aimAssisRayCast = null!; + private Camera3D _camera = null!; public override void _Ready() { @@ -402,18 +414,39 @@ public partial class PlayerController : CharacterBody3D, _aimAssisRayCast = GetNode("AimAssistRayCast"); _aimAssisRayCast.TargetPosition = _aimAssisRayCast.TargetPosition.Normalized() * (TargetingDistance*1.5f); + // Forge stuff + var forgeManager = GetTree().Root.GetNode("ForgeManager")!; + var baseTags = new TagContainer( + forgeManager.TagsManager, + [ + Tag.RequestTag(forgeManager.TagsManager, "character.player"), + Tag.RequestTag(forgeManager.TagsManager, "class.warrior") + ]); + + Attributes = new EntityAttributes(new PlayerAttributeSet()); + Tags = new EntityTags(baseTags); + EffectsManager = new EffectsManager(this, forgeManager.CuesManager); + Abilities = new(this); + Events = new(); + + var health = Attributes["PlayerAttributeSet.Health"].CurrentValue; // 100 + var mana = Attributes["PlayerAttributeSet.Mana"].CurrentValue; // 100 + var strength = Attributes["PlayerAttributeSet.Strength"].CurrentValue; // 10 + var speed = Attributes["PlayerAttributeSet.Speed"].CurrentValue; // 5 + GD.Print(health, mana, strength, speed); + // DashIndicator = GetNode("%DashIndicator"); PowerCooldownIndicator = GetNode("%DashCooldownIndicator"); PowerCooldownIndicator.Visible = false; EmpoweredActionsLeft = MaxNumberOfEmpoweredActions; - _targetSpeed = WalkSpeed; + TargetSpeed = WalkSpeed; DashIndicatorNode = GetNode("DashIndicator"); DashIndicatorMesh = GetNode("DashIndicator/DashIndicatorMesh"); - DashIndicatorMeshCylinder = DashIndicatorMesh.Mesh as CylinderMesh; + DashIndicatorMeshCylinder = (DashIndicatorMesh.Mesh as CylinderMesh)!; DashIndicatorMesh.Visible = false; SfxPlayer = GetNode("SFXPlayer"); - _audioStream = SfxPlayer.GetStreamPlayback() as AudioStreamPlaybackInteractive; + _audioStream = (SfxPlayer.GetStreamPlayback() as AudioStreamPlaybackInteractive)!; // Camera stuff HeadSystem = GetNode("HeadSystem"); @@ -539,7 +572,7 @@ public partial class PlayerController : CharacterBody3D, // Movement stuff // Getting universal setting from GODOT editor to be in sync - _gravity = (float)ProjectSettings.GetSetting("physics/3d/default_gravity"); + Gravity = (float)ProjectSettings.GetSetting("physics/3d/default_gravity"); MantleSystem.Init(); StairsSystem.Init(stairsBelowRayCast3D, stairsAheadRayCast3D, cameraSmooth); DashSystem.Init(HeadSystem, _camera); @@ -701,7 +734,7 @@ public partial class PlayerController : CharacterBody3D, public void SetPlayerHealthOverride(float newHealthValue) { RHealth.StartingHealth = newHealthValue; - CHealth.CurrentHealth = newHealthValue; + CHealth!.CurrentHealth = newHealthValue; PlayerUi.Initialize(CHealth.CurrentHealth); } public void SetPlayerDamageOverride(float newDamageValue) @@ -734,7 +767,7 @@ public partial class PlayerController : CharacterBody3D, return; } - _canDash = true; + CanDash = true; _canDashAirborne = true; _playerState.SendEvent("dash"); } @@ -761,7 +794,7 @@ public partial class PlayerController : CharacterBody3D, public void OnAirborneToGrounded() { HeadSystem.OnJumpEnded(); - _audioStream!.SwitchToClipByName("land"); + _audioStream.SwitchToClipByName("land"); } public bool IsGroundLike() @@ -968,7 +1001,7 @@ public partial class PlayerController : CharacterBody3D, // Utilities // /////////////////////////// - public float CalculateGravityForce() => _gravity * Weight; + public float CalculateGravityForce() => Gravity * Weight; // Camera stuff private Vector2 ComputeAimAssist() @@ -1031,8 +1064,8 @@ public partial class PlayerController : CharacterBody3D, var acceleration = dir.Length() > 0 ? accelerationFactor : decelerationFactor; - float xAcceleration = Mathf.Lerp(Velocity.X, dir.X * _targetSpeed, delta * acceleration); - float zAcceleration = Mathf.Lerp(Velocity.Z, dir.Z * _targetSpeed, delta * acceleration); + float xAcceleration = Mathf.Lerp(Velocity.X, dir.X * TargetSpeed, delta * acceleration); + float zAcceleration = Mathf.Lerp(Velocity.Z, dir.Z * TargetSpeed, delta * acceleration); return new Vector3(xAcceleration, 0, zAcceleration); } public Vector3 ComputeHVelocityGround(float delta) @@ -1091,7 +1124,7 @@ public partial class PlayerController : CharacterBody3D, /////////////////////////// public void DashCooldownTimeout() { - _canDash = true; + CanDash = true; } public void AirborneDashCooldownTimeout() { @@ -1124,8 +1157,8 @@ public partial class PlayerController : CharacterBody3D, return; } - if (!_canDash) return; - _canDash = false; + if (!CanDash) return; + CanDash = false; _simpleDashCooldownTimer.Start(); _playerState.SendEvent("dash"); } @@ -1166,7 +1199,7 @@ public partial class PlayerController : CharacterBody3D, if (MantleSystem.IsMantlePossible && IsPlayerInputtingForward()) { // _bufferedAction = BufferedActions.MantleDash; - _canDash = true; // Restore dash ability + CanDash = true; // Restore dash ability _playerState.SendEvent("mantle"); } } @@ -1203,7 +1236,7 @@ public partial class PlayerController : CharacterBody3D, public void OnWallStarted() { if (_simpleDashCooldownTimer.IsStopped()) - _canDash = true; + CanDash = true; else _simpleDashCooldownTimer.Start(); @@ -1452,7 +1485,7 @@ public partial class PlayerController : CharacterBody3D, public void OnJumpStarted(float verticalVelocity) { HeadSystem.OnJumpStarted(); - _audioStream!.SwitchToClipByName("jump"); + _audioStream.SwitchToClipByName("jump"); _framesSinceJumpAtApex = 0; var angle = GetFloorAngle(); @@ -1474,7 +1507,7 @@ public partial class PlayerController : CharacterBody3D, } public void OnDoubleJumpStarted() { - _canDash = true; + CanDash = true; // _canDashAirborne = true; OnJumpStarted(DoubleJumpStartVelocity); _bufferedAction = BufferedActions.None; @@ -1559,7 +1592,7 @@ public partial class PlayerController : CharacterBody3D, public void OnMantleStarted() { HeadSystem.OnMantle(); - _audioStream!.SwitchToClipByName("mantle"); + _audioStream.SwitchToClipByName("mantle"); _mantlePath = MantlePath.Instantiate() as Path; if (_mantlePath == null) @@ -1584,11 +1617,11 @@ public partial class PlayerController : CharacterBody3D, } public void HandleMantling(float delta) { - GlobalPosition = _mantlePath.Target.GlobalPosition; + GlobalPosition = _mantlePath!.Target.GlobalPosition; } public void MantleFinished() { - _mantlePath.Teardown(); + _mantlePath!.Teardown(); // SetVelocity(_finalCurveDirection.Normalized() * _speedOverCurve); @@ -1667,8 +1700,8 @@ public partial class PlayerController : CharacterBody3D, } public void SlideStarted() { - _targetSpeed = Velocity.Length(); - _audioStream!.SwitchToClipByName("glide"); + TargetSpeed = Velocity.Length(); + _audioStream.SwitchToClipByName("glide"); SetupSlideCollision(); SlidingEnemyDetector.Monitoring = true; @@ -1741,7 +1774,7 @@ public partial class PlayerController : CharacterBody3D, public void OnSlideCanceled() { SetupStandingCollision(); - _targetSpeed = WalkSpeed; + TargetSpeed = WalkSpeed; } public void HandleSlideCanceled(float delta) { @@ -1802,8 +1835,8 @@ public partial class PlayerController : CharacterBody3D, IsInvincible = false; SetupStandingCollision(); - _audioStream!.SwitchToClipByName("footsteps"); - _targetSpeed = WalkSpeed; + _audioStream.SwitchToClipByName("footsteps"); + TargetSpeed = WalkSpeed; } public void EnemyHitWhileSliding(Node enemy) @@ -1836,7 +1869,7 @@ public partial class PlayerController : CharacterBody3D, { SetHorizontalVelocity(Vector2.Zero); SetVerticalVelocity(-SlamSpeed); - _audioStream!.SwitchToClipByName("dash"); + _audioStream.SwitchToClipByName("dash"); } public void HandleSlam(float delta) { @@ -1845,7 +1878,7 @@ public partial class PlayerController : CharacterBody3D, public void SlamEnded() { HeadSystem.OnGetHit(); - _audioStream!.SwitchToClipByName("slam"); + _audioStream.SwitchToClipByName("slam"); if (Explosion.Instantiate() is not Explosion explosion) return; explosion.Radius = 10f; @@ -1978,7 +2011,7 @@ public partial class PlayerController : CharacterBody3D, _dashDirection = travel.Normalized(); var shouldRebound = false; - if (DashSystem.CanDashThroughTarget && DashSystem.CollidedObject is ITargetable targetable) + if (DashSystem is { CanDashThroughTarget: true, CollidedObject: ITargetable targetable }) { var plannedDashLocation = targetable.GetTargetGlobalPosition() + Vector3.Down*_playerHeight/2; travel = plannedDashLocation - GlobalPosition; @@ -2063,7 +2096,7 @@ public partial class PlayerController : CharacterBody3D, DashSystem.HasHit, DashSystem.CollisionPoint, DashSystem.CollisionNormal, - DashSystem.CollidedObject as Node); + (DashSystem.CollidedObject as Node)!); } public void RecoverWeapon() { @@ -2167,7 +2200,7 @@ public partial class PlayerController : CharacterBody3D, WeaponSystem.PlantObject = null; } - public void ManageAttackedEnemyPostDash(Node enemy) + public void ManageAttackedEnemyPostDash(Node? enemy) { if (enemy is IDamageable damageable) { @@ -2227,7 +2260,7 @@ public partial class PlayerController : CharacterBody3D, private bool _isEnemyInDashAttackRange; private Vector3 _targetHitLocation; private Vector3 _targetLocation; - private Object _targetObject; + private Object? _targetObject; public void HandleEnemyTargeting() { _isEnemyInDashAttackRange = false; @@ -2235,7 +2268,7 @@ public partial class PlayerController : CharacterBody3D, var enemyTargetState = PlayerUi.TargetState.NoTarget; var positionOnScreen = Vector2.Zero; - if (DashSystem.CanDashThroughTarget && DashSystem.CollidedObject is ITargetable dashTarget) + if (DashSystem is { CanDashThroughTarget: true, CollidedObject: ITargetable dashTarget }) { enemyTargetState = PlayerUi.TargetState.TargetWouldKill; _targetLocation = dashTarget.GetTargetGlobalPosition(); @@ -2279,11 +2312,11 @@ public partial class PlayerController : CharacterBody3D, if (IsInvincible) return damageRecord with { Damage = new RDamage(0, damageRecord.Damage.DamageType) }; - var finalDamage = CDamageable.TakeDamage(damageRecord); + var finalDamage = CDamageable!.TakeDamage(damageRecord); DamageTaken?.Invoke(this, finalDamage); HeadSystem.OnGetHit(); - _audioStream!.SwitchToClipByName("damage_taken"); + _audioStream.SwitchToClipByName("damage_taken"); TriggerHitstop(); OnHitInvincibility(); @@ -2292,7 +2325,7 @@ public partial class PlayerController : CharacterBody3D, public DamageRecord ComputeDamage(DamageRecord damageRecord) { - return CDamageable.ComputeDamage(damageRecord); + return CDamageable!.ComputeDamage(damageRecord); } public void OnHitInvincibility() @@ -2305,24 +2338,24 @@ public partial class PlayerController : CharacterBody3D, { _attackCooldown.Start(); HeadSystem.OnHit(); - _audioStream!.SwitchToClipByName("attacks"); + _audioStream.SwitchToClipByName("attacks"); } public void OnStandardParryStarted() { _attackCooldown.Start(); HeadSystem.OnParry(); - _audioStream!.SwitchToClipByName("parry"); + _audioStream.SwitchToClipByName("parry"); } - private PhysicsDirectSpaceState3D _spaceState; + private PhysicsDirectSpaceState3D _spaceState = null!; public void StartDashAction(bool isParry) { if (isParry) HeadSystem.OnParry(); else HeadSystem.OnHit(); var streamName = isParry ? "parry" : "attacks"; - _audioStream!.SwitchToClipByName(streamName); + _audioStream.SwitchToClipByName(streamName); IsInvincible = true; var plannedDashLocation = _targetLocation + Vector3.Down*_playerHeight/2; @@ -2452,7 +2485,7 @@ public partial class PlayerController : CharacterBody3D, _hitEnemies.Clear(); HeadSystem.OnHitTarget(); - _audioStream!.SwitchToClipByName("hits"); + _audioStream.SwitchToClipByName("hits"); TriggerHitstop(); } @@ -2469,19 +2502,18 @@ public partial class PlayerController : CharacterBody3D, } public HealthChangedRecord ReduceHealth(IDamageable source, DamageRecord damageRecord) { - GD.Print("That's NOT fine"); - var record = CHealth.ReduceHealth(source, damageRecord); + var record = CHealth!.ReduceHealth(source, damageRecord); HealthChanged?.Invoke(this, record); return record; } public void RegisterKnockback(KnockbackRecord knockbackRecord) { - CKnockback.RegisterKnockback(knockbackRecord); + CKnockback!.RegisterKnockback(knockbackRecord); } public Vector3 ComputeKnockback() { - var kb = CKnockback.ComputeKnockback(); + var kb = CKnockback!.ComputeKnockback(); return kb; } @@ -2500,10 +2532,9 @@ public partial class PlayerController : CharacterBody3D, IsInvincible = false; } - // Sound public void OnFootStepped() { - _audioStream!.SwitchToClipByName("footsteps"); + _audioStream.SwitchToClipByName("footsteps"); } } diff --git a/tests/player/DashSystemUnitTest.cs b/tests/player/DashSystemUnitTest.cs index 30ba91d2..1da71c91 100644 --- a/tests/player/DashSystemUnitTest.cs +++ b/tests/player/DashSystemUnitTest.cs @@ -18,17 +18,17 @@ public class DashSystemUnitTest _dashSystem.DashCast3D = new ShapeCast3D(); _dashSystem.AddChild(_dashSystem.DashCast3D); - _dashSystem._dashCastDrop = new ShapeCast3D(); - _dashSystem.AddChild(_dashSystem._dashCastDrop); + _dashSystem.DashCastDrop = new ShapeCast3D(); + _dashSystem.AddChild(_dashSystem.DashCastDrop); - _dashSystem._dashTarget = new MeshInstance3D(); - _dashSystem.AddChild(_dashSystem._dashTarget); + _dashSystem.DashTarget = new MeshInstance3D(); + _dashSystem.AddChild(_dashSystem.DashTarget); - _dashSystem._dashDropIndicator = new MeshInstance3D(); - _dashSystem.AddChild(_dashSystem._dashDropIndicator); + _dashSystem.DashDropIndicator = new MeshInstance3D(); + _dashSystem.AddChild(_dashSystem.DashDropIndicator); - _dashSystem._dashDropLocationIndicator = new MeshInstance3D(); - _dashSystem.AddChild(_dashSystem._dashDropLocationIndicator); + _dashSystem.DashDropLocationIndicator = new MeshInstance3D(); + _dashSystem.AddChild(_dashSystem.DashDropLocationIndicator); } [AfterTest] @@ -41,15 +41,15 @@ public class DashSystemUnitTest public void TestStopPreparingDash() { _dashSystem.CanDashThroughTarget = true; - _dashSystem._dashTarget.Visible = true; - _dashSystem._dashDropIndicator.Visible = true; - _dashSystem._dashDropLocationIndicator.Visible = true; + _dashSystem.DashTarget.Visible = true; + _dashSystem.DashDropIndicator.Visible = true; + _dashSystem.DashDropLocationIndicator.Visible = true; _dashSystem.StopPreparingDash(); AssertBool(_dashSystem.CanDashThroughTarget).IsFalse(); - AssertBool(_dashSystem._dashTarget.Visible).IsFalse(); - AssertBool(_dashSystem._dashDropIndicator.Visible).IsFalse(); - AssertBool(_dashSystem._dashDropLocationIndicator.Visible).IsFalse(); + AssertBool(_dashSystem.DashTarget.Visible).IsFalse(); + AssertBool(_dashSystem.DashDropIndicator.Visible).IsFalse(); + AssertBool(_dashSystem.DashDropLocationIndicator.Visible).IsFalse(); } } diff --git a/tests/player/PlayerControllerUnitTest.cs b/tests/player/PlayerControllerUnitTest.cs index 3a82f4a8..c41fe8fc 100644 --- a/tests/player/PlayerControllerUnitTest.cs +++ b/tests/player/PlayerControllerUnitTest.cs @@ -15,8 +15,8 @@ public class PlayerControllerUnitTest public void SetupTest() { _player = new PlayerController(); - _player._targetSpeed = 7.0f; - _player._gravity = 9.8f; + _player.TargetSpeed = 7.0f; + _player.Gravity = 9.8f; var rHealth = new RHealth(100.0f); _player.RHealth = rHealth; @@ -113,9 +113,9 @@ public class PlayerControllerUnitTest [TestCase] public void TestDashCooldownTimeout() { - _player._canDash = false; + _player.CanDash = false; _player.DashCooldownTimeout(); - AssertBool(_player._canDash).IsTrue(); + AssertBool(_player.CanDash).IsTrue(); } [TestCase] diff --git a/tools/ForgeManager.cs b/tools/ForgeManager.cs new file mode 100644 index 00000000..a77fcdb1 --- /dev/null +++ b/tools/ForgeManager.cs @@ -0,0 +1,27 @@ +using Gamesmiths.Forge.Cues; +using Gamesmiths.Forge.Tags; +using Godot; + +namespace Movementtests.tools; + +public partial class ForgeManager : Node +{ + public CuesManager CuesManager { get; private set; } = new CuesManager(); + public TagsManager TagsManager { get; private set; } = new TagsManager( + [ + "character.player", + "class.warrior", + "status.stunned", + "status.burning", + "status.enraged", + "status.immune.fire", + "cues.damage.fire", + "events.combat.damage", + "events.combat.hit", + "cooldown.fireball" + ]); + + public ForgeManager() + { + } +} \ No newline at end of file diff --git a/tools/ForgeManager.cs.uid b/tools/ForgeManager.cs.uid new file mode 100644 index 00000000..5121a6e3 --- /dev/null +++ b/tools/ForgeManager.cs.uid @@ -0,0 +1 @@ +uid://c75tpswl62eew