Compare commits
2 Commits
83188b1fa1
...
4e9c33778c
| Author | SHA1 | Date | |
|---|---|---|---|
| 4e9c33778c | |||
| 48737b60c9 |
@ -14,7 +14,10 @@
|
|||||||
"Bash(python \"Tools\\\\analyze_antirecoil.py\" \"E:\\\\ASTERION\\\\SVN\\\\DEV\\\\PROSERVE_UE_5_5\\\\Saved\\\\Logs\\\\AntiRecoil_20260316_153607.csv\")",
|
"Bash(python \"Tools\\\\analyze_antirecoil.py\" \"E:\\\\ASTERION\\\\SVN\\\\DEV\\\\PROSERVE_UE_5_5\\\\Saved\\\\Logs\\\\AntiRecoil_20260316_153607.csv\")",
|
||||||
"Bash(python \"Tools\\\\analyze_antirecoil.py\" \"E:\\\\ASTERION\\\\SVN\\\\DEV\\\\PROSERVE_UE_5_5\\\\Saved\\\\Logs\\\\AntiRecoil_20260316_160323.csv\")",
|
"Bash(python \"Tools\\\\analyze_antirecoil.py\" \"E:\\\\ASTERION\\\\SVN\\\\DEV\\\\PROSERVE_UE_5_5\\\\Saved\\\\Logs\\\\AntiRecoil_20260316_160323.csv\")",
|
||||||
"Bash(python \"Tools\\\\analyze_antirecoil.py\" \"E:\\\\ASTERION\\\\SVN\\\\DEV\\\\PROSERVE_UE_5_5\\\\Saved\\\\Logs\\\\AntiRecoil_20260316_164341.csv\")",
|
"Bash(python \"Tools\\\\analyze_antirecoil.py\" \"E:\\\\ASTERION\\\\SVN\\\\DEV\\\\PROSERVE_UE_5_5\\\\Saved\\\\Logs\\\\AntiRecoil_20260316_164341.csv\")",
|
||||||
"Bash(python \"Tools\\\\analyze_antirecoil.py\" \"E:\\\\ASTERION\\\\SVN\\\\DEV\\\\PROSERVE_UE_5_5\\\\Saved\\\\Logs\\\\AntiRecoil_20260316_170543.csv\")"
|
"Bash(python \"Tools\\\\analyze_antirecoil.py\" \"E:\\\\ASTERION\\\\SVN\\\\DEV\\\\PROSERVE_UE_5_5\\\\Saved\\\\Logs\\\\AntiRecoil_20260316_170543.csv\")",
|
||||||
|
"Bash(find C:ASTERIONSVNDEVPROSERVE_UE_5_5Plugins -type f \\\\\\(-name *.cpp -o -name *.h \\\\\\))",
|
||||||
|
"Bash(git add:*)",
|
||||||
|
"Bash(git commit:*)"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -92,8 +92,9 @@ void UEBBarrel::UpdateTransformHistory()
|
|||||||
|
|
||||||
TransformHistory.Add(Sample);
|
TransformHistory.Add(Sample);
|
||||||
|
|
||||||
// Trim buffer: remove samples older than AntiRecoilBufferTime
|
// Trim buffer: remove samples older than AntiRecoilBufferTimeMs
|
||||||
// During calibration, keep a larger buffer (0.5s min) for reliable 3-sigma analysis
|
// During calibration, keep a larger buffer (0.5s min) for reliable 3-sigma analysis
|
||||||
|
const float AntiRecoilBufferTime = AntiRecoilBufferTimeMs / 1000.0f;
|
||||||
float EffectiveBufferTime = CalibrateAntiRecoil
|
float EffectiveBufferTime = CalibrateAntiRecoil
|
||||||
? FMath::Max(AntiRecoilBufferTime, 0.5f)
|
? FMath::Max(AntiRecoilBufferTime, 0.5f)
|
||||||
: AntiRecoilBufferTime;
|
: AntiRecoilBufferTime;
|
||||||
@ -128,7 +129,7 @@ void UEBBarrel::ComputeAntiRecoilTransform()
|
|||||||
|
|
||||||
case EAntiRecoilMode::ARM_LinearExtrapolation:
|
case EAntiRecoilMode::ARM_LinearExtrapolation:
|
||||||
{
|
{
|
||||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||||
if (SafeN >= 2)
|
if (SafeN >= 2)
|
||||||
{
|
{
|
||||||
PredictLinearExtrapolation(GetWorld()->GetTimeSeconds(), Location, Aim);
|
PredictLinearExtrapolation(GetWorld()->GetTimeSeconds(), Location, Aim);
|
||||||
@ -148,7 +149,7 @@ void UEBBarrel::ComputeAntiRecoilTransform()
|
|||||||
|
|
||||||
case EAntiRecoilMode::ARM_WeightedRegression:
|
case EAntiRecoilMode::ARM_WeightedRegression:
|
||||||
{
|
{
|
||||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||||
if (SafeN >= 2)
|
if (SafeN >= 2)
|
||||||
{
|
{
|
||||||
PredictWeightedRegression(GetWorld()->GetTimeSeconds(), Location, Aim);
|
PredictWeightedRegression(GetWorld()->GetTimeSeconds(), Location, Aim);
|
||||||
@ -168,7 +169,7 @@ void UEBBarrel::ComputeAntiRecoilTransform()
|
|||||||
|
|
||||||
case EAntiRecoilMode::ARM_WeightedLinearRegression:
|
case EAntiRecoilMode::ARM_WeightedLinearRegression:
|
||||||
{
|
{
|
||||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||||
if (SafeN >= 2)
|
if (SafeN >= 2)
|
||||||
{
|
{
|
||||||
PredictWeightedLinearRegression(GetWorld()->GetTimeSeconds(), Location, Aim);
|
PredictWeightedLinearRegression(GetWorld()->GetTimeSeconds(), Location, Aim);
|
||||||
@ -188,7 +189,7 @@ void UEBBarrel::ComputeAntiRecoilTransform()
|
|||||||
|
|
||||||
case EAntiRecoilMode::ARM_KalmanFilter:
|
case EAntiRecoilMode::ARM_KalmanFilter:
|
||||||
{
|
{
|
||||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||||
if (SafeN > 0)
|
if (SafeN > 0)
|
||||||
{
|
{
|
||||||
// Feed only the latest SAFE sample to the Kalman filter
|
// Feed only the latest SAFE sample to the Kalman filter
|
||||||
@ -211,7 +212,7 @@ void UEBBarrel::ComputeAntiRecoilTransform()
|
|||||||
|
|
||||||
case EAntiRecoilMode::ARM_AdaptiveExtrapolation:
|
case EAntiRecoilMode::ARM_AdaptiveExtrapolation:
|
||||||
{
|
{
|
||||||
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||||
if (SafeN >= 2)
|
if (SafeN >= 2)
|
||||||
{
|
{
|
||||||
PredictAdaptiveExtrapolation(GetWorld()->GetTimeSeconds(), Location, Aim);
|
PredictAdaptiveExtrapolation(GetWorld()->GetTimeSeconds(), Location, Aim);
|
||||||
@ -237,7 +238,7 @@ void UEBBarrel::ComputeAntiRecoilTransform()
|
|||||||
|
|
||||||
void UEBBarrel::PredictLinearExtrapolation(double CurrentTime, FVector& OutLocation, FVector& OutAim) const
|
void UEBBarrel::PredictLinearExtrapolation(double CurrentTime, FVector& OutLocation, FVector& OutAim) const
|
||||||
{
|
{
|
||||||
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||||
if (SafeN < 2)
|
if (SafeN < 2)
|
||||||
{
|
{
|
||||||
OutLocation = TransformHistory[0].Location;
|
OutLocation = TransformHistory[0].Location;
|
||||||
@ -317,7 +318,7 @@ void UEBBarrel::PredictLinearExtrapolation(double CurrentTime, FVector& OutLocat
|
|||||||
|
|
||||||
void UEBBarrel::PredictWeightedLinearRegression(double CurrentTime, FVector& OutLocation, FVector& OutAim) const
|
void UEBBarrel::PredictWeightedLinearRegression(double CurrentTime, FVector& OutLocation, FVector& OutAim) const
|
||||||
{
|
{
|
||||||
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||||
if (SafeN < 2)
|
if (SafeN < 2)
|
||||||
{
|
{
|
||||||
OutLocation = TransformHistory[0].Location;
|
OutLocation = TransformHistory[0].Location;
|
||||||
@ -390,7 +391,7 @@ void UEBBarrel::PredictWeightedLinearRegression(double CurrentTime, FVector& Out
|
|||||||
|
|
||||||
void UEBBarrel::PredictWeightedRegression(double CurrentTime, FVector& OutLocation, FVector& OutAim) const
|
void UEBBarrel::PredictWeightedRegression(double CurrentTime, FVector& OutLocation, FVector& OutAim) const
|
||||||
{
|
{
|
||||||
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||||
if (SafeN < 2)
|
if (SafeN < 2)
|
||||||
{
|
{
|
||||||
OutLocation = TransformHistory[0].Location;
|
OutLocation = TransformHistory[0].Location;
|
||||||
@ -706,7 +707,7 @@ void UEBBarrel::PredictKalmanFilter(double CurrentTime, FVector& OutLocation, FV
|
|||||||
|
|
||||||
void UEBBarrel::PredictAdaptiveExtrapolation(double CurrentTime, FVector& OutLocation, FVector& OutAim) const
|
void UEBBarrel::PredictAdaptiveExtrapolation(double CurrentTime, FVector& OutLocation, FVector& OutAim) const
|
||||||
{
|
{
|
||||||
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTime);
|
const int32 SafeN = GetSafeCount(TransformHistory, GetWorld()->GetTimeSeconds(), AntiRecoilDiscardTimeMs / 1000.0f);
|
||||||
if (SafeN < 2)
|
if (SafeN < 2)
|
||||||
{
|
{
|
||||||
OutLocation = TransformHistory[0].Location;
|
OutLocation = TransformHistory[0].Location;
|
||||||
@ -782,30 +783,68 @@ void UEBBarrel::PredictAdaptiveExtrapolation(double CurrentTime, FVector& OutLoc
|
|||||||
float RecentAimSpeed = RecentAimVel.Size();
|
float RecentAimSpeed = RecentAimVel.Size();
|
||||||
|
|
||||||
// Confidence: ratio of recent speed to average speed.
|
// Confidence: ratio of recent speed to average speed.
|
||||||
// Dead zone: ratios above AdaptiveDeadZone are treated as 1.0 (normal fluctuations).
|
// Dead zone: ratios above AdaptiveDeadZone are treated as 1.0 (no correction).
|
||||||
// Remapped ratio: (ratio - deadzone) / (1 - deadzone), clamped to [0, 1].
|
// Only ratios BELOW AdaptiveDeadZone trigger extrapolation reduction.
|
||||||
// AdaptiveSensitivity is the power exponent on the remapped ratio.
|
// Below dead zone: remap [0, deadzone] → [0, 1] then apply sensitivity exponent.
|
||||||
|
// Minimum speed threshold: below this, speed ratios are unreliable (noise dominates),
|
||||||
|
// so we keep full confidence to avoid false deceleration detection.
|
||||||
|
const float MinSpeedThreshold = AdaptiveMinSpeed;
|
||||||
|
|
||||||
float PosRatio = 1.0f;
|
float PosRatio = 1.0f;
|
||||||
float PosConfidence = 1.0f;
|
float PosConfidence = 1.0f;
|
||||||
if (AvgPosSpeed > SMALL_NUMBER)
|
float PosRemapped = 1.0f;
|
||||||
|
if (AvgPosSpeed > MinSpeedThreshold)
|
||||||
{
|
{
|
||||||
PosRatio = FMath::Clamp(RecentPosSpeed / AvgPosSpeed, 0.0f, 1.0f);
|
PosRatio = FMath::Clamp(RecentPosSpeed / AvgPosSpeed, 0.0f, 1.0f);
|
||||||
float PosRemapped = (AdaptiveDeadZone < 1.0f)
|
if (PosRatio >= AdaptiveDeadZone)
|
||||||
? FMath::Clamp((PosRatio - AdaptiveDeadZone) / (1.0f - AdaptiveDeadZone), 0.0f, 1.0f)
|
{
|
||||||
: (PosRatio >= 1.0f ? 1.0f : 0.0f);
|
// Inside dead zone: no correction, full confidence
|
||||||
PosConfidence = FMath::Pow(PosRemapped, AdaptiveSensitivity);
|
PosRemapped = 1.0f;
|
||||||
|
PosConfidence = 1.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Below dead zone: real deceleration detected
|
||||||
|
// Remap [0, deadzone] → [0, 1]
|
||||||
|
PosRemapped = (AdaptiveDeadZone > SMALL_NUMBER)
|
||||||
|
? FMath::Clamp(PosRatio / AdaptiveDeadZone, 0.0f, 1.0f)
|
||||||
|
: 0.0f;
|
||||||
|
PosConfidence = FMath::Pow(PosRemapped, AdaptiveSensitivity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// else: AvgPosSpeed <= MinSpeedThreshold → keep defaults (Ratio=1, Conf=1)
|
||||||
|
|
||||||
float AimRatio = 1.0f;
|
float AimRatio = 1.0f;
|
||||||
float AimConfidence = 1.0f;
|
float AimConfidence = 1.0f;
|
||||||
if (AvgAimSpeed > SMALL_NUMBER)
|
float AimRemapped = 1.0f;
|
||||||
|
if (AvgAimSpeed > MinSpeedThreshold)
|
||||||
{
|
{
|
||||||
AimRatio = FMath::Clamp(RecentAimSpeed / AvgAimSpeed, 0.0f, 1.0f);
|
AimRatio = FMath::Clamp(RecentAimSpeed / AvgAimSpeed, 0.0f, 1.0f);
|
||||||
float AimRemapped = (AdaptiveDeadZone < 1.0f)
|
if (AimRatio >= AdaptiveDeadZone)
|
||||||
? FMath::Clamp((AimRatio - AdaptiveDeadZone) / (1.0f - AdaptiveDeadZone), 0.0f, 1.0f)
|
{
|
||||||
: (AimRatio >= 1.0f ? 1.0f : 0.0f);
|
// Inside dead zone: no correction, full confidence
|
||||||
AimConfidence = FMath::Pow(AimRemapped, AdaptiveSensitivity);
|
AimRemapped = 1.0f;
|
||||||
|
AimConfidence = 1.0f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Below dead zone: real deceleration detected
|
||||||
|
// Remap [0, deadzone] → [0, 1]
|
||||||
|
AimRemapped = (AdaptiveDeadZone > SMALL_NUMBER)
|
||||||
|
? FMath::Clamp(AimRatio / AdaptiveDeadZone, 0.0f, 1.0f)
|
||||||
|
: 0.0f;
|
||||||
|
AimConfidence = FMath::Pow(AimRemapped, AdaptiveSensitivity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
// else: AvgAimSpeed <= MinSpeedThreshold → keep defaults (Ratio=1, Conf=1)
|
||||||
|
|
||||||
|
// Debug logs for dead zone diagnosis
|
||||||
|
UE_LOG(LogTemp, Log, TEXT("[AdaptiveExtrap] DZ=%.3f Sens=%.2f MinSpd=%.1f | Pos: Ratio=%.4f Remap=%.4f Conf=%.4f (Avg=%.2f Recent=%.2f %s) | Aim: Ratio=%.4f Remap=%.4f Conf=%.4f (Avg=%.2f Recent=%.2f %s)"),
|
||||||
|
AdaptiveDeadZone, AdaptiveSensitivity, MinSpeedThreshold,
|
||||||
|
PosRatio, PosRemapped, PosConfidence, AvgPosSpeed, RecentPosSpeed,
|
||||||
|
(AvgPosSpeed <= MinSpeedThreshold) ? TEXT("[LOW]") : (PosRatio >= AdaptiveDeadZone ? TEXT("[DZ]") : TEXT("[DEC]")),
|
||||||
|
AimRatio, AimRemapped, AimConfidence, AvgAimSpeed, RecentAimSpeed,
|
||||||
|
(AvgAimSpeed <= MinSpeedThreshold) ? TEXT("[LOW]") : (AimRatio >= AdaptiveDeadZone ? TEXT("[DZ]") : TEXT("[DEC]")));
|
||||||
|
|
||||||
// Extrapolate from last safe sample
|
// Extrapolate from last safe sample
|
||||||
const FTimestampedTransform& LastSafe = TransformHistory[SafeN - 1];
|
const FTimestampedTransform& LastSafe = TransformHistory[SafeN - 1];
|
||||||
@ -814,6 +853,8 @@ void UEBBarrel::PredictAdaptiveExtrapolation(double CurrentTime, FVector& OutLoc
|
|||||||
// Write debug values for HUD display
|
// Write debug values for HUD display
|
||||||
DbgPosRatio = PosRatio;
|
DbgPosRatio = PosRatio;
|
||||||
DbgAimRatio = AimRatio;
|
DbgAimRatio = AimRatio;
|
||||||
|
DbgPosRemapped = PosRemapped;
|
||||||
|
DbgAimRemapped = AimRemapped;
|
||||||
DbgPosConfidence = PosConfidence;
|
DbgPosConfidence = PosConfidence;
|
||||||
DbgAimConfidence = AimConfidence;
|
DbgAimConfidence = AimConfidence;
|
||||||
DbgAvgPosSpeed = AvgPosSpeed;
|
DbgAvgPosSpeed = AvgPosSpeed;
|
||||||
|
|||||||
@ -17,6 +17,7 @@ void UEBBarrel::Shoot(bool Trigger, int nextFireID) {
|
|||||||
if (ClientSideAim && GetOwner()->GetRemoteRole() == ROLE_Authority && Trigger) {
|
if (ClientSideAim && GetOwner()->GetRemoteRole() == ROLE_Authority && Trigger) {
|
||||||
Aim = GetComponentTransform().GetUnitAxis(EAxis::X);
|
Aim = GetComponentTransform().GetUnitAxis(EAxis::X);
|
||||||
Location = GetComponentTransform().GetLocation();
|
Location = GetComponentTransform().GetLocation();
|
||||||
|
ApplyAimStabilization();
|
||||||
nextFireEventID = nextFireID;
|
nextFireEventID = nextFireID;
|
||||||
ShootRepCSA(Trigger, UGameplayStatics::RebaseLocalOriginOntoZero(GetWorld(), Location), Aim, nextFireID);
|
ShootRepCSA(Trigger, UGameplayStatics::RebaseLocalOriginOntoZero(GetWorld(), Location), Aim, nextFireID);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -29,7 +29,7 @@ FPrimitiveSceneProxy* UEBBarrel::CreateSceneProxy() {
|
|||||||
const FLinearColor DrawColor = GetViewSelectionColor(FColor::Green, *View, IsSelected(), IsHovered(), true, IsIndividuallySelected());
|
const FLinearColor DrawColor = GetViewSelectionColor(FColor::Green, *View, IsSelected(), IsHovered(), true, IsIndividuallySelected());
|
||||||
|
|
||||||
FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
|
FPrimitiveDrawInterface* PDI = Collector.GetPDI(ViewIndex);
|
||||||
DrawDirectionalArrow(PDI, Transform, DrawColor, Component->DebugArrowSize, Component->DebugArrowSize*0.1f, 16, Component->DebugArrowSize*0.01f);
|
DrawDirectionalArrow(PDI, Transform, DrawColor, Component->DebugArrowSize, Component->DebugArrowSize*0.1f, 16, 0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,6 +45,41 @@ void UEBBarrel::EndPlay(const EEndPlayReason::Type EndPlayReason)
|
|||||||
Super::EndPlay(EndPlayReason);
|
Super::EndPlay(EndPlayReason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UEBBarrel::ApplyAimStabilization()
|
||||||
|
{
|
||||||
|
if (AimDeadZoneDegrees <= 0.0f)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bStabilizedAimInitialized)
|
||||||
|
{
|
||||||
|
StabilizedAim = Aim;
|
||||||
|
bStabilizedAimInitialized = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Compute angle between current aim and last stable aim
|
||||||
|
float AngleDeg = FMath::RadiansToDegrees(FMath::Acos(FMath::Clamp(FVector::DotProduct(Aim, StabilizedAim), -1.0f, 1.0f)));
|
||||||
|
if (AngleDeg <= AimDeadZoneDegrees)
|
||||||
|
{
|
||||||
|
// Within dead zone: keep previous stable aim (filter jitter)
|
||||||
|
Aim = StabilizedAim;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Outside dead zone: smooth transition to avoid jumps
|
||||||
|
// Subtract the dead zone from the angle so movement starts from zero
|
||||||
|
float ExcessDeg = AngleDeg - AimDeadZoneDegrees;
|
||||||
|
float BlendAlpha = FMath::Clamp(ExcessDeg / AngleDeg, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
// Slerp from stabilized aim toward real aim, removing the dead zone portion
|
||||||
|
StabilizedAim = FMath::Lerp(StabilizedAim, Aim, BlendAlpha).GetSafeNormal();
|
||||||
|
Aim = StabilizedAim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction* ThisTickFunction)
|
||||||
{
|
{
|
||||||
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
|
||||||
@ -58,6 +93,7 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
|||||||
if (TimeSinceAimUpdate >= 1.0f / ClientAimUpdateFrequency) {
|
if (TimeSinceAimUpdate >= 1.0f / ClientAimUpdateFrequency) {
|
||||||
|
|
||||||
ComputeAntiRecoilTransform();
|
ComputeAntiRecoilTransform();
|
||||||
|
ApplyAimStabilization();
|
||||||
|
|
||||||
ClientAim(UGameplayStatics::RebaseLocalOriginOntoZero(GetWorld(),Location), Aim);
|
ClientAim(UGameplayStatics::RebaseLocalOriginOntoZero(GetWorld(),Location), Aim);
|
||||||
TimeSinceAimUpdate = FMath::Fmod(TimeSinceAimUpdate, 1.0f / ClientAimUpdateFrequency);
|
TimeSinceAimUpdate = FMath::Fmod(TimeSinceAimUpdate, 1.0f / ClientAimUpdateFrequency);
|
||||||
@ -65,6 +101,7 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
|||||||
}else{
|
}else{
|
||||||
if (!RemoteAimReceived) {
|
if (!RemoteAimReceived) {
|
||||||
ComputeAntiRecoilTransform();
|
ComputeAntiRecoilTransform();
|
||||||
|
ApplyAimStabilization();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
FVector LocOffset = (Location - GetComponentLocation());
|
FVector LocOffset = (Location - GetComponentLocation());
|
||||||
@ -77,6 +114,7 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ComputeAntiRecoilTransform();
|
ComputeAntiRecoilTransform();
|
||||||
|
ApplyAimStabilization();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug visualization: raw tracker (green) vs predicted aim (red)
|
// Debug visualization: raw tracker (green) vs predicted aim (red)
|
||||||
@ -104,9 +142,9 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
|||||||
DrawDebugLine(GetWorld(), Location, Location + Aim * DebugAntiRecoilLineLength,
|
DrawDebugLine(GetWorld(), Location, Location + Aim * DebugAntiRecoilLineLength,
|
||||||
FColor::Red, false, -1.0f, 0, DebugAntiRecoilLineThickness);
|
FColor::Red, false, -1.0f, 0, DebugAntiRecoilLineThickness);
|
||||||
|
|
||||||
// Small spheres at origins for clarity
|
// Small dots at origins for clarity
|
||||||
DrawDebugSphere(GetWorld(), RawLocation, 1.5f, 6, FColor::Green, false, -1.0f, 0, DebugAntiRecoilLineThickness * 0.5f);
|
DrawDebugPoint(GetWorld(), RawLocation, 3.0f, FColor::Green, false, -1.0f, 0);
|
||||||
DrawDebugSphere(GetWorld(), Location, 1.5f, 6, FColor::Red, false, -1.0f, 0, DebugAntiRecoilLineThickness * 0.5f);
|
DrawDebugPoint(GetWorld(), Location, 3.0f, FColor::Red, false, -1.0f, 0);
|
||||||
|
|
||||||
// Yellow line: shows where shot would land WITHOUT anti-recoil correction
|
// Yellow line: shows where shot would land WITHOUT anti-recoil correction
|
||||||
// Captures raw aim at shock onset and persists for DebugIMUShockDisplayTime seconds
|
// Captures raw aim at shock onset and persists for DebugIMUShockDisplayTime seconds
|
||||||
@ -131,7 +169,7 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
|||||||
DrawDebugLine(GetWorld(), DebugIMUShockCapturedLocation,
|
DrawDebugLine(GetWorld(), DebugIMUShockCapturedLocation,
|
||||||
DebugIMUShockCapturedLocation + DebugIMUShockCapturedAim * DebugAntiRecoilLineLength,
|
DebugIMUShockCapturedLocation + DebugIMUShockCapturedAim * DebugAntiRecoilLineLength,
|
||||||
FColor::Green, false, -1.0f, 0, DebugAntiRecoilLineThickness);
|
FColor::Green, false, -1.0f, 0, DebugAntiRecoilLineThickness);
|
||||||
DrawDebugSphere(GetWorld(), DebugIMUShockCapturedLocation, 3.0f, 8, FColor::Green, false, -1.0f, 0, DebugAntiRecoilLineThickness);
|
DrawDebugPoint(GetWorld(), DebugIMUShockCapturedLocation, 3.0f, FColor::Green, false, -1.0f, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -147,7 +185,7 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
|||||||
DrawDebugLine(GetWorld(), DebugCorrectedShotCapturedLocation,
|
DrawDebugLine(GetWorld(), DebugCorrectedShotCapturedLocation,
|
||||||
DebugCorrectedShotCapturedLocation + DebugCorrectedShotCapturedAim * DebugAntiRecoilLineLength,
|
DebugCorrectedShotCapturedLocation + DebugCorrectedShotCapturedAim * DebugAntiRecoilLineLength,
|
||||||
FColor::Red, false, -1.0f, 0, DebugAntiRecoilLineThickness);
|
FColor::Red, false, -1.0f, 0, DebugAntiRecoilLineThickness);
|
||||||
DrawDebugSphere(GetWorld(), DebugCorrectedShotCapturedLocation, 3.0f, 8, FColor::Red, false, -1.0f, 0, DebugAntiRecoilLineThickness);
|
DrawDebugPoint(GetWorld(), DebugCorrectedShotCapturedLocation, 3.0f, FColor::Red, false, -1.0f, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -185,7 +223,7 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
|||||||
FVector RealPos = GetComponentTransform().GetLocation();
|
FVector RealPos = GetComponentTransform().GetLocation();
|
||||||
FVector RealAim = GetComponentTransform().GetUnitAxis(EAxis::X);
|
FVector RealAim = GetComponentTransform().GetUnitAxis(EAxis::X);
|
||||||
// Count safe samples (same logic as GetSafeCount in AntiRecoilPredict.cpp)
|
// Count safe samples (same logic as GetSafeCount in AntiRecoilPredict.cpp)
|
||||||
double SafeCutoff = GetWorld()->GetTimeSeconds() - AntiRecoilDiscardTime;
|
double SafeCutoff = GetWorld()->GetTimeSeconds() - (AntiRecoilDiscardTimeMs / 1000.0f);
|
||||||
int32 SafeN = 0;
|
int32 SafeN = 0;
|
||||||
for (int32 si = 0; si < TransformHistory.Num(); si++)
|
for (int32 si = 0; si < TransformHistory.Num(); si++)
|
||||||
{
|
{
|
||||||
@ -240,17 +278,26 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
|||||||
GEngine->AddOnScreenDebugMessage(HudKey--, 0.0f, HudTitle,
|
GEngine->AddOnScreenDebugMessage(HudKey--, 0.0f, HudTitle,
|
||||||
TEXT("====== ADAPTIVE EXTRAPOLATION ======"));
|
TEXT("====== ADAPTIVE EXTRAPOLATION ======"));
|
||||||
|
|
||||||
|
// Dead zone info
|
||||||
|
GEngine->AddOnScreenDebugMessage(HudKey--, 0.0f, HudVal,
|
||||||
|
FString::Printf(TEXT(" DeadZone=%.2f Sensitivity=%.1f"),
|
||||||
|
AdaptiveDeadZone, AdaptiveSensitivity));
|
||||||
|
|
||||||
// Speed ratio + confidence (position)
|
// Speed ratio + confidence (position)
|
||||||
FColor PosColor = (DbgPosConfidence > 0.9f) ? HudGood : HudWarn;
|
bool bPosInDeadZone = (DbgPosRatio >= AdaptiveDeadZone);
|
||||||
|
FColor PosColor = bPosInDeadZone ? HudGood : HudWarn;
|
||||||
GEngine->AddOnScreenDebugMessage(HudKey--, 0.0f, PosColor,
|
GEngine->AddOnScreenDebugMessage(HudKey--, 0.0f, PosColor,
|
||||||
FString::Printf(TEXT(" Pos: ratio=%.2f conf=%.2f speed=%.1f/%.1f cm/s"),
|
FString::Printf(TEXT(" Pos: ratio=%.3f %s remap=%.3f conf=%.3f spd=%.1f/%.1f"),
|
||||||
DbgPosRatio, DbgPosConfidence, DbgRecentPosSpeed, DbgAvgPosSpeed));
|
DbgPosRatio, bPosInDeadZone ? TEXT("[DZ]") : TEXT("[!!]"),
|
||||||
|
DbgPosRemapped, DbgPosConfidence, DbgRecentPosSpeed, DbgAvgPosSpeed));
|
||||||
|
|
||||||
// Speed ratio + confidence (aim)
|
// Speed ratio + confidence (aim)
|
||||||
FColor AimColor = (DbgAimConfidence > 0.9f) ? HudGood : HudWarn;
|
bool bAimInDeadZone = (DbgAimRatio >= AdaptiveDeadZone);
|
||||||
|
FColor AimColor = bAimInDeadZone ? HudGood : HudWarn;
|
||||||
GEngine->AddOnScreenDebugMessage(HudKey--, 0.0f, AimColor,
|
GEngine->AddOnScreenDebugMessage(HudKey--, 0.0f, AimColor,
|
||||||
FString::Printf(TEXT(" Aim: ratio=%.2f conf=%.2f speed=%.4f/%.4f /s"),
|
FString::Printf(TEXT(" Aim: ratio=%.3f %s remap=%.3f conf=%.3f spd=%.4f/%.4f"),
|
||||||
DbgAimRatio, DbgAimConfidence, DbgRecentAimSpeed, DbgAvgAimSpeed));
|
DbgAimRatio, bAimInDeadZone ? TEXT("[DZ]") : TEXT("[!!]"),
|
||||||
|
DbgAimRemapped, DbgAimConfidence, DbgRecentAimSpeed, DbgAvgAimSpeed));
|
||||||
|
|
||||||
// Extrapolation time
|
// Extrapolation time
|
||||||
GEngine->AddOnScreenDebugMessage(HudKey--, 0.0f, HudVal,
|
GEngine->AddOnScreenDebugMessage(HudKey--, 0.0f, HudVal,
|
||||||
@ -320,11 +367,11 @@ void UEBBarrel::TickComponent(float DeltaTime, ELevelTick TickType, FActorCompon
|
|||||||
LastCalibrationResult.AvgPeakAngleDeviation,
|
LastCalibrationResult.AvgPeakAngleDeviation,
|
||||||
LastCalibrationResult.AvgPeakPositionDeviation));
|
LastCalibrationResult.AvgPeakPositionDeviation));
|
||||||
GEngine->AddOnScreenDebugMessage(CalKey--, 0.0f, CalWarn,
|
GEngine->AddOnScreenDebugMessage(CalKey--, 0.0f, CalWarn,
|
||||||
FString::Printf(TEXT(" >> DiscardTime: %.4fs"),
|
FString::Printf(TEXT(" >> DiscardTime: %.1f ms"),
|
||||||
LastCalibrationResult.RecommendedDiscardTime));
|
LastCalibrationResult.RecommendedDiscardTime * 1000.0f));
|
||||||
GEngine->AddOnScreenDebugMessage(CalKey--, 0.0f, CalWarn,
|
GEngine->AddOnScreenDebugMessage(CalKey--, 0.0f, CalWarn,
|
||||||
FString::Printf(TEXT(" >> BufferTime: %.4fs"),
|
FString::Printf(TEXT(" >> BufferTime: %.1f ms"),
|
||||||
LastCalibrationResult.RecommendedBufferTime));
|
LastCalibrationResult.RecommendedBufferTime * 1000.0f));
|
||||||
GEngine->AddOnScreenDebugMessage(CalKey--, 0.0f, CalWarn,
|
GEngine->AddOnScreenDebugMessage(CalKey--, 0.0f, CalWarn,
|
||||||
FString::Printf(TEXT(" >> KalmanProcessNoise: %.3f"),
|
FString::Printf(TEXT(" >> KalmanProcessNoise: %.3f"),
|
||||||
LastCalibrationResult.RecommendedKalmanProcessNoise));
|
LastCalibrationResult.RecommendedKalmanProcessNoise));
|
||||||
|
|||||||
@ -120,6 +120,8 @@ public:
|
|||||||
// Debug HUD state (written by const prediction functions, read by TickComponent)
|
// Debug HUD state (written by const prediction functions, read by TickComponent)
|
||||||
mutable float DbgPosRatio = 0.0f;
|
mutable float DbgPosRatio = 0.0f;
|
||||||
mutable float DbgAimRatio = 0.0f;
|
mutable float DbgAimRatio = 0.0f;
|
||||||
|
mutable float DbgPosRemapped = 0.0f;
|
||||||
|
mutable float DbgAimRemapped = 0.0f;
|
||||||
mutable float DbgPosConfidence = 0.0f;
|
mutable float DbgPosConfidence = 0.0f;
|
||||||
mutable float DbgAimConfidence = 0.0f;
|
mutable float DbgAimConfidence = 0.0f;
|
||||||
mutable float DbgAvgPosSpeed = 0.0f;
|
mutable float DbgAvgPosSpeed = 0.0f;
|
||||||
@ -142,13 +144,13 @@ public:
|
|||||||
float DebugIMUShockDisplayTime = 3.0f;
|
float DebugIMUShockDisplayTime = 3.0f;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Selects the anti-recoil compensation algorithm. Hover over each option in the dropdown for a detailed description of how it works."))
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Selects the anti-recoil compensation algorithm. Hover over each option in the dropdown for a detailed description of how it works."))
|
||||||
EAntiRecoilMode AntiRecoilMode = EAntiRecoilMode::ARM_KalmanFilter;
|
EAntiRecoilMode AntiRecoilMode = EAntiRecoilMode::ARM_AdaptiveExtrapolation;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Total time window (seconds) of tracker history to keep. Determines how far back in time samples are stored. Must be greater than DiscardTime. Example: 0.2s at 60fps stores ~12 samples.", ClampMin = "0.05"))
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Total time window (ms) of tracker history to keep. Determines how far back in time samples are stored. Must be greater than DiscardTime. Example: 200ms at 60fps stores ~12 samples.", ClampMin = "5"))
|
||||||
float AntiRecoilBufferTime = 0.15f;
|
float AntiRecoilBufferTimeMs = 300.0f;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Time window (seconds) of most recent samples to exclude as potentially contaminated by IMU recoil shock. The prediction algorithms only use samples older than this. Increase if the shock lasts longer. Safe window = BufferTime - DiscardTime.", ClampMin = "0.0"))
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Time window (ms) of most recent samples to exclude as potentially contaminated by IMU recoil shock. The prediction algorithms only use samples older than this. Increase if the shock lasts longer. Safe window = BufferTime - DiscardTime.", ClampMin = "0.0"))
|
||||||
float AntiRecoilDiscardTime = 0.03f;
|
float AntiRecoilDiscardTimeMs = 40.0f;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Controls how the weight curve grows across safe samples in regression modes. 1.0 = linear growth, >1.0 = recent samples weighted much more heavily (convex curve), <1.0 = more uniform weighting (concave curve), 0.0 = all samples weighted equally. Formula: weight = pow(sampleIndex+1, exponent).", EditCondition = "AntiRecoilMode == EAntiRecoilMode::ARM_WeightedRegression || AntiRecoilMode == EAntiRecoilMode::ARM_WeightedLinearRegression", ClampMin = "0.0", ClampMax = "5.0"))
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Controls how the weight curve grows across safe samples in regression modes. 1.0 = linear growth, >1.0 = recent samples weighted much more heavily (convex curve), <1.0 = more uniform weighting (concave curve), 0.0 = all samples weighted equally. Formula: weight = pow(sampleIndex+1, exponent).", EditCondition = "AntiRecoilMode == EAntiRecoilMode::ARM_WeightedRegression || AntiRecoilMode == EAntiRecoilMode::ARM_WeightedLinearRegression", ClampMin = "0.0", ClampMax = "5.0"))
|
||||||
float RegressionWeightExponent = 2.0f;
|
float RegressionWeightExponent = 2.0f;
|
||||||
@ -160,13 +162,19 @@ public:
|
|||||||
float KalmanMeasurementNoise = 0.01f;
|
float KalmanMeasurementNoise = 0.01f;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Power curve exponent for deceleration detection. Controls how aggressively slowing down reduces extrapolation. confidence = (remappedRatio)^sensitivity. 1.0 = linear (gentle). 2.0 = quadratic (aggressive). 0.5 = square root (very gentle). During steady movement, ratio is ~1 so confidence is always 1 regardless of this value.", EditCondition = "AntiRecoilMode == EAntiRecoilMode::ARM_AdaptiveExtrapolation", ClampMin = "0.1", ClampMax = "5.0"))
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Power curve exponent for deceleration detection. Controls how aggressively slowing down reduces extrapolation. confidence = (remappedRatio)^sensitivity. 1.0 = linear (gentle). 2.0 = quadratic (aggressive). 0.5 = square root (very gentle). During steady movement, ratio is ~1 so confidence is always 1 regardless of this value.", EditCondition = "AntiRecoilMode == EAntiRecoilMode::ARM_AdaptiveExtrapolation", ClampMin = "0.1", ClampMax = "5.0"))
|
||||||
float AdaptiveSensitivity = 1.0f;
|
float AdaptiveSensitivity = 1.5f;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Dead zone for deceleration detection. Speed ratios (recent/avg) above this value are treated as 1.0 (no correction). Only ratios below trigger extrapolation reduction. Higher = more tolerant to natural speed fluctuations (less false positives). Lower = more sensitive to deceleration. 0.8 = ignore normal jitter, only react to real braking.", EditCondition = "AntiRecoilMode == EAntiRecoilMode::ARM_AdaptiveExtrapolation", ClampMin = "0.0", ClampMax = "0.95"))
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Dead zone for deceleration detection. Speed ratios (recent/avg) above this value are treated as 1.0 (no correction). Only ratios below trigger extrapolation reduction. Higher = more tolerant to natural speed fluctuations (less false positives). Lower = more sensitive to deceleration. 0.8 = ignore normal jitter, only react to real braking.", EditCondition = "AntiRecoilMode == EAntiRecoilMode::ARM_AdaptiveExtrapolation", ClampMin = "0.0", ClampMax = "0.95"))
|
||||||
float AdaptiveDeadZone = 0.8f;
|
float AdaptiveDeadZone = 0.8f;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Minimum average speed (cm/s) required for deceleration detection. Below this threshold, speed ratios are unreliable due to noise, so confidence stays at 1.0 (full extrapolation). Prevents false deceleration detection during slow/small movements. 0 = disabled.", EditCondition = "AntiRecoilMode == EAntiRecoilMode::ARM_AdaptiveExtrapolation", ClampMin = "0.0", ClampMax = "200.0"))
|
||||||
|
float AdaptiveMinSpeed = 30.0f;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Velocity damping during extrapolation. 0 = disabled (default). Higher values cause extrapolated velocity to decay exponentially toward zero over the discard window. Reduces overshoot on fast draw-aim-fire sequences where the user stops moving before firing. Applies to all prediction modes except Buffer. Typical range: 5-15.", ClampMin = "0.0", ClampMax = "50.0"))
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AntiRecoil", meta = (ToolTip = "Velocity damping during extrapolation. 0 = disabled (default). Higher values cause extrapolated velocity to decay exponentially toward zero over the discard window. Reduces overshoot on fast draw-aim-fire sequences where the user stops moving before firing. Applies to all prediction modes except Buffer. Typical range: 5-15.", ClampMin = "0.0", ClampMax = "50.0"))
|
||||||
float ExtrapolationDamping = 0.0f;
|
float ExtrapolationDamping = 8.0f;
|
||||||
|
|
||||||
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "AimStabilization", meta = (ToolTip = "Angular dead zone in degrees. If the aim direction changes by less than this angle since the last stable aim, the change is ignored (aim stays locked). Eliminates micro-jitter from VR tracker vibrations. 0 = disabled. Typical: 0.1 to 0.5 degrees.", ClampMin = "0.0", ClampMax = "5.0"))
|
||||||
|
float AimDeadZoneDegrees = 0.0f;
|
||||||
|
|
||||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Velocity", meta = (ToolTip = "Bullet inherits barrel velocity, only works with physics enabled or with additional velocity set")) float InheritVelocity = 1.0f;
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Velocity", meta = (ToolTip = "Bullet inherits barrel velocity, only works with physics enabled or with additional velocity set")) float InheritVelocity = 1.0f;
|
||||||
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Velocity", meta = (ToolTip = "Amount of recoil applied to the barrel, only works with physics enabled")) float RecoilMultiplier = 1.0f;
|
UPROPERTY(BlueprintReadWrite, EditAnywhere, Category = "Velocity", meta = (ToolTip = "Amount of recoil applied to the barrel, only works with physics enabled")) float RecoilMultiplier = 1.0f;
|
||||||
@ -296,6 +304,10 @@ private:
|
|||||||
FVector Aim;
|
FVector Aim;
|
||||||
FVector Location;
|
FVector Location;
|
||||||
|
|
||||||
|
// Aim stabilization: last accepted aim direction (outside dead zone)
|
||||||
|
FVector StabilizedAim = FVector::ForwardVector;
|
||||||
|
bool bStabilizedAimInitialized = false;
|
||||||
|
|
||||||
TArray<FTimestampedTransform> TransformHistory;
|
TArray<FTimestampedTransform> TransformHistory;
|
||||||
|
|
||||||
// Debug IMU shock simulation state
|
// Debug IMU shock simulation state
|
||||||
@ -336,6 +348,7 @@ private:
|
|||||||
|
|
||||||
void UpdateTransformHistory();
|
void UpdateTransformHistory();
|
||||||
void ComputeAntiRecoilTransform();
|
void ComputeAntiRecoilTransform();
|
||||||
|
void ApplyAimStabilization();
|
||||||
void PredictLinearExtrapolation(double CurrentTime, FVector& OutLocation, FVector& OutAim) const;
|
void PredictLinearExtrapolation(double CurrentTime, FVector& OutLocation, FVector& OutAim) const;
|
||||||
void PredictWeightedLinearRegression(double CurrentTime, FVector& OutLocation, FVector& OutAim) const;
|
void PredictWeightedLinearRegression(double CurrentTime, FVector& OutLocation, FVector& OutAim) const;
|
||||||
void PredictWeightedRegression(double CurrentTime, FVector& OutLocation, FVector& OutAim) const;
|
void PredictWeightedRegression(double CurrentTime, FVector& OutLocation, FVector& OutAim) const;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user