adjustments on cadence

This commit is contained in:
Nilton Constantino 2026-06-13 19:48:59 +01:00
parent 998fd1e462
commit c4e3723e07
No known key found for this signature in database
20 changed files with 3728 additions and 3495 deletions

View File

@ -0,0 +1,85 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: f28542aec01041178adfbc30f7a2a82a, type: 3}
m_Name: Sentinel Config
m_EditorClassIdentifier: Assembly-CSharp::Intrepid.Gameplay.Entities.Player.Sentinel.SentinelConfig
walk:
speed: 5
run:
speed: 10
dashImpulse:
speed: 35
durationMS: 150
dashRecovery:
speed: 10
durationMS: 200
dashMaxAngleFromForward: 90
speedCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: -1
outSlope: -1
tangentMode: 34
weightedMode: 0
inWeight: 0
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 0
inSlope: -1
outSlope: -1
tangentMode: 34
weightedMode: 0
inWeight: 0.33333334
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
dashLanding:
durationMS: 100
dashBreaking:
speed: 10
durationMS: 300
speedCurve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 1
inSlope: -1
outSlope: -1
tangentMode: 34
weightedMode: 0
inWeight: 0
outWeight: 0.33333334
- serializedVersion: 3
time: 1
value: 0
inSlope: -1
outSlope: -1
tangentMode: 34
weightedMode: 0
inWeight: 0.33333334
outWeight: 0
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
fallLanding:
durationMS: 2000
knockdown:
knockoutTimeMultiplier: 0.1
knockdownDurationMS: 100
recoverDurationMS: 500
maxKnockdownStrength: 15

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0805cd1ce642240f5abe420367e78b5e
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because one or more lines are too long

View File

