@@ -83,6 +83,7 @@ void AHuman::Clear()
83
83
m_BGArmFlailScalar = 0 .7F ;
84
84
m_EquipHUDTimer.Reset ();
85
85
m_WalkAngle.fill (Matrix ());
86
+ m_ArmSwingRate = 1 .0F ;
86
87
87
88
m_DeviceState = SCANNING;
88
89
m_SweepState = NOSWEEP;
@@ -179,6 +180,7 @@ int AHuman::Create(const AHuman &reference) {
179
180
m_JetAngleRange = reference.m_JetAngleRange ;
180
181
m_FGArmFlailScalar = reference.m_FGArmFlailScalar ;
181
182
m_BGArmFlailScalar = reference.m_BGArmFlailScalar ;
183
+ m_ArmSwingRate = reference.m_ArmSwingRate ;
182
184
183
185
m_pFGHandGroup = dynamic_cast <AtomGroup *>(reference.m_pFGHandGroup ->Clone ());
184
186
m_pFGHandGroup->SetOwner (this );
@@ -253,6 +255,8 @@ int AHuman::ReadProperty(const std::string_view &propName, Reader &reader) {
253
255
reader >> m_FGArmFlailScalar;
254
256
} else if (propName == " BGArmFlailScalar" ) {
255
257
reader >> m_BGArmFlailScalar;
258
+ } else if (propName == " ArmSwingRate" ) {
259
+ reader >> m_ArmSwingRate;
256
260
} else if (propName == " FGArm" ) {
257
261
SetFGArm (dynamic_cast <Arm *>(g_PresetMan.ReadReflectedPreset (reader)));
258
262
} else if (propName == " BGArm" ) {
@@ -352,6 +356,8 @@ int AHuman::Save(Writer &writer) const
352
356
writer << m_FGArmFlailScalar;
353
357
writer.NewProperty (" BGArmFlailScalar" );
354
358
writer << m_BGArmFlailScalar;
359
+ writer.NewProperty (" ArmSwingRate" );
360
+ writer << m_ArmSwingRate;
355
361
writer.NewProperty (" FGArm" );
356
362
writer << m_pFGArm;
357
363
writer.NewProperty (" BGArm" );
@@ -3180,7 +3186,8 @@ void AHuman::Update()
3180
3186
// //////////////////////////////////
3181
3187
// Movement direction
3182
3188
3183
- bool isStill = m_Vel.GetMagnitude () + m_PrevVel.GetMagnitude () < 1 .0F ;
3189
+ bool isStill = (m_Vel + m_PrevVel).GetMagnitude () < 1 .0F ;
3190
+ bool isSharpAiming = m_Controller.IsState (AIM_SHARP);
3184
3191
3185
3192
// If the pie menu is on, try to preserve whatever move state we had before it going into effect.
3186
3193
if (!m_Controller.IsState (PIE_MENU_ACTIVE)) {
@@ -3211,7 +3218,7 @@ void AHuman::Update()
3211
3218
}
3212
3219
3213
3220
// Walk backwards if the aiming is already focused in the opposite direction of travel.
3214
- if (analogAim.GetMagnitude () != 0 || m_Controller. IsState (AIM_SHARP) ) {
3221
+ if (analogAim.GetMagnitude () != 0 || isSharpAiming ) {
3215
3222
m_Paths[FGROUND][m_MoveState].SetHFlip (m_Controller.IsState (MOVE_LEFT));
3216
3223
m_Paths[BGROUND][m_MoveState].SetHFlip (m_Controller.IsState (MOVE_LEFT));
3217
3224
} else if ((m_Controller.IsState (MOVE_RIGHT) && m_HFlipped) || (m_Controller.IsState (MOVE_LEFT) && !m_HFlipped)) {
@@ -3300,14 +3307,14 @@ void AHuman::Update()
3300
3307
// Set the timer to a base number so we don't get a sluggish feeling at start.
3301
3308
if (m_AimState != AIMUP) { m_AimTmr.SetElapsedSimTimeMS (m_AimState == AIMSTILL ? 150 : 300 ); }
3302
3309
m_AimState = AIMUP;
3303
- m_AimAngle += m_Controller. IsState (AIM_SHARP) ? std::min (static_cast <float >(m_AimTmr.GetElapsedSimTimeMS ()) * 0 .00005F , 0 .05F ) : std::min (static_cast <float >(m_AimTmr.GetElapsedSimTimeMS ()) * 0 .00015F , 0 .15F ) * m_Controller.GetDigitalAimSpeed ();
3310
+ m_AimAngle += isSharpAiming ? std::min (static_cast <float >(m_AimTmr.GetElapsedSimTimeMS ()) * 0 .00005F , 0 .05F ) : std::min (static_cast <float >(m_AimTmr.GetElapsedSimTimeMS ()) * 0 .00015F , 0 .15F ) * m_Controller.GetDigitalAimSpeed ();
3304
3311
if (m_AimAngle > m_AimRange) { m_AimAngle = m_AimRange; }
3305
3312
3306
3313
} else if (m_Controller.IsState (AIM_DOWN) && m_Status != INACTIVE) {
3307
3314
// Set the timer to a base number so we don't get a sluggish feeling at start.
3308
3315
if (m_AimState != AIMDOWN) {m_AimTmr.SetElapsedSimTimeMS (m_AimState == AIMSTILL ? 150 : 300 ); }
3309
3316
m_AimState = AIMDOWN;
3310
- m_AimAngle -= m_Controller. IsState (AIM_SHARP) ? std::min (static_cast <float >(m_AimTmr.GetElapsedSimTimeMS ()) * 0 .00005F , 0 .05F ) : std::min (static_cast <float >(m_AimTmr.GetElapsedSimTimeMS ()) * 0 .00015F , 0 .15F ) * m_Controller.GetDigitalAimSpeed ();
3317
+ m_AimAngle -= isSharpAiming ? std::min (static_cast <float >(m_AimTmr.GetElapsedSimTimeMS ()) * 0 .00005F , 0 .05F ) : std::min (static_cast <float >(m_AimTmr.GetElapsedSimTimeMS ()) * 0 .00015F , 0 .15F ) * m_Controller.GetDigitalAimSpeed ();
3311
3318
if (m_AimAngle < -m_AimRange) { m_AimAngle = -m_AimRange; }
3312
3319
3313
3320
} else if (analogAim.GetMagnitude () != 0 && m_Status != INACTIVE) {
@@ -3343,7 +3350,7 @@ void AHuman::Update()
3343
3350
3344
3351
// TODO: make the delay data driven by both the actor and the device!
3345
3352
//
3346
- if (m_Controller. IsState (AIM_SHARP) && m_Status == STABLE && (m_MoveState == STAND || m_MoveState == CROUCH || m_MoveState == NOMOVE || m_MoveState == WALK) && m_Vel.GetMagnitude () < 5 .0F && GetEquippedItem ()) {
3353
+ if (isSharpAiming && m_Status == STABLE && (m_MoveState == STAND || m_MoveState == CROUCH || m_MoveState == NOMOVE || m_MoveState == WALK) && m_Vel.GetMagnitude () < 5 .0F && GetEquippedItem ()) {
3347
3354
float aimMag = analogAim.GetMagnitude ();
3348
3355
3349
3356
// If aim sharp is being done digitally, then translate to full analog aim mag
@@ -3376,8 +3383,14 @@ void AHuman::Update()
3376
3383
3377
3384
ThrownDevice *pThrown = nullptr ;
3378
3385
if (m_pFGArm && m_Status != INACTIVE) {
3379
- // Force arm to idle by reaching toward a virtually inaccessible point.
3380
- m_pFGArm->ReachToward (Vector ());
3386
+ if (m_pBGLeg && m_MoveState == WALK && m_ArmSwingRate > 0 ) {
3387
+ m_pFGArm->ReachToward (m_pFGArm->GetJointPos () + m_pFGArm->GetIdleOffset ().GetXFlipped (m_HFlipped).RadRotate (std::sin (m_pBGLeg->GetRotAngle () + c_HalfPI * GetFlipFactor ()) * m_ArmSwingRate));
3388
+ } else if (m_pFGLeg && m_ArmSwingRate > 0 ) {
3389
+ m_pFGArm->ReachToward (m_pFGArm->GetJointPos () + m_pFGArm->GetIdleOffset ().GetXFlipped (m_HFlipped).RadRotate (std::sin (m_pFGLeg->GetRotAngle () + c_HalfPI * GetFlipFactor ()) * m_ArmSwingRate));
3390
+ } else {
3391
+ // Force arm to idle by reaching toward a virtually inaccessible point.
3392
+ m_pFGArm->ReachToward (Vector ());
3393
+ }
3381
3394
3382
3395
// Activate held device, if it's not a thrown device.
3383
3396
if (m_pFGArm->HoldsHeldDevice () && !m_pFGArm->HoldsThrownDevice ()) {
@@ -3392,22 +3405,23 @@ void AHuman::Update()
3392
3405
else if (m_pFGArm->GetHeldMO ()) {
3393
3406
pThrown = dynamic_cast <ThrownDevice *>(m_pFGArm->GetHeldMO ());
3394
3407
if (pThrown) {
3408
+ pThrown->SetSharpAim (isSharpAiming ? 1 .0F : 0 );
3395
3409
if (m_Controller.IsState (WEAPON_FIRE)) {
3396
3410
if (m_ArmsState != THROWING_PREP) {
3397
3411
m_ThrowTmr.Reset ();
3398
3412
if (!pThrown->ActivatesWhenReleased ()) { pThrown->Activate (); }
3399
3413
}
3400
3414
m_ArmsState = THROWING_PREP;
3401
- m_pFGArm->ReachToward (m_Pos + ( m_pFGArm->GetParentOffset () + pThrown->GetStartThrowOffset ().RadRotate (m_AimAngle + m_AngularVel * deltaTime)) .GetXFlipped (m_HFlipped) * m_Rotation );
3415
+ m_pFGArm->ReachToward (m_pFGArm->GetJointPos () + pThrown->GetStartThrowOffset ().RadRotate (m_AimAngle + m_AngularVel * deltaTime).GetXFlipped (m_HFlipped));
3402
3416
} else if (m_ArmsState == THROWING_PREP) {
3403
3417
m_ArmsState = THROWING_RELEASE;
3404
3418
// TODO: figure out how to properly use EndThrowOffset, since it doesn't play much a role for just one frame!
3405
- m_pFGArm->SetHandPos (m_Pos + ( m_pFGArm->GetParentOffset () + pThrown->GetEndThrowOffset ().RadRotate (adjustedAimAngle)) .GetXFlipped (m_HFlipped) * m_Rotation );
3419
+ m_pFGArm->SetHandPos (m_pFGArm->GetJointPos () + pThrown->GetEndThrowOffset ().RadRotate (adjustedAimAngle).GetXFlipped (m_HFlipped));
3406
3420
3407
3421
MovableObject *pMO = m_pFGArm->ReleaseHeldMO ();
3408
3422
3409
3423
if (pMO) {
3410
- pMO->SetPos (m_Pos + ( m_pFGArm->GetParentOffset () + Vector (m_pFGArm->GetMaxLength (), -m_pFGArm->GetMaxLength () * 0 .5F )). GetXFlipped (m_HFlipped). RadRotate (adjustedAimAngle) * m_Rotation );
3424
+ pMO->SetPos (m_pFGArm->GetJointPos () + Vector (m_pFGArm->GetMaxLength () * GetFlipFactor () , -m_pFGArm->GetMaxLength () * 0 .5F ). RadRotate (adjustedAimAngle));
3411
3425
float maxThrowVel = pThrown->GetMaxThrowVel ();
3412
3426
float minThrowVel = pThrown->GetMinThrowVel ();
3413
3427
if (maxThrowVel == 0 ) {
@@ -3416,8 +3430,7 @@ void AHuman::Update()
3416
3430
minThrowVel = maxThrowVel * 0 .2F ;
3417
3431
}
3418
3432
Vector tossVec (minThrowVel + (maxThrowVel - minThrowVel) * GetThrowProgress (), 0 .5F * RandomNormalNum ());
3419
- tossVec.RadRotate (m_AimAngle);
3420
- pMO->SetVel (tossVec.GetXFlipped (m_HFlipped) * m_Rotation);
3433
+ pMO->SetVel (m_Vel * 0 .5F + tossVec.RadRotate (m_AimAngle).GetXFlipped (m_HFlipped));
3421
3434
pMO->SetAngularVel (m_AngularVel + RandomNum (-5 .0F , 2 .5F ) * GetFlipFactor ());
3422
3435
pMO->SetRotAngle (adjustedAimAngle);
3423
3436
@@ -3436,11 +3449,14 @@ void AHuman::Update()
3436
3449
}
3437
3450
if (pThrown->ActivatesWhenReleased ()) { pThrown->Activate (); }
3438
3451
m_ThrowTmr.Reset ();
3452
+ } else {
3453
+ m_pFGArm->ReachToward (m_pFGArm->GetJointPos () + pThrown->GetStanceOffset ().RadRotate (adjustedAimAngle));
3439
3454
}
3440
3455
}
3441
3456
} else if (m_ArmsState == THROWING_RELEASE && m_ThrowTmr.GetElapsedSimTimeMS () > 100 ) {
3442
3457
m_pFGArm->SetHeldMO (SwapNextInventory ());
3443
3458
m_pFGArm->SetHandPos (m_Pos + m_HolsterOffset.GetXFlipped (m_HFlipped));
3459
+ EquipShieldInBGArm ();
3444
3460
m_ArmsState = WEAPON_READY;
3445
3461
} else if (m_ArmsState == THROWING_RELEASE) {
3446
3462
m_pFGArm->SetHandPos (m_Pos + (m_HolsterOffset + Vector (15 , -15 )).GetXFlipped (m_HFlipped));
@@ -3546,7 +3562,7 @@ void AHuman::Update()
3546
3562
// Try to detect a new item
3547
3563
if (m_pFGArm && m_Status == STABLE) {
3548
3564
reach += m_pFGArm->GetMaxLength ();
3549
- reachPoint = m_pFGArm->GetPos () + m_pFGArm-> GetJointOffset (). GetXFlipped (m_HFlipped). RadRotate (m_pFGArm-> GetRotAngle () );
3565
+ reachPoint = m_pFGArm->GetJointPos ( );
3550
3566
if (!m_pItemInReach) {
3551
3567
MOID itemMOID = g_SceneMan.CastMORay (reachPoint, Vector (reach * RandomNum (), 0 ).RadRotate (GetAimAngle (true ) + RandomNum (-c_HalfPI, 0 .0F ) * GetFlipFactor ()), m_MOID, Activity::NoTeam, g_MaterialGrass, true , 2 );
3552
3568
@@ -3837,23 +3853,31 @@ void AHuman::Update()
3837
3853
m_pBGArm->ReachToward (m_pBGHandGroup->GetLimbPos (m_HFlipped));
3838
3854
3839
3855
} else {
3840
- if (HeldDevice * heldDevice = dynamic_cast <HeldDevice *>(GetEquippedItem ())) {
3856
+ HeldDevice *heldDevice = dynamic_cast <HeldDevice *>(GetEquippedItem ());
3857
+ ThrownDevice *thrownDevice = dynamic_cast <ThrownDevice *>(heldDevice);
3858
+ if (thrownDevice && (m_ArmsState == THROWING_PREP || isSharpAiming)) {
3859
+ m_pBGArm->ReachToward (m_pBGArm->GetJointPos () + thrownDevice->GetEndThrowOffset ().RadRotate (m_AimAngle).GetXFlipped (m_HFlipped));
3860
+ } else if (heldDevice) {
3841
3861
if (GetEquippedBGItem () && !heldDevice->IsOneHanded ()) {
3842
3862
UnequipBGArm ();
3843
3863
} else {
3844
- m_pBGArm->Reach (m_pFGArm-> GetHeldDevice () ->GetSupportPos ());
3864
+ m_pBGArm->Reach (heldDevice ->GetSupportPos ());
3845
3865
if (m_pBGArm->DidReach ()) {
3846
- m_pFGArm-> GetHeldDevice () ->SetSupported (true );
3847
- m_pBGArm->SetRecoil (m_pFGArm-> GetHeldDevice ()-> GetRecoilForce (), m_pFGArm-> GetHeldDevice ()-> GetRecoilOffset (), m_pFGArm-> GetHeldDevice () ->IsRecoiled ());
3866
+ heldDevice ->SetSupported (true );
3867
+ m_pBGArm->SetRecoil (heldDevice-> GetRecoilForce (), heldDevice-> GetRecoilOffset (), heldDevice ->IsRecoiled ());
3848
3868
} else {
3849
3869
// BGArm did not reach to support the device. Count device as supported anyway, if crouching.
3850
- m_pFGArm-> GetHeldDevice () ->SetSupported (m_MoveState == CROUCH || m_ProneState == PRONE);
3870
+ heldDevice ->SetSupported (m_MoveState == CROUCH || m_ProneState == PRONE);
3851
3871
m_pBGArm->SetRecoil (Vector (), Vector (), false );
3852
3872
}
3853
3873
}
3874
+ } else if (m_pFGLeg && m_MoveState == WALK && m_ArmSwingRate > 0 ) {
3875
+ m_pBGArm->ReachToward (m_pBGArm->GetJointPos () + m_pBGArm->GetIdleOffset ().GetXFlipped (m_HFlipped).RadRotate (std::sin (m_pFGLeg->GetRotAngle () + c_HalfPI * GetFlipFactor ()) * m_ArmSwingRate));
3876
+ } else if (m_pBGLeg && m_ArmSwingRate > 0 ) {
3877
+ m_pBGArm->ReachToward (m_pBGArm->GetJointPos () + m_pBGArm->GetIdleOffset ().GetXFlipped (m_HFlipped).RadRotate (std::sin (m_pBGLeg->GetRotAngle () + c_HalfPI * GetFlipFactor ()) * m_ArmSwingRate));
3854
3878
} else {
3855
- // Use an unreachable position to force this arm to idle, so it wont bug out where the AtomGroup was left off
3856
- m_pBGArm->Reach (Vector ());
3879
+ // Force arm to idle by reaching toward a virtually inaccessible point.
3880
+ m_pBGArm->ReachToward (Vector ());
3857
3881
}
3858
3882
}
3859
3883
} else {
@@ -3981,8 +4005,8 @@ void AHuman::Update()
3981
4005
}
3982
4006
3983
4007
// Rotational balancing spring calc
3984
- if (m_Status == STABLE)
3985
- {
4008
+ if (m_Status == STABLE) {
4009
+
3986
4010
// If we're supposed to be laying down on the ground, make the spring pull the body that way until we reach that angle
3987
4011
if (m_ProneState != NOTPRONE)
3988
4012
{
@@ -4066,34 +4090,28 @@ void AHuman::Update()
4066
4090
// ////////////////////////////////////////////////////////////////////////////////////////
4067
4091
4068
4092
void AHuman::DrawThrowingReticle (BITMAP *targetBitmap, const Vector &targetPos, float progressScalar) const {
4069
- const int pointCount = 9 ;
4070
- Vector points[pointCount];
4071
- // Color colors[pointCount];
4093
+ const int pointCount = 9 ;
4094
+ Vector points[pointCount];
4072
4095
4073
4096
for (int index = 0 ; index < pointCount; index++) {
4074
4097
points[index].SetXY (static_cast <float >(index * 4 ), 0 .0F );
4075
- // colors[index].SetRGB(255 - index * 3, 225 - index * 20, index);
4076
4098
}
4099
+ Vector outOffset (m_pFGArm->GetMaxLength () * GetFlipFactor (), -m_pFGArm->GetMaxLength () * 0 .5F );
4100
+ float adjustedAimAngle = m_AimAngle * GetFlipFactor ();
4077
4101
4078
- Vector outOffset (15 .0F * GetFlipFactor (), -5 .0F );
4079
-
4080
- acquire_bitmap (targetBitmap);
4081
-
4082
- for (int i = 0 ; i < pointCount * progressScalar; ++i) {
4083
- points[i].FlipX (m_HFlipped);
4084
- points[i] += outOffset;
4085
- points[i].RadRotate ((m_AimAngle * GetFlipFactor ()) + m_Rotation.GetRadAngle ());
4086
- points[i] += m_Pos;
4087
- if (m_pFGArm)
4088
- points[i] += m_pFGArm->GetParentOffset ();
4102
+ acquire_bitmap (targetBitmap);
4089
4103
4090
- // Put the flickering glows on the reticle dots, in absolute scene coordinates
4091
- g_PostProcessMan.RegisterGlowDotEffect (points[i], YellowDot, 55 + RandomNum (0 , 100 ));
4104
+ for (int i = 0 ; i < pointCount * progressScalar; ++i) {
4105
+ points[i].FlipX (m_HFlipped);
4106
+ points[i] += outOffset;
4107
+ points[i].RadRotate (adjustedAimAngle);
4108
+ points[i] += m_pFGArm->GetJointPos ();
4092
4109
4093
- putpixel (targetBitmap, points[i].GetFloorIntX () - targetPos.GetFloorIntX (), points[i].GetFloorIntY () - targetPos.GetFloorIntY (), g_YellowGlowColor);
4094
- }
4110
+ g_PostProcessMan.RegisterGlowDotEffect (points[i], YellowDot, RandomNum (63 , 127 ));
4111
+ putpixel (targetBitmap, points[i].GetFloorIntX () - targetPos.GetFloorIntX (), points[i].GetFloorIntY () - targetPos.GetFloorIntY (), g_YellowGlowColor);
4112
+ }
4095
4113
4096
- release_bitmap (targetBitmap);
4114
+ release_bitmap (targetBitmap);
4097
4115
}
4098
4116
4099
4117
// ////////////////////////////////////////////////////////////////////////////////////////
0 commit comments