CPhysical

This commit is contained in:
aap 2020-05-22 14:27:16 +02:00
parent 380f7bc417
commit a53ca58e56
18 changed files with 558 additions and 294 deletions

2
librw

@ -1 +1 @@
Subproject commit 3971dda001cba9c7dc67e86bc0b54a2c7568578f Subproject commit 661feeabf4a4f0a8b0bee23b53ba557a14352d00

View File

@ -50,6 +50,7 @@ public:
int32 m_nExplosionsSinceLastReward; int32 m_nExplosionsSinceLastReward;
int32 field_268; int32 field_268;
int32 field_272; int32 field_272;
int32 m_nHavocCaused; // TODO: check offset
bool m_bInfiniteSprint; bool m_bInfiniteSprint;
bool m_bFastReload; bool m_bFastReload;
bool m_bFireproof; bool m_bFireproof;

View File

@ -57,6 +57,7 @@ int32 CStats::mmRain;
int32 CStats::CarsCrushed; int32 CStats::CarsCrushed;
int32 CStats::FastestTimes[CStats::TOTAL_FASTEST_TIMES]; int32 CStats::FastestTimes[CStats::TOTAL_FASTEST_TIMES];
int32 CStats::HighestScores[CStats::TOTAL_HIGHEST_SCORES]; int32 CStats::HighestScores[CStats::TOTAL_HIGHEST_SCORES];
int32 CStats::PropertyDestroyed;
int32 CStats::Sprayings; int32 CStats::Sprayings;
float CStats::AutoPaintingBudget; float CStats::AutoPaintingBudget;

View File

@ -62,6 +62,7 @@ public:
static int32 CarsCrushed; static int32 CarsCrushed;
static int32 FastestTimes[TOTAL_FASTEST_TIMES]; static int32 FastestTimes[TOTAL_FASTEST_TIMES];
static int32 HighestScores[TOTAL_HIGHEST_SCORES]; static int32 HighestScores[TOTAL_HIGHEST_SCORES];
static int32 PropertyDestroyed;
static int32 Sprayings; static int32 Sprayings;
static float AutoPaintingBudget; static float AutoPaintingBudget;
static int32 NoMoreHurricanes; static int32 NoMoreHurricanes;

View File

@ -56,39 +56,41 @@ int
CSurfaceTable::GetAdhesionGroup(uint8 surfaceType) CSurfaceTable::GetAdhesionGroup(uint8 surfaceType)
{ {
switch(surfaceType){ switch(surfaceType){
case SURFACE_0: return ADHESIVE_ROAD; case SURFACE_DEFAULT: return ADHESIVE_ROAD;
case SURFACE_1: return ADHESIVE_ROAD; case SURFACE_TARMAC: return ADHESIVE_ROAD;
case SURFACE_2: return ADHESIVE_LOOSE; case SURFACE_GRASS: return ADHESIVE_LOOSE;
case SURFACE_3: return ADHESIVE_LOOSE; case SURFACE_DIRT: return ADHESIVE_LOOSE;
case SURFACE_4: return ADHESIVE_HARD; case SURFACE_DIRTTRACK: return ADHESIVE_HARD;
case SURFACE_5: return ADHESIVE_ROAD; case SURFACE_PAVEMENT: return ADHESIVE_ROAD;
case SURFACE_6: return ADHESIVE_HARD; case SURFACE_METAL6: return ADHESIVE_HARD;
case SURFACE_7: return ADHESIVE_HARD; case SURFACE_GLASS: return ADHESIVE_HARD;
case SURFACE_8: return ADHESIVE_HARD; case SURFACE_SCAFFOLD: return ADHESIVE_HARD;
case SURFACE_9: return ADHESIVE_HARD; case SURFACE_METAL_DOOR: return ADHESIVE_HARD;
case SURFACE_10: return ADHESIVE_HARD; case SURFACE_BILLBOARD: return ADHESIVE_HARD;
case SURFACE_11: return ADHESIVE_HARD; case SURFACE_STEEL: return ADHESIVE_HARD;
case SURFACE_12: return ADHESIVE_HARD; case SURFACE_METAL_POLE: return ADHESIVE_HARD;
case SURFACE_13: return ADHESIVE_HARD; case SURFACE_STREET_LIGHT: return ADHESIVE_HARD;
case SURFACE_14: return ADHESIVE_HARD; case SURFACE_METAL14: return ADHESIVE_HARD;
case SURFACE_15: return ADHESIVE_HARD; case SURFACE_METAL15: return ADHESIVE_HARD;
case SURFACE_16: return ADHESIVE_HARD; case SURFACE_METAL_FENCE: return ADHESIVE_HARD;
case SURFACE_17: return ADHESIVE_RUBBER; case SURFACE_FLESH: return ADHESIVE_RUBBER;
case SURFACE_18: return ADHESIVE_LOOSE; case SURFACE_SAND: return ADHESIVE_SAND;
case SURFACE_19: return ADHESIVE_WET; case SURFACE_PUDDLE: return ADHESIVE_WET;
case SURFACE_20: return ADHESIVE_ROAD; case SURFACE_WOOD: return ADHESIVE_ROAD;
case SURFACE_21: return ADHESIVE_ROAD; case SURFACE_WOOD_BOX: return ADHESIVE_ROAD;
case SURFACE_22: return ADHESIVE_ROAD; case SURFACE_WOOD_PLANK: return ADHESIVE_ROAD;
case SURFACE_23: return ADHESIVE_RUBBER; case SURFACE_TIRE: return ADHESIVE_RUBBER;
case SURFACE_24: return ADHESIVE_HARD; case SURFACE_HARD24: return ADHESIVE_HARD;
case SURFACE_25: return ADHESIVE_LOOSE; case SURFACE_HEDGE: return ADHESIVE_LOOSE;
case SURFACE_26: return ADHESIVE_LOOSE; case SURFACE_STONE: return ADHESIVE_LOOSE;
case SURFACE_27: return ADHESIVE_HARD; case SURFACE_METAL27: return ADHESIVE_HARD;
case SURFACE_28: return ADHESIVE_HARD; case SURFACE_METAL28: return ADHESIVE_HARD;
case SURFACE_29: return ADHESIVE_RUBBER; case SURFACE_RUBBER29: return ADHESIVE_RUBBER;
case SURFACE_30: return ADHESIVE_LOOSE; case SURFACE_LOOSE30: return ADHESIVE_LOOSE;
case SURFACE_31: return ADHESIVE_HARD; case SURFACE_BOLLARD: return ADHESIVE_HARD;
case SURFACE_32: return ADHESIVE_HARD; case SURFACE_GATE: return ADHESIVE_HARD;
case SURFACE_SAND33: return ADHESIVE_SAND;
case SURFACE_ROAD34: return ADHESIVE_ROAD;
default: return ADHESIVE_ROAD; default: return ADHESIVE_ROAD;
} }
} }
@ -97,40 +99,45 @@ float
CSurfaceTable::GetWetMultiplier(uint8 surfaceType) CSurfaceTable::GetWetMultiplier(uint8 surfaceType)
{ {
switch(surfaceType){ switch(surfaceType){
case SURFACE_0: case SURFACE_DEFAULT:
case SURFACE_1: case SURFACE_TARMAC:
case SURFACE_4: case SURFACE_DIRTTRACK:
case SURFACE_5: case SURFACE_PAVEMENT:
case SURFACE_8: case SURFACE_SCAFFOLD:
case SURFACE_20: case SURFACE_WOOD:
case SURFACE_21: case SURFACE_WOOD_BOX:
case SURFACE_22: case SURFACE_WOOD_PLANK:
case SURFACE_25: case SURFACE_HEDGE:
case SURFACE_30: case SURFACE_LOOSE30:
case SURFACE_31: case SURFACE_BOLLARD:
case SURFACE_ROAD34:
return 1.0f - CWeather::WetRoads*0.25f; return 1.0f - CWeather::WetRoads*0.25f;
case SURFACE_2: case SURFACE_GRASS:
case SURFACE_6: case SURFACE_METAL6:
case SURFACE_7: case SURFACE_GLASS:
case SURFACE_9: case SURFACE_METAL_DOOR:
case SURFACE_10: case SURFACE_BILLBOARD:
case SURFACE_11: case SURFACE_STEEL:
case SURFACE_12: case SURFACE_METAL_POLE:
case SURFACE_13: case SURFACE_STREET_LIGHT:
case SURFACE_14: case SURFACE_METAL14:
case SURFACE_15: case SURFACE_METAL15:
case SURFACE_16: case SURFACE_METAL_FENCE:
case SURFACE_17: case SURFACE_FLESH:
case SURFACE_23: case SURFACE_TIRE:
case SURFACE_24: case SURFACE_HARD24:
case SURFACE_26: case SURFACE_STONE:
case SURFACE_27: case SURFACE_METAL27:
case SURFACE_28: case SURFACE_METAL28:
case SURFACE_29: case SURFACE_RUBBER29:
case SURFACE_32: case SURFACE_GATE:
return 1.0f - CWeather::WetRoads*0.4f; return 1.0f - CWeather::WetRoads*0.4f;
case SURFACE_SAND:
case SURFACE_SAND33:
return 1.0f - CWeather::WetRoads*0.5f;
default: default:
return 1.0f; return 1.0f;
} }

View File

@ -1,47 +1,6 @@
#pragma once #pragma once
// TODO: check this
enum
{
SURFACE_0,
SURFACE_1,
SURFACE_2,
SURFACE_3,
SURFACE_4,
SURFACE_5,
SURFACE_6,
SURFACE_7,
SURFACE_8,
SURFACE_9,
SURFACE_10,
SURFACE_11,
SURFACE_12,
SURFACE_13,
SURFACE_14,
SURFACE_15,
SURFACE_16,
SURFACE_17,
SURFACE_18,
SURFACE_19,
SURFACE_20,
SURFACE_21,
SURFACE_22,
SURFACE_23,
SURFACE_24,
SURFACE_25,
SURFACE_26,
SURFACE_27,
SURFACE_28,
SURFACE_29,
SURFACE_30,
SURFACE_31,
SURFACE_32,
NUMSURFACETYPES
};
// From nick
// TODO: check and use this
enum eSurfaceType enum eSurfaceType
{ {
SURFACE_DEFAULT, SURFACE_DEFAULT,
@ -77,8 +36,6 @@ enum eSurfaceType
SURFACE_LOOSE30, SURFACE_LOOSE30,
SURFACE_BOLLARD, SURFACE_BOLLARD,
SURFACE_GATE, SURFACE_GATE,
// These are illegal
SURFACE_SAND33, SURFACE_SAND33,
SURFACE_ROAD34, SURFACE_ROAD34,
}; };
@ -89,6 +46,7 @@ enum
ADHESIVE_HARD, ADHESIVE_HARD,
ADHESIVE_ROAD, ADHESIVE_ROAD,
ADHESIVE_LOOSE, ADHESIVE_LOOSE,
ADHESIVE_SAND,
ADHESIVE_WET, ADHESIVE_WET,
NUMADHESIVEGROUPS NUMADHESIVEGROUPS

View File

@ -30,6 +30,7 @@ enum eEntityStatus : uint8
STATUS_PLANE, STATUS_PLANE,
STATUS_PLAYER_REMOTE, STATUS_PLAYER_REMOTE,
STATUS_PLAYER_DISABLED, STATUS_PLAYER_DISABLED,
STATUS_12, // TODO: what is this? used in CPhysical::ApplyAirResistance
}; };
class CEntity : public CPlaceable class CEntity : public CPlaceable

