summaryrefslogtreecommitdiffstats
path: root/src/entities
diff options
context:
space:
mode:
Diffstat (limited to 'src/entities')
-rw-r--r--src/entities/Entity.cpp102
-rw-r--r--src/entities/Entity.h21
-rw-r--r--src/entities/Physical.cpp417
-rw-r--r--src/entities/Physical.h20
4 files changed, 451 insertions, 109 deletions
diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp
index b2fcfbc7..ed432e77 100644
--- a/src/entities/Entity.cpp
+++ b/src/entities/Entity.cpp
@@ -1,10 +1,10 @@
#include "common.h"
-#include "VuVector.h"
#include "General.h"
#include "RwHelper.h"
#include "ModelIndices.h"
#include "Timer.h"
+#include "Streaming.h"
#include "Entity.h"
#include "Object.h"
#include "World.h"
@@ -27,6 +27,12 @@
#include "Dummy.h"
#include "WindModifiers.h"
#include "SaveBuf.h"
+#include "SpecialFX.h"
+#include "VisibilityPlugins.h"
+#include "RpAnimBlend.h"
+#include "CutsceneMgr.h"
+
+//--LCS: file done except TODO for distance alpha
int gBuildings;
@@ -79,6 +85,11 @@ CEntity::CEntity(void)
bUnderwater = false;
bHasPreRenderEffects = false;
+ bIsTreeModel = false;
+ bIsVehicle = false;
+ bIsPed = false;
+ bMakeVisible = false;
+
m_scanCode = 0;
m_modelIndex = -1;
m_rwObject = nil;
@@ -97,6 +108,8 @@ void
CEntity::SetModelIndex(uint32 id)
{
m_modelIndex = id;
+ bIsTreeModel = IsTreeModel(m_modelIndex);
+ bDrawLast |= bIsTreeModel;
bHasPreRenderEffects = HasPreRenderEffects();
CreateRwObject();
}
@@ -105,6 +118,8 @@ void
CEntity::SetModelIndexNoCreate(uint32 id)
{
m_modelIndex = id;
+ bIsTreeModel = IsTreeModel(m_modelIndex);
+ bDrawLast |= bIsTreeModel;
bHasPreRenderEffects = HasPreRenderEffects();
}
@@ -127,6 +142,7 @@ CEntity::CreateRwObject(void)
else if(RwObjectGetType(m_rwObject) == rpCLUMP)
GetMatrix().AttachRW(RwFrameGetMatrix(RpClumpGetFrame((RpClump *)m_rwObject)), false);
+ // useless IsTextureLoaded();
mi->AddRef();
}
}
@@ -183,9 +199,11 @@ CEntity::DeleteRwObject(void)
if(m_rwObject){
if(RwObjectGetType(m_rwObject) == rpATOMIC){
f = RpAtomicGetFrame((RpAtomic*)m_rwObject);
+ CStreaming::UnregisterInstance((RpAtomic*)m_rwObject, nil);
RpAtomicDestroy((RpAtomic*)m_rwObject);
RwFrameDestroy(f);
}else if(RwObjectGetType(m_rwObject) == rpCLUMP){
+ CStreaming::UnregisterInstance((RpClump*)m_rwObject);
if(IsClumpSkinned((RpClump*)m_rwObject))
RpClumpForAllAtomics((RpClump*)m_rwObject, AtomicRemoveAnimFromSkinCB, nil);
RpClumpDestroy((RpClump*)m_rwObject);
@@ -251,9 +269,18 @@ CEntity::UpdateRwFrame(void)
RwFrameUpdateObjects((RwFrame*)rwObjectGetParent(m_rwObject));
}
+bool
+PauseEntityAnims(void)
+{
+ return CSpecialFX::bSnapShotActive;
+}
+
void
CEntity::UpdateRpHAnim(void)
{
+ if(PauseEntityAnims())
+ return;
+
if(IsClumpSkinned(GetClump())){
RpHAnimHierarchy *hier = GetAnimHierarchyFromSkinClump(GetClump());
RpHAnimHierarchyUpdateMatrices(hier);
@@ -315,9 +342,10 @@ CEntity::PreRender(void)
if(!bHasPreRenderEffects)
return;
+ // separate function in LCS but we don't know the name
switch(m_type){
case ENTITY_TYPE_BUILDING:
- if(IsTreeModel(GetModelIndex())){
+ if(bIsTreeModel){
float dist = (TheCamera.GetPosition() - GetPosition()).Magnitude2D();
CObject::fDistToNearestTree = Min(CObject::fDistToNearestTree, dist);
ModifyMatrixForTreeInWind();
@@ -416,12 +444,53 @@ void
CEntity::Render(void)
{
if(m_rwObject){
- bImBeingRendered = true;
- if(RwObjectGetType(m_rwObject) == rpATOMIC)
- RpAtomicRender((RpAtomic*)m_rwObject);
- else
- RpClumpRender((RpClump*)m_rwObject);
- bImBeingRendered = false;
+#ifdef VIS_DISTANCE_ALPHA
+ if(CVisibilityPlugins::GetObjectDistanceAlpha(m_rwObject) != 0)
+#endif
+ {
+ // TODO(LCS): LCS does not use bImBeingRendered here,
+ // but that may be due to the streamed world. better keep it for safety
+ bImBeingRendered = true;
+ if(RwObjectGetType(m_rwObject) == rpATOMIC)
+ RpAtomicRender((RpAtomic*)m_rwObject);
+ else
+ RpClumpRender((RpClump*)m_rwObject);
+ bImBeingRendered = false;
+ }
+ }
+}
+
+#ifdef VIS_DISTANCE_ALPHA
+void
+CEntity::UpdateDistanceFade(void)
+{
+ // bDistanceFade is only valid when entity is in alpha list
+ // but we're always checking it here, see fix in CRenderer
+ int alpha = CVisibilityPlugins::GetObjectDistanceAlpha(m_rwObject);
+ if(CCutsceneMgr::IsRunning() || TheCamera.WorldViewerBeingUsed)
+ alpha = 255;
+ else if(bDistanceFade)
+ alpha = Max(alpha-16, 0);
+ else if(alpha < 255)
+ alpha = Min(alpha+32, 255);
+ CVisibilityPlugins::SetObjectDistanceAlpha(m_rwObject, alpha);
+}
+#endif
+
+void
+CEntity::UpdateAnim(void)
+{
+ if(PauseEntityAnims())
+ return;
+
+ if(m_rwObject && RwObjectGetType(m_rwObject) == rpCLUMP && RpAnimBlendClumpGetFirstAssociation(GetClump())) {
+ if (IsObject())
+ RpAnimBlendClumpUpdateAnimations(GetClump(), CTimer::GetTimeStepNonClippedInSeconds());
+ else {
+ if (!bOffscreen)
+ bOffscreen = !GetIsOnScreen();
+ RpAnimBlendClumpUpdateAnimations(GetClump(), CTimer::GetTimeStepInSeconds(), !bOffscreen);
+ }
}
}
@@ -434,6 +503,12 @@ CEntity::GetIsTouching(CVUVECTOR const &center, float radius)
}
bool
+CEntity::GetIsTouching(CEntity *other)
+{
+ return sq(GetBoundRadius()+other->GetBoundRadius()) > (GetBoundCentre()-other->GetBoundCentre()).MagnitudeSqr();
+}
+
+bool
CEntity::IsVisible(void)
{
return m_rwObject && bIsVisible && GetIsOnScreen();
@@ -634,10 +709,15 @@ CEntity::SetupBigBuilding(void)
m_level = CTheZones::GetLevelFromPosition(&GetPosition());
if(mi->m_lodDistances[0] <= 2000.0f)
bStreamBIGBuilding = true;
- if(mi->m_lodDistances[0] > 2500.0f || mi->m_ignoreDrawDist)
+ if(m_modelIndex == islandLODindust ||
+ m_modelIndex == islandLODcomInd ||
+ m_modelIndex == islandLODcomSub ||
+ m_modelIndex == islandLODsubInd ||
+ m_modelIndex == islandLODsubCom ||
+ mi->m_lodDistances[0] > 5000.0f || mi->m_ignoreDrawDist)
m_level = LEVEL_GENERIC;
- else if(m_level == LEVEL_GENERIC)
- printf("%s isn't in a level\n", mi->GetModelName());
+// else if(m_level == LEVEL_GENERIC)
+// printf("%s isn't in a level\n", mi->GetModelName());
}
float WindTabel[] = {
diff --git a/src/entities/Entity.h b/src/entities/Entity.h
index 957ee3bf..6f948d49 100644
--- a/src/entities/Entity.h
+++ b/src/entities/Entity.h
@@ -14,6 +14,7 @@ enum eEntityType
ENTITY_TYPE_PED,
ENTITY_TYPE_OBJECT,
ENTITY_TYPE_DUMMY,
+ ENTITY_TYPE_MULTIPLAYER
};
enum eEntityStatus
@@ -26,6 +27,8 @@ enum eEntityStatus
STATUS_WRECKED,
STATUS_TRAIN_MOVING,
STATUS_TRAIN_NOT_MOVING,
+ STATUS_FERRY_MOVING,
+ STATUS_FERRY_NOT_MOVING,
STATUS_HELI,
STATUS_PLANE,
STATUS_PLAYER_REMOTE,
@@ -43,6 +46,7 @@ private:
uint32 m_status : 5;
public:
// flagsA
+ // LCS flagsB 02
uint32 bUsesCollision : 1; // does entity use collision
uint32 bCollisionProcessed : 1; // has object been processed by a ProcessEntityCollision function
uint32 bIsStatic : 1; // is entity static
@@ -50,6 +54,7 @@ public:
uint32 bPedPhysics : 1;
uint32 bIsStuck : 1; // is entity stuck
uint32 bIsInSafePosition : 1; // is entity in a collision free safe position
+ // LCS flagsC
uint32 bUseCollisionRecords : 1;
// flagsB
@@ -60,6 +65,7 @@ public:
uint32 bRenderScorched : 1;
uint32 bHasBlip : 1;
uint32 bIsBIGBuilding : 1; // Set if this entity is a big building
+ // LCS flagsD
uint32 bStreamBIGBuilding : 1; // set when draw dist <= 2000
// flagsC
@@ -70,6 +76,7 @@ public:
uint32 bMeleeProof : 1;
uint32 bOnlyDamagedByPlayer : 1;
uint32 bStreamingDontDelete : 1; // Dont let the streaming remove this
+ // LCS flagsE
uint32 bRemoveFromWorld : 1; // remove this entity next time it should be processed
// flagsD
@@ -80,6 +87,7 @@ public:
uint32 bDrawLast : 1; // draw object last
uint32 bNoBrightHeadLights : 1;
uint32 bDoNotRender : 1; //-- only applies to CObjects apparently
+ // LCS flagsF
uint32 bDistanceFade : 1; // Fade entity because it is far away
// flagsE
@@ -91,6 +99,12 @@ public:
uint32 bUnderwater : 1; // this object is underwater change drawing order
uint32 bHasPreRenderEffects : 1; // Object has a prerender effects attached to it
+ // LCS flagsG
+ uint32 bIsTreeModel : 1;
+ uint32 bIsVehicle : 1; // not sure what exactly these two are for
+ uint32 bIsPed : 1;
+ uint32 bMakeVisible : 1;
+
uint16 m_scanCode;
uint16 m_randomSeed;
int16 m_modelIndex;
@@ -118,6 +132,7 @@ public:
virtual void Add(void);
virtual void Remove(void);
+ virtual bool UpdatesInCutscene(void) { return false; }
virtual void SetModelIndex(uint32 id);
virtual void SetModelIndexNoCreate(uint32 id);
virtual void CreateRwObject(void);
@@ -129,6 +144,7 @@ public:
virtual void Teleport(CVector v) {}
virtual void PreRender(void);
virtual void Render(void);
+ virtual void UpdateAnim(void);
virtual bool SetupLighting(void);
virtual void RemoveLighting(bool);
virtual void FlagToDestroyWhenNextProcessed(void) {}
@@ -138,6 +154,7 @@ public:
bool IsPed(void) { return m_type == ENTITY_TYPE_PED; }
bool IsObject(void) { return m_type == ENTITY_TYPE_OBJECT; }
bool IsDummy(void) { return m_type == ENTITY_TYPE_DUMMY; }
+ bool IsMultiplayer(void) { return m_type == ENTITY_TYPE_MULTIPLAYER; }
RpAtomic *GetAtomic(void) {
assert(RwObjectGetType(m_rwObject) == rpATOMIC);
@@ -148,11 +165,15 @@ public:
return (RpClump*)m_rwObject;
}
+#ifdef VIS_DISTANCE_ALPHA
+ void UpdateDistanceFade(void);
+#endif
void GetBoundCentre(CVUVECTOR &out);
CVector GetBoundCentre(void);
float GetBoundRadius(void);
float GetDistanceFromCentreOfMassToBaseOfModel(void);
bool GetIsTouching(CVUVECTOR const &center, float r);
+ bool GetIsTouching(CEntity *other);
bool GetIsOnScreen(void);
bool GetIsOnScreenComplex(void);
bool IsVisible(void);
diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp
index fb796fcd..ef306d5a 100644
--- a/src/entities/Physical.cpp
+++ b/src/entities/Physical.cpp
@@ -20,10 +20,12 @@
#include "Bike.h"
#include "Pickups.h"
#include "Physical.h"
+#include "ColStore.h"
+#include "Script.h"
+
+//--LCS: mostly done
-#ifdef WALLCLIMB_CHEAT
bool gGravityCheat;
-#endif
CPhysical::CPhysical(void)
@@ -82,6 +84,9 @@ CPhysical::CPhysical(void)
bIsFrozen = false;
bDontLoadCollision = false;
+
+ phys_lcs_unk1 = true;
+ phys_lcs_unk2 = 0;
}
CPhysical::~CPhysical(void)
@@ -122,6 +127,9 @@ CPhysical::Add(void)
case ENTITY_TYPE_OBJECT:
list = &s->m_lists[ENTITYLIST_OBJECTS];
break;
+ case ENTITY_TYPE_MULTIPLAYER:
+ list = &s->m_lists[ENTITYLIST_MULTIPLAYER];
+ break;
default:
assert(0);
}else switch(m_type){
@@ -134,6 +142,9 @@ CPhysical::Add(void)
case ENTITY_TYPE_OBJECT:
list = &s->m_lists[ENTITYLIST_OBJECTS_OVERLAP];
break;
+ case ENTITY_TYPE_MULTIPLAYER:
+ list = &s->m_lists[ENTITYLIST_MULTIPLAYER];
+ break;
default:
assert(0);
}
@@ -154,6 +165,37 @@ CPhysical::Remove(void)
}
}
+static void
+MoveVehicleToSafety(CVehicle* pVehicle)
+{
+ if (pVehicle->VehicleCreatedBy != MISSION_VEHICLE) {
+ CVector2D pos = LevelPos(CGame::currLevel);
+ int node = ThePaths.FindNodeClosestToCoors(CVector(pos.x, pos.y, 10.0f), PATH_CAR, 999999.9f, true, true);
+ CVector nodePos = ThePaths.FindNodeCoorsForScript(node);
+ float orientation = ThePaths.FindNodeOrientationForCarPlacement(node);
+ nodePos.x += 0.1f;
+ nodePos.y += 0.1f;
+ pVehicle->Teleport(nodePos + CVector(0.0f, 0.0f, pVehicle->GetDistanceFromCentreOfMassToBaseOfModel()));
+ CTheScripts::ClearSpaceForMissionEntity(nodePos, pVehicle);
+ pVehicle->AutoPilot.m_nCarMission = MISSION_CRUISE;
+ CCarCtrl::JoinCarWithRoadSystem(pVehicle);
+ }
+}
+
+static void
+MovePedToSafety(CPed* pPed)
+{
+ if (pPed->CharCreatedBy == RANDOM_CHAR) {
+ CVector2D pos = LevelPos(CGame::currLevel);
+ int node = ThePaths.FindNodeClosestToCoors(CVector(pos.x, pos.y, 10.0f), PATH_CAR, 999999.9f, true, true);
+ CVector nodePos = ThePaths.FindNodeCoorsForScript(node);
+ nodePos.x += 0.1f;
+ nodePos.y += 0.1f;
+ pPed->Teleport(nodePos + CVector(0.0f, 0.0f, pPed->GetDistanceFromCentreOfMassToBaseOfModel()));
+ CTheScripts::ClearSpaceForMissionEntity(nodePos, pPed);
+ }
+}
+
void
CPhysical::RemoveAndAdd(void)
{
@@ -169,10 +211,53 @@ CPhysical::RemoveAndAdd(void)
ystart = CWorld::GetSectorIndexY(bounds.top);
yend = CWorld::GetSectorIndexY(bounds.bottom);
ymid = CWorld::GetSectorIndexY((bounds.top + bounds.bottom)/2.0f);
- assert(xstart >= 0);
- assert(xend < NUMSECTORS_X);
- assert(ystart >= 0);
- assert(yend < NUMSECTORS_Y);
+ //assert(xstart >= 0);
+ //assert(xend < NUMSECTORS_X);
+ //assert(ystart >= 0);
+ //assert(yend < NUMSECTORS_Y);
+
+ // this is basically a replacement for the asserts above
+ if (xstart < 0 || xstart >= NUMSECTORS_X || ystart < 0 || ystart >= NUMSECTORS_Y) {
+ printf("*****************************\n");
+ printf("ENTITY GONE OUT OF WORLD! :(\n");
+ printf("model id = %d\n", GetModelIndex());
+ printf("type = %d\n", GetType());
+ printf("bound cent = %f %f %f\n",
+ (GetMatrix() * GetColModel()->boundingSphere.center).x,
+ (GetMatrix() * GetColModel()->boundingSphere.center).y,
+ (GetMatrix() * GetColModel()->boundingSphere.center).z);
+ switch (GetType()) {
+ case ENTITY_TYPE_PED:
+ printf("ped created by = %d\n", ((CPed*)this)->CharCreatedBy);
+ break;
+ case ENTITY_TYPE_VEHICLE:
+ printf("vehcile created by = %d\n", ((CVehicle*)this)->VehicleCreatedBy);
+ break;
+ case ENTITY_TYPE_OBJECT:
+ printf("object created by = %d\n", ((CObject*)this)->ObjectCreatedBy);
+ break;
+ case ENTITY_TYPE_DUMMY:
+ printf("no dummy created by info\n");
+ break;
+ default:
+ printf("unknown entity type to be out of world??\n");
+ }
+ printf("*****************************\n");
+ if (GetType() == ENTITY_TYPE_VEHICLE){
+ MoveVehicleToSafety((CVehicle*)this);
+ }
+ else if (GetType() == ENTITY_TYPE_PED) {
+ CPed* pThisPed = ((CPed*)this);
+ if (pThisPed->bInVehicle && pThisPed->m_pMyVehicle)
+ MoveVehicleToSafety(pThisPed->m_pMyVehicle);
+ else if (GetType() == ENTITY_TYPE_PED) // why?
+ MovePedToSafety(pThisPed);
+ else
+ return;
+ }
+ else
+ return;
+ }
// we'll try to recycle nodes from here
CEntryInfoNode *next = m_entryInfoList.first;
@@ -190,6 +275,9 @@ CPhysical::RemoveAndAdd(void)
case ENTITY_TYPE_OBJECT:
list = &s->m_lists[ENTITYLIST_OBJECTS];
break;
+ case ENTITY_TYPE_MULTIPLAYER:
+ list = &s->m_lists[ENTITYLIST_MULTIPLAYER];
+ break;
}else switch(m_type){
case ENTITY_TYPE_VEHICLE:
list = &s->m_lists[ENTITYLIST_VEHICLES_OVERLAP];
@@ -200,6 +288,9 @@ CPhysical::RemoveAndAdd(void)
case ENTITY_TYPE_OBJECT:
list = &s->m_lists[ENTITYLIST_OBJECTS_OVERLAP];
break;
+ case ENTITY_TYPE_MULTIPLAYER:
+ list = &s->m_lists[ENTITYLIST_MULTIPLAYER];
+ break;
}
if(next){
// If we still have old nodes, use them
@@ -236,7 +327,7 @@ CPhysical::GetBoundRect(void)
void
CPhysical::AddToMovingList(void)
{
- if (!bIsStaticWaitingForCollision)
+ if (m_movingListNode == nil && !bIsStaticWaitingForCollision)
m_movingListNode = CWorld::GetMovingEntityList().InsertItem(this);
}
@@ -334,6 +425,8 @@ CPhysical::PlacePhysicalRelativeToOtherPhysical(CPhysical *other, CPhysical *phy
int32
CPhysical::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints)
{
+ if(!GetIsTouching(ent))
+ return 0;
int32 numSpheres = CCollision::ProcessColModels(
GetMatrix(), *GetColModel(),
ent->GetMatrix(), *ent->GetColModel(),
@@ -430,7 +523,7 @@ CPhysical::ApplyTurnSpeed(void)
{
if(bIsFrozen){
m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f);
- }else{
+ }else if(!m_vecTurnSpeed.IsZero()){
// Move the coordinate axes by their speed
// Note that this denormalizes the matrix
CVector turnvec = m_vecTurnSpeed*CTimer::GetTimeStep();
@@ -444,6 +537,9 @@ void
CPhysical::ApplyMoveForce(float jx, float jy, float jz)
{
m_vecMoveSpeed += CVector(jx, jy, jz)*(1.0f/m_fMass);
+ m_vecTurnSpeed.x = Clamp(m_vecTurnSpeed.x, -4.0f, 4.0f);
+ m_vecTurnSpeed.y = Clamp(m_vecTurnSpeed.y, -4.0f, 4.0f);
+ m_vecTurnSpeed.z = Clamp(m_vecTurnSpeed.z, -4.0f, 4.0f);
}
void
@@ -452,6 +548,23 @@ CPhysical::ApplyTurnForce(float jx, float jy, float jz, float px, float py, floa
CVector com = Multiply3x3(GetMatrix(), m_vecCentreOfMass);
CVector turnimpulse = CrossProduct(CVector(px, py, pz)-com, CVector(jx, jy, jz));
m_vecTurnSpeed += turnimpulse*(1.0f/m_fTurnMass);
+ m_vecTurnSpeed.x = Clamp(m_vecTurnSpeed.x, -4.0f, 4.0f);
+ m_vecTurnSpeed.y = Clamp(m_vecTurnSpeed.y, -4.0f, 4.0f);
+ m_vecTurnSpeed.z = Clamp(m_vecTurnSpeed.z, -4.0f, 4.0f);
+}
+
+void
+CPhysical::ApplyTurnForceMultiplayer(const CVector &j, const CVector &p)
+{
+ CVector com = Multiply3x3(GetMatrix(), m_vecCentreOfMass);
+ CVector turnimpulse = CrossProduct(p-com, j);
+ turnimpulse *= (1.0f/m_fTurnMass);
+ m_vecTurnSpeed.x += Clamp(turnimpulse.x, -0.1f, 0.1f);
+ m_vecTurnSpeed.y += Clamp(turnimpulse.y, -0.1f, 0.1f);
+ m_vecTurnSpeed.z += Clamp(turnimpulse.z, -0.1f, 0.1f);
+ m_vecTurnSpeed.x = Clamp(m_vecTurnSpeed.x, -1.0f, 1.0f);
+ m_vecTurnSpeed.y = Clamp(m_vecTurnSpeed.y, -1.0f, 1.0f);
+ m_vecTurnSpeed.z = Clamp(m_vecTurnSpeed.z, -1.0f, 1.0f);
}
void
@@ -482,14 +595,14 @@ CPhysical::ApplySpringCollision(float springConst, CVector &springDir, CVector &
}
bool
-CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir)
+CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir, float &impulse)
{
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;
+ impulse = GRAVITY*m_fMass*step * springConst * compression * bias*2.0f;
if(bIsHeavy)
impulse *= 0.75f;
ApplyMoveForce(forceDir*impulse);
@@ -498,9 +611,12 @@ CPhysical::ApplySpringCollisionAlt(float springConst, CVector &springDir, CVecto
return true;
}
+float DAMPING_LIMIT_OF_SPRING_FORCE = 0.999f;
+float DAMPING_LIMIT_IN_FRAME= 0.25f;
+
// What exactly is speed?
bool
-CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed)
+CPhysical::ApplySpringDampening(float damping, float dampingLimit, CVector &springDir, CVector &point, CVector &speed)
{
float speedA = DotProduct(speed, springDir);
float speedB = DotProduct(GetSpeed(point), springDir);
@@ -509,16 +625,30 @@ CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &poin
return true;
#endif
float step = Min(CTimer::GetTimeStep(), 3.0f);
- float impulse = -damping * (speedA + speedB)/2.0f * m_fMass * step * 0.53f;
+ damping *= step;
if(bIsHeavy)
- impulse *= 2.0f;
+ damping *= 2.0f;
+ damping = Clamp(damping, -DAMPING_LIMIT_IN_FRAME, DAMPING_LIMIT_IN_FRAME);
// what is this?
- float a = m_fTurnMass / ((point.MagnitudeSqr() + 1.0f) * 2.0f * m_fMass);
- a = Min(a, 1.0f);
- float b = Abs(impulse / (speedB * m_fMass));
- if(a < b)
- impulse *= a/b;
+ float fSpeed = -speedA * damping;
+ if(fSpeed > 0.0f && fSpeed+speedB > 0.0f){
+ if(speedB < 0.0f)
+ fSpeed = -speedB;
+ else
+ fSpeed = 0.0f;
+ }else if(fSpeed < 0.0f && fSpeed+speedB < 0.0f){
+ if(speedB > 0.0f)
+ fSpeed = -speedB;
+ else
+ fSpeed = 0.0f;
+ }
+
+ CVector com = Multiply3x3(m_matrix, m_vecCentreOfMass);
+ float impulse = fSpeed*GetMass(point-com, springDir);
+ float limit = Abs(dampingLimit)*DAMPING_LIMIT_OF_SPRING_FORCE;
+ if(impulse > limit)
+ impulse = limit;
ApplyMoveForce(springDir*impulse);
ApplyTurnForce(springDir*impulse, point);
@@ -530,7 +660,6 @@ CPhysical::ApplyGravity(void)
{
if (!bAffectedByGravity)
return;
-#ifdef WALLCLIMB_CHEAT
if (gGravityCheat && this == FindPlayerVehicle()) {
static CVector gravityUp(0.0f, 0.0f, 1.0f), surfaceUp(0.0f, 0.0f, 1.0f);
CVector belowCar = GetPosition() - 2.0f*GetUp();
@@ -549,7 +678,6 @@ CPhysical::ApplyGravity(void)
m_vecMoveSpeed -= GRAVITY * CTimer::GetTimeStep() * gravityUp;
return;
}
-#endif
m_vecMoveSpeed.z -= GRAVITY * CTimer::GetTimeStep();
}
@@ -569,8 +697,8 @@ CPhysical::ApplyAirResistance(void)
float f = Pow(m_fAirResistance, CTimer::GetTimeStep());
m_vecMoveSpeed *= f;
m_vecTurnSpeed *= f;
- }else if(GetStatus() != STATUS_GHOST){
- float f = Pow(1.0f/Abs(1.0f + m_fAirResistance*0.5f*m_vecMoveSpeed.MagnitudeSqr()), CTimer::GetTimeStep());
+ }else{
+ float f = Pow(1.0f - m_fAirResistance*m_vecMoveSpeed.Magnitude(), CTimer::GetTimeStep());
m_vecMoveSpeed *= f;
m_vecTurnSpeed *= 0.99f;
}
@@ -613,6 +741,14 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
foo = true;
}
+ CVector comA, comB;
+ comA = Multiply3x3(A->GetMatrix(), A->m_vecCentreOfMass);
+ comB = Multiply3x3(B->GetMatrix(), B->m_vecCentreOfMass);
+
+ if(A->IsVehicle() && B->IsObject() && ((CObject*)B)->bIsStreetLight ||
+ B->IsVehicle() && A->IsObject() && ((CObject*)A)->bIsStreetLight)
+ colpoint.normal.z = 0.0f;
+
float speedA, speedB;
if(B->GetIsStatic() && !foo){
if(A->bPedPhysics){
@@ -633,6 +769,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
if(IsGlass(B->GetModelIndex()))
CGlass::WindowRespondsToSoftCollision(B, impulseA);
if(!A->bInfiniteMass)
+//TODO(LCS): inline without clamp
A->ApplyMoveForce(colpoint.GetNormal() * (1.0f + A->m_fElasticity) * impulseA);
return true;
}
@@ -643,6 +780,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
impulseA = -speedA * A->m_fMass;
impulseB = 0.0f;
if(!A->bInfiniteMass)
+//TODO(LCS): inline without clamp
A->ApplyMoveForce(colpoint.normal*(1.0f + A->m_fElasticity)*impulseA);
return true;
}
@@ -656,7 +794,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
eA = -1.0f;
else
eA = -(1.0f + A->m_fElasticity);
- impulseA = eA * speedA * A->GetMass(pointposA, colpoint.normal);
+ impulseA = eA * speedA * A->GetMass(pointposA-comA, colpoint.normal);
impulseB = impulseA;
if(Bobj->m_nCollisionDamageEffect && impulseA > 20.0f){
@@ -679,6 +817,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
int16 model = B->GetModelIndex();
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_STEAM, B->GetPosition() - CVector(0.0f, 0.0f, 0.5f), true);
Bobj->bHasBeenDamaged = true;
}else if((model == MI_PARKINGMETER || model == MI_PARKINGMETER2) && !Bobj->bHasBeenDamaged){
CPickups::CreateSomeMoney(GetPosition(), CGeneral::GetRandomNumber()%100);
@@ -724,7 +863,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
float mA = A->m_fMass;
float mB = B->m_fMass;
float speedSum;
- if(((CPed*)A)->GetPedState() == PED_FOLLOW_PATH){
+ if(A->IsPed() && ((CPed*)A)->GetPedState() == PED_FOLLOW_PATH){
affectB = true;
speedSum = (2.0f*mA*speedA + mB*speedB)/(2.0f*mA + mB);
}else{
@@ -756,7 +895,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
speedB = DotProduct(B->GetSpeed(pointposB), colpoint.normal);
float mA = A->m_fMass*massFactorA;
- float mB = B->GetMassTweak(pointposB, colpoint.normal, massFactorB);
+ float mB = B->GetMassTweak(pointposB-comB, colpoint.normal, massFactorB);
float speedSum;
if(foo)
speedSum = speedB;
@@ -794,7 +933,7 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
speedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal);
speedB = DotProduct(B->m_vecMoveSpeed, colpoint.normal);
- float mA = A->GetMassTweak(pointposA, colpoint.normal, massFactorA);
+ float mA = A->GetMassTweak(pointposA-comA, colpoint.normal, massFactorA);
float mB = B->m_fMass*massFactorB;
float speedSum = (mB*speedB + mA*speedA)/(mA + mB);
if(speedA < speedSum){
@@ -834,8 +973,8 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
CVector pointposB = colpoint.point - B->GetPosition();
speedA = DotProduct(A->GetSpeed(pointposA), colpoint.normal);
speedB = DotProduct(B->GetSpeed(pointposB), colpoint.normal);
- float mA = A->GetMassTweak(pointposA, colpoint.normal, massFactorA);
- float mB = B->GetMassTweak(pointposB, colpoint.normal, massFactorB);
+ float mA = A->GetMassTweak(pointposA-comA, colpoint.normal, massFactorA);
+ float mB = B->GetMassTweak(pointposB-comB, colpoint.normal, massFactorB);
float speedSum = (mB*speedB + mA*speedA)/(mA + mB);
if(speedA < speedSum){
if(A->bHasHitWall)
@@ -851,8 +990,8 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
CVector fA = colpoint.normal*(impulseA/massFactorA);
CVector fB = colpoint.normal*(-impulseB/massFactorB);
if(A->IsVehicle() && !A->bHasHitWall){
- fA.x *= 1.4f;
- fA.y *= 1.4f;
+// fA.x *= 1.4f;
+// fA.y *= 1.4f;
if(colpoint.normal.z < 0.7f)
fA.z *= 0.3f;
if(A->GetStatus() == STATUS_PLAYER)
@@ -863,8 +1002,8 @@ CPhysical::ApplyCollision(CPhysical *B, CColPoint &colpoint, float &impulseA, fl
}
}
if(B->IsVehicle() && !B->bHasHitWall){
- fB.x *= 1.4f;
- fB.y *= 1.4f;
+// fB.x *= 1.4f;
+// fB.y *= 1.4f;
if(-colpoint.normal.z < 0.7f)
fB.z *= 0.3f;
if(B->GetStatus() == STATUS_PLAYER)
@@ -915,8 +1054,8 @@ CPhysical::ApplyCollision(CColPoint &colpoint, float &impulse)
impulse = -(m_fElasticity + 1.0f) * speed * mass;
CVector f = colpoint.normal*impulse;
if(IsVehicle()){
- f.x *= 1.4f;
- f.y *= 1.4f;
+// f.x *= 1.4f;
+// f.y *= 1.4f;
if(colpoint.normal.z < 0.7f)
f.z *= 0.3f;
}
@@ -1022,6 +1161,7 @@ CPhysical::ApplyCollisionAlt(CEntity *B, CColPoint &colpoint, float &impulse, CV
return false;
}
+//LCS: the div by 0 is fixed differently. probably should use their fix?
bool
CPhysical::ApplyFriction(CPhysical *B, float adhesiveLimit, CColPoint &colpoint)
{
@@ -1261,6 +1401,10 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists)
A->GetBoundCentre(center);
radius = A->GetBoundRadius();
+
+ if(A->IsMultiplayer())
+ return false;
+
for(i = 0; i <= ENTITYLIST_PEDS_OVERLAP; i++){
list = &lists[i];
for(node = list->first; node; node = node->next){
@@ -1268,7 +1412,7 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists)
Bobj = (CObject*)B;
skipShift = false;
- if(B->IsBuilding() ||
+ if(B->IsMultiplayer() || B->IsBuilding() ||
B->IsObject() && B->bInfiniteMass ||
A->IsPed() && B->IsObject() && B->GetIsStatic() && !Bobj->bHasBeenDamaged)
canshift = true;
@@ -1335,9 +1479,9 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists)
else if(A->IsPed() && ((CPed*)A)->m_pCollidingEntity == B ||
B->IsPed() && ((CPed*)B)->m_pCollidingEntity == A)
skipShift = true;
- else if(A->GetModelIndex() == MI_RCBANDIT && B->IsVehicle() ||
- B->GetModelIndex() == MI_RCBANDIT && (A->IsPed() || A->IsVehicle()))
- skipShift = true;
+// else if(A->GetModelIndex() == MI_RCBANDIT && B->IsVehicle() ||
+// B->GetModelIndex() == MI_RCBANDIT && (A->IsPed() || A->IsVehicle()))
+// skipShift = true;
if(skipShift)
continue;
@@ -1379,6 +1523,7 @@ CPhysical::ProcessShiftSectorList(CPtrList *lists)
dir.Normalise();
B->GetMatrix().Translate(dir * colpoints[mostColliding].GetDepth() / (1.0f - f));
// BUG? how can that ever happen? A is a Ped
+ // LCS: gone or just optimized away?
if(B->IsVehicle())
B->ProcessEntityCollision(A, colpoints);
}else{
@@ -1441,6 +1586,10 @@ CPhysical::ProcessCollisionSectorList_SimpleCar(CPtrList *lists)
B->bUsesCollision &&
B->GetIsTouching(center, radius)){
B->m_scanCode = CWorld::GetCurrentScanCode();
+#ifndef FIX_BUGS
+ // surely they didn't mean to call this twice?
+ numCollisions = A->ProcessEntityCollision(B, aColPoints);
+#endif
numCollisions = A->ProcessEntityCollision(B, aColPoints);
if(numCollisions > 0)
goto collision;
@@ -1591,7 +1740,7 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
radius = A->GetBoundRadius();
A->GetBoundCentre(center);
- for(j = 0; j <= ENTITYLIST_PEDS_OVERLAP; j++){
+ for(j = A->IsMultiplayer() ? 1 : 0; j <= ENTITYLIST_PEDS_OVERLAP; j++){
list = &lists[j];
CPtrNode *listnode;
@@ -1600,7 +1749,6 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
Bobj = (CObject*)B;
Bped = (CPed*)B;
- bool isTouching = true;
if(!B->bUsesCollision ||
B->m_scanCode == CWorld::GetCurrentScanCode() ||
B == A)
@@ -1635,6 +1783,18 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
skipCollision = true;
A->bSkipLineCol = true;
Bobj->m_pCollidingEntity = A;
+ }else if(A->IsObject() && Aobj->m_nSpecialCollisionResponseCases == COLLRESPONSE_FENCEPART &&
+ B->IsObject() && Bobj->m_nSpecialCollisionResponseCases == COLLRESPONSE_FENCEPART){
+ skipCollision = true;
+ A->bSkipLineCol = true;
+ }else if(A->IsObject() && Aobj->bIsStreetLight && !B->IsBuilding() && IsLCSTrafficLight(A->GetModelIndex())){
+ skipCollision = true;
+ A->bSkipLineCol = true;
+ Aobj->m_pCollidingEntity = B;
+ }else if(B->IsObject() && Bobj->bIsStreetLight && !A->IsBuilding() && IsLCSTrafficLight(B->GetModelIndex())){
+ skipCollision = true;
+ B->bSkipLineCol = true;
+ Bobj->m_pCollidingEntity = A;
}else if(A->IsObject() && B->IsVehicle()){
if(A->GetModelIndex() == MI_CAR_BUMPER)
skipCollision = true;
@@ -1679,20 +1839,39 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
B->GetPosition().z < A->GetPosition().z){
skipCollision = true;
A->bSkipLineCol = true;
- }else if(A->IsPed() && Aped->m_pCollidingEntity == B){
+ }else if(A->IsPed() && (Aped->m_pCollidingEntity == B || !A->phys_lcs_unk1)){
skipCollision = true;
if(!Aped->bKnockedUpIntoAir || Aped->bKnockedOffBike)
A->bSkipLineCol = true;
- }else if(B->IsPed() && Bped->m_pCollidingEntity == A){
- skipCollision = true;
- A->bSkipLineCol = true;
- }else if(A->GetModelIndex() == MI_RCBANDIT && (B->IsPed() || B->IsVehicle()) ||
- B->GetModelIndex() == MI_RCBANDIT && (A->IsPed() || A->IsVehicle())){
+ }else if(B->IsPed() && (Bped->m_pCollidingEntity == A || !B->phys_lcs_unk1)){
skipCollision = true;
A->bSkipLineCol = true;
+// }else if(A->GetModelIndex() == MI_RCBANDIT && (B->IsPed() || B->IsVehicle()) ||
+// B->GetModelIndex() == MI_RCBANDIT && (A->IsPed() || A->IsVehicle())){
+// skipCollision = true;
+// A->bSkipLineCol = true;
}else if(A->IsPed() && B->IsObject() && Bobj->m_fUprootLimit > 0.0f)
altcollision = true;
+ if(A->IsObject() && !B->IsBuilding()){
+ if(!A->phys_lcs_unk1){
+ A->bSkipLineCol = true;
+ skipCollision = true;
+#ifdef FIX_BUGS
+ // looks correct below
+ Aobj->m_pCollidingEntity = B;
+#else
+ Aobj->m_pCollidingEntity = A;
+#endif
+ }
+ }
+ if(B->IsObject() && !A->IsBuilding()){
+ if(!B->phys_lcs_unk1){
+ B->bSkipLineCol = true;
+ skipCollision = true;
+ Bobj->m_pCollidingEntity = A;
+ }
+ }
if(!A->bUsesCollision || skipCollision){
B->m_scanCode = CWorld::GetCurrentScanCode();
@@ -1722,6 +1901,8 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
if(impulseA > maxImpulseA) maxImpulseA = impulseA;
if(A->IsVehicle()){
+ if(B->IsMultiplayer())
+ A->SendMuliVehicleCollision(B, &aColPoints[i], impulseA);
if(!(((CVehicle*)A)->IsBoat() && aColPoints[i].surfaceB == SURFACE_WOOD_SOLID) &&
impulseA > A->m_fDamageImpulse)
A->SetDamagedPieceRecord(aColPoints[i].pieceA, impulseA, B, aColPoints[i].normal);
@@ -1759,6 +1940,8 @@ CPhysical::ProcessCollisionSectorList(CPtrList *lists)
float adhesion = CSurfaceTable::GetAdhesiveLimit(aColPoints[i]) / numCollisions;
if(A->IsVehicle()){
+ if(B->IsMultiplayer())
+ A->SendMuliVehicleCollision(B, &aColPoints[i], impulseA);
if(((CVehicle*)A)->IsBoat() && aColPoints[i].surfaceB == SURFACE_WOOD_SOLID)
adhesion = 0.0f;
else if(impulseA > A->m_fDamageImpulse)
@@ -2105,7 +2288,7 @@ CPhysical::ProcessCollision(void)
m_bIsVehicleBeingShifted = false;
bSkipLineCol = false;
- if(!bUsesCollision){
+ if(!bUsesCollision || IsMultiplayer()){
bIsStuck = false;
bIsInSafePosition = true;
RemoveAndAdd();
@@ -2135,61 +2318,66 @@ CPhysical::ProcessCollision(void)
float distSq = m_vecMoveSpeed.MagnitudeSqr() * sq(CTimer::GetTimeStep());
if(IsPed() && (distSq >= sq(0.3f) || ped->IsPlayer())){
- if(ped->IsPlayer()){
- if(ped->m_pCurrentPhysSurface)
- n = Max(NUMSTEPS(0.15f), 4.0f);
- else
- n = Max(NUMSTEPS(0.3f), 2.0f);
- }else
- n = NUMSTEPS(0.45f);
+ if(ped->IsPlayer() && ped->m_pCurrentPhysSurface)
+ n = Max(NUMSTEPS(0.15f), 4.0f);
+ else
+ n = Max(NUMSTEPS(0.3f), 2.0f);
+ if(ped->IsPlayer() && ped->bHasHitWall)
+ n *= 2;
step = savedTimeStep / n;
if(!ped->IsPlayer())
ped->m_fElasticity *= HIGHSPEED_ELASTICITY_MULT_PED;
- }else if(IsVehicle() && distSq >= sq(0.4f)){
+ }else if(IsVehicle()){
if(GetStatus() == STATUS_PLAYER)
- n = NUMSTEPS(0.2f);
+ n = NUMSTEPS(0.3f);
else
- n = distSq > 0.32f ? NUMSTEPS(0.3f) : NUMSTEPS(0.4f);
+ n = NUMSTEPS(0.4f);
+ if(n == 0)
+ n = 1;
step = savedTimeStep / n;
-
- 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;
- bool savedUsesCollision = bUsesCollision;
- bUsesCollision = false;
- if(!CheckCollision()){
+ if(n > 2){
+ 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;
+ float relDist = Max(relDistX, Max(relDistY, relDistZ));
+ if(((CVehicle*)this)->GetVehicleAppearance() == VEHICLE_APPEARANCE_BIKE)
+ relDist *= 2.0f;
+ if(relDist < 1.0f){
+ // check if we can get away with simplified processing
+
+ ApplyMoveSpeed();
+ ApplyTurnSpeed();
+ GetMatrix().Reorthogonalise();
+ bSkipLineCol = false;
+ m_bIsVehicleBeingShifted = false;
+
+ bJustCheckCollision = true;
+ bool savedUsesCollision = bUsesCollision;
+ bUsesCollision = false;
+ if(!CheckCollision()){
+ bJustCheckCollision = false;
+ bUsesCollision = savedUsesCollision;
+ 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 = savedUsesCollision;
- 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;
+ GetMatrix() = savedMatrix;
+ m_vecMoveSpeed = savedMoveSpeed;
+ if(IsVehicle() && ((CVehicle*)this)->bIsLawEnforcer)
+ m_fElasticity *= HIGHSPEED_ELASTICITY_MULT_COPCAR;
}
- bJustCheckCollision = false;
- bUsesCollision = savedUsesCollision;
- 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;
@@ -2272,7 +2460,7 @@ CPhysical::ProcessCollision(void)
bSkipLineCol = false;
if(!m_vecMoveSpeed.IsZero() ||
!m_vecTurnSpeed.IsZero() ||
- bHitByTrain ||
+// bHitByTrain ||
GetStatus() == STATUS_PLAYER ||
IsVehicle() && ((CVehicle*)this)->bRestingOnPhysical ||
IsPed() && ped->IsPlayer()){
@@ -2293,3 +2481,44 @@ CPhysical::ProcessCollision(void)
m_fElasticity = savedElasticity;
RemoveAndAdd();
}
+
+
+
+// TEMP old VC code until bikes are done
+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;
+ if(bIsHeavy)
+ impulse *= 0.75f;
+ ApplyMoveForce(forceDir*impulse);
+ ApplyTurnForce(forceDir*impulse, point);
+ }
+ return true;
+}
+bool
+CPhysical::ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed)
+{
+ float speedA = DotProduct(speed, springDir);
+ float speedB = DotProduct(GetSpeed(point), springDir);
+ float step = Min(CTimer::GetTimeStep(), 3.0f);
+ float impulse = -damping * (speedA + speedB)/2.0f * m_fMass * step * 0.53f;
+ if(bIsHeavy)
+ impulse *= 2.0f;
+
+ // what is this?
+ float a = m_fTurnMass / ((point.MagnitudeSqr() + 1.0f) * 2.0f * m_fMass);
+ a = Min(a, 1.0f);
+ float b = Abs(impulse / (speedB * m_fMass));
+ if(a < b)
+ impulse *= a/b;
+
+ ApplyMoveForce(springDir*impulse);
+ ApplyTurnForce(springDir*impulse, point);
+ return true;
+}
diff --git a/src/entities/Physical.h b/src/entities/Physical.h
index f552da6c..71e30485 100644
--- a/src/entities/Physical.h
+++ b/src/entities/Physical.h
@@ -61,9 +61,13 @@ public:
uint8 m_bIsVehicleBeingShifted : 1; // wrong name - also used on but never set for peds
uint8 bJustCheckCollision : 1; // just see if there is a collision
+bool phys_lcs_unk1;
+
uint8 m_nSurfaceTouched;
int8 m_nZoneLevel;
+int8 phys_lcs_unk2;
+
CPhysical(void);
~CPhysical(void);
@@ -75,6 +79,9 @@ public:
void ProcessShift(void);
void ProcessCollision(void);
+ // these two are virtual in LCS...why?
+ virtual void ApplyMoveSpeed(void);
+ virtual void ApplyTurnSpeed(void);
virtual int32 ProcessEntityCollision(CEntity *ent, CColPoint *colpoints);
void RemoveAndAdd(void);
@@ -141,8 +148,6 @@ public:
m_vecCentreOfMass.z = z;
}
- void ApplyMoveSpeed(void);
- void ApplyTurnSpeed(void);
// Force actually means Impulse here
void ApplyMoveForce(float jx, float jy, float jz);
void ApplyMoveForce(const CVector &j) { ApplyMoveForce(j.x, j.y, j.z); }
@@ -150,14 +155,15 @@ public:
void ApplyTurnForce(float jx, float jy, float jz, float px, float py, float pz);
// j is direction of force, p is point relative to model center where force is applied
void ApplyTurnForce(const CVector &j, const CVector &p) { ApplyTurnForce(j.x, j.y, j.z, p.x, p.y, p.z); }
+ void ApplyTurnForceMultiplayer(const CVector &j, const CVector &p);
void ApplyFrictionMoveForce(float jx, float jy, float jz);
void ApplyFrictionMoveForce(const CVector &j) { ApplyFrictionMoveForce(j.x, j.y, j.z); }
void ApplyFrictionTurnForce(float jx, float jy, float jz, float rx, float ry, float rz);
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
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 ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir, float &impulse);
+ bool ApplySpringDampening(float damping, float dampingLimit, CVector &springDir, CVector &point, CVector &speed);
void ApplyGravity(void);
void ApplyFriction(void);
void ApplyAirResistance(void);
@@ -172,4 +178,10 @@ public:
bool ProcessCollisionSectorList(CPtrList *lists);
bool CheckCollision(void);
bool CheckCollision_SimpleCar(void);
+
+ void SendMuliVehicleCollision(CEntity *,CColPoint *,float) {}
+
+ // TEMP
+ bool ApplySpringCollisionAlt(float springConst, CVector &springDir, CVector &point, float springRatio, float bias, CVector &forceDir);
+ bool ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed);
};