1+ using Elements . Core ;
2+ using FrooxEngine ;
3+ using HarmonyLib ;
4+ using System ;
5+ using System . Collections . Generic ;
6+ using System . Text ;
7+ using static FrooxEngine . LocomotionSimulator ;
8+
9+ namespace CommunityBugFixCollection
10+ {
11+ [ HarmonyPatchCategory ( nameof ( WhiteDesktopDebug ) ) ]
12+ [ HarmonyPatch ( typeof ( LocomotionSimulator ) , nameof ( LocomotionSimulator . SimulateHead ) ) ]
13+ internal sealed class WhiteDesktopDebug : ResoniteBugFixMonkey < WhiteDesktopDebug >
14+ {
15+ public override IEnumerable < string > Authors => Contributors . Banane9 ;
16+
17+ private static bool Prefix ( LocomotionSimulator __instance , in MoveData data )
18+ {
19+ if ( __instance . SimulateHeadLook )
20+ {
21+ __instance . _headLookAdjustmentAge += data . deltaTime ;
22+ __instance . HeadLookDirection = data . invRotationDelta * AsRefReadOnly ( __instance . HeadLookDirection ) ;
23+ if ( __instance . _headLookAdjustmentAge > 2f || MathX . Angle ( __instance . HeadLookDirection , float3 . Forward ) > __instance . HeadMaxLookDirectionAngle )
24+ {
25+ __instance . _headLookAdjustmentAge = 0f ;
26+ __instance . HeadLookDirection = floatQ . AxisAngle ( float3 . Right , RandomX . Range ( - 15f , 15f ) ) * floatQ . AxisAngle ( float3 . Up , RandomX . Range ( - 30f , 30f ) ) * float3 . Forward ;
27+ }
28+ }
29+
30+ __instance . _currentHeadLookDirection = data . invRotationDelta * __instance . _currentHeadLookDirection ;
31+ __instance . _currentHeadLookDirection = MathX . SmoothSlerp ( in __instance . _currentHeadLookDirection , __instance . HeadLookDirection , ref __instance . _intermediateHeadLookDirection , data . deltaTime * __instance . HeadLookSpeed ) ;
32+ __instance . _currentHeadLookDirection = MathX . LimitSwing ( __instance . _currentHeadLookDirection , float3 . Forward , __instance . HeadMaxLookDirectionAngle ) ;
33+ __instance . _headSwaySpeedProgress += data . deltaTime * __instance . HeadSwaySpeedSpeed ;
34+ float headSwaySpeed = MathX . LerpUnclamped ( lerp : MathX . SimplexNoise ( __instance . _headSwaySpeedProgress + __instance . _headSwaySpeedSeed ) . Pack ( ) , a : __instance . HeadSwayMinSpeed , b : __instance . HeadSwayMaxSpeed ) ;
35+ __instance . _headSwayProgress += data . deltaTime * headSwaySpeed ;
36+ float verticalSwayAngle = MathX . SimplexNoise ( __instance . _headSwayVerticalSeed + __instance . _headSwayProgress ) ;
37+ float horizontalSwayAngle = MathX . SimplexNoise ( __instance . _headSwayHorizontalSeed + __instance . _headSwayProgress ) ;
38+ verticalSwayAngle *= __instance . HeadSwayVerticalAngle ;
39+ horizontalSwayAngle *= __instance . HeadSwayHorizontalAngle ;
40+ float horizontalTilt = 0f ;
41+ float verticalTilt = 0f ;
42+ float verticalOffset = 0f ;
43+ float3 referenceDir = MathX . Slerp ( float3 . Forward , in data . positionDir , __instance . MinVelocityLerp ) ;
44+
45+ if ( float . IsNaN ( referenceDir . z ) )
46+ Logger . Error ( ( ) => "referenceDir.z is NaN!" ) ;
47+
48+ int forwardMul = MathX . Sign ( referenceDir . z ) ;
49+ if ( ( float ) forwardMul == 0f )
50+ {
51+ forwardMul = 1 ;
52+ }
53+ if ( MathX . Approximately ( in referenceDir , float3 . Zero ) )
54+ {
55+ referenceDir = float3 . Forward ;
56+ }
57+ floatQ rotationAlign = floatQ . FromToRotation ( in referenceDir , float3 . Forward ) ;
58+ if ( __instance . State == LocomotionState . OnGround )
59+ {
60+ foreach ( LocomotionFoot foot in __instance . _feet )
61+ {
62+ float3 @float = rotationAlign * AsRefReadOnly ( foot . BasePosition ) ;
63+ float footDistanceLerp = MathX . Pow ( 1f - MathX . Clamp01 ( foot . BasePosition . Magnitude / __instance . FootMaxDistance ) , 0.25f ) ;
64+ _ = foot . Position ;
65+
66+ if ( float . IsNaN ( @float . x ) )
67+ Logger . Error ( ( ) => "@float.x is NaN!" ) ;
68+
69+ int horizontalSide = MathX . Sign ( @float . x ) ;
70+ float forwardOffset = MathX . Clamp ( ( @float . z - ( rotationAlign * AsRefReadOnly ( foot . RestingPosition ) ) . z ) / ( __instance . DirectionFootTravelDistance * 0.5f ) , - 1f , 1f ) ;
71+ horizontalTilt -= forwardOffset * ( float ) horizontalSide * ( float ) forwardMul ;
72+ verticalOffset -= MathX . Abs ( forwardOffset ) ;
73+ }
74+ if ( __instance . _feet . Count > 0 )
75+ {
76+ verticalOffset /= ( float ) __instance . _feet . Count ;
77+ }
78+ }
79+ else
80+ {
81+ if ( float . IsNaN ( __instance . CurrentPositionVelocity . z ) )
82+ Logger . Error ( ( ) => "__instance.CurrentPositionVelocity.z is NaN!" ) ;
83+
84+ verticalTilt = ( 0f - MathX . Clamp ( __instance . CurrentPositionVelocity . y / __instance . MaxVerticalReferenceSpeed , - 1f , 1f ) ) * __instance . HeadJumpAngle * ( float ) MathX . Sign ( __instance . CurrentPositionVelocity . z ) ;
85+ }
86+ __instance . _headVerticalPosition -= data . positionDelta . y * ( ( __instance . State == LocomotionState . Floating ) ? __instance . HeadFloatingVerticalTransferRatio : __instance . HeadVerticalTransferRatio ) ;
87+ float drag ;
88+ float force ;
89+ if ( __instance . State == LocomotionState . Floating )
90+ {
91+ drag = __instance . HeadFloatingVerticalDrag ;
92+ force = __instance . HeadFloatingVerticalForce ;
93+ }
94+ else
95+ {
96+ drag = __instance . HeadVerticalDrag ;
97+ force = __instance . HeadVerticalForce ;
98+ }
99+
100+ if ( float . IsNaN ( __instance . _headVerticalVelocity ) )
101+ Logger . Error ( ( ) => "__instance._headVerticalVelocity is NaN!" ) ;
102+
103+ int headVerticalDir = MathX . Sign ( __instance . _headVerticalVelocity ) ;
104+ __instance . _headVerticalVelocity = MathX . Abs ( __instance . _headVerticalVelocity ) ;
105+ __instance . _headVerticalVelocity -= data . deltaTime * drag * __instance . _headVerticalVelocity ;
106+ __instance . _headVerticalVelocity = MathX . Max ( 0f , __instance . _headVerticalVelocity ) ;
107+ __instance . _headVerticalVelocity = MathX . Min ( __instance . HeadMaxVerticalVelocity , __instance . _headVerticalVelocity ) ;
108+ __instance . _headVerticalVelocity *= headVerticalDir ;
109+ __instance . _headVerticalVelocity += ( 0f - __instance . _headVerticalPosition ) * data . deltaTime * force ;
110+ __instance . _headVerticalPosition += __instance . _headVerticalVelocity * data . deltaTime ;
111+ __instance . _headVerticalPosition = MathX . Clamp ( __instance . _headVerticalPosition , __instance . HeadMinVerticalOffset , __instance . HeadMaxVerticalOffset ) ;
112+ float multiplier = MathX . Clamp01 ( __instance . MinVelocityLerp + __instance . AirLerp + __instance . FloatingLerp ) ;
113+ horizontalTilt *= multiplier ;
114+ verticalTilt *= multiplier ;
115+ verticalOffset *= multiplier ;
116+ __instance . _currentHorizontalTilt = MathX . SmoothDamp ( __instance . _currentHorizontalTilt , horizontalTilt , ref __instance . _intermediateHorizontalTilt , __instance . CurrentParameters . HeadSmoothingSpeed , 10f , data . deltaTime ) ;
117+ __instance . _currentVerticalTilt = MathX . SmoothDamp ( __instance . _currentVerticalTilt , verticalTilt , ref __instance . _intermediateVerticalTilt , __instance . CurrentParameters . HeadSmoothingSpeed , 10f , data . deltaTime ) ;
118+ __instance . _currentVerticalOffset = MathX . SmoothDamp ( __instance . _currentVerticalOffset , verticalOffset , ref __instance . _intermediateVerticalOffset , __instance . CurrentParameters . HeadSmoothingSpeed , 10f , data . deltaTime ) ;
119+ __instance . HeadPositionOffset = new float3 ( __instance . _currentHorizontalTilt * __instance . CurrentParameters . HeadHorizontalBobOffset , __instance . _currentVerticalOffset * __instance . CurrentParameters . HeadVerticalBobOffset + __instance . _headVerticalPosition ) ;
120+ __instance . HeadRotationOffset = floatQ . AxisAngle ( float3 . Right , __instance . _currentVerticalTilt + verticalSwayAngle + __instance . CurrentParameters . VerticalHeadAngleOffset ) * floatQ . AxisAngle ( float3 . Forward , __instance . _currentHorizontalTilt * __instance . CurrentParameters . HeadHorizontalBobAngle + horizontalSwayAngle ) * floatQ . LookRotation ( in __instance . _currentHeadLookDirection ) ;
121+
122+ static ref readonly T AsRefReadOnly < T > ( in T temp )
123+ {
124+ //ILSpy generated this function to help ensure overload resolution can pick the overload using 'in'
125+ return ref temp ;
126+ }
127+
128+ return false ;
129+ }
130+ }
131+ }
0 commit comments