View File

@ -1,7 +1,9 @@
#include "common.h" #include "common.h"
#include "World.h" #include "World.h"
#include "General.h"
#include "Timer.h" #include "Timer.h"
#include "Stats.h"
#include "ModelIndices.h" #include "ModelIndices.h"
#include "Treadable.h" #include "Treadable.h"
#include "Vehicle.h" #include "Vehicle.h"
@ -15,8 +17,11 @@
#include "CarCtrl.h" #include "CarCtrl.h"
#include "DMAudio.h" #include "DMAudio.h"
#include "Automobile.h" #include "Automobile.h"
#include "Pickups.h"
#include "Physical.h" #include "Physical.h"
//--MIAMI: file done except one bike thing
CPhysical::CPhysical(void) CPhysical::CPhysical(void)
{ {
int i; int i;
@ -37,6 +42,7 @@ CPhysical::CPhysical(void)
m_aCollisionRecords[i] = nil; m_aCollisionRecords[i] = nil;
m_bIsVehicleBeingShifted = false; m_bIsVehicleBeingShifted = false;
bJustCheckCollision = false;
m_nDamagePieceType = 0; m_nDamagePieceType = 0;
m_fDamageImpulse = 0.0f; m_fDamageImpulse = 0.0f;
@ -45,25 +51,26 @@ CPhysical::CPhysical(void)
bUsesCollision = true; bUsesCollision = true;
m_audioEntityId = -5; m_audioEntityId = -5;
unk1 = 100.0f; m_phys_unused1 = 100.0f;
m_vecCentreOfMass = CVector(0.0f, 0.0f, 0.0f); m_vecCentreOfMass = CVector(0.0f, 0.0f, 0.0f);
field_EC = 0; m_phys_unused2 = 0;
bIsHeavy = false; bIsHeavy = false;
bAffectedByGravity = true; bAffectedByGravity = true;
bInfiniteMass = false; bInfiniteMass = false;
m_phy_flagA08 = false;
bIsInWater = false; bIsInWater = false;
bHitByTrain = false; bHitByTrain = false;
bSkipLineCol = false; bSkipLineCol = false;
m_fDistanceTravelled = 0.0f; m_fDistanceTravelled = 0.0f;
m_treadable[PATH_CAR] = nil;
m_treadable[PATH_PED] = nil;
m_phy_flagA10 = false;
m_phy_flagA20 = false; m_phy_flagA20 = false;
m_nZoneLevel = LEVEL_NONE; m_nZoneLevel = LEVEL_NONE;
bIsFrozen = false;
bDontLoadCollision = false;
} }
CPhysical::~CPhysical(void) CPhysical::~CPhysical(void)
@ -264,7 +271,6 @@ CPhysical::AddCollisionRecord(CEntity *ent)
} }
} }
//--MIAMI: done
void void
CPhysical::AddCollisionRecord_Treadable(CEntity *ent) CPhysical::AddCollisionRecord_Treadable(CEntity *ent)
{ {
@ -401,18 +407,26 @@ CPhysical::GetSpeed(const CVector &r)
void void
CPhysical::ApplyMoveSpeed(void) CPhysical::ApplyMoveSpeed(void)
{ {
if(bIsFrozen)
m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f);
else
GetMatrix().Translate(m_vecMoveSpeed * CTimer::GetTimeStep()); GetMatrix().Translate(m_vecMoveSpeed * CTimer::GetTimeStep());
} }
void void
CPhysical::ApplyTurnSpeed(void) CPhysical::ApplyTurnSpeed(void)
{ {
if(bIsFrozen){
m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
}else{
// Move the coordinate axes by their speed // Move the coordinate axes by their speed
// Note that this denormalizes the matrix // Note that this denormalizes the matrix
CVector turnvec = m_vecTurnSpeed*CTimer::GetTimeStep(); CVector turnvec = m_vecTurnSpeed*CTimer::GetTimeStep();
GetRight() += CrossProduct(turnvec, GetRight()); GetRight() += CrossProduct(turnvec, GetRight());
GetForward() += CrossProduct(turnvec, GetForward()); GetForward() += CrossProduct(turnvec, GetForward());
GetUp() += CrossProduct(turnvec, GetUp()); GetUp() += CrossProduct(turnvec, GetUp());
}
} }
void void
@ -456,6 +470,21 @@ CPhysical::ApplySpringCollision(float springConst, CVector &springDir, CVector &
return true; return true;
} }
bool
CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir)
{
float compression = 1.0f - springRatio;
if(compression > 0.0f){
if(DotProduct(springDir, forceDir) > 0.0f)
forceDir *= -1.0f;
float step = Min(CTimer::GetTimeStep(), 3.0f);
float impulse = -GRAVITY*m_fMass*step * springConst * compression * bias*2.0f;
ApplyMoveForce(forceDir*impulse);
ApplyTurnForce(forceDir*impulse, point);
}
return true;
}
// What exactly is speed? // What exactly is speed?
bool bool
CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed) CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed)
@ -464,6 +493,8 @@ CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &poin
float speedB = DotProduct(GetSpeed(point), springDir); float speedB = DotProduct(GetSpeed(point), springDir);
float step = Min(CTimer::GetTimeStep(), 3.0f); float step = Min(CTimer::GetTimeStep(), 3.0f);
float impulse = -damping * (speedA + speedB)/2.0f * m_fMass * step * 0.53f; float impulse = -damping * (speedA + speedB)/2.0f * m_fMass * step * 0.53f;
if(bIsHeavy)
impulse *= 2.0f;
// what is this? // what is this?
float a = m_fTurnMass / ((point.MagnitudeSqr() + 1.0f) * 2.0f * m_fMass); float a = m_fTurnMass / ((point.MagnitudeSqr() + 1.0f) * 2.0f * m_fMass);
@ -497,9 +528,11 @@ void
CPhysical::ApplyAirResistance(void) CPhysical::ApplyAirResistance(void)
{ {
if(m_fAirResistance > 0.1f){ if(m_fAirResistance > 0.1f){
if(GetStatus() != STATUS_12){
float f = Pow(m_fAirResistance, CTimer::GetTimeStep()); float f = Pow(m_fAirResistance, CTimer::GetTimeStep());
m_vecMoveSpeed *= f; m_vecMoveSpeed *= f;
m_vecTurnSpeed *= f; m_vecTurnSpeed *= f;
}
}else{ }else{
float f = Pow(1.0f/(m_fAirResistance*0.5f*m_vecMoveSpeed.MagnitudeSqr() + 1.0f), CTimer::GetTimeStep()); float f = Pow(1.0f/(m_fAirResistance*0.5f*m_vecMoveSpeed.MagnitudeSqr() + 1.0f), CTimer::GetTimeStep());
m_vecMoveSpeed *= f; m_vecMoveSpeed *= f;
@ -507,7 +540,6 @@ CPhysical::ApplyAirResistance(void)
} }
} }
bool bool
CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, float &impulseB) CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, float &impulseB)
{ {
@ -515,32 +547,38 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
CPhysical *A = this; CPhysical *A = this;
CObject *Bobj = (CObject*)B; CObject *Bobj = (CObject*)B;
bool foo = false; // TODO: what does this mean?
bool ispedcontactA = false; bool ispedcontactA = false;
bool ispedcontactB = false; bool ispedcontactB = false;
float timestepA; float massFactorA;
if(B->bPedPhysics){ if(B->bPedPhysics){
timestepA = 10.0f; massFactorA = 10.0f;
if(B->IsPed() && ((CPed*)B)->m_pCurrentPhysSurface == A) if(B->IsPed() && ((CPed*)B)->m_pCurrentPhysSurface == A)
ispedcontactA = true; ispedcontactA = true;
}else }else
timestepA = A->bIsHeavy ? 2.0f : 1.0f; massFactorA = A->bIsHeavy ? 2.0f : 1.0f;
float timestepB; float massFactorB;
if(A->bPedPhysics){ if(A->bPedPhysics){
if(A->IsPed() && ((CPed*)A)->IsPlayer() && B->IsVehicle() && if(A->IsPed() && ((CPed*)A)->IsPlayer() && B->IsVehicle() &&
(B->GetStatus() == STATUS_ABANDONED || B->GetStatus() == STATUS_WRECKED || A->bHasHitWall)) (B->GetStatus() == STATUS_ABANDONED || B->GetStatus() == STATUS_WRECKED || A->bHasHitWall))
timestepB = 2200.0f / B->m_fMass; massFactorB = 1.0f/(Max(B->m_fMass - 2000.0f, 0.0f)/5000.0f + 1.0f);
else else
timestepB = 10.0f; massFactorB = 10.0f;
if(A->IsPed() && ((CPed*)A)->m_pCurrentPhysSurface == B) if(A->IsPed() && ((CPed*)A)->m_pCurrentPhysSurface == B)
ispedcontactB = true; ispedcontactB = true;
}else }else
timestepB = B->bIsHeavy ? 2.0f : 1.0f; massFactorB = B->bIsHeavy ? 2.0f : 1.0f;
if(B->bInfiniteMass && !B->m_phy_flagA08){
ispedcontactB = false;
foo = true;
}
float speedA, speedB; float speedA, speedB;
if(B->IsStatic()){ if(B->IsStatic() && !foo){
if(A->bPedPhysics){ if(A->bPedPhysics){
speedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal); speedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal);
if(speedA < 0.0f){ if(speedA < 0.0f){
@ -550,8 +588,11 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
if(impulseA > Bobj->m_fUprootLimit){ if(impulseA > Bobj->m_fUprootLimit){
if(IsGlass(B->GetModelIndex())) if(IsGlass(B->GetModelIndex()))
CGlass::WindowRespondsToCollision(B, impulseA, A->m_vecMoveSpeed, colpoint.point, false); CGlass::WindowRespondsToCollision(B, impulseA, A->m_vecMoveSpeed, colpoint.point, false);
else if(!B->bInfiniteMass) else if(!B->bInfiniteMass){
B->bIsStatic = false; B->bIsStatic = false;
CWorld::Players[CWorld::PlayerInFocus].m_nHavocCaused += 2;
CStats::PropertyDestroyed += CGeneral::GetRandomNumberInRange(30, 60);
}
}else{ }else{
if(IsGlass(B->GetModelIndex())) if(IsGlass(B->GetModelIndex()))
CGlass::WindowRespondsToSoftCollision(B, impulseA); CGlass::WindowRespondsToSoftCollision(B, impulseA);
@ -603,6 +644,9 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
if(model == MI_FIRE_HYDRANT && !Bobj->bHasBeenDamaged){ if(model == MI_FIRE_HYDRANT && !Bobj->bHasBeenDamaged){
CParticleObject::AddObject(POBJECT_FIRE_HYDRANT, B->GetPosition() - CVector(0.0f, 0.0f, 0.5f), true); CParticleObject::AddObject(POBJECT_FIRE_HYDRANT, B->GetPosition() - CVector(0.0f, 0.0f, 0.5f), true);
Bobj->bHasBeenDamaged = true; Bobj->bHasBeenDamaged = true;
}else if(model == MI_PARKINGMETER || model == MI_PARKINGMETER2){
CPickups::CreateSomeMoney(GetPosition(), CGeneral::GetRandomNumber()%100);
Bobj->bHasBeenDamaged = true;
}else if(B->IsObject() && !IsExplosiveThingModel(model)) }else if(B->IsObject() && !IsExplosiveThingModel(model))
Bobj->bHasBeenDamaged = true; Bobj->bHasBeenDamaged = true;
}else{ }else{
@ -625,7 +669,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
if(B->IsStatic()) if(B->IsStatic())
return false; return false;
if(!B->bInfiniteMass) if(!B->bInfiniteMass && !B->m_phy_flagA08)
B->AddToMovingList(); B->AddToMovingList();
} }
@ -635,16 +679,36 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
// negative if A is moving towards B // negative if A is moving towards B
speedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal); speedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal);
// positive if B is moving towards A // positive if B is moving towards A
// not interested in how much B moves into A apparently? float speedB = DotProduct(B->m_vecMoveSpeed, colpoint.normal);
// only interested in cases where A collided into B
speedB = Max(0.0f, DotProduct(B->m_vecMoveSpeed, colpoint.normal)); bool affectB = false;
// A has moved into B float mA = A->m_fMass;;
if(speedA < speedB){ float mB = B->m_fMass;;
if(!A->bHasHitWall) float speedSum;
speedB -= (speedA - speedB) * (A->m_fElasticity+B->m_fElasticity)/2.0f; if(((CPed*)A)->GetPedState() == PED_FOLLOW_PATH){
impulseA = (speedB-speedA) * A->m_fMass * timestepA; affectB = true;
speedSum = (2.0f*mA*speedA + mB*speedB)/(2.0f*mA + mB);
}else{
speedSum = Max(speedB, 0.0f);
}
if(speedA < speedSum){
if(A->bHasHitWall)
eA = speedSum;
else
eA = speedSum - (speedA - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f;
impulseA = (eA-speedA) * mA;
if(!A->bInfiniteMass) if(!A->bInfiniteMass)
A->ApplyMoveForce(colpoint.normal*(impulseA/timestepA)); A->ApplyMoveForce(colpoint.normal*impulseA);
if(affectB && speedB < speedSum){
if(B->bHasHitWall)
eB = speedSum;
else
eB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f;
impulseB = -(eB-speedB) * mB;
if(!B->bInfiniteMass)
B->ApplyMoveForce(colpoint.normal*-impulseB);
}
return true; return true;
} }
}else if(A->bPedPhysics){ }else if(A->bPedPhysics){
@ -652,9 +716,13 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
speedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal); speedA = DotProduct(A->m_vecMoveSpeed, colpoint.normal);
speedB = DotProduct(B->GetSpeed(pointposB), colpoint.normal); speedB = DotProduct(B->GetSpeed(pointposB), colpoint.normal);
float a = A->m_fMass*timestepA; float mA = A->m_fMass*massFactorA;
float b = B->GetMassTime(pointposB, colpoint.normal, timestepB); float mB = B->GetMassTweak(pointposB, colpoint.normal, massFactorB);
float speedSum = (b*speedB + a*speedA)/(a + b); float speedSum;
if(foo)
speedSum = speedB;
else
speedSum = (mB*speedB + mA*speedA)/(mA + mB);
if(speedA < speedSum){ if(speedA < speedSum){
if(A->bHasHitWall) if(A->bHasHitWall)
eA = speedSum; eA = speedSum;
@ -664,10 +732,10 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
eB = speedSum; eB = speedSum;
else else
eB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f; eB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f;
impulseA = (eA - speedA) * a; impulseA = (eA - speedA) * mA;
impulseB = -(eB - speedB) * b; impulseB = -(eB - speedB) * mB;
CVector fA = colpoint.normal*(impulseA/timestepA); CVector fA = colpoint.normal*(impulseA/massFactorA);
CVector fB = colpoint.normal*(-impulseB/timestepB); CVector fB = colpoint.normal*(-impulseB/massFactorB);
if(!A->bInfiniteMass){ if(!A->bInfiniteMass){
if(fA.z < 0.0f) fA.z = 0.0f; if(fA.z < 0.0f) fA.z = 0.0f;
if(ispedcontactB){ if(ispedcontactB){
@ -687,9 +755,9 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
speedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal); speedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal);
speedB = DotProduct(B->m_vecMoveSpeed, colpoint.normal); speedB = DotProduct(B->m_vecMoveSpeed, colpoint.normal);
float a = A->GetMassTime(pointposA, colpoint.normal, timestepA); float mA = A->GetMassTweak(pointposA, colpoint.normal, massFactorA);
float b = B->m_fMass*timestepB; float mB = B->m_fMass*massFactorB;
float speedSum = (b*speedB + a*speedA)/(a + b); float speedSum = (mB*speedB + mA*speedA)/(mA + mB);
if(speedA < speedSum){ if(speedA < speedSum){
if(A->bHasHitWall) if(A->bHasHitWall)
eA = speedSum; eA = speedSum;
@ -699,10 +767,10 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
eB = speedSum; eB = speedSum;
else else
eB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f; eB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f;
impulseA = (eA - speedA) * a; impulseA = (eA - speedA) * mA;
impulseB = -(eB - speedB) * b; impulseB = -(eB - speedB) * mB;
CVector fA = colpoint.normal*(impulseA/timestepA); CVector fA = colpoint.normal*(impulseA/massFactorA);
CVector fB = colpoint.normal*(-impulseB/timestepB); CVector fB = colpoint.normal*(-impulseB/massFactorB);
if(!A->bInfiniteMass && !ispedcontactA){ if(!A->bInfiniteMass && !ispedcontactA){
if(fA.z < 0.0f) fA.z = 0.0f; if(fA.z < 0.0f) fA.z = 0.0f;
A->ApplyMoveForce(fA); A->ApplyMoveForce(fA);
@ -727,9 +795,9 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
CVector pointposB = colpoint.point - B->GetPosition(); CVector pointposB = colpoint.point - B->GetPosition();
speedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal); speedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal);
speedB = DotProduct(B->GetSpeed(pointposB), colpoint.normal); speedB = DotProduct(B->GetSpeed(pointposB), colpoint.normal);
float a = A->GetMassTime(pointposA, colpoint.normal, timestepA); float mA = A->GetMassTweak(pointposA, colpoint.normal, massFactorA);
float b = B->GetMassTime(pointposB, colpoint.normal, timestepB); float mB = B->GetMassTweak(pointposB, colpoint.normal, massFactorB);
float speedSum = (b*speedB + a*speedA)/(a + b); float speedSum = (mB*speedB + mA*speedA)/(mA + mB);
if(speedA < speedSum){ if(speedA < speedSum){
if(A->bHasHitWall) if(A->bHasHitWall)
eA = speedSum; eA = speedSum;
@ -739,10 +807,10 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
eB = speedSum; eB = speedSum;
else else
eB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f; eB = speedSum - (speedB - speedSum) * (A->m_fElasticity+B->m_fElasticity)/2.0f;
impulseA = (eA - speedA) * a; impulseA = (eA - speedA) * mA;
impulseB = -(eB - speedB) * b; impulseB = -(eB - speedB) * mB;
CVector fA = colpoint.normal*(impulseA/timestepA); CVector fA = colpoint.normal*(impulseA/massFactorA);
CVector fB = colpoint.normal*(-impulseB/timestepB); CVector fB = colpoint.normal*(-impulseB/massFactorB);
if(A->IsVehicle() && !A->bHasHitWall){ if(A->IsVehicle() && !A->bHasHitWall){
fA.x *= 1.4f; fA.x *= 1.4f;
fA.y *= 1.4f; fA.y *= 1.4f;
@ -758,7 +826,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
if(B->IsVehicle() && !B->bHasHitWall){ if(B->IsVehicle() && !B->bHasHitWall){
fB.x *= 1.4f; fB.x *= 1.4f;
fB.y *= 1.4f; fB.y *= 1.4f;
if(colpoint.normal.z < 0.7f) if(-colpoint.normal.z < 0.7f)
fB.z *= 0.3f; fB.z *= 0.3f;
if(B->GetStatus() == STATUS_PLAYER) if(B->GetStatus() == STATUS_PLAYER)
pointposB *= 0.8f; pointposB *= 0.8f;
@ -784,14 +852,53 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
return false; return false;
} }
bool
CPhysical::ApplyCollision(CColPoint &colpoint, float &impulse)
{
float speed;
if(bPedPhysics){
speed = DotProduct(m_vecMoveSpeed, colpoint.normal);
if(speed < 0.0f){
impulse = -speed * m_fMass;
ApplyMoveForce(colpoint.normal*impulse);
return true;
}
}else{
CVector pointpos = colpoint.point - GetPosition();
speed = DotProduct(GetSpeed(pointpos), colpoint.normal);
if(speed < 0.0f){
float mass = GetMass(pointpos, colpoint.normal);
impulse = -(m_fElasticity + 1.0f) * speed * mass;
CVector f = colpoint.normal*impulse;
if(IsVehicle()){
f.x *= 1.4f;
f.y *= 1.4f;
if(colpoint.normal.z < 0.7f)
f.z *= 0.3f;
}
if(!bInfiniteMass){
ApplyMoveForce(f);
if(!IsVehicle() || !CWorld::bNoMoreCollisionTorque)
ApplyTurnForce(f, pointpos);
}
return true;
}
}
return false;
}
bool bool
CPhysical::ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CVector &moveSpeed, CVector &turnSpeed) CPhysical::ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CVector &moveSpeed, CVector &turnSpeed)
{ {
float normalSpeed; float normalSpeed;
float e;
CVector speed; CVector speed;
CVector vImpulse; CVector vImpulse;
if(GetModelIndex() == MI_BEACHBALL && B != (CEntity*)FindPlayerPed())
((CObject*)this)->m_nBeachballBounces = 0;
if(bPedPhysics){ if(bPedPhysics){
normalSpeed = DotProduct(m_vecMoveSpeed, colpoint.normal); normalSpeed = DotProduct(m_vecMoveSpeed, colpoint.normal);
if(normalSpeed < 0.0f){ if(normalSpeed < 0.0f){
@ -804,29 +911,62 @@ CPhysical::ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CV
speed = GetSpeed(pointpos); speed = GetSpeed(pointpos);
normalSpeed = DotProduct(speed, colpoint.normal); normalSpeed = DotProduct(speed, colpoint.normal);
if(normalSpeed < 0.0f){ if(normalSpeed < 0.0f){
float minspeed = 0.0104f * CTimer::GetTimeStep(); int16 elasticityType = 0;
#ifdef GTA3_1_1_PATCH float mass = GetMass(pointpos, colpoint.normal);
if ((IsObject() || IsVehicle() && (GetUp().z < -0.3f || ((CVehicle*)this)->IsBike() && (GetStatus() == STATUS_ABANDONED || GetStatus() == STATUS_WRECKED))) && float minspeed = GRAVITY * CTimer::GetTimeStep();
#else
if((IsObject() || IsVehicle() && GetUp().z < -0.3f) && if(IsObject())
#endif elasticityType = 1;
!bHasContacted && else if(IsVehicle() && !bIsInWater){
if(((CVehicle*)this)->IsBike() && (GetStatus() == STATUS_ABANDONED || GetStatus() == STATUS_WRECKED)){
minspeed *= 1.3f;
elasticityType = 3;
}else if(((CVehicle*)this)->IsBoat()){
minspeed *= 1.2f;
elasticityType = 4;
}else if(GetUp().z < -0.3f){
minspeed *= 1.1f;
elasticityType = 2;
}
}
if(elasticityType == 1 && !bHasContacted &&
Abs(m_vecMoveSpeed.x) < minspeed && Abs(m_vecMoveSpeed.x) < minspeed &&
Abs(m_vecMoveSpeed.y) < minspeed && Abs(m_vecMoveSpeed.y) < minspeed &&
Abs(m_vecMoveSpeed.z) < minspeed*2.0f) Abs(m_vecMoveSpeed.z) < minspeed*2.0f)
e = -1.0f; impulse = -0.98f * normalSpeed * mass;
if(elasticityType == 3 &&
Abs(m_vecMoveSpeed.x) < minspeed &&
Abs(m_vecMoveSpeed.y) < minspeed &&
Abs(m_vecMoveSpeed.z) < minspeed*2.0f)
impulse = -0.8f * normalSpeed * mass;
else if(elasticityType == 2 &&
Abs(m_vecMoveSpeed.x) < minspeed &&
Abs(m_vecMoveSpeed.y) < minspeed &&
Abs(m_vecMoveSpeed.z) < minspeed*2.0f)
impulse = -0.92f * normalSpeed * mass;
else if(elasticityType == 4 &&
Abs(m_vecMoveSpeed.x) < minspeed &&
Abs(m_vecMoveSpeed.y) < minspeed &&
Abs(m_vecMoveSpeed.z) < minspeed*2.0f)
impulse = -0.8f * normalSpeed * mass;
else if(IsVehicle() && ((CVehicle*)this)->IsBoat() &&
colpoint.surfaceB == SURFACE_WOOD_PLANK && colpoint.normal.z < 0.5f)
impulse = -(2.0f * m_fElasticity + 1.0f) * normalSpeed * mass;
else else
e = -(m_fElasticity + 1.0f); impulse = -(m_fElasticity + 1.0f) * normalSpeed * mass;
impulse = normalSpeed * e * GetMass(pointpos, colpoint.normal);
// ApplyMoveForce // ApplyMoveForce
vImpulse = colpoint.normal*impulse; vImpulse = colpoint.normal*impulse;
if(IsVehicle() && if(IsVehicle()){
(!bHasHitWall || if(!bHasHitWall ||
!(m_vecMoveSpeed.MagnitudeSqr() > 0.1 || !(B->IsBuilding() || ((CPhysical*)B)->bInfiniteMass)))) !(m_vecMoveSpeed.MagnitudeSqr() > 0.1 || !(B->IsBuilding() || ((CPhysical*)B)->bInfiniteMass)))
moveSpeed += vImpulse * 1.2f * (1.0f/m_fMass); moveSpeed += vImpulse * 1.2f * (1.0f/m_fMass);
else else
moveSpeed += vImpulse * (1.0f/m_fMass); moveSpeed += vImpulse * (1.0f/m_fMass);
vImpulse *= 0.8f;
}else
moveSpeed += vImpulse * (1.0f/m_fMass);
// ApplyTurnForce // ApplyTurnForce
CVector com = Multiply3x3(m_matrix, m_vecCentreOfMass); CVector com = Multiply3x3(m_matrix, m_vecCentreOfMass);
@ -1006,7 +1146,7 @@ CPhysical::ApplyFriction(float adhesiveLimit, CColPoint &colpoint)
ApplyFrictionTurnForce(frictionDir*fImpulse, pointpos); ApplyFrictionTurnForce(frictionDir*fImpulse, pointpos);
if(fOtherSpeed > 0.1f && if(fOtherSpeed > 0.1f &&
colpoint.surfaceB != SURFACE_2 && colpoint.surfaceB != SURFACE_4 && colpoint.surfaceB != SURFACE_GRASS && colpoint.surfaceB != SURFACE_DIRTTRACK &&
CSurfaceTable::GetAdhesionGroup(colpoint.surfaceA) == ADHESIVE_HARD){ CSurfaceTable::GetAdhesionGroup(colpoint.surfaceA) == ADHESIVE_HARD){
CVector v = frictionDir * fOtherSpeed * 0.25f; CVector v = frictionDir * fOtherSpeed * 0.25f;
for(int i = 0; i < 4; i++) for(int i = 0; i < 4; i++)
@ -1055,7 +1195,7 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists)
canshift = true; canshift = true;
else else
canshift = A->IsPed() && canshift = A->IsPed() &&
B->IsObject() && B->bInfiniteMass && !Bobj->bHasBeenDamaged; B->IsObject() && B->IsStatic() && !Bobj->bHasBeenDamaged;
if(B == A || if(B == A ||
B->m_scanCode == CWorld::GetCurrentScanCode() || B->m_scanCode == CWorld::GetCurrentScanCode() ||
!B->bUsesCollision || !B->bUsesCollision ||
@ -1075,7 +1215,6 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists)
B->GetUp().z < 0.66f && B->GetUp().z < 0.66f &&
IsLightWithoutShift(B->GetModelIndex())) IsLightWithoutShift(B->GetModelIndex()))
skipShift = true; skipShift = true;
// TODO: maybe flip some ifs here
else if(A->IsObject() && B->IsVehicle()){ else if(A->IsObject() && B->IsVehicle()){
CObject *Aobj = (CObject*)A; CObject *Aobj = (CObject*)A;
if(Aobj->ObjectCreatedBy != TEMP_OBJECT && if(Aobj->ObjectCreatedBy != TEMP_OBJECT &&
@ -1194,6 +1333,9 @@ CPhysical::ProcessCollisionSectorList_SimpleCar(CPtrList *lists)
A = (CPhysical*)this; A = (CPhysical*)this;
if(!A->bUsesCollision)
return false;
radius = A->GetBoundRadius(); radius = A->GetBoundRadius();
A->GetBoundCentre(center); A->GetBoundCentre(center);
@ -1212,6 +1354,7 @@ CPhysical::ProcessCollisionSectorList_SimpleCar(CPtrList *lists)
for(listnode = list->first; listnode; listnode = listnode->next){ for(listnode = list->first; listnode; listnode = listnode->next){
B = (CPhysical*)listnode->item; B = (CPhysical*)listnode->item;
if(B != A && if(B != A &&
!(B->IsObject() && ((CObject*)B)->bIsStreetLight && B->GetUp().z < 0.66f) &&
B->m_scanCode != CWorld::GetCurrentScanCode() && B->m_scanCode != CWorld::GetCurrentScanCode() &&
B->bUsesCollision && B->bUsesCollision &&
B->GetIsTouching(center, radius)){ B->GetIsTouching(center, radius)){
@ -1355,6 +1498,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
int numResponses; int numResponses;
int i, j; int i, j;
bool skipCollision, altcollision; bool skipCollision, altcollision;
bool ret = false;
float impulseA = -1.0f; float impulseA = -1.0f;
float impulseB = -1.0f; float impulseB = -1.0f;
@ -1375,9 +1519,9 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
Bped = (CPed*)B; Bped = (CPed*)B;
bool isTouching = true; bool isTouching = true;
if(B == A || if(!B->bUsesCollision ||
B->m_scanCode == CWorld::GetCurrentScanCode() || B->m_scanCode == CWorld::GetCurrentScanCode() ||
!B->bUsesCollision || B == A ||
!(isTouching = B->GetIsTouching(center, radius))){ !(isTouching = B->GetIsTouching(center, radius))){
if(!isTouching){ if(!isTouching){
if(A->IsObject() && Aobj->m_pCollidingEntity == B) if(A->IsObject() && Aobj->m_pCollidingEntity == B)
@ -1398,27 +1542,27 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
if(B->IsBuilding()) if(B->IsBuilding())
skipCollision = false; skipCollision = false;
else if(IsLightWithoutShift(A->GetModelIndex()) && else if(A->IsObject() && Aobj->bIsStreetLight &&
(B->IsVehicle() || B->IsPed()) && (B->IsVehicle() || B->IsPed()) &&
A->GetUp().z < 0.66f){ A->GetUp().z < 0.66f){
skipCollision = true; skipCollision = true;
A->bSkipLineCol = true; A->bSkipLineCol = true;
Aobj->m_pCollidingEntity = B; Aobj->m_pCollidingEntity = B;
}else if((A->IsVehicle() || A->IsPed()) && }else if(B->IsObject() && Bobj->bIsStreetLight &&
B->GetUp().z < 0.66f && (A->IsVehicle() || A->IsPed()) &&
IsLightWithoutShift(B->GetModelIndex())){ B->GetUp().z < 0.66f){
skipCollision = true; skipCollision = true;
A->bSkipLineCol = true; A->bSkipLineCol = true;
Bobj->m_pCollidingEntity = A; Bobj->m_pCollidingEntity = A;
}else if(A->IsObject() && B->IsVehicle()){ }else if(A->IsObject() && B->IsVehicle()){
if(A->GetModelIndex() == MI_CAR_BUMPER)// || A->GetModelIndex() == MI_FILES) if(A->GetModelIndex() == MI_CAR_BUMPER)
skipCollision = true; skipCollision = true;
else if(Aobj->ObjectCreatedBy == TEMP_OBJECT || else if(Aobj->ObjectCreatedBy == TEMP_OBJECT ||
Aobj->bHasBeenDamaged || Aobj->bHasBeenDamaged ||
!Aobj->IsStatic()){ !Aobj->IsStatic()){
if(Aobj->m_pCollidingEntity == B) if(Aobj->m_pCollidingEntity == B)
skipCollision = true; skipCollision = true;
else{ else if(Aobj->m_nCollisionDamageEffect < DAMAGE_EFFECT_SMASH_COMPLETELY){
CMatrix inv; CMatrix inv;
CVector size = CModelInfo::GetModelInfo(A->GetModelIndex())->GetColModel()->boundingBox.GetSize(); CVector size = CModelInfo::GetModelInfo(A->GetModelIndex())->GetColModel()->boundingBox.GetSize();
size = A->GetMatrix() * size; size = A->GetMatrix() * size;
@ -1430,14 +1574,14 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
} }
} }
}else if(B->IsObject() && A->IsVehicle()){ }else if(B->IsObject() && A->IsVehicle()){
if(B->GetModelIndex() == MI_CAR_BUMPER)// || B->GetModelIndex() == MI_FILES) if(B->GetModelIndex() == MI_CAR_BUMPER)
skipCollision = true; skipCollision = true;
else if(Bobj->ObjectCreatedBy == TEMP_OBJECT || else if(Bobj->ObjectCreatedBy == TEMP_OBJECT ||
Bobj->bHasBeenDamaged || Bobj->bHasBeenDamaged ||
!Bobj->IsStatic()){ !Bobj->IsStatic()){
if(Bobj->m_pCollidingEntity == A) if(Bobj->m_pCollidingEntity == A)
skipCollision = true; skipCollision = true;
else{ else if(Bobj->m_nCollisionDamageEffect < DAMAGE_EFFECT_SMASH_COMPLETELY){
CMatrix inv; CMatrix inv;
CVector size = CModelInfo::GetModelInfo(B->GetModelIndex())->GetColModel()->boundingBox.GetSize(); CVector size = CModelInfo::GetModelInfo(B->GetModelIndex())->GetColModel()->boundingBox.GetSize();
size = B->GetMatrix() * size; size = B->GetMatrix() * size;
@ -1447,14 +1591,16 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
} }
} }
} }
}else if(IsBodyPart(A->GetModelIndex()) && B->IsPed()){ }else if(A->GetModelIndex() == MI_GRENADE && B->IsPed() &&
A->GetPosition().z < B->GetPosition().z){
skipCollision = true; skipCollision = true;
}else if(A->IsPed() && IsBodyPart(B->GetModelIndex())){ }else if(B->GetModelIndex() == MI_GRENADE && A->IsPed() &&
B->GetPosition().z < A->GetPosition().z){
skipCollision = true; skipCollision = true;
A->bSkipLineCol = true; A->bSkipLineCol = true;
}else if(A->IsPed() && Aped->m_pCollidingEntity == B){ }else if(A->IsPed() && Aped->m_pCollidingEntity == B){
skipCollision = true; skipCollision = true;
if(!Aped->bKnockedUpIntoAir) if(!Aped->bKnockedUpIntoAir || Aped->b158_4)
A->bSkipLineCol = true; A->bSkipLineCol = true;
}else if(B->IsPed() && Bped->m_pCollidingEntity == A){ }else if(B->IsPed() && Bped->m_pCollidingEntity == A){
skipCollision = true; skipCollision = true;
@ -1469,7 +1615,11 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
if(!A->bUsesCollision || skipCollision){ if(!A->bUsesCollision || skipCollision){
B->m_scanCode = CWorld::GetCurrentScanCode(); B->m_scanCode = CWorld::GetCurrentScanCode();
A->ProcessEntityCollision(B, aColPoints); numCollisions = A->ProcessEntityCollision(B, aColPoints);
if(A->bJustCheckCollision && numCollisions > 0)
return true;
if(numCollisions == 0 && A == (CEntity*)FindPlayerPed() && Aped->m_pCollidingEntity == B)
Aped->m_pCollidingEntity = nil;
}else if(B->IsBuilding() || B->bIsStuck || B->bInfiniteMass || altcollision){ }else if(B->IsBuilding() || B->bIsStuck || B->bInfiniteMass || altcollision){
// This is the case where B doesn't move // This is the case where B doesn't move
@ -1481,6 +1631,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
CVector moveSpeed = { 0.0f, 0.0f, 0.0f }; CVector moveSpeed = { 0.0f, 0.0f, 0.0f };
CVector turnSpeed = { 0.0f, 0.0f, 0.0f }; CVector turnSpeed = { 0.0f, 0.0f, 0.0f };
float maxImpulseA = 0.0f;
numResponses = 0; numResponses = 0;
if(A->bHasContacted){ if(A->bHasContacted){
for(i = 0; i < numCollisions; i++){ for(i = 0; i < numCollisions; i++){
@ -1488,20 +1639,35 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
continue; continue;
numResponses++; numResponses++;
if(impulseA > maxImpulseA) maxImpulseA = impulseA;
if(impulseA > A->m_fDamageImpulse) if(A->IsVehicle()){
if(!(((CVehicle*)A)->IsBoat() && aColPoints[i].surfaceB == SURFACE_WOOD_PLANK) &&
impulseA > A->m_fDamageImpulse)
A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal); A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);
float imp = impulseA; if(CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_SAND)
if(A->IsVehicle() && A->GetUp().z < -0.6f && aColPoints[i].surfaceB = SURFACE_SAND;
Abs(A->m_vecMoveSpeed.x) < 0.05f &&
Abs(A->m_vecMoveSpeed.y) < 0.05f)
imp *= 0.1f;
float turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr(); float turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr();
float moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr(); float moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr();
DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, imp, Max(turnSpeedDiff, moveSpeedDiff)); if(A->GetUp().z < -0.6f &&
Abs(A->m_vecMoveSpeed.x) < 0.05f &&
Abs(A->m_vecMoveSpeed.y) < 0.05f)
DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, 0.1f*impulseA, Max(turnSpeedDiff, moveSpeedDiff));
else
DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));
}else{
if(impulseA > A->m_fDamageImpulse)
A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);
float turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr();
float moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr();
DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));
}
} }
}else{ }else{
for(i = 0; i < numCollisions; i++){ for(i = 0; i < numCollisions; i++){
@ -1509,39 +1675,52 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
continue; continue;
numResponses++; numResponses++;
if(impulseA > maxImpulseA) maxImpulseA = impulseA;
float adhesion = CSurfaceTable::GetAdhesiveLimit(aColPoints[i]) / numCollisions;
if(impulseA > A->m_fDamageImpulse) if(A->IsVehicle()){
if(((CVehicle*)A)->IsBoat() && aColPoints[i].surfaceB == SURFACE_WOOD_PLANK)
adhesion = 0.0f;
else if(impulseA > A->m_fDamageImpulse)
A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal); A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);
float imp = impulseA; if(CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_SAND)
if(A->IsVehicle() && A->GetUp().z < -0.6f && aColPoints[i].surfaceB = SURFACE_SAND;
Abs(A->m_vecMoveSpeed.x) < 0.05f &&
Abs(A->m_vecMoveSpeed.y) < 0.05f)
imp *= 0.1f;
float turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr(); float turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr();
float moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr(); float moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr();
DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, imp, Max(turnSpeedDiff, moveSpeedDiff)); if(A->GetUp().z < -0.6f &&
Abs(A->m_vecMoveSpeed.x) < 0.05f &&
Abs(A->m_vecMoveSpeed.y) < 0.05f)
DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, 0.1f*impulseA, Max(turnSpeedDiff, moveSpeedDiff));
else
DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));
float adhesion = CSurfaceTable::GetAdhesiveLimit(aColPoints[i]) / numCollisions;
if(A->GetModelIndex() == MI_RCBANDIT) if(A->GetModelIndex() == MI_RCBANDIT)
adhesion *= 0.2f; adhesion *= 0.2f;
// TODO(MIAMI): check this else if(((CVehicle*)A)->IsBoat()){
else if(A->IsVehicle() && ((CVehicle*)A)->IsBoat()){
if(aColPoints[i].normal.z > 0.6f){ if(aColPoints[i].normal.z > 0.6f){
if(CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_LOOSE) if(CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_LOOSE ||
CSurfaceTable::GetAdhesionGroup(aColPoints[i].surfaceB) == ADHESIVE_SAND)
adhesion *= 3.0f; adhesion *= 3.0f;
}else }else
adhesion = 0.0f; adhesion = 0.0f;
}else if(A->IsVehicle()){ }else if(A->GetStatus() == STATUS_WRECKED)
if(A->GetStatus() == STATUS_WRECKED)
adhesion *= 3.0f; adhesion *= 3.0f;
else if(A->GetUp().z > 0.3f) else if(A->GetUp().z > 0.3f)
adhesion = 0.0f; adhesion = 0.0f;
else else
adhesion *= Min(5.0f, 0.03f*impulseA + 1.0f); adhesion *= Min(5.0f, 0.03f*impulseA + 1.0f);
}else{
if(impulseA > A->m_fDamageImpulse)
A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);
float turnSpeedDiff = A->m_vecTurnSpeed.MagnitudeSqr();
float moveSpeedDiff = A->m_vecMoveSpeed.MagnitudeSqr();
DMAudio.ReportCollision(A, B, aColPoints[i].surfaceA, aColPoints[i].surfaceB, impulseA, Max(turnSpeedDiff, moveSpeedDiff));
} }
if(A->ApplyFriction(adhesion, aColPoints[i])) if(A->ApplyFriction(adhesion, aColPoints[i]))
@ -1560,7 +1739,13 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
A->m_vecMoveFriction.y += moveSpeed.y * -0.3f / numCollisions; A->m_vecMoveFriction.y += moveSpeed.y * -0.3f / numCollisions;
A->m_vecTurnFriction += turnSpeed * -0.3f / numCollisions; A->m_vecTurnFriction += turnSpeed * -0.3f / numCollisions;
} }
if(B->IsObject() && Bobj->m_nCollisionDamageEffect && maxImpulseA > 20.0f)
Bobj->ObjectDamage(maxImpulseA);
if(!CWorld::bSecondShift)
return true; return true;
ret = true;
} }
}else{ }else{
@ -1691,18 +1876,34 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
} }
if(B->IsPed() && A->IsVehicle() && if(B->IsPed() && A->IsVehicle() &&
(!Bped->IsPlayer() || B->bHasHitWall && A->m_vecMoveSpeed.MagnitudeSqr() > 0.0025f)) (!Bped->IsPlayer() || B->bHasHitWall && A->m_vecMoveSpeed.MagnitudeSqr() > SQR(0.05f)))
Bped->KillPedWithCar((CVehicle*)A, maxImpulseB); Bped->KillPedWithCar((CVehicle*)A, maxImpulseB);
else if(B->GetModelIndex() == MI_TRAIN && A->IsPed() && else if(B->GetModelIndex() == MI_TRAIN && A->IsPed() &&
(!Aped->IsPlayer() || A->bHasHitWall)) (!Aped->IsPlayer() || A->bHasHitWall))
Aped->KillPedWithCar((CVehicle*)B, maxImpulseA*2.0f); Aped->KillPedWithCar((CVehicle*)B, maxImpulseA*2.0f);
else if(B->IsObject() && B->bUsesCollision && A->IsVehicle()){ else if(B->IsObject() && B->bUsesCollision && A->IsVehicle()){
// BUG? not impulseA?
if(Bobj->m_nCollisionDamageEffect && maxImpulseB > 20.0f) if(Bobj->m_nCollisionDamageEffect && maxImpulseB > 20.0f)
Bobj->ObjectDamage(maxImpulseB); Bobj->ObjectDamage(maxImpulseB);
else if(Bobj->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY){
CMatrix inv;
CVector size = CModelInfo::GetModelInfo(B->GetModelIndex())->GetColModel()->boundingBox.GetSize();
size = B->GetMatrix() * size;
if(size.z < B->GetPosition().z ||
(Invert(A->GetMatrix(), inv) * size).z < 0.0f)
Bobj->ObjectDamage(50.0f);
}
}else if(A->IsObject() && A->bUsesCollision && B->IsVehicle()){ }else if(A->IsObject() && A->bUsesCollision && B->IsVehicle()){
// BUG? not impulseA?
if(Aobj->m_nCollisionDamageEffect && maxImpulseB > 20.0f) if(Aobj->m_nCollisionDamageEffect && maxImpulseB > 20.0f)
Aobj->ObjectDamage(maxImpulseB); Aobj->ObjectDamage(maxImpulseB);
else if(Aobj->m_nCollisionDamageEffect >= DAMAGE_EFFECT_SMASH_COMPLETELY){
CMatrix inv;
CVector size = CModelInfo::GetModelInfo(A->GetModelIndex())->GetColModel()->boundingBox.GetSize();
size = A->GetMatrix() * size;
if(size.z < A->GetPosition().z ||
(Invert(B->GetMatrix(), inv) * size).z < 0.0f)
Aobj->ObjectDamage(50.0f);
}
} }
if(B->GetStatus() == STATUS_SIMPLE){ if(B->GetStatus() == STATUS_SIMPLE){
@ -1711,13 +1912,15 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
CCarCtrl::SwitchVehicleToRealPhysics((CVehicle*)B); CCarCtrl::SwitchVehicleToRealPhysics((CVehicle*)B);
} }
if(!CWorld::bSecondShift)
return true; return true;
ret = true;
} }
} }
} }
return false; return ret;
} }
bool bool
@ -1746,6 +1949,8 @@ CPhysical::CheckCollision_SimpleCar(void)
return false; return false;
} }
float PHYSICAL_SHIFT_SPEED_DAMP = 0.707f;
void void
CPhysical::ProcessShift(void) CPhysical::ProcessShift(void)
{ {
@ -1755,6 +1960,13 @@ CPhysical::ProcessShift(void)
bIsInSafePosition = true; bIsInSafePosition = true;
RemoveAndAdd(); RemoveAndAdd();
}else{ }else{
CPhysical *surf;
if(bHasHitWall && IsPed() && (surf = ((CPed*)this)->m_pCurrentPhysSurface, surf == nil || !surf->bInfiniteMass || surf->m_phy_flagA08) ||
CWorld::bSecondShift){
m_vecMoveSpeed *= Pow(PHYSICAL_SHIFT_SPEED_DAMP, CTimer::GetTimeStep());
m_vecTurnSpeed *= Pow(PHYSICAL_SHIFT_SPEED_DAMP, CTimer::GetTimeStep());
}
CMatrix matrix(GetMatrix()); CMatrix matrix(GetMatrix());
ApplyMoveSpeed(); ApplyMoveSpeed();
ApplyTurnSpeed(); ApplyTurnSpeed();
@ -1766,14 +1978,22 @@ CPhysical::ProcessShift(void)
m_bIsVehicleBeingShifted = true; m_bIsVehicleBeingShifted = true;
CEntryInfoNode *node; CEntryInfoNode *node;
bool hasshifted = false; // whatever that means... bool hasshifted = false;
for(node = m_entryInfoList.first; node; node = node->next) for(node = m_entryInfoList.first; node; node = node->next)
hasshifted |= ProcessShiftSectorList(node->sector->m_lists); hasshifted |= ProcessShiftSectorList(node->sector->m_lists);
m_bIsVehicleBeingShifted = false; m_bIsVehicleBeingShifted = false;
if(hasshifted){ if(hasshifted){
CWorld::AdvanceCurrentScanCode(); CWorld::AdvanceCurrentScanCode();
bool hadCollision = false;
for(node = m_entryInfoList.first; node; node = node->next) for(node = m_entryInfoList.first; node; node = node->next)
if(ProcessCollisionSectorList(node->sector->m_lists)){ if(ProcessCollisionSectorList(node->sector->m_lists)){
if(!CWorld::bSecondShift){
GetMatrix() = matrix;
return;
}
hadCollision = true;
}
if(hadCollision){
GetMatrix() = matrix; GetMatrix() = matrix;
return; return;
} }
@ -1788,6 +2008,9 @@ CPhysical::ProcessShift(void)
// x is the number of units (m) we would like to step // x is the number of units (m) we would like to step
#define NUMSTEPS(x) ceil(Sqrt(distSq) * (1.0f/(x))) #define NUMSTEPS(x) ceil(Sqrt(distSq) * (1.0f/(x)))
float HIGHSPEED_ELASTICITY_MULT_PED = 2.0f;
float HIGHSPEED_ELASTICITY_MULT_COPCAR = 2.0f;
void void
CPhysical::ProcessCollision(void) CPhysical::ProcessCollision(void)
{ {
@ -1819,31 +2042,78 @@ CPhysical::ProcessCollision(void)
// Save current state // Save current state
CMatrix savedMatrix(GetMatrix()); CMatrix savedMatrix(GetMatrix());
float savedElasticity = m_fElasticity;
CVector savedMoveSpeed = m_vecMoveSpeed;
float savedTimeStep = CTimer::GetTimeStep(); float savedTimeStep = CTimer::GetTimeStep();
int8 n = 1; // The number of steps we divide the time step into int8 n = 1; // The number of steps we divide the time step into
float step = 0.0f; // divided time step float step = 0.0f; // divided time step
float distSq = GetDistanceSq(); float distSq = m_vecMoveSpeed.MagnitudeSqr() * sq(CTimer::GetTimeStep());
if(IsPed() && (distSq >= sq(0.2f) || ped->IsPlayer())){ if(IsPed() && (distSq >= sq(0.3f) || ped->IsPlayer())){
if(ped->IsPlayer()) if(ped->IsPlayer()){
n = Max(NUMSTEPS(0.2f), 2.0f); if(ped->m_pCurrentPhysSurface)
n = Max(NUMSTEPS(0.15f), 4.0f);
else else
n = NUMSTEPS(0.3f); n = Max(NUMSTEPS(0.3f), 2.0f);
}else
n = NUMSTEPS(0.45f);
step = savedTimeStep / n; step = savedTimeStep / n;
if(!ped->IsPlayer())
ped->m_fElasticity *= HIGHSPEED_ELASTICITY_MULT_PED;
}else if(IsVehicle() && distSq >= sq(0.4f)){ }else if(IsVehicle() && distSq >= sq(0.4f)){
if(GetStatus() == STATUS_PLAYER) if(GetStatus() == STATUS_PLAYER)
n = NUMSTEPS(0.2f); n = NUMSTEPS(0.2f);
else else
n = distSq > 0.32f ? NUMSTEPS(0.3f) : NUMSTEPS(0.4f); n = distSq > 0.32f ? NUMSTEPS(0.3f) : NUMSTEPS(0.4f);
step = savedTimeStep / n; step = savedTimeStep / n;
}else if(IsObject()){
CVector bbox = GetColModel()->boundingBox.GetSize();
float relDistX = Abs(DotProduct(m_vecMoveSpeed, GetRight())) * CTimer::GetTimeStep() / bbox.x;
float relDistY = Abs(DotProduct(m_vecMoveSpeed, GetForward())) * CTimer::GetTimeStep() / bbox.y;
float relDistZ = Abs(DotProduct(m_vecMoveSpeed, GetUp())) * CTimer::GetTimeStep() / bbox.z;
if(Max(relDistX, Max(relDistY, relDistZ)) < 1.0f){
// check if we can get away with simplified processing
ApplyMoveSpeed();
ApplyTurnSpeed();
GetMatrix().Reorthogonalise();
bSkipLineCol = false;
m_bIsVehicleBeingShifted = false;
bJustCheckCollision = true;
bUsesCollision = false;
if(!CheckCollision()){
bJustCheckCollision = false;
bUsesCollision = true;
if(IsVehicle())
((CVehicle*)this)->bVehicleColProcessed = true;
bHitByTrain = false;
m_fDistanceTravelled = (GetPosition() - savedMatrix.GetPosition()).Magnitude();
bSkipLineCol = false;
bIsStuck = false;
bIsInSafePosition = true;
m_fElasticity = savedElasticity;
RemoveAndAdd();
return;
}
bJustCheckCollision = false;
bUsesCollision = true;
GetMatrix() = savedMatrix;
m_vecMoveSpeed = savedMoveSpeed;
if(IsVehicle() && ((CVehicle*)this)->bIsLawEnforcer)
m_fElasticity *= HIGHSPEED_ELASTICITY_MULT_COPCAR;
}
}else if(IsObject() && ((CObject*)this)->ObjectCreatedBy != TEMP_OBJECT){
int responsecase = ((CObject*)this)->m_nSpecialCollisionResponseCases; int responsecase = ((CObject*)this)->m_nSpecialCollisionResponseCases;
if(responsecase == COLLRESPONSE_LAMPOST){ if(responsecase == COLLRESPONSE_LAMPOST){
CVector speedUp = { 0.0f, 0.0f, 0.0f }; CVector speedUp = { 0.0f, 0.0f, 0.0f };
CVector speedDown = { 0.0f, 0.0f, 0.0f }; CVector speedDown = { 0.0f, 0.0f, 0.0f };
speedUp.z = GetBoundRadius(); CColModel *colModel = GetColModel();
speedDown.z = -speedUp.z; speedUp.z = colModel->boundingBox.max.z;
speedDown.z = colModel->boundingBox.min.z;
speedUp = Multiply3x3(GetMatrix(), speedUp); speedUp = Multiply3x3(GetMatrix(), speedUp);
speedDown = Multiply3x3(GetMatrix(), speedDown); speedDown = Multiply3x3(GetMatrix(), speedDown);
speedUp = GetSpeed(speedUp); speedUp = GetSpeed(speedUp);
@ -1883,6 +2153,7 @@ CPhysical::ProcessCollision(void)
savedMatrix.GetPosition().z = GetPosition().z; savedMatrix.GetPosition().z = GetPosition().z;
GetMatrix() = savedMatrix; GetMatrix() = savedMatrix;
CTimer::SetTimeStep(savedTimeStep); CTimer::SetTimeStep(savedTimeStep);
m_fElasticity = savedElasticity;
return; return;
} }
if(IsPed() && m_vecMoveSpeed.z == 0.0f && if(IsPed() && m_vecMoveSpeed.z == 0.0f &&
@ -1900,7 +2171,7 @@ CPhysical::ProcessCollision(void)
car->m_aSuspensionSpringRatio[2] = 1.0f; car->m_aSuspensionSpringRatio[2] = 1.0f;
car->m_aSuspensionSpringRatio[3] = 1.0f; car->m_aSuspensionSpringRatio[3] = 1.0f;
}else if(veh->m_vehType == VEHICLE_TYPE_BIKE){ }else if(veh->m_vehType == VEHICLE_TYPE_BIKE){
assert(0 && "TODO - but unused"); assert(0 && "TODO(MIAMI)");
} }
} }
} }
@ -1913,11 +2184,14 @@ CPhysical::ProcessCollision(void)
if(!m_vecMoveSpeed.IsZero() || if(!m_vecMoveSpeed.IsZero() ||
!m_vecTurnSpeed.IsZero() || !m_vecTurnSpeed.IsZero() ||
bHitByTrain || bHitByTrain ||
GetStatus() == STATUS_PLAYER || IsPed() && ped->IsPlayer()){ GetStatus() == STATUS_PLAYER ||
IsVehicle() && ((CVehicle*)this)->bRestingOnPhysical ||
IsPed() && ped->IsPlayer()){
if(IsVehicle()) if(IsVehicle())
((CVehicle*)this)->bVehicleColProcessed = true; ((CVehicle*)this)->bVehicleColProcessed = true;
if(CheckCollision()){ if(CheckCollision()){
GetMatrix() = savedMatrix; GetMatrix() = savedMatrix;
m_fElasticity = savedElasticity;
return; return;
} }
} }
@ -1927,5 +2201,6 @@ CPhysical::ProcessCollision(void)
bIsStuck = false; bIsStuck = false;
bIsInSafePosition = true; bIsInSafePosition = true;
m_fElasticity = savedElasticity;
RemoveAndAdd(); RemoveAndAdd();
} }

View File

@ -18,8 +18,7 @@ public:
// The not properly indented fields haven't been checked properly yet // The not properly indented fields haven't been checked properly yet
int32 m_audioEntityId; int32 m_audioEntityId;
float unk1; float m_phys_unused1;
CTreadable *m_treadable[2]; // car and ped
uint32 m_nLastTimeCollided; uint32 m_nLastTimeCollided;
CVector m_vecMoveSpeed; // velocity CVector m_vecMoveSpeed; // velocity
CVector m_vecTurnSpeed; // angular velocity CVector m_vecTurnSpeed; // angular velocity
@ -37,16 +36,15 @@ public:
CEntryInfoList m_entryInfoList; CEntryInfoList m_entryInfoList;
CPtrNode *m_movingListNode; CPtrNode *m_movingListNode;
char field_EC; int8 m_phys_unused2;
uint8 m_nStaticFrames; uint8 m_nStaticFrames;
uint8 m_nCollisionRecords; uint8 m_nCollisionRecords;
bool m_bIsVehicleBeingShifted;
CEntity *m_aCollisionRecords[PHYSICAL_MAX_COLLISIONRECORDS]; CEntity *m_aCollisionRecords[PHYSICAL_MAX_COLLISIONRECORDS];
float m_fDistanceTravelled; float m_fDistanceTravelled;
// damaged piece // damaged piece
float m_fDamageImpulse; // fCollisionPower float m_fDamageImpulse;
CEntity *m_pDamageEntity; CEntity *m_pDamageEntity;
CVector m_vecDamageNormal; CVector m_vecDamageNormal;
int16 m_nDamagePieceType; int16 m_nDamagePieceType;
@ -54,12 +52,17 @@ public:
uint8 bIsHeavy : 1; uint8 bIsHeavy : 1;
uint8 bAffectedByGravity : 1; uint8 bAffectedByGravity : 1;
uint8 bInfiniteMass : 1; uint8 bInfiniteMass : 1;
uint8 m_phy_flagA08 : 1;
uint8 bIsInWater : 1; uint8 bIsInWater : 1;
uint8 m_phy_flagA10 : 1; // unused
uint8 m_phy_flagA20 : 1; // unused uint8 m_phy_flagA20 : 1; // unused
uint8 bHitByTrain : 1; uint8 bHitByTrain : 1;
uint8 bSkipLineCol : 1; uint8 bSkipLineCol : 1;
uint8 bIsFrozen : 1;
uint8 bDontLoadCollision : 1;
uint8 m_bIsVehicleBeingShifted : 1; // wrong name - also used on but never set for peds
uint8 bJustCheckCollision : 1; // just see if there is a collision
uint8 m_nSurfaceTouched; uint8 m_nSurfaceTouched;
int8 m_nZoneLevel; int8 m_nZoneLevel;
@ -86,7 +89,6 @@ public:
void RemoveRefsToEntity(CEntity *ent); void RemoveRefsToEntity(CEntity *ent);
static void PlacePhysicalRelativeToOtherPhysical(CPhysical *other, CPhysical *phys, CVector localPos); static void PlacePhysicalRelativeToOtherPhysical(CPhysical *other, CPhysical *phys, CVector localPos);
float GetDistanceSq(void) { return m_vecMoveSpeed.MagnitudeSqr() * sq(CTimer::GetTimeStep()); }
// get speed of point p relative to entity center // get speed of point p relative to entity center
CVector GetSpeed(const CVector &r); CVector GetSpeed(const CVector &r);
CVector GetSpeed(void) { return GetSpeed(CVector(0.0f, 0.0f, 0.0f)); } CVector GetSpeed(void) { return GetSpeed(CVector(0.0f, 0.0f, 0.0f)); }
@ -94,7 +96,7 @@ public:
return 1.0f / (CrossProduct(pos, dir).MagnitudeSqr()/m_fTurnMass + return 1.0f / (CrossProduct(pos, dir).MagnitudeSqr()/m_fTurnMass +
1.0f/m_fMass); 1.0f/m_fMass);
} }
float GetMassTime(const CVector &pos, const CVector &dir, float t) { float GetMassTweak(const CVector &pos, const CVector &dir, float t) {
return 1.0f / (CrossProduct(pos, dir).MagnitudeSqr()/(m_fTurnMass*t) + return 1.0f / (CrossProduct(pos, dir).MagnitudeSqr()/(m_fTurnMass*t) +
1.0f/(m_fMass*t)); 1.0f/(m_fMass*t));
} }
@ -156,11 +158,13 @@ public:
void ApplyFrictionTurnForce(const CVector &j, const CVector &p) { ApplyFrictionTurnForce(j.x, j.y, j.z, p.x, p.y, p.z); } void ApplyFrictionTurnForce(const CVector &j, const CVector &p) { ApplyFrictionTurnForce(j.x, j.y, j.z, p.x, p.y, p.z); }
// springRatio: 1.0 fully extended, 0.0 fully compressed // springRatio: 1.0 fully extended, 0.0 fully compressed
bool ApplySpringCollision(float springConst, CVector &springDir, CVector &point, float springRatio, float bias); bool ApplySpringCollision(float springConst, CVector &springDir, CVector &point, float springRatio, float bias);
bool ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir);
bool ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed); bool ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed);
void ApplyGravity(void); void ApplyGravity(void);
void ApplyFriction(void); void ApplyFriction(void);
void ApplyAirResistance(void); void ApplyAirResistance(void);
bool ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, float &impulseB); bool ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, float &impulseB);
bool ApplyCollision(CColPoint &colpoint, float &impulse);
bool ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CVector &moveSpeed, CVector &turnSpeed); bool ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CVector &moveSpeed, CVector &turnSpeed);
bool ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint); bool ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint);
bool ApplyFriction(float adhesiveLimit, CColPoint &colpoint); bool ApplyFriction(float adhesiveLimit, CColPoint &colpoint);

