summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/control/Phones.cpp37
-rw-r--r--src/control/Phones.h28
-rw-r--r--src/core/World.cpp78
-rw-r--r--src/core/World.h4
-rw-r--r--src/entities/Physical.cpp2
-rw-r--r--src/peds/Ped.cpp40
-rw-r--r--src/peds/Ped.h11
7 files changed, 191 insertions, 9 deletions
diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp
index fa4f83e5..1d3a9777 100644
--- a/src/control/Phones.cpp
+++ b/src/control/Phones.cpp
@@ -2,5 +2,42 @@
#include "patcher.h"
#include "Phones.h"
+CPhoneInfo &gPhoneInfo = * (CPhoneInfo*) * (uintptr*)0x732A20;
+
+int
+CPhoneInfo::FindNearestFreePhone(CVector *pos)
+{
+ int nearestPhoneId = -1;
+ float nearestPhoneDist = 60.0f;
+
+ for (int phoneId = 0; phoneId < m_nMax; phoneId++) {
+
+ if (gPhoneInfo.m_aPhones[phoneId].m_nState == 0) {
+ float phoneDist = (m_aPhones[phoneId].m_vecPos - *pos).Magnitude2D();
+
+ if (phoneDist < nearestPhoneDist) {
+ nearestPhoneDist = phoneDist;
+ nearestPhoneId = phoneId;
+ }
+ }
+ }
+ return nearestPhoneId;
+}
+
+bool
+CPhoneInfo::PhoneAtThisPosition(CVector pos)
+{
+ for (int phoneId = 0; phoneId < m_nMax; phoneId++) {
+ if (pos.x == m_aPhones[phoneId].m_vecPos.x && pos.y == m_aPhones[phoneId].m_vecPos.y)
+ return true;
+ }
+ return false;
+}
+
+STARTPATCHES
+ InjectHook(0x42F720, &CPhoneInfo::FindNearestFreePhone, PATCH_JUMP);
+ InjectHook(0x42FD50, &CPhoneInfo::PhoneAtThisPosition, PATCH_JUMP);
+ENDPATCHES
+
WRAPPER void PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x42F570); }
WRAPPER void PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x42F470); }
diff --git a/src/control/Phones.h b/src/control/Phones.h
index a29043ed..7ac34c3a 100644
--- a/src/control/Phones.h
+++ b/src/control/Phones.h
@@ -1,6 +1,34 @@
#pragma once
+#include "Physical.h"
#include "AnimBlendAssociation.h"
+struct CPhone
+{
+ CVector m_vecPos;
+ uint16 *m_apMessages[6];
+ int32 field_24;
+ CEntity *m_pEntity;
+ int32 m_nState;
+ uint8 field_30;
+};
+
+static_assert(sizeof(CPhone) == 0x34, "CPhone: error");
+
+class CPhoneInfo {
+public:
+ int32 m_nMax;
+ int32 m_nNum;
+ CPhone m_aPhones[50];
+
+ CPhoneInfo() { }
+ ~CPhoneInfo() { }
+
+ int FindNearestFreePhone(CVector*);
+ bool PhoneAtThisPosition(CVector);
+};
+
+extern CPhoneInfo &gPhoneInfo;
+
void PhonePutDownCB(CAnimBlendAssociation *assoc, void *arg);
void PhonePickUpCB(CAnimBlendAssociation *assoc, void *arg); \ No newline at end of file
diff --git a/src/core/World.cpp b/src/core/World.cpp
index 538e15c5..a31f87a7 100644
--- a/src/core/World.cpp
+++ b/src/core/World.cpp
@@ -564,6 +564,82 @@ CWorld::GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bo
return true;
}
+void
+CWorld::FindObjectsInRangeSectorList(CPtrList &list, CVector &centre, float distance, bool ignoreZ, short *nextObject, short lastObject, CEntity **objects)
+{
+ float distSqr = distance * distance;
+ float objDistSqr;
+
+ for (CPtrNode *node = list.first; node; node = node->next) {
+ CEntity *object = (CEntity*)node->item;
+ if (object->m_scanCode != CWorld::GetCurrentScanCode()) {
+ object->m_scanCode = CWorld::GetCurrentScanCode();
+
+ CVector diff = centre - object->GetPosition();
+ if (ignoreZ)
+ objDistSqr = diff.MagnitudeSqr2D();
+ else
+ objDistSqr = diff.MagnitudeSqr();
+
+ if (objDistSqr < distSqr && *nextObject < lastObject) {
+ if (objects) {
+ objects[*nextObject] = object;
+ }
+ (*nextObject)++;
+ }
+ }
+ }
+}
+
+void
+CWorld::FindObjectsInRange(CVector &centre, float distance, bool ignoreZ, short *nextObject, short lastObject, CEntity **objects, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies)
+{
+ int minX = GetSectorIndexX(centre.x - distance);
+ if (minX <= 0)
+ minX = 0;
+
+ int minY = GetSectorIndexY(centre.y - distance);
+ if (minY <= 0)
+ minY = 0;
+
+ int maxX = GetSectorIndexX(centre.x + distance);
+ if (maxX >= 100)
+ maxX = 100;
+
+ int maxY = GetSectorIndexY(centre.y + distance);
+ if (maxY >= 100)
+ maxY = 100;
+
+ AdvanceCurrentScanCode();
+
+ *nextObject = 0;
+ for(int curY = minY; curY <= maxY; curY++) {
+ for(int curX = minX; curX <= maxX; curX++) {
+ CSector *sector = GetSector(curX, curY);
+ if (checkBuildings) {
+ CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_BUILDINGS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ }
+ if (checkVehicles) {
+ CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_VEHICLES_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ }
+ if (checkPeds) {
+ CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_PEDS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ }
+ if (checkObjects) {
+ CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_OBJECTS_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ }
+ if (checkDummies) {
+ CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ CWorld::FindObjectsInRangeSectorList(sector->m_lists[ENTITYLIST_DUMMIES_OVERLAP], centre, distance, ignoreZ, nextObject, lastObject, objects);
+ }
+ }
+ }
+}
+
float
CWorld::FindGroundZForCoord(float x, float y)
{
@@ -712,6 +788,8 @@ STARTPATCHES
InjectHook(0x4B2000, CWorld::GetIsLineOfSightSectorClear, PATCH_JUMP);
InjectHook(0x4B2160, CWorld::GetIsLineOfSightSectorListClear, PATCH_JUMP);
+ InjectHook(0x4B2200, CWorld::FindObjectsInRange, PATCH_JUMP);
+ InjectHook(0x4B2540, CWorld::FindObjectsInRangeSectorList, PATCH_JUMP);
InjectHook(0x4B3A80, CWorld::FindGroundZForCoord, PATCH_JUMP);
InjectHook(0x4B3AE0, CWorld::FindGroundZFor3DCoord, PATCH_JUMP);
InjectHook(0x4B3B50, CWorld::FindRoofZFor3DCoord, PATCH_JUMP);
diff --git a/src/core/World.h b/src/core/World.h
index 3b7090da..d6063d70 100644
--- a/src/core/World.h
+++ b/src/core/World.h
@@ -93,7 +93,9 @@ public:
static bool GetIsLineOfSightClear(const CVector &point1, const CVector &point2, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
static bool GetIsLineOfSightSectorClear(CSector &sector, const CColLine &line, bool checkBuildings, bool checkVehicles, bool checkPeds, bool checkObjects, bool checkDummies, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
static bool GetIsLineOfSightSectorListClear(CPtrList &list, const CColLine &line, bool ignoreSeeThrough, bool ignoreSomeObjects = false);
-
+
+ static void FindObjectsInRangeSectorList(CPtrList&, CVector&, float, bool, short*, short, CEntity**);
+ static void FindObjectsInRange(CVector&, float, bool, short*, short, CEntity**, bool, bool, bool, bool, bool);
static float FindGroundZForCoord(float x, float y);
static float FindGroundZFor3DCoord(float x, float y, float z, bool *found);
static float FindRoofZFor3DCoord(float x, float y, float z, bool *found);
diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp
index b2512ec2..c9e0da90 100644
--- a/src/entities/Physical.cpp
+++ b/src/entities/Physical.cpp
@@ -33,7 +33,7 @@ CPhysical::CPhysical(void)
m_nCollisionRecords = 0;
for(i = 0; i < 6; i++)
- m_aCollisionRecords[0] = nil;
+ m_aCollisionRecords[i] = nil;
field_EF = false;
diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp
index 692fc4f2..cce5d6a9 100644
--- a/src/peds/Ped.cpp
+++ b/src/peds/Ped.cpp
@@ -23,6 +23,7 @@
#include "Lights.h"
#include "PointLights.h"
#include "Pad.h"
+#include "Phones.h"
WRAPPER void CPed::KillPedWithCar(CVehicle *veh, float impulse) { EAXJMP(0x4EC430); }
WRAPPER void CPed::Say(uint16 audio) { EAXJMP(0x4E5A10); }
@@ -42,6 +43,7 @@ WRAPPER void CPed::SetFollowRoute(int16, int16) { EAXJMP(0x4DD690); }
WRAPPER void CPed::SetDuck(uint32) { EAXJMP(0x4E4920); }
WRAPPER void CPed::RegisterThreatWithGangPeds(CEntity*) { EAXJMP(0x4E3870); }
WRAPPER void CPed::MakeChangesForNewWeapon(int8) { EAXJMP(0x4F2560); }
+WRAPPER bool CPed::Seek(void) { EAXJMP(0x4D1640); }
bool &CPed::bNastyLimbsCheat = *(bool*)0x95CD44;
bool &CPed::bPedCheat2 = *(bool*)0x95CD5A;
@@ -1389,7 +1391,7 @@ CPed::PedSetDraggedOutCarCB(CAnimBlendAssociation *dragAssoc, void *arg)
if (ped->m_nPedState != PED_ARRESTED) {
ped->m_nLastPedState = PED_NONE;
if (dragAssoc)
- dragAssoc->blendDelta = -1000.0;
+ dragAssoc->blendDelta = -1000.0f;
}
ped->RestartNonPartialAnims();
ped->m_pVehicleAnim = nil;
@@ -2055,6 +2057,7 @@ CPed::SetupLighting(void)
{
ActivateDirectional();
SetAmbientColoursForPedsCarsAndObjects();
+
if (bRenderScorched) {
WorldReplaceNormalLightsWithScorched(Scene.world, 0.1f);
} else {
@@ -2696,7 +2699,7 @@ CPed::QuitEnteringCar(void)
if (veh->m_nNumGettingIn != 0)
veh->m_nNumGettingIn--;
- veh->m_nGettingInFlags = GetVehDoorFlag(m_vehEnterType);
+ veh->m_nGettingInFlags = ~GetVehDoorFlag(m_vehEnterType);
}
bUsesCollision = true;
@@ -2869,6 +2872,38 @@ CPed::Chat(void)
}
}
+void
+CPed::CheckAroundForPossibleCollisions(void)
+{
+ CVector ourCentre, objCentre;
+ CEntity *objects[8];
+ int16 maxObject;
+
+ if (CTimer::GetTimeInMilliseconds() <= m_nPedStateTimer)
+ return;
+
+ GetBoundCentre(ourCentre);
+
+ CWorld::FindObjectsInRange(ourCentre, 10.0f, true, &maxObject, 6, objects, false, true, false, true, false);
+ for (int i = 0; i < maxObject; i++) {
+ CEntity *object = objects[i];
+ if (field_31C) {
+ if (gPhoneInfo.PhoneAtThisPosition(object->GetPosition()))
+ break;
+ }
+ object->GetBoundCentre(objCentre);
+ float radius = object->GetBoundRadius();
+ if (radius > 4.5f || radius < 1.0f)
+ radius = 1.0f;
+
+ // According to code, developers gave up calculating Z diff. later.
+ float diff = CVector(ourCentre - objCentre).MagnitudeSqr2D();
+
+ if (sq(radius + 1.0f) > diff)
+ m_fRotationDest += DEGTORAD(22.5f);
+ }
+}
+
WRAPPER void CPed::PedGetupCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE810); }
WRAPPER void CPed::PedStaggerCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4CE8D0); }
WRAPPER void CPed::PedEvadeCB(CAnimBlendAssociation *assoc, void *arg) { EAXJMP(0x4D36E0); }
@@ -2961,4 +2996,5 @@ STARTPATCHES
InjectHook(0x4D3C80, &CPed::ClearChat, PATCH_JUMP);
InjectHook(0x4D1390, &CPed::TurnBody, PATCH_JUMP);
InjectHook(0x4D3AC0, &CPed::Chat, PATCH_JUMP);
+ InjectHook(0x4D0490, &CPed::CheckAroundForPossibleCollisions, PATCH_JUMP);
ENDPATCHES
diff --git a/src/peds/Ped.h b/src/peds/Ped.h
index 2390d1d4..4909a583 100644
--- a/src/peds/Ped.h
+++ b/src/peds/Ped.h
@@ -13,7 +13,7 @@
struct CPathNode;
-enum eWaitState : uint32 {
+enum eWaitState {
WAITSTATE_FALSE,
WAITSTATE_TRAFFIC_LIGHTS,
WAITSTATE_CROSS_ROAD,
@@ -292,10 +292,10 @@ public:
int32 m_nPrevActionState;
eWaitState m_nWaitState;
uint32 m_nWaitTimer;
- void *m_pPathNodesStates[8];
+ void *m_pPathNodesStates[8]; // seems unused
CVector2D m_stPathNodeStates[10];
uint16 m_nPathNodes;
- uint8 m_nCurPathNode;
+ int16 m_nCurPathNode;
int8 m_nPathState;
private:
int8 _pad2B5[3];
@@ -324,7 +324,7 @@ public:
CVehicle *m_pMyVehicle;
bool bInVehicle;
uint8 pad_315[3];
- uint32 field_318;
+ float field_318;
uint8 field_31C;
uint8 field_31D;
int16 m_phoneId;
@@ -457,7 +457,8 @@ public:
bool TurnBody(void);
void Chat(void);
void MakeChangesForNewWeapon(int8);
-
+ void CheckAroundForPossibleCollisions(void);
+ bool Seek(void);
// Static methods
static void GetLocalPositionToOpenCarDoor(CVector *output, CVehicle *veh, uint32 enterType, float offset);