diff --git a/src/control/Script.cpp b/src/control/Script.cpp index af151802..5e7f4936 100644 --- a/src/control/Script.cpp +++ b/src/control/Script.cpp @@ -144,7 +144,7 @@ void CUpsideDownCarCheck::Init() bool CUpsideDownCarCheck::IsCarUpsideDown(int32 id) { CVehicle* v = CPools::GetVehiclePool()->GetAt(id); - return v->GetMatrix().GetUp()->z <= -0.97f && + return v->GetUp().z <= -0.97f && v->GetMoveSpeed().Magnitude() < 0.01f && v->GetTurnSpeed().Magnitude() < 0.02f; } diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index b7ca1904..600e5dca 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -304,6 +304,22 @@ CPhysical::RemoveRefsToEntity(CEntity *ent) } } +void +CPhysical::PlacePhysicalRelativeToOtherPhysical(CPhysical *other, CPhysical *phys, CVector localPos) +{ + CVector worldPos = other->GetMatrix() * localPos; + float step = 0.9f * CTimer::GetTimeStep(); + CVector pos = other->m_vecMoveSpeed*step + worldPos; + + CWorld::Remove(phys); + phys->GetMatrix() = other->GetMatrix(); + phys->GetPosition() = pos; + phys->m_vecMoveSpeed = other->m_vecMoveSpeed; + phys->GetMatrix().UpdateRW(); + phys->UpdateRwFrame(); + CWorld::Add(phys); +} + int32 CPhysical::ProcessEntityCollision(CEntity *ent, CColPoint *colpoints) { @@ -434,15 +450,38 @@ CPhysical::ApplyFrictionTurnForce(float jx, float jy, float jz, float px, float m_vecTurnFriction += turnimpulse*(1.0f/m_fTurnMass); } -void -CPhysical::ApplySpringCollision(float f1, CVector &v, CVector &p, float f2, float f3) +bool +CPhysical::ApplySpringCollision(float springConst, CVector &springDir, CVector &point, float springRatio, float bias) { - if(1.0f - f2 <= 0.0f) - return; + float compression = 1.0f - springRatio; + if(compression > 0.0f){ + float step = min(CTimer::GetTimeStep(), 3.0f); + float impulse = -0.008f*m_fMass*step * springConst * compression * bias*2.0f; + ApplyMoveForce(springDir*impulse); + ApplyTurnForce(springDir*impulse, point); + } + return true; +} + +// What exactly is speed? +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 strength = -0.008f*m_fMass*2.0f*step * f1 * (1.0f-f2) * f3; - ApplyMoveForce(v*strength); - ApplyTurnForce(v*strength, p); + float impulse = -damping * (speedA + speedB)/2.0f * m_fMass * step * 0.53f; + + // what is this? + float a = m_fTurnMass / ((point.MagnitudeSqr() + 1.0f) * 2.0f * m_fMass); + a = min(a, 1.0f); + float b = fabs(impulse / (speedB * m_fMass)); + if(a < b) + impulse *= a/b; + + ApplyMoveForce(springDir*impulse); + ApplyTurnForce(springDir*impulse, point); + return true; } void @@ -1909,6 +1948,7 @@ STARTPATCHES InjectHook(0x4970C0, &CPhysical::AddCollisionRecord_Treadable, PATCH_JUMP); InjectHook(0x497240, &CPhysical::GetHasCollidedWith, PATCH_JUMP); InjectHook(0x49F820, &CPhysical::RemoveRefsToEntity, PATCH_JUMP); + InjectHook(0x49F890, &CPhysical::PlacePhysicalRelativeToOtherPhysical, PATCH_JUMP); #define F3 float, float, float InjectHook(0x495B10, &CPhysical::ApplyMoveSpeed, PATCH_JUMP); @@ -1918,6 +1958,7 @@ STARTPATCHES InjectHook(0x495D90, (void (CPhysical::*)(F3))&CPhysical::ApplyFrictionMoveForce, PATCH_JUMP); InjectHook(0x495E10, (void (CPhysical::*)(F3, F3))&CPhysical::ApplyFrictionTurnForce, PATCH_JUMP); InjectHook(0x499890, &CPhysical::ApplySpringCollision, PATCH_JUMP); + InjectHook(0x499990, &CPhysical::ApplySpringDampening, PATCH_JUMP); InjectHook(0x495B50, &CPhysical::ApplyGravity, PATCH_JUMP); InjectHook(0x495B80, (void (CPhysical::*)(void))&CPhysical::ApplyFriction, PATCH_JUMP); InjectHook(0x495C20, &CPhysical::ApplyAirResistance, PATCH_JUMP); diff --git a/src/entities/Physical.h b/src/entities/Physical.h index 0104268a..81d3d649 100644 --- a/src/entities/Physical.h +++ b/src/entities/Physical.h @@ -81,6 +81,7 @@ public: void AddCollisionRecord_Treadable(CEntity *ent); bool GetHasCollidedWith(CEntity *ent); void RemoveRefsToEntity(CEntity *ent); + 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 @@ -104,8 +105,8 @@ public: bIsInSafePosition = false; } - const CVector& GetMoveSpeed() { return m_vecMoveSpeed; } - const CVector& GetTurnSpeed() { return m_vecTurnSpeed; } + const CVector &GetMoveSpeed() { return m_vecMoveSpeed; } + const CVector &GetTurnSpeed() { return m_vecTurnSpeed; } void ApplyMoveSpeed(void); void ApplyTurnSpeed(void); @@ -120,7 +121,9 @@ public: 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); } - void ApplySpringCollision(float f1, CVector &v, CVector &p, float f2, float f3); + // springRatio: 1.0 fully extended, 0.0 fully compressed + bool ApplySpringCollision(float springConst, CVector &springDir, CVector &point, float springRatio, float bias); + bool ApplySpringDampening(float damping, CVector &springDir, CVector &point, CVector &speed); void ApplyGravity(void); void ApplyFriction(void); void ApplyAirResistance(void);