View File

@ -399,6 +399,18 @@ IsLightThatNeedsRepositioning(int16 id)
id == MI_STREETLAMP2; id == MI_STREETLAMP2;
} }
inline bool
IsLightObject(int16 id)
{
return id == MI_TRAFFICLIGHTS_MIAMI ||
id == MI_MLAMPPOST ||
id == MI_SINGLESTREETLIGHTS1 ||
id == MI_SINGLESTREETLIGHTS2 ||
id == MI_SINGLESTREETLIGHTS3 ||
id == MI_DOUBLESTREETLIGHTS ||
id == MI_TRAFFICLIGHTS_TWOVERTICAL;
}
inline bool inline bool
IsBodyPart(int16 id) IsBodyPart(int16 id)
{ {
@ -455,7 +467,8 @@ inline bool
IsExplosiveThingModel(int16 id) IsExplosiveThingModel(int16 id)
{ {
return id == MI_EXPLODINGBARREL || return id == MI_EXPLODINGBARREL ||
id == MI_PETROLPUMP; id == MI_PETROLPUMP ||
id == MI_PETROLPUMP2;
} }
inline bool inline bool

View File

@ -330,6 +330,8 @@ CObject::Init(void)
m_colour1 = 0; m_colour1 = 0;
m_colour2 = 0; m_colour2 = 0;
m_nBonusValue = 0; m_nBonusValue = 0;
bIsWeapon = false;
// TODO(MIAMI): some new field here
m_pCollidingEntity = nil; m_pCollidingEntity = nil;
CColPoint point; CColPoint point;
CEntity* outEntity = nil; CEntity* outEntity = nil;
@ -342,7 +344,9 @@ CObject::Init(void)
if (GetModelIndex() == MI_BUOY) if (GetModelIndex() == MI_BUOY)
bTouchingWater = true; bTouchingWater = true;
// TODO(Miami): Second flag set initialization if(CModelInfo::GetModelInfo(GetModelIndex())->GetModelType() == MITYPE_WEAPON)
bIsWeapon = true;
bIsStreetLight = IsLightObject(GetModelIndex());
m_area = AREA_EVERYWHERE; m_area = AREA_EVERYWHERE;
} }

