Merge pull request #272 from erorcun/erorcun

CPed completed!
This commit is contained in:
erorcun 2019-11-21 00:06:22 +03:00 committed by GitHub
commit a7d0404c89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 404 additions and 88 deletions

View File

@ -2307,17 +2307,23 @@ int8 CRunningScript::ProcessCommandsFrom200To299(int32 command)
assert(pCurrent); // GetIndex(0) doesn't look good
int handle = CPools::GetVehiclePool()->GetIndex(pCurrent);
if (handle != CTheScripts::StoreVehicleIndex && m_bIsMissionScript){
CVehicle* pOld = CPools::GetVehiclePool()->GetAt(CTheScripts::StoreVehicleIndex);
if (pOld){
CCarCtrl::RemoveFromInterestingVehicleList(pOld);
if (pOld->VehicleCreatedBy == MISSION_VEHICLE && CTheScripts::StoreVehicleWasRandom){
pOld->VehicleCreatedBy = RANDOM_VEHICLE;
pOld->bIsLocked = false;
CCarCtrl::NumRandomCars++;
CCarCtrl::NumMissionCars--;
CTheScripts::MissionCleanup.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
#ifdef FIX_BUGS
if (CTheScripts::StoreVehicleIndex != -1)
#endif
{
CVehicle* pOld = CPools::GetVehiclePool()->GetAt(CTheScripts::StoreVehicleIndex);
if (pOld){
CCarCtrl::RemoveFromInterestingVehicleList(pOld);
if (pOld->VehicleCreatedBy == MISSION_VEHICLE && CTheScripts::StoreVehicleWasRandom){
pOld->VehicleCreatedBy = RANDOM_VEHICLE;
pOld->bIsLocked = false;
CCarCtrl::NumRandomCars++;
CCarCtrl::NumMissionCars--;
CTheScripts::MissionCleanup.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
}
}
}
CTheScripts::StoreVehicleIndex = handle;
switch (pCurrent->VehicleCreatedBy){
case RANDOM_VEHICLE:
@ -2357,17 +2363,23 @@ int8 CRunningScript::ProcessCommandsFrom200To299(int32 command)
assert(pCurrent); // Here pCurrent shouldn't be NULL anyway
int handle = CPools::GetVehiclePool()->GetIndex(pCurrent);
if (handle != CTheScripts::StoreVehicleIndex && m_bIsMissionScript) {
CVehicle* pOld = CPools::GetVehiclePool()->GetAt(CTheScripts::StoreVehicleIndex);
if (pOld) {
CCarCtrl::RemoveFromInterestingVehicleList(pOld);
if (pOld->VehicleCreatedBy == MISSION_VEHICLE && CTheScripts::StoreVehicleWasRandom) {
pOld->VehicleCreatedBy = RANDOM_VEHICLE;
pOld->bIsLocked = false;
CCarCtrl::NumRandomCars++;
CCarCtrl::NumMissionCars--;
CTheScripts::MissionCleanup.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
#ifdef FIX_BUGS
if (CTheScripts::StoreVehicleIndex != -1)
#endif
{
CVehicle* pOld = CPools::GetVehiclePool()->GetAt(CTheScripts::StoreVehicleIndex);
if (pOld){
CCarCtrl::RemoveFromInterestingVehicleList(pOld);
if (pOld->VehicleCreatedBy == MISSION_VEHICLE && CTheScripts::StoreVehicleWasRandom){
pOld->VehicleCreatedBy = RANDOM_VEHICLE;
pOld->bIsLocked = false;
CCarCtrl::NumRandomCars++;
CCarCtrl::NumMissionCars--;
CTheScripts::MissionCleanup.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
}
}
}
CTheScripts::StoreVehicleIndex = handle;
switch (pCurrent->VehicleCreatedBy) {
case RANDOM_VEHICLE:

View File

@ -140,7 +140,7 @@ bool COnscreenTimerEntry::ProcessForDisplay() {
if(m_nTimerOffset != 0) {
m_bTimerProcessed = true;
ProcessForDisplayTimer();
ProcessForDisplayClock();
}
if(m_nCounterOffset != 0) {
@ -150,21 +150,21 @@ bool COnscreenTimerEntry::ProcessForDisplay() {
return true;
}
int COnscreenTimerEntry::ProcessForDisplayTimer() {
void COnscreenTimerEntry::ProcessForDisplayClock() {
uint32 time = *(uint32*)&CTheScripts::ScriptSpace[m_nTimerOffset];
return sprintf(m_bTimerBuffer, "%02d:%02d", time / 1000 / 60,
sprintf(m_bTimerBuffer, "%02d:%02d", time / 1000 / 60,
time / 1000 % 60);
}
int COnscreenTimerEntry::ProcessForDisplayCounter() {
void COnscreenTimerEntry::ProcessForDisplayCounter() {
uint32 counter = *(uint32*)&CTheScripts::ScriptSpace[m_nCounterOffset];
return sprintf(m_bCounterBuffer, "%d", counter);
sprintf(m_bCounterBuffer, "%d", counter);
}
STARTPATCHES
InjectHook(0x429160, &COnscreenTimerEntry::Process, PATCH_JUMP);
InjectHook(0x429110, &COnscreenTimerEntry::ProcessForDisplay, PATCH_JUMP);
InjectHook(0x429080, &COnscreenTimerEntry::ProcessForDisplayTimer, PATCH_JUMP);
InjectHook(0x429080, &COnscreenTimerEntry::ProcessForDisplayClock, PATCH_JUMP);
InjectHook(0x4290F0, &COnscreenTimerEntry::ProcessForDisplayCounter, PATCH_JUMP);
InjectHook(0x429220, &COnscreenTimer::Init, PATCH_JUMP);

View File

@ -18,8 +18,8 @@ public:
void Process();
bool ProcessForDisplay();
int ProcessForDisplayTimer();
int ProcessForDisplayCounter();
void ProcessForDisplayClock();
void ProcessForDisplayCounter();
};
static_assert(sizeof(COnscreenTimerEntry) == 0x74, "COnscreenTimerEntry: error");

View File

@ -49,12 +49,6 @@
#include "ParticleObject.h"
#include "Floater.h"
WRAPPER void CPed::WanderPath(void) { EAXJMP(0x4D28D0); }
WRAPPER bool CPed::WarpPedToNearEntityOffScreen(CEntity*) { EAXJMP(0x4E5570); }
WRAPPER void CPed::SetObjective(eObjective, CVector, float) { EAXJMP(0x4D8770); }
WRAPPER void CPed::SetCarJack(CVehicle*) { EAXJMP(0x4E0220); }
WRAPPER void CPed::WarpPedToNearLeaderOffScreen(void) { EAXJMP(0x4E52A0); }
#define FEET_OFFSET 1.04f
CPed *gapTempPedList[50];
@ -461,7 +455,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_wanderRangeBounds = nil;
m_nPathNodes = 0;
m_nCurPathNode = 0;
m_nPathState = 0;
m_nPathDir = 0;
m_pLastPathNode = nil;
m_pNextPathNode = nil;
m_routeLastPoint = -1;
@ -787,9 +781,7 @@ CPed::AimGun(void)
if (m_pSeekTarget) {
if (m_pSeekTarget->IsPed()) {
((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(&pos, PED_MID);
vector.x = pos.x;
vector.y = pos.y;
vector.z = pos.z;
vector = pos;
} else {
vector = m_pSeekTarget->GetPosition();
}
@ -1445,8 +1437,15 @@ CPed::ClearPointGunAt(void)
ClearLookFlag();
ClearAimFlag();
bIsPointingGunAt = false;
#ifndef VC_PED_PORTS
if (m_nPedState == PED_AIM_GUN) {
RestorePreviousState();
#else
if (m_nPedState == PED_AIM_GUN || m_nPedState == PED_ATTACK) {
m_nPedState = PED_IDLE;
RestorePreviousState();
}
#endif
weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay);
if (!animAssoc || animAssoc->blendDelta < 0.0f) {
@ -1456,7 +1455,9 @@ CPed::ClearPointGunAt(void)
animAssoc->flags |= ASSOC_DELETEFADEDOUT;
animAssoc->blendDelta = -4.0f;
}
#ifndef VC_PED_PORTS
}
#endif
}
void
@ -2772,6 +2773,12 @@ void
CPed::SetIdle(void)
{
if (m_nPedState != PED_IDLE && m_nPedState != PED_MUG && m_nPedState != PED_FLEE_ENTITY) {
#ifdef VC_PED_PORTS
if (m_nPedState == PED_AIM_GUN)
ClearPointGunAt();
m_nLastPedState = PED_NONE;
#endif
m_nPedState = PED_IDLE;
SetMoveState(PEDMOVE_STILL);
}
@ -4171,39 +4178,36 @@ CPed::SetWanderPath(int8 pathStateDest)
SetIdle();
return false;
} else {
// m_nPathState is pure direction for values 1,2,3 and 5,6,7
m_nPathState = pathStateDest;
m_nPathDir = pathStateDest;
if (pathStateDest == 0)
pathStateDest = CGeneral::GetRandomNumberInRange(1, 7);
ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
m_nPathState, &nextPathState);
m_nPathDir, &nextPathState);
// Circular loop until we find a node for current m_nPathState
// Circular loop until we find a node for current m_nPathDir
while (!m_pNextPathNode) {
m_nPathState = (m_nPathState+1) % 8;
m_nPathDir = (m_nPathDir+1) % 8;
// We're at where we started and couldn't find any node
if (m_nPathState == pathStateDest) {
if (m_nPathDir == pathStateDest) {
ClearAll();
SetIdle();
return false;
}
ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
m_nPathState, &nextPathState);
m_nPathDir, &nextPathState);
}
// We did it, save next path state and return true
m_nPathState = nextPathState;
m_nPathDir = nextPathState;
m_nPedState = PED_WANDER_PATH;
SetMoveState(PEDMOVE_WALK);
bIsRunning = false;
return true;
}
} else {
m_nPathState = pathStateDest;
m_nPathDir = pathStateDest;
bStartWanderPathOnFoot = true;
return false;
}
@ -4338,6 +4342,9 @@ CPed::SetPointGunAt(CEntity *to)
if (to) {
SetLookFlag(to, true);
SetAimFlag(to);
#ifdef VC_PED_PORTS
SetLookTimer(INT_MAX);
#endif
}
if (m_nPedState == PED_AIM_GUN || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK)
@ -5921,12 +5928,7 @@ void
CPed::SetSeek(CVector pos, float distanceToCountDone)
{
if (!IsPedInControl()
// FIX: Directly comparing floats are bad.
#ifdef FIX_BUGS
|| (m_nPedState == PED_SEEK_POS && Abs(m_vecSeekPos.x - pos.x) < 0.01f && Abs(m_vecSeekPos.y - pos.y) < 0.01f))
#else
|| (m_nPedState == PED_SEEK_POS && m_vecSeekPos.x == pos.x && m_vecSeekPos.y == pos.y))
#endif
return;
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_M16
@ -7454,10 +7456,10 @@ CPed::Flee(void)
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;
if (m_nPathDir < curDirectionShouldBe)
m_nPathDir += 8;
int dirDiff = m_nPathState - curDirectionShouldBe;
int dirDiff = m_nPathDir - curDirectionShouldBe;
if (dirDiff > 2 && dirDiff < 6) {
realLastNode = nil;
m_pLastPathNode = m_pNextPathNode;
@ -7493,7 +7495,7 @@ CPed::Flee(void)
curDirectionShouldBe += 8;
if (m_pNextPathNode && m_pNextPathNode != realLastNode && m_pNextPathNode != m_pLastPathNode && curDirectionShouldBe - nextDirection != 4) {
m_nPathState = nextDirection;
m_nPathDir = nextDirection;
m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000;
} else {
bUsePedNodeSeek = false;
@ -10072,7 +10074,7 @@ CPed::ProcessControl(void)
if (bStartWanderPathOnFoot) {
if (IsPedInControl()) {
ClearAll();
SetWanderPath(m_nPathState);
SetWanderPath(m_nPathDir);
bStartWanderPathOnFoot = false;
} else if (m_nPedState == PED_DRIVING) {
bWanderPathAfterExitingCar = true;
@ -11962,6 +11964,20 @@ CPed::ReplaceWeaponWhenExitingVehicle(void)
}
}
// Same, it's inlined in III.
inline void
CPed::RemoveWeaponWhenEnteringVehicle(void)
{
if (IsPlayer() && HasWeapon(WEAPONTYPE_UZI) && GetWeapon(WEAPONTYPE_UZI).m_nAmmoTotal > 0) {
if (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED)
m_storedWeapon = GetWeapon()->m_eWeaponType;
SetCurrentWeapon(WEAPONTYPE_UZI);
} else {
CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
RemoveWeaponModel(ourWeapon->m_nModelId);
}
}
void
CPed::PedSetOutTrainCB(CAnimBlendAssociation *animAssoc, void *arg)
{
@ -15753,6 +15769,7 @@ CPed::SeekCar(void)
else
bVehEnterDoorIsBlocked = false;
// Arrived to the car
if (Seek()) {
if (!foundBetterPosToSeek) {
if (1.5f + GetPosition().z > dest.z && GetPosition().z - 0.5f < dest.z) {
@ -16566,17 +16583,8 @@ CPed::WarpPedIntoCar(CVehicle *car)
CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
RemoveWeaponModel(ourWeapon->m_nModelId);
} else {
// Because we can use Uzi for drive by
// RemoveWeaponWhenEnteringVehicle in VC
if (IsPlayer() && HasWeapon(WEAPONTYPE_UZI) && GetWeapon(WEAPONTYPE_UZI).m_nAmmoTotal > 0) {
if (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED)
m_storedWeapon = GetWeapon()->m_eWeaponType;
SetCurrentWeapon(WEAPONTYPE_UZI);
} else {
CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
RemoveWeaponModel(ourWeapon->m_nModelId);
}
RemoveWeaponWhenEnteringVehicle();
if (car->bLowVehicle)
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f);
@ -16785,17 +16793,7 @@ void
CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
{
float zDiff = 0.0f;
if (!IsPlayer() || GetWeapon()->m_eWeaponType != WEAPONTYPE_UZI) {
// RemoveWeaponWhenEnteringVehicle in VC
if (IsPlayer() && HasWeapon(WEAPONTYPE_UZI) && GetWeapon(WEAPONTYPE_UZI).m_nAmmoTotal > 0) {
if (m_storedWeapon == WEAPONTYPE_UNIDENTIFIED)
m_storedWeapon = GetWeapon()->m_eWeaponType;
SetCurrentWeapon(WEAPONTYPE_UZI);
} else {
CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
RemoveWeaponModel(ourWeapon->m_nModelId);
}
}
RemoveWeaponWhenEnteringVehicle();
car->m_nGettingInFlags |= doorFlag;
bVehEnterDoorIsBlocked = false;
if (m_nPedState != PED_SEEK_CAR && m_nPedState != PED_SEEK_IN_BOAT)
@ -16832,22 +16830,321 @@ CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
if (IsPlayer())
CWaterLevel::AllocateBoatWakeArray();
} else {
if (m_vehEnterType != CAR_DOOR_LF && m_vehEnterType != CAR_DOOR_LR) {
if (zDiff <= 4.4f) {
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_RHS, 4.0f);
} else {
if (zDiff > 4.4f) {
if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_RHS, 4.0f);
}
} else if (zDiff <= 4.4f) {
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_LHS, 4.0f);
else
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_LHS, 4.0f);
} else {
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_LHS, 4.0f);
if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_RHS, 4.0f);
else
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_LHS, 4.0f);
}
m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
car->AutoPilot.m_nCruiseSpeed = 0;
}
}
void
CPed::WanderPath(void)
{
if (!m_pNextPathNode) {
printf("THIS SHOULDN@T HAPPEN TOO OFTEN\n");
SetIdle();
return;
}
if (m_nWaitState == WAITSTATE_FALSE) {
if (m_nMoveState == PEDMOVE_STILL || m_nMoveState == PEDMOVE_NONE)
SetMoveState(PEDMOVE_WALK);
}
m_vecSeekPos = m_pNextPathNode->pos;
m_vecSeekPos.z += 1.0f;
// Only returns true when ped is stuck(not stopped) I think, then we should assign new direction or wait state to him.
if (!Seek())
return;
CPathNode *previousLastNode = m_pLastPathNode;
uint8 randVal = (m_randomSeed + 3 * CTimer::GetFrameCounter()) % 100;
// We don't prefer 180-degree turns in normal situations
uint8 dirWeWouldntPrefer = m_nPathDir;
if (dirWeWouldntPrefer <= 3)
dirWeWouldntPrefer += 4;
else
dirWeWouldntPrefer -= 4;
CPathNode *nodeWeWouldntPrefer = nil;
uint8 dirToSet = 9; // means undefined
uint8 dirWeWouldntPrefer2 = 9; // means undefined
if (randVal <= 90) {
if (randVal > 80) {
m_nPathDir += 2;
m_nPathDir %= 8;
}
} else {
m_nPathDir -= 2;
if (m_nPathDir < 0)
m_nPathDir += 8;
}
m_pLastPathNode = m_pNextPathNode;
ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
m_nPathDir, &dirToSet);
uint8 tryCount = 0;
// NB: SetWanderPath checks for m_nPathDir == dirToStartWith, this one checks for tryCount > 7
while (!m_pNextPathNode) {
tryCount++;
m_nPathDir = (m_nPathDir + 1) % 8;
// We're at where we started and couldn't find any node
if (tryCount > 7) {
if (!nodeWeWouldntPrefer) {
ClearAll();
SetIdle();
// Probably this text carried over here after copy-pasting this loop from early version of SetWanderPath.
Error("Can't find valid path node, SetWanderPath, Ped.cpp");
return;
}
m_pNextPathNode = nodeWeWouldntPrefer;
dirToSet = dirWeWouldntPrefer2;
} else {
ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode,
m_nPathDir, &dirToSet);
if (m_pNextPathNode) {
if (dirToSet == dirWeWouldntPrefer) {
nodeWeWouldntPrefer = m_pNextPathNode;
dirWeWouldntPrefer2 = dirToSet;
m_pNextPathNode = nil;
}
}
}
}
m_nPathDir = dirToSet;
if (m_pLastPathNode == m_pNextPathNode) {
m_pNextPathNode = previousLastNode;
SetWaitState(WAITSTATE_DOUBLEBACK, nil);
Say(SOUND_PED_WAIT_DOUBLEBACK);
} else if (ThePaths.TestForPedTrafficLight(m_pLastPathNode, m_pNextPathNode)) {
SetWaitState(WAITSTATE_TRAFFIC_LIGHTS, nil);
} else if (ThePaths.TestCrossesRoad(m_pLastPathNode, m_pNextPathNode)) {
SetWaitState(WAITSTATE_CROSS_ROAD, nil);
} else if (m_pNextPathNode == previousLastNode) {
SetWaitState(WAITSTATE_DOUBLEBACK, nil);
Say(SOUND_PED_WAIT_DOUBLEBACK);
}
}
bool
CPed::WarpPedToNearEntityOffScreen(CEntity *warpTo)
{
bool teleported = false;
if (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds())
return false;
CVector warpToPos = warpTo->GetPosition();
CVector distVec = warpToPos - GetPosition();
float halfOfDist = distVec.Magnitude() * 0.5f;
CVector halfNormalizedDist = distVec / halfOfDist;
CVector appropriatePos = GetPosition();
CVector zCorrectedPos = appropriatePos;
int tryCount = min(10, halfOfDist);
for (int i = 0; i < tryCount; ++i) {
appropriatePos += halfNormalizedDist;
CPedPlacement::FindZCoorForPed(&zCorrectedPos);
if (Abs(zCorrectedPos.z - warpToPos.z) >= 3.0f && Abs(zCorrectedPos.z - appropriatePos.z) >= 3.0f)
continue;
appropriatePos.z = zCorrectedPos.z;
if (!TheCamera.IsSphereVisible(appropriatePos, 0.6f, &TheCamera.GetCameraMatrix())
&& CWorld::GetIsLineOfSightClear(appropriatePos, warpToPos, true, true, false, true, false, false, false)
&& !CWorld::TestSphereAgainstWorld(appropriatePos, 0.6f, this, true, true, false, true, false, false)) {
teleported = true;
Teleport(appropriatePos);
}
}
m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;
return teleported;
}
bool
CPed::WarpPedToNearLeaderOffScreen(void)
{
bool teleported = false;
if (GetIsOnScreen() || m_leaveCarTimer > CTimer::GetTimeInMilliseconds())
return false;
CVector warpToPos = m_leader->GetPosition();
CVector distVec = warpToPos - GetPosition();
float halfOfDist = distVec.Magnitude() * 0.5f;
CVector halfNormalizedDist = distVec / halfOfDist;
CVector appropriatePos = GetPosition();
CVector zCorrectedPos = appropriatePos;
int tryCount = min(10, halfOfDist);
for (int i = 0; i < tryCount; ++i) {
appropriatePos += halfNormalizedDist;
CPedPlacement::FindZCoorForPed(&zCorrectedPos);
if (Abs(zCorrectedPos.z - warpToPos.z) >= 3.0f && Abs(zCorrectedPos.z - appropriatePos.z) >= 3.0f)
continue;
appropriatePos.z = zCorrectedPos.z;
if (!TheCamera.IsSphereVisible(appropriatePos, 0.6f, &TheCamera.GetCameraMatrix())
&& CWorld::GetIsLineOfSightClear(appropriatePos, warpToPos, true, true, false, true, false, false, false)
&& !CWorld::TestSphereAgainstWorld(appropriatePos, 0.6f, this, true, true, false, true, false, false)) {
teleported = true;
Teleport(appropriatePos);
}
}
m_leaveCarTimer = CTimer::GetTimeInMilliseconds() + 3000;
return teleported;
}
void
CPed::SetCarJack_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
{
RemoveWeaponWhenEnteringVehicle();
if (m_nPedState != PED_SEEK_CAR)
SetStoredState();
m_pSeekTarget = car;
m_pSeekTarget->RegisterReference((CEntity**)&m_pSeekTarget);
m_nPedState = PED_CARJACK;
car->bIsBeingCarJacked = true;
m_pMyVehicle = (CVehicle*)m_pSeekTarget;
m_pMyVehicle->RegisterReference((CEntity**)&m_pMyVehicle);
((CVehicle*)m_pSeekTarget)->m_nNumGettingIn++;
Say(m_nPedType == PEDTYPE_COP ? SOUND_PED_ARREST_COP : SOUND_PED_CAR_JACKING);
CVector carEnterPos;
carEnterPos = GetPositionToOpenCarDoor(car, m_vehEnterType);
car->m_nGettingInFlags |= doorFlag;
m_vecOffsetSeek = carEnterPos - GetPosition();
m_nPedStateTimer = CTimer::GetTimeInMilliseconds() + 600;
float zDiff = max(0.0f, carEnterPos.z - GetPosition().z);
bUsesCollision = false;
if (zDiff > 4.4f) {
if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_RHS, 4.0f);
else
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_LHS, 4.0f);
} else {
if (m_vehEnterType == CAR_DOOR_RF || m_vehEnterType == CAR_DOOR_RR)
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_RHS, 4.0f);
else
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_LHS, 4.0f);
}
m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
}
void
CPed::SetObjective(eObjective newObj, CVector dest, float safeDist)
{
if (DyingOrDead())
return;
if (m_prevObjective != OBJECTIVE_NONE && m_prevObjective == newObj)
return;
SetObjectiveTimer(0);
if (m_objective == newObj) {
if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) {
if (m_nextRoutePointPos == dest && m_distanceToCountSeekDone == safeDist)
return;
} else if (newObj == OBJECTIVE_GUARD_SPOT) {
if (m_vecSeekPosEx == dest && m_distanceToCountSeekDoneEx == safeDist)
return;
}
}
#ifdef VC_PED_PORTS
ClearPointGunAt();
#endif
bObjectiveCompleted = false;
if (IsTemporaryObjective(m_objective)) {
m_prevObjective = newObj;
} else {
if (m_objective != newObj)
SetStoredObjective();
m_objective = newObj;
}
if (newObj == OBJECTIVE_GUARD_SPOT) {
m_vecSeekPosEx = dest;
m_distanceToCountSeekDoneEx = safeDist;
} else if (newObj == OBJECTIVE_GOTO_AREA_ANY_MEANS || newObj == OBJECTIVE_GOTO_AREA_ON_FOOT || newObj == OBJECTIVE_RUN_TO_AREA) {
m_pNextPathNode = nil;
m_nextRoutePointPos = dest;
m_vecSeekPos = m_nextRoutePointPos;
bUsePedNodeSeek = true;
}
}
void
CPed::SetCarJack(CVehicle* car)
{
uint8 doorFlag;
eDoors door;
CPed *pedInSeat = nil;
if (car->IsBoat())
return;
switch (m_vehEnterType) {
case CAR_DOOR_RF:
doorFlag = CAR_DOOR_FLAG_RF;
door = DOOR_FRONT_RIGHT;
if (car->pPassengers[0]) {
pedInSeat = car->pPassengers[0];
} else if (m_nPedType == PEDTYPE_COP) {
pedInSeat = car->pDriver;
}
break;
case CAR_DOOR_RR:
doorFlag = CAR_DOOR_FLAG_RR;
door = DOOR_REAR_RIGHT;
pedInSeat = car->pPassengers[2];
break;
case CAR_DOOR_LF:
doorFlag = CAR_DOOR_FLAG_LF;
door = DOOR_FRONT_LEFT;
pedInSeat = car->pDriver;
break;
case CAR_DOOR_LR:
doorFlag = CAR_DOOR_FLAG_LR;
door = DOOR_REAR_LEFT;
pedInSeat = car->pPassengers[1];
break;
default:
doorFlag = CAR_DOOR_FLAG_UNKNOWN;
break;
}
if(car->bIsBus)
pedInSeat = car->pDriver;
if (m_fHealth > 0.0f && (IsPlayer() || m_objective == OBJECTIVE_KILL_CHAR_ON_FOOT || m_objective == OBJECTIVE_KILL_CHAR_ANY_MEANS ||
(car->VehicleCreatedBy != MISSION_VEHICLE && car->m_modelIndex != MI_DODO)))
if (pedInSeat && !pedInSeat->IsPedDoingDriveByShooting() && pedInSeat->m_nPedState == PED_DRIVING)
if (m_nPedState != PED_CARJACK && !m_pVehicleAnim)
if ((car->IsDoorReady(door) || car->IsDoorFullyOpen(door)))
if (!car->bIsBeingCarJacked && !(doorFlag & car->m_nGettingInFlags) && !(doorFlag & car->m_nGettingOutFlags))
SetCarJack_AllClear(car, m_vehEnterType, doorFlag);
}
class CPed_ : public CPed
{
public:
@ -16919,6 +17216,7 @@ STARTPATCHES
InjectHook(0x4D83E0, (void (CPed::*)(eObjective, void*)) &CPed::SetObjective, PATCH_JUMP);
InjectHook(0x4D89A0, (void (CPed::*)(eObjective, int16, int16)) &CPed::SetObjective, PATCH_JUMP);
InjectHook(0x4D8A90, (void (CPed::*)(eObjective, CVector)) &CPed::SetObjective, PATCH_JUMP);
InjectHook(0x4D8770, (void (CPed::*)(eObjective, CVector, float)) &CPed::SetObjective, PATCH_JUMP);
InjectHook(0x4DDEC0, &CPed::ReactToAttack, PATCH_JUMP);
InjectHook(0x4D0600, &CPed::SetIdle, PATCH_JUMP);
InjectHook(0x4E0E00, &CPed::QuitEnteringCar, PATCH_JUMP);
@ -17075,4 +17373,8 @@ STARTPATCHES
InjectHook(0x4D4970, &CPed::SetPedPositionInCar, PATCH_JUMP);
InjectHook(0x4D7D20, &CPed::WarpPedIntoCar, PATCH_JUMP);
InjectHook(0x4E0A40, &CPed::SetEnterCar_AllClear, PATCH_JUMP);
InjectHook(0x4D28D0, &CPed::WanderPath, PATCH_JUMP);
InjectHook(0x4E5570, &CPed::WarpPedToNearEntityOffScreen, PATCH_JUMP);
InjectHook(0x4E52A0, &CPed::WarpPedToNearLeaderOffScreen, PATCH_JUMP);
InjectHook(0x4E0220, &CPed::SetCarJack, PATCH_JUMP);
ENDPATCHES

View File

@ -411,7 +411,7 @@ public:
CVector2D m_stPathNodeStates[10];
uint16 m_nPathNodes;
int16 m_nCurPathNode;
int8 m_nPathState;
int8 m_nPathDir;
private:
int8 _pad2B5[3];
public:
@ -690,7 +690,7 @@ public:
void ScanForInterestingStuff(void);
void WarpPedIntoCar(CVehicle*);
void SetCarJack(CVehicle*);
void WarpPedToNearLeaderOffScreen(void);
bool WarpPedToNearLeaderOffScreen(void);
// Static methods
static CVector GetLocalPositionToOpenCarDoor(CVehicle *veh, uint32 component, float offset);
@ -768,6 +768,7 @@ public:
void SeekBoatPosition(void);
void UpdatePosition(void);
CObject *SpawnFlyingComponent(int, int8);
void SetCarJack_AllClear(CVehicle*, uint32, uint32);
#ifdef VC_PED_PORTS
bool CanPedJumpThis(CEntity*, CVector*);
#else
@ -782,6 +783,7 @@ public:
void SetPedState(PedState state) { m_nPedState = state; }
bool DyingOrDead(void) { return m_nPedState == PED_DIE || m_nPedState == PED_DEAD; }
void ReplaceWeaponWhenExitingVehicle(void);
void RemoveWeaponWhenEnteringVehicle(void);
bool IsNotInWreckedVehicle();
// set by 0482:set_threat_reaction_range_multiplier opcode