From c03efd0aa152ed3c82d8990ac208933baebc826e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sun, 29 Sep 2019 19:44:51 +0300 Subject: [PATCH] Moar peds --- src/audio/DMAudio.h | 18 +- src/math/Matrix.h | 1 + src/math/math.cpp | 6 + src/peds/Ped.cpp | 793 +++++++++++++++++++++++++++++++++++++---- src/peds/Ped.h | 28 +- src/peds/PlayerPed.cpp | 2 +- src/peds/PlayerPed.h | 2 +- 7 files changed, 755 insertions(+), 95 deletions(-) diff --git a/src/audio/DMAudio.h b/src/audio/DMAudio.h index 42dd9ef4..fe120576 100644 --- a/src/audio/DMAudio.h +++ b/src/audio/DMAudio.h @@ -101,25 +101,25 @@ enum eSound : int16 SOUND_EVIDENCE_PICKUP = 94, SOUND_UNLOAD_GOLD = 95, SOUND_PAGER = 96, - SOUND_PED_DEATH = 97, - SOUND_PED_DAMAGE = 98, - SOUND_PED_HIT = 99, - SOUND_PED_LAND = 100, + SOUND_PED_DEATH = 97, // 103 in VC + SOUND_PED_DAMAGE = 98, // 104 in VC + SOUND_PED_HIT = 99, // 105 in VC + SOUND_PED_LAND = 100, // hopefully 106 in VC SOUND_PED_BULLET_HIT = 101, SOUND_PED_BOMBER = 102, - SOUND_PED_BURNING = 103, + SOUND_PED_BURNING = 103, // 108 in VC SOUND_PED_ARREST_FBI = 104, SOUND_PED_ARREST_SWAT = 105, SOUND_PED_ARREST_COP = 106, SOUND_PED_HELI_PLAYER_FOUND = 107, SOUND_PED_HANDS_UP = 108, SOUND_PED_HANDS_COWER = 109, - SOUND_PED_FLEE_SPRINT = 110, + SOUND_PED_FLEE_SPRINT = 110, // 120 in VC SOUND_PED_CAR_JACKING = 111, SOUND_PED_MUGGING = 112, SOUND_PED_CAR_JACKED = 113, SOUND_PED_ROBBED = 114, - SOUND_PED_TAXI_WAIT = 115, + SOUND_PED_TAXI_WAIT = 115, // 137 in VC SOUND_PED_ATTACK = 116, SOUND_PED_DEFEND = 117, SOUND_PED_PURSUIT_ARMY = 118, @@ -129,9 +129,9 @@ enum eSound : int16 SOUND_PED_HEALING = 122, SOUND_PED_7B = 123, SOUND_PED_LEAVE_VEHICLE = 124, - SOUND_PED_EVADE = 125, + SOUND_PED_EVADE = 125, // 142 in VC SOUND_PED_FLEE_RUN = 126, - SOUND_PED_CAR_COLLISION = 127, + SOUND_PED_CAR_COLLISION = 127, // 144-145-146 in VC SOUND_PED_SOLICIT = 128, SOUND_PED_EXTINGUISHING_FIRE = 129, SOUND_PED_WAIT_DOUBLEBACK = 130, diff --git a/src/math/Matrix.h b/src/math/Matrix.h index 7d8c02ab..5a3473ad 100644 --- a/src/math/Matrix.h +++ b/src/math/Matrix.h @@ -213,6 +213,7 @@ public: void SetRotate(float xAngle, float yAngle, float zAngle); void Rotate(float x, float y, float z); void RotateX(float x); + void RotateZ(float z); void Reorthogonalise(void); void CopyOnlyMatrix(CMatrix *other){ diff --git a/src/math/math.cpp b/src/math/math.cpp index 66260709..0707e3d2 100644 --- a/src/math/math.cpp +++ b/src/math/math.cpp @@ -46,6 +46,12 @@ CMatrix::RotateX(float x) Rotate(x, 0.0f, 0.0f); } +void +CMatrix::RotateZ(float z) +{ + Rotate(0.0f, 0.0f, z); +} + void CMatrix::Reorthogonalise(void) { diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 94b45cd6..be0ebd45 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -54,7 +54,6 @@ WRAPPER void CPed::SetFollowRoute(int16, int16) { EAXJMP(0x4DD690); } WRAPPER void CPed::SetDuck(uint32) { EAXJMP(0x4E4920); } WRAPPER void CPed::SetFollowPath(CVector) { EAXJMP(0x4D2EA0); } WRAPPER void CPed::StartFightDefend(uint8, uint8, uint8) { EAXJMP(0x4E7780); } -WRAPPER void CPed::SetDirectionToWalkAroundObject(CEntity*) { EAXJMP(0x4CCEB0); } WRAPPER void CPed::SetRadioStation(void) { EAXJMP(0x4D7BC0); } WRAPPER void CPed::ProcessBuoyancy(void) { EAXJMP(0x4C7FF0); } WRAPPER void CPed::ServiceTalking(void) { EAXJMP(0x4E5870); } @@ -69,6 +68,8 @@ WRAPPER void CPed::SetEnterCar(CVehicle*, uint32) { EAXJMP(0x4E0920); } WRAPPER bool CPed::WarpPedToNearEntityOffScreen(CEntity*) { EAXJMP(0x4E5570); } WRAPPER void CPed::SetExitCar(CVehicle*, uint32) { EAXJMP(0x4E1010); } +#define NEW_WALK_AROUND_ALGORITHM + CPed *gapTempPedList[50]; uint16 gnNumTempPedList; @@ -486,11 +487,11 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bHasACamera = false; m_ped_flagD2 = false; - m_ped_flagD4 = false; - m_ped_flagD8 = false; + bPedIsBleeding = false; + bStopAndShoot = false; bIsPedDieAnimPlaying = false; bUsePedNodeSeek = false; - m_ped_flagD40 = false; + bObjectiveCompleted = false; bScriptObjectiveCompleted = false; bKindaStayInSamePlace = false; @@ -508,7 +509,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_ped_flagF8 = false; bWillBeQuickJacked = false; bCancelEnteringCar = false; - m_ped_flagF40 = false; + bObstacleShowedUpDuringKillObjective = false; bDuckAndCover = false; m_ped_flagG1 = false; @@ -1695,7 +1696,6 @@ CPed::LineUpPedWithCar(PedLineUpPhase phase) CVehicle *veh = m_pMyVehicle; // Not quite right, IsUpsideDown func. checks for <= -0.9f. - // Since that function is also used in this file, doesn't this variable indicate upsidedownness?! if (veh->GetUp().z <= -0.8f) vehIsUpsideDown = true; @@ -2396,29 +2396,51 @@ CPed::CanPedDriveOff(void) return true; } +#ifdef VC_PED_PORTS bool +CPed::CanPedJumpThis(CEntity *unused, CVector *damageNormal = nil) +{ + if (m_nSurfaceTouched == SURFACE_PUDDLE) + return true; + + CVector pos = GetPosition(); + CVector forwardOffset = GetForward(); + if (damageNormal && damageNormal->z > 0.17f) { + if (damageNormal->z > 0.9f) + return false; + + CColModel *ourCol = CModelInfo::GetModelInfo(m_modelIndex)->GetColModel(); + pos.z = ourCol->spheres->center.z - ourCol->spheres->radius * damageNormal->z + pos.z; + pos.z = pos.z + 0.05f; + float collPower = damageNormal->Magnitude2D(); + if (damageNormal->z <= 0.5f) { + forwardOffset += collPower * ourCol->spheres->radius * forwardOffset; + } else { + CVector invDamageNormal(-damageNormal->x, -damageNormal->y, 0.0f); + invDamageNormal *= 1.0f / collPower; + CVector estimatedJumpDist = invDamageNormal + collPower * invDamageNormal * ourCol->spheres->radius; + forwardOffset = estimatedJumpDist * min(2.0f / collPower, 4.0f); + } + } else { + pos.z -= 0.15f; + } + + CVector forwardPos = pos + forwardOffset; + return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false); +} +#else CPed::CanPedJumpThis(CEntity *unused) { -#ifndef VC_PED_PORTS CVector2D forward(-Sin(m_fRotationCur), Cos(m_fRotationCur)); CVector pos = GetPosition(); CVector forwardPos( forward.x + pos.x, forward.y + pos.y, pos.z); -#else - if (m_nSurfaceTouched == SURFACE_PUDDLE) - return true; - // VC makes some other calculations if there is a CVector passed with function, which isn't possible here. - - CVector pos = GetPosition(); - pos.z -= 0.15f; - - CVector forwardPos = pos + GetForward(); -#endif return CWorld::GetIsLineOfSightClear(pos, forwardPos, true, false, false, true, false, false, false); } +#endif bool CPed::CanPedReturnToState(void) @@ -2551,7 +2573,7 @@ CPed::RestorePreviousObjective(void) m_objective = m_prevObjective; m_prevObjective = OBJECTIVE_NONE; } - m_ped_flagD40 = false; + bObjectiveCompleted = false; } void @@ -2623,7 +2645,7 @@ CPed::SetObjective(eObjective newObj, void *entity) return; } - m_ped_flagD40 = false; + bObjectiveCompleted = false; if (!IsTemporaryObjective(m_objective) || IsTemporaryObjective(newObj)) { if (m_objective != newObj) { if (IsTemporaryObjective(newObj)) @@ -2775,7 +2797,7 @@ CPed::SetObjective(eObjective newObj) m_objective = newObj; } - m_ped_flagD40 = false; + bObjectiveCompleted = false; switch (newObj) { case OBJECTIVE_NONE: @@ -2808,7 +2830,7 @@ CPed::SetObjective(eObjective newObj, int16 routePoint, int16 routeType) if (m_objective == newObj && newObj == OBJECTIVE_FOLLOW_ROUTE && m_routeLastPoint == routePoint && m_routeType == routeType) return; - m_ped_flagD40 = false; + bObjectiveCompleted = false; if (IsTemporaryObjective(m_objective)) { m_prevObjective = newObj; } else { @@ -4796,7 +4818,7 @@ CPed::GetLocalDirection(const CVector2D &posOffset) for (direction = (int)RADTODEG(direction) / 90; direction > 3; direction -= 4); - // Should be 0-east, 1-north, 2-west, 3-south. Not sure about order. + // 0-forward, 1-left, 2-backward, 3-right. return direction; } @@ -5263,6 +5285,8 @@ CPed::Say(uint16 audio) uint16 audioToPlay = audio; if (IsPlayer()) { + + // Ofc this part isn't in VC. switch (audio) { case SOUND_PED_DEATH: audioToPlay = SOUND_PED_DAMAGE; @@ -5284,14 +5308,27 @@ CPed::Say(uint16 audio) return; if (TheCamera.m_CameraAverageSpeed > 1.65f) { - return; +#ifdef VC_PED_PORTS + if (audio != SOUND_PED_DAMAGE && audio != SOUND_PED_HIT && audio != SOUND_PED_LAND) +#endif + return; + } else if (TheCamera.m_CameraAverageSpeed > 1.25f) { - if (audio != SOUND_PED_DEATH && audio != SOUND_PED_TAXI_WAIT && audio != SOUND_PED_EVADE) + if (audio != SOUND_PED_DEATH && +#ifdef VC_PED_PORTS + audio != SOUND_PED_DAMAGE && audio != SOUND_PED_HIT && audio != SOUND_PED_LAND && +#endif + audio != SOUND_PED_TAXI_WAIT && audio != SOUND_PED_EVADE) return; } else if (TheCamera.m_CameraAverageSpeed > 0.9f) { switch (audio) { case SOUND_PED_DEATH: +#ifdef VC_PED_PORTS + case SOUND_PED_DAMAGE: + case SOUND_PED_HIT: + case SOUND_PED_LAND: +#endif case SOUND_PED_BURNING: case SOUND_PED_FLEE_SPRINT: case SOUND_PED_TAXI_WAIT: @@ -5332,7 +5369,12 @@ CPed::CollideWithPed(CPed *collideWith) 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)) { + && (IsPlayer() || heIsMissionChar && weAreMissionChar || m_nMoveState != PEDMOVE_RUN && m_nMoveState != PEDMOVE_SPRINT +#ifdef VC_PED_PORTS + || m_objective == OBJECTIVE_FOLLOW_PED_IN_FORMATION && m_pedInObjective == collideWith + || collideWith->m_objective == OBJECTIVE_FOLLOW_PED_IN_FORMATION && collideWith->m_pedInObjective == this +#endif + )) { if (m_objective != OBJECTIVE_FOLLOW_PED_IN_FORMATION && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT) { @@ -5359,14 +5401,62 @@ CPed::CollideWithPed(CPed *collideWith) } 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); +#ifdef VC_PED_PORTS + if (FindPlayerPed() != m_pedInObjective + || m_objective != OBJECTIVE_KILL_CHAR_ANY_MEANS && m_objective != OBJECTIVE_KILL_CHAR_ON_FOOT + || collideWith == m_pedInObjective) { +#endif + 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); + } +#ifdef VC_PED_PORTS + } else if (collideWith->m_nMoveState != PEDMOVE_STILL && GetWeapon()->IsTypeMelee() + && collideWith->m_pedInObjective == m_pedInObjective) { + + int colliderIsAtPlayerSafePosID = -1; + int weAreAtPlayerSafePosID = -1; + for (int i = 0; i < 6; i++) { + CPed *pedAtSafePos = ((CPlayerPed*)m_pedInObjective)->m_pPedAtSafePos[i]; + if (pedAtSafePos == this) { + weAreAtPlayerSafePosID = i; + } else if (pedAtSafePos == collideWith) { + colliderIsAtPlayerSafePosID = i; + } + } + bool weAreCloserToTargetThenCollider = false; + if ((GetPosition() - m_vecSeekPos).MagnitudeSqr2D() < (collideWith->GetPosition() - m_vecSeekPos).MagnitudeSqr2D()) + weAreCloserToTargetThenCollider = true; + + if (weAreAtPlayerSafePosID <= 0 || weAreCloserToTargetThenCollider) { + if (!weAreCloserToTargetThenCollider) { + int time = 300; + SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time; + } + } else if (colliderIsAtPlayerSafePosID <= 0) { + if (collideWith->m_pedInObjective == FindPlayerPed()) { + // VC specific + // ((CPlayerPed*)m_pedInObjective)->RemovePedFromMeleeList(this); + int time = 500; + SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time; + } + } else { + int time = 300; + SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &time); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + time; + } + } else { + SetDirectionToWalkAroundObject(collideWith); + } +#endif } } else { if (m_pedStats->m_temper <= m_pedStats->m_fear @@ -5423,7 +5513,11 @@ CPed::CollideWithPed(CPed *collideWith) } } } - } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar) { + } else if (collideWith->m_pedStats->m_defendWeakness <= 1.5f || heIsMissionChar +#ifdef VC_PED_PORTS + || m_pedStats->m_defendWeakness <= collideWith->m_pedStats->m_defendWeakness +#endif + ) { // He looks us and we're not at his right side if (heLooksToUs && DotProduct(posDiff,collideWith->GetRight()) > 0.0f) { CVector moveForce = GetRight(); @@ -7378,8 +7472,8 @@ CPed::Flee(void) double angleToFleeDamagingThing = CGeneral::GetRadianAngleBetweenPoints( m_vecDamageNormal.x, m_vecDamageNormal.y, - 0.0, - 0.0); + 0.0f, + 0.0f); angleToFleeDamagingThing = CGeneral::LimitRadianAngle(angleToFleeDamagingThing); if (angleToFleeEntity - PI > angleToFleeDamagingThing) @@ -9150,19 +9244,30 @@ CPed::ProcessControl(void) break; } - float angleToFlee = CGeneral::GetRadianAngleBetweenPoints( + float angleToFaceWhenHit = CGeneral::GetRadianAngleBetweenPoints( GetPosition().x, GetPosition().y, m_vecDamageNormal.x + GetPosition().x, m_vecDamageNormal.y + GetPosition().y); - float neededTurn = Abs(m_fRotationCur - angleToFlee); + float neededTurn = Abs(m_fRotationCur - angleToFaceWhenHit); if (neededTurn > PI) neededTurn = TWOPI - neededTurn; float oldDestRot = CGeneral::LimitRadianAngle(m_fRotationDest); +#ifdef VC_PED_PORTS + if (m_nPedState == PED_FOLLOW_PATH) { + if (DotProduct(m_vecDamageNormal, GetForward()) < -0.866f && CanPedJumpThis(collidingEnt, &m_vecDamageNormal)) { + SetJump(); + + // Moved break into here, for compatibility with III + break; + } + // break; + } +#endif if (m_pedInObjective && (m_objective == OBJECTIVE_GOTO_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT)) { @@ -9410,7 +9515,6 @@ CPed::ProcessControl(void) DMAudio.PlayOneShot(collidingVeh->m_audioEntityId, SOUND_CAR_PED_COLLISION, adjustedImpulse); if (IsPlayer()) { - /* VC specific if (adjustedImpulse > 20.0f) adjustedImpulse = 20.0f; @@ -9418,9 +9522,9 @@ CPed::ProcessControl(void) if (adjustedImpulse <= 13.0f) playerSufferSound = true; else - Say(104); + Say(SOUND_PED_DAMAGE); } - */ + CColModel* collidingCol = CModelInfo::GetModelInfo(collidingVeh->m_modelIndex)->GetColModel(); CVector colMinVec = collidingCol->boundingBox.min; CVector colMaxVec = collidingCol->boundingBox.max; @@ -9433,15 +9537,15 @@ CPed::ProcessControl(void) float angleDiffFromLookingFrontTLVC = angleToVehFront - vehColCenterDist.Heading(); angleDiffFromLookingFrontTLVC = CGeneral::LimitRadianAngle(angleDiffFromLookingFrontTLVC); - // Not sure about this one - float minNeededTurnTLVC = Atan2(colMaxVec.x - colMinVec.x, colMaxVec.y - colMinVec.y); + // I don't know why do we use that + float vehTopRightHeading = Atan2(colMaxVec.x - colMinVec.x, colMaxVec.y - colMinVec.y); CVector vehDist = GetPosition() - collidingVeh->GetPosition(); vehDist.Normalise(); float vehRightVecAndSpeedDotProd; - if (Abs(angleDiffFromLookingFrontTLVC) >= minNeededTurnTLVC && Abs(angleDiffFromLookingFrontTLVC) < PI - minNeededTurnTLVC) { + if (Abs(angleDiffFromLookingFrontTLVC) >= vehTopRightHeading && Abs(angleDiffFromLookingFrontTLVC) < PI - vehTopRightHeading) { if (angleDiffFromLookingFrontTLVC <= 0.0f) { vehRightVecAndSpeedDotProd = DotProduct(collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed); @@ -9494,13 +9598,12 @@ CPed::ProcessControl(void) } /* VC specific - bPushedAlongByCar = true; + if (m_pCollidingEntity != collidingEnt) + bPushedAlongByCar = true; */ } - /* VC specific if (m_fHealth < oldHealth && playerSufferSound) - Say(105); - */ + Say(SOUND_PED_HIT); #else if (collidingVehSpeedSqr <= 1.0f / 400.0f) { if (!IsPedInControl() @@ -9566,15 +9669,15 @@ CPed::ProcessControl(void) float angleDiffFromLookingFrontTLVC = angleToVehFront - vehColCenterDist.Heading(); angleDiffFromLookingFrontTLVC = CGeneral::LimitRadianAngle(angleDiffFromLookingFrontTLVC); - // Not sure about this one - float minNeededTurnTLVC = Atan2(colMaxVec.x - colMinVec.x, colMaxVec.y - colMinVec.y); + // I don't know why do we use that + float vehTopRightHeading = Atan2(colMaxVec.x - colMinVec.x, colMaxVec.y - colMinVec.y); CVector vehDist = GetPosition() - collidingVeh->GetPosition(); vehDist.Normalise(); float vehRightVecAndSpeedDotProd; - if (Abs(angleDiffFromLookingFrontTLVC) >= minNeededTurnTLVC && Abs(angleDiffFromLookingFrontTLVC) < PI - minNeededTurnTLVC) { + if (Abs(angleDiffFromLookingFrontTLVC) >= vehTopRightHeading && Abs(angleDiffFromLookingFrontTLVC) < PI - vehTopRightHeading) { if (angleDiffFromLookingFrontTLVC <= 0.0f) { vehRightVecAndSpeedDotProd = DotProduct(collidingVeh->GetRight(), collidingVeh->m_vecMoveSpeed); @@ -9792,7 +9895,7 @@ CPed::ProcessControl(void) int16 padWalkX = pad0->GetPedWalkLeftRight(); int16 padWalkY = pad0->GetPedWalkUpDown(); if (Abs(padWalkX) > 0.0f || Abs(padWalkY) > 0.0f) { - m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0, 0.0, -padWalkX, padWalkY); + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(0.0f, 0.0f, -padWalkX, padWalkY); m_fRotationDest -= TheCamera.Orientation; m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest); m_fRotationCur = m_fRotationDest; @@ -10191,7 +10294,7 @@ CPed::ProcessControl(void) break; } SetMoveAnim(); - if (m_ped_flagD4) { + if (bPedIsBleeding) { if (CGame::nastyGame) { if (!(CTimer::GetFrameCounter() & 3)) { CVector cameraDist = GetPosition() - TheCamera.GetPosition(); @@ -12266,7 +12369,7 @@ CPed::ProcessObjective(void) } } else { ClearLookFlag(); - m_ped_flagD40 = true; + bObjectiveCompleted = true; } } case OBJECTIVE_KILL_CHAR_ON_FOOT: @@ -12279,7 +12382,7 @@ CPed::ProcessObjective(void) if (!m_pedInObjective || m_pedInObjective->DyingOrDead()) { ClearLookFlag(); - m_ped_flagD40 = true; + bObjectiveCompleted = true; SetMoveAnim(); break; } @@ -12342,7 +12445,7 @@ CPed::ProcessObjective(void) break; } if (m_pedInObjective->m_fHealth <= 0.0f) { - m_ped_flagD40 = true; + bObjectiveCompleted = true; bScriptObjectiveCompleted = true; SetMoveAnim(); break; @@ -12427,7 +12530,7 @@ CPed::ProcessObjective(void) return; } } - if (!bKindaStayInSamePlace && !m_ped_flagD8 && m_nPedState != PED_ATTACK && !killPlayerInNoPoliceZone) { + if (!bKindaStayInSamePlace && !bStopAndShoot && m_nPedState != PED_ATTACK && !killPlayerInNoPoliceZone) { if (distWithTargetSc > wepRange || m_pedInObjective->m_getUpTimer > CTimer::GetTimeInMilliseconds() || m_pedInObjective->m_nPedState == PED_ARRESTED @@ -12462,13 +12565,13 @@ CPed::ProcessObjective(void) SetCurrentWeapon(WEAPONTYPE_COLT45); } } else { - m_ped_flagD8 = true; + bStopAndShoot = true; } SetMoveState(PEDMOVE_STILL); SetMoveAnim(); break; } - m_ped_flagD8 = false; + bStopAndShoot = false; SetMoveAnim(); break; } @@ -12490,7 +12593,7 @@ CPed::ProcessObjective(void) GetPosition().x, GetPosition().y); SetShootTimer(CGeneral::GetRandomNumberInRange(0.0f, 500.0f)); SetAttackTimer(CGeneral::GetRandomNumberInRange(0.0f, 1500.0f)); - m_ped_flagF40 = false; + bObstacleShowedUpDuringKillObjective = false; } else { CVector target; @@ -12527,22 +12630,22 @@ CPed::ProcessObjective(void) time = CGeneral::GetRandomNumberInRange(1500.0f, 3000.0f); SetAttackTimer(time); - m_ped_flagF40 = false; + bObstacleShowedUpDuringKillObjective = false; } else if (foundEnt) { if (foundEnt->IsPed()) { SetAttackTimer(CGeneral::GetRandomNumberInRange(500.0f, 1000.0f)); - m_ped_flagF40 = false; + bObstacleShowedUpDuringKillObjective = false; } else { if (foundEnt->IsObject()) { SetAttackTimer(CGeneral::GetRandomNumberInRange(200.0f, 400.0f)); - m_ped_flagF40 = true; + bObstacleShowedUpDuringKillObjective = true; } else if (foundEnt->IsVehicle()) { SetAttackTimer(CGeneral::GetRandomNumberInRange(400.0f, 600.0f)); - m_ped_flagF40 = true; + bObstacleShowedUpDuringKillObjective = true; } else { SetAttackTimer(CGeneral::GetRandomNumberInRange(700.0f, 1200.0f)); - m_ped_flagF40 = true; + bObstacleShowedUpDuringKillObjective = true; } } @@ -12553,7 +12656,7 @@ CPed::ProcessObjective(void) } } else { if (!m_pedInObjective->m_pCurrentPhysSurface) - m_ped_flagD8 = false; + bStopAndShoot = false; if (m_nPedState != PED_ATTACK && m_nPedState != PED_FIGHT) { @@ -12575,7 +12678,7 @@ CPed::ProcessObjective(void) } } } - if (m_ped_flagF40) { + if (bObstacleShowedUpDuringKillObjective) { if (m_nPedType == PEDTYPE_COP) { if (GetWeapon()->m_eWeaponType > WEAPONTYPE_COLT45 || m_fleeFrom && m_fleeFrom->IsObject()) { @@ -12598,7 +12701,7 @@ CPed::ProcessObjective(void) } } else { if (m_nPedState != PED_SEEK_ENTITY && m_nPedState != PED_SEEK_POS - && !m_ped_flagD8 && !killPlayerInNoPoliceZone && !bKindaStayInSamePlace) { + && !bStopAndShoot && !killPlayerInNoPoliceZone && !bKindaStayInSamePlace) { Say(SOUND_PED_ATTACK); SetSeek(m_pedInObjective, wepRangeAdjusted); bIsRunning = true; @@ -12770,7 +12873,7 @@ CPed::ProcessObjective(void) case OBJECTIVE_ENTER_CAR_AS_DRIVER: { if (!m_carInObjective || bInVehicle) { - m_ped_flagD40 = true; + bObjectiveCompleted = true; bScriptObjectiveCompleted = true; RestorePreviousState(); } else { @@ -12847,7 +12950,7 @@ CPed::ProcessObjective(void) { if (!m_carInObjective) { ClearLookFlag(); - m_ped_flagD40 = true; + bObjectiveCompleted = true; break; } float distWithTargetSc = distWithTarget.Magnitude(); @@ -12969,7 +13072,7 @@ CPed::ProcessObjective(void) distWithTarget = m_nextRoutePointPos - GetPosition(); distWithTarget.z = 0.0f; if (sq(m_distanceToCountSeekDone) >= distWithTarget.MagnitudeSqr()) { - m_ped_flagD40 = true; + bObjectiveCompleted = true; bScriptObjectiveCompleted = true; SetMoveState(PEDMOVE_STILL); } else if (CTimer::GetTimeInMilliseconds() > m_nPedStateTimer || m_nPedState != PED_SEEK_POS) { @@ -13270,7 +13373,7 @@ CPed::ProcessObjective(void) } #endif } - if (m_ped_flagD40 + if (bObjectiveCompleted || m_objectiveTimer != 0 && CTimer::GetTimeInMilliseconds() > m_objectiveTimer) { RestorePreviousObjective(); if (m_objectiveTimer > CTimer::GetTimeInMilliseconds() || !m_objectiveTimer) @@ -13349,6 +13452,552 @@ CPed::SetExitTrain(CVehicle* train) } } +#ifdef NEW_WALK_AROUND_ALGORITHM +CVector +LocalPosForWalkAround(CVector2D colMin, CVector2D colMax, int walkAround) { + switch (walkAround) { + case 0: + case 1: + return CVector(colMin.x, colMax.y, 0.0f); + case 2: + case 3: + return CVector(colMax.x, colMax.y, 0.0f); + case 4: + case 5: + return CVector(colMax.x, colMin.y, 0.0f); + case 6: + case 7: + return CVector(colMin.x, colMin.y, 0.0f); + default: + // case 9: + return CVector(0.0f, 0.0f, 0.0f); // just a placeholder, supposed to be -GetForward(); + } +} +#endif + +// This function looks completely same on VC. +void +CPed::SetDirectionToWalkAroundObject(CEntity *obj) +{ + float distLimitForTimer = 8.0f; + CColModel *objCol = CModelInfo::GetModelInfo(obj->m_modelIndex)->GetColModel(); + CVector objColMin = objCol->boundingBox.min; + CVector objColMax = objCol->boundingBox.max; + CVector objColCenter = (objColMin + objColMax) / 2.0f; + CMatrix objMat(obj->GetMatrix()); + float dirToSet = obj->GetForward().Heading(); + bool objIsSeekTargetAndVan = false; + bool objIsSeekTarget = false; + bool objUpsideDown = false; + + float checkIntervalInDist = (objColMax.y - objColMin.y) * 0.1f; + float checkIntervalInTime; + + if (m_nMoveState == PEDMOVE_NONE || m_nMoveState == PEDMOVE_STILL) + return; + + if (CharCreatedBy != MISSION_CHAR && obj->m_modelIndex == MI_PHONEBOOTH1) { + bool isRunning = m_nMoveState == PEDMOVE_RUN || m_nMoveState == PEDMOVE_SPRINT; + SetFlee(obj, 5000); + bUsePedNodeSeek = true; + m_pNextPathNode = nil; + if (!isRunning) + SetMoveState(PEDMOVE_WALK); + return; + } + CVector2D adjustedColMin(objColMin.x - 0.35f, objColMin.y - 0.35f); + CVector2D adjustedColMax(objColMax.x + 0.35f, objColMax.y + 0.35f); + + checkIntervalInDist = max(checkIntervalInDist, 0.5f); + checkIntervalInDist = min(checkIntervalInDist, (objColMax.z - objColMin.z) / 2.0f); + checkIntervalInDist = min(checkIntervalInDist, (adjustedColMax.x - adjustedColMin.x) / 2.0f); + + if (objMat.GetUp().z < 0.0f) + objUpsideDown = true; + + if (obj->m_modelIndex != MI_TRAFFICLIGHTS && obj->m_modelIndex != MI_SINGLESTREETLIGHTS1 && obj->m_modelIndex != MI_SINGLESTREETLIGHTS2) { + objColCenter = obj->GetMatrix() * objColCenter; + } else { + checkIntervalInDist = 0.4f; + if (objMat.GetUp().z <= 0.57f) { + + // Specific calculations for traffic lights, didn't get a bit. + adjustedColMin.x = 1.2f * (adjustedColMin.x < adjustedColMin.y ? adjustedColMin.x : adjustedColMin.y); + adjustedColMax.x = 1.2f * (adjustedColMax.x > adjustedColMax.y ? adjustedColMax.x : adjustedColMax.y); + adjustedColMin.y = 1.2f * objColMin.z; + adjustedColMax.y = 1.2f * objColMax.z; + dirToSet = objMat.GetUp().Heading(); + objMat.SetUnity(); + objMat.RotateZ(dirToSet); + objMat.GetPosition() += obj->GetPosition(); + objColCenter = obj->GetPosition(); + } else { + objColCenter.x = adjustedColMax.x - 0.25f; + objColCenter = obj->GetMatrix() * objColCenter; + distLimitForTimer = 0.75f; + } + objUpsideDown = false; + } + float oldRotDest = m_fRotationDest; + float angleToFaceObjCenter = (objColCenter - GetPosition()).Heading(); + float angleDiffBtwObjCenterAndForward = CGeneral::LimitRadianAngle(dirToSet - angleToFaceObjCenter); + + // What is the purpose of using this? + float objTopRightHeading = Atan2(adjustedColMax.x - adjustedColMin.x, adjustedColMax.y - adjustedColMin.y); + + if (IsPlayer()) { + if (FindPlayerPed()->m_fMoveSpeed <= 0.0f) + checkIntervalInTime = 0.0f; + else + checkIntervalInTime = 2.0f / FindPlayerPed()->m_fMoveSpeed; + } else { + switch (m_nMoveState) { + case PEDMOVE_WALK: + checkIntervalInTime = 2.0f; + break; + case PEDMOVE_RUN: + checkIntervalInTime = 0.5f; + break; + case PEDMOVE_SPRINT: + checkIntervalInTime = 0.5f; + break; + default: + checkIntervalInTime = 0.0f; + break; + } + } + if (m_pSeekTarget == obj && obj->IsVehicle()) { + if (m_objective == OBJECTIVE_ENTER_CAR_AS_DRIVER || m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER + || m_objective == OBJECTIVE_SOLICIT) { + objIsSeekTarget = true; + if (IsPlayer()) + checkIntervalInTime = 0.0f; + + if (((CVehicle*)obj)->bIsVan) + objIsSeekTargetAndVan = true; + } + } + + int entityOnTopLeftOfObj = 0; + int entityOnBottomLeftOfObj = 0; + int entityOnTopRightOfObj = 0; + int entityOnBottomRightOfObj = 0; + + if (CTimer::GetTimeInMilliseconds() > m_collidingThingTimer || m_collidingEntityWhileFleeing != obj) { + bool collidingThingChanged = true; + CEntity *obstacle; + +#ifndef NEW_WALK_AROUND_ALGORITHM + if (!obj->IsVehicle() || objUpsideDown) { + collidingThingChanged = false; + } else { +#else + CVector cornerToGo; + int dirToGo; + m_walkAroundType = 0; +#endif + float adjustedCheckInterval = 0.7f * checkIntervalInDist; + CVector posToCheck; + + // Top left of obj + posToCheck.x = adjustedColMin.x + adjustedCheckInterval; + posToCheck.y = adjustedColMax.y - adjustedCheckInterval; + posToCheck.z = 0.0f; + posToCheck = objMat * posToCheck; + posToCheck.z += 0.6f; + obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj, + true, true, false, true, false, false); + if (obstacle) { + if (obstacle->IsBuilding()) { + entityOnTopLeftOfObj = 1; + } else if (obstacle->IsVehicle()) { + entityOnTopLeftOfObj = 2; + } else { + entityOnTopLeftOfObj = 3; + } + } +#ifdef NEW_WALK_AROUND_ALGORITHM + else { + CVector tl = obj->GetMatrix() * CVector(adjustedColMin.x, adjustedColMax.y, 0.0f) - GetPosition(); + cornerToGo = tl; + dirToGo = GetLocalDirection(tl); + if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) { + m_walkAroundType = 1; + } else { + if (dirToGo == 1) + m_walkAroundType = 0; // ALL of the next turns will be right turn + else if (dirToGo == 3) + m_walkAroundType = 1; // ALL of the next turns will be left turn + } + } +#endif + + // Top right of obj + posToCheck.x = adjustedColMax.x - adjustedCheckInterval; + posToCheck.y = adjustedColMax.y - adjustedCheckInterval; + posToCheck.z = 0.0f; + posToCheck = objMat * posToCheck; + posToCheck.z += 0.6f; + obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj, + true, true, false, true, false, false); + if (obstacle) { + if (obstacle->IsBuilding()) { + entityOnTopRightOfObj = 1; + } else if (obstacle->IsVehicle()) { + entityOnTopRightOfObj = 2; + } else { + entityOnTopRightOfObj = 3; + } + } +#ifdef NEW_WALK_AROUND_ALGORITHM + else { + CVector tr = obj->GetMatrix() * CVector(adjustedColMax.x, adjustedColMax.y, 0.0f) - GetPosition(); + if (tr.Magnitude2D() < cornerToGo.Magnitude2D()) { + cornerToGo = tr; + dirToGo = GetLocalDirection(tr); + if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) { + m_walkAroundType = 2; + } else { + if (dirToGo == 1) + m_walkAroundType = 2; // ALL of the next turns will be right turn + else if (dirToGo == 3) + m_walkAroundType = 3; // ALL of the next turns will be left turn + } + } + } +#endif + + // Bottom right of obj + posToCheck.x = adjustedColMax.x - adjustedCheckInterval; + posToCheck.y = adjustedColMin.y + adjustedCheckInterval; + posToCheck.z = 0.0f; + posToCheck = objMat * posToCheck; + posToCheck.z += 0.6f; + obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj, + true, true, false, true, false, false); + if (obstacle) { + if (obstacle->IsBuilding()) { + entityOnBottomRightOfObj = 1; + } else if (obstacle->IsVehicle()) { + entityOnBottomRightOfObj = 2; + } else { + entityOnBottomRightOfObj = 3; + } + } +#ifdef NEW_WALK_AROUND_ALGORITHM + else { + CVector br = obj->GetMatrix() * CVector(adjustedColMax.x, adjustedColMin.y, 0.0f) - GetPosition(); + if (br.Magnitude2D() < cornerToGo.Magnitude2D()) { + cornerToGo = br; + dirToGo = GetLocalDirection(br); + if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) { + m_walkAroundType = 5; + } else { + if (dirToGo == 1) + m_walkAroundType = 4; // ALL of the next turns will be right turn + else if (dirToGo == 3) + m_walkAroundType = 5; // ALL of the next turns will be left turn + } + } + } +#endif + + // Bottom left of obj + posToCheck.x = adjustedColMin.x + adjustedCheckInterval; + posToCheck.y = adjustedColMin.y + adjustedCheckInterval; + posToCheck.z = 0.0f; + posToCheck = objMat * posToCheck; + posToCheck.z += 0.6f; + obstacle = CWorld::TestSphereAgainstWorld(posToCheck, checkIntervalInDist, obj, + true, true, false, true, false, false); + if (obstacle) { + if (obstacle->IsBuilding()) { + entityOnBottomLeftOfObj = 1; + } else if (obstacle->IsVehicle()) { + entityOnBottomLeftOfObj = 2; + } else { + entityOnBottomLeftOfObj = 3; + } + } +#ifdef NEW_WALK_AROUND_ALGORITHM + else { + CVector bl = obj->GetMatrix() * CVector(adjustedColMin.x, adjustedColMin.y, 0.0f) - GetPosition(); + if (bl.Magnitude2D() < cornerToGo.Magnitude2D()) { + cornerToGo = bl; + dirToGo = GetLocalDirection(bl); + if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) { + m_walkAroundType = 6; + } else { + if (dirToGo == 1) + m_walkAroundType = 6; // ALL of the next turns will be right turn + else if (dirToGo == 3) + m_walkAroundType = 7; // ALL of the next turns will be left turn + } + } + } +#else + } +#endif + if (entityOnTopLeftOfObj && entityOnTopRightOfObj && entityOnBottomRightOfObj && entityOnBottomLeftOfObj) { + collidingThingChanged = false; + entityOnTopLeftOfObj = 0; + entityOnBottomLeftOfObj = 0; + entityOnTopRightOfObj = 0; + entityOnBottomRightOfObj = 0; + } + +#ifndef NEW_WALK_AROUND_ALGORITHM + if (!collidingThingChanged) { + m_walkAroundType = 0; + } else { + if (Abs(angleDiffBtwObjCenterAndForward) >= objTopRightHeading) { + if (PI - objTopRightHeading >= Abs(angleDiffBtwObjCenterAndForward)) { + if ((angleDiffBtwObjCenterAndForward <= 0.0f || objUpsideDown) && (angleDiffBtwObjCenterAndForward < 0.0f || !objUpsideDown)) { + if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)) { + m_walkAroundType = 0; + } else { + if (CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) >= 0.0f) { + if (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) { + m_walkAroundType = 1; + } else if (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) { + m_walkAroundType = 1; + } + } else { + if (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) { + m_walkAroundType = 4; + } else if (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) { + m_walkAroundType = 4; + } + } + } + } else { + if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR)) { + m_walkAroundType = 0; + } else { + if (CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) <= 0.0f) { + if (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) { + m_walkAroundType = 2; + } else if (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnTopRightOfObj) { + m_walkAroundType = 2; + } + } else { + if (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) { + m_walkAroundType = 3; + } else if (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnBottomRightOfObj && !entityOnBottomLeftOfObj) { + m_walkAroundType = 3; + } + } + } + } + } else if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) + || CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) < 0.0f) { + if (entityOnTopLeftOfObj == 1 || entityOnTopLeftOfObj && !entityOnTopRightOfObj && !entityOnBottomRightOfObj) { + m_walkAroundType = 3; + } + } else if (entityOnTopRightOfObj == 1 || entityOnTopRightOfObj && !entityOnTopLeftOfObj && !entityOnBottomLeftOfObj) { + m_walkAroundType = 4; + } + } else if (objIsSeekTarget && (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) + || CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) { + if (entityOnBottomLeftOfObj == 1 || entityOnBottomLeftOfObj && !entityOnTopRightOfObj && !entityOnBottomRightOfObj) { + m_walkAroundType = 2; + } + } else if (entityOnBottomRightOfObj == 1 || entityOnBottomRightOfObj && !entityOnTopLeftOfObj && !entityOnBottomLeftOfObj) { + m_walkAroundType = 1; + } else { + m_walkAroundType = 0; + } + } +#endif + } + m_collidingEntityWhileFleeing = obj; + m_collidingEntityWhileFleeing->RegisterReference((CEntity**) &m_collidingEntityWhileFleeing); + + // TODO: This random may need to be changed. + m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 512 + CGeneral::GetRandomNumber(); + + CVector localPosToHead; + +#ifdef NEW_WALK_AROUND_ALGORITHM + int nextWalkAround = m_walkAroundType; + if (m_walkAroundType % 2 == 0) { + nextWalkAround += 2; + if (nextWalkAround > 6) + nextWalkAround = 0; + } else { + nextWalkAround -= 2; + if (nextWalkAround < 0) + nextWalkAround = 7; + } + + if (CGeneral::GetRandomNumber() & 1){ + bool nextRouteIsClear = CWorld::GetIsLineOfSightClear(GetPosition(), objMat * LocalPosForWalkAround(adjustedColMin, adjustedColMax, nextWalkAround), + true, true, true, true, true, true, false); + if(nextRouteIsClear) + m_walkAroundType = nextWalkAround; + } else { + bool currentRouteIsClear = CWorld::GetIsLineOfSightClear(GetPosition(), objMat * LocalPosForWalkAround(adjustedColMin, adjustedColMax, m_walkAroundType), + true, true, true, true, true, true, false); + if (!currentRouteIsClear) { + // Change both target and direction (involves changing even/oddness) + if (m_walkAroundType % 2 == 0) { + m_walkAroundType -= 2; + if (m_walkAroundType < 0) + m_walkAroundType = 7; + else + m_walkAroundType += 1; + } else { + m_walkAroundType += 2; + if (m_walkAroundType > 6) + m_walkAroundType = 0; + else + m_walkAroundType -= 1; + } + } + } + + localPosToHead = LocalPosForWalkAround(adjustedColMin, adjustedColMax, m_walkAroundType); +#else + if (Abs(angleDiffBtwObjCenterAndForward) < objTopRightHeading) { + if (objIsSeekTarget) { + if (objIsSeekTargetAndVan) { + if (m_vehEnterType == CAR_DOOR_LR || m_vehEnterType == CAR_DOOR_RR) + return; + } + if (m_vehEnterType != CAR_DOOR_LF && m_vehEnterType != CAR_DOOR_LR && (!entityOnBottomRightOfObj || entityOnBottomLeftOfObj)) { + m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI); + localPosToHead.x = adjustedColMax.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } else { + m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet); + localPosToHead.x = adjustedColMin.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } + } else { + if (m_walkAroundType != 1 && m_walkAroundType != 4 + && (m_walkAroundType || CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) <= 0.0f)) { + + m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI); + localPosToHead.x = adjustedColMax.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } else { + m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet); + localPosToHead.x = adjustedColMin.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } + } + } else { + if (PI - objTopRightHeading >= Abs(angleDiffBtwObjCenterAndForward)) { + if (angleDiffBtwObjCenterAndForward <= 0.0f) { + if (!objIsSeekTarget || !objIsSeekTargetAndVan || m_vehEnterType != CAR_DOOR_LR && m_vehEnterType != CAR_DOOR_RR) { + if (objIsSeekTarget) { + if (m_vehEnterType == CAR_DOOR_RF || (m_vehEnterType == CAR_DOOR_RR && !objIsSeekTargetAndVan)) + return; + } + if (m_walkAroundType == 4 || m_walkAroundType == 3 + || !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) { + + m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); + localPosToHead.x = adjustedColMax.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } else { + m_fRotationDest = dirToSet; + localPosToHead.x = adjustedColMax.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMax.y; + } + } else { + m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); + localPosToHead.x = adjustedColMax.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } + } else if (objIsSeekTarget && objIsSeekTargetAndVan && (m_vehEnterType == CAR_DOOR_LR || m_vehEnterType == CAR_DOOR_RR)) { + m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); + localPosToHead.x = adjustedColMin.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } else { + if (objIsSeekTarget) { + if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR && !objIsSeekTargetAndVan) + return; + } + if (m_walkAroundType == 1 || m_walkAroundType == 2 + || !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) { + + m_fRotationDest = dirToSet; + localPosToHead.x = adjustedColMin.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMax.y; + } else { + m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); + localPosToHead.x = adjustedColMin.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMin.y; + } + } + } else { + if (objIsSeekTarget && (!objIsSeekTargetAndVan || m_vehEnterType != CAR_DOOR_LR && m_vehEnterType != CAR_DOOR_RR)) { + if (m_vehEnterType != CAR_DOOR_LF && m_vehEnterType != CAR_DOOR_LR && (!entityOnTopRightOfObj || entityOnTopLeftOfObj)) { + + m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI); + localPosToHead.x = adjustedColMax.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMax.y; + } else { + m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet); + localPosToHead.x = adjustedColMin.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMax.y; + } + } else { + if (m_walkAroundType == 2 || m_walkAroundType == 3 + || !m_walkAroundType && CGeneral::LimitRadianAngle(m_fRotationDest - angleToFaceObjCenter) > 0.0f) { + + m_fRotationDest = CGeneral::LimitRadianAngle(dirToSet - HALFPI); + localPosToHead.x = adjustedColMax.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMax.y; + } else { + m_fRotationDest = CGeneral::LimitRadianAngle(HALFPI + dirToSet); + localPosToHead.x = adjustedColMin.x; + localPosToHead.z = 0.0f; + localPosToHead.y = adjustedColMax.y; + } + } + } + } +#endif + if (objUpsideDown) + localPosToHead.x = localPosToHead.x * -1.0f; + + localPosToHead = objMat * localPosToHead; + m_actionX = localPosToHead.x; + m_actionY = localPosToHead.y; + localPosToHead -= GetPosition(); + m_fRotationDest = CGeneral::LimitRadianAngle(localPosToHead.Heading()); + if (m_fRotationDest != m_fRotationCur && bHitSomethingLastFrame) { + if (m_fRotationDest == oldRotDest) { + m_fRotationDest = oldRotDest; + } else { + m_fRotationDest = CGeneral::LimitRadianAngle(PI + dirToSet); + } + } + + float dist = localPosToHead.Magnitude2D(); + if (dist < 0.5f) + dist = 0.5f; + + if (dist > distLimitForTimer) + dist = distLimitForTimer; + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 280.0f * dist * checkIntervalInTime; +} + class CPed_ : public CPed { public: @@ -13408,7 +14057,6 @@ STARTPATCHES InjectHook(0x4C7EA0, &CPed::CalculateNewOrientation, PATCH_JUMP); InjectHook(0x4C78F0, &CPed::WorkOutHeadingForMovingFirstPerson, PATCH_JUMP); InjectHook(0x4C73F0, &CPed::CalculateNewVelocity, PATCH_JUMP); - InjectHook(0x4D72F0, &CPed::CanPedJumpThis, PATCH_JUMP); InjectHook(0x4DD820, &CPed::CanSeeEntity, PATCH_JUMP); InjectHook(0x4D9460, &CPed::RestorePreviousObjective, PATCH_JUMP); InjectHook(0x4D82C0, (void (CPed::*)(eObjective)) &CPed::SetObjective, PATCH_JUMP); @@ -13550,4 +14198,5 @@ STARTPATCHES InjectHook(0x4E4F30, &CPed::PositionPedOutOfCollision, PATCH_JUMP); InjectHook(0x4D6A00, &CPed::PossiblyFindBetterPosToSeekCar, PATCH_JUMP); InjectHook(0x4D94E0, &CPed::ProcessObjective, PATCH_JUMP); + InjectHook(0x4CCEB0, &CPed::SetDirectionToWalkAroundObject, PATCH_JUMP); ENDPATCHES \ No newline at end of file diff --git a/src/peds/Ped.h b/src/peds/Ped.h index 29916bf4..91cd8f99 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -266,7 +266,7 @@ public: // cf. https://github.com/DK22Pac/plugin-sdk/blob/master/plugin_sa/game_sa/CPed.h from R* uint8 bIsStanding : 1; - uint8 m_ped_flagA2 : 1; + uint8 m_ped_flagA2 : 1; // bWasStanding? uint8 bIsAttacking : 1; // doesn't reset after fist fight uint8 bIsPointingGunAt : 1; uint8 bIsLooking : 1; @@ -281,9 +281,9 @@ public: uint8 bIsLanding : 1; uint8 bIsRunning : 1; // on some conditions uint8 bHitSomethingLastFrame : 1; - uint8 m_ped_flagB80 : 1; // bIsNearCar? something related with reaction to colliding vehicle + uint8 m_ped_flagB80 : 1; // bIsNearCar? it's sure that it's related with cars and used for deciding whether we should move - uint8 m_ped_flagC1 : 1; + uint8 m_ped_flagC1 : 1; // bCanPedEnterSeekedCar? uint8 bRespondsToThreats : 1; uint8 bRenderPedInCar : 1; uint8 bChangedSeat : 1; @@ -294,15 +294,15 @@ public: uint8 bHasACamera : 1; // does ped possess a camera to document accidents involves fire/explosion uint8 m_ped_flagD2 : 1; // set when ped witnessed an event - uint8 m_ped_flagD4 : 1; // bPedIsBleeding? so far only creates blood pool in hands up state - uint8 m_ped_flagD8 : 1; + uint8 bPedIsBleeding : 1; + uint8 bStopAndShoot : 1; // Ped cannot reach target to attack with fist, need to use gun uint8 bIsPedDieAnimPlaying : 1; uint8 bUsePedNodeSeek : 1; - uint8 m_ped_flagD40 : 1; // reset when objective changes + uint8 bObjectiveCompleted : 1; uint8 bScriptObjectiveCompleted : 1; uint8 bKindaStayInSamePlace : 1; - uint8 m_ped_flagE2 : 1; + uint8 m_ped_flagE2 : 1; // bBeingChasedByPolice? uint8 bNotAllowedToDuck : 1; uint8 bCrouchWhenShooting : 1; uint8 bIsDucking : 1; @@ -316,7 +316,7 @@ public: uint8 m_ped_flagF8 : 1; uint8 bWillBeQuickJacked : 1; uint8 bCancelEnteringCar : 1; // after door is opened or couldn't be opened due to it's locked - uint8 m_ped_flagF40 : 1; + uint8 bObstacleShowedUpDuringKillObjective : 1; uint8 bDuckAndCover : 1; uint8 m_ped_flagG1 : 1; @@ -328,7 +328,7 @@ public: uint8 bGonnaKillTheCarJacker : 1; // only set when car is jacked from right door uint8 bFadeOut : 1; - uint8 bKnockedUpIntoAir : 1; // has ped been knocked up into the air by a car collision + uint8 bKnockedUpIntoAir : 1; // NOT CERTAIN - has ped been knocked up into the air by a car collision uint8 m_ped_flagH2 : 1; uint8 m_ped_flagH4 : 1; uint8 bClearObjective : 1; @@ -339,7 +339,7 @@ public: uint8 bShakeFist : 1; // test shake hand at look entity uint8 bNoCriticalHits : 1; // if set, limbs won't came off - uint8 m_ped_flagI4 : 1; + uint8 m_ped_flagI4 : 1; // seems like related with cars uint8 bHasAlreadyBeenRecorded : 1; uint8 bFallenDown : 1; uint8 m_ped_flagI20 : 1; @@ -402,7 +402,7 @@ public: float m_fRotationDest; float m_headingRate; uint16 m_vehEnterType; // TODO: this is more like a door, not a type - uint16 m_walkAroundType; + int16 m_walkAroundType; CEntity *m_pCurrentPhysSurface; CVector m_vecOffsetFromPhysSurface; CEntity *m_pCurSurface; @@ -530,7 +530,6 @@ public: void CalculateNewOrientation(void); float WorkOutHeadingForMovingFirstPerson(float); void CalculateNewVelocity(void); - bool CanPedJumpThis(CEntity*); bool CanSeeEntity(CEntity*, float); void RestorePreviousObjective(void); void SetIdle(void); @@ -732,6 +731,11 @@ public: void SetSeekCar(CVehicle*, uint32); void SetSeekBoatPosition(CVehicle*); void SetExitTrain(CVehicle*); +#ifdef VC_PED_PORTS + bool CanPedJumpThis(CEntity*, CVector*); +#else + bool CanPedJumpThis(CEntity*); +#endif bool HasWeapon(uint8 weaponType) { return m_weapons[weaponType].m_eWeaponType == weaponType; } CWeapon &GetWeapon(uint8 weaponType) { return m_weapons[weaponType]; } diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index ceee0bd2..668a6011 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -51,7 +51,7 @@ CPlayerPed::CPlayerPed(void) : CPed(PEDTYPE_PLAYER1) field_1413 = 0; for (int i = 0; i < 6; i++) { m_vecSafePos[i] = CVector(0.0f, 0.0f, 0.0f); - field_1488[i] = 0; + m_pPedAtSafePos[i] = nil; } } diff --git a/src/peds/PlayerPed.h b/src/peds/PlayerPed.h index 16fc65ee..136fcc48 100644 --- a/src/peds/PlayerPed.h +++ b/src/peds/PlayerPed.h @@ -35,7 +35,7 @@ public: int8 field_1414; int8 field_1415; CVector m_vecSafePos[6]; // safe places from the player, for example behind a tree - int32 field_1488[6]; // m_pPedAtSafePos? + CPed *m_pPedAtSafePos[6]; float m_fWalkAngle; float m_fFPSMoveHeading;