View File

@ -59,26 +59,23 @@ public:
CMatrix m_objectMatrix; CMatrix m_objectMatrix;
float m_fUprootLimit; float m_fUprootLimit;
int8 ObjectCreatedBy; int8 ObjectCreatedBy;
int8 bIsPickup : 1; uint8 bIsPickup : 1;
int8 bPickupObjWithMessage : 1; uint8 obj_flag_02 : 1;
int8 bOutOfStock : 1; uint8 bPickupObjWithMessage : 1;
int8 bGlassCracked : 1; uint8 bOutOfStock : 1;
int8 bGlassBroken : 1; uint8 bGlassCracked : 1;
int8 bHasBeenDamaged : 1; uint8 bGlassBroken : 1;
int8 bUseVehicleColours : 1; uint8 bHasBeenDamaged : 1;
uint8 bUseVehicleColours : 1;
uint8 bIsWeapon : 1;
uint8 bIsStreetLight : 1;
int8 m_nBonusValue; int8 m_nBonusValue;
float m_fCollisionDamageMultiplier; float m_fCollisionDamageMultiplier;
uint8 m_nCollisionDamageEffect; uint8 m_nCollisionDamageEffect;
uint8 m_nSpecialCollisionResponseCases; uint8 m_nSpecialCollisionResponseCases;
bool m_bCameraToAvoidThisObject; bool m_bCameraToAvoidThisObject;
int8 m_nBeachballBounces;
// this batch is unused uint32 m_obj_unused1;
int8 field_17B;
int8 field_17C;
int8 field_17D;
int8 field_17E;
int8 field_17F;
uint32 m_nEndOfLifeTime; uint32 m_nEndOfLifeTime;
int16 m_nRefModelIndex; int16 m_nRefModelIndex;
CEntity *m_pCurSurface; CEntity *m_pCurSurface;
@ -86,8 +83,6 @@ public:
int8 m_colour1, m_colour2; int8 m_colour1, m_colour2;
static int16 nNoTempObjects; static int16 nNoTempObjects;
// static int16 nBodyCastHealth;
static float fDistToNearestTree; static float fDistToNearestTree;
static void *operator new(size_t); static void *operator new(size_t);