@ -2,23 +2,17 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.Cadence
{
public readonly struct CadenceEvaluation
{
public static CadenceEvaluation None = new(0f, 0f, CadenceBand.None, 0f, 0f);
public static CadenceEvaluation None = new(CadenceBand.None, 0f, 0f);
public float T { get; }
public float ElapsedAt { get; }
public CadenceBand Band { get; }
public float SettlementFactor { get; }
public float Recovery { get; }
public CadenceEvaluation(
float t,
float elapsedAt,
CadenceBand band,
float settlementFactor,
float recovery)
{
T = t;
ElapsedAt = elapsedAt;
Band = band;
SettlementFactor = settlementFactor;
Recovery = recovery;

View File

@ -7,43 +7,19 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.Cadence
[CreateAssetMenu(fileName = "Cadence Profile", menuName = "GON/Services/Cadence/Cadence Profile")]
public sealed class CadenceProfile : ScriptableObject
{
[SerializeField, Min(1f)] private float totalTimeMS = 370f;
[GroupConfigurations("Normalized Band End Points"), SerializeField, Range(0f, 1f)] private float strained;
[GroupConfigurations("Normalized Band End Points"), SerializeField, Range(0f, 1f)] private float aligned;
[GroupConfigurations("Normalized Band End Points"), SerializeField, Range(0f, 1f)] private float resonant;
[GroupConfigurations("Normalized Band End Points"), SerializeField, Range(0f, 1f)] private float strainedEndP = 0.25f;
[GroupConfigurations("Normalized Band End Points"), SerializeField, Range(0f, 1f)] private float alignedEndP = 0.65f;
[GroupConfigurations("Normalized Band End Points"), SerializeField, Range(0f, 1f)] private float resonantEndP = 1f;
[GroupConfigurations("Settlement"), SerializeField, Range(0f, 1f)] private float strainedSettlement = 1f;
[GroupConfigurations("Settlement"), SerializeField, Range(0f, 1f)] private float alignedSettlement = 0.5f;
[GroupConfigurations("Settlement"), SerializeField, Range(0f, 1f)] private float strainedSettlement;
[GroupConfigurations("Settlement"), SerializeField, Range(0f, 1f)] private float alignedSettlement;
[GroupConfigurations("Settlement"), SerializeField, Range(0f, 1f)] private float resonantSettlement;
[GroupConfigurations("Settlement"), SerializeField, Range(0f, 1f)] private float lateSettlement = 1f;
[GroupConfigurations("Settlement"), SerializeField, Range(0f, 1f)] private float lateSettlement;
[GroupConfigurations("Core Stability"), SerializeField, Range(0, 100)] private float maxCoreCost = 8f;
[GroupConfigurations("Core Stability"), SerializeField, Range(0, 100)] private float resonantRecovery = 8f;
public float TotalTimeMS => totalTimeMS;
public float TotalTime => TotalTimeMS * 0.001f;
public float StrainedEndP => strainedEndP;
public float AlignedEndP => alignedEndP;
public float ResonantEndP => resonantEndP;
// public float StrainedEndTime => TotalTime * strainedEndP;
// public float AlignedEndTime => TotalTime * alignedEndP;
// public float ResonantEndTime => TotalTime * resonantEndP;
//
// public float StrainedEndMS => totalTimeMS * strainedEndP;
// public float AlignedEndMS => totalTimeMS * alignedEndP;
// public float ResonantEndMS => totalTimeMS * resonantEndP;
public float StrainedSettlement => strainedSettlement;
public float AlignedSettlement => alignedSettlement;
public float ResonantSettlement => resonantSettlement;
public float LateSettlement => lateSettlement;
[GroupConfigurations("Core Stability"), SerializeField, Range(0, 50)] private float maxCoreCost;
[GroupConfigurations("Core Stability"), SerializeField, Range(0, 50)] private float resonantRecovery;
public float MaxCoreCost => maxCoreCost;
public float ResonantRecovery => resonantRecovery;
private void OnValidate()
{
@ -53,21 +29,12 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.Cadence
[GroupDebug, Button(ButtonSizes.Medium)]
private void Validate()
{
totalTimeMS = Mathf.Max(1f, totalTimeMS);
strained = Mathf.Clamp01(strained);
aligned = Mathf.Clamp01(aligned);
resonant = Mathf.Clamp01(resonant);
strainedEndP = Mathf.Clamp01(strainedEndP);
alignedEndP = Mathf.Clamp01(alignedEndP);
resonantEndP = Mathf.Clamp01(resonantEndP);
if (alignedEndP < strainedEndP)
{
alignedEndP = strainedEndP;
}
if (resonantEndP < alignedEndP)
{
resonantEndP = alignedEndP;
}
if (aligned < strained) aligned = strained;
if (resonant < aligned) resonant = aligned;
strainedSettlement = Mathf.Clamp01(strainedSettlement);
alignedSettlement = Mathf.Clamp01(alignedSettlement);
@ -78,55 +45,32 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.Cadence
resonantRecovery = Mathf.Max(0f, resonantRecovery);
}
public CadenceEvaluation Evaluate(float elapsedTime)
public CadenceEvaluation Evaluate(float t)
{
if (TotalTime <= 0f)
{
return CadenceEvaluation.None;
}
if (t < strained) return StrainedEvaluation();
if (t < aligned) return AlignedEvaluation();
if (t < resonant) return ResonantEvaluation();
return StrainedEvaluation();
}
var t = Mathf.Clamp01(elapsedTime / TotalTime);
public CadenceEvaluation StrainedEvaluation()
{
return new CadenceEvaluation(CadenceBand.Strained, strainedSettlement, 0f);
}
if (t < StrainedEndP)
{
return new CadenceEvaluation(
t,
elapsedTime,
CadenceBand.Strained,
StrainedSettlement,
0f
);
}
public CadenceEvaluation AlignedEvaluation()
{
return new CadenceEvaluation(CadenceBand.Aligned, alignedSettlement, 0f);
}
if (t < AlignedEndP)
{
return new CadenceEvaluation(
t,
elapsedTime,
CadenceBand.Aligned,
AlignedSettlement,
0f
);
}
public CadenceEvaluation ResonantEvaluation()
{
return new CadenceEvaluation(CadenceBand.Resonant, resonantSettlement, resonantRecovery);
}
if (t < ResonantEndP)
{
return new CadenceEvaluation(
t,
elapsedTime,
CadenceBand.Resonant,
ResonantSettlement,
ResonantRecovery
);
}
return new CadenceEvaluation(
t,
elapsedTime,
CadenceBand.Late,
LateSettlement,
0f
);
public CadenceEvaluation LateEvaluation()
{
return new CadenceEvaluation(CadenceBand.Late, lateSettlement, 0f);
}
}
}

View File

@ -1,4 +1,6 @@
using System;
using Intrepid.Core.TimeControl;
using Intrepid.Diagnostics;
using Intrepid.Utilities;
using UnityEngine;
@ -8,88 +10,87 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.Cadence
[CreateAssetMenu(fileName = "Cadence Service", menuName = "GON/Services/Cadence/Cadence Service")]
public class CadenceService : SingletonScriptableObject<CadenceService>
{
private Timer CadenceTimer { get; set; } = new();
private Timer CadenceProfileTimer { get; set; } = new();
private Timer CadenceTotalTimer { get; set; } = new();
private CadenceProfile CurrentProfile { get; set; }
private float TargetTime { get; set; }
private float StartedProfileAt { get; set; }
public bool IsCadenceRunning => CadenceTimer.IsRunning;
public float CadenceElapsedTime => (float)CadenceTimer.ElapsedTime;
public bool IsCadenceRunning => CadenceProfileTimer.IsRunning;
private float CadenceProfileElapsedTime => (float)CadenceProfileTimer.ElapsedTime; // elapsed time since a single cadence began
public float TotalCadenceElapsedTime => (float)CadenceTotalTimer.ElapsedTime; // elapsed time since first cadence began
private float _startedAt;
protected override void WhenInstantiate(CadenceService s)
{
base.WhenInstantiate(s);
ResetCadence();
ResetCadenceProfile();
CadenceTotalTimer.Stop();
}
public void BeginCadence(CadenceProfile profile, float elapsedTime)
public void BeginCadence(CadenceProfile profile, float targetTime)
{
if (profile is null)
if (profile is null || targetTime <= 0)
{
ResetCadence();
DLogger.LogError($"profile should not be null: (is null? {profile.IsNull()}); targetTime should be > 0: {targetTime}");
ResetCadenceProfile();
return;
}
_startedAt = elapsedTime;
StartedProfileAt = TimeSimulation.Instance.ScaledElapsedTime;
CurrentProfile = profile;
CadenceTimer.Start();
TargetTime = targetTime;
CadenceProfileTimer.Start();
if (CadenceTotalTimer.IsNotRunning) CadenceTotalTimer.Start();
}
public CadenceEvaluation EvaluateAndConsumeAt(float inputTimeAt)
public CadenceEvaluation EndCadence()
{
CadenceTotalTimer.Stop();
if (!IsCadenceRunning || CurrentProfile is null) // if cadence was already ended
{
return CadenceEvaluation.None;
}
var cadenceEvaluation = CurrentProfile.LateEvaluation();
ResetCadenceProfile();
return cadenceEvaluation;
}
public CadenceEvaluation TryEndCadenceProfileWithInputAt(float inputAt)
{
if (!IsCadenceRunning || CurrentProfile is null)
{
return CadenceEvaluation.None;
}
var elapsedAtInput = Mathf.Max(0f, inputTimeAt - _startedAt);
var evaluation = CurrentProfile.Evaluate(elapsedAtInput);
ResetCadence();
var elapsedAtInput = Mathf.Max(0f, inputAt - StartedProfileAt);
var evaluation = CurrentProfile.Evaluate(elapsedAtInput / TargetTime);
ResetCadenceProfile();
return evaluation;
}
public CadenceEvaluation EvaluateAndConsume()
public bool UpdateCadence(float deltaTime)
{
if (!IsCadenceRunning || CurrentProfile is null)
{
return CadenceEvaluation.None;
}
var evaluation = CurrentProfile.Evaluate(CadenceElapsedTime);
ResetCadence();
return evaluation;
}
public bool UpdateCadence(out CadenceEvaluation autoSettlement)
{
autoSettlement = CadenceEvaluation.None;
if (!IsCadenceRunning || CurrentProfile is null)
{
return false;
}
CadenceTimer.Update(Timer.ScaledTime);
if (!CadenceTimer.Check(CurrentProfile.TotalTime))
{
return false;
}
autoSettlement = CurrentProfile.Evaluate(CadenceElapsedTime);
ResetCadence();
CadenceProfileTimer.Update(deltaTime);
CadenceTotalTimer.Update(deltaTime);
return true;
}
public void ResetCadence()
public void ResetCadenceProfile()
{
CadenceTimer.Stop();
CadenceProfileTimer.Stop();
CurrentProfile = null;
TargetTime = 0;
}
}
}

View File

@ -1,4 +1,3 @@
using Intrepid.Gameplay.Entities.Player.Sentinel.Inputs;
using Intrepid.Utilities;
using TMPro;
using UnityEngine;
@ -15,12 +14,18 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.Cadence.UI
[GroupInjections, SerializeField] private Slider effective;
[GroupInjections, SerializeField] private Slider projection;
private string _lastCadenceTimer;
private string _lastCadenceConnectedCounter;
private void Update()
{
cadenceTimer.text = CadenceService.Instance.IsCadenceRunning
? CadenceService.Instance.CadenceElapsedTime.ToString("F2")
: "--";
btnElapsedTimes.text = controls.CadenceConnectedCounter.ToString();
if (CadenceService.Instance.IsCadenceRunning)
{
_lastCadenceTimer = $"{CadenceService.Instance.TotalCadenceElapsedTime * 1000f:F2}ms";
_lastCadenceConnectedCounter = $"{controls.CadenceConnectedCounter}";
}
cadenceTimer.text = _lastCadenceTimer;
btnElapsedTimes.text = _lastCadenceConnectedCounter;
effective.value = CoreStabilityService.Instance.EffectiveStabilityP;
projection.value = CoreStabilityService.Instance.ProjectedStabilityP;
}

View File

@ -1,24 +1,20 @@
using System;
using System.Linq;
using Intrepid.Core;
using Intrepid.Core.Camera;
using Intrepid.Core.Entities;
using Intrepid.Core.Entities.Messages;
using Intrepid.Core.Grounding;
using Intrepid.Core.TimeControl;
using Intrepid.Gameplay.Entities.Player.ActionBelt;
using Intrepid.Gameplay.Entities.Player.Sentinel;
using Intrepid.Gameplay.Entities.Player.Sentinel.Cadence;
using Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine;
using Intrepid.Structures;
using Intrepid.Utilities;
using Unity.Cinemachine;
using UnityEngine;
namespace Intrepid.Gameplay.Entities.Player.Sentinel
{
public class SentinelBrain : EntityBrain
{
[GroupInjections, SerializeField] private SentinelConfig config;
[GroupInjections, SerializeField] private PlayerInputResolver inputResolver;
[GroupInjections, SerializeField] private SentinelControls controls;
[GroupInjections, SerializeField] private ActionBeltManager actionBeltManager;
@ -29,6 +25,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel
public SentinelEntity Entity => RootEntity as SentinelEntity;
public SentinelStateType CurrentState => StateMachine.CurrentImplementation.GetStateKey();
public SentinelConfig Config => config;
public PlayerInputResolver InputResolver => inputResolver;
public SentinelControls Controls => controls;
public ActionBeltManager ActionBeltManager => actionBeltManager;
@ -84,19 +81,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel
StateMachine.CurrentImplementation.RunOnUpdate();
StateMachine.CurrentImplementation.RunAfterUpdate();
if (CadenceService.Instance.UpdateCadence(out var evaluation))
{
// DLogger.LogDebug(
// $"CADENCE EXPIRED: {evaluation.Band} " +
// $"t={evaluation.T * 100f}% " +
// $"elapsedAt={evaluation.ElapsedAt * 1000f}ms " +
// $"set={evaluation.SettlementFactor} " +
// $"rec={evaluation.Recovery}"
// );
Controls.ExpireCadence();
CoreStabilityService.Instance.Settle(evaluation);
}
CadenceService.Instance.UpdateCadence(Timer.ScaledTime);
CoreStabilityService.Instance.UpdateCore(Timer.ScaledTime);
// state machine could take this responsibility in the future...

View File

@ -0,0 +1,117 @@
using System;
using Intrepid.Utilities;
using Sirenix.OdinInspector;
using UnityEngine;
namespace Intrepid.Gameplay.Entities.Player.Sentinel
{
[Serializable, HideLabel, GroupConfigurations("Walk")]
public class WalkConfig
{
[SerializeField, Range(0, 100)] private float speed = 5;
public float Speed => speed;
}
[Serializable, HideLabel, GroupConfigurations("Run")]
public class RunConfig
{
[SerializeField, Range(0, 100)] private float speed = 10;
public float Speed => speed;
}
[Serializable, HideLabel, GroupConfigurations("Dash Impulse")]
public class DashImpulseConfig
{
[SerializeField, Range(0, 50)] private float speed = 35f;
[SerializeField, Range(0, 5000)] private float durationMS = 150f;
public float Speed => speed;
public float Duration => durationMS * 0.001f;
}
[Serializable, HideLabel, GroupConfigurations("Dash Recovery")]
public class DashRecoveryConfig
{
[SerializeField, Range(0, 30)] private float speed = 10;
[SerializeField, Range(0, 5000)] private float durationMS = 200f;
[SerializeField, Range(15, 90)] private float dashMaxAngleFromForward = 90f;
[SerializeField] private AnimationCurve speedCurve;
public float Speed => speed;
public float Duration => durationMS * 0.001f;
public float DashMaxAngleFromForward => dashMaxAngleFromForward;
public AnimationCurve SpeedCurve => speedCurve;
}
[Serializable, HideLabel, GroupConfigurations("Dash Landing")]
public class DashLandingConfig
{
[SerializeField, Range(0, 500)] private float durationMS = 100f;
public float Duration => durationMS * 0.001f;
}
[Serializable, HideLabel, GroupConfigurations("Dash Breaking")]
public class DashBreakingConfig
{
[SerializeField, Range(5, 30)] private float speed = 10;
[SerializeField, Range(0, 500)] private float durationMS = 300f;
[SerializeField] private AnimationCurve speedCurve;
public float Speed => speed;
public float Duration => durationMS * 0.001f;
public AnimationCurve SpeedCurve => speedCurve;
}
[Serializable, HideLabel, GroupConfigurations("Fall Landing")]
public class FallLandingConfig
{
[SerializeField, Range(0, 5000)] private float durationMS = 2000f;
public float Duration => durationMS * 0.001f;
}
[Serializable, HideLabel, GroupConfigurations("Knockdown")]
public class KnockdownConfig
{
[SerializeField] private float knockoutTimeMultiplier = 0.1f;
[SerializeField, Range(0, 3000)] private float knockdownDurationMS = 100f;
[SerializeField, Range(0, 3000)] private float recoverDurationMS = 500f;
[SerializeField] private float maxKnockdownStrength = 15f;
public float KnockoutTimeMultiplier => knockoutTimeMultiplier;
public float KnockdownDuration => knockdownDurationMS * 0.001f;
public float RecoverDuration => recoverDurationMS * 0.001f;
public float MaxKnockdownStrength => maxKnockdownStrength;
}
[CreateAssetMenu(fileName = "Sentinel Config", menuName = "GON/Services/Sentinel/Config")]
public class SentinelConfig : ScriptableObject
{
[SerializeField] private WalkConfig walk;
[SerializeField] private RunConfig run;
[SerializeField] private DashImpulseConfig dashImpulse;
[SerializeField] private DashRecoveryConfig dashRecovery;
[SerializeField] private DashLandingConfig dashLanding;
[SerializeField] private DashBreakingConfig dashBreaking;
[SerializeField] private FallLandingConfig fallLanding;
[SerializeField] private KnockdownConfig knockdown;
public WalkConfig Walk => walk;
public RunConfig Run => run;
public DashImpulseConfig DashImpulse => dashImpulse;
public DashRecoveryConfig DashRecovery => dashRecovery;
public DashLandingConfig DashLanding => dashLanding;
public DashBreakingConfig DashBreaking => dashBreaking;
public FallLandingConfig FallLanding => fallLanding;
public KnockdownConfig Knockdown => knockdown;
}
}

View File

@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: f28542aec01041178adfbc30f7a2a82a
timeCreated: 1781369939

View File

@ -74,27 +74,16 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine
}
}
protected void BeginCadencedActionAt(CadenceProfile profile, float actionTimeAt)
{
LogAndProjectCadence(profile, CadenceService.Instance.EvaluateAndConsumeAt(actionTimeAt));
}
protected void BeginCadencedAction(CadenceProfile profile)
{
LogAndProjectCadence(profile, CadenceService.Instance.EvaluateAndConsume());
}
private void LogAndProjectCadence(CadenceProfile profile, CadenceEvaluation previousEvaluation)
protected void KeepCadenceWithInputAt(CadenceProfile nextProfile, float targetTime, float inputAt)
{
var previousEvaluation = CadenceService.Instance.TryEndCadenceProfileWithInputAt(inputAt);
if (previousEvaluation.Band != CadenceBand.None)
{
// DLogger.LogDebug(
// $"CADENCE CONNECTED: {previousEvaluation.Band} " +
// $"t={previousEvaluation.T * 100f}% " +
// $"elapsedAt={previousEvaluation.ElapsedAt * 1000f}ms " +
// $"set={previousEvaluation.SettlementFactor} " +
// $"rec={previousEvaluation.Recovery}"
// );
DLogger.LogDebug(
$"CADENCE CONNECTED: {previousEvaluation.Band} " +
$"set={previousEvaluation.SettlementFactor} " +
$"rec={previousEvaluation.Recovery}"
);
Brain.Controls.CadenceConnectedCounterInc();
CoreStabilityService.Instance.Settle(previousEvaluation);
@ -104,8 +93,20 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine
Brain.Controls.ExpireCadence();
}
CoreStabilityService.Instance.ProjectCost(profile.MaxCoreCost);
CadenceService.Instance.BeginCadence(profile, TimeSimulation.Instance.ScaledElapsedTime);
CoreStabilityService.Instance.ProjectCost(nextProfile.MaxCoreCost);
CadenceService.Instance.BeginCadence(nextProfile, targetTime);
}
protected void EndCadence()
{
var evaluation = CadenceService.Instance.EndCadence();
DLogger.LogDebug(
$"CADENCE ENDED: {evaluation.Band} " +
$"set={evaluation.SettlementFactor} " +
$"rec={evaluation.Recovery}"
);
CoreStabilityService.Instance.Settle(evaluation);
Brain.Controls.ExpireCadence();
}
protected bool TryConsumeDash()
@ -113,7 +114,8 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine
if (Brain.InputResolver.Sentinel.TryConsumeDash(out var dashTimeAt)) // dash with no ground: this could be a feature to be unlocked
//if (Brain.Entity.IsGrounded && Brain.InputResolver.TryConsumeDash(out var dashTimeAt))
{
BeginCadencedActionAt(Brain.Cadences.DashProfile, dashTimeAt);
var targetTime = Brain.Config.DashImpulse.Duration + Brain.Config.DashRecovery.Duration;
KeepCadenceWithInputAt(Brain.Cadences.DashProfile, targetTime, dashTimeAt);
return true;
}
return false;

View File

@ -7,12 +7,8 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
public class SentinelStateDashBreaking : SentinelState
{
[GroupConfigurations, SerializeField] private AnimationClip dashBreaking;
[GroupConfigurations, SerializeField, Range(5, 30)] private float speed = 10;
[GroupConfigurations, SerializeField, Range(0, 500)] private float extraTimeMS = 300f;
[GroupConfigurations, SerializeField] private AnimationCurve speedCurve;
private Timer Timer { get; } = new();
private float ExtraTime => extraTimeMS * 0.001f;
public override SentinelStateType GetStateKey()
{
@ -25,6 +21,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
protected override void RunOnEnter(ParameterStore parameterStore)
{
EndCadence();
Brain.Controls.ResetDash();
Brain.Entity.ModelAnimation.Play(dashBreaking);
Timer.Stop();
@ -49,14 +46,15 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
}
else
{
Brain.Entity.DesiredVelocity = Brain.Entity.Forward * speed;
Brain.Entity.DesiredVelocity = Brain.Entity.Forward * Brain.Config.DashBreaking.Speed;
}
if (Timer.IsNotRunning) return;
Timer.Update(Time.deltaTime);
var evaluation = speedCurve.Evaluate((float) Timer.ElapsedTime / ExtraTime);
Brain.Entity.DesiredVelocity = Brain.Entity.Forward * (speed * evaluation);
if (Timer.Check(ExtraTime))
var speedCurve = Brain.Config.DashBreaking.SpeedCurve;
var evaluation = speedCurve.Evaluate((float) Timer.ElapsedTime / Brain.Config.DashBreaking.Duration);
Brain.Entity.DesiredVelocity = Brain.Entity.Forward * (Brain.Config.DashBreaking.Speed * evaluation);
if (Timer.Check(Brain.Config.DashBreaking.Duration))
{
Timer.Stop();
Brain.ChangeState(SentinelStateType.Idle);

View File

@ -8,10 +8,6 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
public class SentinelStateDashImpulse : SentinelState
{
[GroupConfigurations, SerializeField] private AnimationClip dash;
[GroupConfigurations, SerializeField, Range(0, 100)] private float speed = 35;
[GroupConfigurations, SerializeField, Range(0, 5000)] private float targetTimeMS = 100f;
public float TargetTime => targetTimeMS * 0.001f;
private Timer Timer { get; } = new();
@ -52,9 +48,9 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
{
Timer.Update(Time.deltaTime);
Brain.Entity.DesiredVelocity = Brain.Entity.Forward * speed;
Brain.Entity.DesiredVelocity = Brain.Entity.Forward * Brain.Config.DashImpulse.Speed;
if (!Timer.Check(TargetTime))
if (!Timer.Check(Brain.Config.DashImpulse.Duration))
{
return;
}

View File

@ -7,10 +7,8 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
public class SentinelStateDashLanding : SentinelState
{
[GroupConfigurations, SerializeField] private AnimationClip dashLanding;
[GroupConfigurations, SerializeField, Range(0, 500)] private float landingTimeMS = 100f;
private Timer Timer { get; } = new();
private float LandingTime => landingTimeMS * 0.001f;
public override SentinelStateType GetStateKey()
{
@ -23,6 +21,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
protected override void RunOnEnter(ParameterStore parameterStore)
{
EndCadence();
Brain.Controls.ResetDash();
Brain.Entity.DesiredVelocity = Vector2.zero;
Brain.Entity.ModelAnimation.CrossFade(dashLanding, .1f);
@ -39,7 +38,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
{
if (Timer.IsNotRunning) return;
Timer.Update(Timer.ScaledTime);
if (Timer.Check(LandingTime))
if (Timer.Check(Brain.Config.DashLanding.Duration))
{
Timer.Stop();
Brain.ChangeState(SentinelStateType.Idle);

View File

@ -8,12 +8,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
public class SentinelStateDashRecovery : SentinelState
{
[GroupConfigurations, SerializeField] private AnimationClip dashRecovery;
[GroupConfigurations, SerializeField, Range(0, 30)] private float speed = 10;
[GroupConfigurations, SerializeField, Range(15, 90)] private float dashMaxAngleFromForward = 60f;
[GroupConfigurations, SerializeField, Range(0, 5000)] private float targetTimeMS = 200f;
[GroupConfigurations, SerializeField] private AnimationCurve speedCurve;
public float TargetTime => targetTimeMS * 0.001f;
private Timer Timer { get; } = new();
public override SentinelStateType GetStateKey()
@ -55,7 +50,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
var movement = Brain.InputResolver.Sentinel.Movement();
var forward = Brain.Entity.Forward;
var direction = GonFunctions
.ConstrainDirectionToForwardCone(movement, forward, dashMaxAngleFromForward);
.ConstrainDirectionToForwardCone(movement, forward, Brain.Config.DashRecovery.DashMaxAngleFromForward);
Brain.Entity.ChangeOrientation(direction);
return;
}
@ -72,14 +67,15 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
return;
}
Timer.Update(Time.deltaTime);
if (Timer.Check(TargetTime))
if (Timer.Check(Brain.Config.DashRecovery.Duration))
{
Timer.Stop();
return;
}
var speedFactor = 1f + speedCurve.Evaluate((float)Timer.ElapsedTime / TargetTime);
Brain.Entity.DesiredVelocity = Brain.Entity.Forward * (speed * speedFactor);
var speedCurve = Brain.Config.DashRecovery.SpeedCurve;
var speedFactor = 1f + speedCurve.Evaluate((float)Timer.ElapsedTime / Brain.Config.DashRecovery.Duration);
Brain.Entity.DesiredVelocity = Brain.Entity.Forward * (Brain.Config.DashRecovery.Speed * speedFactor);
}
}
}

View File

@ -26,6 +26,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
protected override void RunOnEnter(ParameterStore ps)
{
EndCadence();
Brain.Controls.ResetDash();
Brain.Entity.ModelAnimation.CrossFade(fall, .1f);
Brain.Entity.DesiredVelocity = Vector2.zero;

View File

@ -7,7 +7,6 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
public class SentinelStateFallLanding : SentinelState
{
[GroupConfigurations, SerializeField] private AnimationClip fallLanding;
[GroupConfigurations, SerializeField, Range(0, 5)] private float fallLandingDuration = 2f;
private Timer Timer { get; } = new();
@ -36,7 +35,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
{
if (Timer.IsNotRunning) return;
Timer.Update(Timer.ScaledTime);
if (!Timer.Check(fallLandingDuration)) return;
if (!Timer.Check(Brain.Config.FallLanding.Duration)) return;
Timer.Stop();
Brain.ChangeState(SentinelStateType.Idle);
}

View File

@ -1,4 +1,3 @@
using Intrepid.Diagnostics;
using Intrepid.Structures;
using Intrepid.Utilities;
using UnityEngine;
@ -9,10 +8,6 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
{
[GroupConfigurations, SerializeField] private AnimationClip knockdown;
[GroupConfigurations, SerializeField] private AnimationClip knockout;
[GroupConfigurations, SerializeField] private float KnockoutTimeMultiplier = 0.1f;
[GroupConfigurations, SerializeField, Range(0, 3)] private float knockdownTime = .1f;
[GroupConfigurations, SerializeField, Range(0, 3)] private float recoverTime = .5f;
[GroupConfigurations, SerializeField] private float maxKnockdown = 15f;
private Vector2 KnockdownForce { get; set; }
private float KnockoutTime { get; set; }
@ -34,8 +29,8 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
Brain.Entity.ModelAnimation.CrossFade(knockdown, 0.1f);
KnockdownForce = ps.Get<Vector2>(SentinelConstants.Parameters.KnockdownForce);
Brain.Entity.ChangeOrientation(-KnockdownForce.normalized);
KnockoutTime = KnockdownForce.sqrMagnitude * KnockoutTimeMultiplier;
Brain.Entity.DesiredVelocity = Vector2.ClampMagnitude(KnockdownForce, maxKnockdown);
KnockoutTime = KnockdownForce.sqrMagnitude * Brain.Config.Knockdown.KnockoutTimeMultiplier;
Brain.Entity.DesiredVelocity = Vector2.ClampMagnitude(KnockdownForce, Brain.Config.Knockdown.MaxKnockdownStrength);
KnockdownTimer.Start();
KnockoutTimer.Stop();
RecoverTimer.Stop();
@ -50,7 +45,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
if (RecoverTimer.IsRunning)
{
RecoverTimer.Update(Timer.ScaledTime);
if (RecoverTimer.Check(recoverTime))
if (RecoverTimer.Check(Brain.Config.Knockdown.RecoverDuration))
{
RecoverTimer.Stop();
Brain.ChangeState(SentinelStateType.Idle);
@ -62,7 +57,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
if (KnockoutTimer.IsRunning)
{
KnockoutTimer.Update(Timer.ScaledTime);
if (KnockoutTimer.Check(recoverTime))
if (KnockoutTimer.Check(Brain.Config.Knockdown.RecoverDuration))
{
KnockoutTimer.Stop();
RecoverTimer.Start();
@ -86,7 +81,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
}
KnockdownTimer.Update(Timer.ScaledTime);
if (KnockdownTimer.Check(knockdownTime))
if (KnockdownTimer.Check(Brain.Config.Knockdown.KnockdownDuration))
{
KnockdownTimer.Stop();
Brain.Entity.ModelAnimation.CrossFade(knockout, 0.1f);

View File

@ -7,8 +7,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
public class SentinelStateRun : SentinelState
{
[GroupConfigurations, SerializeField] private AnimationClip run;
[GroupConfigurations, SerializeField, Range(0, 100)] private float speed = 10;
[GroupConfigurations, SerializeField, Range(0, 10)] private float animationSpeed = 1.2f;
[GroupConfigurations, SerializeField, Range(0, 10)] private float animationSpeed = 3f;
private Vector2 Movement { get; set; }
@ -43,7 +42,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
return;
}
if (CheckMovement()) return;
Brain.Entity.DesiredVelocity = Movement * speed;
Brain.Entity.DesiredVelocity = Movement * Brain.Config.Run.Speed;
}
private bool CheckMovement()

View File

@ -7,8 +7,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
public class SentinelStateWalk : SentinelState
{
[GroupConfigurations, SerializeField] private AnimationClip walk;
[GroupConfigurations, SerializeField, Range(0, 100)] private float speed = 5;
[GroupConfigurations, SerializeField, Range(0, 100)] private float animationSpeed = 3;
[GroupConfigurations, SerializeField, Range(0, 100)] private float animationSpeed = 2;
private Vector2 Movement { get; set; }
@ -43,7 +42,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
return;
}
if (CheckMovement()) return;
Brain.Entity.DesiredVelocity = Movement * speed;
Brain.Entity.DesiredVelocity = Movement * Brain.Config.Walk.Speed;
}
private bool CheckMovement()