summaryrefslogtreecommitdiffstats
path: root/src/entities
diff options
context:
space:
mode:
authoraap <aap@papnet.eu>2019-05-17 14:08:18 +0200
committeraap <aap@papnet.eu>2019-05-17 14:08:18 +0200
commit5b8f20b08e6a40e2b07df73e90c5e84e259140fe (patch)
treed8c5977bb4fda8c2521fad3810e4436f1bdf2127 /src/entities
parentrenames and a fix (diff)
downloadre3-5b8f20b08e6a40e2b07df73e90c5e84e259140fe.tar
re3-5b8f20b08e6a40e2b07df73e90c5e84e259140fe.tar.gz
re3-5b8f20b08e6a40e2b07df73e90c5e84e259140fe.tar.bz2
re3-5b8f20b08e6a40e2b07df73e90c5e84e259140fe.tar.lz
re3-5b8f20b08e6a40e2b07df73e90c5e84e259140fe.tar.xz
re3-5b8f20b08e6a40e2b07df73e90c5e84e259140fe.tar.zst
re3-5b8f20b08e6a40e2b07df73e90c5e84e259140fe.zip
Diffstat (limited to 'src/entities')
-rw-r--r--src/entities/Object.h4
-rw-r--r--src/entities/Ped.h6
-rw-r--r--src/entities/Physical.cpp175
-rw-r--r--src/entities/Physical.h4
-rw-r--r--src/entities/Vehicle.h6
5 files changed, 193 insertions, 2 deletions
diff --git a/src/entities/Object.h b/src/entities/Object.h
index 6992b92d..5d648e07 100644
--- a/src/entities/Object.h
+++ b/src/entities/Object.h
@@ -8,6 +8,8 @@ enum {
TEMP_OBJECT = 3,
};
+class CVehicle;
+
class CObject : public CPhysical
{
public:
@@ -39,7 +41,7 @@ public:
int8 field_186;
int8 field_187;
CEntity *m_pCurSurface;
- CEntity *field_18C;
+ CVehicle *m_pCollidingVehicle;
int8 m_colour1, m_colour2;
static void *operator new(size_t);
diff --git a/src/entities/Ped.h b/src/entities/Ped.h
index fd71b616..fe448a94 100644
--- a/src/entities/Ped.h
+++ b/src/entities/Ped.h
@@ -24,7 +24,10 @@ public:
bool bInVehicle;
uint8 stuff4[23];
int32 m_nPedType;
- uint8 stuff5[528];
+
+ uint8 stuff5[28];
+ CVehicle *m_pCollidingVehicle;
+ uint8 stuff6[496];
bool IsPlayer(void) { return m_nPedType == 0 || m_nPedType== 1 || m_nPedType == 2 || m_nPedType == 3; }
};
@@ -32,4 +35,5 @@ static_assert(offsetof(CPed, m_nPedState) == 0x224, "CPed: error");
static_assert(offsetof(CPed, m_pCurSurface) == 0x2FC, "CPed: error");
static_assert(offsetof(CPed, m_pMyVehicle) == 0x310, "CPed: error");
static_assert(offsetof(CPed, m_nPedType) == 0x32C, "CPed: error");
+static_assert(offsetof(CPed, m_pCollidingVehicle) == 0x34C, "CPed: error");
static_assert(sizeof(CPed) == 0x540, "CPed: error");
diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp
index f235cb42..c528444e 100644
--- a/src/entities/Physical.cpp
+++ b/src/entities/Physical.cpp
@@ -787,6 +787,17 @@ CPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint)
}
+// ProcessCollision calls
+// CheckCollision
+// CheckCollision_SimpleCar
+// CheckCollision calls
+// ProcessCollisionSectorList
+// CheckCollision_SimpleCar
+// ProcessCollisionSectorList_SimpleCar
+// ProcessShift calls
+// ProcessCollisionSectorList
+// ProcessShiftSectorList
+
void
CPhysical::AddCollisionRecord(CEntity *ent)
{
@@ -839,6 +850,168 @@ CPhysical::GetHasCollidedWith(CEntity *ent)
return false;
}
+bool
+CPhysical::ProcessShiftSectorList(CPtrList *lists)
+{
+ int i, j;
+ CPtrList *list;
+ CPtrNode *node;
+ CPhysical *A, *B;
+ CObject *Bobj;
+ bool canshift;
+ CVector center;
+ float radius;
+
+ int numCollisions;
+ int mostColliding;
+ CColPoint colpoints[32];
+ CVector shift = { 0.0f, 0.0f, 0.0f };
+ bool doShift = false;
+ CEntity *boat = nil;
+
+ bool skipShift;
+
+ A = this;
+
+ A->GetBoundCentre(center);
+ radius = A->GetBoundRadius();
+ for(i = 0; i <= ENTITYLIST_PEDS_OVERLAP; i++){
+ list = &lists[i];
+ for(node = list->first; node; node = node->next){
+ B = (CPhysical*)node->item;
+ Bobj = (CObject*)B;
+ skipShift = false;
+
+ if(B->IsBuilding() ||
+ B->IsObject() && B->bInfiniteMass)
+ canshift = true;
+ else
+ canshift = A->IsPed() &&
+ B->IsObject() && B->bInfiniteMass && !Bobj->bHasBeenDamaged;
+ if(B == A ||
+ B->m_scanCode == CWorld::GetCurrentScanCode() ||
+ !B->bUsesCollision ||
+ (A->bHasHitWall && !canshift) ||
+ !B->GetIsTouching(center, radius))
+ continue;
+
+ // This could perhaps be done a bit nicer
+
+ if(B->IsBuilding())
+ skipShift = false;
+ else if(IsTrafficLight(A->GetModelIndex()) &&
+ (B->IsVehicle() || B->IsPed()) &&
+ A->GetUp().z < 0.66f)
+ skipShift = true;
+ else if((A->IsVehicle() || A->IsPed()) &&
+ B->GetUp().z < 0.66f &&
+ IsTrafficLight(B->GetModelIndex()))
+ skipShift = true;
+ else if(A->IsObject() && B->IsVehicle()){
+ CObject *Aobj = (CObject*)A;
+ if(Aobj->ObjectCreatedBy != TEMP_OBJECT &&
+ !Aobj->bHasBeenDamaged &&
+ Aobj->bIsStatic){
+ if(Aobj->m_pCollidingVehicle == B)
+ Aobj->m_pCollidingVehicle = nil;
+ }else if(Aobj->m_pCollidingVehicle != B){
+ CMatrix inv;
+ CVector size = CModelInfo::GetModelInfo(A->GetModelIndex())->GetColModel()->boundingBox.GetSize();
+ size = A->GetMatrix() * size;
+ if(size.z < B->GetPosition().z ||
+ (Invert(B->GetMatrix(), inv) * size).z < 0.0f){
+ skipShift = true;
+ Aobj->m_pCollidingVehicle = (CVehicle*)B;
+ }
+ }
+ }else if(B->IsObject() && A->IsVehicle()){
+ CObject *Bobj = (CObject*)B;
+ if(Bobj->ObjectCreatedBy != TEMP_OBJECT &&
+ !Bobj->bHasBeenDamaged &&
+ Bobj->bIsStatic){
+ if(Bobj->m_pCollidingVehicle == A)
+ Bobj->m_pCollidingVehicle = nil;
+ }else if(Bobj->m_pCollidingVehicle != A){
+ CMatrix inv;
+ CVector size = CModelInfo::GetModelInfo(B->GetModelIndex())->GetColModel()->boundingBox.GetSize();
+ size = B->GetMatrix() * size;
+ if(size.z < A->GetPosition().z ||
+ (Invert(A->GetMatrix(), inv) * size).z < 0.0f){
+ skipShift = true;
+ Bobj->m_pCollidingVehicle = (CVehicle*)A;
+ }
+ }
+ }else if(IsBodyPart(A->GetModelIndex()) && B->IsPed())
+ skipShift = true;
+ else if(A->IsPed() && IsBodyPart(B->GetModelIndex()))
+ skipShift = true;
+ else if(A->IsPed() && ((CPed*)A)->m_pCollidingVehicle == B ||
+ B->IsPed() && ((CPed*)B)->m_pCollidingVehicle == A ||
+ A->GetModelIndex() == MI_RCBANDIT && B->IsVehicle() ||
+ B->GetModelIndex() == MI_RCBANDIT && (A->IsPed() || A->IsVehicle()))
+ skipShift = true;
+
+ if(skipShift)
+ continue;
+
+ B->m_scanCode = CWorld::GetCurrentScanCode();
+ numCollisions = A->ProcessEntityCollision(B, colpoints);
+ if(numCollisions <= 0)
+ continue;
+
+ mostColliding = 0;
+ for(j = 1; j < numCollisions; j++)
+ if(colpoints[j].depth > colpoints[mostColliding].depth)
+ mostColliding = j;
+
+ if(CWorld::bSecondShift)
+ for(j = 0; j < numCollisions; j++)
+ shift += colpoints[j].normal * colpoints[j].depth * 1.5f/numCollisions;
+ else
+ for(j = 0; j < numCollisions; j++)
+ shift += colpoints[j].normal * colpoints[j].depth * 1.2f/numCollisions;
+
+ if(A->IsVehicle() && B->IsVehicle()){
+ CVector dir = A->GetPosition() - B->GetPosition();
+ dir.Normalise();
+ if(dir.z < 0.0f && dir.z < A->GetForward().z && dir.z < A->GetRight().z)
+ dir.z = min(0.0f, min(A->GetForward().z, A->GetRight().z));
+ shift += dir * colpoints[mostColliding].depth * 0.5f;
+ }else if(A->IsPed() && B->IsVehicle() && ((CVehicle*)B)->IsBoat()){
+ CVector dir = colpoints[mostColliding].normal;
+ float f = min(fabs(dir.z), 0.9f);
+ dir.z = 0.0f;
+ dir.Normalise();
+ shift += dir * colpoints[mostColliding].depth / (1.0f - f);
+ boat = B;
+ }else if(B->IsPed() && A->IsVehicle() && ((CVehicle*)A)->IsBoat()){
+ CVector dir = colpoints[mostColliding].normal * -1.0f;
+ float f = min(fabs(dir.z), 0.9f);
+ dir.z = 0.0f;
+ dir.Normalise();
+ B->GetPosition() += dir * colpoints[mostColliding].depth / (1.0f - f);
+ // BUG? how can that ever happen? A is a Ped
+ if(B->IsVehicle())
+ B->ProcessEntityCollision(A, colpoints);
+ }else{
+ if(CWorld::bSecondShift)
+ shift += colpoints[mostColliding].normal * colpoints[mostColliding].depth * 0.4f;
+ else
+ shift += colpoints[mostColliding].normal * colpoints[mostColliding].depth * 0.2f;
+ }
+
+ doShift = true;
+ }
+ }
+
+ if(!doShift)
+ return false;
+ GetPosition() += shift;
+ if(boat)
+ ProcessEntityCollision(boat, colpoints);
+ return true;
+}
+
void
CPhysical::ProcessControl(void)
{
@@ -897,6 +1070,8 @@ STARTPATCHES
InjectHook(0x4970C0, &CPhysical::AddCollisionRecord_Treadable, PATCH_JUMP);
InjectHook(0x497240, &CPhysical::GetHasCollidedWith, PATCH_JUMP);
+ InjectHook(0x49DA10, &CPhysical::ProcessShiftSectorList, PATCH_JUMP);
+
#define F3 float, float, float
InjectHook(0x495B10, &CPhysical::ApplyMoveSpeed, PATCH_JUMP);
InjectHook(0x497280, &CPhysical::ApplyTurnSpeed, PATCH_JUMP);
diff --git a/src/entities/Physical.h b/src/entities/Physical.h
index 681ab5c8..9867c33c 100644
--- a/src/entities/Physical.h
+++ b/src/entities/Physical.h
@@ -77,6 +77,8 @@ public:
CRect GetBoundRect(void);
void ProcessControl(void);
+ virtual int32 ProcessEntityCollision(CEntity *ent, CColPoint *point);
+
void RemoveAndAdd(void);
void AddToMovingList(void);
void RemoveFromMovingList(void);
@@ -128,6 +130,8 @@ public:
void AddCollisionRecord_Treadable(CEntity *ent);
bool GetHasCollidedWith(CEntity *ent);
+ bool ProcessShiftSectorList(CPtrList *ptrlists);
+
// to make patching virtual functions possible
void Add_(void) { CPhysical::Add(); }
void Remove_(void) { CPhysical::Remove(); }
diff --git a/src/entities/Vehicle.h b/src/entities/Vehicle.h
index 598b4a57..1a43e075 100644
--- a/src/entities/Vehicle.h
+++ b/src/entities/Vehicle.h
@@ -16,6 +16,12 @@ public:
CEntity *m_pCurSurface;
uint8 stuff3[160];
int32 m_vehType;
+
+ bool IsCar(void) { return m_vehType == VEHICLE_TYPE_CAR; }
+ bool IsBoat(void) { return m_vehType == VEHICLE_TYPE_BOAT; }
+ bool IsTrain(void) { return m_vehType == VEHICLE_TYPE_TRAIN; }
+ bool IsHeli(void) { return m_vehType == VEHICLE_TYPE_HELI; }
+ bool IsPlane(void) { return m_vehType == VEHICLE_TYPE_PLANE; }
};
static_assert(sizeof(CVehicle) == 0x288, "CVehicle: error");
static_assert(offsetof(CVehicle, m_pCurSurface) == 0x1E0, "CVehicle: error");