View File

@ -59,6 +59,7 @@
#include "Floater.h" #include "Floater.h"
#include "Streaming.h" #include "Streaming.h"
#include "PedAttractor.h" #include "PedAttractor.h"
#include "Debug.h"
#define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f) #define CAN_SEE_ENTITY_ANGLE_THRESHOLD DEGTORAD(60.0f)

View File

@ -466,7 +466,7 @@ public:
//uint32 b158_1 //uint32 b158_1
//uint32 b158_2 //uint32 b158_2
//uint32 b158_4 uint32 b158_4 : 1;
//uint32 b158_8 //uint32 b158_8
//uint32 b158_10 //uint32 b158_10
//uint32 b158_20 //uint32 b158_20

View File

@ -155,7 +155,7 @@ public:
static float GetSpriteSize(void) { return m_fCurrentSpriteSize; } static float GetSpriteSize(void) { return m_fCurrentSpriteSize; }
static int GetShadowStrength(void) { return m_nCurrentShadowStrength; } static int GetShadowStrength(void) { return m_nCurrentShadowStrength; }
static int GetLightShadowStrength(void) { return m_nCurrentLightShadowStrength; } static int GetLightShadowStrength(void) { return m_nCurrentLightShadowStrength; }
static int GetLightOnGroundBrightness(void) { return m_fCurrentLightsOnGroundBrightness; } static float GetLightOnGroundBrightness(void) { return m_fCurrentLightsOnGroundBrightness; }
static float GetFarClip(void) { return m_fCurrentFarClip; } static float GetFarClip(void) { return m_fCurrentFarClip; }
static float GetFogStart(void) { return m_fCurrentFogStart; } static float GetFogStart(void) { return m_fCurrentFogStart; }

