From 93d55bd029b62224a0690bc06bf5d9d6126e59ce Mon Sep 17 00:00:00 2001 From: aap Date: Wed, 24 Jul 2019 23:06:48 +0200 Subject: [PATCH] fixed buoyancy; implemented CAutomobile::ProcessBuoyancy --- src/objects/ParticleObject.cpp | 7 +- src/objects/ParticleObject.h | 7 +- src/vehicles/Automobile.cpp | 135 +++++++++++++++++++++++++++++++-- src/vehicles/Automobile.h | 2 +- src/vehicles/Floater.cpp | 14 ++-- src/vehicles/Floater.h | 4 +- 6 files changed, 146 insertions(+), 23 deletions(-) diff --git a/src/objects/ParticleObject.cpp b/src/objects/ParticleObject.cpp index 25f223e1..f5cd4c94 100644 --- a/src/objects/ParticleObject.cpp +++ b/src/objects/ParticleObject.cpp @@ -2,9 +2,10 @@ #include "patcher.h" #include "ParticleObject.h" -WRAPPER void CParticleObject::AddObject(uint16 type, const CVector &pos, bool remove) { EAXJMP(0x4BC4D0); } -WRAPPER void CParticleObject::AddObject(uint16 type, const CVector &pos, float size, bool remove) { EAXJMP(0x4BC520); } -WRAPPER void CParticleObject::AddObject(uint16 type, const CVector &pos, const CVector &dir, float size, bool remove) { EAXJMP(0x4BC570); } +WRAPPER void CParticleObject::AddObject(uint16 type, const CVector &pos, uint8 remove) { EAXJMP(0x4BC4D0); } +WRAPPER void CParticleObject::AddObject(uint16 type, const CVector &pos, float size, uint8 remove) { EAXJMP(0x4BC520); } +WRAPPER void CParticleObject::AddObject(uint16 type, const CVector &pos, const CVector &dir, float size, uint8 remove) { EAXJMP(0x4BC570); } +WRAPPER void CParticleObject::AddObject(uint16 type, const CVector &pos, const CVector &dir, float size, uint32, const RwRGBA &col, uint8 remove) { EAXJMP(0x4BC5B0); } // Converted from static void __cdecl CParticleObject::Initialise() 0x42C760 void CParticleObject::Initialise() diff --git a/src/objects/ParticleObject.h b/src/objects/ParticleObject.h index 6ec090e7..192d3703 100644 --- a/src/objects/ParticleObject.h +++ b/src/objects/ParticleObject.h @@ -29,9 +29,10 @@ enum eParticleObjectType class CParticleObject : CPlaceable { public: - static void AddObject(uint16 type, const CVector &pos, bool remove); - static void AddObject(uint16 type, const CVector &pos, float size, bool remove); - static void AddObject(uint16 type, const CVector &pos, const CVector &dir, float size, bool remove); + static void AddObject(uint16 type, const CVector &pos, uint8 remove); + static void AddObject(uint16 type, const CVector &pos, float size, uint8 remove); + static void AddObject(uint16 type, const CVector &pos, const CVector &dir, float size, uint8 remove); + static void AddObject(uint16 type, const CVector &pos, const CVector &dir, float size, uint32, const RwRGBA &col, uint8 remove); static void Initialise(); static void UpdateAll(); }; diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index fb42e6e6..bc0c8593 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -7,12 +7,16 @@ #include "ModelIndices.h" #include "VisibilityPlugins.h" #include "DMAudio.h" +#include "TimeCycle.h" #include "Camera.h" #include "Darkel.h" #include "Rubbish.h" #include "Fire.h" #include "Explosion.h" #include "Particle.h" +#include "ParticleObject.h" +#include "WaterLevel.h" +#include "Floater.h" #include "World.h" #include "SurfaceTable.h" #include "HandlingMgr.h" @@ -49,7 +53,7 @@ CAutomobile::CAutomobile(int32 id, uint8 CreatedBy) bTaxiLight = m_sAllTaxiLights; m_auto_flagA20 = false; m_auto_flagA40 = false; - m_auto_flagA80 = false; + bWaterTight = false; SetModelIndex(id); @@ -1179,10 +1183,6 @@ CAutomobile::ProcessControl(void) m_vecTurnSpeed.z = 0.0f; } } - -// TEMP -if(pDriver) - pDriver->m_fHealth = 100.0f; } void @@ -1431,9 +1431,130 @@ CAutomobile::HydraulicControl(void) { EAXJMP(0x52D4E0); } -WRAPPER void +void CAutomobile::ProcessBuoyancy(void) -{ EAXJMP(0x5308D0); +{ + int i; + CVector impulse, point; + + if(mod_Buoyancy.ProcessBuoyancy(this, m_fBuoyancy, &point, &impulse)){ + m_flagD8 = true; + ApplyMoveForce(impulse); + ApplyTurnForce(impulse, point); + + CVector initialSpeed = m_vecMoveSpeed; + float timeStep = max(CTimer::GetTimeStep(), 0.01f); + float impulseRatio = impulse.z / (GRAVITY * m_fMass * timeStep); + float waterResistance = Pow(1.0f - 0.05f*impulseRatio, CTimer::GetTimeStep()); + m_vecMoveSpeed *= waterResistance; + m_vecTurnSpeed *= waterResistance; + + if(impulseRatio > 0.5f){ + bIsInWater = true; + if(m_vecMoveSpeed.z < -0.1f) + m_vecMoveSpeed.z = -0.1f; + + if(pDriver){ + pDriver->bIsInWater = true; + if(pDriver->IsPlayer() || !bWaterTight) + pDriver->InflictDamage(nil, WEAPONTYPE_WATER, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0); + } + for(i = 0; i < m_nNumMaxPassengers; i++) + if(pPassengers[i]){ + pPassengers[i]->bIsInWater = true; + if(pPassengers[i]->IsPlayer() || !bWaterTight) + pPassengers[i]->InflictDamage(nil, WEAPONTYPE_WATER, CTimer::GetTimeStep(), PEDPIECE_TORSO, 0); + } + }else + bIsInWater = false; + + static uint32 nGenerateRaindrops = 0; + static uint32 nGenerateWaterCircles = 0; + + if(initialSpeed.z < -0.3f && impulse.z > 0.3f){ + RwRGBA color; + color.red = (0.5f * CTimeCycle::GetDirectionalRed() + CTimeCycle::GetAmbientRed())*0.45f*255; + color.green = (0.5f * CTimeCycle::GetDirectionalGreen() + CTimeCycle::GetAmbientGreen())*0.45f*255; + color.blue = (0.5f * CTimeCycle::GetDirectionalBlue() + CTimeCycle::GetAmbientBlue())*0.45f*255; + color.alpha = CGeneral::GetRandomNumberInRange(0, 32) + 128; + CParticleObject::AddObject(POBJECT_CAR_WATER_SPLASH, GetPosition(), + CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.15f, 0.3f)), + 0.0f, 75, color, true); + + nGenerateRaindrops = CTimer::GetTimeInMilliseconds() + 300; + nGenerateWaterCircles = CTimer::GetTimeInMilliseconds() + 60; + if(m_vecMoveSpeed.z < -0.2f) + m_vecMoveSpeed.z = -0.2f; + DMAudio.PlayOneShot(m_audioEntityId, SOUND_WATER_FALL, 0.0f); + } + + if(nGenerateWaterCircles > 0 && nGenerateWaterCircles < CTimer::GetTimeInMilliseconds()){ + CVector pos = GetPosition(); + float waterLevel = 0.0f; + if(CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &waterLevel, false)) + pos.z = waterLevel; + static RwRGBA black; + if(pos.z != 0.0f){ + nGenerateWaterCircles = 0; + pos.z += 1.0f; + for(i = 0; i < 4; i++){ + CVector p = pos; + p.x += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f); + p.y += CGeneral::GetRandomNumberInRange(-2.5f, 2.5f); + CParticle::AddParticle(PARTICLE_RAIN_SPLASH_BIGGROW, + p, CVector(0.0f, 0.0f, 0.0f), + nil, 0.0f, black, 0, 0, 0, 0); + } + } + } + + if(nGenerateRaindrops > 0 && nGenerateRaindrops < CTimer::GetTimeInMilliseconds()){ + CVector pos = GetPosition(); + float waterLevel = 0.0f; + if(CWaterLevel::GetWaterLevel(pos.x, pos.y, pos.z, &waterLevel, false)) + pos.z = waterLevel; + static RwRGBA black; + if(pos.z >= 0.0f){ + nGenerateRaindrops = 0; + pos.z += 0.5; + CParticleObject::AddObject(POBJECT_SPLASHES_AROUND, + pos, CVector(0.0f, 0.0f, 0.0f), 6.5f, 2500, black, true); + } + } + }else{ + bIsInWater = false; + m_flagD8 = false; + + static RwRGBA splashCol = {155, 155, 185, 196}; + static RwRGBA smokeCol = {255, 255, 255, 255}; + + for(i = 0; i < 4; i++){ + if(m_aSuspensionSpringRatio[i] < 1.0f && m_aWheelColPoints[i].surfaceB == SURFACE_PUDDLE){ + CVector pos = m_aWheelColPoints[i].point + 0.3f*GetUp() - GetPosition(); + CVector vSpeed = GetSpeed(pos); + vSpeed.z = 0.0f; + float fSpeed = vSpeed.MagnitudeSqr(); + if(fSpeed > sq(0.05f)){ + fSpeed = Sqrt(fSpeed); + float size = min((fSpeed < 0.15f ? 0.25f : 0.75f)*fSpeed, 0.6f); + CVector right = 0.2f*fSpeed*GetRight() + 0.2f*vSpeed; + + CParticle::AddParticle(PARTICLE_PED_SPLASH, + pos + GetPosition(), -0.5f*right, + nil, size, splashCol, + CGeneral::GetRandomNumberInRange(0.0f, 10.0f), + CGeneral::GetRandomNumberInRange(0.0f, 90.0f), 1, 0); + + CParticle::AddParticle(PARTICLE_RUBBER_SMOKE, + pos + GetPosition(), -0.6f*right, + nil, size, smokeCol, 0, 0, 0, 0); + + if((CTimer::GetFrameCounter() & 0xF) == 0) + DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_SPLASH, 2000.0f*fSpeed); + } + } + } + } } void diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h index 1a103777..fd3eb203 100644 --- a/src/vehicles/Automobile.h +++ b/src/vehicles/Automobile.h @@ -48,7 +48,7 @@ public: uint8 bHadDriver : 1; // for bombs uint8 m_auto_flagA20 : 1; uint8 m_auto_flagA40 : 1; - uint8 m_auto_flagA80 : 1; + uint8 bWaterTight : 1; // no damage for non-player peds uint8 bNotDamagedUpsideDown : 1; uint8 bMoreResistantToDamage : 1; uint8 field_4DB; diff --git a/src/vehicles/Floater.cpp b/src/vehicles/Floater.cpp index cabe00c3..6b8bf755 100644 --- a/src/vehicles/Floater.cpp +++ b/src/vehicles/Floater.cpp @@ -22,7 +22,7 @@ static float fBoatVolumeDistribution[9] = { }; bool -cBuoyancy::ProcessBuoyancy(CPhysical *phys, float buoyancy, CVector *impulse, CVector *point) +cBuoyancy::ProcessBuoyancy(CPhysical *phys, float buoyancy, CVector *point, CVector *impulse) { m_numSteps = 2.0f; @@ -32,7 +32,7 @@ cBuoyancy::ProcessBuoyancy(CPhysical *phys, float buoyancy, CVector *impulse, CV PreCalcSetup(phys, buoyancy); SimpleCalcBuoyancy(); - float f = CalcBuoyancyForce(phys, impulse, point); + float f = CalcBuoyancyForce(phys, point, impulse); if(m_isBoat) return true; return f != 0.0f; @@ -82,7 +82,7 @@ cBuoyancy::PreCalcSetup(CPhysical *phys, float buoyancy) m_haveVolume = false; m_numPartialVolumes = 1.0f; m_volumeUnderWater = 0.0f; - m_impulse = CVector(0.0f, 0.0f, 0.0f); + m_impulsePoint = CVector(0.0f, 0.0f, 0.0f); m_position = phys->GetPosition(); m_positionZ = CVector(0.0f, 0.0f, m_position.z); m_buoyancy = buoyancy; @@ -148,7 +148,7 @@ cBuoyancy::SimpleSumBuoyancyData(CVector &waterLevel, tWaterLevel waterPosition) fFraction = 1.0f/m_numPartialVolumes; fRemainingSlice = 1.0f - fFraction; - m_impulse = m_impulse*fRemainingSlice + AverageOfWaterLevel*fThisVolume*fFraction; + m_impulsePoint = m_impulsePoint*fRemainingSlice + AverageOfWaterLevel*fThisVolume*fFraction; m_numPartialVolumes += 1.0f; m_haveVolume = true; return fThisVolume; @@ -175,13 +175,13 @@ cBuoyancy::FindWaterLevel(const CVector &zpos, CVector *waterLevel, tWaterLevel } bool -cBuoyancy::CalcBuoyancyForce(CPhysical *phys, CVector *impulse, CVector *point) +cBuoyancy::CalcBuoyancyForce(CPhysical *phys, CVector *point, CVector *impulse) { if(!m_haveVolume) return false; - *impulse = Multiply3x3(m_matrix, m_impulse); - *point = CVector(0.0f, 0.0f, m_volumeUnderWater*m_buoyancy*CTimer::GetTimeStep()); + *point = Multiply3x3(m_matrix, m_impulsePoint); + *impulse = CVector(0.0f, 0.0f, m_volumeUnderWater*m_buoyancy*CTimer::GetTimeStep()); return true; } diff --git a/src/vehicles/Floater.h b/src/vehicles/Floater.h index ede2b9d0..0a2ae809 100644 --- a/src/vehicles/Floater.h +++ b/src/vehicles/Floater.h @@ -1,6 +1,6 @@ #pragma once -class Physical; +class CPhysical; enum tWaterLevel { @@ -33,7 +33,7 @@ public: char m_field_B9; bool m_isBoat; float m_volumeUnderWater; - CVector m_impulse; + CVector m_impulsePoint; bool ProcessBuoyancy(CPhysical *phys, float buoyancy, CVector *impulse, CVector *point); void PreCalcSetup(CPhysical *phys, float buoyancy);