From be1c7b0761c2de0362a47ecfff616a8931b54805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?eray=20or=C3=A7unus?= Date: Sat, 10 Aug 2019 18:15:22 +0300 Subject: [PATCH] P.e.d.s. and fixes --- src/core/General.h | 15 + src/core/re3.cpp | 16 + src/peds/Ped.cpp | 649 +++++++++++++++++++++++++++++++++----- src/peds/Ped.h | 31 +- src/vehicles/Automobile.h | 18 +- 5 files changed, 627 insertions(+), 102 deletions(-) diff --git a/src/core/General.h b/src/core/General.h index fe277689..12f781d4 100644 --- a/src/core/General.h +++ b/src/core/General.h @@ -96,6 +96,21 @@ public: } } + // should return direction in 0-8 range. fits perfectly to peds' path directions. + static int CGeneral::GetNodeHeadingFromVector(float x, float y) + { + float angle = CGeneral::GetRadianAngleBetweenPoints(x, y, 0.0f, 0.0f); + if (angle < 0.0f) + angle += TWOPI; + + angle = DEGTORAD(22.5f) + TWOPI - angle; + + if (angle >= TWOPI) + angle -= TWOPI; + + return (int)floorf(angle / DEGTORAD(45.0f)); + } + // not too sure about all these... static uint16 GetRandomNumber(void) { return myrand() & MYRAND_MAX; } diff --git a/src/core/re3.cpp b/src/core/re3.cpp index 9fe53579..dc501075 100644 --- a/src/core/re3.cpp +++ b/src/core/re3.cpp @@ -139,6 +139,20 @@ SpawnCar(int id) } } +static void +LetThemFollowYou(void) { + CPed* player = (CPed*) FindPlayerPed(); + for (int i = 0; i < player->m_numNearPeds; i++) { + + CPed* nearPed = player->m_nearPeds[i]; + if (nearPed && !nearPed->IsPlayer()) { + nearPed->SetObjective(OBJECTIVE_FOLLOW_PED_IN_FORMATION, (void*)player); + nearPed->m_pedFormation = rand() & 7; + nearPed->bScriptObjectiveCompleted = false; + } + } +} + static void FixCar(void) { @@ -335,6 +349,8 @@ DebugMenuPopulate(void) DebugMenuAddVarBool8("Debug", "Don't render Peds", (int8*)&gbDontRenderPeds, nil); DebugMenuAddVarBool8("Debug", "Don't render Vehicles", (int8*)&gbDontRenderVehicles, nil); DebugMenuAddVarBool8("Debug", "Don't render Objects", (int8*)&gbDontRenderObjects, nil); + + DebugMenuAddCmd("Debug", "Make peds around you follow you", LetThemFollowYou); #ifndef FINAL DebugMenuAddVarBool8("Debug", "Toggle unused fight feature", (int8*)&CPed::bUnusedFightThingOnPlayer, nil); #endif diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index f349ae6d..dac17f30 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -45,7 +45,6 @@ WRAPPER void CPed::SetMoveAnim(void) { EAXJMP(0x4C5A40); } WRAPPER void CPed::SetFollowRoute(int16, int16) { EAXJMP(0x4DD690); } WRAPPER void CPed::SetDuck(uint32) { EAXJMP(0x4E4920); } WRAPPER void CPed::RegisterThreatWithGangPeds(CEntity*) { EAXJMP(0x4E3870); } -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); } @@ -58,19 +57,22 @@ bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44; bool &CPed::bPedCheat2 = *(bool*)0x95CD5A; bool &CPed::bPedCheat3 = *(bool*)0x95CD59; -CColPoint &CPed::ms_tempColPoint = *(CColPoint*)0x62DB14; +CColPoint &CPed::aTempPedColPts = *(CColPoint*)0x62DB14; -// TODO: PedAudioData should be hardcoded into exe, and it isn't reversed yet. -CPedAudioData (&CPed::PedAudioData)[38] = *(CPedAudioData(*)[38]) * (uintptr*)0x5F94C4; +// TODO: CommentWaitTime should be hardcoded into exe, and it isn't reversed yet. +CPedAudioData (&CPed::CommentWaitTime)[38] = *(CPedAudioData(*)[38]) * (uintptr*)0x5F94C4; uint16 &CPed::nPlayerInComboMove = *(uint16*)0x95CC58; FightMove (&CPed::tFightMoves)[24] = * (FightMove(*)[24]) * (uintptr*)0x5F9844; -uint16 &CPed::distanceMultToCountPedNear = *(uint16*)0x5F8C98; +uint16 &CPed::nThreatReactionRangeMultiplier = *(uint16*)0x5F8C98; -CVector &CPed::offsetToOpenRegularCarDoor = *(CVector*)0x62E030; -CVector &CPed::offsetToOpenLowCarDoor = *(CVector*)0x62E03C; -CVector &CPed::offsetToOpenVanDoor = *(CVector*)0x62E048; +CVector &CPed::vecPedCarDoorAnimOffset = *(CVector*)0x62E030; +CVector &CPed::vecPedCarDoorLoAnimOffset = *(CVector*)0x62E03C; +CVector &CPed::vecPedVanRearDoorAnimOffset = *(CVector*)0x62E048; +CVector &CPed::vecPedQuickDraggedOutCarAnimOffset = *(CVector*)0x62E06C; + +CVector2D &CPed::ms_vec2DFleePosition = *(CVector2D*)0x6EDF70; #ifndef FINAL bool CPed::bUnusedFightThingOnPlayer = false; @@ -290,7 +292,6 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_type = ENTITY_TYPE_PED; bPedPhysics = true; bUseCollisionRecords = true; -// m_status = STATUS_SIMPLE; m_vecAnimMoveDelta.x = 0.0f; m_vecAnimMoveDelta.y = 0.0f; @@ -314,7 +315,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_vecOffsetSeek.y = 0.0f; m_vecOffsetSeek.z = 0.0f; m_pedFormation = 0; - m_lastThreatTimer = 0; + m_collidingThingTimer = 0; m_nPedStateTimer = 0; m_actionX = 0; m_actionY = 0; @@ -338,9 +339,9 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_pCurrentPhysSurface = nil; m_vecOffsetFromPhysSurface = CVector(0.0f, 0.0f, 0.0f); m_pSeekTarget = nil; - m_vecSeekVehicle = CVector(0.0f, 0.0f, 0.0f); + m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); m_wepSkills = 0; - field_318 = 1.0f; + m_distanceToCountSeekDone = 1.0f; bRunningToPhone = false; m_phoneId = -1; m_lastAccident = 0; @@ -366,8 +367,8 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) m_nPathNodes = 0; m_nCurPathNode = 0; m_nPathState = 0; - m_pNextPathNode = nil; m_pLastPathNode = nil; + m_pNextPathNode = nil; m_routeLastPoint = -1; m_routePoints = 0; m_routePos = 0; @@ -393,7 +394,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this) bIsTalking = false; bIsInTheAir = false; bIsLanding = false; - m_ped_flagB20 = false; + bIsRunning = false; m_ped_flagB40 = false; m_ped_flagB80 = false; @@ -1477,13 +1478,13 @@ CPed::GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float seatP vehModel = (CVehicleModelInfo*) CModelInfo::GetModelInfo(veh->m_modelIndex); if (veh->bIsVan && (component == CAR_DOOR_LR || component == CAR_DOOR_RR)) { seatOffset = 0.0f; - vehDoorOffset = offsetToOpenVanDoor; + vehDoorOffset = vecPedVanRearDoorAnimOffset; } else { seatOffset = veh->pHandling->fSeatOffsetDistance * seatPosMult; if (veh->bLowVehicle) { - vehDoorOffset = offsetToOpenLowCarDoor; + vehDoorOffset = vecPedCarDoorLoAnimOffset; } else { - vehDoorOffset = offsetToOpenRegularCarDoor; + vehDoorOffset = vecPedCarDoorAnimOffset; } } @@ -1544,12 +1545,12 @@ CPed::GetPositionToOpenCarDoor(CVehicle *veh, uint32 component) CVector localVehDoorOffset; if (veh->bIsVan && (component == VEHICLE_ENTER_REAR_LEFT || component == VEHICLE_ENTER_REAR_RIGHT)) { - localVehDoorOffset = offsetToOpenVanDoor; + localVehDoorOffset = vecPedVanRearDoorAnimOffset; } else { if (veh->bIsLow) { - localVehDoorOffset = offsetToOpenLowCarDoor; + localVehDoorOffset = vecPedCarDoorLoAnimOffset; } else { - localVehDoorOffset = offsetToOpenRegularCarDoor; + localVehDoorOffset = vecPedCarDoorAnimOffset; } } @@ -1993,8 +1994,8 @@ CPed::SortPeds(CPed **list, int min, int max) void CPed::BuildPedLists(void) { - static CPed *unsortedNearPeds[10]; - uint16 nextNearPedSlot = 0; + static CPed *gapTempPedList[10]; // unsorted + static int16 gnNumTempPedList; if ((CTimer::GetFrameCounter() + (m_randomSeed % 256)) % 16) { @@ -2026,6 +2027,7 @@ CPed::BuildPedLists(void) (centre.y - 20.0f) * 0.025f + 50.0f, (centre.x + 20.0f) * 0.025f + 50.0f, (centre.y + 20.0f) * 0.025f + 50.0f); + gnNumTempPedList = 0; for(int y = rect.top; y <= rect.bottom; y++) { for(int x = rect.left; x <= rect.right; x++) { @@ -2033,19 +2035,18 @@ CPed::BuildPedLists(void) CPed *ped = (CPed*)pedPtrNode->item; if (ped != this && !ped->bInVehicle) { float dist = (ped->GetPosition() - GetPosition()).Magnitude2D(); - if (distanceMultToCountPedNear * 30.0f > dist) - { - unsortedNearPeds[nextNearPedSlot] = ped; - nextNearPedSlot++; + if (nThreatReactionRangeMultiplier * 30.0f > dist) { + gapTempPedList[gnNumTempPedList] = ped; + gnNumTempPedList++; } } } } } - unsortedNearPeds[nextNearPedSlot] = nil; - SortPeds(unsortedNearPeds, 0, nextNearPedSlot - 1); + gapTempPedList[gnNumTempPedList] = nil; + SortPeds(gapTempPedList, 0, gnNumTempPedList - 1); for (m_numNearPeds = 0; m_numNearPeds < 10; m_numNearPeds++) { - CPed *ped = unsortedNearPeds[m_numNearPeds]; + CPed *ped = gapTempPedList[m_numNearPeds]; if (!ped) break; @@ -2489,9 +2490,9 @@ CPed::SetObjective(eObjective newObj, void *entity) case OBJECTIVE_KILL_CHAR_ON_FOOT: case OBJECTIVE_KILL_CHAR_ANY_MEANS: case OBJECTIVE_MUG_CHAR: - m_pLastPathNode = nil; + m_pNextPathNode = nil; bIsFleeing = false; - m_vecSeekVehicle = CVector(0.0f, 0.0f, 0.0f); + m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); m_pedInObjective = (CPed*)entity; m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); m_pLookTarget = (CEntity*)entity; @@ -2501,7 +2502,7 @@ CPed::SetObjective(eObjective newObj, void *entity) case OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS: case OBJECTIVE_GOTO_CHAR_ON_FOOT: case OBJECTIVE_FIGHT_CHAR: - m_vecSeekVehicle = CVector(0.0f, 0.0f, 0.0f); + m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); m_pedInObjective = (CPed*)entity; m_pedInObjective->RegisterReference((CEntity**)&m_pedInObjective); break; @@ -2542,7 +2543,7 @@ CPed::SetObjective(eObjective newObj, void *entity) m_carInObjective->RegisterReference((CEntity**)&m_carInObjective); m_pSeekTarget = m_carInObjective; m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget); - m_vecSeekVehicle = CVector(0.0f, 0.0f, 0.0f); + m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); if (newObj == OBJECTIVE_SOLICIT) { m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 10000; } else if (m_objective == OBJECTIVE_ENTER_CAR_AS_PASSENGER && CharCreatedBy == MISSION_CHAR && @@ -3131,7 +3132,7 @@ CPed::ClearAll(void) m_nPedState = PED_NONE; m_nMoveState = PEDMOVE_NONE; m_pSeekTarget = nil; - m_vecSeekVehicle = CVector(0.0f, 0.0f, 0.0f); + m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); m_fleeFromPosX = 0.0f; m_fleeFromPosY = 0.0f; m_fleeFrom = nil; @@ -3715,7 +3716,7 @@ CPed::SetGetUp(void) && ((CTimer::GetFrameCounter() + m_randomSeed % 256 + 5) % 8 || CCollision::ProcessColModels(GetMatrix(), *CModelInfo::GetModelInfo(m_modelIndex)->GetColModel(), collidingVeh->GetMatrix(), *CModelInfo::GetModelInfo(collidingVeh->m_modelIndex)->GetColModel(), - &ms_tempColPoint, nil, nil) > 0)) { + &aTempPedColPts, nil, nil) > 0)) { bGetUpAnimStarted = false; if (IsPlayer()) @@ -3856,11 +3857,11 @@ CPed::SetWanderPath(int8 pathStateDest) if (pathStateDest == 0) pathStateDest = CGeneral::GetRandomNumberInRange(1, 7); - ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pNextPathNode, &m_pLastPathNode, + ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, m_nPathState, &nextPathState); // Circular loop until we find a node for current m_nPathState - while (!m_pLastPathNode) { + while (!m_pNextPathNode) { m_nPathState = (m_nPathState+1) % 8; // We're at where we started and couldn't find any node @@ -3869,7 +3870,7 @@ CPed::SetWanderPath(int8 pathStateDest) SetIdle(); return false; } - ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pNextPathNode, &m_pLastPathNode, + ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, m_nPathState, &nextPathState); } @@ -3877,7 +3878,7 @@ CPed::SetWanderPath(int8 pathStateDest) m_nPathState = nextPathState; m_nPedState = PED_WANDER_PATH; SetMoveState(PEDMOVE_WALK); - m_ped_flagB20 = false; + bIsRunning = false; return true; } } else { @@ -3962,10 +3963,10 @@ CPed::RestorePreviousState(void) break; case PED_WANDER_PATH: m_nPedState = PED_WANDER_PATH; - m_ped_flagB20 = false; + bIsRunning = false; if (!m_ped_flagC80) { - if (m_pLastPathNode) { - CVector diff = m_pLastPathNode->pos - GetPosition(); + if (m_pNextPathNode) { + CVector diff = m_pNextPathNode->pos - GetPosition(); if (diff.MagnitudeSqr() < 49.0f) { SetMoveState(PEDMOVE_WALK); break; @@ -4385,7 +4386,7 @@ CPed::SetAttack(CEntity* victim) } animAssoc->SetRun(); - if (animAssoc->currentTime != animAssoc->hierarchy->totalLength) + if (animAssoc->currentTime == animAssoc->hierarchy->totalLength) animAssoc->SetCurrentTime(0.0f); animAssoc->SetFinishCallback(FinishedAttackCB, this); @@ -4814,7 +4815,7 @@ CPed::SetFlee(CVector2D &from, int time) } bIsFleeing = true; - m_pLastPathNode = nil; + m_pNextPathNode = nil; m_fleeTimer = CTimer::GetTimeInMilliseconds() + time; float angleToFace = CGeneral::GetRadianAngleBetweenPoints( @@ -5073,9 +5074,9 @@ CPed::Say(uint16 audio) if (audioToPlay < m_queuedSound) { if (audioToPlay != m_lastQueuedSound || audioToPlay == SOUND_PED_DEATH - || PedAudioData[audioToPlay - SOUND_PED_DEATH].m_nOverrideMaxRandomDelayTime + || CommentWaitTime[audioToPlay - SOUND_PED_DEATH].m_nOverrideMaxRandomDelayTime + m_lastSoundStart - + (uint32) CGeneral::GetRandomNumberInRange(0, PedAudioData[audioToPlay - SOUND_PED_DEATH].m_nMaxRandomDelayTime) <= CTimer::GetTimeInMilliseconds()) { + + (uint32) CGeneral::GetRandomNumberInRange(0, CommentWaitTime[audioToPlay - SOUND_PED_DEATH].m_nMaxRandomDelayTime) <= CTimer::GetTimeInMilliseconds()) { m_queuedSound = audioToPlay; } } @@ -5111,10 +5112,10 @@ CPed::CollideWithPed(CPed *collideWith) 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(); + float seekPosDist = (GetPosition() - m_vecSeekPos).MagnitudeSqr2D(); + float heAndSeekPosDist = (collideWith->GetPosition() - m_vecSeekPos).MagnitudeSqr2D(); - if (weAndCarDist <= heAndCarDist) { + if (seekPosDist <= heAndSeekPosDist) { waitTime = 1000; collideWith->SetWaitState(WAITSTATE_CROSS_ROAD_LOOK, &waitTime); collideWith->m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + waitTime; @@ -5286,7 +5287,7 @@ CPed::CollideWithPed(CPed *collideWith) SetFlee(collideWith, 5000); bIsFleeing = true; - m_pLastPathNode = nil; + m_pNextPathNode = nil; if (!doWeRun) SetMoveState(PEDMOVE_WALK); } @@ -5477,7 +5478,7 @@ CPed::SetDead(void) } void -CPed::SetSeek(CEntity *seeking, float unk) +CPed::SetSeek(CEntity *seeking, float distanceToCountDone) { if (!IsPedInControl()) return; @@ -5492,17 +5493,17 @@ CPed::SetSeek(CEntity *seeking, float unk) SetStoredState(); m_nPedState = PED_SEEK_ENTITY; - field_318 = unk; + m_distanceToCountSeekDone = distanceToCountDone; m_pSeekTarget = seeking; m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); SetMoveState(PEDMOVE_STILL); } void -CPed::SetSeek(CVector pos, float unk) +CPed::SetSeek(CVector pos, float distanceToCountDone) { if (!IsPedInControl() - || (m_nPedState == PED_SEEK_POS && m_vecSeekVehicle.x != pos.x && m_vecSeekVehicle.y != pos.y)) + || (m_nPedState == PED_SEEK_POS && m_vecSeekPos.x == pos.x && m_vecSeekPos.y == pos.y)) return; if (GetWeapon()->m_eWeaponType == WEAPONTYPE_M16 @@ -5517,8 +5518,8 @@ CPed::SetSeek(CVector pos, float unk) SetStoredState(); m_nPedState = PED_SEEK_POS; - field_318 = unk; - m_vecSeekVehicle = pos; + m_distanceToCountSeekDone = distanceToCountDone; + m_vecSeekPos = pos; } void @@ -5662,7 +5663,7 @@ CPed::DuckAndCover(void) && CWorld::GetIsLineOfSightClear(GetPosition(), duckPos, 1, 0, 0, 1, 0, 0, 0)) { SetSeek(duckPos, 1.0f); m_headingRate = 15.0f; - m_ped_flagB20 = true; + bIsRunning = true; bDuckAndCover = true; justDucked = true; m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 500; @@ -5689,7 +5690,7 @@ CPed::DuckAndCover(void) bKindaStayInSamePlace = true; bDuckAndCover = false; - m_vecSeekVehicle = CVector(0.0f, 0.0f, 0.0f); + m_vecSeekPos = CVector(0.0f, 0.0f, 0.0f); if (m_pSeekTarget && m_pSeekTarget->IsVehicle()) ((CVehicle*)m_pSeekTarget)->m_numPedsUseItAsCover++; @@ -5769,7 +5770,7 @@ CPed::GetNearestTrainPedPosition(CVehicle *train, CVector &enterPos) CVector leftEntryPos, rightEntryPos, midEntryPos; float distLeftEntry, distRightEntry, distMidEntry; - // enterStepOffset = offsetToOpenRegularCarDoor; + // enterStepOffset = vecPedCarDoorAnimOffset; enterStepOffset = CVector(1.5f, 0.0f, 0.0f); if (train->pPassengers[TRAIN_POS_LEFT_ENTRY]) { @@ -6240,7 +6241,7 @@ CPed::Fight(void) animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, tFightMoves[m_lastFightMove].animId, 4.0f); animAssoc->SetFinishCallback(FinishFightMoveCB, this); - if (m_fightUnk2 == -2 && animAssoc->currentTime == 0.0f) { + if (m_fightUnk2 == -2 && animAssoc->currentTime != 0.0f) { animAssoc->SetCurrentTime(0.0f); animAssoc->SetRun(); } @@ -6294,16 +6295,16 @@ SelectClosestNodeForSeek(CPed *ped, CPathNode *node, CVector2D closeDist, CVecto CPathNode *testNode = &ThePaths.m_pathNodes[ThePaths.m_connections[i + node->firstLink]]; if (testNode && testNode != closeNode && testNode != closeNode2) { - CVector2D posDiff(ped->m_vecSeekVehicle - testNode->pos); + CVector2D posDiff(ped->m_vecSeekPos - testNode->pos); float dist = posDiff.MagnitudeSqr(); if (farDist.MagnitudeSqr() > dist) { if (closeDist.MagnitudeSqr() <= dist) { - ped->m_pLastPathNode = closeNode; + ped->m_pNextPathNode = closeNode; closeDist = posDiff; } else { - ped->m_pLastPathNode = (closeNode2 ? closeNode2 : testNode); + ped->m_pNextPathNode = (closeNode2 ? closeNode2 : testNode); farDist = posDiff; } } @@ -6317,37 +6318,37 @@ SelectClosestNodeForSeek(CPed *ped, CPathNode *node, CVector2D closeDist, CVecto bool CPed::FindBestCoordsFromNodes(CVector unused, CVector *bestCoords) { - if (m_pLastPathNode || !bIsFleeing) + if (m_pNextPathNode || !bIsFleeing) return false; CVector ourPos = GetPosition(); int closestNodeId = ThePaths.FindNodeClosestToCoors(GetPosition(), 1, 999999.9f, false, false); - CVector seekObjPos = m_vecSeekVehicle; + CVector seekObjPos = m_vecSeekPos; seekObjPos.z += 1.0f; if (CWorld::GetIsLineOfSightClear(ourPos, seekObjPos, true, false, false, true, false, false, false)) return false; - m_pLastPathNode = nil; + m_pNextPathNode = nil; - CVector2D seekObjDist (m_vecSeekVehicle - ourPos); + CVector2D seekPosDist (m_vecSeekPos - ourPos); CPathNode *closestNode = &ThePaths.m_pathNodes[closestNodeId]; - CVector2D closeDist(m_vecSeekVehicle - closestNode->pos); + CVector2D closeDist(m_vecSeekPos - closestNode->pos); - SelectClosestNodeForSeek(this, closestNode, closeDist, seekObjDist, closestNode, nil); + SelectClosestNodeForSeek(this, closestNode, closeDist, seekPosDist, closestNode, nil); // Above function decided that going to the next node is more logical than seeking the object. - if (m_pLastPathNode) { + if (m_pNextPathNode) { - CVector pathToNextNode = m_pLastPathNode->pos - ourPos; - if (pathToNextNode.MagnitudeSqr2D() < seekObjDist.MagnitudeSqr()) { - *bestCoords = m_pLastPathNode->pos; + CVector pathToNextNode = m_pNextPathNode->pos - ourPos; + if (pathToNextNode.MagnitudeSqr2D() < seekPosDist.MagnitudeSqr()) { + *bestCoords = m_pNextPathNode->pos; return true; } - m_pLastPathNode = nil; + m_pNextPathNode = nil; } return false; @@ -6449,11 +6450,11 @@ CPed::FinishLaunchCB(CAnimBlendAssociation *animAssoc, void *arg) if (TheCamera.Cams[0].Using3rdPersonMouseCam()) { float fpsAngle = ped->WorkOutHeadingForMovingFirstPerson(ped->m_fRotationCur); - ped->m_vecMoveSpeed.x = -velocityFromAnim * sin(fpsAngle); - ped->m_vecMoveSpeed.y = velocityFromAnim * cos(fpsAngle); + ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(fpsAngle); + ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(fpsAngle); } else { - ped->m_vecMoveSpeed.x = -velocityFromAnim * sin(ped->m_fRotationCur); - ped->m_vecMoveSpeed.y = velocityFromAnim * cos(ped->m_fRotationCur); + ped->m_vecMoveSpeed.x = -velocityFromAnim * Sin(ped->m_fRotationCur); + ped->m_vecMoveSpeed.y = velocityFromAnim * Cos(ped->m_fRotationCur); } } @@ -6574,8 +6575,8 @@ CPed::Wait(void) case WAITSTATE_HITWALL: if (CTimer::GetTimeInMilliseconds() <= m_nWaitTimer) { - if (m_lastThreatTimer > CTimer::GetTimeInMilliseconds()) { - m_lastThreatTimer = CTimer::GetTimeInMilliseconds() + 2500; + if (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) { + m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500; } } else { m_nWaitState = WAITSTATE_FALSE; @@ -6591,8 +6592,8 @@ CPed::Wait(void) ClearInvestigateEvent(); } - if (m_lastThreatTimer > CTimer::GetTimeInMilliseconds()) { - m_lastThreatTimer = CTimer::GetTimeInMilliseconds() + 2500; + if (m_collidingThingTimer > CTimer::GetTimeInMilliseconds()) { + m_collidingThingTimer = CTimer::GetTimeInMilliseconds() + 2500; } break; @@ -6659,7 +6660,7 @@ CPed::Wait(void) break; } - animAssoc = CAnimManager::BlendAnimation(GetClump(), m_animGroup, animToRun, 4.0f); + animAssoc = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, animToRun, 4.0f); if (animToRun == ANIM_TURN_180) animAssoc->SetFinishCallback(FinishedWaitCB, this); @@ -6710,7 +6711,7 @@ CPed::Wait(void) if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) { bIsFleeing = true; - m_pLastPathNode = nil; + m_pNextPathNode = nil; } if (m_nMoveState != PEDMOVE_RUN) SetMoveState(PEDMOVE_WALK); @@ -6728,7 +6729,7 @@ CPed::Wait(void) if (m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_FLEE_POS) { bIsFleeing = true; - m_pLastPathNode = nil; + m_pNextPathNode = nil; } SetMoveState(PEDMOVE_RUN); Say(SOUND_PED_FLEE_RUN); @@ -6789,6 +6790,478 @@ CPed::Wait(void) RestoreHeadingRate(); } +bool +CPed::Seek(void) +{ + float distanceToCountItDone = m_distanceToCountSeekDone; + eMoveState nextMove = PEDMOVE_NONE; + + if (m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) { + + if (m_nPedState != PED_EXIT_TRAIN && m_nPedState != PED_ENTER_TRAIN && m_nPedState != PED_SEEK_IN_BOAT && + m_objective != OBJECTIVE_ENTER_CAR_AS_PASSENGER && m_objective != OBJECTIVE_SOLICIT && !bDuckAndCover) { + + if ((!m_pedInObjective || !m_pedInObjective->bInVehicle) + && !((CTimer::GetFrameCounter() + (m_randomSeed % 256) + 17) & 7)) { + + CEntity *foundEnt = CWorld::TestSphereAgainstWorld(m_vecSeekPos, 0.4f, nil, + false, true, false, false, false, false); + + if (foundEnt) { + if (!foundEnt->IsVehicle() || ((CVehicle*)foundEnt)->m_vehType == VEHICLE_TYPE_CAR) { + distanceToCountItDone = 2.5f; + } else { + CVehicleModelInfo *vehModel = (CVehicleModelInfo*) CModelInfo::GetModelInfo(foundEnt->m_modelIndex); + float yLength = vehModel->GetColModel()->boundingBox.max.y + - vehModel->GetColModel()->boundingBox.min.y; + distanceToCountItDone = yLength * 0.55f; + } + } + } + } + } + + if (!m_pSeekTarget && m_nPedState == PED_SEEK_ENTITY) + ClearSeek(); + + float seekPosDist = (m_vecSeekPos - GetPosition()).Magnitude2D(); + if (seekPosDist < 2.0f || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT) { + + if (m_objective == OBJECTIVE_FOLLOW_PED_IN_FORMATION) { + + if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL) + nextMove = m_pedInObjective->m_nMoveState; + } else + nextMove = PEDMOVE_WALK; + + } else if (m_objective != OBJECTIVE_FOLLOW_PED_IN_FORMATION) { + + if (m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS || m_objective == OBJECTIVE_RUN_TO_AREA || bIsRunning) + nextMove = PEDMOVE_RUN; + else + nextMove = PEDMOVE_WALK; + + } else if (seekPosDist <= 2.0f) { + + if (m_pedInObjective->m_nMoveState != PEDMOVE_STILL) + nextMove = m_pedInObjective->m_nMoveState; + + } else { + nextMove = PEDMOVE_RUN; + } + + if (m_nPedState == PED_SEEK_ENTITY) { + if (m_pSeekTarget->IsPed()) { + if (((CPed*)m_pSeekTarget)->bInVehicle) + distanceToCountItDone += 2.0f; + } + } + + if (seekPosDist >= distanceToCountItDone) { + if (bIsRunning) + nextMove = PEDMOVE_RUN; + + if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer) { + + if (m_actionX != 0.0f && m_actionY != 0.0f) { + + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( + m_actionX, m_actionY, + GetPosition().x, GetPosition().y); + + float neededTurn = Abs(m_fRotationDest - m_fRotationCur); + + if (neededTurn > PI) + neededTurn = TWOPI - neededTurn; + + if (neededTurn > HALFPI) { + if (seekPosDist >= 1.0f) { + if (seekPosDist < 2.0f) { + if (bIsRunning) + nextMove = PEDMOVE_RUN; + else + nextMove = PEDMOVE_WALK; + } + } else { + nextMove = PEDMOVE_STILL; + } + } + + CVector2D moveDist(GetPosition().x - m_actionX, GetPosition().y - m_actionY); + if (moveDist.Magnitude() < 0.5f) { + m_nPedStateTimer = 0; + m_actionX = 0; + m_actionY = 0; + } + } + } else { + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( + m_vecSeekPos.x, m_vecSeekPos.y, + GetPosition().x, GetPosition().y); + + float neededTurn = Abs(m_fRotationDest - m_fRotationCur); + + if (neededTurn > PI) + neededTurn = TWOPI - neededTurn; + + if (neededTurn > HALFPI) { + if (seekPosDist >= 1.0 && neededTurn <= DEGTORAD(135.0f)) { + if (seekPosDist < 2.0f) + nextMove = PEDMOVE_WALK; + } else { + nextMove = PEDMOVE_STILL; + } + } + } + + if (((m_nPedState == PED_FLEE_POS || m_nPedState == PED_FLEE_ENTITY) && m_nMoveState < nextMove) + || (m_nPedState != PED_FLEE_POS && m_nPedState != PED_FLEE_ENTITY && m_objective != OBJECTIVE_GOTO_CHAR_ON_FOOT && m_nWaitState == WAITSTATE_FALSE)) { + + SetMoveState(nextMove); + } + + SetMoveAnim(); + return false; + } + + if ((m_objective != OBJECTIVE_FOLLOW_PED_IN_FORMATION || m_pedInObjective->m_nMoveState == PEDMOVE_STILL) && m_nMoveState != PEDMOVE_STILL) { + m_nPedStateTimer = 0; + m_actionX = 0; + m_actionY = 0; + } + + if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_GOTO_AREA_ANY_MEANS) { + if (m_pNextPathNode) + m_pNextPathNode = nil; + else + bScriptObjectiveCompleted = true; + + bIsFleeing = true; + } + + if (SeekFollowingPath(nil)) + m_nCurPathNode++; + + return true; +} + +bool +CPed::SeekFollowingPath(CVector *unused) +{ + return m_nCurPathNode <= m_nPathNodes && m_nPathNodes; +} + +void +CPed::Flee(void) +{ + if (CTimer::GetTimeInMilliseconds() > m_fleeTimer && m_fleeTimer) { + bool mayFinishFleeing = true; + if (m_nPedState == PED_FLEE_ENTITY) { + if ((CVector2D(GetPosition()) - ms_vec2DFleePosition).MagnitudeSqr() < 900.0f) + mayFinishFleeing = false; + } + + if (mayFinishFleeing) { + eMoveState moveState = m_nMoveState; + ClearFlee(); + + if (m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_TILL_SAFE || m_objective == OBJECTIVE_FLEE_CHAR_ON_FOOT_ALWAYS) + RestorePreviousObjective(); + + if ((m_nPedState == PED_IDLE || m_nPedState == PED_WANDER_PATH) && CGeneral::GetRandomNumber() & 1) { + SetWaitState(moveState <= PEDMOVE_WALK ? WAITSTATE_CROSS_ROAD_LOOK : WAITSTATE_FINISH_FLEE, nil); + } + return; + } + m_fleeTimer = CTimer::GetTimeInMilliseconds() + 5000; + } + + if (bIsFleeing) { + CPathNode *realLastNode = nil; + uint8 nextDirection = 0; + uint8 curDirectionShouldBe = 9; // means not defined yet + + if (m_nPedStateTimer < CTimer::GetTimeInMilliseconds() + && m_collidingThingTimer < CTimer::GetTimeInMilliseconds()) { + + if (m_pNextPathNode && CTimer::GetTimeInMilliseconds() > m_standardTimer) { + + curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y); + if (m_nPathState < curDirectionShouldBe) + m_nPathState += 8; + + int dirDiff = m_nPathState - curDirectionShouldBe; + if (dirDiff > 2 && dirDiff < 6) { + realLastNode = nil; + m_pLastPathNode = m_pNextPathNode; + m_pNextPathNode = 0; + } + } + + if (m_pNextPathNode) { + m_vecSeekPos = m_pNextPathNode->pos; + if (m_nMoveState == PEDMOVE_RUN) + bIsRunning = true; + + eMoveState moveState = m_nMoveState; + if (Seek()) { + realLastNode = m_pLastPathNode; + m_pLastPathNode = m_pNextPathNode; + m_pNextPathNode = nil; + } + bIsRunning = false; + SetMoveState(moveState); + } + } + + if (!m_pNextPathNode) { + if (curDirectionShouldBe == 9) { + curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y); + } + ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, + curDirectionShouldBe, + &nextDirection); + + if (curDirectionShouldBe < nextDirection) + curDirectionShouldBe += 8; + + if (m_pNextPathNode && m_pNextPathNode != realLastNode && m_pNextPathNode != m_pLastPathNode && curDirectionShouldBe - nextDirection != 4) { + m_nPathState = nextDirection; + m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000; + } else { + bIsFleeing = false; + SetMoveState(PEDMOVE_RUN); + Flee(); + } + } + return; + } + + if ((m_nPedState == PED_FLEE_ENTITY || m_nPedState == PED_ON_FIRE) && m_nPedStateTimer < CTimer::GetTimeInMilliseconds()) { + + float angleToFleeFromPos = CGeneral::GetRadianAngleBetweenPoints( + GetPosition().x, + GetPosition().y, + ms_vec2DFleePosition.x, + ms_vec2DFleePosition.y); + + m_fRotationDest = CGeneral::LimitRadianAngle(angleToFleeFromPos); + + if (m_fRotationCur - PI > m_fRotationDest) + m_fRotationDest += TWOPI; + else if (PI + m_fRotationCur < m_fRotationDest) + m_fRotationDest -= TWOPI; + } + + if (CTimer::GetTimeInMilliseconds() & 0x20) { + //CVector forwardPos = GetPosition(); + CMatrix forwardMat(GetMatrix()); + forwardMat.GetPosition() += Multiply3x3(forwardMat, CVector(0.0f, 4.0f, 0.0f)); + CVector forwardPos = forwardMat.GetPosition(); + + CEntity *foundEnt; + CColPoint foundCol; + bool found = CWorld::ProcessVerticalLine(forwardPos, forwardMat.GetPosition().z - 100.0f, foundCol, foundEnt, 1, 0, 0, 0, 1, 0, 0); + + if (!found || Abs(forwardPos.z - forwardMat.GetPosition().z) > 1.0f) { + m_fRotationDest += DEGTORAD(112.5f); + m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 2000; + } + } + + if (CTimer::GetTimeInMilliseconds() >= m_collidingThingTimer) + return; + + if (!m_collidingEntityWhileFleeing) + return; + + double damagingThingPriorityMult = (double)(m_collidingThingTimer - CTimer::GetTimeInMilliseconds()) * 2.0 / 2500; + + if (damagingThingPriorityMult <= 1.5) { + + double angleToFleeEntity = CGeneral::GetRadianAngleBetweenPoints( + GetPosition().x, + GetPosition().y, + m_collidingEntityWhileFleeing->GetPosition().x, + m_collidingEntityWhileFleeing->GetPosition().y); + angleToFleeEntity = CGeneral::LimitRadianAngle(angleToFleeEntity); + + // It includes projectiles, but is everything collides with us included? + double angleToFleeDamagingThing = CGeneral::GetRadianAngleBetweenPoints( + m_vecDamageNormal.x, + m_vecDamageNormal.y, + 0.0, + 0.0); + angleToFleeDamagingThing = CGeneral::LimitRadianAngle(angleToFleeDamagingThing); + + if (angleToFleeEntity - PI > angleToFleeDamagingThing) + angleToFleeDamagingThing += TWOPI; + else if (PI + angleToFleeEntity < angleToFleeDamagingThing) + angleToFleeDamagingThing -= TWOPI; + + if (damagingThingPriorityMult <= 1.0) { + // Range [0.0, 1.0] + + double angleToFleeBoth = (angleToFleeDamagingThing + angleToFleeEntity) * 0.5; + + if (m_fRotationDest - PI > angleToFleeBoth) + angleToFleeBoth += TWOPI; + else if (PI + m_fRotationDest < angleToFleeBoth) + angleToFleeBoth -= TWOPI; + + m_fRotationDest = (1.0 - damagingThingPriorityMult) * m_fRotationDest + damagingThingPriorityMult * angleToFleeBoth; + } else { + // Range (1.0, 1.5] + + double adjustedMult = (damagingThingPriorityMult - 1.0) * 2.0; + m_fRotationDest = angleToFleeEntity * (1.0 - adjustedMult) + adjustedMult * angleToFleeDamagingThing; + } + } else { + m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( + m_vecDamageNormal.x, + m_vecDamageNormal.y, + 0.0f, + 0.0f); + m_fRotationDest = CGeneral::LimitRadianAngle(m_fRotationDest); + } + + m_fRotationCur = CGeneral::LimitRadianAngle(m_fRotationCur); + + if (m_fRotationCur - PI > m_fRotationDest) + m_fRotationDest += TWOPI; + else if (PI + m_fRotationCur < m_fRotationDest) + m_fRotationDest -= TWOPI; + +} + +void +CPed::FollowPath(void) +{ + m_vecSeekPos.x = m_stPathNodeStates[m_nCurPathNode].x; + m_vecSeekPos.y = m_stPathNodeStates[m_nCurPathNode].y; + m_vecSeekPos.z = GetPosition().z; + + // Mysterious code +/* int v4 = 0; + int maxNodeIndex = m_nPathNodes - 1; + if (maxNodeIndex > 0) { + if (maxNodeIndex > 8) { + while (v4 < maxNodeIndex - 8) + v4 += 8; + } + + while (v4 < maxNodeIndex) + v4++; + + } +*/ + if (Seek()) { + m_nCurPathNode++; + if (m_nCurPathNode == m_nPathNodes) + RestorePreviousState(); + } +} + +CVector +CPed::GetFormationPosition(void) +{ + CPed *referencePed = m_pedInObjective; + + if (referencePed->m_nPedState == PED_DEAD) { + CPed *referencePedOfReference = referencePed->m_pedInObjective; + if (!referencePedOfReference) { + m_pedInObjective = nil; + return GetPosition(); + } + m_pedInObjective = referencePed = referencePedOfReference; + } + + CVector formationOffset; + switch (m_pedFormation) { + case 1: + formationOffset = CVector(0.0f, -1.5f, 0.0f); + break; + case 2: + formationOffset = CVector(-1.5f, -1.5f, 0.0f); + break; + case 3: + formationOffset = CVector(1.5f, -1.5f, 0.0f); + break; + case 4: + formationOffset = CVector(-1.5f, 1.5f, 0.0f); + break; + case 5: + formationOffset = CVector(1.5f, 1.5f, 0.0f); + break; + case 6: + formationOffset = CVector(-1.5f, 0.0f, 0.0f); + break; + case 7: + formationOffset = CVector(1.5f, 0.0f, 0.0f); + break; + case 8: + formationOffset = CVector(0.0f, 1.5f, 0.0f); + break; + default: + formationOffset = CVector(0.0f, 0.0f, 0.0f); + break; + } + return formationOffset + referencePed->GetPosition(); +} + +void +CPed::GetNearestDoor(CVehicle *veh, CVector &posToOpen) +{ + CVector *enterOffset = nil; + if (m_vehEnterType == CAR_DOOR_LF && veh->pDriver + || m_vehEnterType == CAR_DOOR_RF && veh->pPassengers[0] + || m_vehEnterType == CAR_DOOR_LR && veh->pPassengers[1] + || m_vehEnterType == CAR_DOOR_RR && veh->pPassengers[2]) + { + enterOffset = &vecPedQuickDraggedOutCarAnimOffset; + } + + CVector lfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_LF); + CVector rfPos = GetPositionToOpenCarDoor(veh, CAR_DOOR_RF); + + // Right front door is closer + if ((lfPos - GetPosition()).MagnitudeSqr2D() >= (rfPos - GetPosition()).MagnitudeSqr2D()) { + + if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) { + + CPed *rfPassenger = veh->pPassengers[0]; + if (!rfPassenger + || rfPassenger->m_leader != this && !m_ped_flagF4 && (veh->VehicleCreatedBy != MISSION_VEHICLE || m_objective != OBJECTIVE_ENTER_CAR_AS_DRIVER) + || veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset) == 0) { + + if ((veh->m_nGettingInFlags & CAR_DOOR_FLAG_RF) == 0 + || veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset) == 0) { + m_vehEnterType = CAR_DOOR_RF; + posToOpen = rfPos; + return; + } + } + } else { + if (!veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) + return; + } + m_vehEnterType = CAR_DOOR_LF; + posToOpen = lfPos; + return; + } + + if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_LF, enterOffset)) { + m_vehEnterType = CAR_DOOR_LF; + posToOpen = lfPos; + return; + } + + if (veh->IsRoomForPedToLeaveCar(CAR_DOOR_RF, enterOffset)) { + m_vehEnterType = CAR_DOOR_RF; + posToOpen = rfPos; + } +} + 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); } @@ -6952,4 +7425,10 @@ STARTPATCHES InjectHook(0x4D6520, &CPed::FinishedWaitCB, PATCH_JUMP); InjectHook(0x4D5D80, &CPed::Wait, PATCH_JUMP); InjectHook(0x4E3A90, &CPed::FindBestCoordsFromNodes, PATCH_JUMP); + InjectHook(0x4D2E70, &CPed::SeekFollowingPath, PATCH_JUMP); + InjectHook(0x4D1640, &CPed::Seek, PATCH_JUMP); + InjectHook(0x4D3020, &CPed::FollowPath, PATCH_JUMP); + InjectHook(0x4D1ED0, &CPed::Flee, PATCH_JUMP); + InjectHook(0x4E1CF0, &CPed::GetNearestDoor, PATCH_JUMP); + InjectHook(0x4DF420, &CPed::GetFormationPosition, PATCH_JUMP); ENDPATCHES \ No newline at end of file diff --git a/src/peds/Ped.h b/src/peds/Ped.h index d078f4d4..091a9cd6 100644 --- a/src/peds/Ped.h +++ b/src/peds/Ped.h @@ -260,7 +260,7 @@ public: uint8 bIsTalking : 1; uint8 bIsInTheAir : 1; uint8 bIsLanding : 1; - uint8 m_ped_flagB20 : 1; + uint8 bIsRunning : 1; // not fleeing uint8 m_ped_flagB40 : 1; uint8 m_ped_flagB80 : 1; @@ -370,8 +370,8 @@ public: private: int8 _pad2B5[3]; public: - CPathNode *m_pNextPathNode; CPathNode *m_pLastPathNode; + CPathNode *m_pNextPathNode; float m_fHealth; float m_fArmour; int16 m_routeLastPoint; @@ -389,12 +389,12 @@ public: CEntity *m_pCurrentPhysSurface; CVector m_vecOffsetFromPhysSurface; CEntity *m_pCurSurface; - CVector m_vecSeekVehicle; + CVector m_vecSeekPos; CEntity *m_pSeekTarget; CVehicle *m_pMyVehicle; bool bInVehicle; uint8 pad_315[3]; - float field_318; + float m_distanceToCountSeekDone; bool bRunningToPhone; uint8 field_31D; int16 m_phoneId; @@ -407,8 +407,8 @@ public: float m_fleeFromPosY; CEntity *m_fleeFrom; uint32 m_fleeTimer; - uint32 field_344; - uint32 m_lastThreatTimer; // I don't think so + CEntity* m_collidingEntityWhileFleeing; + uint32 m_collidingThingTimer; CEntity *m_pCollidingEntity; uint8 m_stateUnused; uint8 pad_351[3]; @@ -600,6 +600,11 @@ public: bool FindBestCoordsFromNodes(CVector unused, CVector* a6); void Wait(void); void ProcessObjective(void); + bool SeekFollowingPath(CVector*); + void Flee(void); + void FollowPath(void); + CVector GetFormationPosition(void); + void GetNearestDoor(CVehicle*, CVector&); // Static methods static CVector GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset); @@ -669,18 +674,20 @@ public: void SetPedState(PedState state) { m_nPedState = state; } // set by 0482:set_threat_reaction_range_multiplier opcode - static uint16 &distanceMultToCountPedNear; + static uint16 &nThreatReactionRangeMultiplier; - static CVector &offsetToOpenRegularCarDoor; - static CVector &offsetToOpenLowCarDoor; - static CVector &offsetToOpenVanDoor; + static CVector &vecPedCarDoorAnimOffset; + static CVector &vecPedCarDoorLoAnimOffset; + static CVector &vecPedVanRearDoorAnimOffset; + static CVector &vecPedQuickDraggedOutCarAnimOffset; static bool &bNastyLimbsCheat; static bool &bPedCheat2; static bool &bPedCheat3; - static CColPoint &ms_tempColPoint; + static CVector2D &ms_vec2DFleePosition; + static CColPoint &aTempPedColPts; static uint16 &nPlayerInComboMove; static FightMove (&tFightMoves)[24]; - static CPedAudioData (&PedAudioData)[38]; + static CPedAudioData (&CommentWaitTime)[38]; #ifndef FINAL static bool bUnusedFightThingOnPlayer; diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h index e6b64e6e..4dd3a087 100644 --- a/src/vehicles/Automobile.h +++ b/src/vehicles/Automobile.h @@ -58,6 +58,14 @@ enum eBombType CARBOMB_ONIGNITIONACTIVE, }; +enum { + CAR_DOOR_FLAG_UNKNOWN = 0x0, + CAR_DOOR_FLAG_LF = 0x1, + CAR_DOOR_FLAG_LR = 0x2, + CAR_DOOR_FLAG_RF = 0x4, + CAR_DOOR_FLAG_RR = 0x8 +}; + class CAutomobile : public CVehicle { public: @@ -189,14 +197,14 @@ static_assert(sizeof(CAutomobile) == 0x5A8, "CAutomobile: error"); inline uint8 GetCarDoorFlag(int32 carnode) { switch (carnode) { case CAR_DOOR_LF: - return 1; + return CAR_DOOR_FLAG_LF; case CAR_DOOR_LR: - return 2; + return CAR_DOOR_FLAG_LR; case CAR_DOOR_RF: - return 4; + return CAR_DOOR_FLAG_RF; case CAR_DOOR_RR: - return 8; + return CAR_DOOR_FLAG_RR; default: - return 0; + return CAR_DOOR_FLAG_UNKNOWN; } }