@@ -55,7 +55,7 @@ void AHuman::Clear() {
55
55
m_ProneState = NOTPRONE;
56
56
m_ProneTimer.Reset ();
57
57
m_MaxWalkPathCrouchShift = 6 .0F ;
58
- m_MaxCrouchRotation = c_QuarterPI * 0 . 85F ;
58
+ m_CrouchAmount = 0 . 0F ;
59
59
m_CrouchAmountOverride = -1 .0F ;
60
60
for (int i = 0 ; i < MOVEMENTSTATECOUNT; ++i) {
61
61
m_Paths[FGROUND][i].Reset ();
@@ -64,6 +64,8 @@ void AHuman::Clear() {
64
64
m_Paths[BGROUND][i].Terminate ();
65
65
m_RotAngleTargets[i] = 0 .0F ;
66
66
}
67
+ // Default CROUCH RotAngleTarget to a more sensible number
68
+ m_RotAngleTargets[CROUCH] = c_QuarterPI * 0 .85F ;
67
69
m_Aiming = false ;
68
70
m_ArmClimbing[FGROUND] = false ;
69
71
m_ArmClimbing[BGROUND] = false ;
@@ -213,7 +215,6 @@ int AHuman::Create(const AHuman& reference) {
213
215
m_BackupBGFootGroup->SetLimbPos (atomGroupToUseAsFootGroupBG->GetLimbPos ());
214
216
215
217
m_MaxWalkPathCrouchShift = reference.m_MaxWalkPathCrouchShift ;
216
- m_MaxCrouchRotation = reference.m_MaxCrouchRotation ;
217
218
218
219
if (reference.m_StrideSound ) {
219
220
m_StrideSound = dynamic_cast <SoundContainer*>(reference.m_StrideSound ->Clone ());
@@ -293,7 +294,6 @@ int AHuman::ReadProperty(const std::string_view& propName, Reader& reader) {
293
294
m_BackupBGFootGroup->RemoveAllAtoms ();
294
295
});
295
296
MatchProperty (" MaxWalkPathCrouchShift" , { reader >> m_MaxWalkPathCrouchShift; });
296
- MatchProperty (" MaxCrouchRotation" , { reader >> m_MaxCrouchRotation; });
297
297
MatchProperty (" StrideSound" , {
298
298
m_StrideSound = new SoundContainer;
299
299
reader >> m_StrideSound;
@@ -302,8 +302,8 @@ int AHuman::ReadProperty(const std::string_view& propName, Reader& reader) {
302
302
MatchProperty (" StandLimbPathBG" , { reader >> m_Paths[BGROUND][STAND]; });
303
303
MatchProperty (" WalkLimbPath" , { reader >> m_Paths[FGROUND][WALK]; });
304
304
MatchProperty (" RunLimbPath" , { reader >> m_Paths[FGROUND][RUN]; });
305
- MatchProperty (" CrouchLimbPath" , { reader >> m_Paths[FGROUND][CROUCH ]; });
306
- MatchProperty (" CrouchLimbPathBG" , { reader >> m_Paths[BGROUND][CROUCH ]; });
305
+ MatchProperty (" CrouchLimbPath" , { reader >> m_Paths[FGROUND][PRONE ]; });
306
+ MatchProperty (" CrouchLimbPathBG" , { reader >> m_Paths[BGROUND][PRONE ]; });
307
307
MatchProperty (" CrawlLimbPath" , { reader >> m_Paths[FGROUND][CRAWL]; });
308
308
MatchProperty (" ArmCrawlLimbPath" , { reader >> m_Paths[FGROUND][ARMCRAWL]; });
309
309
MatchProperty (" ClimbLimbPath" , { reader >> m_Paths[FGROUND][CLIMB]; });
@@ -353,8 +353,6 @@ int AHuman::Save(Writer& writer) const {
353
353
writer << m_pBGFootGroup;
354
354
writer.NewProperty (" MaxWalkPathCrouchShift" );
355
355
writer << m_MaxWalkPathCrouchShift;
356
- writer.NewProperty (" MaxCrouchRotation" );
357
- writer << m_MaxCrouchRotation;
358
356
writer.NewProperty (" StrideSound" );
359
357
writer << m_StrideSound;
360
358
@@ -367,7 +365,7 @@ int AHuman::Save(Writer& writer) const {
367
365
writer.NewProperty (" RunLimbPath" );
368
366
writer << m_Paths[FGROUND][RUN];
369
367
writer.NewProperty (" CrouchLimbPath" );
370
- writer << m_Paths[FGROUND][CROUCH ];
368
+ writer << m_Paths[FGROUND][PRONE ];
371
369
writer.NewProperty (" CrawlLimbPath" );
372
370
writer << m_Paths[FGROUND][CRAWL];
373
371
writer.NewProperty (" ArmCrawlLimbPath" );
@@ -382,7 +380,7 @@ int AHuman::Save(Writer& writer) const {
382
380
writer.NewPropertyWithValue (" StandRotAngleTarget" , m_RotAngleTargets[STAND]);
383
381
writer.NewPropertyWithValue (" WalkRotAngleTarget" , m_RotAngleTargets[WALK]);
384
382
writer.NewPropertyWithValue (" RunRotAngleTarget" , m_RotAngleTargets[RUN]);
385
- writer.NewPropertyWithValue (" CrouchRotAngleTarget" , m_RotAngleTargets[CROUCH ]);
383
+ writer.NewPropertyWithValue (" CrouchRotAngleTarget" , m_RotAngleTargets[PRONE ]);
386
384
writer.NewPropertyWithValue (" JumpRotAngleTarget" , m_RotAngleTargets[JUMP]);
387
385
388
386
return 0 ;
@@ -1438,12 +1436,19 @@ void AHuman::UpdateCrouching() {
1438
1436
1439
1437
float finalWalkPathYOffset = std::clamp (Lerp (0 .0F , 1 .0F , -m_WalkPathOffset.m_Y , desiredWalkPathYOffset, 0 .3F ), 0 .0F , m_MaxWalkPathCrouchShift);
1440
1438
m_WalkPathOffset.m_Y = -finalWalkPathYOffset;
1439
+
1440
+ m_CrouchAmount = desiredWalkPathYOffset / m_MaxWalkPathCrouchShift;
1441
1441
1442
1442
// Adjust our X offset to try to keep our legs under our centre-of-mass
1443
1443
const float ratioBetweenBodyAndHeadToAimFor = 0 .15F ;
1444
1444
Vector headPos = m_pHead ? m_pHead->GetPos () : m_Pos;
1445
1445
float predictedPosition = ((headPos.m_X - m_Pos.m_X ) * ratioBetweenBodyAndHeadToAimFor) + m_Vel.m_X ;
1446
1446
m_WalkPathOffset.m_X = predictedPosition;
1447
+ if (m_CrouchAmount > 0 .9F && !m_MoveState == WALK ) {
1448
+ // Let the CrouchLimbPath take over here
1449
+ m_WalkPathOffset.m_Y = 0 .0F ;
1450
+ m_WalkPathOffset.m_X = 0 .0F ;
1451
+ }
1447
1452
}
1448
1453
1449
1454
void AHuman::UpdateLimbPathSpeed () {
@@ -1512,6 +1517,11 @@ void AHuman::PreControllerUpdate() {
1512
1517
1513
1518
if (!keepOldState) {
1514
1519
bool prone = m_Controller.IsState (BODY_PRONE);
1520
+ // Engage prone state, this makes the body's rotational spring pull it horizontal instead of upright.
1521
+ if (prone && m_ProneState == NOTPRONE) {
1522
+ m_ProneState = GOPRONE;
1523
+ m_ProneTimer.Reset ();
1524
+ }
1515
1525
if ((m_Controller.IsState (MOVE_RIGHT) || m_Controller.IsState (MOVE_LEFT) || m_MoveState == JUMP) && m_Status != INACTIVE) {
1516
1526
for (int i = WALK; i < MOVEMENTSTATECOUNT; ++i) {
1517
1527
m_Paths[FGROUND][i].SetHFlip (m_HFlipped);
@@ -1520,9 +1530,9 @@ void AHuman::PreControllerUpdate() {
1520
1530
// Only if not jumping, OR if jumping, and apparently stuck on something - then help out with the limbs.
1521
1531
if (m_MoveState != JUMP || isStill) {
1522
1532
MovementState oldMoveState = m_MoveState;
1523
- if (prone ) {
1533
+ if (!m_ProneState == NOTPRONE ) {
1524
1534
m_MoveState = CRAWL;
1525
- } else if (m_Controller.IsState (MOVE_FAST) && !m_Controller.IsState (BODY_CROUCH)) {
1535
+ } else if (m_CanRun && m_Controller.IsState (MOVE_FAST) && !m_Controller.IsState (BODY_CROUCH)) {
1526
1536
m_MoveState = RUN;
1527
1537
} else {
1528
1538
m_MoveState = WALK;
@@ -1533,12 +1543,6 @@ void AHuman::PreControllerUpdate() {
1533
1543
m_StrideStart = true ;
1534
1544
MoveOutOfTerrain (g_MaterialGrass);
1535
1545
}
1536
-
1537
- // Engage prone state, this makes the body's rotational spring pull it horizontal instead of upright.
1538
- if (m_MoveState == CRAWL && m_ProneState == NOTPRONE) {
1539
- m_ProneState = GOPRONE;
1540
- m_ProneTimer.Reset ();
1541
- }
1542
1546
}
1543
1547
1544
1548
// Walk backwards if the aiming is already focused in the opposite direction of travel.
@@ -1562,15 +1566,18 @@ void AHuman::PreControllerUpdate() {
1562
1566
m_StrideStart = true ;
1563
1567
// Stop the going prone spring.
1564
1568
if (m_ProneState == GOPRONE) {
1565
- m_ProneState = PRONE ;
1569
+ m_ProneState = LAYINGPRONE ;
1566
1570
}
1567
1571
}
1568
1572
} else {
1569
1573
m_ArmClimbing[FGROUND] = false ;
1570
1574
m_ArmClimbing[BGROUND] = false ;
1571
1575
if (prone) {
1572
1576
// Don't go back to prone if we're already prone, the player has to let go of the crouch button first. If already laying down, just stay put.
1573
- m_MoveState = m_ProneState == NOTPRONE ? CROUCH : NOMOVE;
1577
+ m_MoveState = m_ProneState == NOTPRONE ? PRONE : NOMOVE;
1578
+ } else if (m_CrouchAmount > 0 .9F ) {
1579
+ // Fully crouching will set the appropriate state so we can use CrouchLimbPath
1580
+ m_MoveState = CROUCH;
1574
1581
} else {
1575
1582
m_MoveState = STAND;
1576
1583
}
@@ -1682,7 +1689,7 @@ void AHuman::PreControllerUpdate() {
1682
1689
m_StrideStart = true ;
1683
1690
// Stop the going prone spring.
1684
1691
if (m_ProneState == GOPRONE) {
1685
- m_ProneState = PRONE ;
1692
+ m_ProneState = LAYINGPRONE ;
1686
1693
}
1687
1694
}
1688
1695
// Correct angle based on flip.
@@ -1699,7 +1706,7 @@ void AHuman::PreControllerUpdate() {
1699
1706
1700
1707
// TODO: make the delay data driven by both the actor and the device!
1701
1708
//
1702
- if (isSharpAiming && m_Status == STABLE && (m_MoveState == STAND || m_MoveState == CROUCH || m_MoveState == NOMOVE || m_MoveState == WALK) && m_Vel.MagnitudeIsLessThan (5 .0F ) && GetEquippedItem ()) {
1709
+ if (isSharpAiming && m_Status == STABLE && (m_MoveState == STAND || m_MoveState == PRONE || m_MoveState == NOMOVE || m_MoveState == WALK) && m_Vel.MagnitudeIsLessThan (5 .0F ) && GetEquippedItem ()) {
1703
1710
float aimMag = analogAim.GetMagnitude ();
1704
1711
1705
1712
// If aim sharp is being done digitally, then translate to full analog aim mag
@@ -2119,7 +2126,7 @@ void AHuman::PreControllerUpdate() {
2119
2126
}
2120
2127
} else if (m_MoveState == CRAWL) {
2121
2128
// Start crawling only once we are fully prone.
2122
- if (m_ProneState == PRONE ) {
2129
+ if (m_ProneState == LAYINGPRONE ) {
2123
2130
2124
2131
float FGLegProg = m_Paths[FGROUND][CRAWL].GetRegularProgress ();
2125
2132
float BGLegProg = m_Paths[BGROUND][CRAWL].GetRegularProgress ();
@@ -2184,11 +2191,11 @@ void AHuman::PreControllerUpdate() {
2184
2191
m_Paths[BGROUND][CRAWL].Terminate ();
2185
2192
2186
2193
if (m_pFGLeg) {
2187
- m_pFGFootGroup->PushAsLimb (m_Pos.GetFloored () + m_pFGLeg->GetParentOffset ().GetXFlipped (m_HFlipped), m_Vel, Matrix (), m_Paths[FGROUND][CROUCH ], deltaTime);
2194
+ m_pFGFootGroup->PushAsLimb (m_Pos.GetFloored () + m_pFGLeg->GetParentOffset ().GetXFlipped (m_HFlipped), m_Vel, Matrix (), m_Paths[FGROUND][PRONE ], deltaTime);
2188
2195
}
2189
2196
2190
2197
if (m_pBGLeg) {
2191
- m_pBGFootGroup->PushAsLimb (m_Pos.GetFloored () + m_pBGLeg->GetParentOffset ().GetXFlipped (m_HFlipped), m_Vel, Matrix (), m_Paths[BGROUND][CROUCH ], deltaTime);
2198
+ m_pBGFootGroup->PushAsLimb (m_Pos.GetFloored () + m_pBGLeg->GetParentOffset ().GetXFlipped (m_HFlipped), m_Vel, Matrix (), m_Paths[BGROUND][PRONE ], deltaTime);
2192
2199
}
2193
2200
2194
2201
} else {
@@ -2289,7 +2296,7 @@ void AHuman::PreControllerUpdate() {
2289
2296
if (m_Status == STABLE) {
2290
2297
if (m_ArmClimbing[BGROUND]) {
2291
2298
// Can't climb or crawl with the shield
2292
- if (m_MoveState != CRAWL || m_ProneState == PRONE ) {
2299
+ if (m_MoveState != CRAWL || m_ProneState == LAYINGPRONE ) {
2293
2300
UnequipBGArm ();
2294
2301
}
2295
2302
m_pBGArm->AddHandTarget (" Hand AtomGroup Limb Pos" , m_pBGHandGroup->GetLimbPos (m_HFlipped));
@@ -2309,7 +2316,7 @@ void AHuman::PreControllerUpdate() {
2309
2316
m_pBGArm->SetRecoil (heldDevice->GetRecoilForce (), heldDevice->GetRecoilOffset (), heldDevice->IsRecoiled ());
2310
2317
} else {
2311
2318
// BGArm did not reach to support the device. Count device as supported anyway, if crouching or prone.
2312
- heldDevice->SetSupported (m_MoveState == CROUCH || m_ProneState == PRONE );
2319
+ heldDevice->SetSupported (m_MoveState == PRONE || m_ProneState == LAYINGPRONE );
2313
2320
m_pBGArm->SetRecoil (Vector (), Vector (), false );
2314
2321
}
2315
2322
}
@@ -2335,7 +2342,7 @@ void AHuman::PreControllerUpdate() {
2335
2342
if (arm && !arm->GetHeldDeviceThisArmIsTryingToSupport ()) {
2336
2343
Leg* legToSwingWith = arm == m_pFGArm ? m_pBGLeg : m_pFGLeg;
2337
2344
Leg* otherLeg = legToSwingWith == m_pBGLeg ? m_pFGLeg : m_pBGLeg;
2338
- if (!legToSwingWith || m_MoveState == JUMP || m_MoveState == CROUCH ) {
2345
+ if (!legToSwingWith || m_MoveState == JUMP || m_MoveState == PRONE ) {
2339
2346
std::swap (legToSwingWith, otherLeg);
2340
2347
}
2341
2348
@@ -2376,10 +2383,8 @@ void AHuman::Update() {
2376
2383
m_SharpAimMaxedOut = true ;
2377
2384
} else if (m_MoveState == WALK) {
2378
2385
maxLength *= 0 .7F ;
2379
- }
2380
-
2381
- // If we're fully crouching, improve our aim a little
2382
- if (m_MaxWalkPathCrouchShift > 0 .0F && m_WalkPathOffset.m_Y * -1 .0F >= m_MaxWalkPathCrouchShift * 0 .9F ) {
2386
+ } else if (m_MoveState == CROUCH) {
2387
+ // Only when crouching still, otherwise it's WALK
2383
2388
maxLength *= 1 .2F ;
2384
2389
}
2385
2390
@@ -2461,9 +2466,9 @@ void AHuman::Update() {
2461
2466
} else {
2462
2467
// Done going down, now stay down without spring.
2463
2468
m_AngularVel *= 0 .5F ;
2464
- m_ProneState = PRONE ;
2469
+ m_ProneState = LAYINGPRONE ;
2465
2470
}
2466
- } else if (m_ProneState == PRONE ) {
2471
+ } else if (m_ProneState == LAYINGPRONE ) {
2467
2472
// If down, try to keep flat against the ground.
2468
2473
if (std::abs (rotDiff) > c_SixteenthPI && std::abs (rotDiff) < c_HalfPI) {
2469
2474
m_AngularVel += rotDiff * 0 .65F ;
@@ -2475,18 +2480,22 @@ void AHuman::Update() {
2475
2480
// Upright body posture
2476
2481
float rotTarget = (GetRotAngleTarget (m_MoveState) * (m_AimAngle > 0 ? 1 .0F - (m_AimAngle / c_HalfPI) : 1 .0F ) * GetFlipFactor ());
2477
2482
2478
- // Lean forwards when crouching
2479
- float crouchAngleAdjust = m_HFlipped ? m_MaxCrouchRotation : -m_MaxCrouchRotation;
2480
- rotTarget += Lerp (0 .0F , m_MaxWalkPathCrouchShift, 0 .0F , crouchAngleAdjust, m_WalkPathOffset.m_Y * -1 .0F );
2481
-
2483
+ if (m_MoveState != CROUCH) {
2484
+ // In crouch state the above is rotated already, but in any other state we do the incremental lean here
2485
+ float crouchAngleAdjust = m_HFlipped ? -m_RotAngleTargets[CROUCH] : m_RotAngleTargets[CROUCH];
2486
+ float difference = crouchAngleAdjust - rotTarget;
2487
+ rotTarget += Lerp (0 .0F , 1 .0F , 0 .0F , difference, m_CrouchAmount);
2488
+ }
2489
+
2482
2490
float rotDiff = rot - rotTarget;
2483
- if (std::abs (rotDiff) > c_HalfPI ) {
2491
+ if (std::abs (rotDiff) > c_PI ) {
2484
2492
// We've h-flipped, so just snap to new orientation
2485
2493
rot = rotTarget;
2486
2494
} else {
2487
2495
// Lerp towards the angle
2488
2496
m_AngularVel = m_AngularVel * (0 .98F - 0 .06F * (m_Health / m_MaxHealth)) - (rotDiff * 0 .5F );
2489
2497
}
2498
+
2490
2499
}
2491
2500
} else if (m_Status == UNSTABLE) {
2492
2501
float rotTarget = 0 ;
0 commit comments