2130 lines
84 KiB
C++
2130 lines
84 KiB
C++
#include "audio/northaudioengine.h"
|
|
#include "audio/scriptaudioentity.h"
|
|
#include "audioengine/engine.h"
|
|
#include "PedFootstepHelper.h"
|
|
#include "Peds/Ped.h"
|
|
#include "peds/pedintelligence.h"
|
|
#include "Physics/archetype.h"
|
|
#include "Physics/gtaInst.h"
|
|
#include "physics/physics.h"
|
|
#include "task/Weapons/Gun/TaskGun.h"
|
|
#include "scene/playerswitch/PlayerSwitchInterface.h"
|
|
#include "system/timer.h"
|
|
#include "fwanimation/animdefines.h"
|
|
#include "fwanimation/expressionsets.h"
|
|
#include "fwmaths/vectorutil.h"
|
|
#include "control/replay/replay.h"
|
|
#include "task/Vehicle/TaskEnterVehicle.h"
|
|
#include "task/Vehicle/TaskExitVehicle.h"
|
|
|
|
#include "PhBound/boundcomposite.h"
|
|
PED_OPTIMISATIONS()
|
|
// Footsteps timers
|
|
PF_PAGE(Ped_Audio_Timers, "audPedAudioEntity");
|
|
PF_GROUP(PedAudioEntity);
|
|
PF_LINK(Ped_Audio_Timers, PedAudioEntity);
|
|
PF_TIMER(UpdateFootSteps,PedAudioEntity);
|
|
PF_TIMER(PreUpdateFootstepGTest,PedAudioEntity);
|
|
PF_TIMER(UpdateFootstepGTest,PedAudioEntity);
|
|
PF_TIMER(ProcessAsyncLineTProbes,PedAudioEntity);
|
|
PF_TIMER(IssueAsyncLineTProbes,PedAudioEntity);
|
|
PF_TIMER(GetRes,PedAudioEntity);
|
|
|
|
#if __BANK
|
|
f32 CPedFootStepHelper::sm_FUpOffset = 0.f;
|
|
f32 CPedFootStepHelper::sm_FFrontOffset = 0.f;
|
|
f32 CPedFootStepHelper::sm_RUpOffset = 0.f;
|
|
f32 CPedFootStepHelper::sm_RFrontOffset = 0.f;
|
|
|
|
f32 CPedFootStepHelper::sm_OverriddenMovementFactor = 0.f;
|
|
f32 CPedFootStepHelper::sm_OverriddenSlopeAngle = 0.f;
|
|
|
|
bool CPedFootStepHelper::sm_OverrideSlopeAngle = false;
|
|
bool CPedFootStepHelper::sm_ShowSlopeInfo = false;
|
|
bool CPedFootStepHelper::sm_OverrideSlopeVariables = false;
|
|
bool CPedFootStepHelper::sm_OverrideFOffsets = false;
|
|
bool CPedFootStepHelper::sm_OverrideROffsets = false;
|
|
bool CPedFootStepHelper::sm_ApplyHeelsOffsets = false;
|
|
bool CPedFootStepHelper::sm_ApplyHighHeelsOffsets = false;
|
|
bool CPedFootStepHelper::sm_DrawHLODResults = false;
|
|
bool CPedFootStepHelper::sm_DrawFeetPosition = false;
|
|
bool CPedFootStepHelper::sm_DrawFeetVelocity = false;
|
|
|
|
bool CPedFootStepHelper::sm_OnlyUpdateFLFoot = false;
|
|
bool CPedFootStepHelper::sm_OnlyUpdateFRFoot = false;
|
|
bool CPedFootStepHelper::sm_OnlyUpdateRLFoot = false;
|
|
bool CPedFootStepHelper::sm_OnlyUpdateRRFoot = false;
|
|
|
|
bool CPedFootStepHelper::sm_DrawResults = false;
|
|
bool CPedFootStepHelper::sm_ForceSyncProbesToAllPeds = false;
|
|
bool CPedFootStepHelper::sm_DrawDebugInfo = false;
|
|
bool CPedFootStepHelper::sm_ShowPedSpeed = false;
|
|
|
|
bool CPedFootStepHelper::sm_ShowFootStepTuningInfo = false;
|
|
bool CPedFootStepHelper::sm_PauseOnLimits = false;
|
|
bool CPedFootStepHelper::sm_PauseOnFootstepEvents = false;
|
|
bool CPedFootStepHelper::sm_PauseOnDragEvents = false;
|
|
#endif
|
|
|
|
atRangeArray<pedHLODInfo,NumQuadrants> CPedFootStepHelper::sm_HLODPeds;
|
|
atRangeArray<f32,NUM_SHOETYPES> CPedFootStepHelper::sm_ShoesFitness;
|
|
|
|
audCurve CPedFootStepHelper::sm_DistanceToHLODFitness;
|
|
audCurve CPedFootStepHelper::sm_PlayerClumsinessToScuffProb;
|
|
audCurve CPedFootStepHelper::sm_SlopeAngleToDeltaSpeed;
|
|
|
|
bank_u32 g_TimeToResetStairsFlagThreshold = 250;
|
|
f32 CPedFootStepHelper::sm_DeltaAimSpeed = 1.15f;
|
|
f32 CPedFootStepHelper::sm_NonPlayerBoneSpeedScalar = 1.15f;
|
|
f32 CPedFootStepHelper::sm_SprintBoneSpeedScalar = 0.65f;
|
|
f32 CPedFootStepHelper::sm_MaxBoneSpeedDecrease = 0.05f;
|
|
f32 CPedFootStepHelper::sm_MaxBoneVelocityInv = 1.0f / 0.050f;
|
|
|
|
f32 CPedFootStepHelper::sm_HeelUpOffset = 0.085f;
|
|
f32 CPedFootStepHelper::sm_HeelFrontOffset = -0.034f;
|
|
f32 CPedFootStepHelper::sm_HighHeelFrontOffset = -0.026f;
|
|
f32 CPedFootStepHelper::sm_HighHeelUpOffset = 0.129f;
|
|
|
|
f32 CPedFootStepHelper::sm_RunFitnessScale = 1.5f;
|
|
f32 CPedFootStepHelper::sm_AnimalFitnessScale = 0.5f;
|
|
f32 CPedFootStepHelper::sm_StairsDeltaSpeed = 1.5f;
|
|
f32 CPedFootStepHelper::sm_UpDistaneToTriggerLift = 0.1f;
|
|
|
|
|
|
f32 CPedFootStepHelper::sm_TriggerScuffThresh = 0.9f;
|
|
ScalarV CPedFootStepHelper::sm_DistanceThresholdSqToUpdateFootsteps = ScalarV(550);
|
|
ScalarV CPedFootStepHelper::sm_DistanceThresholdSqToUpdateFootstepsNetworkPlayer = ScalarV(2500);// 50*50 Note: may need to be larger than the distance you care about, for possibly measuring distance to the camera, and because footstep events don't get generated every frame.
|
|
f32 CPedFootStepHelper::sm_FootStepLineTestStartOffset = 0.896f;
|
|
f32 CPedFootStepHelper::sm_FootStepLineTestLong = 0.216f;
|
|
f32 CPedFootStepHelper::sm_FootStepHeightThreshold = 0.3f;
|
|
s32 CPedFootStepHelper::sm_NumIntersections = 1;
|
|
f32 CPedFootStepHelper::sm_SlopeDAngleThreshold = 12.5f;
|
|
f32 CPedFootStepHelper::sm_SlopeDebrisProb = 0.3f;
|
|
|
|
u32 CPedFootStepHelper::sm_NumberOfTestResultStored = 0;
|
|
u32 CPedFootStepHelper::sm_DeltaTimeToResetLadders = 1000;
|
|
|
|
bool CPedFootStepHelper::sm_AsyncProbesGroundTest = true;
|
|
bool CPedFootStepHelper::sm_SyncProbesGroundTest = false;
|
|
bool CPedFootStepHelper::sm_UseProceduralFootsteps = true;
|
|
bool CPedFootStepHelper::sm_WasPlayerSwitchActive = false;
|
|
bool CPedFootStepHelper::sm_IsWalkingOnPuddle = false;
|
|
|
|
atRangeArray<groundFootStepTest,MAX_NUMBER_OF_GROUND_FOOTSTEPS_TESTS> CPedFootStepHelper::sm_GroundFootStepTests;
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
CPedFootStepHelper::CPedFootStepHelper()
|
|
{
|
|
m_HasIkResultsThisFrame = false;
|
|
m_pParentPed = NULL;
|
|
m_WasOnStairs = false;
|
|
m_AlreadyLanded = false;
|
|
m_TimeToResetStairsFlag = 0;
|
|
m_TimeToResetLaddersFlag = 0;
|
|
m_IsWalkingOnSlope = false;
|
|
m_SlopeAngle = 0.f;
|
|
m_PrevHeight = 0.f;
|
|
for(u8 i = 0; i < MAX_NUM_FEET; i ++)
|
|
{
|
|
m_FootHeightState[i] = kHeightDown;
|
|
m_FootMoveState[i] = kMovePlanted;
|
|
m_LastTimeFootPlanted[i] = 0;
|
|
m_GroundPosition[i] = Vec3V(V_ZERO);
|
|
m_GroundNormal[i] = Vec3V(V_ZERO);
|
|
m_FeetOffsets[i].front = 0.f;
|
|
m_FeetOffsets[i].up = 0.f;
|
|
}
|
|
for(u8 i = 0; i < MaxFeetTags - 1; i ++)
|
|
{
|
|
m_FeetInfo[i] = Vec4V(V_ZERO);
|
|
}
|
|
for(u8 i = 0; i < MaxNumberAudDetValues; i ++)
|
|
{
|
|
m_DetectionValuesIndices[i] = 0;
|
|
}
|
|
m_AlreadyLifted.Reset();
|
|
m_AlreadyTriggered.Reset();
|
|
m_ScuffAlreadyTriggered.Reset();
|
|
m_WasClimbingLadder.Reset();
|
|
m_WasInTheAir.Reset();
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::InitClass()
|
|
{
|
|
for (s32 i = 0 ; i < MAX_NUMBER_OF_GROUND_FOOTSTEPS_TESTS; ++i)
|
|
{
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].numberOfHits = 0;
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].lastNumberOfHits = 0;
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].height = -5000;
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].groundPos = Vec3V(V_ZERO);
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].groundNormal = Vec3V(V_ZERO);
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].entity = NULL;
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].component = 0;
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].materialId = phMaterialMgr::DEFAULT_MATERIAL_ID;
|
|
|
|
}
|
|
sysMemSet(&sm_HLODPeds, 0, sizeof(sm_HLODPeds));
|
|
sysMemSet(&sm_ShoesFitness, 0, sizeof(sm_ShoesFitness));
|
|
sm_DistanceToHLODFitness.Init(ATSTRINGHASH("PED_DISTANCE_TO_FITNESS", 0xECD21958));
|
|
sm_PlayerClumsinessToScuffProb.Init(ATSTRINGHASH("PLAYER_CLUMSINESS_TO_SCUFF_PROB", 0x32D04003));
|
|
sm_SlopeAngleToDeltaSpeed.Init(ATSTRINGHASH("SLOPE_ANGLE_TO_DELTA_SPEED", 0x433F362F));
|
|
sm_WasPlayerSwitchActive = false;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::SetGroundInfo(u32 legId,Vec3V_In groundPos,Vec3V_In groundNormal)
|
|
{
|
|
m_HasIkResultsThisFrame = true;
|
|
m_GroundPosition[legId] = groundPos;
|
|
m_GroundNormal[legId] = groundNormal;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::ComputeFootInfo(FeetTags footId,Mat34V_InOut footMtx, Vec3V_InOut footVel,f32 upOffset,f32 frontOffset)
|
|
{
|
|
eAnimBoneTag boneTag = BONETAG_ROOT;
|
|
switch(footId)
|
|
{
|
|
case LeftFoot:
|
|
boneTag = BONETAG_L_PH_FOOT;
|
|
break;
|
|
case RightFoot:
|
|
boneTag = BONETAG_R_PH_FOOT;
|
|
break;
|
|
case LeftHand:
|
|
boneTag = BONETAG_L_PH_HAND;
|
|
break;
|
|
case RightHand:
|
|
boneTag = BONETAG_R_PH_HAND;
|
|
break;
|
|
default:
|
|
footMtx = Mat34V(V_IDENTITY);
|
|
footMtx.SetCol3(m_pParentPed->GetTransform().GetPosition());
|
|
return;
|
|
}
|
|
if ( IsAnAnimal())
|
|
{
|
|
// don't apply offsets on animals.
|
|
upOffset = frontOffset = 0.f;
|
|
}
|
|
Vec3V footPos = Vec3V(V_ZERO);
|
|
crSkeleton& skel = *m_pParentPed->GetSkeleton();
|
|
const crSkeletonData& skelData = skel.GetSkeletonData();
|
|
s32 iBoneIndex;
|
|
if (skelData.ConvertBoneIdToIndex((u16)boneTag, iBoneIndex))
|
|
{
|
|
footMtx = skel.GetObjectMtx(iBoneIndex);
|
|
naAssertf(IsFiniteAll(footMtx),"Wrong foot matrix.");
|
|
Mat34V_ConstRef mPedMat = m_pParentPed->GetMatrixRef();
|
|
Matrix34 footMx34 = MAT34V_TO_MATRIX34(footMtx);
|
|
footMx34.Dot(MAT34V_TO_MATRIX34(mPedMat));
|
|
footMtx = MATRIX34_TO_MAT34V(footMx34);
|
|
footPos = footMtx.GetCol3Ref();
|
|
footPos = Subtract(footPos,footMtx.GetCol2() * ScalarV(upOffset));
|
|
footPos = Add(footPos,footMtx.GetCol1() * ScalarV(frontOffset));
|
|
}
|
|
footVel = Subtract(footPos, m_FeetInfo[footId].GetXYZ()) * TIME.GetInvSecondsV();
|
|
footMtx.SetCol3(footPos);
|
|
|
|
#if __BANK
|
|
if(sm_DrawFeetPosition)
|
|
{
|
|
grcDebugDraw::Axis(footMtx, 1.0f, false, 1);
|
|
}
|
|
if(sm_DrawFeetVelocity)
|
|
{
|
|
grcDebugDraw::Line(footPos, m_FeetInfo[footId].GetXYZ(), Color32(1.0f, 0.0f, 0.0f, 1.0f));
|
|
}
|
|
#endif
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::FootstepGroundTest(Vec3V_InOut groundPosition,Vec3V_InOut groundNormal)
|
|
{
|
|
PreUpdateFootstepGroundTest(groundPosition, groundNormal);
|
|
if(!m_HasResultThisFrame)
|
|
{
|
|
// Check if the height of the ped pass our test with some of the results that we already have.
|
|
s32 testIndex = -1 ;
|
|
const Matrix34 &rootMatrix = MAT34V_TO_MATRIX34(m_pParentPed->GetTransform().GetMatrix());
|
|
if(CPedFootStepHelper::sm_NumberOfTestResultStored > 0)
|
|
{
|
|
for(s32 i = 0; i < MAX_NUMBER_OF_GROUND_FOOTSTEPS_TESTS; ++i)
|
|
{
|
|
if(testIndex == -1 && (fabs(rootMatrix.d.GetZ() - CPedFootStepHelper::sm_GroundFootStepTests[i].height) <= sm_FootStepHeightThreshold))
|
|
{
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].numberOfHits ++;
|
|
testIndex = i;
|
|
}
|
|
}
|
|
}
|
|
//If we found a good solution, use it.
|
|
if (testIndex != -1)
|
|
{
|
|
#if __BANK
|
|
if(sm_DrawDebugInfo)
|
|
{
|
|
Vector3 headPos = m_pParentPed->GetBonePositionCached(BONETAG_HEAD);
|
|
|
|
grcDebugDraw::Sphere(headPos + Vector3(0.f,0.f,1.f),0.2f,Color_yellow,true);
|
|
}
|
|
#endif
|
|
groundPosition = CPedFootStepHelper::sm_GroundFootStepTests[testIndex].groundPos;
|
|
groundNormal = CPedFootStepHelper::sm_GroundFootStepTests[testIndex].groundNormal;
|
|
if(m_pParentPed->GetPedAudioEntity())
|
|
{
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().SetStandingMaterial(CPedFootStepHelper::sm_GroundFootStepTests[testIndex].materialId
|
|
, CPedFootStepHelper::sm_GroundFootStepTests[testIndex].entity, CPedFootStepHelper::sm_GroundFootStepTests[testIndex].component);
|
|
}
|
|
}
|
|
// We didn't get any good result but we have some of them stored.
|
|
else
|
|
{
|
|
SyncProbesFromFeetGroundTest(groundPosition, groundNormal);
|
|
}
|
|
}
|
|
m_HasResultThisFrame = false;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
ScalarV_Out CPedFootStepHelper::GetFootVelocity(const FeetTags footId) const
|
|
{
|
|
naAssertf(footId < (MaxFeetTags - 1), "boneId id out of bounds of m_BoneLocalNormalisedSpeeds[]");
|
|
return m_FeetInfo[footId].GetW();
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
Vec3V_Out CPedFootStepHelper::GetHeelPosition(const FeetTags footId) const
|
|
{
|
|
naAssertf(footId < (MaxFeetTags - 1), "boneId id out of bounds of m_BoneLocalNormalisedSpeeds[]");
|
|
return m_FeetInfo[footId].GetXYZ();
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::CalculateFootInfo(FeetTags footId, Mat34V_InOut footMtx, Vec3V_InOut footVel)
|
|
{
|
|
// default the foot info
|
|
footVel = Vec3V(V_ZERO);
|
|
footMtx = Mat34V(V_IDENTITY);
|
|
if(Verifyf(m_pParentPed,"Null ped pointer, can't calculate foot info"))
|
|
{
|
|
f32 upOffset = m_FeetOffsets[footId].up;
|
|
f32 frontOffset = m_FeetOffsets[footId].front;
|
|
// Correct the heels position.
|
|
if(m_pParentPed->GetPedAudioEntity())
|
|
{
|
|
if( m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().IsWearingHeels())
|
|
{
|
|
upOffset = m_FeetOffsets[footId].up + sm_HeelUpOffset;
|
|
frontOffset = m_FeetOffsets[footId].front + sm_HeelFrontOffset;
|
|
}
|
|
else if ( m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().IsWearingHighHeels())
|
|
{
|
|
upOffset = m_FeetOffsets[footId].up + sm_HighHeelUpOffset;
|
|
frontOffset = m_FeetOffsets[footId].front + sm_HighHeelFrontOffset;
|
|
}
|
|
}
|
|
#if __BANK
|
|
if(sm_ApplyHeelsOffsets && (footId == RearLeft || footId == RearRight))
|
|
{
|
|
upOffset = m_FeetOffsets[footId].up + sm_HeelUpOffset;
|
|
frontOffset = m_FeetOffsets[footId].front + sm_HeelFrontOffset;
|
|
}
|
|
else if (sm_ApplyHighHeelsOffsets && (footId == RearLeft || footId == RearRight))
|
|
{
|
|
upOffset = m_FeetOffsets[footId].up + sm_HighHeelUpOffset;
|
|
frontOffset = m_FeetOffsets[footId].front + sm_HighHeelFrontOffset;
|
|
}
|
|
if(sm_OverrideROffsets && (footId == RearLeft || footId == RearRight))
|
|
{
|
|
upOffset = sm_RUpOffset;
|
|
frontOffset = sm_RFrontOffset;
|
|
}
|
|
else if ( sm_OverrideFOffsets && (footId == FrontLeft || footId == FrontRight))
|
|
{
|
|
upOffset = sm_FUpOffset;
|
|
frontOffset = sm_FFrontOffset;
|
|
}
|
|
#endif
|
|
ComputeFootInfo(footId,footMtx, footVel, upOffset, frontOffset);
|
|
m_FeetInfo[footId] = Vec4V(Vec::V4PermuteTwo<Vec::X1,Vec::Y1,Vec::Z1,Vec::X2>( footMtx.GetCol3().GetIntrin128(), Mag(footVel).GetIntrin128() ));
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::UpdateHandPositions()
|
|
{
|
|
Mat34V handMtx = Mat34V(V_IDENTITY);
|
|
Vec3V handVel= Vec3V(V_ZERO);
|
|
// default the foot info
|
|
if(Verifyf(m_pParentPed,"Null ped pointer, can't calculate foot info"))
|
|
{
|
|
f32 upOffset = m_FeetOffsets[LeftHand].up;
|
|
f32 frontOffset = m_FeetOffsets[LeftHand].front;
|
|
#if __BANK
|
|
if ( sm_OverrideFOffsets)
|
|
{
|
|
upOffset = sm_FUpOffset;
|
|
frontOffset = sm_FFrontOffset;
|
|
}
|
|
#endif
|
|
ComputeFootInfo(LeftHand,handMtx, handVel, upOffset, frontOffset);
|
|
m_FeetInfo[LeftHand] = Vec4V(Vec::V4PermuteTwo<Vec::X1,Vec::Y1,Vec::Z1,Vec::X2>( handMtx.GetCol3().GetIntrin128(), Mag(handVel).GetIntrin128() ));
|
|
upOffset = m_FeetOffsets[RightHand].up;
|
|
frontOffset = m_FeetOffsets[RightHand].front;
|
|
#if __BANK
|
|
if ( sm_OverrideFOffsets)
|
|
{
|
|
upOffset = sm_FUpOffset;
|
|
frontOffset = sm_FFrontOffset;
|
|
}
|
|
#endif
|
|
ComputeFootInfo(RightHand,handMtx, handVel, upOffset, frontOffset);
|
|
m_FeetInfo[RightHand] = Vec4V(Vec::V4PermuteTwo<Vec::X1,Vec::Y1,Vec::Z1,Vec::X2>( handMtx.GetCol3().GetIntrin128(), Mag(handVel).GetIntrin128() ));
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::GetPositionForPedSound(audFootstepEvent event, Vec3V_InOut pos)
|
|
{
|
|
GetPositionForPedSound(GetFeetTagForFootstepEvent(event), pos);
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::GetPositionForPedSound(FeetTags tag, Vec3V_InOut pos)
|
|
{
|
|
// if the ped is culled for rendering then the skeleton isn't posed, and the bone positions never update
|
|
if(m_pParentPed->GetIsVisibleInSomeViewportThisFrame())
|
|
{
|
|
switch(tag)
|
|
{
|
|
case RearLeft:
|
|
pos = m_FeetInfo[LeftFoot].GetXYZ();
|
|
break;
|
|
case FrontLeft:
|
|
pos = m_FeetInfo[LeftHand].GetXYZ();
|
|
break;
|
|
case FrontRight:
|
|
pos = m_FeetInfo[RightHand].GetXYZ();
|
|
break;
|
|
case RearRight:
|
|
pos = m_FeetInfo[RightFoot].GetXYZ();
|
|
break;
|
|
case ExtraMouth:
|
|
pos = m_pParentPed->GetBonePositionCachedV(BONETAG_HEAD);
|
|
break;
|
|
default:
|
|
naAssertf(false,"Bad feet tag %d, defaulting position to ped pos.",tag);
|
|
pos = m_pParentPed->GetTransform().GetPosition();
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pos = m_pParentPed->GetTransform().GetPosition();
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
FeetTags CPedFootStepHelper::GetFeetTagForFootstepEvent(const audFootstepEvent event) const
|
|
{
|
|
switch(event)
|
|
{
|
|
case AUD_FOOTSTEP_WALK_L:
|
|
case AUD_FOOTSTEP_SCUFFHARD_L:
|
|
case AUD_FOOTSTEP_SCUFF_L:
|
|
case AUD_FOOTSTEP_LADDER_L:
|
|
case AUD_FOOTSTEP_LADDER_L_UP:
|
|
case AUD_FOOTSTEP_JUMP_LAND_L:
|
|
case AUD_FOOTSTEP_RUN_L:
|
|
case AUD_FOOTSTEP_SPRINT_L:
|
|
return RearLeft;
|
|
case AUD_FOOTSTEP_HAND_L:
|
|
case AUD_FOOTSTEP_LADDER_HAND_L:
|
|
return FrontLeft;
|
|
case AUD_FOOTSTEP_HAND_R:
|
|
case AUD_FOOTSTEP_LADDER_HAND_R:
|
|
return FrontRight;
|
|
default:
|
|
return RearRight;
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
ScalarV CPedFootStepHelper::GetDistanceThresholdSqToUpdateFootSteps(const CPed& ped)
|
|
{
|
|
// It's important in MP that remote players generate noise from far enough away -
|
|
// not for the actual audio, but so that CPlayerInfo::ReportStealthNoise() gets called
|
|
// and the player gets blipped on the radar. So, we use a larger threshold value for that case.
|
|
|
|
if(NetworkInterface::IsGameInProgress() && ped.IsAPlayerPed())
|
|
{
|
|
return sm_DistanceThresholdSqToUpdateFootstepsNetworkPlayer;
|
|
}
|
|
else
|
|
{
|
|
return sm_DistanceThresholdSqToUpdateFootsteps;
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::Init(CPed * pParentPed)
|
|
{
|
|
m_pParentPed = pParentPed;
|
|
m_UpDiffWihtGround = 1.f;
|
|
for(u8 i = 0; i < MAX_NUM_FEET; i ++)
|
|
{
|
|
m_FootHeightState[i] = kHeightDown;
|
|
m_FootMoveState[i] = kMovePlanted;
|
|
m_LastTimeFootPlanted[i] = 0;
|
|
m_GroundPosition[i] = Vec3V(V_ZERO);
|
|
m_GroundNormal[i] = Vec3V(V_ZERO);
|
|
m_FeetOffsets[i].front = 0.f;
|
|
m_FeetOffsets[i].up = 0.f;
|
|
}
|
|
for(u8 i = 0; i < MaxFeetTags - 1; i ++)
|
|
{
|
|
m_FeetInfo[i] = Vec4V(V_ZERO);
|
|
}
|
|
for(u8 i = 0; i < MaxNumberAudDetValues; i ++)
|
|
{
|
|
m_DetectionValuesIndices[i] = 0;
|
|
}
|
|
m_AlreadyLifted.Reset();
|
|
m_AlreadyTriggered.Reset();
|
|
m_ScuffAlreadyTriggered.Reset();
|
|
m_WasClimbingLadder.Reset();
|
|
m_WasInTheAir.Reset();
|
|
|
|
m_pModPhys = NULL;
|
|
m_HasToInitGroundTest = true;
|
|
m_UpDiffWihtGround = 1.f;
|
|
m_LastTimeOnGround = 0;
|
|
m_TimeInTheAir = 0;
|
|
m_ScriptStepType = AUD_FOOTSTEP_WALK_L;
|
|
m_ScriptDetectionValuesIdx = audDVWalk;
|
|
|
|
m_AccCosAngle = 0.f;
|
|
m_PrevCosAngle = 0.f;
|
|
|
|
m_LastTimeSoftStepPlayed = 0;
|
|
m_LastEvent = AUD_FOOTSTEP_SOFT_L;
|
|
|
|
m_ScriptForceStepType = false;
|
|
m_ScriptForceUpdate = false;
|
|
m_VfxWantsToUpdate = false;
|
|
m_IsAudioHLOD = false;
|
|
m_IsPlayingSwitchScene = false;
|
|
m_SlidingDownALadder = false;
|
|
m_ClimbingLadder = false;
|
|
m_ApplyHeelOffsets = false;
|
|
m_ApplyHighHeelOffsets = false;
|
|
m_PedVelocitySmoother.Init(1.0f,1.0f,0.0,10.f);
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::SetSlidingDownALadder()
|
|
{
|
|
if(m_pModPhys)
|
|
{
|
|
for(u32 i = 0; i < m_pModPhys->NumFeet ; i++)
|
|
{
|
|
m_WasClimbingLadder.Set(i);
|
|
m_FootMoveState[i] = kMoveMoving;
|
|
m_AlreadyTriggered.Clear(i);
|
|
m_AlreadyLifted.Clear(i);
|
|
m_LastTimeFootPlanted[i] = 0;
|
|
}
|
|
m_ClimbingLadder = false;
|
|
m_SlidingDownALadder = true;
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::SetClimbingLadder(bool isClimbing)
|
|
{
|
|
if(!isClimbing && m_ClimbingLadder)
|
|
{
|
|
if(m_pModPhys)
|
|
{
|
|
for(u32 i = 0; i < m_pModPhys->NumFeet ; i++)
|
|
{
|
|
m_WasClimbingLadder.Set(i);
|
|
m_FootMoveState[i] = kMoveMoving;
|
|
m_AlreadyTriggered.Clear(i);
|
|
m_AlreadyLifted.Clear(i);
|
|
}
|
|
}
|
|
}
|
|
m_ClimbingLadder = isClimbing;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::ResetAirFlags()
|
|
{
|
|
for(u32 i = 0; i < (MaxFeetTags -1) ; i++)
|
|
{
|
|
m_WasInTheAir.Clear(i);
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::UpdateClass()
|
|
{
|
|
#if __BANK
|
|
if(sm_DrawHLODResults)
|
|
{
|
|
for(u32 i = 0; i<NumQuadrants ; i++)
|
|
{
|
|
if(sm_HLODPeds[i].ped)
|
|
{
|
|
Vector3 headPos = sm_HLODPeds[i].ped->GetBonePositionCached(BONETAG_HEAD);
|
|
grcDebugDraw::Sphere(headPos,0.2f,Color32(0.f,255.f,0.f,128.f),false);
|
|
}
|
|
}
|
|
Vector3 playerPos = VEC3V_TO_VECTOR3(CGameWorld::FindLocalPlayer()->GetTransform().GetPosition());
|
|
grcDebugDraw::Line(playerPos,playerPos + 10.f *MAT34V_TO_MATRIX34(g_AudioEngine.GetEnvironment().GetVolumeListenerMatrix()).b,Color_red);
|
|
grcDebugDraw::Line(playerPos,playerPos - 10.f *MAT34V_TO_MATRIX34(g_AudioEngine.GetEnvironment().GetVolumeListenerMatrix()).b,Color_red);
|
|
grcDebugDraw::Line(playerPos,playerPos + 10.f *MAT34V_TO_MATRIX34(g_AudioEngine.GetEnvironment().GetVolumeListenerMatrix()).a,Color_red);
|
|
grcDebugDraw::Line(playerPos,playerPos - 10.f *MAT34V_TO_MATRIX34(g_AudioEngine.GetEnvironment().GetVolumeListenerMatrix()).a,Color_red);
|
|
}
|
|
#endif
|
|
// Clean up the array for the next iteration
|
|
for(u32 i = 0; i<NumQuadrants ; i++)
|
|
{
|
|
sm_HLODPeds[i].ped = NULL;
|
|
sm_HLODPeds[i].fitness = 0.f;
|
|
}
|
|
ShoeList *shoeList = audNorthAudioEngine::GetObject<ShoeList>(ATSTRINGHASH("ShoeList",0xCB4E5724));
|
|
if(naVerifyf(shoeList, "Couldn't find autogenerated shoe type list"))
|
|
{
|
|
for (s32 i = 0; i < shoeList->numShoes; ++i)
|
|
{
|
|
ShoeAudioSettings *settings = audNorthAudioEngine::GetObject<ShoeAudioSettings>(shoeList->Shoe[i].ShoeAudioSettings);
|
|
if(settings)
|
|
{
|
|
sm_ShoesFitness[settings->ShoeType] = settings->ShoeFitness;
|
|
}
|
|
}
|
|
}
|
|
if(g_PlayerSwitch.IsActive())
|
|
{
|
|
sm_WasPlayerSwitchActive = true;
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::ForceStepType(bool force, const audFootstepEvent stepType, const audDetectionValues detectionValuesIdx)
|
|
{
|
|
m_ScriptForceStepType = force;
|
|
m_ScriptStepType = stepType;
|
|
m_ScriptDetectionValuesIdx = detectionValuesIdx;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::UpdateAudioLOD()
|
|
{
|
|
m_IsAudioHLOD = false;
|
|
//UpdateUpDiffWithGround();
|
|
const crSkeleton* pSkel = m_pParentPed->GetFragInst()->GetSkeleton();
|
|
if (pSkel == NULL || !m_pParentPed->GetIsVisible())
|
|
{
|
|
return;
|
|
}
|
|
if(m_pParentPed->IsLocalPlayer())
|
|
{
|
|
m_IsAudioHLOD = true;
|
|
return;
|
|
}
|
|
// Distance test to check if we have to update the footsteps for the current ped.
|
|
Vec3V pedPos = m_pParentPed->GetTransform().GetPosition();
|
|
Vec3V dirToPed = Subtract(pedPos ,g_AudioEngine.GetEnvironment().GetVolumeListenerPosition());
|
|
ScalarV distanceToPed = MagSquared(dirToPed);
|
|
//If using the sniper avoid the distance check
|
|
if(IsTrue(distanceToPed > GetDistanceThresholdSqToUpdateFootSteps(*m_pParentPed)))
|
|
{
|
|
return;
|
|
}
|
|
// At this point the ped is a candidate to be a HLOD, check it.
|
|
dirToPed = Normalize(dirToPed);
|
|
audQuadrants pedQuadrant = CalculatePedQuadrant(dirToPed);
|
|
f32 pedFitness = CalculatePedFitness(distanceToPed.Getf());
|
|
if(!sm_HLODPeds[pedQuadrant].ped || (sm_HLODPeds[pedQuadrant].fitness < pedFitness))
|
|
{
|
|
if(sm_HLODPeds[pedQuadrant].ped)
|
|
{
|
|
//sm_ShoesFitness[m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().GetShoeType()] = m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().GetCachedShoeSettings()->ShoeFitness;
|
|
sm_HLODPeds[pedQuadrant].ped->GetFootstepHelper().SetIsAudioHLOD(false);
|
|
}
|
|
sm_HLODPeds[pedQuadrant].ped = m_pParentPed;
|
|
sm_HLODPeds[pedQuadrant].fitness = pedFitness;
|
|
m_IsAudioHLOD = true;
|
|
if(!IsAnAnimal())
|
|
{
|
|
sm_ShoesFitness[m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().GetShoeType()] = 0.01f;
|
|
}
|
|
}
|
|
//g_Count = 0;
|
|
#if __BANK
|
|
if(sm_DrawHLODResults)
|
|
{
|
|
Vector3 headPos = m_pParentPed->GetBonePositionCached(BONETAG_HEAD);
|
|
char txt[64];
|
|
formatf(txt,"Q%u %f",pedQuadrant,pedFitness);
|
|
grcDebugDraw::Text(headPos + Vector3(0.f,0.f,1.f),Color_white,txt);
|
|
}
|
|
#endif
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
audQuadrants CPedFootStepHelper::CalculatePedQuadrant(Vec3V_In dirToPed)
|
|
{
|
|
// Quadrant 0 Fdot + Rdot -
|
|
audQuadrants pedQuadrant = Q0;
|
|
ScalarV fDot = Dot(g_AudioEngine.GetEnvironment().GetVolumeListenerMatrix().GetCol1(),dirToPed);
|
|
ScalarV rDot = Dot(g_AudioEngine.GetEnvironment().GetVolumeListenerMatrix().GetCol0(),dirToPed);
|
|
// Quadrant 3 Fdot + Rdot +
|
|
if(IsTrue(fDot >= ScalarV(V_ZERO)) && IsTrue(rDot >= ScalarV(V_ZERO)))
|
|
{
|
|
pedQuadrant = Q3;
|
|
}
|
|
// Quadrant 2 Fdot - Rdot +
|
|
else if (IsTrue(fDot < ScalarV(V_ZERO)) && IsTrue(rDot >= ScalarV(V_ZERO)))
|
|
{
|
|
pedQuadrant = Q2;
|
|
}
|
|
// Quadrant 1 Fdot - Rdot -
|
|
else if (IsTrue(fDot < ScalarV(V_ZERO)) && IsTrue(rDot < ScalarV(V_ZERO)))
|
|
{
|
|
pedQuadrant = Q1;
|
|
}
|
|
return pedQuadrant;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
f32 CPedFootStepHelper::CalculatePedFitness(f32 distanceToPed)
|
|
{
|
|
//Early out if we don't have an audio entity
|
|
if(!m_pParentPed->GetPedAudioEntity())
|
|
{
|
|
return 0.f;
|
|
}
|
|
// The fitness is based on the shore type and the distance to the camera.
|
|
f32 fitness = sm_DistanceToHLODFitness.CalculateRescaledValue(0.f,1.f,0.f,GetDistanceThresholdSqToUpdateFootSteps(*m_pParentPed).Getf(),distanceToPed);
|
|
fitness *= sm_ShoesFitness[m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().GetShoeType()];
|
|
fitness *= (m_pParentPed->GetMotionData()->GetIsStill()) ? 0.f : 1.f;
|
|
fitness *= (m_pParentPed->GetMotionData()->GetIsRunning()) ? sm_RunFitnessScale : 1.f;
|
|
fitness *= (IsAnAnimal()) ? sm_AnimalFitnessScale : 1.f;
|
|
//fitness += (m_pParentPed->GetMotionData()->GetIsRunning()) ? sm_RunFitnessScale : 0.f; Adding fitness instead of scaling
|
|
fitness = Clamp(fitness, 0.f,1.f);
|
|
return fitness;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
bool CPedFootStepHelper::IsAnAnimal()
|
|
{
|
|
return m_pParentPed->GetPedType() == PEDTYPE_ANIMAL;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::IssueAsyncLineTestProbes()
|
|
{
|
|
const Matrix34 &rootMatrix = MAT34V_TO_MATRIX34(m_pParentPed->GetTransform().GetMatrix());
|
|
Vector3 vecStart = rootMatrix.d;
|
|
Vector3 vecEnd = rootMatrix.d;
|
|
vecStart.z -= sm_FootStepLineTestStartOffset;
|
|
vecEnd.z = vecStart.z - sm_FootStepLineTestLong;
|
|
u32 nFlags = ArchetypeFlags::GTA_MAP_TYPE_MOVER | ArchetypeFlags::GTA_VEHICLE_TYPE | ArchetypeFlags::GTA_PED_TYPE | ArchetypeFlags::GTA_OBJECT_TYPE;
|
|
m_CachedLineTest.m_MainLineTest.AddProbe(vecStart,vecEnd,m_pParentPed,nFlags,false);
|
|
#if __BANK
|
|
if(sm_DrawDebugInfo)
|
|
{
|
|
grcDebugDraw::Line(vecStart,vecEnd,Color_red,Color_red);
|
|
}
|
|
#endif
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::PreUpdateFootstepGroundTest(Vec3V_InOut groundPosition,Vec3V_InOut groundNormal)
|
|
{
|
|
// Send an async probe.
|
|
if(m_HasToInitGroundTest)
|
|
{
|
|
PF_FUNC(PreUpdateFootstepGTest);
|
|
if(m_CachedLineTest.Clear())
|
|
{
|
|
m_HasResultThisFrame = false;
|
|
m_HasToInitGroundTest = false;
|
|
IssueAsyncLineTestProbes();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PF_FUNC(UpdateFootstepGTest);
|
|
// Update the active tests.
|
|
UpdateFootstepGroundTest(groundPosition, groundNormal);
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
bool CPedFootStepHelper::ProcessAsyncLineTestProbes()
|
|
{
|
|
PF_FUNC(ProcessAsyncLineTProbes);
|
|
audCachedLos & lineTest = m_CachedLineTest.m_MainLineTest;
|
|
|
|
if(lineTest.m_bContainsProbe)
|
|
{
|
|
if(lineTest.m_bHitSomething==true)
|
|
{
|
|
m_CachedLineTest.m_GroundPosition = lineTest.m_vIntersectPos;
|
|
m_CachedLineTest.m_GroundNormal = lineTest.m_vIntersectNormal;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::SyncProbesGroundTest(Vec3V_InOut groundPosition,Vec3V_InOut groundNormal)
|
|
{
|
|
phIntersection testIntersections[AUD_NUM_INTERSECTIONS_FOR_PED_PROBES];
|
|
phSegment testSegment;
|
|
const Matrix34 &rootMatrix = MAT34V_TO_MATRIX34(m_pParentPed->GetTransform().GetMatrix());
|
|
Vector3 vecStart = rootMatrix.d;
|
|
Vector3 vecEnd = rootMatrix.d;
|
|
vecEnd.z -= PED_HUMAN_GROUNDTOROOTOFFSET * sm_FootStepLineTestLong;
|
|
|
|
testSegment.Set(vecStart, vecEnd);
|
|
#if __BANK
|
|
Vector3 headPos = m_pParentPed->GetBonePositionCached(BONETAG_HEAD);
|
|
if(sm_DrawDebugInfo)
|
|
{
|
|
grcDebugDraw::Sphere(headPos,0.4f,Color_red,true);
|
|
grcDebugDraw::Line(vecStart,vecEnd,Color_red,Color_red);
|
|
}
|
|
#endif
|
|
u32 nFlags = ArchetypeFlags::GTA_MAP_TYPE_MOVER | ArchetypeFlags::GTA_VEHICLE_TYPE | ArchetypeFlags::GTA_PED_TYPE | ArchetypeFlags::GTA_OBJECT_TYPE;
|
|
int nNumResults = CPhysics::GetLevel()->TestProbe(testSegment, testIntersections, m_pParentPed->GetCurrentPhysicsInst(), nFlags, TYPE_FLAGS_ALL, phLevelBase::STATE_FLAGS_ALL, AUD_NUM_INTERSECTIONS_FOR_PED_PROBES);
|
|
|
|
int nUseIntersection = -1;
|
|
for(int i=0; i<nNumResults; i++)
|
|
{
|
|
|
|
if(testIntersections[i].IsAHit())
|
|
{
|
|
CEntity* pHitEntity = CPhysics::GetEntityFromInst(testIntersections[i].GetInstance());
|
|
if(pHitEntity && pHitEntity->IsCollisionEnabled())
|
|
{
|
|
// check we've got the first intersection along the probe
|
|
if(nUseIntersection < 0 || IsTrue(testIntersections[i].GetPosition().GetZ() > testIntersections[nUseIntersection].GetPosition().GetZ()))
|
|
{
|
|
nUseIntersection = i;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
if(nUseIntersection > -1)
|
|
{
|
|
if(testIntersections[nUseIntersection].GetInstance() && CPhysics::GetEntityFromInst(testIntersections[nUseIntersection].GetInstance())
|
|
&& CPhysics::GetEntityFromInst(testIntersections[nUseIntersection].GetInstance())->GetIsPhysical()
|
|
&& ((CPhysical*)CPhysics::GetEntityFromInst(testIntersections[nUseIntersection].GetInstance()))->GetAttachParent() == m_pParentPed)
|
|
{
|
|
//Assertf(false, "Ped is trying to stand on something he's attached to");
|
|
return;
|
|
}
|
|
#if __BANK
|
|
if(sm_DrawDebugInfo)
|
|
{
|
|
grcDebugDraw::Sphere(headPos + Vector3(0.f,0.f,0.5f),0.2f,Color_yellow,true);
|
|
}
|
|
#endif
|
|
phMaterialMgr::Id ProbeHitMaterial=0;
|
|
ProbeHitMaterial = testIntersections[nUseIntersection].GetMaterialId();
|
|
groundPosition = testIntersections[nUseIntersection].GetPosition();
|
|
groundNormal = testIntersections[nUseIntersection].GetNormal();
|
|
if(m_pParentPed->GetPedAudioEntity())
|
|
{
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().SetStandingMaterial(ProbeHitMaterial, CPhysics::GetEntityFromInst(testIntersections[nUseIntersection].GetInstance()), testIntersections[nUseIntersection].GetComponent());
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::SyncProbesFromFeetGroundTest(Vec3V_InOut groundPosition,Vec3V_InOut groundNormal)
|
|
{
|
|
phIntersection testIntersections[AUD_NUM_INTERSECTIONS_FOR_PED_PROBES];
|
|
phSegment testSegment;
|
|
const Matrix34 &rootMatrix = MAT34V_TO_MATRIX34(m_pParentPed->GetTransform().GetMatrix());
|
|
Vector3 vecStart = rootMatrix.d;
|
|
Vector3 vecEnd = rootMatrix.d;
|
|
|
|
vecStart.z -= sm_FootStepLineTestStartOffset;
|
|
vecEnd.z = vecStart.z - sm_FootStepLineTestLong;
|
|
testSegment.Set(vecStart, vecEnd);
|
|
#if __BANK
|
|
if(sm_DrawDebugInfo)
|
|
{
|
|
Vector3 headPos = m_pParentPed->GetBonePositionCached(BONETAG_HEAD);
|
|
|
|
|
|
grcDebugDraw::Sphere(headPos + Vector3(0.f,0.f,0.5f),0.2f,Color_red,true);
|
|
grcDebugDraw::Line(vecStart,vecEnd,Color_red,Color_red);
|
|
}
|
|
#endif
|
|
|
|
u32 nFlags = ArchetypeFlags::GTA_MAP_TYPE_MOVER | ArchetypeFlags::GTA_VEHICLE_TYPE | ArchetypeFlags::GTA_PED_TYPE | ArchetypeFlags::GTA_OBJECT_TYPE;
|
|
int nNumResults = CPhysics::GetLevel()->TestProbe(testSegment, testIntersections, m_pParentPed->GetCurrentPhysicsInst(), nFlags, TYPE_FLAGS_ALL, phLevelBase::STATE_FLAGS_ALL, sm_NumIntersections);
|
|
|
|
int nUseIntersection = -1;
|
|
for(int i=0; i<nNumResults; i++)
|
|
{
|
|
|
|
if(testIntersections[i].IsAHit())
|
|
{
|
|
CEntity* pHitEntity = CPhysics::GetEntityFromInst(testIntersections[i].GetInstance());
|
|
if(pHitEntity && pHitEntity->IsCollisionEnabled())
|
|
{
|
|
// check we've got the first intersection along the probe
|
|
if(nUseIntersection < 0 || IsTrue(testIntersections[i].GetPosition().GetZ() > testIntersections[nUseIntersection].GetPosition().GetZ()))
|
|
{
|
|
nUseIntersection = i;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
if(nUseIntersection > -1)
|
|
{
|
|
if(testIntersections[nUseIntersection].GetInstance() && CPhysics::GetEntityFromInst(testIntersections[nUseIntersection].GetInstance())
|
|
&& CPhysics::GetEntityFromInst(testIntersections[nUseIntersection].GetInstance())->GetIsPhysical()
|
|
&& ((CPhysical*)CPhysics::GetEntityFromInst(testIntersections[nUseIntersection].GetInstance()))->GetAttachParent()==m_pParentPed)
|
|
{
|
|
//Assertf(false, "Ped is trying to stand on something he's attached to");
|
|
return;
|
|
}
|
|
|
|
phMaterialMgr::Id ProbeHitMaterial=0;
|
|
ProbeHitMaterial = testIntersections[nUseIntersection].GetMaterialId();
|
|
groundPosition = testIntersections[nUseIntersection].GetPosition();
|
|
groundNormal = testIntersections[nUseIntersection].GetNormal();
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().SetStandingMaterial(ProbeHitMaterial, CPhysics::GetEntityFromInst(testIntersections[nUseIntersection].GetInstance()), testIntersections[nUseIntersection].GetComponent());
|
|
// We have to store the new result by LRU scheme.
|
|
if(CPedFootStepHelper::sm_NumberOfTestResultStored < MAX_NUMBER_OF_GROUND_FOOTSTEPS_TESTS)
|
|
{
|
|
// No override needed.
|
|
for (s32 i = 0; i < MAX_NUMBER_OF_GROUND_FOOTSTEPS_TESTS; ++i )
|
|
{
|
|
if (CPedFootStepHelper::sm_GroundFootStepTests[i].height == -5000)
|
|
{
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].height = rootMatrix.d.GetZ();
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].numberOfHits = 1;
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].groundPos = testIntersections[nUseIntersection].GetPosition();
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].groundNormal = testIntersections[nUseIntersection].GetNormal();
|
|
CPedFootStepHelper::sm_NumberOfTestResultStored++;
|
|
break;
|
|
}
|
|
}
|
|
}else
|
|
{
|
|
s32 badCandidateIndex = 0;
|
|
for (s32 i = 0; i < MAX_NUMBER_OF_GROUND_FOOTSTEPS_TESTS; ++i )
|
|
{
|
|
// Look for a bad candidate so we'll override it if needed.
|
|
if(CPedFootStepHelper::sm_GroundFootStepTests[i].lastNumberOfHits < CPedFootStepHelper::sm_GroundFootStepTests[badCandidateIndex].lastNumberOfHits)
|
|
{
|
|
badCandidateIndex = i;
|
|
}
|
|
|
|
}
|
|
CPedFootStepHelper::sm_GroundFootStepTests[badCandidateIndex].height = rootMatrix.d.GetZ();
|
|
CPedFootStepHelper::sm_GroundFootStepTests[badCandidateIndex].numberOfHits = 1;
|
|
CPedFootStepHelper::sm_GroundFootStepTests[badCandidateIndex].groundPos = testIntersections[nUseIntersection].GetPosition();
|
|
CPedFootStepHelper::sm_GroundFootStepTests[badCandidateIndex].groundNormal = testIntersections[nUseIntersection].GetNormal();
|
|
}
|
|
Assertf((CPedFootStepHelper::sm_NumberOfTestResultStored<=MAX_NUMBER_OF_GROUND_FOOTSTEPS_TESTS),"Bad number of test on updateFootSteps");
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::ProcessFootstepVfx(audFootstepEvent event, bool hindLegs, Mat34V_In footMatrix, const u32 foot, Vec3V_In groundNormal)
|
|
{
|
|
if (m_pParentPed->GetPedVfx() == NULL)
|
|
{
|
|
return;
|
|
}
|
|
naAssertf(IsFiniteAll(footMatrix),"Wrong foot matrix.");
|
|
if (event==AUD_FOOTSTEP_WALK_L ||
|
|
event==AUD_FOOTSTEP_SCUFFHARD_L ||
|
|
event==AUD_FOOTSTEP_SCUFF_L ||
|
|
event==AUD_FOOTSTEP_JUMP_LAND_L ||
|
|
event==AUD_FOOTSTEP_RUN_L ||
|
|
event==AUD_FOOTSTEP_SPRINT_L ||
|
|
event==AUD_FOOTSTEP_SOFT_L)
|
|
{
|
|
m_pParentPed->GetPedVfx()->ProcessVfxFootStep(true, hindLegs, footMatrix, foot, groundNormal);
|
|
}
|
|
else if (event==AUD_FOOTSTEP_WALK_R ||
|
|
event==AUD_FOOTSTEP_SCUFFHARD_R ||
|
|
event==AUD_FOOTSTEP_SCUFF_R ||
|
|
event==AUD_FOOTSTEP_JUMP_LAND_R ||
|
|
event==AUD_FOOTSTEP_RUN_R ||
|
|
event==AUD_FOOTSTEP_SPRINT_R ||
|
|
event==AUD_FOOTSTEP_SOFT_R)
|
|
{
|
|
m_pParentPed->GetPedVfx()->ProcessVfxFootStep(false, hindLegs,footMatrix, foot, groundNormal);
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::InitDetectionValuesIndices()
|
|
{
|
|
for (u8 i = 0; i < m_pModPhys->numModes; i++)
|
|
{
|
|
audDetectionValues detectionMode = FindDetectionModeForHash(m_pModPhys->Modes[i].Name);
|
|
m_DetectionValuesIndices[detectionMode] = i;
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
audDetectionValues CPedFootStepHelper::FindDetectionModeForHash(const u32 modeHash)
|
|
{
|
|
const u32 s_Lookuptable[ModelPhysicsParams::MAX_MODES][2] = {
|
|
{ATSTRINGHASH("STOP", 0x930CA7F2), audDVStop},
|
|
{ATSTRINGHASH("WALK", 0x83504C9C), audDVWalk},
|
|
{ATSTRINGHASH("RUN", 0x1109B569), audDVRun},
|
|
{ATSTRINGHASH("SPRINT", 0xBC29E48), audDVSprint},
|
|
{ATSTRINGHASH("JUMP", 0x2E90C5D5), audDVJump},
|
|
{ATSTRINGHASH("STAIRS_STOP", 0xA8EA8DB3), audDVStairsStop},
|
|
{ATSTRINGHASH("STAIRS_WALK", 0x2A29F8E2), audDVStairsWalk},
|
|
{ATSTRINGHASH("STAIRS_RUN", 0xD540F6ED), audDVStairsRun},
|
|
{ATSTRINGHASH("SLOPES", 0x6C7A1EAF), audDVSlopes},
|
|
{ATSTRINGHASH("SLOPES_RUN", 0x4EA5C142), audDVSlopesRun},
|
|
{ATSTRINGHASH("STEALTH_WALK", 0xD028448C), audDVStealthWalk},
|
|
{ATSTRINGHASH("STEALTH_RUN", 0x3224A955), audDVStealthRun},
|
|
{ATSTRINGHASH("LADDER", 0x1A53E8E4), audDVLadder},
|
|
{ATSTRINGHASH("VAULT", 0x4806CCCA), audDVVault}};
|
|
|
|
for (u8 i = 0; i < NELEM(s_Lookuptable); i++)
|
|
{
|
|
if (s_Lookuptable[i][0] == modeHash)
|
|
{
|
|
return (audDetectionValues)s_Lookuptable[i][1];
|
|
}
|
|
}
|
|
return audDVWalk;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::UpdatePhysicProbes(Vec4V_InOut groundPlane)
|
|
{
|
|
// In case the Ik solver has a result this frame, use the ground position from it, otherwise store the ped ground position and normal
|
|
// in the first element of the array.
|
|
if(!m_HasIkResultsThisFrame)
|
|
{
|
|
m_GroundPosition[0] = VECTOR3_TO_VEC3V(m_pParentPed->GetGroundPos());
|
|
m_GroundNormal[0] = VECTOR3_TO_VEC3V(m_pParentPed->GetGroundNormal());
|
|
|
|
if(sm_WasPlayerSwitchActive || m_ScriptForceUpdate)
|
|
{
|
|
m_IsPlayingSwitchScene = m_pParentPed->GetPedIntelligence()->GetQueriableInterface()->IsTaskCurrentlyRunning( CTaskTypes::TASK_SYNCHRONIZED_SCENE )
|
|
|| m_pParentPed->GetPedIntelligence()->GetQueriableInterface()->IsTaskCurrentlyRunning( CTaskTypes::TASK_SCRIPTED_ANIMATION );
|
|
}
|
|
if(BANK_ONLY(sm_ForceSyncProbesToAllPeds ||) m_IsPlayingSwitchScene || (!m_pParentPed->GetIsStanding() && (m_pParentPed->GetUseExtractedZ() && ! m_pParentPed->GetPedIntelligence()->GetQueriableInterface()->IsTaskCurrentlyRunning( CTaskTypes::TASK_CLIMB_LADDER ))) )
|
|
{
|
|
if(!sm_AsyncProbesGroundTest)
|
|
{
|
|
SyncProbesGroundTest(m_GroundPosition[0],m_GroundNormal[0]);
|
|
}else
|
|
{
|
|
FootstepGroundTest(m_GroundPosition[0],m_GroundNormal[0]);
|
|
}
|
|
#if __BANK
|
|
if(sm_DrawResults)
|
|
{
|
|
grcDebugDraw::Line(m_GroundPosition[0],m_GroundPosition[0] + ScalarV(20) * m_GroundNormal[0],Color_beige,Color_beige);
|
|
}
|
|
#endif
|
|
}
|
|
groundPlane = Vec4V(Vec::V4PermuteTwo<Vec::X1,Vec::Y1,Vec::Z1,Vec::X2>( m_GroundNormal[0].GetIntrin128(),
|
|
(m_GroundNormal[0].GetX() * m_GroundPosition[0].GetX()
|
|
+ m_GroundNormal[0].GetY() * m_GroundPosition[0].GetY()
|
|
+ m_GroundNormal[0].GetZ() * m_GroundPosition[0].GetZ()).GetIntrin128() ));
|
|
|
|
/* groundPlane.SetXYZ(m_GroundNormal[0]);
|
|
groundPlane.SetW((m_GroundNormal[0].GetX() * m_GroundPosition[0].GetX())
|
|
+ m_GroundNormal[0].GetY() * m_GroundPosition[0].GetY()
|
|
+ m_GroundNormal[0].GetZ() * m_GroundPosition[0].GetZ()) ;*/
|
|
}
|
|
else
|
|
{
|
|
sm_WasPlayerSwitchActive = false;
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::ComputeStepInfo( f32 pedVelocity,audFootstepEvent &stepType,u8 &detectionValuesIndex)
|
|
{
|
|
BANK_ONLY (char text[256]);
|
|
if(m_pParentPed->GetPedResetFlag(CPED_RESET_FLAG_PedHitWallLastFrame) )
|
|
{
|
|
BANK_ONLY (formatf(text,"SPECIAL_CASE"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVSprint];
|
|
stepType = (audFootstepEvent)(AUD_FOOTSTEP_WALK_L);
|
|
}
|
|
else if( m_ScriptForceStepType && naVerifyf(m_ScriptDetectionValuesIdx < MaxNumberAudDetValues,"Wrong detection value idx coming from script"))
|
|
{
|
|
BANK_ONLY (formatf(text,"SCRIPT"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[m_ScriptDetectionValuesIdx];
|
|
stepType = m_ScriptStepType;
|
|
}
|
|
else
|
|
{
|
|
if(m_IsWalkingOnSlope && !m_pParentPed->GetPedConfigFlag(CPED_CONFIG_FLAG_StairsDetected))
|
|
{
|
|
pedVelocity -= sm_SlopeAngleToDeltaSpeed.CalculateValue(RtoD * fabs(m_SlopeAngle));
|
|
pedVelocity = Max(pedVelocity, 0.f);
|
|
}
|
|
if(m_pParentPed->IsLocalPlayer() && (m_pParentPed->GetPedConfigFlag(CPED_CONFIG_FLAG_StairsDetected) || m_WasOnStairs))
|
|
{
|
|
if( pedVelocity != 0.f)
|
|
{
|
|
pedVelocity += sm_StairsDeltaSpeed;
|
|
}
|
|
}
|
|
|
|
bool isVaulting = m_pParentPed->GetPedResetFlag(CPED_RESET_FLAG_IsVaulting);
|
|
if (isVaulting)
|
|
{
|
|
BANK_ONLY (formatf(text,"VAULT"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVVault];
|
|
stepType = (audFootstepEvent)(AUD_FOOTSTEP_RUN_L);
|
|
}
|
|
else if (m_pParentPed->GetPedResetFlag(CPED_RESET_FLAG_InCoverTaskActive))
|
|
{
|
|
BANK_ONLY (formatf(text,"IN COVER USING RUN"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVRun];
|
|
stepType = (audFootstepEvent)(AUD_FOOTSTEP_RUN_L);
|
|
}
|
|
else if(pedVelocity <= m_pModPhys->StopSpeedThreshold && m_pParentPed->GetDeepSurfaceInfo().GetDepth() <= 0.05f)
|
|
{
|
|
//moving = false;
|
|
BANK_ONLY (formatf(text,"STOP"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVStop];
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().ResetLastMoveBlendRatio();
|
|
stepType = (audFootstepEvent)(AUD_FOOTSTEP_SOFT_L);
|
|
if(m_pParentPed->GetPedConfigFlag(CPED_CONFIG_FLAG_StairsDetected) || m_WasOnStairs)
|
|
{
|
|
BANK_ONLY (formatf(text,"STAIRS_STOP"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVStairsStop];
|
|
}
|
|
else if(m_pParentPed->GetMotionData()->GetUsingStealth())
|
|
{
|
|
BANK_ONLY (formatf(text,"STEALTH_STOP using STOP"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVStop];
|
|
//detectionValuesIndex = m_DetectionValuesIndices[audDVStealthWalk];
|
|
}
|
|
else if (m_IsWalkingOnSlope)
|
|
{
|
|
BANK_ONLY (formatf(text,"SLOPE_STOP using SLOP_WALK"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVSlopes];
|
|
stepType = (audFootstepEvent)(AUD_FOOTSTEP_WALK_L);
|
|
}
|
|
}
|
|
else if(pedVelocity <= m_pModPhys->WalkSpeedThreshold)
|
|
{
|
|
BANK_ONLY (formatf(text,"WALK"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVWalk];
|
|
if(m_pParentPed->GetPedConfigFlag(CPED_CONFIG_FLAG_StairsDetected) || m_WasOnStairs)
|
|
{
|
|
BANK_ONLY (formatf(text,"STAIRS_WALK"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVStairsWalk];
|
|
}
|
|
else if(m_pParentPed->GetMotionData()->GetUsingStealth())
|
|
{
|
|
BANK_ONLY (formatf(text,"STEALTH_WALK using WALK"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVWalk];
|
|
//detectionValuesIndex = m_DetectionValuesIndices[audDVStealthWalk];
|
|
}
|
|
else if (m_pParentPed->GetPedResetFlag(CPED_RESET_FLAG_HasGunTaskWithAimingState))
|
|
{
|
|
BANK_ONLY (formatf(text,"AIM_WALK using RUN"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVRun];
|
|
}
|
|
else if (m_IsWalkingOnSlope)
|
|
{
|
|
BANK_ONLY (formatf(text,"SLOPE_WALK using SLOPES"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVSlopes];
|
|
}
|
|
stepType = (audFootstepEvent)(AUD_FOOTSTEP_WALK_L);
|
|
}
|
|
else if(pedVelocity <= m_pModPhys->RunSpeedThreshold)
|
|
{
|
|
BANK_ONLY (formatf(text,"RUN"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVRun];
|
|
if(m_pParentPed->GetPedConfigFlag(CPED_CONFIG_FLAG_StairsDetected) || m_WasOnStairs)
|
|
{
|
|
BANK_ONLY (formatf(text,"STAIRS_RUN"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVStairsRun];
|
|
}
|
|
else if(m_pParentPed->GetMotionData()->GetUsingStealth())
|
|
{
|
|
BANK_ONLY (formatf(text,"STEALTH_RUN using RUN"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVRun];
|
|
//detectionValuesIndex = m_DetectionValuesIndices[audDVStealthRun];
|
|
}
|
|
else if (m_IsWalkingOnSlope)
|
|
{
|
|
BANK_ONLY (formatf(text,"SLOPE_RUN using SLOPES"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVSlopesRun];
|
|
}
|
|
stepType = (audFootstepEvent)(AUD_FOOTSTEP_RUN_L);
|
|
}
|
|
else
|
|
{
|
|
BANK_ONLY (formatf(text,"SPRINT"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVSprint];
|
|
if(m_pParentPed->GetPedConfigFlag(CPED_CONFIG_FLAG_StairsDetected) || m_WasOnStairs)
|
|
{
|
|
BANK_ONLY (formatf(text,"STAIRS_SPRINT using STAIRS_RUN"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVStairsRun];
|
|
}
|
|
else if(m_pParentPed->GetMotionData()->GetUsingStealth())
|
|
{
|
|
BANK_ONLY (formatf(text,"STEALTH_RUN using RUN"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVRun];
|
|
//detectionValuesIndex = m_DetectionValuesIndices[audDVStealthRun];
|
|
}
|
|
else if (m_IsWalkingOnSlope)
|
|
{
|
|
BANK_ONLY (formatf(text,"SLOPE_RUN using SLOPES"));
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVSlopesRun];
|
|
}
|
|
stepType = (audFootstepEvent)(AUD_FOOTSTEP_SPRINT_L);
|
|
}
|
|
}
|
|
|
|
#if __BANK
|
|
if(sm_ShowPedSpeed)
|
|
{
|
|
char txt[512];
|
|
Vector3 headPos = m_pParentPed->GetBonePositionCached(BONETAG_HEAD);
|
|
formatf(txt,"%s -> %f ",text,pedVelocity);
|
|
grcDebugDraw::AddDebugOutput(text);
|
|
//formatf(text,"ped angular vel -> %f ",angularVelocity);
|
|
//grcDebugDraw::AddDebugOutput(text);
|
|
//formatf(text,"angular acceleration -> %f",fabs((angularVelocity - m_LastPedAngVel) / fwTimer::GetTimeStep()));
|
|
//grcDebugDraw::AddDebugOutput(text);
|
|
grcDebugDraw::Text(headPos,Color_white,txt);
|
|
naDisplayf("%s %f",txt,pedVelocity);
|
|
}
|
|
#endif
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::UpdateFootPlanted(const u32 footId BANK_ONLY(,ScalarV_In footSpeed), const f32 upDistanceToGround, const u8 detectionValuesIndex BANK_ONLY(,const audFootstepEvent stepType),Vec3V_In /*downSlopeDirection*/ BANK_ONLY(,Vec3V_In heelPos))
|
|
{
|
|
#if __BANK
|
|
if(sm_ShowFootStepTuningInfo)
|
|
{
|
|
naDisplayf("______________________________________________________________________________________________");
|
|
char txt[128];
|
|
formatf(txt,"PLANTED: ");
|
|
naDisplayf("%s", txt);
|
|
formatf(txt,"Foot %d [footSpeed = %f] [upDistanceToGround = %f] [groundDistanceUpEpsilon = %f]",footId,footSpeed.Getf(),upDistanceToGround,m_pModPhys->Modes[detectionValuesIndex].GroundDistanceUpEpsilon);
|
|
naDisplayf("%s", txt);
|
|
|
|
}
|
|
#endif
|
|
//Check if the foot is far enough from the groudn to even consider if it's moving
|
|
if(upDistanceToGround > m_pModPhys->Modes[detectionValuesIndex].GroundDistanceUpEpsilon )
|
|
{
|
|
#if __BANK
|
|
if(sm_PauseOnLimits )
|
|
{
|
|
Color32 color = Color_red;
|
|
if(stepType == AUD_FOOTSTEP_SOFT_L || stepType == AUD_FOOTSTEP_SOFT_R)
|
|
{
|
|
color = Color_green;
|
|
}
|
|
else if ( stepType == AUD_FOOTSTEP_JUMP_LAND_L || stepType == AUD_FOOTSTEP_JUMP_LAND_R )
|
|
{
|
|
color = Color_purple;
|
|
}
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.5f,0.f,0.f),color,color,50);
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.f,0.5f,0.f),color,color,50);
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.f,0.f,0.5f),color,color,50);
|
|
|
|
fwTimer::StartUserPause();
|
|
}
|
|
#endif
|
|
if(m_pParentPed->GetMotionData()->GetUsingStealth())
|
|
{
|
|
f32 scuffProb = sm_PlayerClumsinessToScuffProb.CalculateValue(m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().GetPlayerClumsiness());
|
|
if(audEngineUtil::ResolveProbability(scuffProb))
|
|
{
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddFootstepEvent((audFootstepEvent)(AUD_FOOTSTEP_SCUFF_L + footId));
|
|
//if(m_IsWalkingOnSlope)
|
|
//{
|
|
//m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddSlopeDebrisEvent((audFootstepEvent)(AUD_FOOTSTEP_SCUFF_L + footId),downSlopeDirection,m_SlopeAngle);
|
|
//}
|
|
#if __BANK
|
|
if(sm_PauseOnDragEvents)
|
|
{
|
|
naDisplayf("[footSpeed = %f] [downSpeedEpsilon = %f] [upDistanceToGround = %f]", footSpeed.Getf(), m_pModPhys->Modes[detectionValuesIndex].DownSpeedEpsilon, upDistanceToGround);
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.5f,0.f,0.f),Color_blue,Color_blue,50);
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.f,0.5f,0.f),Color_blue,Color_blue,50);
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.f,0.f,0.5f),Color_blue,Color_blue,50);
|
|
fwTimer::StartUserPause();
|
|
}
|
|
else if (sm_ShowFootStepTuningInfo)
|
|
{
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.5f,0.f,0.f),Color_blue,Color_blue,50);
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.f,0.5f,0.f),Color_blue,Color_blue,50);
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.f,0.f,0.5f),Color_blue,Color_blue,50);
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
m_AlreadyLifted.Clear(footId);
|
|
m_AlreadyTriggered.Clear(footId);
|
|
m_FootMoveState[footId] = kMoveMoving;
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::SetWalkingOnPuddle(bool walkingOnPuddle)
|
|
{
|
|
sm_IsWalkingOnPuddle = walkingOnPuddle;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
bool CPedFootStepHelper::IsWalkingOnPuddle()
|
|
{
|
|
if( m_pParentPed && m_pParentPed->IsLocalPlayer())
|
|
{
|
|
return sm_IsWalkingOnPuddle;
|
|
}
|
|
return false;
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::UpdateFootMoving(const u32 footId,ScalarV_In footSpeed, const f32 upDistanceToGround, const u8 detectionValuesIndex,audFootstepEvent stepType,Vec3V_In downSlopeDirection,bool hindFoot,const u32 /*foot*/,Mat34V_In footMatrix BANK_ONLY(,Vec3V_In heelPos))
|
|
{
|
|
#if GTA_REPLAY
|
|
if(CReplayMgr::IsEditModeActive())
|
|
{
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
#if __BANK
|
|
if(sm_ShowFootStepTuningInfo )
|
|
{
|
|
naDisplayf("______________________________________________________________________________________________");
|
|
char txt[128];
|
|
formatf(txt,"MOVING: ");
|
|
naDisplayf("%s", txt);
|
|
formatf(txt,"Foot %d [footSpeed %f] [downSpeedEpsilon %f] [upDistanceToGround = %f] [groundDistanceDownEpsilon = %f]",footId,footSpeed.Getf(),m_pModPhys->Modes[detectionValuesIndex].DownSpeedEpsilon,upDistanceToGround,m_pModPhys->Modes[detectionValuesIndex].GroundDistanceDownEpsilon);
|
|
naDisplayf("%s", txt);
|
|
|
|
}
|
|
#endif
|
|
if (m_AlreadyLifted.IsClear(footId) && (upDistanceToGround > sm_UpDistaneToTriggerLift) && m_pParentPed->GetDeepSurfaceInfo().GetDepth() > 0.f)
|
|
{
|
|
m_AlreadyLifted.Set(footId);
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddFootstepEvent((audFootstepEvent)(AUD_FOOTSTEP_LIFT_L + (footId % 2)));
|
|
}
|
|
bool applyDeltaFix = false;
|
|
if( m_pParentPed->IsLocalPlayer() && footId == 1 && detectionValuesIndex == audDVStairsRun && m_pParentPed->GetPedConfigFlag(CPED_CONFIG_FLAG_StairsDetected) && m_PrevHeight < m_pParentPed->GetTransform().GetPosition().GetZf())
|
|
{
|
|
if( audNorthAudioEngine::GetGtaEnvironment() && audNorthAudioEngine::GetGtaEnvironment()->HasNavMeshInfoBeenUpdated() && audNorthAudioEngine::GetGtaEnvironment()->GetListenerInteriorInstance() && audNorthAudioEngine::GetGtaEnvironment()->GetListenerInteriorInstance()->GetBaseModelInfo()
|
|
&& (audNorthAudioEngine::GetGtaEnvironment()->GetListenerInteriorInstance()->GetBaseModelInfo()->GetModelNameHash() == ATSTRINGHASH("v_sweat", 0x5DE36999)
|
|
|| audNorthAudioEngine::GetGtaEnvironment()->GetListenerInteriorInstance()->GetBaseModelInfo()->GetModelNameHash() == ATSTRINGHASH("v_sweatempty", 0xC404F5CB)))
|
|
{
|
|
applyDeltaFix = true ;
|
|
}
|
|
}
|
|
u32 deltaTimeFix = applyDeltaFix ? 250 : 0;
|
|
if( m_LastTimeFootPlanted[footId] + m_pModPhys->Modes[detectionValuesIndex].TimeToRetrigger + deltaTimeFix < g_AudioEngine.GetSoundManager().GetTimeInMilliseconds(0))
|
|
{
|
|
f32 deltaFix = applyDeltaFix ? 0.25f : 0.f;
|
|
if(upDistanceToGround < m_pModPhys->Modes[detectionValuesIndex].GroundDistanceDownEpsilon + deltaFix )
|
|
{
|
|
#if __BANK
|
|
if(sm_PauseOnLimits )
|
|
{
|
|
Color32 color = Color_red;
|
|
if(stepType == AUD_FOOTSTEP_SOFT_L || stepType == AUD_FOOTSTEP_SOFT_R)
|
|
{
|
|
color = Color_green;
|
|
}
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.5f,0.f,0.f),color,color,25);
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.f,0.5f,0.f),color,color,25);
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.f,0.f,0.5f),color,color,25);
|
|
|
|
|
|
fwTimer::StartUserPause();
|
|
}
|
|
#endif
|
|
f32 deltaSpeed = 0.f;
|
|
if(m_SlidingDownALadder)
|
|
{
|
|
deltaSpeed = 5.f;
|
|
}
|
|
if (m_pParentPed->GetPedAudioEntity() && m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().GetIsStandingOnVehicle())
|
|
{
|
|
CVehicle* vehicle = ((CVehicle*) m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().GetLastStandingEntity());
|
|
deltaSpeed = fabs(vehicle->GetVelocity().Mag());
|
|
}
|
|
// Check the footsped for audio.
|
|
if(m_AlreadyTriggered.IsClear(footId) && (footSpeed.Getf() < (m_pModPhys->Modes[detectionValuesIndex].DownSpeedEpsilon + deltaSpeed) ))
|
|
{
|
|
m_AlreadyTriggered.Set(footId);
|
|
if(m_IsPlayingSwitchScene)
|
|
{
|
|
stepType = (audFootstepEvent)(AUD_FOOTSTEP_WALK_L + (footId % 2));
|
|
}
|
|
else if(m_WasClimbingLadder.IsSet(footId))
|
|
{
|
|
stepType = (audFootstepEvent)(AUD_FOOTSTEP_SOFT_L + (footId % 2));
|
|
if(m_SlidingDownALadder)
|
|
{
|
|
stepType = (audFootstepEvent)(AUD_FOOTSTEP_JUMP_LAND_L + (footId % 2));
|
|
}
|
|
m_WasClimbingLadder.Clear(footId);
|
|
if( m_WasClimbingLadder.IsClear(0) && m_WasClimbingLadder.IsClear(1))
|
|
{
|
|
m_SlidingDownALadder = false;
|
|
}
|
|
}
|
|
else if(m_WasInTheAir.IsSet(footId))
|
|
{
|
|
stepType = (audFootstepEvent)(AUD_FOOTSTEP_JUMP_LAND_L + (footId % 2));
|
|
m_WasInTheAir.Clear(footId);
|
|
}
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddFootstepEvent(stepType);
|
|
if(m_pParentPed->GetPedResetFlag(CPED_RESET_FLAG_InContactWithFoliage) || m_pParentPed->GetPedResetFlag(CPED_RESET_FLAG_InContactWithBIGFoliage))
|
|
{
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddBushEvent(stepType, m_pParentPed->GetContactedFoliageHash());
|
|
}
|
|
if(!IsAnAnimal())
|
|
{
|
|
if(stepType != AUD_FOOTSTEP_SOFT_L && stepType != AUD_FOOTSTEP_SOFT_R)
|
|
{
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddClothEvent(stepType);
|
|
}
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddPetrolCanEvent(stepType);
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddMolotovEvent(stepType);
|
|
if(m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().ShouldScriptAddSweetenersEvents())
|
|
{
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddScriptSweetenerEvent(stepType);
|
|
}
|
|
}
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddWaterEvent(stepType);
|
|
|
|
if(m_IsWalkingOnSlope && (stepType != AUD_FOOTSTEP_SOFT_L && stepType != AUD_FOOTSTEP_SOFT_R))
|
|
{
|
|
if(audEngineUtil::ResolveProbability(sm_SlopeDebrisProb))
|
|
{
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddSlopeDebrisEvent(stepType,downSlopeDirection,m_SlopeAngle);
|
|
}
|
|
}
|
|
#if __BANK
|
|
if(sm_PauseOnFootstepEvents)
|
|
{
|
|
naDisplayf("[footSpeed = %f] [downSpeedEpsilon = %f] [upDistanceToGround = %f]", footSpeed.Getf(), m_pModPhys->Modes[detectionValuesIndex].DownSpeedEpsilon, upDistanceToGround);
|
|
Color32 color = Color_red;
|
|
if(stepType == AUD_FOOTSTEP_SOFT_L || stepType == AUD_FOOTSTEP_SOFT_R)
|
|
{
|
|
color = Color_green;
|
|
}
|
|
else if ( stepType == AUD_FOOTSTEP_JUMP_LAND_L || stepType == AUD_FOOTSTEP_JUMP_LAND_R )
|
|
{
|
|
color = Color_purple;
|
|
}
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.5f,0.f,0.f),color,color,25);
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.f,0.5f,0.f),color,color,25);
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.f,0.f,0.5f),color,color,25);
|
|
fwTimer::StartUserPause();
|
|
}else if (sm_ShowFootStepTuningInfo)
|
|
{
|
|
Color32 color = Color_red;
|
|
if(stepType == AUD_FOOTSTEP_SOFT_L || stepType == AUD_FOOTSTEP_SOFT_R)
|
|
{
|
|
color = Color_green;
|
|
}
|
|
else if ( stepType == AUD_FOOTSTEP_JUMP_LAND_L || stepType == AUD_FOOTSTEP_JUMP_LAND_R )
|
|
{
|
|
color = Color_purple;
|
|
}
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.5f,0.f,0.f),color,color,25);
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.f,0.5f,0.f),color,color,25);
|
|
grcDebugDraw::Line(heelPos,heelPos + Vec3V(0.f,0.f,0.5f),color,color,25);
|
|
}
|
|
#endif
|
|
if(m_HasIkResultsThisFrame)
|
|
{
|
|
ProcessFootstepVfx(stepType,hindFoot,footMatrix,footId,m_GroundNormal[footId]);
|
|
}
|
|
else
|
|
{
|
|
ProcessFootstepVfx(stepType,hindFoot,footMatrix,footId,m_GroundNormal[0]);
|
|
}
|
|
|
|
m_FootMoveState[footId] = kMovePlanted;
|
|
m_LastTimeFootPlanted[footId] = g_AudioEngine.GetSoundManager().GetTimeInMilliseconds(0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::SetSpeedSmootherRates()
|
|
{
|
|
u8 index = m_DetectionValuesIndices[audDVStop];
|
|
if(m_pParentPed->GetMotionData()->GetIsWalking())
|
|
{
|
|
index = m_DetectionValuesIndices[audDVWalk];
|
|
if(m_pParentPed->GetPedConfigFlag(CPED_CONFIG_FLAG_StairsDetected) || m_WasOnStairs)
|
|
{
|
|
index = m_DetectionValuesIndices[audDVStairsWalk];
|
|
}
|
|
else if(m_pParentPed->GetMotionData()->GetUsingStealth())
|
|
{
|
|
index = m_DetectionValuesIndices[audDVWalk];
|
|
//index = m_DetectionValuesIndices[audDVStealthWalk];
|
|
}
|
|
}
|
|
else if (m_pParentPed->GetMotionData()->GetIsRunning())
|
|
{
|
|
index = m_DetectionValuesIndices[audDVRun];
|
|
if(m_pParentPed->GetPedConfigFlag(CPED_CONFIG_FLAG_StairsDetected) || m_WasOnStairs)
|
|
{
|
|
index = m_DetectionValuesIndices[audDVStairsRun];
|
|
}
|
|
else if(m_pParentPed->GetMotionData()->GetUsingStealth())
|
|
{
|
|
index = m_DetectionValuesIndices[audDVRun];
|
|
//index = m_DetectionValuesIndices[audDVStairsRun];
|
|
//index = m_DetectionValuesIndices[audDVStealthRun];
|
|
}
|
|
}
|
|
else if (m_pParentPed->GetMotionData()->GetIsSprinting())
|
|
{
|
|
index = m_DetectionValuesIndices[audDVSprint];
|
|
if(m_pParentPed->GetPedConfigFlag(CPED_CONFIG_FLAG_StairsDetected) || m_WasOnStairs)
|
|
{
|
|
index = m_DetectionValuesIndices[audDVStairsRun];
|
|
}
|
|
else if(m_pParentPed->GetMotionData()->GetUsingStealth())
|
|
{
|
|
index = m_DetectionValuesIndices[audDVStealthRun];
|
|
}
|
|
}
|
|
if(naVerifyf( m_pModPhys->numModes >= index,"Wrong footstep detection value index"))
|
|
{
|
|
m_PedVelocitySmoother.SetRates(m_pModPhys->Modes[index].SpeedSmootherIncreaseRate,m_pModPhys->Modes[index].SpeedSmootherDecreaseRate);
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::UpdateFeetDetection(audFootstepEvent stepType,u8 detectionValuesIndex,Vec3V_In downSlopeDirection)
|
|
{
|
|
Vec4V groundPlane;
|
|
m_IsPlayingSwitchScene = false;
|
|
UpdatePhysicProbes(groundPlane);
|
|
Vec3V heelPos;
|
|
Vec3V boneVel;
|
|
|
|
//static const u32 feetTags[MAX_NUM_FEET] = {RearLeft ,RearRight,FrontLeft, FrontRight};
|
|
const u32 numFeet = m_pModPhys->NumFeet;
|
|
naAssertf(numFeet <= 4, "Creature with more than 4 feet found. This could lead to audio exceeding the bounds of an array!");
|
|
audFootstepEvent originalStep = stepType;
|
|
for(u32 uFootId = 0; uFootId < numFeet; uFootId++)
|
|
{
|
|
stepType = originalStep;
|
|
#if __BANK
|
|
if(!ShouldUpdateFoot(uFootId))
|
|
continue;
|
|
#endif
|
|
// Check if hind foot.
|
|
bool hindFoot = false;
|
|
if(m_pModPhys->NumFeet > 2)
|
|
{
|
|
hindFoot = (uFootId < 2);
|
|
}
|
|
// left or right step.
|
|
stepType = (audFootstepEvent) ((u32)stepType + (uFootId % 2));
|
|
Mat34V footMatrix = Mat34V(V_IDENTITY);
|
|
CalculateFootInfo((FeetTags)uFootId/*FeetTags(feetTags[uFootId])*/, footMatrix, boneVel);
|
|
heelPos = footMatrix.GetCol3Ref();
|
|
|
|
ScalarV_ConstRef fFootSpeed = Mag(boneVel);
|
|
eFootHeightState heightState = m_FootHeightState[uFootId];
|
|
if(m_HasIkResultsThisFrame)
|
|
{
|
|
groundPlane = Vec4V(Vec::V4PermuteTwo<Vec::X1,Vec::Y1,Vec::Z1,Vec::X2>( m_GroundNormal[0].GetIntrin128(),
|
|
(m_GroundNormal[0].GetX() * m_GroundPosition[0].GetX()
|
|
+ m_GroundNormal[0].GetY() * m_GroundPosition[0].GetY()
|
|
+ m_GroundNormal[0].GetZ() * m_GroundPosition[0].GetZ()).GetIntrin128() ));
|
|
}
|
|
|
|
ScalarV distanceToPlane = Subtract(Dot(groundPlane.GetXYZ(),heelPos),groundPlane.GetW());
|
|
const f32 upDistanceToGround = distanceToPlane.Getf();// groundPlane.DistanceToPlane(heelPos);
|
|
|
|
#if __BANK
|
|
if(m_IsWalkingOnSlope && sm_ShowSlopeInfo)
|
|
{
|
|
char txt[64];
|
|
formatf(txt,"Slope : [Angle %f] ",RtoD * m_SlopeAngle);
|
|
grcDebugDraw::AddDebugOutput(Color_white,txt);
|
|
}
|
|
#endif
|
|
if(m_IsPlayingSwitchScene && !m_ScriptForceStepType)
|
|
{
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVWalk];
|
|
}
|
|
else if(m_WasInTheAir.IsSet(uFootId))
|
|
{
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVJump];
|
|
}
|
|
else if (m_WasClimbingLadder.IsSet(uFootId))
|
|
{
|
|
detectionValuesIndex = m_DetectionValuesIndices[audDVLadder];
|
|
}
|
|
// Moving or planted
|
|
eFootMoveState moveState = m_FootMoveState[uFootId];
|
|
switch (moveState)
|
|
{
|
|
case kMovePlanted:
|
|
{
|
|
UpdateFootPlanted(uFootId BANK_ONLY(,fFootSpeed), upDistanceToGround,detectionValuesIndex BANK_ONLY(,stepType),downSlopeDirection BANK_ONLY(,heelPos));
|
|
break;
|
|
}
|
|
case kMoveMoving:
|
|
{
|
|
UpdateFootMoving(uFootId,fFootSpeed, upDistanceToGround,detectionValuesIndex,stepType,downSlopeDirection,hindFoot,/*feetTags[*/uFootId/*]*/,footMatrix BANK_ONLY(,heelPos));
|
|
break;
|
|
}
|
|
}
|
|
m_FootHeightState[uFootId] = heightState;
|
|
//m_WasMoving = moving;
|
|
|
|
} // for(u32 i = 0; i < numBones; i++)
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::UpdateFootsteps()
|
|
{
|
|
// First of all check if the ped is in the air
|
|
if(m_pParentPed->GetPedConfigFlag( CPED_CONFIG_FLAG_IsInTheAir ))
|
|
{
|
|
// if the ped is in the air don't bother updating the footsteps
|
|
for(u32 i = 0; i < m_pModPhys->NumFeet ; i++)
|
|
{
|
|
m_WasInTheAir.Set(i);
|
|
m_FootMoveState[i] = kMoveMoving;
|
|
m_AlreadyTriggered.Clear(i);
|
|
}
|
|
m_AlreadyLanded = false;
|
|
m_WasClimbingLadder.Reset();
|
|
m_ClimbingLadder = false;
|
|
m_SlidingDownALadder = false;
|
|
if(m_pParentPed->GetPedAudioEntity())
|
|
{
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().StopLadderSlide();
|
|
}
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if( !m_AlreadyLanded)
|
|
{
|
|
m_AlreadyLanded = true;
|
|
m_TimeInTheAir = g_AudioEngine.GetSoundManager().GetTimeInMilliseconds(0) - m_LastTimeOnGround;
|
|
}
|
|
m_LastTimeOnGround = g_AudioEngine.GetSoundManager().GetTimeInMilliseconds(0);
|
|
if(m_pParentPed->GetIsSwimming())
|
|
{
|
|
m_WasInTheAir.Reset();
|
|
}
|
|
}
|
|
if(m_pParentPed->IsLocalPlayer())
|
|
{
|
|
if(m_pParentPed->GetIsArrested() || m_pParentPed->GetPedIntelligence()->GetQueriableInterface()->IsTaskCurrentlyRunning(CTaskTypes::TASK_BUSTED))
|
|
{
|
|
m_WasClimbingLadder.Reset();
|
|
m_ClimbingLadder = false;
|
|
m_SlidingDownALadder = false;
|
|
if(m_pParentPed->GetPedAudioEntity())
|
|
{
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().StopLadderSlide();
|
|
}
|
|
}
|
|
}
|
|
|
|
const CVehicle* vehiclePedEntering = m_pParentPed->GetVehiclePedEntering();
|
|
|
|
if (vehiclePedEntering)
|
|
{
|
|
// url:bugstar:6122431 - Special case, Formula car is super low to the ground and ped feet clip through the bottom when getting in/out, so just suppress footsteps while this is happening
|
|
if (vehiclePedEntering->GetModelNameHash() == ATSTRINGHASH("FORMULA", 0x1446590A) && m_pParentPed->GetPedResetFlag(CPED_RESET_FLAG_IsEnteringOrExitingVehicle))
|
|
{
|
|
bool isPedEnteringOrExitingVehicle = false;
|
|
|
|
if (m_pParentPed->GetPedIntelligence()->GetQueriableInterface()->IsTaskCurrentlyRunning(CTaskTypes::TASK_ENTER_VEHICLE))
|
|
{
|
|
CTaskEnterVehicle *task = (CTaskEnterVehicle*)m_pParentPed->GetPedIntelligence()->FindTaskActiveByType(CTaskTypes::TASK_ENTER_VEHICLE);
|
|
if (task && task->GetState() >= CTaskEnterVehicle::State_EnterSeat)
|
|
{
|
|
isPedEnteringOrExitingVehicle = true;
|
|
}
|
|
}
|
|
else if (m_pParentPed->GetPedIntelligence()->GetQueriableInterface()->IsTaskCurrentlyRunning(CTaskTypes::TASK_EXIT_VEHICLE))
|
|
{
|
|
CTaskExitVehicle *task = (CTaskExitVehicle*)m_pParentPed->GetPedIntelligence()->FindTaskActiveByType(CTaskTypes::TASK_EXIT_VEHICLE);
|
|
if (task && task->GetState() <= CTaskExitVehicle::State_ExitSeat)
|
|
{
|
|
isPedEnteringOrExitingVehicle = true;
|
|
}
|
|
}
|
|
|
|
if (isPedEnteringOrExitingVehicle)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (m_ClimbingLadder)
|
|
{
|
|
m_WasInTheAir.Reset();
|
|
m_TimeToResetLaddersFlag = 0;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
if(m_TimeToResetLaddersFlag == 0)
|
|
{
|
|
m_TimeToResetLaddersFlag = fwTimer::GetTimeInMilliseconds() + sm_DeltaTimeToResetLadders;
|
|
}
|
|
if(m_TimeToResetLaddersFlag < fwTimer::GetTimeInMilliseconds())
|
|
{
|
|
m_WasClimbingLadder.Reset();
|
|
m_SlidingDownALadder = false;
|
|
}
|
|
}
|
|
|
|
//Slopes
|
|
Vec3V downSlopeDirection (V_ONE_WZERO);
|
|
if(m_pParentPed->IsLocalPlayer())
|
|
{
|
|
UpdateSlopeDirection(downSlopeDirection);
|
|
}
|
|
|
|
f32 fLocalMoverSpeed = 0.f;
|
|
SetSpeedSmootherRates();
|
|
fLocalMoverSpeed = m_PedVelocitySmoother.CalculateValue(m_pParentPed->GetVelocity().Mag(),audNorthAudioEngine::GetTimeStep());
|
|
|
|
audFootstepEvent stepType = AUD_FOOTSTEP_SOFT_L;
|
|
u8 detectionValuesIndex = 0;
|
|
ComputeStepInfo(fLocalMoverSpeed,stepType,detectionValuesIndex);
|
|
if(audNorthAudioEngine::GetMicrophones().IsFirstPerson() && ( stepType == AUD_FOOTSTEP_SOFT_L || stepType == AUD_FOOTSTEP_SOFT_R))
|
|
{
|
|
UpdateSoftStepsFirstPerson();
|
|
}
|
|
else
|
|
{
|
|
UpdateFeetDetection(stepType,detectionValuesIndex,downSlopeDirection);
|
|
}
|
|
m_HasIkResultsThisFrame = false;
|
|
if(m_WasOnStairs && !m_pParentPed->GetPedConfigFlag(CPED_CONFIG_FLAG_StairsDetected))
|
|
{
|
|
m_TimeToResetStairsFlag += fwTimer::GetTimeStepInMilliseconds();
|
|
if(m_TimeToResetStairsFlag >= g_TimeToResetStairsFlagThreshold)
|
|
{
|
|
m_WasOnStairs = false;
|
|
}
|
|
}
|
|
else if(m_pParentPed->GetPedConfigFlag(CPED_CONFIG_FLAG_StairsDetected))
|
|
{
|
|
m_TimeToResetStairsFlag = 0;
|
|
m_WasOnStairs = true;
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::UpdateSoftStepsFirstPerson()
|
|
{
|
|
// We still need to update the feet position to properly place the footstep sounds.
|
|
Mat34V footMatrix = Mat34V(V_IDENTITY);
|
|
Vec3V boneVel = Vec3V(V_ZERO);
|
|
CalculateFootInfo(LeftFoot, footMatrix, boneVel);
|
|
CalculateFootInfo(RightFoot, footMatrix, boneVel);
|
|
|
|
const Vec3V north = Vec3V(0.0f, 1.0f, 0.0f);
|
|
const Vec3V front = NormalizeFast(g_AudioEngine.GetEnvironment().GetPanningListenerMatrix().b());
|
|
const f32 cosangle = fabs(Dot(front, north).Getf());
|
|
m_AccCosAngle += fabs(cosangle - m_PrevCosAngle);
|
|
m_PrevCosAngle = cosangle;
|
|
u32 currentTime = g_AudioEngine.GetSoundManager().GetTimeInMilliseconds(0);
|
|
u32 timeElapsed = currentTime - m_LastTimeSoftStepPlayed;
|
|
if ( m_AccCosAngle > 0.8f && timeElapsed > 500 )
|
|
{
|
|
m_AccCosAngle = 0.f;
|
|
m_LastTimeSoftStepPlayed = currentTime;
|
|
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddFootstepEvent(m_LastEvent);
|
|
if(m_pParentPed->GetPedResetFlag(CPED_RESET_FLAG_InContactWithFoliage) || m_pParentPed->GetPedResetFlag(CPED_RESET_FLAG_InContactWithBIGFoliage))
|
|
{
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddBushEvent(m_LastEvent, m_pParentPed->GetContactedFoliageHash());
|
|
}
|
|
if(!IsAnAnimal())
|
|
{
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddPetrolCanEvent(m_LastEvent);
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddMolotovEvent(m_LastEvent);
|
|
}
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().AddWaterEvent(m_LastEvent);
|
|
if(m_LastEvent == AUD_FOOTSTEP_SOFT_L)
|
|
{
|
|
m_LastEvent = AUD_FOOTSTEP_SOFT_R;
|
|
}
|
|
else
|
|
{
|
|
m_LastEvent = AUD_FOOTSTEP_SOFT_L;
|
|
}
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::UpdateSlopeDirection(Vec3V_InOut downSlopeDirection)
|
|
{
|
|
//First of all get the slope angle:
|
|
f32 mdo = sqrtf( m_pParentPed->GetGroundNormal().x * m_pParentPed->GetGroundNormal().x + m_pParentPed->GetGroundNormal().y * m_pParentPed->GetGroundNormal().y );
|
|
f32 angle = atan2( m_pParentPed->GetGroundNormal().z, mdo );
|
|
m_SlopeAngle = angle;
|
|
if( 90.f - fabs(RtoD * m_SlopeAngle) < sm_SlopeDAngleThreshold )
|
|
{
|
|
m_IsWalkingOnSlope = false;
|
|
}
|
|
else
|
|
{
|
|
m_IsWalkingOnSlope = true;
|
|
}
|
|
// Negate the angle to get the line downhill
|
|
m_SlopeAngle *= -1.f;
|
|
#if __BANK
|
|
if(sm_OverrideSlopeAngle)
|
|
{
|
|
m_SlopeAngle = DtoR * sm_OverriddenSlopeAngle;
|
|
}
|
|
#endif
|
|
// We are walking along a slope, compute a line down the slope plane where to place the sounds.
|
|
//Cross product between up and ground normal to get the direction of rotation.
|
|
Vec3V rotDirection = CrossZAxis(VECTOR3_TO_VEC3V(m_pParentPed->GetGroundNormal()));
|
|
f32 sinAngle = 0.f;
|
|
f32 cosAngle = 0.f;
|
|
rage::cos_and_sin(cosAngle,sinAngle,m_SlopeAngle);
|
|
QuatV rotation(rotDirection * ScalarV(sinAngle), ScalarV(cosAngle));
|
|
|
|
downSlopeDirection = Transform(rotation,VECTOR3_TO_VEC3V( m_pParentPed->GetGroundNormal()));
|
|
#if __BANK
|
|
if(sm_ShowSlopeInfo)
|
|
{
|
|
grcDebugDraw::Line(m_pParentPed->GetTransform().GetPosition(),m_pParentPed->GetTransform().GetPosition() + VECTOR3_TO_VEC3V(m_pParentPed->GetGroundNormal()),Color_YellowGreen);
|
|
grcDebugDraw::Line(m_pParentPed->GetTransform().GetPosition(),m_pParentPed->GetTransform().GetPosition() + ScalarV(V_TEN) * downSlopeDirection,Color_red);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void CPedFootStepHelper::GetSlopeDirection(Vec3V_InOut downSlopeDirection) const
|
|
{
|
|
// We are walking along a slope, compute a line down the slope plane where to place the sounds.
|
|
//Cross product between up and ground normal to get the direction of rotation.
|
|
Vec3V rotDirection = CrossZAxis(VECTOR3_TO_VEC3V(m_pParentPed->GetGroundNormal()));
|
|
f32 sinAngle = 0.f;
|
|
f32 cosAngle = 0.f;
|
|
rage::cos_and_sin(cosAngle,sinAngle,m_SlopeAngle);
|
|
QuatV rotation(rotDirection * ScalarV(sinAngle), ScalarV(cosAngle));
|
|
|
|
downSlopeDirection = Transform(rotation,VECTOR3_TO_VEC3V( m_pParentPed->GetGroundNormal()));
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::UpdateFootstepGroundTest(Vec3V_InOut groundPosition,Vec3V_InOut groundNormal)
|
|
{
|
|
|
|
#if __BANK
|
|
if(sm_DrawDebugInfo)
|
|
{
|
|
const Matrix34 &rootMatrix = MAT34V_TO_MATRIX34(m_pParentPed->GetTransform().GetMatrix());
|
|
Vector3 vecStart = rootMatrix.d;
|
|
Vector3 vecEnd = rootMatrix.d;
|
|
vecStart.z -= sm_FootStepLineTestStartOffset;
|
|
vecEnd.z = vecStart.z - sm_FootStepLineTestLong;
|
|
grcDebugDraw::Line(vecStart,vecEnd,Color_red,Color_red);
|
|
}
|
|
#endif
|
|
//Collect all the results we can from the CWorldProbeAsync
|
|
{
|
|
PF_FUNC(GetRes);
|
|
m_CachedLineTest.GetProbeResults();
|
|
}
|
|
//Check if we complete a new test and process it.
|
|
//Otherwise wait another frame until a new one is complete.
|
|
if(m_CachedLineTest.IsComplete())
|
|
{
|
|
// Process it
|
|
if (ProcessAsyncLineTestProbes())
|
|
{
|
|
#if __BANK
|
|
if(sm_DrawDebugInfo)
|
|
{
|
|
Vector3 headPos = m_pParentPed->GetBonePositionCached(BONETAG_HEAD);
|
|
|
|
grcDebugDraw::Sphere(headPos,0.4f,Color_green,true);
|
|
}
|
|
#endif
|
|
const Matrix34 &rootMatrix = MAT34V_TO_MATRIX34(m_pParentPed->GetTransform().GetMatrix());
|
|
// We have to store the new result by LRU scheme.
|
|
if(CPedFootStepHelper::sm_NumberOfTestResultStored < MAX_NUMBER_OF_GROUND_FOOTSTEPS_TESTS)
|
|
{
|
|
// No override needed.
|
|
for (s32 i = 0; i < MAX_NUMBER_OF_GROUND_FOOTSTEPS_TESTS; ++i )
|
|
{
|
|
if (CPedFootStepHelper::sm_GroundFootStepTests[i].height == -5000)
|
|
{
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].height = rootMatrix.d.GetZ();
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].numberOfHits = 1;
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].groundPos = VECTOR3_TO_VEC3V(m_CachedLineTest.m_GroundPosition);
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].groundNormal = VECTOR3_TO_VEC3V(m_CachedLineTest.m_GroundNormal);
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].entity = CPhysics::GetEntityFromInst(m_CachedLineTest.m_MainLineTest.m_Instance);
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].component = m_CachedLineTest.m_MainLineTest.m_Component;
|
|
CPedFootStepHelper::sm_GroundFootStepTests[i].materialId = m_CachedLineTest.m_MainLineTest.m_MaterialId;
|
|
CPedFootStepHelper::sm_NumberOfTestResultStored++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
s32 badCandidateIndex = 0;
|
|
for (s32 i = 0; i < MAX_NUMBER_OF_GROUND_FOOTSTEPS_TESTS; ++i )
|
|
{
|
|
// Look for a bad candidate so we'll override it if needed.
|
|
if(CPedFootStepHelper::sm_GroundFootStepTests[i].lastNumberOfHits < CPedFootStepHelper::sm_GroundFootStepTests[badCandidateIndex].lastNumberOfHits)
|
|
{
|
|
badCandidateIndex = i;
|
|
}
|
|
|
|
}
|
|
CPedFootStepHelper::sm_GroundFootStepTests[badCandidateIndex].height = rootMatrix.d.GetZ();
|
|
CPedFootStepHelper::sm_GroundFootStepTests[badCandidateIndex].numberOfHits = 1;
|
|
CPedFootStepHelper::sm_GroundFootStepTests[badCandidateIndex].lastNumberOfHits = 1;
|
|
CPedFootStepHelper::sm_GroundFootStepTests[badCandidateIndex].groundPos = VECTOR3_TO_VEC3V(m_CachedLineTest.m_GroundPosition);
|
|
CPedFootStepHelper::sm_GroundFootStepTests[badCandidateIndex].groundNormal = VECTOR3_TO_VEC3V(m_CachedLineTest.m_GroundNormal);
|
|
CPedFootStepHelper::sm_GroundFootStepTests[badCandidateIndex].entity = CPhysics::GetEntityFromInst(m_CachedLineTest.m_MainLineTest.m_Instance);
|
|
CPedFootStepHelper::sm_GroundFootStepTests[badCandidateIndex].component = m_CachedLineTest.m_MainLineTest.m_Component;
|
|
CPedFootStepHelper::sm_GroundFootStepTests[badCandidateIndex].materialId = m_CachedLineTest.m_MainLineTest.m_MaterialId;
|
|
|
|
}
|
|
Assertf((CPedFootStepHelper::sm_NumberOfTestResultStored<=MAX_NUMBER_OF_GROUND_FOOTSTEPS_TESTS),"Bad number of test on updateFootSteps");
|
|
groundPosition = VECTOR3_TO_VEC3V(m_CachedLineTest.m_GroundPosition);
|
|
groundNormal = VECTOR3_TO_VEC3V(m_CachedLineTest.m_GroundNormal);
|
|
if(m_pParentPed->GetPedAudioEntity())
|
|
{
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().SetStandingMaterial( m_CachedLineTest.m_MainLineTest.m_MaterialId
|
|
, CPhysics::GetEntityFromInst(m_CachedLineTest.m_MainLineTest.m_Instance),m_CachedLineTest.m_MainLineTest.m_Component);
|
|
}
|
|
m_HasResultThisFrame = true;
|
|
}
|
|
if(m_CachedLineTest.Clear())
|
|
{
|
|
PF_FUNC(IssueAsyncLineTProbes);
|
|
IssueAsyncLineTestProbes();
|
|
}
|
|
}
|
|
}
|
|
//-------------------- -----------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::UpdateUpDiffWithGround(/*const phBoundComposite *pRagdollBoundComp*/)
|
|
{
|
|
if(naVerifyf(m_pParentPed, "NULL ped pointer"))
|
|
{
|
|
/*atHashValue hashedPersonality(m_pParentPed->GetPedModelInfo()->GetPersonalitySettings().GetPersonalityNameHash());
|
|
if(hashedPersonality == g_AnimalPed)
|
|
{
|
|
if(pRagdollBoundComp && (pRagdollBoundComp->GetMaxNumBounds() >= RAGDOLL_BUTTOCKS))
|
|
{
|
|
Matrix34 rootMatrix = RCC_MATRIX34(pRagdollBoundComp->GetCurrentMatrix(RAGDOLL_BUTTOCKS));
|
|
const Matrix34& currWorldMatrix = MAT34V_TO_MATRIX34(m_pParentPed->GetRagdollInst()->GetMatrix());
|
|
rootMatrix.Dot(currWorldMatrix);
|
|
m_UpDiffWihtGround = rootMatrix.c.Dot(m_pParentPed->GetGroundNormal());
|
|
m_UpDiffWihtGround = fabs(m_UpDiffWihtGround);
|
|
}
|
|
}
|
|
else*/
|
|
{
|
|
Matrix34 rootMatrix = M34_IDENTITY;
|
|
m_pParentPed->GetBoneMatrix(rootMatrix,BONETAG_ROOT);
|
|
m_UpDiffWihtGround = rootMatrix.c.Dot(m_pParentPed->GetGroundNormal());
|
|
m_UpDiffWihtGround = fabs(m_UpDiffWihtGround);
|
|
}
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::Update()
|
|
{
|
|
if (!m_pModPhys)
|
|
{
|
|
InitializeModelPhysics();
|
|
}
|
|
UpdatePrivate();
|
|
m_PrevHeight = m_pParentPed->GetTransform().GetPosition().GetZf();
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::UpdatePrivate()
|
|
{
|
|
if(m_pModPhys && (m_pModPhys->NumFeet != 0) && sm_UseProceduralFootsteps && !m_pParentPed->m_nDEflags.bFrozenByInterior
|
|
&& ((!m_pParentPed->GetIsInVehicle() && !audPedAudioEntity::GetBJVehicle()) || (m_pParentPed->GetIsInVehicle() && m_pParentPed->GetPedResetFlag(CPED_RESET_FLAG_IsEnteringOrExitingVehicle))))
|
|
{
|
|
if(IsAudioHLOD() || m_ScriptForceUpdate || m_VfxWantsToUpdate || audNorthAudioEngine::GetMicrophones().IsVisibleBySniper((CEntity*)m_pParentPed))
|
|
{
|
|
//g_Count++;
|
|
//naDisplayf("Frame %u Count %u Ped %u",fwTimer::GetFrameCount(),g_Count,&m_pParentPed);
|
|
if(!m_pParentPed->GetIsSwimming())
|
|
{
|
|
//Vector3 headPos = m_pParentPed->GetBonePositionCached(BONETAG_HEAD);
|
|
//grcDebugDraw::Sphere(headPos,0.2f,Color32(0.f,255.f,0.f,128.f),false);
|
|
UpdateFootsteps();
|
|
// if the ped has only 2 feet, update the position of the hands, the update footstep call is not doing it.
|
|
if(m_pModPhys->NumFeet == 2 && !IsAnAnimal())
|
|
{
|
|
UpdateHandPositions();
|
|
}
|
|
}
|
|
else if(m_WasInTheAir.IsSet(0) || m_WasInTheAir.IsSet(1))
|
|
{
|
|
m_WasInTheAir.Reset();
|
|
if(m_pParentPed->GetPedAudioEntity())
|
|
{
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().ShouldTriggerFallInWaterSplash();
|
|
}
|
|
}
|
|
m_IsAudioHLOD = false;
|
|
}
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::InitializeModelPhysics()
|
|
{
|
|
if(m_pParentPed->GetPedModelInfo())
|
|
{
|
|
m_pModPhys = audNorthAudioEngine::GetObject<ModelPhysicsParams>(m_pParentPed->GetPedModelInfo()->GetHashKey());
|
|
}
|
|
if(m_pModPhys == NULL)
|
|
{
|
|
if (!IsAnAnimal())
|
|
{
|
|
m_pModPhys = audNorthAudioEngine::GetObject<ModelPhysicsParams>(ATSTRINGHASH("DEFAULT_MODEL", 0x0d2bc59f5));
|
|
}
|
|
else
|
|
{
|
|
//m_pModPhys = audNorthAudioEngine::GetObject<ModelPhysicsParams>(ATSTRINGHASH("DEFAULT_ANIMAL_MODEL", 0x9AC3F963));
|
|
naAssertf(false, "Missing animal physic parameters for %s",m_pParentPed->GetPedModelInfo()->GetModelName());
|
|
}
|
|
}
|
|
if(naVerifyf(m_pModPhys,"All peds need a modelPhysicsParams object, please bug the audio team."))
|
|
{
|
|
m_pParentPed->GetPedAudioEntity()->GetFootStepAudio().InitModelSpecifics();
|
|
InitDetectionValuesIndices();
|
|
// Set up the feet offsets for the ped
|
|
m_FeetOffsets[LeftHand].front = m_pParentPed->GetPedModelInfo()->GetFFrontOffset();
|
|
m_FeetOffsets[LeftHand].up = m_pParentPed->GetPedModelInfo()->GetFUpOffset();
|
|
m_FeetOffsets[RightHand].front = m_pParentPed->GetPedModelInfo()->GetFFrontOffset();
|
|
m_FeetOffsets[RightHand].up = m_pParentPed->GetPedModelInfo()->GetFUpOffset();
|
|
m_FeetOffsets[LeftFoot].front = m_pParentPed->GetPedModelInfo()->GetRFrontOffset();
|
|
m_FeetOffsets[LeftFoot].up = m_pParentPed->GetPedModelInfo()->GetRUpOffset();
|
|
m_FeetOffsets[RightFoot].front = m_pParentPed->GetPedModelInfo()->GetRFrontOffset();
|
|
m_FeetOffsets[RightFoot].up = m_pParentPed->GetPedModelInfo()->GetRUpOffset();
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
#if __BANK
|
|
bool CPedFootStepHelper::ShouldUpdateFoot(const u32 footId)
|
|
{
|
|
bool shouldUpdate = false;
|
|
if(sm_OnlyUpdateFLFoot)
|
|
{
|
|
if((m_pModPhys->NumFeet == 2 && footId == 0 ) || (m_pModPhys->NumFeet == 4 && footId == 2))
|
|
{
|
|
shouldUpdate = true;
|
|
}
|
|
}
|
|
else if (sm_OnlyUpdateFRFoot)
|
|
{
|
|
if((m_pModPhys->NumFeet == 2 && footId == 1 ) || (m_pModPhys->NumFeet == 4 && footId == 3))
|
|
{
|
|
shouldUpdate = true;
|
|
}
|
|
}
|
|
else if (sm_OnlyUpdateRLFoot)
|
|
{
|
|
if((m_pModPhys->NumFeet == 4 && footId == 0))
|
|
{
|
|
shouldUpdate = true;
|
|
}
|
|
}
|
|
else if (sm_OnlyUpdateRRFoot)
|
|
{
|
|
if((m_pModPhys->NumFeet == 4 && footId == 1))
|
|
{
|
|
shouldUpdate = true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
shouldUpdate = true;
|
|
}
|
|
return shouldUpdate;
|
|
}
|
|
void TogglePause(void)
|
|
{
|
|
fwTimer::EndUserPause();
|
|
}
|
|
//-------------------------------------------------------------------------------------------------------------------
|
|
void CPedFootStepHelper::AddWidgets(bkBank &bank)
|
|
{
|
|
bank.PushGroup("Peds footstep helper",false);
|
|
bank.PushGroup("Footstep detection",false);
|
|
bank.AddToggle("Draw HLOD peds", &sm_DrawHLODResults);
|
|
bank.AddSlider("Run fitness scale", &sm_RunFitnessScale, 0.f, 5.f, 0.001f);
|
|
bank.AddSlider("Animal fitness scale", &sm_AnimalFitnessScale, 0.f, 5.f, 0.001f);
|
|
bank.AddSlider("Foot lift", &sm_UpDistaneToTriggerLift, 0.f, 5.f, 0.001f);
|
|
bank.PushGroup("Slopes",false);
|
|
bank.AddToggle("Show slope info", &sm_ShowSlopeInfo);
|
|
bank.AddSlider("sm_SlopeDebrisProb", &sm_SlopeDebrisProb, 0.f, 1.f, 0.001f);
|
|
bank.AddToggle("sm_OverrideSlopeAngle", &sm_OverrideSlopeAngle);
|
|
bank.AddSlider("sm_OverriddenSlopeAngle", &sm_OverriddenSlopeAngle, -180.f, 360.f, 0.001f);
|
|
bank.AddSlider("Slope angle (degrees) threshold", &sm_SlopeDAngleThreshold, 0.f, 360.f, 1.f);
|
|
bank.AddToggle("Override slope variables", &sm_OverrideSlopeVariables);
|
|
bank.AddSlider("sm_OverriddenMovementFactor", &sm_OverriddenMovementFactor, 0.f, 1.f, 0.001f);
|
|
bank.AddSlider("sm_DeltaTimeToResetLadders", &sm_DeltaTimeToResetLadders, 0, 5000, 1);
|
|
bank.PopGroup();
|
|
bank.AddToggle("Only Update FL Foot", &sm_OnlyUpdateFLFoot);
|
|
bank.AddToggle("Only Update FR Foot", &sm_OnlyUpdateFRFoot);
|
|
bank.AddToggle("Only Update RL Foot", &sm_OnlyUpdateRLFoot);
|
|
bank.AddToggle("Only Update RR Foot", &sm_OnlyUpdateRRFoot);
|
|
bank.AddSeparator();
|
|
bank.AddSlider("g_TimeToResetStairsFlagThreshold", &g_TimeToResetStairsFlagThreshold, 0, 3000, 100);
|
|
|
|
bank.AddToggle("Show footstep tuning info", &sm_ShowFootStepTuningInfo);
|
|
bank.AddSlider("sm_StairsDeltaSpeed", &sm_StairsDeltaSpeed, 0.f, 10.f, 0.001f);
|
|
|
|
bank.AddToggle("Pause On state limits", &sm_PauseOnLimits);
|
|
bank.AddToggle("Pause On Footstep Event", &sm_PauseOnFootstepEvents);
|
|
bank.AddToggle("Pause On Drag Event", &sm_PauseOnDragEvents);
|
|
bank.AddSlider("sm_DeltaAimSpeed", &sm_DeltaAimSpeed, 0.f, 2.f, 0.001f);
|
|
|
|
bank.AddButton("Toggle Pause", datCallback(CFA(TogglePause)));
|
|
bank.AddSeparator();
|
|
bank.AddToggle("Draw debug info", &sm_DrawDebugInfo);
|
|
bank.AddToggle("show ped velocities ", &sm_ShowPedSpeed);
|
|
bank.AddSlider("Trigger scuff threshold", &sm_TriggerScuffThresh, 0.f, 500.f, 1.f);
|
|
bank.PushGroup("Probes tests");
|
|
bank.AddSlider("g_FootStepLineTestStartOffset", &sm_FootStepLineTestStartOffset, 0.f, 2.f, 0.001f);
|
|
bank.AddSlider("g_FootStepLineTestLong", &sm_FootStepLineTestLong, 0.f, 2.f, 0.01f);
|
|
bank.AddSlider("g_FootStepHeightThreshold", &sm_FootStepHeightThreshold, 0.f, 10.f, 0.1f);
|
|
bank.AddToggle("Force all peds to use sync probes", &sm_ForceSyncProbesToAllPeds);
|
|
bank.AddSlider("Number of Intersections", &sm_NumIntersections, 0, 16, 1);
|
|
bank.AddToggle("Sync from rootBone", &sm_SyncProbesGroundTest);
|
|
bank.AddToggle("ASync from footsteps.+ height algorithm", &sm_AsyncProbesGroundTest);
|
|
bank.AddToggle("Draw results asyncTest", &sm_DrawResults);
|
|
bank.PopGroup();
|
|
bank.PopGroup();
|
|
bank.PushGroup("Footstep position calculation",false);
|
|
bank.AddToggle("Draw feet position", &sm_DrawFeetPosition);
|
|
bank.AddToggle("Draw feet velocity", &sm_DrawFeetVelocity);
|
|
bank.AddSeparator();
|
|
bank.AddToggle("Apply Heels Offset",&sm_ApplyHeelsOffsets);
|
|
bank.AddToggle("Apply High-Heels Offset",&sm_ApplyHighHeelsOffsets);
|
|
bank.AddSlider("Heels up offset",&sm_HeelUpOffset,-1.f,1.f,0.001f);
|
|
bank.AddSlider("Heels front offset",&sm_HeelFrontOffset,-1.f,1.f,0.001f);
|
|
bank.AddSlider("High-Heels front offset",&sm_HighHeelFrontOffset,-1.f,1.f,0.001f);
|
|
bank.AddSlider("High-Heels up offset",&sm_HighHeelUpOffset,-1.f,1.f,0.001f);
|
|
bank.AddToggle("Override Front foot offsets",&sm_OverrideFOffsets);
|
|
bank.AddSlider("Front foot up offset",&sm_FUpOffset,-1.f,1.f,0.001f);
|
|
bank.AddSlider("Front foot front offset",&sm_FFrontOffset,-1.f,1.f,0.001f);
|
|
bank.AddToggle("Override Rear foot offsets",&sm_OverrideROffsets);
|
|
bank.AddSlider("Rear foot up offset",&sm_RUpOffset,-1.f,1.f,0.001f);
|
|
bank.AddSlider("Rear foot front offset",&sm_RFrontOffset,-1.f,1.f,0.001f);
|
|
bank.AddSlider("MaxBoneVelocity INV", &sm_MaxBoneVelocityInv, 0.0001f, 100.f, 0.0001f);
|
|
bank.AddSlider("sm_SprintBoneSpeedScalar", &sm_SprintBoneSpeedScalar, 0.f, 100.f, 0.01f);
|
|
bank.AddSlider("sm_NonPlayerBoneSpeedScalar", &sm_NonPlayerBoneSpeedScalar, 0.f, 100.f, 0.01f);
|
|
bank.AddSlider("sm_MaxBoneSpeedDecrease", &sm_MaxBoneSpeedDecrease, 0.f, 10.f, 0.001f);
|
|
bank.PopGroup();
|
|
bank.PopGroup();
|
|
}
|
|
#endif
|