Peds, mission switcher & fixes

This commit is contained in:
eray orçunus 2020-06-13 23:39:14 +03:00
parent f78f707935
commit db6110e996
10 changed files with 838 additions and 186 deletions

View File

@ -166,6 +166,9 @@ bool doingMissionRetry;
#endif #endif
#ifdef MISSION_SWITCHER
int switchMissionTo = -1;
#endif
const uint32 CRunningScript::nSaveStructSize = const uint32 CRunningScript::nSaveStructSize =
#ifdef COMPATIBLE_SAVES #ifdef COMPATIBLE_SAVES
@ -885,11 +888,19 @@ void CRunningScript::Process()
} }
int8 CRunningScript::ProcessOneCommand() int8 CRunningScript::ProcessOneCommand()
{
int32 command;
#ifdef MISSION_SWITCHER
if (switchMissionTo != -1)
command = COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL;
else
#endif
{ {
++CTheScripts::CommandsExecuted; ++CTheScripts::CommandsExecuted;
int32 command = CTheScripts::Read2BytesFromScript(&m_nIp); command = CTheScripts::Read2BytesFromScript(&m_nIp);
m_bNotFlag = (command & 0x8000); m_bNotFlag = (command & 0x8000);
command &= 0x7FFF; command &= 0x7FFF;
}
if (command < 100) if (command < 100)
return ProcessCommands0To99(command); return ProcessCommands0To99(command);
if (command < 200) if (command < 200)
@ -2032,7 +2043,13 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
ped->ClearAll(); ped->ClearAll();
int8 path = ScriptParams[1]; int8 path = ScriptParams[1];
if (ScriptParams[1] < 0 || ScriptParams[1] > 7) if (ScriptParams[1] < 0 || ScriptParams[1] > 7)
// Max number GetRandomNumberInRange returns is max-1
#ifdef FIX_BUGS
path = CGeneral::GetRandomNumberInRange(0, 8);
#else
path = CGeneral::GetRandomNumberInRange(0, 7); path = CGeneral::GetRandomNumberInRange(0, 7);
#endif
ped->SetWanderPath(path); ped->SetWanderPath(path);
return 0; return 0;
} }
@ -2051,10 +2068,11 @@ int8 CRunningScript::ProcessCommands100To199(int32 command)
eMoveState state; eMoveState state;
switch (ScriptParams[5]) { switch (ScriptParams[5]) {
case 0: state = PEDMOVE_WALK; break; case 0: state = PEDMOVE_WALK; break;
case 1: state = PEDMOVE_SPRINT; break; case 1: state = PEDMOVE_RUN; break;
default: assert(0); default: assert(0);
} }
ped->ClearAll(); ped->ClearAll();
ped->m_pathNodeTimer = 0;
ped->SetFollowPath(pos, radius, state, nil, nil, 999999); ped->SetFollowPath(pos, radius, state, nil, nil, 999999);
return 0; return 0;
} }
@ -9125,7 +9143,14 @@ int8 CRunningScript::ProcessCommands1000To1099(int32 command)
return 0; return 0;
case COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL: case COMMAND_LOAD_AND_LAUNCH_MISSION_INTERNAL:
{ {
#ifdef MISSION_SWITCHER
if (switchMissionTo != -1) {
ScriptParams[0] = switchMissionTo;
switchMissionTo = -1;
} else
#endif
CollectParameters(&m_nIp, 1); CollectParameters(&m_nIp, 1);
if (CTheScripts::NumberOfExclusiveMissionScripts > 0 && ScriptParams[0] <= UINT16_MAX - 2) if (CTheScripts::NumberOfExclusiveMissionScripts > 0 && ScriptParams[0] <= UINT16_MAX - 2)
return 0; return 0;
#ifdef MISSION_REPLAY #ifdef MISSION_REPLAY
@ -10676,7 +10701,7 @@ int8 CRunningScript::ProcessCommands1200To1299(int32 command)
CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]); CPed* pTargetPed = CPools::GetPedPool()->GetAt(ScriptParams[1]);
assert(pTargetPed); assert(pTargetPed);
pPed->bScriptObjectiveCompleted = false; pPed->bScriptObjectiveCompleted = false;
pPed->SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING, pPed); pPed->SetObjective(OBJECTIVE_GOTO_CHAR_ON_FOOT_WALKING, pTargetPed);
return 0; return 0;
} }
//case COMMAND_IS_PICKUP_IN_ZONE: //case COMMAND_IS_PICKUP_IN_ZONE:
@ -14220,7 +14245,7 @@ void CTheScripts::CleanUpThisPed(CPed* pPed)
pPed->CharCreatedBy = RANDOM_CHAR; pPed->CharCreatedBy = RANDOM_CHAR;
if (pPed->m_nPedType == PEDTYPE_PROSTITUTE) if (pPed->m_nPedType == PEDTYPE_PROSTITUTE)
pPed->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 30000; pPed->m_objectiveTimer = CTimer::GetTimeInMilliseconds() + 30000;
if (pPed->bInVehicle) { if (pPed->InVehicle()) {
if (pPed->m_pMyVehicle->pDriver == pPed) { if (pPed->m_pMyVehicle->pDriver == pPed) {
if (pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR) { if (pPed->m_pMyVehicle->m_vehType == VEHICLE_TYPE_CAR) {
CCarCtrl::JoinCarWithRoadSystem(pPed->m_pMyVehicle); CCarCtrl::JoinCarWithRoadSystem(pPed->m_pMyVehicle);
@ -14245,10 +14270,14 @@ void CTheScripts::CleanUpThisPed(CPed* pPed)
pPed->ClearObjective(); pPed->ClearObjective();
pPed->bRespondsToThreats = true; pPed->bRespondsToThreats = true;
pPed->bScriptObjectiveCompleted = false; pPed->bScriptObjectiveCompleted = false;
pPed->bKindaStayInSamePlace = false;
pPed->ClearLeader(); pPed->ClearLeader();
if (pPed->IsPedInControl()) if (pPed->IsPedInControl())
pPed->SetWanderPath(CGeneral::GetRandomNumber() & 7); pPed->SetWanderPath(CGeneral::GetRandomNumber() & 7);
if (flees) { if (flees) {
if (pPed->m_nPedState == PED_FOLLOW_PATH && state != PED_FOLLOW_PATH)
pPed->ClearFollowPath();
pPed->m_nPedState = state; pPed->m_nPedState = state;
pPed->SetMoveState(ms); pPed->SetMoveState(ms);
} }

View File

@ -546,3 +546,7 @@ void RetryMission(int, int);
#ifdef USE_DEBUG_SCRIPT_LOADER #ifdef USE_DEBUG_SCRIPT_LOADER
extern int scriptToLoad; extern int scriptToLoad;
#endif #endif
#ifdef MISSION_SWITCHER
extern int switchMissionTo;
#endif

View File

@ -1801,6 +1801,21 @@ CColSphere::Set(float radius, const CVector &center, uint8 surf, uint8 piece)
this->piece = piece; this->piece = piece;
} }
bool
CColSphere::IntersectRay(CVector const& from, CVector const& dir, CVector &entry, CVector &exit)
{
CVector distToCenter = from - center;
float distToTouchSqr = distToCenter.MagnitudeSqr() - sq(radius);
float root1, root2;
if (!CGeneral::SolveQuadratic(1.0f, DotProduct(distToCenter, dir) * 2.f, distToTouchSqr, root1, root2))
return false;
entry = from + dir * root1;
exit = from + dir * root2;
return true;
}
void void
CColBox::Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece) CColBox::Set(const CVector &min, const CVector &max, uint8 surf, uint8 piece)
{ {

View File

@ -31,6 +31,7 @@ struct CColSphere : public CSphere
uint8 piece; uint8 piece;
void Set(float radius, const CVector &center, uint8 surf, uint8 piece); void Set(float radius, const CVector &center, uint8 surf, uint8 piece);
bool IntersectRay(CVector const &from, CVector const &dir, CVector &entry, CVector &exit);
using CSphere::Set; using CSphere::Set;
}; };

View File

@ -134,6 +134,18 @@ public:
return *str2 != '\0'; return *str2 != '\0';
} }
static bool SolveQuadratic(float a, float b, float c, float &root1, float &root2)
{
float discriminant = b * b - 4.f * a * c;
if (discriminant < 0.f)
return false;
float discriminantSqrt = Sqrt(discriminant);
root2 = (-b + discriminantSqrt) / (2.f * a);
root1 = (-b - discriminantSqrt) / (2.f * a);
return true;
}
// not too sure about all these... // not too sure about all these...
static uint16 GetRandomNumber(void) static uint16 GetRandomNumber(void)
{ return myrand() & MYRAND_MAX; } { return myrand() & MYRAND_MAX; }

View File

@ -202,12 +202,11 @@ enum Config {
#define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible #define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible
#define FIX_HIGH_FPS_BUGS_ON_FRONTEND #define FIX_HIGH_FPS_BUGS_ON_FRONTEND
// Rendering/display
#define ASPECT_RATIO_SCALE // Not just makes everything scale with aspect ratio, also adds support for all aspect ratios
// Just debug menu entries // Just debug menu entries
#ifdef DEBUGMENU #ifdef DEBUGMENU
#define TOGGLEABLE_BETA_FEATURES // not too many things #define TOGGLEABLE_BETA_FEATURES // not too many things
#define RELOADABLES // some debug menu options to reload TXD files #define RELOADABLES // some debug menu options to reload TXD files
#define MISSION_SWITCHER // from debug menu
#endif #endif
// Rendering/display // Rendering/display

View File

@ -31,6 +31,7 @@
#include "Text.h" #include "Text.h"
#include "WaterLevel.h" #include "WaterLevel.h"
#include "main.h" #include "main.h"
#include "Script.h"
#ifndef _WIN32 #ifndef _WIN32
#include "assert.h" #include "assert.h"
@ -309,6 +310,15 @@ ResetCamStatics(void)
TheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true; TheCamera.Cams[TheCamera.ActiveCam].ResetStatics = true;
} }
#ifdef MISSION_SWITCHER
int8 nextMissionToSwitch = 0;
static void
SwitchToMission(void)
{
switchMissionTo = nextMissionToSwitch;
}
#endif
static const char *carnames[] = { static const char *carnames[] = {
"landstal", "idaho", "stinger", "linerun", "peren", "sentinel", "rio", "firetruk", "trash", "stretch", "manana", "landstal", "idaho", "stinger", "linerun", "peren", "sentinel", "rio", "firetruk", "trash", "stretch", "manana",
"infernus", "voodoo", "pony", "mule", "cheetah", "ambulan", "fbicar", "moonbeam", "esperant", "taxi", "washing", "infernus", "voodoo", "pony", "mule", "cheetah", "ambulan", "fbicar", "moonbeam", "esperant", "taxi", "washing",
@ -512,7 +522,10 @@ DebugMenuPopulate(void)
#ifdef TIMEBARS #ifdef TIMEBARS
DebugMenuAddVarBool8("Debug", "Show Timebars", &gbShowTimebars, nil); DebugMenuAddVarBool8("Debug", "Show Timebars", &gbShowTimebars, nil);
#endif #endif
#ifdef MISSION_SWITCHER
DebugMenuAddInt8("Debug", "Select mission no", &nextMissionToSwitch, nil, 1, 0, 96, nil);
DebugMenuAddCmd("Debug", "Start selected mission ", SwitchToMission);
#endif
extern bool PrintDebugCode; extern bool PrintDebugCode;
extern int16 DebugCamMode; extern int16 DebugCamMode;
DebugMenuAddVarBool8("Cam", "Use mouse Cam", &CCamera::m_bUseMouse3rdPerson, nil); DebugMenuAddVarBool8("Cam", "Use mouse Cam", &CCamera::m_bUseMouse3rdPerson, nil);

View File

@ -102,6 +102,9 @@ bool CPed::bPedCheat2;
bool CPed::bPedCheat3; bool CPed::bPedCheat3;
CVector2D CPed::ms_vec2DFleePosition; CVector2D CPed::ms_vec2DFleePosition;
CVector vecNextPathNode;
bool vecNextPathNodeInitialized;
void *CPed::operator new(size_t sz) { return CPools::GetPedPool()->New(); } void *CPed::operator new(size_t sz) { return CPools::GetPedPool()->New(); }
void *CPed::operator new(size_t sz, int handle) { return CPools::GetPedPool()->New(handle); } void *CPed::operator new(size_t sz, int handle) { return CPools::GetPedPool()->New(handle); }
void CPed::operator delete(void *p, size_t sz) { CPools::GetPedPool()->Delete((CPed*)p); } void CPed::operator delete(void *p, size_t sz) { CPools::GetPedPool()->Delete((CPed*)p); }
@ -145,6 +148,7 @@ CPed::~CPed(void)
DMAudio.DestroyEntity(m_audioEntityId); DMAudio.DestroyEntity(m_audioEntityId);
} }
// --MIAMI: Done
void void
CPed::FlagToDestroyWhenNextProcessed(void) CPed::FlagToDestroyWhenNextProcessed(void)
{ {
@ -231,6 +235,9 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_wepSkills = 0; m_wepSkills = 0;
m_distanceToCountSeekDone = 1.0f; m_distanceToCountSeekDone = 1.0f;
m_acceptableHeadingOffset = 0.1f; m_acceptableHeadingOffset = 0.1f;
m_followPathDestPos = CVector(0.f, 0.f, 0.f);
m_followPathAbortDist = 0.0f;
m_followPathMoveState = PEDMOVE_NONE;
bRunningToPhone = false; bRunningToPhone = false;
m_phoneId = -1; m_phoneId = -1;
m_lastAccident = 0; m_lastAccident = 0;
@ -257,11 +264,20 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
m_fLookDirection = 0.0f; m_fLookDirection = 0.0f;
m_pCurSurface = nil; m_pCurSurface = nil;
m_wanderRangeBounds = nil; m_wanderRangeBounds = nil;
m_nPathNodes = 0;
m_nCurPathNode = 0; for (int i = 0; i < ARRAY_SIZE(m_pathNodesToGo); i++) {
m_pathNodesToGo[i] = nil;
}
m_nNumPathNodes = 0;
m_nCurPathNodeId = 0;
m_nPathDir = 0; m_nPathDir = 0;
m_pLastPathNode = nil; m_pLastPathNode = nil;
m_pNextPathNode = nil; m_pNextPathNode = nil;
m_followPathWalkAroundEnt = nil;
m_followPathTargetEnt = nil;
m_pathNodeTimer = 0;
m_pCurPathNode = nil;
m_routeLastPoint = -1; m_routeLastPoint = -1;
m_routeStartPoint = 0; m_routeStartPoint = 0;
m_routePointsPassed = 0; m_routePointsPassed = 0;
@ -398,9 +414,6 @@ CPed::CPed(uint32 pedType) : m_pedIK(this)
for (int i = 0; i < ARRAY_SIZE(m_nearPeds); i++) { for (int i = 0; i < ARRAY_SIZE(m_nearPeds); i++) {
m_nearPeds[i] = nil; m_nearPeds[i] = nil;
if (i < ARRAY_SIZE(m_pPathNodesStates)) {
m_pPathNodesStates[i] = nil;
}
} }
m_maxWeaponTypeAllowed = WEAPONTYPE_UNARMED; m_maxWeaponTypeAllowed = WEAPONTYPE_UNARMED;
m_currentWeapon = WEAPONTYPE_UNARMED; m_currentWeapon = WEAPONTYPE_UNARMED;
@ -995,7 +1008,7 @@ CPed::FinishedReloadCB(CAnimBlendAssociation *reloadAssoc, void *arg)
void void
CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg) CPed::FinishedAttackCB(CAnimBlendAssociation *attackAssoc, void *arg)
{ {
CAnimBlendAssociation *newAnim, *reloadAnimAssoc; CAnimBlendAssociation *newAnim, *reloadAnimAssoc = nil;
CPed *ped = (CPed*)arg; CPed *ped = (CPed*)arg;
CWeaponInfo *currentWeapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType); CWeaponInfo *currentWeapon = CWeaponInfo::GetWeaponInfo(ped->GetWeapon()->m_eWeaponType);
@ -1650,30 +1663,24 @@ CPed::ClearPointGunAt(void)
} }
} }
// --MIAMI: Done
void void
CPed::BeingDraggedFromCar(void) CPed::BeingDraggedFromCar(void)
{ {
CAnimBlendAssociation *animAssoc;
AnimationId enterAnim; AnimationId enterAnim;
bool dontRunAnim = false; bool dontRunAnim = false;
PedLineUpPhase lineUpType;
if (!m_pVehicleAnim) { if (!m_pVehicleAnim) {
CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f); CAnimManager::BlendAnimation(GetClump(), m_animGroup, ANIM_IDLE_STANCE, 100.0f);
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SIT);
if (!animAssoc) {
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_LSIT);
if (!animAssoc) {
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITP);
if (!animAssoc)
animAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_CAR_SITPLO);
}
}
if (animAssoc)
animAssoc->blendDelta = -1000.0f;
AssocGroupId assocGroup;
if (m_pMyVehicle->IsBike()) {
enterAnim = ANIM_BIKE_HIT;
assocGroup = ((CBike*)m_pMyVehicle)->m_bikeAnimType;
} else {
if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) { if (m_vehEnterType == CAR_DOOR_LF || m_vehEnterType == CAR_DOOR_LR) {
if (bWillBeQuickJacked) { if (bWillBeQuickJacked && m_vehEnterType == CAR_DOOR_LF) {
enterAnim = ANIM_CAR_QJACKED; enterAnim = ANIM_CAR_QJACKED;
} else if (m_pMyVehicle->bLowVehicle) { } else if (m_pMyVehicle->bLowVehicle) {
enterAnim = ANIM_CAR_LJACKED_LHS; enterAnim = ANIM_CAR_LJACKED_LHS;
@ -1688,27 +1695,38 @@ CPed::BeingDraggedFromCar(void)
} else } else
dontRunAnim = true; dontRunAnim = true;
assocGroup = ASSOCGRP_STD;
}
if (!dontRunAnim) if (!dontRunAnim)
m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), ASSOCGRP_STD, enterAnim); m_pVehicleAnim = CAnimManager::AddAnimation(GetClump(), assocGroup, enterAnim);
m_pVehicleAnim->SetFinishCallback(PedSetDraggedOutCarCB, this); m_pVehicleAnim->SetFinishCallback(PedSetDraggedOutCarCB, this);
lineUpType = LINE_UP_TO_CAR_START;
if (m_pMyVehicle && m_pMyVehicle->IsBike()) {
LineUpPedWithCar(LINE_UP_TO_CAR_FALL);
} else {
LineUpPedWithCar(LINE_UP_TO_CAR_START);
}
return;
} else if (m_pVehicleAnim->animId == ANIM_BIKE_HIT) {
LineUpPedWithCar(LINE_UP_TO_CAR_FALL);
} else if (m_pVehicleAnim->currentTime <= 1.4f) { } else if (m_pVehicleAnim->currentTime <= 1.4f) {
m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
lineUpType = LINE_UP_TO_CAR_START; LineUpPedWithCar(LINE_UP_TO_CAR_START);
} else { } else {
lineUpType = LINE_UP_TO_CAR_2; LineUpPedWithCar(LINE_UP_TO_CAR_2);
} }
LineUpPedWithCar(lineUpType); static float mult = 5.f;
#ifdef VC_PED_PORTS
if (m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) { if (m_objective == OBJECTIVE_LEAVE_CAR_AND_DIE) {
if (m_pMyVehicle) { if (m_pMyVehicle) {
m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_STD_ANIMS, m_pVehicleAnim->currentTime * 5.0f); m_pMyVehicle->ProcessOpenDoor(m_vehEnterType, NUM_STD_ANIMS, m_pVehicleAnim->currentTime * mult);
} }
} }
#endif
} }
void void
@ -4575,6 +4593,7 @@ CPed::ClearInvestigateEvent(void)
SetMoveState(PEDMOVE_WALK); SetMoveState(PEDMOVE_WALK);
} }
// --MIAMI: Done
void void
CPed::ClearLeader(void) CPed::ClearLeader(void)
{ {
@ -4836,19 +4855,15 @@ CPed::SetPointGunAt(CEntity *to)
CAnimBlendAssociation *aimAssoc; CAnimBlendAssociation *aimAssoc;
if (bCrouchWhenShooting && bIsDucking) { if (bCrouchWhenShooting && bIsDucking && GetCrouchFireAnim(curWeapon)) {
if (!!curWeapon->m_bCrouchFire) {
aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(curWeapon)); aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), GetCrouchFireAnim(curWeapon));
}
} else { } else {
aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE); aimAssoc = RpAnimBlendClumpGetAssociation(GetClump(), ANIM_WEAPON_FIRE);
} }
if (!aimAssoc || aimAssoc->blendDelta < 0.0f) { if (!aimAssoc || aimAssoc->blendDelta < 0.0f) {
if (bCrouchWhenShooting && bIsDucking) { if (bCrouchWhenShooting && bIsDucking && GetCrouchFireAnim(curWeapon)) {
if (!!curWeapon->m_bCrouchFire) {
aimAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon), 4.0f); aimAssoc = CAnimManager::BlendAnimation(GetClump(), curWeapon->m_AnimToPlay, GetCrouchFireAnim(curWeapon), 4.0f);
}
} else { } else {
aimAssoc = CAnimManager::AddAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE); aimAssoc = CAnimManager::AddAnimation(GetClump(), curWeapon->m_AnimToPlay, ANIM_WEAPON_FIRE);
} }
@ -5741,7 +5756,7 @@ CPed::SetWaitState(eWaitState state, void *time)
if (!IsPedInControl()) if (!IsPedInControl())
return; return;
if (m_nWaitState == WAITSTATE_RIOT && state == WAITSTATE_FALSE) if (m_nWaitState == WAITSTATE_RIOT && state != WAITSTATE_FALSE)
return; return;
if (state != m_nWaitState) if (state != m_nWaitState)
@ -6429,8 +6444,10 @@ CPed::SetBuyIceCream(void)
void void
CPed::SetChat(CEntity *chatWith, uint32 time) CPed::SetChat(CEntity *chatWith, uint32 time)
{ {
if(m_nPedState != PED_CHAT) if (m_nPedState != PED_CHAT) {
m_nLastPedState = PED_NONE;
SetStoredState(); SetStoredState();
}
SetPedState(PED_CHAT); SetPedState(PED_CHAT);
SetMoveState(PEDMOVE_STILL); SetMoveState(PEDMOVE_STILL);
@ -6510,6 +6527,7 @@ CPed::SetDead(void)
CEventList::RegisterEvent(EVENT_DEAD_PED, EVENT_ENTITY_PED, this, nil, 1000); CEventList::RegisterEvent(EVENT_DEAD_PED, EVENT_ENTITY_PED, this, nil, 1000);
} }
// --MIAMI: Done
void void
CPed::SetSeek(CEntity *seeking, float distanceToCountDone) CPed::SetSeek(CEntity *seeking, float distanceToCountDone)
{ {
@ -6519,24 +6537,25 @@ CPed::SetSeek(CEntity *seeking, float distanceToCountDone)
if (m_nPedState == PED_SEEK_ENTITY && m_pSeekTarget == seeking) if (m_nPedState == PED_SEEK_ENTITY && m_pSeekTarget == seeking)
return; return;
if (!seeking) if (!seeking || m_nPedState == PED_FOLLOW_PATH)
return; return;
if (m_nPedState != PED_SEEK_ENTITY) if (m_nPedState != PED_SEEK_ENTITY)
SetStoredState(); SetStoredState();
m_nPedState = PED_SEEK_ENTITY; SetPedState(PED_SEEK_ENTITY);
m_distanceToCountSeekDone = distanceToCountDone; m_distanceToCountSeekDone = distanceToCountDone;
m_pSeekTarget = seeking; m_pSeekTarget = seeking;
m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget); m_pSeekTarget->RegisterReference((CEntity **) &m_pSeekTarget);
SetMoveState(PEDMOVE_STILL); SetMoveState(PEDMOVE_STILL);
} }
// --MIAMI: Done
void void
CPed::SetSeek(CVector pos, float distanceToCountDone) CPed::SetSeek(CVector pos, float distanceToCountDone)
{ {
if (!IsPedInControl() if (!IsPedInControl()
|| (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) || m_nPedState == PED_FOLLOW_PATH)
return; return;
if (!CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAimWithArm) { if (!CWeaponInfo::GetWeaponInfo(GetWeapon()->m_eWeaponType)->m_bCanAimWithArm) {
@ -6546,7 +6565,7 @@ CPed::SetSeek(CVector pos, float distanceToCountDone)
if (m_nPedState != PED_SEEK_POS) if (m_nPedState != PED_SEEK_POS)
SetStoredState(); SetStoredState();
m_nPedState = PED_SEEK_POS; SetPedState(PED_SEEK_POS);
m_distanceToCountSeekDone = distanceToCountDone; m_distanceToCountSeekDone = distanceToCountDone;
m_vecSeekPos = pos; m_vecSeekPos = pos;
} }
@ -8094,6 +8113,7 @@ CPed::Wait(void)
RestoreHeadingRate(); RestoreHeadingRate();
} }
// --MIAMI: Done
bool bool
CPed::Seek(void) CPed::Seek(void)
{ {
@ -8112,7 +8132,7 @@ CPed::Seek(void)
false, true, false, false, false, false); false, true, false, false, false, false);
if (obstacle) { if (obstacle) {
if (!obstacle->IsVehicle() || ((CVehicle*)obstacle)->m_vehType == VEHICLE_TYPE_CAR) { if (!obstacle->IsVehicle() || ((CVehicle*)obstacle)->IsCar()) {
distanceToCountItDone = 2.5f; distanceToCountItDone = 2.5f;
} else { } else {
CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(obstacle->GetModelIndex()); CVehicleModelInfo *vehModel = (CVehicleModelInfo *)CModelInfo::GetModelInfo(obstacle->GetModelIndex());
@ -8128,6 +8148,13 @@ CPed::Seek(void)
if (!m_pSeekTarget && m_nPedState == PED_SEEK_ENTITY) if (!m_pSeekTarget && m_nPedState == PED_SEEK_ENTITY)
ClearSeek(); ClearSeek();
if (m_objective == OBJECTIVE_FOLLOW_PED_IN_FORMATION && !m_pedInObjective) {
m_objective = OBJECTIVE_NONE;
ClearObjective();
SetWanderPath(0);
return false;
}
float seekPosDist = (m_vecSeekPos - GetPosition()).Magnitude2D(); float seekPosDist = (m_vecSeekPos - GetPosition()).Magnitude2D();
if (seekPosDist < 2.0f || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT) { if (seekPosDist < 2.0f || m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT) {
@ -8163,7 +8190,9 @@ CPed::Seek(void)
} }
} }
if (seekPosDist >= distanceToCountItDone) { CVector *nextNode = SeekFollowingPath();
if (nextNode || seekPosDist >= distanceToCountItDone) {
if (bIsRunning && nextMove != PEDMOVE_SPRINT) if (bIsRunning && nextMove != PEDMOVE_SPRINT)
nextMove = PEDMOVE_RUN; nextMove = PEDMOVE_RUN;
@ -8200,10 +8229,17 @@ CPed::Seek(void)
m_actionY = 0; m_actionY = 0;
} }
} }
} else {
if (nextNode) {
m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
nextNode->x, nextNode->y,
GetPosition().x, GetPosition().y);
} else { } else {
m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints( m_fRotationDest = CGeneral::GetRadianAngleBetweenPoints(
m_vecSeekPos.x, m_vecSeekPos.y, m_vecSeekPos.x, m_vecSeekPos.y,
GetPosition().x, GetPosition().y); GetPosition().x, GetPosition().y);
}
float neededTurn = Abs(m_fRotationDest - m_fRotationCur); float neededTurn = Abs(m_fRotationDest - m_fRotationCur);
@ -8237,7 +8273,7 @@ CPed::Seek(void)
} }
if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_SPRINT_TO_COORD || if (m_objective == OBJECTIVE_GOTO_AREA_ON_FOOT || m_objective == OBJECTIVE_RUN_TO_AREA || m_objective == OBJECTIVE_SPRINT_TO_COORD ||
m_objective == OBJECTIVE_GOTO_AREA_ANY_MEANS) { m_objective == OBJECTIVE_GOTO_AREA_ANY_MEANS || IsUseAttractorObjective(m_objective)) {
if (m_pNextPathNode) if (m_pNextPathNode)
m_pNextPathNode = nil; m_pNextPathNode = nil;
@ -8247,16 +8283,30 @@ CPed::Seek(void)
bUsePedNodeSeek = true; bUsePedNodeSeek = true;
} }
if (SeekFollowingPath(nil))
m_nCurPathNode++;
return true; return true;
} }
bool CVector*
CPed::SeekFollowingPath(CVector *unused) CPed::SeekFollowingPath(void)
{ {
return m_nCurPathNode <= m_nPathNodes && m_nPathNodes; // unused
if (!vecNextPathNodeInitialized)
vecNextPathNodeInitialized = true;
if (m_nCurPathNodeId >= m_nNumPathNodes || m_nNumPathNodes == 0)
return nil;
vecNextPathNode = m_pathNodesToGo[m_nCurPathNodeId]->GetPosition();
if ((vecNextPathNode - GetPosition()).Magnitude2D() < m_distanceToCountSeekDone) {
m_nCurPathNodeId++;
if (m_nCurPathNodeId < m_nNumPathNodes)
m_pCurPathNode = m_pathNodesToGo[m_nCurPathNodeId];
}
if (m_nCurPathNodeId == m_nNumPathNodes)
return nil;
else
return &vecNextPathNode;
} }
void void
@ -8442,31 +8492,34 @@ CPed::Flee(void)
} }
// --MIAMI: Done
void void
CPed::FollowPath(void) CPed::FollowPath(void)
{ {
m_vecSeekPos.x = m_stPathNodeStates[m_nCurPathNode].x; m_pCurPathNode = m_pathNodesToGo[m_nCurPathNodeId];
m_vecSeekPos.y = m_stPathNodeStates[m_nCurPathNode].y; if (m_pathNodeTimer && CTimer::GetTimeInMilliseconds() > m_pathNodeTimer) {
RestorePreviousState();
ClearFollowPath();
m_pathNodeTimer = 0;
} else {
if (m_pathNodesToGo[m_nCurPathNodeId]) {
m_vecSeekPos.x = m_pathNodesToGo[m_nCurPathNodeId]->GetPosition().x;
m_vecSeekPos.y = m_pathNodesToGo[m_nCurPathNodeId]->GetPosition().y;
m_vecSeekPos.z = GetPosition().z; 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()) { if (Seek()) {
m_nCurPathNode++; if (m_nCurPathNodeId == m_nNumPathNodes) {
if (m_nCurPathNode == m_nPathNodes)
RestorePreviousState(); RestorePreviousState();
ClearFollowPath();
SetFollowPath(m_followPathDestPos, m_followPathAbortDist, m_followPathMoveState, m_followPathWalkAroundEnt,
m_followPathTargetEnt, m_pathNodeTimer - CTimer::GetTimeInMilliseconds());
}
}
} else {
RestorePreviousState();
ClearFollowPath();
m_pathNodeTimer = 0;
}
} }
} }
@ -10534,17 +10587,22 @@ CPed::ProcessControl(void)
if (!bVehEnterDoorIsBlocked) { if (!bVehEnterDoorIsBlocked) {
if (collidingVeh->GetStatus() != STATUS_PLAYER || CharCreatedBy == MISSION_CHAR) { if (collidingVeh->GetStatus() != STATUS_PLAYER || CharCreatedBy == MISSION_CHAR) {
// VC calls SetDirectionToWalkAroundVehicle instead if ped is in PED_SEEK_CAR. if (m_nPedState == PED_SEEK_CAR) {
SetDirectionToWalkAroundObject(collidingVeh); SetDirectionToWalkAroundObject(collidingVeh);
CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer; CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer;
} else {
SetDirectionToWalkAroundVehicle(collidingVeh);
}
} else { } else {
if (CTimer::GetTimeInMilliseconds() >= CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer if (CTimer::GetTimeInMilliseconds() >= CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer
|| m_nPedStateTimer >= CTimer::GetTimeInMilliseconds()) { || m_nPedStateTimer >= CTimer::GetTimeInMilliseconds()) {
// VC calls SetDirectionToWalkAroundVehicle instead if ped is in PED_SEEK_CAR. if (m_nPedState == PED_SEEK_CAR) {
SetDirectionToWalkAroundObject(collidingVeh); SetDirectionToWalkAroundObject(collidingVeh);
CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer; CWorld::Players[CWorld::PlayerInFocus].m_nLastBumpPlayerCarTimer = m_nPedStateTimer;
} else {
SetDirectionToWalkAroundVehicle(collidingVeh);
}
} else if (m_fleeFrom != collidingVeh) { } else if (m_fleeFrom != collidingVeh) {
SetFlee(collidingVeh, 4000); SetFlee(collidingVeh, 4000);
bUsePedNodeSeek = false; bUsePedNodeSeek = false;
@ -14926,6 +14984,9 @@ CPed::SetSeekCar(CVehicle *car, uint32 doorNode)
if (m_nPedState == PED_SEEK_CAR) if (m_nPedState == PED_SEEK_CAR)
return; return;
if (!CanSetPedState() || m_nPedState == PED_DRIVING)
return;
SetStoredState(); SetStoredState();
m_pSeekTarget = car; m_pSeekTarget = car;
m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget); m_pSeekTarget->RegisterReference((CEntity**) &m_pSeekTarget);
@ -15024,7 +15085,13 @@ CanWeSeeTheCorner(CVector2D dist, CVector2D fwdOffset)
} }
#endif #endif
// This function looks completely same on VC. // --MIAMI: Done
bool
CPed::SetDirectionToWalkAroundVehicle(CVehicle* veh)
{
return SetFollowPath(m_vecSeekPos, 0.0f, m_nMoveState, veh, m_pedInObjective, m_nMoveState == PEDMOVE_WALK ? 2000 : 250);
}
void void
CPed::SetDirectionToWalkAroundObject(CEntity *obj) CPed::SetDirectionToWalkAroundObject(CEntity *obj)
{ {
@ -16355,36 +16422,519 @@ CPed::SetSolicit(uint32 time)
} }
} }
// --MIAMI: Done
bool bool
CPed::SetFollowPath(CVector dest, float radius, eMoveState state, CEntity* pFollowedPed, CEntity*, int time) CPed::SetFollowPathStatic(void)
{ {
// TODO(MIAMI): new follow ClearFollowPath();
if (m_nPedState == PED_FOLLOW_PATH) if (sq(m_followPathAbortDist) > (GetPosition() - m_followPathDestPos).MagnitudeSqr()
return false; && CWorld::IsWanderPathClear(GetPosition(), m_followPathDestPos, 0.5f, 4)) {
if (FindPlayerPed() != this) RestorePreviousState();
return false; if (m_objective == OBJECTIVE_NONE) {
if (m_followPathMoveState == PEDMOVE_RUN)
SetObjective(OBJECTIVE_RUN_TO_AREA, m_followPathDestPos);
else
SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, m_followPathDestPos);
}
SetPedState(PED_NONE);
return true;
} else {
ThePaths.DoPathSearch(PATH_PED, GetPosition(), -1, m_followPathDestPos, m_pathNodesToGo, &m_nNumPathNodes,
ARRAY_SIZE(m_pathNodesToGo), nil, nil, 999999.0f, -1);
if ((dest - GetPosition()).Magnitude() <= 2.0f) if (m_nNumPathNodes != 0) {
return false; if (m_nNumPathNodes > 0 && m_pathNodesToGo[0] != m_pCurPathNode) {
for (int i = 0; i < ARRAY_SIZE(m_pathNodesToGo) - 1; i++) {
m_pathNodesToGo[i] = m_pathNodesToGo[i+1];
}
--m_nNumPathNodes;
}
for (int i = 0; i < m_nNumPathNodes; ++i) {
CVector nodePos = m_pathNodesToGo[i]->GetPosition();
if (sq(m_followPathAbortDist) > (nodePos - m_followPathDestPos).MagnitudeSqr()
&& CWorld::IsWanderPathClear(nodePos, m_followPathDestPos, 0.5f, 4)) {
CVector pointPoses[7]; m_nNumPathNodes = i + 1;
int16 pointsFound; break;
CPedPath::CalcPedRoute(0, GetPosition(), dest, pointPoses, &pointsFound, 7); }
for(int i = 0; i < pointsFound; i++) {
m_stPathNodeStates[i].x = pointPoses[i].x;
m_stPathNodeStates[i].y = pointPoses[i].y;
} }
m_nCurPathNode = 0; m_nCurPathNodeId = 0;
m_nPathNodes = pointsFound; if (m_pCurPathNode) {
if (m_nPathNodes < 1) for (int j = 0; j < m_nNumPathNodes; ++j) {
if (m_pathNodesToGo[j] == m_pCurPathNode) {
m_nCurPathNodeId = j;
break;
}
}
}
m_pCurPathNode = m_pathNodesToGo[m_nCurPathNodeId];
PedState oldLastState = m_nLastPedState;
m_nLastPedState = PED_NONE;
SetStoredState();
if (m_nLastPedState == PED_NONE)
m_nLastPedState = oldLastState;
m_nPedState = PED_FOLLOW_PATH;
m_nMoveState = m_followPathMoveState;
return true;
} else {
RestorePreviousState();
if (m_objective == OBJECTIVE_NONE) {
if (m_followPathMoveState == PEDMOVE_RUN)
SetObjective(OBJECTIVE_RUN_TO_AREA, m_followPathDestPos);
else
SetObjective(OBJECTIVE_GOTO_AREA_ON_FOOT, m_followPathDestPos);
}
SetPedState(PED_NONE);
return true;
}
}
}
// --MIAMI: Done
bool
CPed::SetFollowPath(CVector dest, float radius, eMoveState state, CEntity* walkAroundEnt, CEntity* targetEnt, int time)
{
if (m_nPedState == PED_FOLLOW_PATH) {
bool stopFollow = false;
if (walkAroundEnt && walkAroundEnt != m_followPathWalkAroundEnt || !walkAroundEnt && m_followPathWalkAroundEnt
|| targetEnt && targetEnt != m_followPathTargetEnt || !targetEnt && m_followPathTargetEnt) {
stopFollow = true;
} else if (targetEnt) {
if ((targetEnt->GetPosition() - m_followPathDestPos).MagnitudeSqr() > 1.f)
stopFollow = true;
} else if (!walkAroundEnt && !targetEnt) {
if ((dest - m_followPathDestPos).MagnitudeSqr() > 1.f)
stopFollow = true;
}
if (!stopFollow)
return false;
}
m_pathNodeTimer = CTimer::GetTimeInMilliseconds() + time;
m_followPathWalkAroundEnt = walkAroundEnt;
m_followPathTargetEnt = targetEnt;
m_distanceToCountSeekDone = 0.5f;
bool weHaveTargetPed = targetEnt && targetEnt->IsPed();
bool useDestVec = !weHaveTargetPed;
CVector targetPos;
if (useDestVec)
targetPos = dest;
else
targetPos = targetEnt->GetPosition();
m_followPathDestPos = targetPos;
if (targetEnt && m_nPedState == PED_SEEK_POS) {
m_followPathDestPos = m_vecSeekPos;
}
float newRadius = radius > 0.f ? radius : 20.f;
bool useGivenPedMove = true;
m_followPathAbortDist = newRadius;
if (state != PEDMOVE_RUN && state != PEDMOVE_WALK)
useGivenPedMove = false;
if (useGivenPedMove)
m_followPathMoveState = state;
else
m_followPathMoveState = PEDMOVE_WALK;
if (m_followPathWalkAroundEnt)
return SetFollowPathDynamic();
else
return SetFollowPathStatic();
}
// --MIAMI: Done
bool
CPed::SetFollowPathDynamic(void)
{
CVector colBoxMin = m_followPathWalkAroundEnt->GetColModel()->boundingBox.min + CVector(-0.35f, -0.35f, 0.f);
CVector colBoxMax = m_followPathWalkAroundEnt->GetColModel()->boundingBox.max + CVector(0.35f, 0.35f, 0.f);
CVector colCornerOffsets[4]; // BL, BR, TR, TL
colCornerOffsets[0] = CVector(colBoxMin.x, colBoxMin.y, 0.f);
colCornerOffsets[1] = CVector(colBoxMax.x, colBoxMin.y, 0.f);
colCornerOffsets[2] = CVector(colBoxMax.x, colBoxMax.y, 0.f);
colCornerOffsets[3] = CVector(colBoxMin.x, colBoxMax.y, 0.f);
if (m_followPathWalkAroundEnt->IsVehicle() && ((CVehicle*)m_followPathWalkAroundEnt)->IsUpsideDown()) {
CVector old0 = colCornerOffsets[0];
colCornerOffsets[0] = colCornerOffsets[1];
colCornerOffsets[1] = old0;
CVector old2 = colCornerOffsets[2];
colCornerOffsets[2] = colCornerOffsets[3];
colCornerOffsets[3] = old2;
}
CVector colCornerPos[4]; // global. again BL, BR, TR, TL
float dotProdCorrection[4];
CVector colBoxPlaneNormal[4];
for (int i=0; i<4; i++) {
colCornerPos[i] = m_followPathWalkAroundEnt->GetMatrix() * colCornerOffsets[i];
colCornerPos[i].z = GetPosition().z;
}
CVector prevColCorner = colCornerPos[3]; // top left
CVector *curCornerPos;
CVector fwdToNextCorner;
for (int i=0; i<4; i++) {
curCornerPos = &colCornerPos[i];
fwdToNextCorner = *curCornerPos - prevColCorner;
fwdToNextCorner.Normalise();
colBoxPlaneNormal[i] = CrossProduct(fwdToNextCorner, CVector(0.f, 0.f, 1.f));
dotProdCorrection[i] = -DotProduct(prevColCorner, colBoxPlaneNormal[i]); // yes, dp with global coord, as if in distance to plane calculation
prevColCorner = *curCornerPos;
}
bool weReGoingGreat = false;
CVector startVecCandidate = GetPosition();
CVector targetVecCandidate = m_followPathDestPos;
CVector dirToGo = targetVecCandidate - startVecCandidate;
dirToGo.Normalise();
CVector ourPos = startVecCandidate;
for (int i=0; i<4; i++) {
CVector curPlaneNormal = colBoxPlaneNormal[i];
float minusGlobalCornerPos = dotProdCorrection[i];
float startVecDistToPlane = DotProduct(curPlaneNormal, startVecCandidate) + minusGlobalCornerPos;
#define FRONT_OF_PLANE 1
#define ON_THE_PLANE 0
#define BEHIND_THE_PLANE -1
int8 startVecStatus;
int8 targetVecStatus;
if (startVecDistToPlane > 0.1f)
startVecStatus = FRONT_OF_PLANE;
else if (startVecDistToPlane < -0.1f)
startVecStatus = BEHIND_THE_PLANE;
else
startVecStatus = ON_THE_PLANE;
float targetVecDistToPlane = DotProduct(curPlaneNormal, targetVecCandidate) + minusGlobalCornerPos;
if (targetVecDistToPlane > 0.1f)
targetVecStatus = FRONT_OF_PLANE;
else if (targetVecDistToPlane < -0.1f)
targetVecStatus = BEHIND_THE_PLANE;
else
targetVecStatus = ON_THE_PLANE;
if (startVecStatus == BEHIND_THE_PLANE || targetVecStatus == BEHIND_THE_PLANE) {
if (startVecStatus == BEHIND_THE_PLANE && targetVecStatus == FRONT_OF_PLANE) {
targetVecCandidate = -(DotProduct(ourPos, curPlaneNormal) + minusGlobalCornerPos) / DotProduct(dirToGo, curPlaneNormal) * dirToGo + ourPos;
} else if (startVecStatus == FRONT_OF_PLANE && targetVecStatus == BEHIND_THE_PLANE) {
startVecCandidate = -(DotProduct(ourPos, curPlaneNormal) + minusGlobalCornerPos) / DotProduct(dirToGo, curPlaneNormal) * dirToGo + ourPos;
}
} else {
weReGoingGreat = true;
if (startVecStatus == ON_THE_PLANE)
startVecCandidate += (0.1f - startVecDistToPlane) * curPlaneNormal;
if (targetVecStatus == ON_THE_PLANE)
targetVecCandidate += (0.1f - targetVecDistToPlane) * curPlaneNormal;
}
#undef FRONT_OF_PLANE
#undef ON_THE_PLANE
#undef BEHIND_THE_PLANE
}
if (!weReGoingGreat) {
CVector avgOfColPoints = (colCornerPos[0] + colCornerPos[1] + colCornerPos[2] + colCornerPos[3]) / 4.f;
float radius = 0.0f;
// Find radius of col box of the entity we follow
for (int i=0; i<4; i++) {
float cornerDist = (colCornerPos[i] - avgOfColPoints).MagnitudeSqr();
if (cornerDist > radius)
radius = cornerDist;
}
CColSphere followedEntSphere;
followedEntSphere.Set(Sqrt(radius) * 1.1f, avgOfColPoints, 0, 0);
CVector distToDest = m_followPathDestPos - GetPosition();
distToDest.z = 0.f;
if (distToDest.Magnitude() == 0.0f)
return false; return false;
distToDest.Normalise();
// Entity we follow doesn't go toward destination anymore, abort the following.
if (!followedEntSphere.IntersectRay(GetPosition(), distToDest, startVecCandidate, targetVecCandidate)) {
m_pathNodeTimer = 0;
if (m_nPedState == PED_FOLLOW_PATH)
RestorePreviousState();
return false;
}
}
int lastPlaneBehindUs = -1;
int lastPlaneInFrontOfUs = -1;
CVector oldstartVecCandidate = startVecCandidate;
CVector oldDirToGo = targetVecCandidate - startVecCandidate;
oldDirToGo.Normalise();
// At least one plane should be between target and us.
for (int i=0; i<4; i++) {
CVector curPlaneNormal = colBoxPlaneNormal[i];
float minusGlobalCornerPos = dotProdCorrection[i];
float startVecDistToPlane = DotProduct(curPlaneNormal, startVecCandidate) + minusGlobalCornerPos;
float targetVecDistToPlane = DotProduct(curPlaneNormal, targetVecCandidate) + minusGlobalCornerPos;
if (startVecDistToPlane > 0.0f && targetVecDistToPlane < 0.0f) {
lastPlaneInFrontOfUs = i;
startVecCandidate = -(DotProduct(oldstartVecCandidate, curPlaneNormal) + minusGlobalCornerPos) / DotProduct(oldDirToGo, curPlaneNormal) * oldDirToGo + oldstartVecCandidate;
} else if (startVecDistToPlane < 0.0f && targetVecDistToPlane > 0.0f) {
lastPlaneBehindUs = i;
targetVecCandidate = -(DotProduct(oldstartVecCandidate, curPlaneNormal) + minusGlobalCornerPos) / DotProduct(oldDirToGo, curPlaneNormal) * oldDirToGo + oldstartVecCandidate;
}
}
CVector destsVariant1[5];
CVector destsVariant2[5];
// If not, followed entity diverged from route and we should abort the following.
if (lastPlaneBehindUs >= 0 && lastPlaneInFrontOfUs >= 0) {
int planeInFrontCircular = (lastPlaneInFrontOfUs + 4) % -4;
int planeInFrontCircularMinusOne = (lastPlaneInFrontOfUs + 3) % -4;
int planeInBehindCircular = (lastPlaneBehindUs + 4) % -4;
int planeInBehindCircularMinusOne = (lastPlaneBehindUs + 3) % -4;
destsVariant1[0] = GetPosition();
destsVariant1[1] = colCornerPos[planeInFrontCircularMinusOne];
int destsVar1LastNode = 2;
for(; planeInFrontCircularMinusOne != planeInBehindCircular; destsVar1LastNode++) {
planeInFrontCircularMinusOne = (planeInFrontCircularMinusOne + 3) % -4;
destsVariant1[destsVar1LastNode] = colCornerPos[planeInFrontCircularMinusOne];
}
destsVariant1[destsVar1LastNode] = m_followPathDestPos;
destsVariant2[0] = GetPosition();
destsVariant2[1] = colCornerPos[planeInFrontCircular];
int destsVar2LastNode = 2;
for (; planeInFrontCircular != planeInBehindCircularMinusOne; destsVar2LastNode++) {
planeInFrontCircular = (planeInFrontCircular + 5) % -4;
destsVariant2[destsVar2LastNode] = colCornerPos[planeInFrontCircular];
}
destsVariant2[destsVar2LastNode] = m_followPathDestPos;
CEntity *foundEnt1 = nil;
int dests1isOk = true;
int nodeToStopDestsVar1 = destsVar1LastNode + 1;
CVector avgOfColPoints2 = (colCornerPos[0] + colCornerPos[1] + colCornerPos[2] + colCornerPos[3]) / 4.f;
CVector prevDestVar1 = destsVariant1[0];
for (int i = 1; i < destsVar1LastNode + 1; i++) {
CVector *curDestVar1 = &destsVariant1[i];
CVector routeNormalHalf = *curDestVar1 - prevDestVar1;
routeNormalHalf.z = 0.f;
routeNormalHalf.Normalise();
routeNormalHalf *= 0.5f;
float oldX = -routeNormalHalf.x;
routeNormalHalf.z = 0.0f;
routeNormalHalf.x = routeNormalHalf.y;
routeNormalHalf.y = oldX;
if (DotProduct(*curDestVar1 - avgOfColPoints2, routeNormalHalf) < 0.0f)
routeNormalHalf *= -1.f;
CColPoint foundCol;
bool foundObstacle = CWorld::ProcessLineOfSight(prevDestVar1, *curDestVar1, foundCol, foundEnt1,
true, true, true, true, false, false, false, false);
if (!foundObstacle)
foundObstacle = CWorld::ProcessLineOfSight(prevDestVar1 + routeNormalHalf, *curDestVar1 + routeNormalHalf, foundCol, foundEnt1, true, true, true, true, false, false, false, false);
if (foundObstacle) {
if (foundEnt1 == m_followPathWalkAroundEnt || foundEnt1 == this || foundEnt1 == m_pSeekTarget) {
foundEnt1 = nil;
} else {
if (!foundEnt1->IsPed()) {
dests1isOk = false;
nodeToStopDestsVar1 = i;
break;
}
if (((CPed*)foundEnt1)->m_nPedState == PED_IDLE) {
dests1isOk = false;
nodeToStopDestsVar1 = i;
break;
}
if (DotProduct(*curDestVar1 - prevDestVar1, foundEnt1->GetForward()) < 0.f) {
dests1isOk = false;
nodeToStopDestsVar1 = i;
break;
}
if (((CPed*)foundEnt1)->m_pedInObjective == this) {
dests1isOk = false;
nodeToStopDestsVar1 = i;
break;
}
}
}
prevDestVar1 = *curDestVar1;
}
CEntity *foundEnt2 = nil;
int dests2isOk = true;
int nodeToStopDestsVar2 = destsVar2LastNode + 1;
CVector prevDestVar2 = destsVariant2[0];
for (int i = 1; i < destsVar2LastNode + 1; i++) {
CVector *curDestVar2 = &destsVariant2[i];
CVector routeNormalHalf = *curDestVar2 - prevDestVar2;
routeNormalHalf.z = 0.f;
routeNormalHalf.Normalise();
routeNormalHalf *= 0.5f;
float oldX = -routeNormalHalf.x;
routeNormalHalf.z = 0.0f;
routeNormalHalf.x = routeNormalHalf.y;
routeNormalHalf.y = oldX;
if (DotProduct(*curDestVar2 - avgOfColPoints2, routeNormalHalf) < 0.0f)
routeNormalHalf *= -1.f;
CColPoint foundCol;
bool foundObstacle = CWorld::ProcessLineOfSight(prevDestVar2, *curDestVar2, foundCol, foundEnt2,
true, true, true, true, false, false, false, false);
if (!foundObstacle)
foundObstacle = CWorld::ProcessLineOfSight(prevDestVar2 + routeNormalHalf, *curDestVar2 + routeNormalHalf, foundCol, foundEnt2, true, true, true, true, false, false, false, false);
if (foundObstacle) {
if (foundEnt2 == m_followPathWalkAroundEnt || foundEnt2 == this || foundEnt2 == m_pSeekTarget) {
foundEnt2 = 0;
} else {
if (!foundEnt2->IsPed()) {
dests2isOk = false;
nodeToStopDestsVar2 = i;
break;
}
if (((CPed*)foundEnt2)->m_nPedState == PED_IDLE) {
dests2isOk = false;
nodeToStopDestsVar2 = i;
break;
}
if (DotProduct(*curDestVar2 - prevDestVar2, foundEnt2->GetForward()) < 0.f) {
dests2isOk = false;
nodeToStopDestsVar2 = i;
break;
}
if (((CPed*)foundEnt2)->m_pedInObjective == this) {
dests2isOk = false;
nodeToStopDestsVar2 = i;
break;
}
}
}
prevDestVar2 = *curDestVar2;
}
float destTotalLengthVar1 = 0.0f;
for(int i=0; i < destsVar1LastNode; i++){
destTotalLengthVar1 += (destsVariant1[i + 1] - destsVariant1[i]).Magnitude();
}
float destTotalLengthVar2 = 0.0f;
for (int i = 0; i < destsVar2LastNode; i++) {
destTotalLengthVar2 += (destsVariant2[i + 1] - destsVariant2[i]).Magnitude();
}
int destVariantToUse;
if (dests1isOk && dests2isOk) {
if (destTotalLengthVar1 < destTotalLengthVar2)
destVariantToUse = 1;
else
destVariantToUse = 2;
} else if (dests1isOk) {
destVariantToUse = 1;
} else if (dests2isOk) {
destVariantToUse = 2;
} else if (nodeToStopDestsVar1 == 1 && nodeToStopDestsVar2 > 1) {
destVariantToUse = 2;
} else if (nodeToStopDestsVar1 > 1 && nodeToStopDestsVar2 == 1) {
destVariantToUse = 1;
} else if (foundEnt1 == foundEnt2) {
if (destTotalLengthVar1 < destTotalLengthVar2)
destVariantToUse = 1;
else
destVariantToUse = 2;
} else if (foundEnt1->GetColModel()->boundingSphere.radius >= foundEnt2->GetColModel()->boundingSphere.radius) {
destVariantToUse = 2;
} else {
destVariantToUse = 1;
}
if (destVariantToUse == 1) {
ClearFollowPath();
for (int i = 1; i < destsVar1LastNode; i++) {
CPathNode* nextNode = &m_pathNodeObjPool[m_nNumPathNodes];
nextNode->SetPosition(destsVariant1[i]);
m_pathNodesToGo[m_nNumPathNodes++] = nextNode;
}
} else if (destVariantToUse == 2) {
ClearFollowPath();
for (int i = 1; i < destsVar2LastNode; i++) {
CPathNode *nextNode = &m_pathNodeObjPool[m_nNumPathNodes];
nextNode->SetPosition(destsVariant2[i]);
m_pathNodesToGo[m_nNumPathNodes++] = nextNode;
}
}
if (m_nNumPathNodes != 0) {
PedState oldLastState = m_nLastPedState;
m_nLastPedState = PED_NONE;
SetStoredState(); SetStoredState();
if (m_nLastPedState == PED_NONE)
m_nLastPedState = oldLastState;
m_nPedState = PED_FOLLOW_PATH; m_nPedState = PED_FOLLOW_PATH;
SetMoveState(PEDMOVE_WALK); m_nMoveState = m_followPathMoveState;
return true; return true;
} else {
m_pathNodeTimer = 0;
if (m_nPedState == PED_FOLLOW_PATH)
RestorePreviousState();
return false;
}
} else {
m_pathNodeTimer = 0;
if (m_nPedState == PED_FOLLOW_PATH)
RestorePreviousState();
return false;
}
} }
void void
@ -18942,11 +19492,11 @@ CPed::RequestDelayedWeapon()
void void
CPed::ClearFollowPath() CPed::ClearFollowPath()
{ {
for (int i = 0; i < ARRAY_SIZE(m_pPathNodesStates); i++) { for (int i = 0; i < ARRAY_SIZE(m_pathNodesToGo); i++) {
m_pPathNodesStates[i] = nil; m_pathNodesToGo[i] = nil;
} }
m_nPathNodes = 0; m_nNumPathNodes = 0;
m_nCurPathNode = 0; m_nCurPathNodeId = 0;
} }
// --MIAMI: Done // --MIAMI: Done
@ -19303,7 +19853,7 @@ CPed::DriveVehicle(void)
(0.0f == bike->m_aWheelTimer[2] && 0.0f == bike->m_aWheelTimer[3])) { (0.0f == bike->m_aWheelTimer[2] && 0.0f == bike->m_aWheelTimer[3])) {
if (0.0f == bike->m_aWheelTimer[2] && 0.0f == bike->m_aWheelTimer[3] && if (0.0f == bike->m_aWheelTimer[2] && 0.0f == bike->m_aWheelTimer[3] &&
(bike->GetForward().y < 0.0f && (bike->m_aWheelTimer[0] != 0.0f || bike->m_aWheelTimer[1] != 0.0f))) { (bike->GetForward().z < 0.0f && (bike->m_aWheelTimer[0] != 0.0f || bike->m_aWheelTimer[1] != 0.0f))) {
stoppieAng = bike->pBikeHandling->fStoppieAng; stoppieAng = bike->pBikeHandling->fStoppieAng;
if (stoppieAng - bike->GetForward().z > 0.6f * stoppieAng) if (stoppieAng - bike->GetForward().z > 0.6f * stoppieAng)

View File

@ -10,11 +10,11 @@
#include "Weapon.h" #include "Weapon.h"
#include "WeaponInfo.h" #include "WeaponInfo.h"
#include "AnimationId.h" #include "AnimationId.h"
#include "PathFind.h"
#define FEET_OFFSET 1.04f #define FEET_OFFSET 1.04f
#define CHECK_NEARBY_THINGS_MAX_DIST 15.0f #define CHECK_NEARBY_THINGS_MAX_DIST 15.0f
struct CPathNode;
class CAccident; class CAccident;
class CObject; class CObject;
class CFire; class CFire;
@ -346,6 +346,9 @@ enum eMoveState {
PEDMOVE_NONE, PEDMOVE_NONE,
PEDMOVE_STILL, PEDMOVE_STILL,
PEDMOVE_WALK, PEDMOVE_WALK,
PEDMOVE_UNK,
PEDMOVE_RUN, PEDMOVE_RUN,
PEDMOVE_SPRINT, PEDMOVE_SPRINT,
}; };
@ -521,13 +524,20 @@ public:
int32 m_nPrevMoveState; int32 m_nPrevMoveState;
eWaitState m_nWaitState; eWaitState m_nWaitState;
uint32 m_nWaitTimer; uint32 m_nWaitTimer;
void *m_pPathNodesStates[8]; // unused, probably leftover from VC CPathNode* m_pathNodesToGo[8];
CVector2D m_stPathNodeStates[10]; int16 m_nNumPathNodes;
uint16 m_nPathNodes; int16 m_nCurPathNodeId;
int16 m_nCurPathNode; CEntity* m_followPathWalkAroundEnt;
int8 m_nPathDir; CEntity* m_followPathTargetEnt;
uint32 m_pathNodeTimer;
CPathNode m_pathNodeObjPool[8];
CPathNode* m_pCurPathNode;
char m_nPathDir;
CPathNode* m_pLastPathNode; CPathNode* m_pLastPathNode;
CPathNode* m_pNextPathNode; CPathNode* m_pNextPathNode;
CVector m_followPathDestPos;
float m_followPathAbortDist;
eMoveState m_followPathMoveState;
float m_fHealth; float m_fHealth;
float m_fArmour; float m_fArmour;
uint32 m_nExtendedRangeTimer; uint32 m_nExtendedRangeTimer;
@ -756,6 +766,7 @@ public:
void RemoveInCarAnims(void); void RemoveInCarAnims(void);
void CollideWithPed(CPed*); void CollideWithPed(CPed*);
void SetDirectionToWalkAroundObject(CEntity*); void SetDirectionToWalkAroundObject(CEntity*);
bool SetDirectionToWalkAroundVehicle(CVehicle*);
void RemoveWeaponAnims(int, float); void RemoveWeaponAnims(int, float);
void CreateDeadPedMoney(void); void CreateDeadPedMoney(void);
void CreateDeadPedWeaponPickups(void); void CreateDeadPedWeaponPickups(void);
@ -778,7 +789,7 @@ public:
bool FindBestCoordsFromNodes(CVector, CVector*); bool FindBestCoordsFromNodes(CVector, CVector*);
void Wait(void); void Wait(void);
void ProcessObjective(void); void ProcessObjective(void);
bool SeekFollowingPath(CVector*); CVector *SeekFollowingPath(void);
void Flee(void); void Flee(void);
void FollowPath(void); void FollowPath(void);
CVector GetFormationPosition(void); CVector GetFormationPosition(void);

View File

@ -4,47 +4,65 @@
#include "General.h" #include "General.h"
#include "Ped.h" #include "Ped.h"
// --MIAMI: Done
// Corresponds to ped sounds (from SOUND_PED_DEATH to SOUND_PED_TAXI_CALL) // Corresponds to ped sounds (from SOUND_PED_DEATH to SOUND_PED_TAXI_CALL)
PedAudioData CommentWaitTime[39] = { PedAudioData CommentWaitTime[56] = {
{ 500, 800, 500, 2 }, { 500, 800, 500, 2 },
{ 500, 800, 500, 2 }, { 500, 800, 500, 2 },
{ 500, 800, 500, 2 }, { 500, 800, 500, 2 },
{ 500, 800, 500, 2 }, { 500, 800, 500, 2 },
{ 100, 2, 100, 2 }, { 100, 2, 100, 2 },
{700, 500, 1000, 500}, { 500, 500, 2000, 1000 },
{700, 500, 1000, 500}, { 2000, 50, 2050, 1000 },
{5000, 2000, 15000, 3000}, { 5000, 2000, 7000, 3000 },
{5000, 2000, 15000, 3000}, { 5000, 2000, 7000, 3000 },
{5000, 2000, 15000, 3000}, { 300, 200, 500, 200 },
{ 3000, 1000, 4000, 1000 },
{ 6000, 6000, 6000, 6000 }, { 6000, 6000, 6000, 6000 },
{ 4000, 1000, 5000, 1000 },
{ 3000, 1000, 4000, 1000 },
{ 1000, 1000, 2000, 2000 }, { 1000, 1000, 2000, 2000 },
{ 1000, 500, 2000, 1500 }, { 1000, 500, 2000, 1500 },
{1000, 500, 2000, 1500}, { 1700, 1000, 3000, 1000 },
{ 800, 200, 1000, 500 }, { 800, 200, 1000, 500 },
{ 800, 200, 1000, 500 }, { 800, 200, 1000, 500 },
{ 800, 400, 2000, 1000 }, { 800, 400, 2000, 1000 },
{ 800, 400, 2000, 1000 }, { 800, 400, 2000, 1000 },
{400, 300, 2000, 1000}, { 2000, 2000, 4000, 4000 },
{2000, 1000, 2500, 1500}, { 2000, 2000, 4000, 1000 },
{ 4000, 1000, 5000, 1000 },
{ 800, 400, 1200, 500 },
{ 5000, 1000, 6000, 2000 },
{ 5000, 1000, 6000, 2000 },
{ 5000, 1000, 6000, 2000 },
{ 5000, 1000, 6000, 2000 },
{ 5000, 1000, 6000, 2000 },
{ 5000, 1000, 6000, 2000 },
{ 5000, 1000, 6000, 2000 },
{ 4000, 2000, 7000, 2000 },
{ 1000, 300, 2000, 1000 },
{ 1500, 1000, 2500, 1000 },
{ 200, 200, 200, 200 }, { 200, 200, 200, 200 },
{6000, 3000, 5000, 6000}, { 2000, 1000, 4000, 1000 },
{6000, 3000, 9000, 5000}, { 2000, 1000, 4000, 1000 },
{6000, 3000, 9000, 5000},
{6000, 3000, 9000, 5000},
{400, 300, 4000, 1000},
{400, 300, 4000, 1000},
{400, 300, 4000, 1000},
{ 1000, 500, 3000, 1000 }, { 1000, 500, 3000, 1000 },
{ 1000, 500, 1000, 1000 }, { 1000, 500, 1000, 1000 },
{ 3000, 2000, 5000, 1000 },
{ 3000, 2000, 5000, 1000 },
{ 3000, 2000, 3000, 2000 }, { 3000, 2000, 3000, 2000 },
{1000, 500, 3000, 6000}, { 2000, 1000, 3000, 1000 },
{ 2500, 1000, 5000, 5000 },
{ 2000, 1000, 3000, 2000 },
{ 4000, 1000, 5000, 1000 },
{ 1000, 500, 2000, 4000 }, { 1000, 500, 2000, 4000 },
{ 1000, 500, 2000, 5000 }, { 1000, 500, 2000, 5000 },
{ 2000, 500, 2500, 500 },
{ 1000, 500, 3000, 2000 }, { 1000, 500, 3000, 2000 },
{ 1600, 1000, 2000, 2000 }, { 1600, 1000, 2000, 2000 },
{3000, 2000, 5000, 3000}, { 2000, 1000, 4000, 2000 },
{1000, 1000, 1000, 1000}, { 1500, 1000, 2500, 1000 },
{ 1000, 1000, 5000, 5000 }, { 1000, 1000, 5000, 5000 },
{ 0, 0, 0, 0 }
}; };
// --MIAMI: Done // --MIAMI: Done
@ -54,7 +72,7 @@ CPed::ServiceTalkingWhenDead(void)
return m_queuedSound == SOUND_PED_DEATH; return m_queuedSound == SOUND_PED_DEATH;
} }
// --MIAMI: Done except ifdef // --MIAMI: Done
void void
CPed::ServiceTalking(void) CPed::ServiceTalking(void)
{ {
@ -84,7 +102,7 @@ CPed::ServiceTalking(void)
} }
} }
// --MIAMI: Done except ifdef // --MIAMI: Done
void void
CPed::Say(uint16 audio) CPed::Say(uint16 audio)
{ {