diff options
-rw-r--r-- | src/peds/CivilianPed.cpp | 2 | ||||
-rw-r--r-- | src/peds/Ped.cpp | 256 | ||||
-rw-r--r-- | src/peds/Ped.h | 18 | ||||
-rw-r--r-- | src/peds/PedIK.cpp | 1 |
4 files changed, 252 insertions, 25 deletions
diff --git a/src/peds/CivilianPed.cpp b/src/peds/CivilianPed.cpp index 3b1f9e1c..f28a1134 100644 --- a/src/peds/CivilianPed.cpp +++ b/src/peds/CivilianPed.cpp @@ -28,7 +28,7 @@ CCivilianPed::ProcessNearestFreePhone(int unused) if (gPhoneInfo.m_aPhones[phoneId].m_nState != PHONE_STATE_FREE) return false; - field_31C = 1; + bRunningToPhone = true; SetMoveState(PEDMOVE_RUN); SetSeek(gPhoneInfo.m_aPhones[phoneId].m_vecPos, 0.3f); m_phoneId = phoneId; diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 7b4fb412..f8b44301 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -49,6 +49,7 @@ WRAPPER bool CPed::Seek(void) { EAXJMP(0x4D1640); } WRAPPER void CPed::SetFollowPath(CVector) { EAXJMP(0x4D2EA0); } WRAPPER void CPed::RemoveInCarAnims(void) { EAXJMP(0x4E4E20); } WRAPPER void CPed::StartFightDefend(uint8, uint8, uint8) { EAXJMP(0x4E7780); } +WRAPPER void CPed::SetDirectionToWalkAroundObject(CEntity*) { EAXJMP(0x4CCEB0); } bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44; bool &CPed::bPedCheat2 = *(bool*)0x95CD5A; @@ -56,6 +57,7 @@ bool &CPed::bPedCheat3 = *(bool*)0x95CD59; CColPoint &CPed::ms_tempColPoint = *(CColPoint*)0x62DB14; +// TODO: PedAudioData should be hardcoded into exe, and it isn't reversed yet. CPedAudioData (&CPed::PedAudioData)[38] = *(CPedAudioData(*)[38]) * (uintptr*)0x5F94C4; uint16 &CPed::unknownFightThing = *(uint16*)0x95CC58; @@ -287,8 +289,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_fHealth = 100.0f; m_fArmour = 0.0f; m_nPedType = pedType; - m_currentSoundStart = 0; - m_talkTimer = 0; + m_lastSoundStart = 0; + m_soundStart = 0; m_lastQueuedSound = SOUND_TOTAL_PED_SOUNDS; m_queuedSound = SOUND_TOTAL_PED_SOUNDS; m_objective = OBJECTIVE_NONE; @@ -297,7 +299,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_leader = nil; m_pedInObjective = nil; m_carInObjective = nil; - bInVehicle = 0; + bInVehicle = false; m_pMyVehicle = nil; m_pVehicleAnim = nil; m_vecOffsetSeek.x = 0.0f; @@ -331,7 +333,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_vecSeekVehicle = CVector(0.0f, 0.0f, 0.0f); m_wepSkills = 0; field_318 = 1.0f; - field_31C = 0; + bRunningToPhone = false; m_phoneId = -1; m_lastAccident = 0; m_fleeFrom = nil; @@ -457,7 +459,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) DMAudio.SetEntityStatus(m_audioEntityId, 1); m_fearFlags = CPedType::GetThreats(m_nPedType); m_threatEntity = nil; - m_eventOrThread = CVector2D(0.0f, 0.0f); + m_eventOrThreat = CVector2D(0.0f, 0.0f); m_pEventEntity = nil; m_fAngleToEvent = 0.0f; m_numNearPeds = 0; @@ -469,8 +471,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_pPathNodesStates[i] = nil; } } - m_maxWeaponTypeAllowed = 0; - m_currentWeapon = 0; + m_maxWeaponTypeAllowed = WEAPONTYPE_UNARMED; + m_currentWeapon = WEAPONTYPE_UNARMED; m_storedWeapon = WEAPONTYPE_UNIDENTIFIED; for(int i = 0; i < WEAPONTYPE_TOTAL_INVENTORY_WEAPONS; i++) @@ -1616,6 +1618,16 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) } else { m_fRotationDest = veh->GetForward().Heading(); } + } else { + // I don't know will this part ever run(maybe boats?), but the game also handles that. I don't know is it intentional. + + if (vehIsUpsideDown) { + m_fRotationDest = veh->GetForward().Heading(); + } else if (veh->bIsBus) { + m_fRotationDest = 0.5f * PI + veh->GetForward().Heading(); + } else { + m_fRotationDest = veh->GetForward().Heading(); + } } if (!bInVehicle) @@ -1759,9 +1771,9 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) neededPos -= timeUntilStateChange * m_vecOffsetSeek; } - if (limitedAngle > PI + m_fRotationCur) { + if (PI + m_fRotationCur < limitedAngle) { limitedAngle -= 2 * PI; - } else if (limitedAngle < m_fRotationCur - PI) { + } else if (m_fRotationCur - PI > limitedAngle) { limitedAngle += 2 * PI; } m_fRotationCur -= (m_fRotationCur - limitedAngle) * (1.0f - timeUntilStateChange); @@ -1976,7 +1988,7 @@ CPed::BuildPedLists(void) static CPed *unsortedNearPeds[10]; uint16 nextNearPedSlot = 0; - if ((CTimer::GetFrameCounter() + m_randomSeed) % 16) { + if ((CTimer::GetFrameCounter() + (m_randomSeed % 256)) % 16) { for(int i = 0; i < 10; ) { if (m_nearPeds[i]) { @@ -2901,7 +2913,7 @@ CPed::CheckAroundForPossibleCollisions(void) CWorld::FindObjectsInRange(ourCentre, 10.0f, true, &maxObject, 6, objects, false, true, false, true, false); for (int i = 0; i < maxObject; i++) { CEntity *object = objects[i]; - if (field_31C) { + if (bRunningToPhone) { if (gPhoneInfo.PhoneAtThisPosition(object->GetPosition())) break; } @@ -3246,7 +3258,7 @@ CPed::SetDie(AnimationId animId, float delta, float speed) if (!bInVehicle) StopNonPartialAnims(); - // ??? + // BUG: This is not timer. m_bloodyFootprintCount = CTimer::GetTimeInMilliseconds(); } @@ -3343,7 +3355,7 @@ CPed::InflictDamage(CEntity* damagedBy, eWeaponType method, float damage, ePedPi if (IsPedHeadAbovePos(-0.3f)) { dieAnim = NUM_ANIMS; } else { - if (RpAnimBlendClumpGetFirstAssociation(GetClump(), 0x800u)) + if (RpAnimBlendClumpGetFirstAssociation(GetClump(), ASSOC_FLAG800)) dieAnim = ANIM_FLOOR_HIT_F; else dieAnim = ANIM_FLOOR_HIT; @@ -3818,7 +3830,7 @@ void CPed::ClearSeek(void) { SetIdle(); - field_31C = 0; + bRunningToPhone = false; } bool @@ -4294,7 +4306,7 @@ CPed::SetAttack(CEntity* victim) animAssoc->SetFinishCallback(FinishedAttackCB, this); } } else { - StartFightAttack(CGeneral::GetRandomNumber() & 255); + StartFightAttack(CGeneral::GetRandomNumber() % 256); } return; } @@ -5037,13 +5049,224 @@ CPed::Say(uint16 audio) if (audioToPlay < m_queuedSound) { if (audioToPlay != m_lastQueuedSound || audioToPlay == SOUND_PED_DEATH || PedAudioData[audioToPlay - SOUND_PED_DEATH].m_nOverrideMaxRandomDelayTime - + m_currentSoundStart + + m_lastSoundStart + (uint32) CGeneral::GetRandomNumberInRange(0, PedAudioData[audioToPlay - SOUND_PED_DEATH].m_nMaxRandomDelayTime) <= CTimer::GetTimeInMilliseconds()) { m_queuedSound = audioToPlay; } } } +void +CPed::CollideWithPed(CPed *collideWith) +{ + CAnimBlendAssociation *animAssoc; + AnimationId animToRun; + + bool weAreMissionChar = CharCreatedBy == MISSION_CHAR; + bool heIsMissionChar = collideWith->CharCreatedBy == MISSION_CHAR; + CVector posDiff = collideWith->GetPosition() - GetPosition(); + int waitTime = 0; + + if (weAreMissionChar || !collideWith->IsPlayer() || collideWith->m_nPedState != PED_MAKE_CALL) { + bool weDontLookToHim = DotProduct(posDiff, GetForward()) > 0.0f; + bool heLooksToUs = DotProduct(posDiff, collideWith->GetForward()) < 0.0f; + + if (m_nMoveState != PEDMOVE_NONE && m_nMoveState != PEDMOVE_STILL) { + + if ((!IsPlayer() || ((CPlayerPed*)this)->m_fMoveSpeed <= 1.8f) + && (IsPlayer() || heIsMissionChar && weAreMissionChar || m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT)) { + + if (m_objective != OBJECTIVE_FOLLOW_PED_IN_FORMATION && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT) { + + if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { + + if (heIsMissionChar || !weAreMissionChar && collideWith->m_nMoveState != PEDMOVE_STILL) { + + if (weAreMissionChar && ((m_nPedState == PED_SEEK_POS) || m_nPedState == PED_SEEK_ENTITY)) { + + if (collideWith->m_nMoveState != PEDMOVE_STILL + && (!collideWith->IsPlayer() || collideWith->IsPlayer() && CPad::GetPad(0)->ArePlayerControlsDisabled())) { + float weAndCarDist = (GetPosition() - m_vecSeekVehicle).MagnitudeSqr2D(); + float heAndCarDist = (collideWith->GetPosition() - m_vecSeekVehicle).MagnitudeSqr2D(); + + if (weAndCarDist <= heAndCarDist) { + waitTime = 1000; + collideWith->SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime); + collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime; + } else { + waitTime = 500; + SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime; + } + } else if (collideWith->m_nMoveState == PEDMOVE_STILL) { + SetDirectionToWalkAroundObject(collideWith); + } + } else if (weAreMissionChar || m_pedStats->m_fear <= 100 - collideWith->m_pedStats->m_temper + || (collideWith->IsPlayer() || collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) && + (!collideWith->IsPlayer() || ((CPlayerPed*)collideWith)->m_fMoveSpeed <= 1.0f)) { + SetDirectionToWalkAroundObject(collideWith); + if (!weAreMissionChar) + Say(SOUND_PED_CHAT); + } else { + SetEvasiveStep(collideWith, 2); + } + } else { + if (m_pedStats->m_temper <= m_pedStats->m_fear + || GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED + || weAreMissionChar + || collideWith->m_nPedType == PEDTYPE_CIVFEMALE + || collideWith->m_nPedType == m_nPedType + || collideWith->GetWeapon()->m_eWeaponType != WEAPONTYPE_UNARMED) { + SetDirectionToWalkAroundObject(collideWith); + Say(SOUND_PED_CHAT); + } else { + TurnBody(); + SetAttack(collideWith); + } + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + CGeneral::GetRandomNumberInRange(250, 450); + } + } + } else { + if (m_pedInObjective && collideWith == m_pedInObjective && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { + if (heLooksToUs) { + SetEvasiveStep(collideWith, 1); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000; + } + } else if (weDontLookToHim && IsPedInControl()) { + + if (m_pedStats != collideWith->m_pedStats) { + + if (collideWith->m_pedStats->m_fear <= 100 - m_pedStats->m_temper) { + + if (collideWith->IsPlayer()) { + // He's on our right side + if (DotProduct(posDiff,GetRight()) <= 0.0f) + m_fRotationCur -= m_headingRate; + else + m_fRotationCur += m_headingRate; + } else { + // He's on our right side + if (DotProduct(posDiff, GetRight()) <= 0.0f) + m_fRotationCur -= m_headingRate; + else + m_fRotationCur += m_headingRate; + } + } else { + SetLookFlag(collideWith, 0); + TurnBody(); + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_FIGHT_PPUNCH, 8.0f); + animAssoc->flags |= ASSOC_FADEOUTWHENDONE; + if (!heIsMissionChar) { + int direction = collideWith->GetLocalDirection(CVector2D(posDiff.x, posDiff.y)); + collideWith->StartFightDefend(direction, 4, 5); + } + } + } + } + } + } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar) { + // He looks us and we're not at his right side + if (heLooksToUs && DotProduct(posDiff,collideWith->GetRight()) > 0.0f) { + CVector moveForce = GetRight(); + moveForce.z += 0.1f; + ApplyMoveForce(moveForce); + if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT) + animToRun = ANIM_HIT_LEFT; + else + animToRun = ANIM_SHOT_LEFT_PARTIAL; + } else if (heLooksToUs) { + CVector moveForce = GetRight() * -1.0f; + moveForce.z += 0.1f; + ApplyMoveForce(moveForce); + if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT) + animToRun = ANIM_HIT_RIGHT; + else + animToRun = ANIM_SHOT_RIGHT_PARTIAL; + } else { + if (collideWith->m_nMoveState != PEDMOVE_RUN && collideWith->m_nMoveState != PEDMOVE_SPRINT) + animToRun = ANIM_HIT_BACK; + else + animToRun = ANIM_SHOT_BACK_PARTIAL; + } + + if (collideWith->IsPedInControl() && CTimer::GetTimeInMilliseconds() > collideWith->m_nPedStateTimer) { + animAssoc = CAnimManager::BlendAnimation(collideWith->GetClump(), ASSOCGRP_STD, animToRun, 8.0f); + animAssoc->flags |= ASSOC_FADEOUTWHENDONE; + collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 1000; + if (m_nPedState == PED_ATTACK) + DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f); + } + } else { + // We're at his right side + if (DotProduct(posDiff, collideWith->GetRight()) <= 0.0f) { + CVector moveForce = GetRight() * -1.0f; + moveForce.z += 0.1f; + ApplyMoveForce(moveForce); + if (heLooksToUs) + animToRun = ANIM_KO_SPIN_L; + else + animToRun = ANIM_KD_RIGHT; + } else { + CVector moveForce = GetRight(); + moveForce.z += 0.1f; + ApplyMoveForce(moveForce); + if (heLooksToUs) + animToRun = ANIM_KO_SPIN_R; + else + animToRun = ANIM_KD_LEFT; + } + + if (m_nPedState == PED_ATTACK && collideWith->IsPedInControl()) + DMAudio.PlayOneShot(m_audioEntityId, SOUND_FIGHT_PUNCH_39, 0.0f); + + collideWith->SetFall(3000, animToRun, 0); + } + } else { + if (!IsPedInControl()) + return; + + if (collideWith->m_nMoveState == PEDMOVE_NONE || collideWith->m_nMoveState == PEDMOVE_STILL) + return; + + if (m_nPedType != collideWith->m_nPedType || m_nPedType == PEDTYPE_CIVMALE || m_nPedType == PEDTYPE_CIVFEMALE) { + + if (!weAreMissionChar && heLooksToUs && m_pedStats->m_fear > 100 - collideWith->m_pedStats->m_temper) { + + if (CGeneral::GetRandomNumber() & 1 && CTimer::GetTimeInMilliseconds() < m_nPedStateTimer){ + SetEvasiveStep(collideWith, 2); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000; + } else if (collideWith->m_nMoveState > PEDMOVE_WALK) { + waitTime = 2000; + SetWaitState(WAITSTATE_PLAYANIM_DUCK, &waitTime); + } + } + } else if (heLooksToUs + && collideWith->m_nPedState != PED_STEP_AWAY + && m_nPedState != PED_STEP_AWAY + && CTimer::GetTimeInMilliseconds() > m_nPedStateTimer) { + + SetEvasiveStep(collideWith, 1); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 3000; + } + } + + if (IsPlayer()) { + SetLookFlag(collideWith, 1); + SetLookTimer(800); + } + } else { + bool doWeRun = true; + if (m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT) + doWeRun = false; + + SetFlee(collideWith, 5000); + bIsFleeing = true; + m_pLastPathNode = nil; + if (!doWeRun) + SetMoveState(PEDMOVE_WALK); + } +} + WRAPPER void CPed::PedGetupCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE810); } WRAPPER void CPed::PedStaggerCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8D0); } WRAPPER void CPed::PedEvadeCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D36E0); } @@ -5185,4 +5408,5 @@ STARTPATCHES InjectHook(0x4D58D0, &CPed::SetWaitState, PATCH_JUMP); InjectHook(0x4D1D70, (void (CPed::*)(CEntity*, int)) &CPed::SetFlee, PATCH_JUMP); InjectHook(0x4D1C40, (void (CPed::*)(CVector2D&, int)) &CPed::SetFlee, PATCH_JUMP); + InjectHook(0x4EB9A0, &CPed::CollideWithPed, PATCH_JUMP); ENDPATCHES
\ No newline at end of file diff --git a/src/peds/Ped.h b/src/peds/Ped.h index c526d023..dcbe247a 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -352,7 +352,7 @@ public: uint32 m_pedFormation; uint32 m_fearFlags; CEntity *m_threatEntity; - CVector2D m_eventOrThread; + CVector2D m_eventOrThreat; uint32 m_eventType; CEntity* m_pEventEntity; float m_fAngleToEvent; @@ -405,7 +405,7 @@ public: bool bInVehicle; uint8 pad_315[3]; float field_318; - uint8 field_31C; // may be cutscene or phone cutscene status + bool bRunningToPhone; uint8 field_31D; int16 m_phoneId; uint32 m_lookingForPhone; // unused @@ -437,7 +437,7 @@ public: int8 m_fightUnk2; // TODO uint8 m_fightUnk1; // TODO uint8 pad_4B3; - CFire* m_pFire; + CFire *m_pFire; CEntity *m_pLookTarget; float m_fLookDirection; int32 m_wepModelID; @@ -452,16 +452,16 @@ public: uint32 m_duckTimer; uint32 field_4E8; int32 m_bloodyFootprintCount; - uint8 stuff9[2]; + uint8 m_panicCounter; + uint8 m_deadBleeding; int8 m_bodyPartBleeding; // PedNode uint8 m_field_4F3; CPed *m_nearPeds[10]; uint16 m_numNearPeds; int8 m_lastWepDam; uint8 pad_51F; - uint8 m_currentSoundStart; - uint8 pad_521[3]; - uint32 m_talkTimer; + uint32 m_lastSoundStart; + uint32 m_soundStart; uint16 m_lastQueuedSound; uint16 m_queuedSound; CVector m_vecSeekPosEx; @@ -586,6 +586,9 @@ public: void SetFall(int, AnimationId, uint8); void SetFlee(CEntity*, int); void SetFlee(CVector2D&, int); + void RemoveInCarAnims(void); + void CollideWithPed(CPed*); + void SetDirectionToWalkAroundObject(CEntity*); // Static methods static CVector GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset); @@ -642,7 +645,6 @@ public: void SetLeader(CEntity* leader); void SetPedStats(ePedStats); bool IsGangMember(void); - void RemoveInCarAnims(void); bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; } CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; } diff --git a/src/peds/PedIK.cpp b/src/peds/PedIK.cpp index 768e0bf0..8909fcc4 100644 --- a/src/peds/PedIK.cpp +++ b/src/peds/PedIK.cpp @@ -8,6 +8,7 @@ WRAPPER bool CPedIK::PointGunAtPosition(CVector *position) { EAXJMP(0x4ED920); } WRAPPER void CPedIK::ExtractYawAndPitchLocal(RwMatrixTag*, float*, float*) { EAXJMP(0x4ED2C0); } WRAPPER void CPedIK::ExtractYawAndPitchWorld(RwMatrixTag*, float*, float*) { EAXJMP(0x4ED140); } +// TODO: Hardcoded into exe, reverse it. LimbMovementInfo &CPedIK::ms_torsoInfo = *(LimbMovementInfo*)0x5F9F8C; CPedIK::CPedIK(CPed *ped) |