View File

@ -83,7 +83,7 @@ CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner)
bIsInWater = true; bIsInWater = true;
unk1 = 0.0f; m_phys_unused1 = 0.0f;
m_bIsAnchored = true; m_bIsAnchored = true;
m_fOrientation = INVALID_ORIENTATION; m_fOrientation = INVALID_ORIENTATION;
bTouchingWater = true; bTouchingWater = true;

View File

@ -127,6 +127,9 @@ CVehicle::CVehicle(uint8 CreatedBy)
AutoPilot.m_bStayInCurrentLevel = false; AutoPilot.m_bStayInCurrentLevel = false;
AutoPilot.m_bIgnorePathfinding = false; AutoPilot.m_bIgnorePathfinding = false;
AutoPilot.m_nSwitchDistance = 20; AutoPilot.m_nSwitchDistance = 20;
// TODO(MIAMI)
bRestingOnPhysical = false;
} }
CVehicle::~CVehicle() CVehicle::~CVehicle()

View File

@ -189,7 +189,7 @@ public:
uint8 bIsDrowning : 1; // is vehicle occupants taking damage in water (i.e. vehicle is dead in water) uint8 bIsDrowning : 1; // is vehicle occupants taking damage in water (i.e. vehicle is dead in water)
//uint8 bTyresDontBurst : 1; // If this is set the tyres are invincible //uint8 bTyresDontBurst : 1; // If this is set the tyres are invincible
uint8 bCreatedAsPoliceVehicle : 1;// True if this guy was created as a police vehicle (enforcer, policecar, miamivice car etc) uint8 bCreatedAsPoliceVehicle : 1;// True if this guy was created as a police vehicle (enforcer, policecar, miamivice car etc)
//uint8 bRestingOnPhysical : 1; // Dont go static cause car is sitting on a physical object that might get removed uint8 bRestingOnPhysical : 1; // Dont go static cause car is sitting on a physical object that might get removed
uint8 bParking : 1; uint8 bParking : 1;
//uint8 bCanPark : 1; //uint8 bCanPark : 1;