CPed completed!

And a few fixes
This commit is contained in:
eray orçunus 2019-11-20 01:15:45 +03:00
parent dd23030523
commit bd68b56b5d
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 assert(pCurrent); // GetIndex(0) doesn't look good
int handle = CPools::GetVehiclePool()->GetIndex(pCurrent); int handle = CPools::GetVehiclePool()->GetIndex(pCurrent);
if (handle != CTheScripts::StoreVehicleIndex && m_bIsMissionScript){ if (handle != CTheScripts::StoreVehicleIndex && m_bIsMissionScript){
CVehicle* pOld = CPools::GetVehiclePool()->GetAt(CTheScripts::StoreVehicleIndex); #ifdef FIX_BUGS
if (pOld){ if (CTheScripts::StoreVehicleIndex != -1)
CCarCtrl::RemoveFromInterestingVehicleList(pOld); #endif
if (pOld->VehicleCreatedBy == MISSION_VEHICLE && CTheScripts::StoreVehicleWasRandom){ {
pOld->VehicleCreatedBy = RANDOM_VEHICLE; CVehicle* pOld = CPools::GetVehiclePool()->GetAt(CTheScripts::StoreVehicleIndex);
pOld->bIsLocked = false; if (pOld){
CCarCtrl::NumRandomCars++; CCarCtrl::RemoveFromInterestingVehicleList(pOld);
CCarCtrl::NumMissionCars--; if (pOld->VehicleCreatedBy == MISSION_VEHICLE && CTheScripts::StoreVehicleWasRandom){
CTheScripts::MissionCleanup.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR); pOld->VehicleCreatedBy = RANDOM_VEHICLE;
pOld->bIsLocked = false;
CCarCtrl::NumRandomCars++;
CCarCtrl::NumMissionCars--;
CTheScripts::MissionCleanup.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
}
} }
} }
CTheScripts::StoreVehicleIndex = handle; CTheScripts::StoreVehicleIndex = handle;
switch (pCurrent->VehicleCreatedBy){ switch (pCurrent->VehicleCreatedBy){
case RANDOM_VEHICLE: case RANDOM_VEHICLE:
@ -2357,17 +2363,23 @@ int8 CRunningScript::ProcessCommandsFrom200To299(int32 command)
assert(pCurrent); // Here pCurrent shouldn't be NULL anyway assert(pCurrent); // Here pCurrent shouldn't be NULL anyway
int handle = CPools::GetVehiclePool()->GetIndex(pCurrent); int handle = CPools::GetVehiclePool()->GetIndex(pCurrent);
if (handle != CTheScripts::StoreVehicleIndex && m_bIsMissionScript) { if (handle != CTheScripts::StoreVehicleIndex && m_bIsMissionScript) {
CVehicle* pOld = CPools::GetVehiclePool()->GetAt(CTheScripts::StoreVehicleIndex); #ifdef FIX_BUGS
if (pOld) { if (CTheScripts::StoreVehicleIndex != -1)
CCarCtrl::RemoveFromInterestingVehicleList(pOld); #endif
if (pOld->VehicleCreatedBy == MISSION_VEHICLE && CTheScripts::StoreVehicleWasRandom) { {
pOld->VehicleCreatedBy = RANDOM_VEHICLE; CVehicle* pOld = CPools::GetVehiclePool()->GetAt(CTheScripts::StoreVehicleIndex);
pOld->bIsLocked = false; if (pOld){
CCarCtrl::NumRandomCars++; CCarCtrl::RemoveFromInterestingVehicleList(pOld);
CCarCtrl::NumMissionCars--; if (pOld->VehicleCreatedBy == MISSION_VEHICLE && CTheScripts::StoreVehicleWasRandom){
CTheScripts::MissionCleanup.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR); pOld->VehicleCreatedBy = RANDOM_VEHICLE;
pOld->bIsLocked = false;
CCarCtrl::NumRandomCars++;
CCarCtrl::NumMissionCars--;
CTheScripts::MissionCleanup.RemoveEntityFromList(CTheScripts::StoreVehicleIndex, CLEANUP_CAR);
}
} }
} }
CTheScripts::StoreVehicleIndex = handle; CTheScripts::StoreVehicleIndex = handle;
switch (pCurrent->VehicleCreatedBy) { switch (pCurrent->VehicleCreatedBy) {
case RANDOM_VEHICLE: case RANDOM_VEHICLE:

View File

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

View File

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

View File

@ -49,12 +49,6 @@
#include "ParticleObject.h" #include "ParticleObject.h"
#include "Floater.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 #define FEET_OFFSET 1.04f
CPed *gapTempPedList[50]; CPed *gapTempPedList[50];
@ -461,7 +455,7 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_wanderRangeBounds = nil; m_wanderRangeBounds = nil;
m_nPathNodes = 0; m_nPathNodes = 0;
m_nCurPathNode = 0; m_nCurPathNode = 0;
m_nPathState = 0; m_nPathDir = 0;
m_pLastPathNode = nil; m_pLastPathNode = nil;
m_pNextPathNode = nil; m_pNextPathNode = nil;
m_routeLastPoint = -1; m_routeLastPoint = -1;
@ -787,9 +781,7 @@ CPed::AimGun(void)
if (m_pSeekTarget) { if (m_pSeekTarget) {
if (m_pSeekTarget->IsPed()) { if (m_pSeekTarget->IsPed()) {
((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(&pos, PED_MID); ((CPed*)m_pSeekTarget)->m_pedIK.GetComponentPosition(&pos, PED_MID);
vector.x = pos.x; vector = pos;
vector.y = pos.y;
vector.z = pos.z;
} else { } else {
vector = m_pSeekTarget->GetPosition(); vector = m_pSeekTarget->GetPosition();
} }
@ -1445,8 +1437,15 @@ CPed::ClearPointGunAt(void)
ClearLookFlag(); ClearLookFlag();
ClearAimFlag(); ClearAimFlag();
bIsPointingGunAt = false; bIsPointingGunAt = false;
#ifndef VC_PED_PORTS
if (m_nPedState == PED_AIM_GUN) { if (m_nPedState == PED_AIM_GUN) {
RestorePreviousState(); RestorePreviousState();
#else
if (m_nPedState == PED_AIM_GUN || m_nPedState == PED_ATTACK) {
m_nPedState = PED_IDLE;
RestorePreviousState();
}
#endif
weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType); weaponInfo = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay); animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), weaponInfo->m_AnimToPlay);
if (!animAssoc || animAssoc->blendDelta < 0.0f) { if (!animAssoc || animAssoc->blendDelta < 0.0f) {
@ -1456,7 +1455,9 @@ CPed::ClearPointGunAt(void)
animAssoc->flags |= ASSOC_DELETEFADEDOUT; animAssoc->flags |= ASSOC_DELETEFADEDOUT;
animAssoc->blendDelta = -4.0f; animAssoc->blendDelta = -4.0f;
} }
#ifndef VC_PED_PORTS
} }
#endif
} }
void void
@ -2772,6 +2773,12 @@ void
CPed::SetIdle(void) CPed::SetIdle(void)
{ {
if (m_nPedState != PED_IDLE && m_nPedState != PED_MUG && m_nPedState != PED_FLEE_ENTITY) { 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; m_nPedState = PED_IDLE;
SetMoveState(PEDMOVE_STILL); SetMoveState(PEDMOVE_STILL);
} }
@ -4171,39 +4178,36 @@ CPed::SetWanderPath(int8 pathStateDest)
SetIdle(); SetIdle();
return false; return false;
} else { } else {
m_nPathDir = pathStateDest;
// m_nPathState is pure direction for values 1,2,3 and 5,6,7
m_nPathState = pathStateDest;
if (pathStateDest == 0) if (pathStateDest == 0)
pathStateDest = CGeneral::GetRandomNumberInRange(1, 7); pathStateDest = CGeneral::GetRandomNumberInRange(1, 7);
ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, 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) { 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 // We're at where we started and couldn't find any node
if (m_nPathState == pathStateDest) { if (m_nPathDir == pathStateDest) {
ClearAll(); ClearAll();
SetIdle(); SetIdle();
return false; return false;
} }
ThePaths.FindNextNodeWandering(PATH_PED, GetPosition(), &m_pLastPathNode, &m_pNextPathNode, 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 // We did it, save next path state and return true
m_nPathState = nextPathState; m_nPathDir = nextPathState;
m_nPedState = PED_WANDER_PATH; m_nPedState = PED_WANDER_PATH;
SetMoveState(PEDMOVE_WALK); SetMoveState(PEDMOVE_WALK);
bIsRunning = false; bIsRunning = false;
return true; return true;
} }
} else { } else {
m_nPathState = pathStateDest; m_nPathDir = pathStateDest;
bStartWanderPathOnFoot = true; bStartWanderPathOnFoot = true;
return false; return false;
} }
@ -4338,6 +4342,9 @@ CPed::SetPointGunAt(CEntity *to)
if (to) { if (to) {
SetLookFlag(to, true); SetLookFlag(to, true);
SetAimFlag(to); SetAimFlag(to);
#ifdef VC_PED_PORTS
SetLookTimer(INT_MAX);
#endif
} }
if (m_nPedState == PED_AIM_GUN || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK) if (m_nPedState == PED_AIM_GUN || bIsDucking || m_nWaitState == WAITSTATE_PLAYANIM_DUCK)
@ -5921,12 +5928,7 @@ void
CPed::SetSeek(CVector pos, float distanceToCountDone) CPed::SetSeek(CVector pos, float distanceToCountDone)
{ {
if (!IsPedInControl() 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)) || (m_nPedState == PED_SEEK_POS && m_vecSeekPos.x == pos.x && m_vecSeekPos.y == pos.y))
#endif
return; return;
if (GetWeapon()->m_eWeaponType == WEAPONTYPE_M16 if (GetWeapon()->m_eWeaponType == WEAPONTYPE_M16
@ -7454,10 +7456,10 @@ CPed::Flee(void)
if (m_pNextPathNode && CTimer::GetTimeInMilliseconds() > m_standardTimer) { if (m_pNextPathNode && CTimer::GetTimeInMilliseconds() > m_standardTimer) {
curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y); curDirectionShouldBe = CGeneral::GetNodeHeadingFromVector(GetPosition().x - ms_vec2DFleePosition.x, GetPosition().y - ms_vec2DFleePosition.y);
if (m_nPathState < curDirectionShouldBe) if (m_nPathDir < curDirectionShouldBe)
m_nPathState += 8; m_nPathDir += 8;
int dirDiff = m_nPathState - curDirectionShouldBe; int dirDiff = m_nPathDir - curDirectionShouldBe;
if (dirDiff > 2 && dirDiff < 6) { if (dirDiff > 2 && dirDiff < 6) {
realLastNode = nil; realLastNode = nil;
m_pLastPathNode = m_pNextPathNode; m_pLastPathNode = m_pNextPathNode;
@ -7493,7 +7495,7 @@ CPed::Flee(void)
curDirectionShouldBe += 8; curDirectionShouldBe += 8;
if (m_pNextPathNode && m_pNextPathNode != realLastNode && m_pNextPathNode != m_pLastPathNode && curDirectionShouldBe - nextDirection != 4) { if (m_pNextPathNode && m_pNextPathNode != realLastNode && m_pNextPathNode != m_pLastPathNode && curDirectionShouldBe - nextDirection != 4) {
m_nPathState = nextDirection; m_nPathDir = nextDirection;
m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000; m_standardTimer = CTimer::GetTimeInMilliseconds() + 2000;
} else { } else {
bUsePedNodeSeek = false; bUsePedNodeSeek = false;
@ -10072,7 +10074,7 @@ CPed::ProcessControl(void)
if (bStartWanderPathOnFoot) { if (bStartWanderPathOnFoot) {
if (IsPedInControl()) { if (IsPedInControl()) {
ClearAll(); ClearAll();
SetWanderPath(m_nPathState); SetWanderPath(m_nPathDir);
bStartWanderPathOnFoot = false; bStartWanderPathOnFoot = false;
} else if (m_nPedState == PED_DRIVING) { } else if (m_nPedState == PED_DRIVING) {
bWanderPathAfterExitingCar = true; 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 void
CPed::PedSetOutTrainCB(CAnimBlendAssociation *animAssoc, void *arg) CPed::PedSetOutTrainCB(CAnimBlendAssociation *animAssoc, void *arg)
{ {
@ -15753,6 +15769,7 @@ CPed::SeekCar(void)
else else
bVehEnterDoorIsBlocked = false; bVehEnterDoorIsBlocked = false;
// Arrived to the car
if (Seek()) { if (Seek()) {
if (!foundBetterPosToSeek) { if (!foundBetterPosToSeek) {
if (1.5f + GetPosition().z > dest.z && GetPosition().z - 0.5f < dest.z) { 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); CWeaponInfo *ourWeapon = CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType);
RemoveWeaponModel(ourWeapon->m_nModelId); RemoveWeaponModel(ourWeapon->m_nModelId);
} else { } else {
// Because we can use Uzi for drive by // Because we can use Uzi for drive by
// RemoveWeaponWhenEnteringVehicle in VC RemoveWeaponWhenEnteringVehicle();
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);
}
if (car->bLowVehicle) if (car->bLowVehicle)
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_LSIT, 100.0f); 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) CPed::SetEnterCar_AllClear(CVehicle *car, uint32 doorNode, uint32 doorFlag)
{ {
float zDiff = 0.0f; float zDiff = 0.0f;
if (!IsPlayer() || GetWeapon()->m_eWeaponType != WEAPONTYPE_UZI) { RemoveWeaponWhenEnteringVehicle();
// 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);
}
}
car->m_nGettingInFlags |= doorFlag; car->m_nGettingInFlags |= doorFlag;
bVehEnterDoorIsBlocked = false; bVehEnterDoorIsBlocked = false;
if (m_nPedState != PED_SEEK_CAR && m_nPedState != PED_SEEK_IN_BOAT) 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()) if (IsPlayer())
CWaterLevel::AllocateBoatWakeArray(); CWaterLevel::AllocateBoatWakeArray();
} else { } else {
if (m_vehEnterType != CAR_DOOR_LF && m_vehEnterType != CAR_DOOR_LR) { if (zDiff > 4.4f) {
if (zDiff <= 4.4f) { 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_ALIGNHI_RHS, 4.0f); m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_RHS, 4.0f);
} else
} else if (zDiff <= 4.4f) { m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGNHI_LHS, 4.0f);
m_pVehicleAnim = CAnimManager::BlendAnimation(GetClump(), ASSOCGRP_STD, ANIM_CAR_ALIGN_LHS, 4.0f);
} else { } 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); m_pVehicleAnim->SetFinishCallback(PedAnimAlignCB, this);
car->AutoPilot.m_nCruiseSpeed = 0; 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 class CPed_ : public CPed
{ {
public: public:
@ -16919,6 +17216,7 @@ STARTPATCHES
InjectHook(0x4D83E0, (void (CPed::*)(eObjective, void*)) &CPed::SetObjective, PATCH_JUMP); InjectHook(0x4D83E0, (void (CPed::*)(eObjective, void*)) &CPed::SetObjective, PATCH_JUMP);
InjectHook(0x4D89A0, (void (CPed::*)(eObjective, int16, int16)) &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(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(0x4DDEC0, &CPed::ReactToAttack, PATCH_JUMP);
InjectHook(0x4D0600, &CPed::SetIdle, PATCH_JUMP); InjectHook(0x4D0600, &CPed::SetIdle, PATCH_JUMP);
InjectHook(0x4E0E00, &CPed::QuitEnteringCar, PATCH_JUMP); InjectHook(0x4E0E00, &CPed::QuitEnteringCar, PATCH_JUMP);
@ -17075,4 +17373,8 @@ STARTPATCHES
InjectHook(0x4D4970, &CPed::SetPedPositionInCar, PATCH_JUMP); InjectHook(0x4D4970, &CPed::SetPedPositionInCar, PATCH_JUMP);
InjectHook(0x4D7D20, &CPed::WarpPedIntoCar, PATCH_JUMP); InjectHook(0x4D7D20, &CPed::WarpPedIntoCar, PATCH_JUMP);
InjectHook(0x4E0A40, &CPed::SetEnterCar_AllClear, 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 ENDPATCHES

View File

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