cadence first attempt
This commit is contained in:
parent
56baa88bad
commit
9aead314a7
@ -118,7 +118,7 @@ ModelImporter:
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: Dash
|
||||
name: Dash Impulse
|
||||
takeName: Armature|Main
|
||||
internalID: 3938472908730161291
|
||||
firstFrame: 158
|
||||
@ -147,7 +147,7 @@ ModelImporter:
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: Dash Window
|
||||
name: Dash Recovery
|
||||
takeName: Armature|Main
|
||||
internalID: 9206814923105168154
|
||||
firstFrame: 159
|
||||
@ -176,7 +176,7 @@ ModelImporter:
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: Dash Breaking
|
||||
name: Dash Landing
|
||||
takeName: Armature|Main
|
||||
internalID: 44099723154497190
|
||||
firstFrame: 171
|
||||
@ -234,7 +234,7 @@ ModelImporter:
|
||||
maskSource: {instanceID: 0}
|
||||
additiveReferencePoseFrame: 0
|
||||
- serializedVersion: 16
|
||||
name: FallLanding
|
||||
name: Fall Landing
|
||||
takeName: Armature|Main
|
||||
internalID: 7716892539185763080
|
||||
firstFrame: 165
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60e9c0806878144959bcc23c977fcdb2
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,24 @@
|
||||
%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: 8f4d583fd594418e8ecea0731be75f23, type: 3}
|
||||
m_Name: Dash - Cadence Profile
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Intrepid.Gameplay.Entities.Player.Sentinel.Cadence.CadenceProfile
|
||||
totalTimeMS: 400
|
||||
strainedEndP: 0.25
|
||||
alignedEndP: 0.65
|
||||
resonantEndP: 1
|
||||
strainedSettlement: 1
|
||||
alignedSettlement: 0.5
|
||||
resonantSettlement: 0
|
||||
lateSettlement: 1
|
||||
maxCoreCost: 8
|
||||
resonantRecovery: 5
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d78cbdd6d5253439f830d91ccedc2132
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,19 @@
|
||||
%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: 8cb4003a571646f28d99cec70813327d, type: 3}
|
||||
m_Name: Core Stability Service
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Intrepid.Gameplay.Entities.Player.Sentinel.Cadence.CoreStabilityService
|
||||
maxStability: 100
|
||||
unstableThresholdP: 0.7
|
||||
criticalThresholdP: 0.35
|
||||
collapsedRecoveryStability: 25
|
||||
naturalRecoveryPerSecond: 10
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7023b8d166c954e5a8b93090dc373803
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,18 @@
|
||||
%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: c03b6f34733d48c18d0373cc1ca3d338, type: 3}
|
||||
m_Name: Sentinel Controls
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Intrepid.Gameplay.Entities.Player.Sentinel.SentinelControls
|
||||
dashBreakingThreshold: 3
|
||||
cadenceConnectedThreshold: 3
|
||||
cadenceConnectedCounter: 0
|
||||
dashCounter: 0
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 648f106f61b2f40f6b83c7e3d14a1a2f
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,15 @@
|
||||
%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: 4042f157f2bd47e3938657e1c2fca5b0, type: 3}
|
||||
m_Name: Sentinel Input Resolver
|
||||
m_EditorClassIdentifier: Assembly-CSharp::Intrepid.Gameplay.Entities.Player.Sentinel.Inputs.SentinelInputResolver
|
||||
inputLifespan: 0.5
|
||||
@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4115e0e987fe248c998f6106517eb4e1
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -14,4 +14,6 @@ MonoBehaviour:
|
||||
m_EditorClassIdentifier: Intrepid General Utilities::Intrepid.Utilities.SingletonScriptableObjectManifest
|
||||
singletons:
|
||||
- {fileID: 11400000, guid: 9ea72f9e3cacb4fc495eff7431ec5551, type: 2}
|
||||
- {fileID: 11400000, guid: 4115e0e987fe248c998f6106517eb4e1, type: 2}
|
||||
- {fileID: 11400000, guid: 84f36528c13ab48d6ae2ae41878f2f9f, type: 2}
|
||||
- {fileID: 11400000, guid: 7023b8d166c954e5a8b93090dc373803, type: 2}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -78,7 +78,7 @@ namespace Intrepid.Core.Entities
|
||||
return StateMachine.ChangeState(state, parameters);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
public void UpdateStateMachine()
|
||||
{
|
||||
CurrentState = StateMachine.GetCurrentState().GetStateKey();
|
||||
}
|
||||
|
||||
3
Assets/Scripts/Intrepid/Core/TimeControl.meta
Normal file
3
Assets/Scripts/Intrepid/Core/TimeControl.meta
Normal file
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cfc7dee444ad4606b32b1b35c4b276a5
|
||||
timeCreated: 1781160724
|
||||
143
Assets/Scripts/Intrepid/Core/TimeControl/TimeSimulation.cs
Normal file
143
Assets/Scripts/Intrepid/Core/TimeControl/TimeSimulation.cs
Normal file
@ -0,0 +1,143 @@
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Core.TimeControl
|
||||
{
|
||||
internal enum TargetTimeScale
|
||||
{
|
||||
NONE,
|
||||
VERY_SLOW_MOTION,
|
||||
SLOW_MOTION,
|
||||
BREATH_MOTION,
|
||||
NORMAL,
|
||||
FAST_MOTION,
|
||||
}
|
||||
|
||||
[DefaultExecutionOrder(GonConstants.ExecutionOrder.TimeSimulation)]
|
||||
public class TimeSimulation : SingletonMonoBehaviour<TimeSimulation>
|
||||
{
|
||||
[GroupConfigurations, SerializeField, Range(0f, 1f)] private float verySlowMotionScale = 0.25f;
|
||||
[GroupConfigurations, SerializeField, Range(0f, 1f)] private float slowMotionScale = 0.5f;
|
||||
[GroupConfigurations, SerializeField, Range(0f, 1f)] private float breathMotionScale = 0.75f;
|
||||
[GroupConfigurations, SerializeField, Range(1f, 2f)] private float fastMotionScale = 1.25f;
|
||||
|
||||
public float UnscaledElapsedTime { get; private set; }
|
||||
public float ScaledElapsedTime { get; private set; }
|
||||
|
||||
private TargetTimeScale _currentTargetTimeScale = TargetTimeScale.NONE;
|
||||
private TargetTimeScale _targetTimeScale = TargetTimeScale.NONE;
|
||||
private float _blendStartedAt;
|
||||
private float _blendDuration;
|
||||
private float _blendStartScale;
|
||||
private float _blendTargetScale;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
SingletonInstantiation(false, s =>
|
||||
{
|
||||
s.ResetSimulation();
|
||||
});
|
||||
}
|
||||
|
||||
public void ResetSimulation()
|
||||
{
|
||||
Time.timeScale = 1f;
|
||||
|
||||
UnscaledElapsedTime = 0f;
|
||||
ScaledElapsedTime = 0f;
|
||||
|
||||
_currentTargetTimeScale = TargetTimeScale.NORMAL;
|
||||
_targetTimeScale = TargetTimeScale.NONE;
|
||||
|
||||
_blendStartedAt = 0f;
|
||||
_blendDuration = 0f;
|
||||
_blendStartScale = 1f;
|
||||
_blendTargetScale = 1f;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
UpdateTimeScaleBlend();
|
||||
|
||||
UnscaledElapsedTime += Time.unscaledDeltaTime;
|
||||
ScaledElapsedTime += Time.deltaTime;
|
||||
}
|
||||
|
||||
private void UpdateTimeScaleBlend()
|
||||
{
|
||||
if (_targetTimeScale == TargetTimeScale.NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (_blendDuration <= 0f)
|
||||
{
|
||||
Time.timeScale = _blendTargetScale;
|
||||
_currentTargetTimeScale = _targetTimeScale;
|
||||
_targetTimeScale = TargetTimeScale.NONE;
|
||||
return;
|
||||
}
|
||||
|
||||
var elapsed = UnscaledElapsedTime - _blendStartedAt;
|
||||
var t = Mathf.Clamp01(elapsed / _blendDuration);
|
||||
Time.timeScale = Mathf.Lerp(_blendStartScale, _blendTargetScale, t);
|
||||
|
||||
if (t >= 1f)
|
||||
{
|
||||
Time.timeScale = _blendTargetScale;
|
||||
_currentTargetTimeScale = _targetTimeScale;
|
||||
_targetTimeScale = TargetTimeScale.NONE;
|
||||
}
|
||||
}
|
||||
|
||||
public void AsBreathMotion(float blendTimeInSeconds = 0f)
|
||||
{
|
||||
BlendTo(TargetTimeScale.BREATH_MOTION, breathMotionScale, blendTimeInSeconds);
|
||||
}
|
||||
|
||||
public void AsVerySlowMotion(float blendTimeInSeconds = 0f)
|
||||
{
|
||||
BlendTo(TargetTimeScale.VERY_SLOW_MOTION, verySlowMotionScale, blendTimeInSeconds);
|
||||
}
|
||||
|
||||
public void AsSlowMotion(float blendTimeInSeconds = 0f)
|
||||
{
|
||||
BlendTo(TargetTimeScale.SLOW_MOTION, slowMotionScale, blendTimeInSeconds);
|
||||
}
|
||||
|
||||
public void AsFastMotion(float blendTimeInSeconds = 0f)
|
||||
{
|
||||
BlendTo(TargetTimeScale.FAST_MOTION, fastMotionScale, blendTimeInSeconds);
|
||||
}
|
||||
|
||||
public void AsNormalMotion(float blendTimeInSeconds = 0f)
|
||||
{
|
||||
BlendTo(TargetTimeScale.NORMAL, 1f, blendTimeInSeconds);
|
||||
}
|
||||
|
||||
private void BlendTo(
|
||||
TargetTimeScale target,
|
||||
float targetScale,
|
||||
float blendTimeInSeconds)
|
||||
{
|
||||
if (_currentTargetTimeScale == target)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (blendTimeInSeconds <= 0f)
|
||||
{
|
||||
Time.timeScale = targetScale;
|
||||
return;
|
||||
}
|
||||
|
||||
_targetTimeScale = target;
|
||||
|
||||
_blendStartedAt = UnscaledElapsedTime;
|
||||
_blendDuration = Mathf.Max(0f, blendTimeInSeconds);
|
||||
|
||||
_blendStartScale = Time.timeScale;
|
||||
_blendTargetScale = Mathf.Max(0f, targetScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c627436787e94833b34c62a63b81e075
|
||||
timeCreated: 1781160746
|
||||
@ -0,0 +1,11 @@
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel.Cadence
|
||||
{
|
||||
public enum CadenceBand
|
||||
{
|
||||
None,
|
||||
Strained,
|
||||
Aligned,
|
||||
Resonant,
|
||||
Late
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ca7e3fbd71414fb58db003ab08548dd5
|
||||
timeCreated: 1781091177
|
||||
@ -1,25 +0,0 @@
|
||||
using System;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel.Cadence
|
||||
{
|
||||
[Serializable]
|
||||
public class CadenceContext
|
||||
{
|
||||
[SerializeField, Range(0, 5000)] private float warmTimeMS;
|
||||
[SerializeField, Range(0, 5000)] private float activationTimeMS;
|
||||
[MinMaxSlider("warmTimeMS", "TotalTimeMS", true), SerializeField] private Vector2 optimalWindowMS;
|
||||
|
||||
public float OptimalMinTimeMS => optimalWindowMS.x;
|
||||
public float OptimalMaxTimeMS => optimalWindowMS.y;
|
||||
public float TotalTimeMS => warmTimeMS + activationTimeMS;
|
||||
|
||||
public float OptimalMinTime => OptimalMinTimeMS * 0.001f;
|
||||
public float OptimalMaxTime => OptimalMaxTimeMS * 0.001f;
|
||||
public float WarmTime => warmTimeMS * 0.001f;
|
||||
public float ActivationTime => activationTimeMS * 0.001f;
|
||||
public float TotalTime => (warmTimeMS + activationTimeMS) * 0.001f;
|
||||
public float OptimalTime => (OptimalMinTime + OptimalMaxTime) * 0.5f;
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df1d7ef780ec4251bc0c7101c986eeca
|
||||
timeCreated: 1781075513
|
||||
@ -0,0 +1,27 @@
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel.Cadence
|
||||
{
|
||||
public readonly struct CadenceEvaluation
|
||||
{
|
||||
public static CadenceEvaluation None = new(0f, 0f, 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aa860d1818f7460698edb395014cb9ae
|
||||
timeCreated: 1781091290
|
||||
@ -0,0 +1,132 @@
|
||||
using Intrepid.Utilities;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
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 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 resonantSettlement;
|
||||
[GroupConfigurations("Settlement"), SerializeField, Range(0f, 1f)] private float lateSettlement = 1f;
|
||||
|
||||
[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;
|
||||
|
||||
public float MaxCoreCost => maxCoreCost;
|
||||
public float ResonantRecovery => resonantRecovery;
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
Validate();
|
||||
}
|
||||
|
||||
[GroupDebug, Button(ButtonSizes.Medium)]
|
||||
private void Validate()
|
||||
{
|
||||
totalTimeMS = Mathf.Max(1f, totalTimeMS);
|
||||
|
||||
strainedEndP = Mathf.Clamp01(strainedEndP);
|
||||
alignedEndP = Mathf.Clamp01(alignedEndP);
|
||||
resonantEndP = Mathf.Clamp01(resonantEndP);
|
||||
|
||||
if (alignedEndP < strainedEndP)
|
||||
{
|
||||
alignedEndP = strainedEndP;
|
||||
}
|
||||
|
||||
if (resonantEndP < alignedEndP)
|
||||
{
|
||||
resonantEndP = alignedEndP;
|
||||
}
|
||||
|
||||
strainedSettlement = Mathf.Clamp01(strainedSettlement);
|
||||
alignedSettlement = Mathf.Clamp01(alignedSettlement);
|
||||
resonantSettlement = Mathf.Clamp01(resonantSettlement);
|
||||
lateSettlement = Mathf.Clamp01(lateSettlement);
|
||||
|
||||
maxCoreCost = Mathf.Max(0f, maxCoreCost);
|
||||
resonantRecovery = Mathf.Max(0f, resonantRecovery);
|
||||
}
|
||||
|
||||
public CadenceEvaluation Evaluate(float elapsedTime)
|
||||
{
|
||||
if (TotalTime <= 0f)
|
||||
{
|
||||
return CadenceEvaluation.None;
|
||||
}
|
||||
|
||||
var t = Mathf.Clamp01(elapsedTime / TotalTime);
|
||||
|
||||
if (t < StrainedEndP)
|
||||
{
|
||||
return new CadenceEvaluation(
|
||||
t,
|
||||
elapsedTime,
|
||||
CadenceBand.Strained,
|
||||
StrainedSettlement,
|
||||
0f
|
||||
);
|
||||
}
|
||||
|
||||
if (t < AlignedEndP)
|
||||
{
|
||||
return new CadenceEvaluation(
|
||||
t,
|
||||
elapsedTime,
|
||||
CadenceBand.Aligned,
|
||||
AlignedSettlement,
|
||||
0f
|
||||
);
|
||||
}
|
||||
|
||||
if (t < ResonantEndP)
|
||||
{
|
||||
return new CadenceEvaluation(
|
||||
t,
|
||||
elapsedTime,
|
||||
CadenceBand.Resonant,
|
||||
ResonantSettlement,
|
||||
ResonantRecovery
|
||||
);
|
||||
}
|
||||
|
||||
return new CadenceEvaluation(
|
||||
t,
|
||||
elapsedTime,
|
||||
CadenceBand.Late,
|
||||
LateSettlement,
|
||||
0f
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f4d583fd594418e8ecea0731be75f23
|
||||
timeCreated: 1781091714
|
||||
@ -1,61 +1,95 @@
|
||||
using System;
|
||||
using Intrepid.Utilities;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel.Cadence
|
||||
{
|
||||
[Serializable]
|
||||
[CreateAssetMenu(fileName = "Cadence Service", menuName = "GON/Services/Cadence Service")]
|
||||
[CreateAssetMenu(fileName = "Cadence Service", menuName = "GON/Services/Cadence/Cadence Service")]
|
||||
public class CadenceService : SingletonScriptableObject<CadenceService>
|
||||
{
|
||||
[GroupDebug, SerializeField, ReadOnly] private float currentCadence;
|
||||
|
||||
private Timer CadenceTimer { get; set; } = new();
|
||||
private CadenceProfile CurrentProfile { get; set; }
|
||||
|
||||
public float CurrentCadence
|
||||
{
|
||||
get => currentCadence;
|
||||
private set => currentCadence = value;
|
||||
}
|
||||
public bool IsCadenceRunning => CadenceTimer.IsRunning;
|
||||
public float CadenceElapsedTime => (float)CadenceTimer.ElapsedTime;
|
||||
public bool IsCadenceRunning => CadenceTotalTime > 0f && CadenceTimer.IsRunning;
|
||||
|
||||
private float CadenceTotalTime => CadenceContext is null ? 0f : 0.001f * CadenceContext.TotalTimeMS;
|
||||
private CadenceContext CadenceContext { get; set; }
|
||||
public float WarmCadencePercent => CadenceContext?.WarmTime / CadenceTotalTime ?? 0f;
|
||||
public float OptimalCadenceMinPercent => CadenceContext?.OptimalMinTime / CadenceTotalTime ?? 0f;
|
||||
public float OptimalCadenceMaxPercent => CadenceContext?.OptimalMaxTime / CadenceTotalTime ?? 0f;
|
||||
private float _startedAt;
|
||||
|
||||
protected override void WhenInstantiate(CadenceService s)
|
||||
{
|
||||
base.WhenInstantiate(s);
|
||||
StopCadence();
|
||||
ResetCadence();
|
||||
}
|
||||
|
||||
public void BeginCadence(CadenceProfile profile, float elapsedTime)
|
||||
{
|
||||
if (profile is null)
|
||||
{
|
||||
ResetCadence();
|
||||
return;
|
||||
}
|
||||
|
||||
_startedAt = elapsedTime;
|
||||
CurrentProfile = profile;
|
||||
CadenceTimer.Start();
|
||||
}
|
||||
|
||||
public void StartCadence(CadenceContext ctx)
|
||||
public CadenceEvaluation EvaluateAndConsumeAt(float inputTimeAt)
|
||||
{
|
||||
if (ctx is null || ctx.TotalTimeMS <= 0f) return;
|
||||
CadenceTimer.Start();
|
||||
CadenceContext = ctx;
|
||||
if (!IsCadenceRunning || CurrentProfile is null)
|
||||
{
|
||||
return CadenceEvaluation.None;
|
||||
}
|
||||
|
||||
var elapsedAtInput = Mathf.Max(0f, inputTimeAt - _startedAt);
|
||||
var evaluation = CurrentProfile.Evaluate(elapsedAtInput);
|
||||
ResetCadence();
|
||||
|
||||
return evaluation;
|
||||
}
|
||||
|
||||
public void StopCadence()
|
||||
public CadenceEvaluation EvaluateAndConsume()
|
||||
{
|
||||
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();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void ResetCadence()
|
||||
{
|
||||
CadenceTimer.Stop();
|
||||
CadenceContext = null;
|
||||
}
|
||||
|
||||
public void UpdateCadence()
|
||||
{
|
||||
if (CadenceTimer.IsNotRunning) return;
|
||||
CadenceTimer.Update(Timer.ScaledTime);
|
||||
var totalTime = CadenceTotalTime;
|
||||
CurrentCadence = CadenceElapsedTime / totalTime;
|
||||
if (CadenceTimer.Check(totalTime))
|
||||
{
|
||||
StopCadence();
|
||||
}
|
||||
CurrentProfile = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel.Cadence
|
||||
{
|
||||
public class Cadences : MonoBehaviour
|
||||
{
|
||||
[GroupInjections, SerializeField] private CadenceProfile dashProfile;
|
||||
|
||||
public CadenceProfile DashProfile => dashProfile;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d17424d8ff134fd89c1bee1bfc94054e
|
||||
timeCreated: 1781105637
|
||||
@ -0,0 +1,208 @@
|
||||
using System;
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel.Cadence
|
||||
{
|
||||
[Serializable]
|
||||
[CreateAssetMenu(fileName = "Core Stability Service", menuName = "GON/Services/Sentinel/Core Stability Service")]
|
||||
public class CoreStabilityService : SingletonScriptableObject<CoreStabilityService>
|
||||
{
|
||||
[GroupConfigurations, SerializeField, Min(1f)] private float maxStability = 100f;
|
||||
[GroupConfigurations, SerializeField, Range(0f, 1f)] private float unstableThresholdP = 0.7f;
|
||||
[GroupConfigurations, SerializeField, Range(0f, 1f)] private float criticalThresholdP = 0.35f;
|
||||
[GroupConfigurations, SerializeField, Min(0f)] private float collapsedRecoveryStability = 25f;
|
||||
[GroupConfigurations, SerializeField, Min(0f)] private float naturalRecoveryPerSecond = 3f;
|
||||
|
||||
public float MaxStability => maxStability;
|
||||
|
||||
public float EffectiveStability { get; private set; }
|
||||
public float ProjectedStability { get; private set; }
|
||||
public float EffectiveStabilityP => maxStability <= 0f
|
||||
? 0f
|
||||
: EffectiveStability / maxStability;
|
||||
public float ProjectedStabilityP => maxStability <= 0f
|
||||
? 0f
|
||||
: ProjectedStability / maxStability;
|
||||
|
||||
private bool _hasProjectedCost;
|
||||
|
||||
public CoreStabilityState State
|
||||
{
|
||||
get
|
||||
{
|
||||
if (EffectiveStability <= 0f)
|
||||
{
|
||||
return CoreStabilityState.Collapsed;
|
||||
}
|
||||
|
||||
var p = EffectiveStabilityP;
|
||||
|
||||
if (p <= criticalThresholdP)
|
||||
{
|
||||
return CoreStabilityState.Critical;
|
||||
}
|
||||
|
||||
if (p <= unstableThresholdP)
|
||||
{
|
||||
return CoreStabilityState.Unstable;
|
||||
}
|
||||
|
||||
return CoreStabilityState.Stable;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsCollapsed => State == CoreStabilityState.Collapsed;
|
||||
|
||||
protected override void WhenInstantiate(CoreStabilityService s)
|
||||
{
|
||||
base.WhenInstantiate(s);
|
||||
ResetCore();
|
||||
}
|
||||
|
||||
public void ResetCore()
|
||||
{
|
||||
EffectiveStability = maxStability;
|
||||
ProjectedStability = maxStability;
|
||||
|
||||
_hasProjectedCost = false;
|
||||
}
|
||||
|
||||
public void ProjectCost(float maxCost)
|
||||
{
|
||||
maxCost = Mathf.Max(0f, maxCost);
|
||||
|
||||
var baseStability = _hasProjectedCost
|
||||
? Mathf.Min(EffectiveStability, ProjectedStability)
|
||||
: EffectiveStability;
|
||||
|
||||
ProjectedStability = Mathf.Clamp(
|
||||
baseStability - maxCost,
|
||||
0f,
|
||||
maxStability
|
||||
);
|
||||
|
||||
_hasProjectedCost = true;
|
||||
}
|
||||
|
||||
public void Settle(CadenceEvaluation evaluation)
|
||||
{
|
||||
var settlementFactor = Mathf.Clamp01(evaluation.SettlementFactor);
|
||||
var recovery = Mathf.Max(0f, evaluation.Recovery);
|
||||
|
||||
EffectiveStability = Mathf.Lerp(
|
||||
EffectiveStability,
|
||||
ProjectedStability,
|
||||
settlementFactor
|
||||
);
|
||||
|
||||
if (recovery > 0f)
|
||||
{
|
||||
EffectiveStability = Mathf.Clamp(
|
||||
EffectiveStability + recovery,
|
||||
0f,
|
||||
maxStability
|
||||
);
|
||||
}
|
||||
|
||||
ProjectedStability = EffectiveStability;
|
||||
_hasProjectedCost = false;
|
||||
}
|
||||
|
||||
public void ApplyDamage(float damage)
|
||||
{
|
||||
damage = Mathf.Max(0f, damage);
|
||||
|
||||
EffectiveStability = Mathf.Clamp(
|
||||
EffectiveStability - damage,
|
||||
0f,
|
||||
maxStability
|
||||
);
|
||||
|
||||
ProjectedStability = Mathf.Min(ProjectedStability, EffectiveStability);
|
||||
}
|
||||
|
||||
public void Recover(float amount)
|
||||
{
|
||||
amount = Mathf.Max(0f, amount);
|
||||
|
||||
EffectiveStability = Mathf.Clamp(
|
||||
EffectiveStability + amount,
|
||||
0f,
|
||||
maxStability
|
||||
);
|
||||
|
||||
if (!_hasProjectedCost)
|
||||
{
|
||||
ProjectedStability = EffectiveStability;
|
||||
}
|
||||
}
|
||||
|
||||
public void RecoverFromCollapse()
|
||||
{
|
||||
EffectiveStability = Mathf.Clamp(
|
||||
collapsedRecoveryStability,
|
||||
0f,
|
||||
maxStability
|
||||
);
|
||||
|
||||
ProjectedStability = EffectiveStability;
|
||||
_hasProjectedCost = false;
|
||||
}
|
||||
|
||||
public void UpdateCore(float deltaTime)
|
||||
{
|
||||
if (deltaTime <= 0f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsCollapsed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RecoverNaturally(deltaTime);
|
||||
|
||||
if (!_hasProjectedCost)
|
||||
{
|
||||
ProjectedStability = EffectiveStability;
|
||||
}
|
||||
}
|
||||
|
||||
private void RecoverNaturally(float deltaTime)
|
||||
{
|
||||
if (EffectiveStability >= maxStability)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EffectiveStability = Mathf.Clamp(
|
||||
EffectiveStability + naturalRecoveryPerSecond * deltaTime,
|
||||
0f,
|
||||
maxStability
|
||||
);
|
||||
}
|
||||
|
||||
private void OnValidate()
|
||||
{
|
||||
maxStability = Mathf.Max(1f, maxStability);
|
||||
|
||||
unstableThresholdP = Mathf.Clamp01(unstableThresholdP);
|
||||
criticalThresholdP = Mathf.Clamp01(criticalThresholdP);
|
||||
|
||||
if (criticalThresholdP > unstableThresholdP)
|
||||
{
|
||||
criticalThresholdP = unstableThresholdP;
|
||||
}
|
||||
|
||||
collapsedRecoveryStability = Mathf.Clamp(
|
||||
collapsedRecoveryStability,
|
||||
0f,
|
||||
maxStability
|
||||
);
|
||||
|
||||
naturalRecoveryPerSecond = Mathf.Max(0f, naturalRecoveryPerSecond);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8cb4003a571646f28d99cec70813327d
|
||||
timeCreated: 1781094387
|
||||
@ -0,0 +1,10 @@
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel.Cadence
|
||||
{
|
||||
public enum CoreStabilityState
|
||||
{
|
||||
Stable,
|
||||
Unstable,
|
||||
Critical,
|
||||
Collapsed,
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5dfa2f80ab9246ad96f7721fbd2316ac
|
||||
timeCreated: 1781094456
|
||||
@ -1,4 +1,6 @@
|
||||
using Intrepid.Gameplay.Entities.Player.Sentinel.Inputs;
|
||||
using Intrepid.Utilities;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
@ -6,84 +8,21 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.Cadence.UI
|
||||
{
|
||||
public class UICadence : MonoBehaviour
|
||||
{
|
||||
[GroupInjections, SerializeField] private Slider slider;
|
||||
[GroupInjections, SerializeField] private RectTransform warmLimit;
|
||||
[GroupInjections, SerializeField] private RectTransform optimal;
|
||||
|
||||
private bool IsActive { get; set; }
|
||||
[GroupInjections, SerializeField] private SentinelControls controls;
|
||||
[GroupInjections, SerializeField] private SentinelInputResolver inputResolver;
|
||||
[GroupInjections, SerializeField] private TextMeshProUGUI cadenceTimer;
|
||||
[GroupInjections, SerializeField] private TextMeshProUGUI btnElapsedTimes;
|
||||
[GroupInjections, SerializeField] private Slider effective;
|
||||
[GroupInjections, SerializeField] private Slider projection;
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (CadenceService.Instance.IsCadenceRunning)
|
||||
{
|
||||
if (!IsActive)
|
||||
{
|
||||
IsActive = true;
|
||||
|
||||
slider.gameObject.SetActive(true);
|
||||
warmLimit.gameObject.SetActive(true);
|
||||
optimal.gameObject.SetActive(true);
|
||||
|
||||
SetHorizontalRange(
|
||||
optimal,
|
||||
CadenceService.Instance.OptimalCadenceMinPercent,
|
||||
CadenceService.Instance.OptimalCadenceMaxPercent
|
||||
);
|
||||
|
||||
SetVerticalLine(
|
||||
warmLimit,
|
||||
CadenceService.Instance.WarmCadencePercent
|
||||
);
|
||||
}
|
||||
|
||||
slider.value = CadenceService.Instance.CurrentCadence;
|
||||
return;
|
||||
}
|
||||
|
||||
IsActive = false;
|
||||
|
||||
slider.value = 0f;
|
||||
slider.gameObject.SetActive(false);
|
||||
warmLimit.gameObject.SetActive(false);
|
||||
optimal.gameObject.SetActive(false);
|
||||
}
|
||||
|
||||
private static void SetHorizontalRange(
|
||||
RectTransform rect,
|
||||
float minPercent,
|
||||
float maxPercent,
|
||||
float height = 10f
|
||||
)
|
||||
{
|
||||
minPercent = Mathf.Clamp01(minPercent);
|
||||
maxPercent = Mathf.Clamp01(maxPercent);
|
||||
|
||||
if (maxPercent < minPercent)
|
||||
{
|
||||
(minPercent, maxPercent) = (maxPercent, minPercent);
|
||||
}
|
||||
|
||||
rect.anchorMin = new Vector2(minPercent, 0.5f);
|
||||
rect.anchorMax = new Vector2(maxPercent, 0.5f);
|
||||
rect.pivot = new Vector2(0.5f, 0.5f);
|
||||
|
||||
rect.offsetMin = new Vector2(0f, -height * 0.5f);
|
||||
rect.offsetMax = new Vector2(0f, height * 0.5f);
|
||||
|
||||
rect.anchoredPosition = Vector2.zero;
|
||||
}
|
||||
|
||||
private static void SetVerticalLine(RectTransform rect, float percent)
|
||||
{
|
||||
percent = Mathf.Clamp01(percent);
|
||||
|
||||
rect.anchorMin = new Vector2(percent, 0f);
|
||||
rect.anchorMax = new Vector2(percent, 1f);
|
||||
|
||||
rect.anchoredPosition = Vector2.zero;
|
||||
|
||||
rect.offsetMin = new Vector2(rect.offsetMin.x, 0f);
|
||||
rect.offsetMax = new Vector2(rect.offsetMax.x, 0f);
|
||||
cadenceTimer.text = CadenceService.Instance.IsCadenceRunning
|
||||
? CadenceService.Instance.CadenceElapsedTime.ToString("F2")
|
||||
: "--";
|
||||
btnElapsedTimes.text = controls.CadenceConnectedCounter.ToString();
|
||||
effective.value = CoreStabilityService.Instance.EffectiveStabilityP;
|
||||
projection.value = CoreStabilityService.Instance.ProjectedStabilityP;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1209b3e567948f5ad282f1f2028f91d
|
||||
timeCreated: 1781108166
|
||||
@ -0,0 +1,36 @@
|
||||
using System;
|
||||
using Intrepid.Integration.Input;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel.Inputs
|
||||
{
|
||||
public class SentinelInputActions : SentinelInputs
|
||||
{
|
||||
public Func<bool> Dash { get; set; }
|
||||
|
||||
public Func<Vector2> Movement { get; set; }
|
||||
public Func<bool> Interact { get; set; }
|
||||
public Func<bool> DPadLeft { get; set; }
|
||||
public Func<bool> DPadRight { get; set; }
|
||||
public Func<bool> Reset { get; set; }
|
||||
|
||||
public static SentinelInputActions BuildSentinelInputActions()
|
||||
{
|
||||
var locking = InputService.Instance.Locking;
|
||||
var inputActions = InputService.Instance.InputActions.sentinel;
|
||||
return new SentinelInputActions
|
||||
{
|
||||
Movement = () => locking.IsNotLocked
|
||||
? inputActions.Movement.ReadValue<Vector2>()
|
||||
: Vector2.zero,
|
||||
Interact = () => locking.IsNotLocked && inputActions.Interact.WasPressedThisFrame(),
|
||||
DPadLeft = () => locking.IsNotLocked && inputActions.DPadLeft.WasPressedThisFrame(),
|
||||
DPadRight = () => locking.IsNotLocked && inputActions.DPadRight.WasPressedThisFrame(),
|
||||
Dash = () => locking.IsNotLocked && inputActions.Dash.WasPressedThisFrame(),
|
||||
|
||||
// debug
|
||||
Reset = () => locking.IsNotLocked && inputActions.Reset.WasPressedThisFrame(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d2d27d34559344689042676574451a32
|
||||
timeCreated: 1781114588
|
||||
@ -0,0 +1,92 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel.Inputs
|
||||
{
|
||||
internal enum SentinelBufferedActionType
|
||||
{
|
||||
None,
|
||||
Dash,
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[CreateAssetMenu(fileName = "Sentinel Input Resolver", menuName = "GON/Services/Sentinel/Input Resolver")]
|
||||
public sealed class SentinelInputResolver : SingletonScriptableObject<SentinelInputResolver>, SentinelInputs
|
||||
{
|
||||
[GroupConfigurations, SerializeField, Range(0, 5)] private float inputLifespan = .35f;
|
||||
|
||||
private Dictionary<SentinelBufferedActionType, float> IntentBuffer { get; set; }
|
||||
private SentinelInputActions InputActions { get; set; }
|
||||
|
||||
protected override void WhenInstantiate(SentinelInputResolver singleton)
|
||||
{
|
||||
base.WhenInstantiate(singleton);
|
||||
IntentBuffer = new Dictionary<SentinelBufferedActionType, float>();
|
||||
InputActions = SentinelInputActions.BuildSentinelInputActions();
|
||||
}
|
||||
|
||||
public void CaptureAndPrune(float elapsedTime)
|
||||
{
|
||||
IntentBuffer.RemoveAll((_, at) => elapsedTime - at > inputLifespan);
|
||||
if (InputActions.Dash())
|
||||
{
|
||||
IntentBuffer.TryAdd(SentinelBufferedActionType.Dash, elapsedTime);
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
InnerClear();
|
||||
}
|
||||
|
||||
public void ClearDash()
|
||||
{
|
||||
InnerClear(SentinelBufferedActionType.Dash);
|
||||
}
|
||||
|
||||
private void InnerClear(SentinelBufferedActionType bufferedActionType = SentinelBufferedActionType.None)
|
||||
{
|
||||
if (bufferedActionType == SentinelBufferedActionType.None)
|
||||
{
|
||||
IntentBuffer.Clear();
|
||||
return;
|
||||
}
|
||||
IntentBuffer.Remove(bufferedActionType);
|
||||
}
|
||||
|
||||
private bool TryPeek(SentinelBufferedActionType bufferedActionType, out float actionTypeTimeAt)
|
||||
{
|
||||
if (IntentBuffer.TryGetValue(bufferedActionType, out actionTypeTimeAt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
actionTypeTimeAt = 0f;
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool TryConsume(SentinelBufferedActionType bufferedActionType, out float actionTypeTimeAt)
|
||||
{
|
||||
if (!TryPeek(bufferedActionType, out actionTypeTimeAt))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
IntentBuffer.Remove(bufferedActionType);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Buffered Input Actions
|
||||
public bool TryPeekDash(out float dashTimeAt) => TryPeek(SentinelBufferedActionType.Dash, out dashTimeAt);
|
||||
public bool TryConsumeDash(out float dashTimeAt) => TryConsume(SentinelBufferedActionType.Dash, out dashTimeAt);
|
||||
|
||||
// No Buffered Input Actions
|
||||
public Func<Vector2> Movement => InputActions.Movement;
|
||||
public Func<bool> Interact => InputActions.Interact;
|
||||
public Func<bool> DPadLeft => InputActions.DPadLeft;
|
||||
public Func<bool> DPadRight => InputActions.DPadRight;
|
||||
public Func<bool> Reset => InputActions.Reset;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4042f157f2bd47e3938657e1c2fca5b0
|
||||
timeCreated: 1781111024
|
||||
@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel.Inputs
|
||||
{
|
||||
public interface SentinelInputs
|
||||
{
|
||||
Func<Vector2> Movement { get; }
|
||||
Func<bool> Interact { get; }
|
||||
Func<bool> DPadLeft { get; }
|
||||
Func<bool> DPadRight { get; }
|
||||
|
||||
// debug
|
||||
public Func<bool> Reset { get; }
|
||||
}
|
||||
}
|
||||
@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using Intrepid.Core.Entities;
|
||||
using Intrepid.Core.Entities.Messages;
|
||||
using Intrepid.Core.TimeControl;
|
||||
using Intrepid.Diagnostics;
|
||||
using Intrepid.Gameplay.Entities.Player.ActionBelt;
|
||||
using Intrepid.Gameplay.Entities.Player.Sentinel.Cadence;
|
||||
using Intrepid.Gameplay.Entities.Player.Sentinel.Inputs;
|
||||
using Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine;
|
||||
using Intrepid.Integration.Input;
|
||||
using Intrepid.Structures;
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
@ -13,20 +15,24 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel
|
||||
{
|
||||
public class SentinelBrain : EntityBrain
|
||||
{
|
||||
[GroupInjections, SerializeField] private ActionBeltManager actionBeltManager;
|
||||
[GroupInjections, SerializeField] private SentinelInputResolver inputResolver;
|
||||
[GroupInjections, SerializeField] private SentinelControls controls;
|
||||
[GroupInjections, SerializeField] private ActionBeltManager actionBeltManager;
|
||||
[GroupInjections, SerializeField] private Cadences cadences;
|
||||
|
||||
private bool StateFirstFrame { get; set; }
|
||||
protected SentinelStateMachine StateMachine { get; private set; }
|
||||
|
||||
|
||||
public SentinelEntity Entity => RootEntity as SentinelEntity;
|
||||
public SentinelInputs Inputs { get; private set; }
|
||||
public SentinelStateType CurrentState => StateMachine.CurrentImplementation.GetStateKey();
|
||||
public ActionBeltManager ActionBeltManager => actionBeltManager;
|
||||
public SentinelInputResolver InputResolver => inputResolver;
|
||||
public SentinelControls Controls => controls;
|
||||
|
||||
public ActionBeltManager ActionBeltManager => actionBeltManager;
|
||||
public Cadences Cadences => cadences;
|
||||
public static bool IsCoreStable => !CoreStabilityService.Instance.IsCollapsed;
|
||||
|
||||
protected override void InitializeVariables()
|
||||
{
|
||||
Inputs = InputService.Instance.BuildSentinelInputs();
|
||||
StateMachine = GetComponentInChildren<SentinelStateMachine>();
|
||||
foreach (var sentinelState in GetComponentsInChildren<SentinelState>())
|
||||
{
|
||||
@ -37,6 +43,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel
|
||||
protected override void OnBootstrap()
|
||||
{
|
||||
StateMachine.StartMachine();
|
||||
ResetBrain();
|
||||
}
|
||||
|
||||
protected override void Subscriptions()
|
||||
@ -53,23 +60,59 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel
|
||||
StateMachine.ChangeState(SentinelStateType.Fall);
|
||||
});
|
||||
}
|
||||
|
||||
public void ResetBrain()
|
||||
{
|
||||
}
|
||||
|
||||
public override void UpdateFromUpdatable()
|
||||
{
|
||||
CadenceService.Instance.UpdateCadence();
|
||||
{
|
||||
StateMachine.UpdateStateMachine();
|
||||
|
||||
InputResolver.CaptureAndPrune(TimeSimulation.Instance.ScaledElapsedTime);
|
||||
|
||||
// that is the right place?
|
||||
if (Controls.OnCadence)
|
||||
{
|
||||
TimeSimulation.Instance.AsBreathMotion(.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
TimeSimulation.Instance.AsNormalMotion(.5f);
|
||||
}
|
||||
|
||||
if (StateFirstFrame)
|
||||
{
|
||||
StateMachine.CurrentImplementation.RunOnFirstFrameOnly();
|
||||
StateFirstFrame = false;
|
||||
}
|
||||
StateMachine.CurrentImplementation.RunBeforeUpdate();
|
||||
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);
|
||||
}
|
||||
|
||||
CoreStabilityService.Instance.UpdateCore(Timer.ScaledTime);
|
||||
|
||||
// state machine could take this responsibility in the future...
|
||||
if (Inputs.Reset())
|
||||
if (InputResolver.Reset())
|
||||
{
|
||||
Entity.ResetLastSafeGroundPosition();
|
||||
StateMachine.ChangeState(SentinelStateType.FallLanding);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void LateUpdateFromUpdatable()
|
||||
{
|
||||
StateMachine.CurrentImplementation.RunOnLateUpdate();
|
||||
@ -82,7 +125,10 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel
|
||||
|
||||
public void ChangeState(SentinelStateType stateType, params Parameter[] ps)
|
||||
{
|
||||
StateMachine.ChangeState(stateType, ps);
|
||||
if (StateMachine.ChangeState(stateType, ps))
|
||||
{
|
||||
StateFirstFrame = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,22 +1,31 @@
|
||||
using Intrepid.Gameplay.Entities.Player.Sentinel.Cadence;
|
||||
using System;
|
||||
using Intrepid.Utilities;
|
||||
using Sirenix.OdinInspector;
|
||||
using Unity.Collections;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel
|
||||
{
|
||||
public class SentinelControls : MonoBehaviour
|
||||
[Serializable]
|
||||
[CreateAssetMenu(fileName = "Sentinel Controls", menuName = "GON/Services/Sentinel/Sentinel Controls")]
|
||||
public class SentinelControls : ScriptableObject
|
||||
{
|
||||
[GroupConfigurations("Dash Context"), SerializeField, HideLabel] private CadenceContext dashContext;
|
||||
[GroupConfigurations, SerializeField, Range(0, 5)] private int dashBreakingThreshold = 3;
|
||||
[GroupConfigurations, SerializeField, Range(0, 10)] private int cadenceConnectedThreshold = 3;
|
||||
[GroupDebug, SerializeField, ReadOnly] private int cadenceConnectedCounter;
|
||||
[GroupDebug, SerializeField, ReadOnly] private int dashCounter;
|
||||
|
||||
[GroupConfigurations, SerializeField, Range(0, 3)] private int dashBreakingThreshold = 2;
|
||||
[GroupDebug, SerializeField] private int dashCounter;
|
||||
|
||||
public CadenceContext DashContext => dashContext;
|
||||
|
||||
public int DashCounter => dashCounter;
|
||||
public bool IsDashing => dashCounter > 0;
|
||||
|
||||
public int CadenceConnectedCounter => cadenceConnectedCounter;
|
||||
public bool ShouldDashBreak => DashCounter >= dashBreakingThreshold;
|
||||
public bool OnCadence => CadenceConnectedCounter > cadenceConnectedThreshold;
|
||||
public bool IsDashing => DashCounter > 0;
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
ResetDash();
|
||||
ExpireCadence();
|
||||
}
|
||||
|
||||
public void DashCounterInc()
|
||||
{
|
||||
dashCounter++;
|
||||
@ -26,10 +35,15 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel
|
||||
{
|
||||
dashCounter = 0;
|
||||
}
|
||||
|
||||
public bool DashShouldBreak()
|
||||
|
||||
public void CadenceConnectedCounterInc()
|
||||
{
|
||||
return DashCounter >= dashBreakingThreshold;
|
||||
cadenceConnectedCounter++;
|
||||
}
|
||||
|
||||
public void ExpireCadence()
|
||||
{
|
||||
cadenceConnectedCounter = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -32,6 +32,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel
|
||||
|
||||
public override void DeployEntity(Vector2 position)
|
||||
{
|
||||
Brain.ResetBrain();
|
||||
RefreshMovementNormal();
|
||||
}
|
||||
|
||||
|
||||
@ -1,17 +0,0 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel
|
||||
{
|
||||
public class SentinelInputs
|
||||
{
|
||||
public Func<Vector2> Movement { get; set; }
|
||||
public Func<bool> Interact { get; set; }
|
||||
public Func<bool> DPadLeft { get; set; }
|
||||
public Func<bool> DPadRight { get; set; }
|
||||
public Func<bool> Dash { get; set; }
|
||||
|
||||
// debug
|
||||
public Func<bool> Reset { get; set; }
|
||||
}
|
||||
}
|
||||
@ -10,9 +10,10 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel
|
||||
|
||||
Run = 30,
|
||||
|
||||
Dash = 40,
|
||||
DashWindow = 41,
|
||||
DashBreaking = 42,
|
||||
DashImpulse = 40,
|
||||
DashRecovery = 41,
|
||||
DashLanding = 42,
|
||||
DashBreaking = 43,
|
||||
|
||||
Knockdown = 80,
|
||||
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
using Intrepid.Core.Entities;
|
||||
using Intrepid.Core.TimeControl;
|
||||
using Intrepid.Diagnostics;
|
||||
using Intrepid.GameManagers;
|
||||
using Intrepid.Gameplay.Entities.Player.ActionBelt.Events;
|
||||
using Intrepid.Gameplay.Entities.Player.Sentinel.Cadence;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine
|
||||
{
|
||||
@ -15,6 +18,10 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
public virtual void RunOnFirstFrameOnly()
|
||||
{
|
||||
}
|
||||
|
||||
public abstract void RunOnUpdate();
|
||||
|
||||
@ -38,7 +45,7 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine
|
||||
{
|
||||
if (!Brain.ActionBeltManager.IsOperational) return;
|
||||
if (Brain.ActionBeltManager.IsEmpty) return;
|
||||
if (Brain.Inputs.Interact())
|
||||
if (Brain.InputResolver.Interact())
|
||||
{
|
||||
Proxy.Instance.EventBus.Raise(new ActionBeltTakeActionEvent
|
||||
{
|
||||
@ -47,8 +54,8 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine
|
||||
return;
|
||||
}
|
||||
|
||||
var left = Brain.Inputs.DPadLeft();
|
||||
var right = Brain.Inputs.DPadRight();
|
||||
var left = Brain.InputResolver.DPadLeft();
|
||||
var right = Brain.InputResolver.DPadRight();
|
||||
|
||||
if (left && right) return;
|
||||
if (left)
|
||||
@ -66,5 +73,51 @@ 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)
|
||||
{
|
||||
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}"
|
||||
// );
|
||||
|
||||
Brain.Controls.CadenceConnectedCounterInc();
|
||||
CoreStabilityService.Instance.Settle(previousEvaluation);
|
||||
}
|
||||
else
|
||||
{
|
||||
Brain.Controls.ExpireCadence();
|
||||
}
|
||||
|
||||
CoreStabilityService.Instance.ProjectCost(profile.MaxCoreCost);
|
||||
CadenceService.Instance.BeginCadence(profile, TimeSimulation.Instance.ScaledElapsedTime);
|
||||
}
|
||||
|
||||
protected bool TryConsumeDash()
|
||||
{
|
||||
if (Brain.InputResolver.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);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,3 @@
|
||||
using Intrepid.Gameplay.Entities.Player.Sentinel.Cadence;
|
||||
using Intrepid.Gameplay.Messages.Events;
|
||||
using Intrepid.Structures;
|
||||
using Intrepid.Utilities;
|
||||
@ -6,19 +5,21 @@ using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
|
||||
{
|
||||
public class SentinelStateDash : SentinelState
|
||||
public class SentinelStateDashImpulse : SentinelState
|
||||
{
|
||||
[GroupConfigurations, SerializeField] private AnimationClip dash;
|
||||
[GroupConfigurations, SerializeField, Range(0, 100)] private float speed = 35;
|
||||
// [GroupConfigurations, SerializeField, Range(0, 500)] private float targetTimeMS = 100f;
|
||||
[GroupConfigurations, SerializeField, Range(0, 5000)] private float targetTimeMS = 100f;
|
||||
|
||||
public float TargetTime => Brain.Controls.DashContext.WarmTime;
|
||||
|
||||
private Timer Timer { get; } = new();
|
||||
public float TargetTime => targetTimeMS * 0.001f;
|
||||
|
||||
private Timer Timer { get; } = new();
|
||||
|
||||
public override bool CanEnterState => SentinelBrain.IsCoreStable;
|
||||
|
||||
public override SentinelStateType GetStateKey()
|
||||
{
|
||||
return SentinelStateType.Dash;
|
||||
return SentinelStateType.DashImpulse;
|
||||
}
|
||||
|
||||
protected override void Subscriptions()
|
||||
@ -34,30 +35,32 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
|
||||
{
|
||||
Brain.Controls.DashCounterInc();
|
||||
Brain.Entity.RefreshMovementNormal();
|
||||
Brain.Entity.ModelAnimation.CrossFade(dash, 0.01f);
|
||||
Timer.Start();
|
||||
CadenceService.Instance.StartCadence(Brain.Controls.DashContext);
|
||||
Brain.Entity.ModelAnimation.CrossFade(dash, 0.05f);
|
||||
}
|
||||
|
||||
protected override void RunOnExit()
|
||||
{
|
||||
Timer.Stop();
|
||||
}
|
||||
|
||||
public override void RunOnFirstFrameOnly()
|
||||
{
|
||||
Timer.Start();
|
||||
}
|
||||
|
||||
public override void RunOnUpdate()
|
||||
{
|
||||
if (Timer.IsNotRunning)
|
||||
{
|
||||
Brain.ChangeState(SentinelStateType.DashWindow);
|
||||
return;
|
||||
}
|
||||
Timer.Update(Time.deltaTime);
|
||||
if (Timer.Check(TargetTime))
|
||||
|
||||
Brain.Entity.DesiredVelocity = Brain.Entity.Forward * speed;
|
||||
|
||||
if (!Timer.Check(TargetTime))
|
||||
{
|
||||
Timer.Stop();
|
||||
return;
|
||||
}
|
||||
Brain.Entity.DesiredVelocity = Brain.Entity.Forward * speed;
|
||||
|
||||
Timer.Stop();
|
||||
Brain.ChangeState(SentinelStateType.DashRecovery);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
using Intrepid.Structures;
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
|
||||
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()
|
||||
{
|
||||
return SentinelStateType.DashLanding;
|
||||
}
|
||||
|
||||
protected override void Subscriptions()
|
||||
{
|
||||
}
|
||||
|
||||
protected override void RunOnEnter(ParameterStore parameterStore)
|
||||
{
|
||||
Brain.Controls.ResetDash();
|
||||
Brain.Entity.DesiredVelocity = Vector2.zero;
|
||||
Brain.Entity.ModelAnimation.CrossFade(dashLanding, .1f);
|
||||
Timer.Start();
|
||||
}
|
||||
|
||||
protected override void RunOnExit()
|
||||
{
|
||||
Timer.Stop();
|
||||
Brain.InputResolver.Clear();
|
||||
}
|
||||
|
||||
public override void RunOnUpdate()
|
||||
{
|
||||
if (Timer.IsNotRunning) return;
|
||||
Timer.Update(Timer.ScaledTime);
|
||||
if (Timer.Check(LandingTime))
|
||||
{
|
||||
Timer.Stop();
|
||||
Brain.ChangeState(SentinelStateType.Idle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: daca982531174c5e82acb0a9312913b1
|
||||
timeCreated: 1781164678
|
||||
@ -4,19 +4,20 @@ using UnityEngine;
|
||||
|
||||
namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
|
||||
{
|
||||
public class SentinelStateDashWindow : SentinelState
|
||||
public class SentinelStateDashRecovery : SentinelState
|
||||
{
|
||||
[GroupConfigurations, SerializeField] private AnimationClip dashWindow;
|
||||
[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, 500)] private float targetTimeMS = 150f;
|
||||
[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();
|
||||
private float TargetTime => Brain.Controls.DashContext.ActivationTime;
|
||||
|
||||
public override SentinelStateType GetStateKey()
|
||||
{
|
||||
return SentinelStateType.DashWindow;
|
||||
return SentinelStateType.DashRecovery;
|
||||
}
|
||||
|
||||
protected override void Subscriptions()
|
||||
@ -25,30 +26,38 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
|
||||
|
||||
protected override void RunOnEnter(ParameterStore parameterStore)
|
||||
{
|
||||
Brain.Entity.ModelAnimation.Play(dashWindow);
|
||||
Timer.Start();
|
||||
Brain.Entity.ModelAnimation.CrossFade(dashRecovery, 0.05f);
|
||||
}
|
||||
|
||||
protected override void RunOnExit()
|
||||
{
|
||||
Timer.Stop();
|
||||
var movement = Brain.Inputs.Movement();
|
||||
var forward = Brain.Entity.Forward;
|
||||
var direction = GonFunctions
|
||||
.ConstrainDirectionToForwardCone(movement, forward, dashMaxAngleFromForward);
|
||||
Brain.Entity.ChangeOrientation(direction);
|
||||
}
|
||||
|
||||
|
||||
public override void RunOnFirstFrameOnly()
|
||||
{
|
||||
Timer.Start();
|
||||
}
|
||||
|
||||
public override void RunOnUpdate()
|
||||
{
|
||||
if (CheckDash()) return;
|
||||
if (Timer.IsNotRunning)
|
||||
{
|
||||
if (TryConsumeDash())
|
||||
{
|
||||
Brain.ChangeState(SentinelStateType.DashImpulse);
|
||||
var movement = Brain.InputResolver.Movement();
|
||||
var forward = Brain.Entity.Forward;
|
||||
var direction = GonFunctions
|
||||
.ConstrainDirectionToForwardCone(movement, forward, dashMaxAngleFromForward);
|
||||
Brain.Entity.ChangeOrientation(direction);
|
||||
return;
|
||||
}
|
||||
if (Brain.Entity.IsGrounded)
|
||||
{
|
||||
Brain.ChangeState(Brain.Controls.DashShouldBreak()
|
||||
Brain.ChangeState(Brain.Controls.ShouldDashBreak
|
||||
? SentinelStateType.DashBreaking
|
||||
: SentinelStateType.Idle);
|
||||
: SentinelStateType.DashLanding);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -62,24 +71,9 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
|
||||
Timer.Stop();
|
||||
return;
|
||||
}
|
||||
Brain.Entity.DesiredVelocity = Brain.Entity.Forward * speed;
|
||||
|
||||
var speedFactor = 1f + speedCurve.Evaluate((float)Timer.ElapsedTime / TargetTime);
|
||||
Brain.Entity.DesiredVelocity = Brain.Entity.Forward * (speed * speedFactor);
|
||||
}
|
||||
|
||||
private bool CheckDash()
|
||||
{
|
||||
// this could be a feature to be unlocked
|
||||
// if (Brain.Inputs.Dash())
|
||||
if (Brain.Entity.IsGrounded && Brain.Inputs.Dash())
|
||||
{
|
||||
Brain.ChangeState(SentinelStateType.Dash);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,3 @@
|
||||
using Intrepid.GameManagers;
|
||||
using Intrepid.Gameplay.Entities.Player.ActionBelt.Events;
|
||||
using Intrepid.Structures;
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
@ -31,20 +29,14 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
|
||||
|
||||
public override void RunOnUpdate()
|
||||
{
|
||||
Movement = Brain.Inputs.Movement();
|
||||
Movement = Brain.InputResolver.Movement();
|
||||
VerifyInteraction();
|
||||
if (CheckDash()) return;
|
||||
if (CheckMovement()) return;
|
||||
}
|
||||
|
||||
private bool CheckDash()
|
||||
{
|
||||
if (Brain.Inputs.Dash())
|
||||
if (TryConsumeDash())
|
||||
{
|
||||
Brain.ChangeState(SentinelStateType.Dash);
|
||||
return true;
|
||||
Brain.ChangeState(SentinelStateType.DashImpulse);
|
||||
return;
|
||||
}
|
||||
return false;
|
||||
if (CheckMovement()) return;
|
||||
}
|
||||
|
||||
private bool CheckMovement()
|
||||
|
||||
@ -33,24 +33,18 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
|
||||
|
||||
public override void RunOnUpdate()
|
||||
{
|
||||
Movement = Brain.Inputs.Movement();
|
||||
Movement = Brain.InputResolver.Movement();
|
||||
Brain.Entity.ChangeOrientation(Movement);
|
||||
VerifyInteraction();
|
||||
if (CheckDash()) return;
|
||||
if (TryConsumeDash())
|
||||
{
|
||||
Brain.ChangeState(SentinelStateType.DashImpulse);
|
||||
return;
|
||||
}
|
||||
if (CheckMovement()) return;
|
||||
Brain.Entity.DesiredVelocity = Movement * speed;
|
||||
}
|
||||
|
||||
private bool CheckDash()
|
||||
{
|
||||
if (Brain.Inputs.Dash())
|
||||
{
|
||||
Brain.ChangeState(SentinelStateType.Dash);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CheckMovement()
|
||||
{
|
||||
switch (Movement.sqrMagnitude)
|
||||
|
||||
@ -33,24 +33,18 @@ namespace Intrepid.Gameplay.Entities.Player.Sentinel.StateMachine.States
|
||||
|
||||
public override void RunOnUpdate()
|
||||
{
|
||||
Movement = Brain.Inputs.Movement();
|
||||
Movement = Brain.InputResolver.Movement();
|
||||
Brain.Entity.ChangeOrientation(Movement);
|
||||
VerifyInteraction();
|
||||
if (CheckDash()) return;
|
||||
if (TryConsumeDash())
|
||||
{
|
||||
Brain.ChangeState(SentinelStateType.DashImpulse);
|
||||
return;
|
||||
}
|
||||
if (CheckMovement()) return;
|
||||
Brain.Entity.DesiredVelocity = Movement * speed;
|
||||
}
|
||||
|
||||
private bool CheckDash()
|
||||
{
|
||||
if (Brain.Inputs.Dash())
|
||||
{
|
||||
Brain.ChangeState(SentinelStateType.Dash);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private bool CheckMovement()
|
||||
{
|
||||
switch (Movement.sqrMagnitude)
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
using Intrepid.Diagnostics;
|
||||
using Intrepid.Gameplay.Entities.Player.Sentinel;
|
||||
using Intrepid.Gameplay.Entities.Player.Sentinel.Inputs;
|
||||
using Intrepid.Utilities;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
@ -9,7 +9,7 @@ namespace Intrepid.Integration.Input
|
||||
[CreateAssetMenu(fileName = "Input Action Service", menuName = "GON/Input Actions Service")]
|
||||
public class InputService : SingletonScriptableObject<InputService>
|
||||
{
|
||||
private InputActions InputActions { get; set; }
|
||||
public InputActions InputActions { get; private set; }
|
||||
public InputSchema CurrentInputSchema { get; private set; }
|
||||
public InputLocking Locking { get; private set; }
|
||||
|
||||
@ -54,21 +54,5 @@ namespace Intrepid.Integration.Input
|
||||
}
|
||||
}
|
||||
|
||||
public SentinelInputs BuildSentinelInputs()
|
||||
{
|
||||
return new SentinelInputs
|
||||
{
|
||||
Movement = () => Locking.IsNotLocked
|
||||
? InputActions.sentinel.Movement.ReadValue<Vector2>()
|
||||
: Vector2.zero,
|
||||
Interact = () => Locking.IsNotLocked && InputActions.sentinel.Interact.WasPressedThisFrame(),
|
||||
DPadLeft = () => Locking.IsNotLocked && InputActions.sentinel.DPadLeft.WasPressedThisFrame(),
|
||||
DPadRight = () => Locking.IsNotLocked && InputActions.sentinel.DPadRight.WasPressedThisFrame(),
|
||||
Dash = () => Locking.IsNotLocked && InputActions.sentinel.Dash.WasPressedThisFrame(),
|
||||
|
||||
// debug
|
||||
Reset = () => Locking.IsNotLocked && InputActions.sentinel.Reset.WasPressedThisFrame(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,8 @@ namespace Intrepid.Utilities
|
||||
{
|
||||
public const int ALAP = 10000; // As Last As Possible
|
||||
public const int ASAP = -ALAP; // As Soon As Possible
|
||||
public const int TimeSimulation = ASAP + 1; // Time Simulation updates first
|
||||
public const int UpdatableManager = TimeSimulation + 1; // Updatables updates later
|
||||
}
|
||||
|
||||
public static class Prototyping
|
||||
|
||||
@ -2,7 +2,7 @@ using UnityEngine;
|
||||
|
||||
namespace Intrepid.Utilities.Updatable
|
||||
{
|
||||
[DefaultExecutionOrder(GonConstants.ExecutionOrder.ASAP)]
|
||||
[DefaultExecutionOrder(GonConstants.ExecutionOrder.UpdatableManager)]
|
||||
public class UpdatableManager : MonoBehaviour
|
||||
{
|
||||
private void FixedUpdate()
|
||||
|
||||
@ -3,7 +3,12 @@
|
||||
--- !u!5 &1
|
||||
TimeManager:
|
||||
m_ObjectHideFlags: 0
|
||||
Fixed Timestep: 0.02
|
||||
serializedVersion: 2
|
||||
Fixed Timestep:
|
||||
m_Count: 2822399
|
||||
m_Rate:
|
||||
m_Denominator: 1
|
||||
m_Numerator: 141120000
|
||||
Maximum Allowed Timestep: 0.33333334
|
||||
m_TimeScale: 1
|
||||
Maximum Particle Timestep: 0.03
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user