From fd01f9b25cdc3b527a886ee6b9237b01a5475295 Mon Sep 17 00:00:00 2001 From: aap Date: Thu, 18 Jul 2019 15:41:09 +0200 Subject: CAutomobile::ProcessControl done --- src/control/CarAI.cpp | 1 + src/control/CarAI.h | 1 + src/control/CarCtrl.cpp | 1 + src/control/CarCtrl.h | 1 + src/core/Camera.cpp | 8 ++ src/core/Camera.h | 1 + src/core/common.h | 3 +- src/math/Vector.h | 1 + src/vehicles/Automobile.cpp | 223 ++++++++++++++++++++++++++++++++++++++++++-- src/vehicles/Automobile.h | 2 +- src/vehicles/Vehicle.cpp | 2 +- src/vehicles/Vehicle.h | 6 +- 12 files changed, 239 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/control/CarAI.cpp b/src/control/CarAI.cpp index 92dc5ab9..faf27788 100644 --- a/src/control/CarAI.cpp +++ b/src/control/CarAI.cpp @@ -3,3 +3,4 @@ #include "CarAI.h" WRAPPER void CCarAI::UpdateCarAI(CVehicle*) { EAXJMP(0x413E50); } +WRAPPER void CCarAI::MakeWayForCarWithSiren(CVehicle *veh) { EAXJMP(0x416280); } diff --git a/src/control/CarAI.h b/src/control/CarAI.h index d463e1a9..5112f769 100644 --- a/src/control/CarAI.h +++ b/src/control/CarAI.h @@ -6,4 +6,5 @@ class CCarAI { public: static void UpdateCarAI(CVehicle*); + static void MakeWayForCarWithSiren(CVehicle *veh); }; diff --git a/src/control/CarCtrl.cpp b/src/control/CarCtrl.cpp index edf4d1ae..5e436c84 100644 --- a/src/control/CarCtrl.cpp +++ b/src/control/CarCtrl.cpp @@ -16,6 +16,7 @@ WRAPPER bool CCarCtrl::JoinCarWithRoadSystemGotoCoors(CVehicle*, CVector, bool) WRAPPER void CCarCtrl::JoinCarWithRoadSystem(CVehicle*) { EAXJMP(0x41F820); } WRAPPER void CCarCtrl::SteerAICarWithPhysics(CVehicle*) { EAXJMP(0x41DA60); } WRAPPER void CCarCtrl::UpdateCarOnRails(CVehicle*) { EAXJMP(0x418880); } +WRAPPER void CCarCtrl::ScanForPedDanger(CVehicle *veh) { EAXJMP(0x418F40); } bool CCarCtrl::MapCouldMoveInThisArea(float x, float y) diff --git a/src/control/CarCtrl.h b/src/control/CarCtrl.h index 7e3f70a9..677dcf36 100644 --- a/src/control/CarCtrl.h +++ b/src/control/CarCtrl.h @@ -14,6 +14,7 @@ public: static void SteerAICarWithPhysics(CVehicle*); static void UpdateCarOnRails(CVehicle*); static bool MapCouldMoveInThisArea(float x, float y); + static void ScanForPedDanger(CVehicle *veh); static int32 &NumLawEnforcerCars; static int32 &NumAmbulancesOnDuty; diff --git a/src/core/Camera.cpp b/src/core/Camera.cpp index e35198d8..a66d6ac9 100644 --- a/src/core/Camera.cpp +++ b/src/core/Camera.cpp @@ -95,6 +95,14 @@ CCamera::GetLookDirection(void) return LOOKING_FORWARD;; } +bool +CCamera::GetLookingForwardFirstPerson() +{ + return Cams[ActiveCam].Mode == CCam::MODE_FIRSTPERSON && + Cams[ActiveCam].DirectionWasLooking == LOOKING_FORWARD; +} + + WRAPPER void CCamera::Fade(float timeout, int16 direction) { EAXJMP(0x46B3A0); } WRAPPER void CCamera::ProcessFade(void) { EAXJMP(0x46F080); } WRAPPER void CCamera::ProcessMusicFade(void) { EAXJMP(0x46F1E0); } diff --git a/src/core/Camera.h b/src/core/Camera.h index a88bf83a..b5c9103c 100644 --- a/src/core/Camera.h +++ b/src/core/Camera.h @@ -448,6 +448,7 @@ int m_iModeObbeCamIsInForCar; bool IsSphereVisible(const CVector ¢er, float radius); bool IsBoxVisible(RwV3d *box, const CMatrix *mat); int GetLookDirection(void); + bool GetLookingForwardFirstPerson(void); void Fade(float timeout, int16 direction); int GetScreenFadeStatus(void); diff --git a/src/core/common.h b/src/core/common.h index fd961dd7..c241e1c6 100644 --- a/src/core/common.h +++ b/src/core/common.h @@ -139,7 +139,8 @@ inline float sq(float x) { return x*x; } #define SQR(x) ((x) * (x)) #define PI M_PI -#define TWOPI PI*2 +#define TWOPI (PI*2) +#define HALFPI (PI/2) #define DEGTORAD(x) ((x) * PI / 180.0f) #define RADTODEG(x) ((x) * 180.0f / PI) diff --git a/src/math/Vector.h b/src/math/Vector.h index de8092eb..f794a57f 100644 --- a/src/math/Vector.h +++ b/src/math/Vector.h @@ -22,6 +22,7 @@ public: return *((RwV3d*)this); } #endif + // (0,1,0) means no rotation. So get right vector and its atan float Heading(void) const { return Atan2(-x, y); } float Magnitude(void) const { return Sqrt(x*x + y*y + z*z); } float MagnitudeSqr(void) const { return x*x + y*y + z*z; } diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index 5580ee6d..ecf3bde3 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -10,6 +10,7 @@ #include "Rubbish.h" #include "Fire.h" #include "Explosion.h" +#include "Particle.h" #include "World.h" #include "SurfaceTable.h" #include "HandlingMgr.h" @@ -46,6 +47,9 @@ CAutomobile::SetModelIndex(uint32 id) SetupModelNodes(); } +CVector vecDAMAGE_ENGINE_POS_SMALL(-0.1f, -0.1f, 0.0f); +CVector vecDAMAGE_ENGINE_POS_BIG(-0.5f, -0.3f, 0.0f); + //WRAPPER void CAutomobile::ProcessControl(void) { EAXJMP(0x531470); } void CAutomobile::ProcessControl(void) @@ -330,12 +334,51 @@ CAutomobile::ProcessControl(void) break; default: if(CVehicle::bCheat3){ - // strong grip cheat - // TODO: make cars jump when horn key is pressed + // Make vehicle jump when horn is sounded + if(m_status == STATUS_PLAYER && m_vecMoveSpeed.MagnitudeSqr() > sq(0.2f) && + // BUG: game checks [0] four times, instead of all wheels + m_aSuspensionSpringRatio[0] < 1.0f && + CPad::GetPad(0)->HornJustDown()){ + + DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_HYDRALIC_1, 0.0f); + DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_JUMP, 1.0f); + + CParticle::AddParticle(PARTICLE_ENGINE_STEAM, + m_aWheelColPoints[0].point + 0.5f*GetUp(), + 1.3f*m_vecMoveSpeed, nil, 2.5f); + CParticle::AddParticle(PARTICLE_ENGINE_SMOKE, + m_aWheelColPoints[0].point + 0.5f*GetUp(), + 1.2f*m_vecMoveSpeed, nil, 2.0f); + + CParticle::AddParticle(PARTICLE_ENGINE_STEAM, + m_aWheelColPoints[2].point + 0.5f*GetUp(), + 1.3f*m_vecMoveSpeed, nil, 2.5f); + CParticle::AddParticle(PARTICLE_ENGINE_SMOKE, + m_aWheelColPoints[2].point + 0.5f*GetUp(), + 1.2f*m_vecMoveSpeed, nil, 2.0f); + + CParticle::AddParticle(PARTICLE_ENGINE_STEAM, + m_aWheelColPoints[0].point + 0.5f*GetUp() - GetForward(), + 1.3f*m_vecMoveSpeed, nil, 2.5f); + CParticle::AddParticle(PARTICLE_ENGINE_SMOKE, + m_aWheelColPoints[0].point + 0.5f*GetUp() - GetForward(), + 1.2f*m_vecMoveSpeed, nil, 2.0f); + + CParticle::AddParticle(PARTICLE_ENGINE_STEAM, + m_aWheelColPoints[2].point + 0.5f*GetUp() - GetForward(), + 1.3f*m_vecMoveSpeed, nil, 2.5f); + CParticle::AddParticle(PARTICLE_ENGINE_SMOKE, + m_aWheelColPoints[2].point + 0.5f*GetUp() - GetForward(), + 1.2f*m_vecMoveSpeed, nil, 2.0f); + + ApplyMoveForce(CVector(0.0f, 0.0f, 1.0f)*m_fMass*0.4f); + ApplyTurnForce(GetUp()*m_fMass*0.035f, GetForward()*1.0f); + } } break; } + float brake; if(skipPhysics){ bHasContacted = false; bIsInSafePosition = false; @@ -473,7 +516,7 @@ CAutomobile::ProcessControl(void) GetModelIndex() == MI_MIAMI_SPARROW) acceleration = 0.0f; - float brake = m_fBrakePedal * pHandling->fBrakeDeceleration * CTimer::GetTimeStep(); + brake = m_fBrakePedal * pHandling->fBrakeDeceleration * CTimer::GetTimeStep(); bool neutralHandling = !!(pHandling->Flags & HANDLING_NEUTRALHANDLING); float brakeBiasFront = neutralHandling ? 1.0f : 2.0f*pHandling->fBrakeBias; float brakeBiasRear = neutralHandling ? 1.0f : 2.0f*(1.0f-pHandling->fBrakeBias); @@ -766,7 +809,7 @@ CAutomobile::ProcessControl(void) for(i = 0; i < 4; i++){ float wheelPos = colModel->lines[i].p0.z; if(m_aSuspensionSpringRatio[i] > 0.0f) - wheelPos -= m_aSuspensionSpringRatio[i]*m_aSuspensionLineLength[i]; + wheelPos -= m_aSuspensionSpringRatio[i]*m_aSuspensionSpringLength[i]; m_aWheelPosition[i] += (wheelPos - m_aWheelPosition[i])*0.75f; } for(i = 0; i < 4; i++) @@ -824,7 +867,174 @@ CAutomobile::ProcessControl(void) } } - assert(0 && "misc stuff"); + + + // Process car on fire + // A similar calculation of damagePos is done elsewhere for smoke + + uint8 engineStatus = Damage.GetEngineStatus(); + CVector damagePos = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->m_positions[CAR_POS_HEADLIGHTS]; + + switch(Damage.GetDoorStatus(DOOR_BONNET)){ + case DOOR_STATUS_OK: + case DOOR_STATUS_SMASHED: + // Bonnet is still there, smoke comes out at the edge + damagePos += vecDAMAGE_ENGINE_POS_SMALL; + break; + case DOOR_STATUS_SWINGING: + case DOOR_STATUS_MISSING: + // Bonnet is gone, smoke comes out at the engine + damagePos += vecDAMAGE_ENGINE_POS_BIG; + break; + } + + // move fire forward if in first person + if(this == FindPlayerVehicle() && TheCamera.GetLookingForwardFirstPerson()) + if(m_fHealth < 250.0f && m_status != STATUS_WRECKED){ + if(GetModelIndex() == MI_FIRETRUCK) + damagePos += CVector(0.0f, 3.0f, -0.2f); + else + damagePos += CVector(0.0f, 1.2f, -0.8f); + } + + damagePos = GetMatrix()*damagePos; + damagePos.z += 0.15f; + + if(m_fHealth < 250.0f && m_status != STATUS_WRECKED){ + // Car is on fire + + CParticle::AddParticle(PARTICLE_CARFLAME, damagePos, + CVector(0.0f, 0.0f, CGeneral::GetRandomNumberInRange(0.01125f, 0.09f)), + nil, 0.9f); + + CVector coors = damagePos; + coors.x += CGeneral::GetRandomNumberInRange(-0.5625f, 0.5625f), + coors.y += CGeneral::GetRandomNumberInRange(-0.5625f, 0.5625f), + coors.z += CGeneral::GetRandomNumberInRange(0.5625f, 2.25f); + CParticle::AddParticle(PARTICLE_CARFLAME_SMOKE, coors, CVector(0.0f, 0.0f, 0.0f)); + + CParticle::AddParticle(PARTICLE_ENGINE_SMOKE2, damagePos, CVector(0.0f, 0.0f, 0.0f), nil, 0.5f); + + // Blow up car after 5 seconds + m_fFireBlowUpTimer += CTimer::GetTimeStepInMilliseconds(); + if(m_fFireBlowUpTimer > 5000.0f){ + CWorld::Players[CWorld::PlayerInFocus].AwardMoneyForExplosion(this); + BlowUpCar(m_pSetOnFireEntity); + } + }else + m_fFireBlowUpTimer = 0.0f; + + // Decrease car health if engine is damaged badly + if(engineStatus > 225 && m_fHealth > 250.0f) + m_fHealth -= 2.0f; + + ProcessDelayedExplosion(); + + + if(m_bSirenOrAlarm && (CTimer::GetFrameCounter()&7) == 5 && + UsesSiren(GetModelIndex()) && GetModelIndex() != MI_RCBANDIT) + CCarAI::MakeWayForCarWithSiren(this); + + + // Find out how much to shake the pad depending on suspension and ground surface + + float suspShake = 0.0f; + float surfShake = 0.0f; + for(i = 0; i < 4; i++){ + float suspChange = m_aSuspensionSpringRatioPrev[i] - m_aSuspensionSpringRatio[i]; + if(suspChange > 0.3f){ + DMAudio.PlayOneShot(m_audioEntityId, SOUND_CAR_JUMP, suspChange); + if(suspChange > suspShake) + suspShake = suspChange; + } + + uint8 surf = m_aWheelColPoints[i].surfaceB; + if(surf == SURFACE_DIRT || surf == SURFACE_PUDDLE || surf == SURFACE_HEDGE){ + if(surfShake < 0.2f) + surfShake = 0.3f; + }else if(surf == SURFACE_DIRTTRACK || surf == SURFACE_SAND){ + if(surfShake < 0.1f) + surfShake = 0.2f; + }else if(surf == SURFACE_GRASS){ + if(surfShake < 0.05f) + surfShake = 0.1f; + } + + m_aSuspensionSpringRatioPrev[i] = m_aSuspensionSpringRatio[i]; + m_aSuspensionSpringRatio[i] = 1.0f; + } + + // Shake pad + + if((suspShake > 0.0f || surfShake > 0.0f) && m_status == STATUS_PLAYER){ + float speed = m_vecMoveSpeed.MagnitudeSqr(); + if(speed > sq(0.1f)){ + speed = Sqrt(speed); + if(suspShake > 0.0f){ + uint8 freq = min(200.0f*suspShake*speed*2000.0f/m_fMass + 100.0f, 250.0f); + CPad::GetPad(0)->StartShake(20000.0f*CTimer::GetTimeStep()/freq, freq); + }else{ + uint8 freq = min(200.0f*surfShake*speed*2000.0f/m_fMass + 40.0f, 145.0f); + CPad::GetPad(0)->StartShake(5000.0f*CTimer::GetTimeStep()/freq, freq); + } + } + } + + bVehicleColProcessed = false; + + if(!bWarnedPeds) + CCarCtrl::ScanForPedDanger(this); + + + // Turn around at the edge of the world + // TODO: make the numbers defines + + float heading; + if(GetPosition().x > 1900.0f){ + if(m_vecMoveSpeed.x > 0.0f) + m_vecMoveSpeed.x *= -1.0f; + heading = GetForward().Heading(); + if(heading > 0.0f) // going west + SetHeading(-heading); + }else if(GetPosition().x < -1900.0f){ + if(m_vecMoveSpeed.x < 0.0f) + m_vecMoveSpeed.x *= -1.0f; + heading = GetForward().Heading(); + if(heading < 0.0f) // going east + SetHeading(-heading); + } + if(GetPosition().y > 1900.0f){ + if(m_vecMoveSpeed.y > 0.0f) + m_vecMoveSpeed.y *= -1.0f; + heading = GetForward().Heading(); + if(heading < HALFPI && heading > 0.0f) + SetHeading(PI-heading); + else if(heading > -HALFPI && heading < 0.0f) + SetHeading(-PI-heading); + }else if(GetPosition().y < -1900.0f){ + if(m_vecMoveSpeed.y < 0.0f) + m_vecMoveSpeed.y *= -1.0f; + heading = GetForward().Heading(); + if(heading > HALFPI) + SetHeading(PI-heading); + else if(heading < -HALFPI) + SetHeading(-PI-heading); + } + + if(bInfiniteMass){ + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + m_vecTurnSpeed = CVector(0.0f, 0.0f, 0.0f); + m_vecMoveFriction = CVector(0.0f, 0.0f, 0.0f); + m_vecTurnFriction = CVector(0.0f, 0.0f, 0.0f); + }else if(!skipPhysics && + (m_fGasPedal == 0.0f && brake == 0.0f || m_status == STATUS_WRECKED)){ + if(Abs(m_vecMoveSpeed.x) < 0.005f && + Abs(m_vecMoveSpeed.y) < 0.005f && + Abs(m_vecMoveSpeed.z) < 0.005f){ + m_vecMoveSpeed = CVector(0.0f, 0.0f, 0.0f); + m_vecTurnSpeed.z = 0.0f; + } + } } void @@ -1557,7 +1767,7 @@ void CAutomobile::ScanForCrimes(void) { if(FindPlayerVehicle() && FindPlayerVehicle()->IsCar()) - if(FindPlayerVehicle()->m_nAlarmState != -1) + if(FindPlayerVehicle()->IsAlarmOn()) // if player's alarm is on, increase wanted level if((FindPlayerVehicle()->GetPosition() - GetPosition()).MagnitudeSqr() < sq(20.0f)) CWorld::Players[CWorld::PlayerInFocus].m_pPed->SetWantedLevelNoDrop(1); @@ -2064,6 +2274,7 @@ public: STARTPATCHES InjectHook(0x52D170, &CAutomobile_::dtor, PATCH_JUMP); InjectHook(0x52D190, &CAutomobile_::SetModelIndex_, PATCH_JUMP); + InjectHook(0x531470, &CAutomobile_::ProcessControl_, PATCH_JUMP); InjectHook(0x535180, &CAutomobile_::Teleport_, PATCH_JUMP); InjectHook(0x53B270, &CAutomobile_::ProcessEntityCollision_, PATCH_JUMP); InjectHook(0x53B660, &CAutomobile_::ProcessControlInputs_, PATCH_JUMP); diff --git a/src/vehicles/Automobile.h b/src/vehicles/Automobile.h index 69df9bb3..5ff39fed 100644 --- a/src/vehicles/Automobile.h +++ b/src/vehicles/Automobile.h @@ -59,7 +59,7 @@ public: float m_fHeightAboveRoad; float m_fTraction; uint8 stuff6[28]; - float field_530; + float m_fFireBlowUpTimer; CPhysical *m_aGroundPhysical[4]; // physicals touching wheels CVector m_aGroundOffset[4]; // from ground object to colpoint CEntity *m_pSetOnFireEntity; diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index e521a699..b91e4268 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -364,7 +364,7 @@ CVehicle::ExtinguishCarFire(void) CAutomobile *car = (CAutomobile*)this; if(car->Damage.GetEngineStatus() >= 225) car->Damage.SetEngineStatus(215); - car->field_530 = 0.0f; + car->m_fFireBlowUpTimer = 0.0f; } } diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index de74264b..7513c0da 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -130,7 +130,7 @@ public: uint8 m_currentColour1; uint8 m_currentColour2; uint8 m_aExtras[2]; - int16 m_nAlarmState; // m_nWantedStarsOnEnter on DK22 + int16 m_nAlarmState; int16 m_nMissionValue; CPed *pDriver; CPed *pPassengers[8]; @@ -188,7 +188,7 @@ public: uint8 m_nAmmoInClip; // Used to make the guns on boat do a reload (20 by default) int8 field_1FB; int8 field_1FC[4]; - float m_fHealth; // 1000.0f = full health. 0 -> explode + float m_fHealth; // 1000.0f = full health. 250.0f = fire. 0 -> explode uint8 m_nCurrentGear; int8 field_205[3]; float m_fChangeGearTime; @@ -277,6 +277,8 @@ public: void RemoveDriver(void); void ProcessCarAlarm(void); bool IsSphereTouchingVehicle(float sx, float sy, float sz, float radius); + + bool IsAlarmOn(void) { return m_nAlarmState != 0 && m_nAlarmState != -1; } static bool &bWheelsOnlyCheat; static bool &bAllDodosCheat; -- cgit v1.2.3