diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/render/WaterLevel.h | 2 | ||||
-rw-r--r-- | src/vehicles/Boat.cpp | 248 | ||||
-rw-r--r-- | src/vehicles/Boat.h | 23 |
3 files changed, 264 insertions, 9 deletions
diff --git a/src/render/WaterLevel.h b/src/render/WaterLevel.h index afc6eac3..827e83d2 100644 --- a/src/render/WaterLevel.h +++ b/src/render/WaterLevel.h @@ -64,6 +64,8 @@ #define MAX_BOAT_WAKES 8 +extern RwRaster*& gpWaterRaster; + class CWaterLevel { static int32 ms_nNoOfWaterLevels; diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index f614b78f..71c3374b 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -1,6 +1,12 @@ #include "common.h" #include "patcher.h" #include "Boat.h" +#include "HandlingMgr.h" +#include "RwHelper.h" +#include "ModelIndices.h" +#include "WaterLevel.h" +#include "Pools.h" +#include "World.h" float &fShapeLength = *(float*)0x600E78; float &fShapeTime = *(float*)0x600E7C; @@ -13,14 +19,195 @@ float WAKE_LIFETIME = 400.0f; CBoat * (&CBoat::apFrameWakeGeneratingBoats)[4] = *(CBoat * (*)[4])*(uintptr*)0x8620E0; -CBoat::CBoat(int mi, uint8 owner) +WRAPPER void CBoat::ProcessControl() { EAXJMP(0x53EF10); } +WRAPPER void CBoat::ProcessControlInputs(uint8) { EAXJMP(0x53EC70); } +WRAPPER void CBoat::BlowUpCar(CEntity* ent) { EAXJMP(0x541CB0); } + +CBoat::CBoat(int mi, uint8 owner) : CVehicle(owner) +{ + CVehicleModelInfo *minfo = (CVehicleModelInfo*)CModelInfo::GetModelInfo(mi); + m_vehType = VEHICLE_TYPE_BOAT; + m_fAccelerate = 0.0f; + m_fBrake = 0.0f; + m_fSteeringLeftRight = 0.0f; + m_nPadID = 0; + m_fMovingHiRotation = 0.0f; + SetModelIndex(mi); + + pHandling = mod_HandlingManager.GetHandlingData((eHandlingId)minfo->m_handlingId); + minfo->ChooseVehicleColour(m_currentColour1, m_currentColour2); + + m_fMass = pHandling->fMass; + m_fTurnMass = pHandling->fTurnMass / 2.0f; + m_vecCentreOfMass = pHandling->CentreOfMass; + m_fAirResistance = pHandling->Dimension.x * pHandling->Dimension.z / m_fMass; + m_fElasticity = 0.1f; + m_fBuoyancy = pHandling->fBuoyancy; + m_fSteerAngle = 0.0f; + m_fGasPedal = 0.0f; + m_fBrakePedal = 0.0f; + + field_288 = 0.25f; + field_28C = 0.35f; + field_290 = 0.7f; + field_294 = 0.998f; + field_298 = 0.999f; + field_29C = 0.85f; + field_2A0 = 0.96f; + field_2A4 = 0.96f; + _unk2 = false; + + m_fTurnForceZ = 7.0f; + field_2FC = 7.0f; + m_vecMoveForce = CVector(0.0f, 0.0f, 0.0f); + + field_300 = 0; + m_bBoatFlag1 = true; + m_bBoatFlag2 = true; + + bIsInWater = true; + + unk1 = 0.0f; + m_bIsAnchored = true; + field_2C4 = -9999.99f; + m_flagD8 = true; + field_2CC = 0.0f; + field_2D0 = 0; + m_nNumWakePoints = 0; + + for (int16 i = 0; i < 32; i++) + m_afWakePointLifeTime[i] = 0.0f; + + m_nAmmoInClip = 20; +} + +void +CBoat::SetModelIndex(uint32 id) +{ + CEntity::SetModelIndex(id); + SetupModelNodes(); +} + +void +CBoat::GetComponentWorldPosition(int32 component, CVector &pos) { - ctor(mi, owner); + pos = *RwMatrixGetPos(RwFrameGetLTM(m_aBoatNodes[component])); } -WRAPPER CBoat* CBoat::ctor(int, uint8) { EAXJMP(0x53E3E0); } +RxObjSpace3DVertex KeepWaterOutVertices[4]; +RwImVertexIndex KeepWaterOutIndices[6]; -bool CBoat::IsSectorAffectedByWake(CVector2D sector, float fSize, CBoat **apBoats) +void +CBoat::Render() +{ + CMatrix matrix; + + if (m_aBoatNodes[1] != nil) { + matrix.Attach(&m_aBoatNodes[1]->modelling); + + CVector pos = matrix.GetPosition(); + matrix.SetRotateZOnly(m_fMovingHiRotation); + matrix.Translate(pos); + + matrix.UpdateRW(); + if (CVehicle::bWheelsOnlyCheat) { + RpAtomicRenderMacro((RpAtomic*)GetFirstObject(m_aBoatNodes[1])); + } + } + m_fMovingHiRotation += 0.05f; + ((CVehicleModelInfo*)CModelInfo::GetModelInfo(GetModelIndex()))->SetVehicleColour(m_currentColour1, m_currentColour2); + if (!CVehicle::bWheelsOnlyCheat) + CEntity::Render(); + KeepWaterOutVertices[0].color = -1; + KeepWaterOutIndices[0] = 0; + KeepWaterOutVertices[1].color = -1; + KeepWaterOutIndices[1] = 2; + KeepWaterOutVertices[2].color = -1; + KeepWaterOutIndices[2] = 1; + KeepWaterOutVertices[3].color = -1; + KeepWaterOutIndices[3] = 1; + KeepWaterOutIndices[4] = 2; + KeepWaterOutIndices[5] = 3; + switch (GetModelIndex()) { + case MI_SPEEDER: + KeepWaterOutVertices[0].objVertex.x = -1.15f; + KeepWaterOutVertices[0].objVertex.y = 3.61f; + KeepWaterOutVertices[0].objVertex.z = 1.03f; + KeepWaterOutVertices[1].objVertex.x = 1.15f; + KeepWaterOutVertices[1].objVertex.y = 3.61f; + KeepWaterOutVertices[1].objVertex.z = 1.03f; + KeepWaterOutVertices[2].objVertex.x = -1.15f; + KeepWaterOutVertices[2].objVertex.y = 0.06f; + KeepWaterOutVertices[2].objVertex.z = 1.03f; + KeepWaterOutVertices[3].objVertex.x = 1.15f; + KeepWaterOutVertices[3].objVertex.y = 0.06f; + KeepWaterOutVertices[3].objVertex.z = 1.03f; + break; + case MI_REEFER: + KeepWaterOutVertices[2].objVertex.x = -1.9f; + KeepWaterOutVertices[2].objVertex.y = 2.83f; + KeepWaterOutVertices[2].objVertex.z = 1.0f; + KeepWaterOutVertices[3].objVertex.x = 1.9f; + KeepWaterOutVertices[3].objVertex.y = 2.83f; + KeepWaterOutVertices[3].objVertex.z = 1.0f; + KeepWaterOutVertices[0].objVertex.x = -1.66f; + KeepWaterOutVertices[0].objVertex.y = -4.48f; + KeepWaterOutVertices[0].objVertex.z = 0.83f; + KeepWaterOutVertices[1].objVertex.x = 1.66f; + KeepWaterOutVertices[1].objVertex.y = -4.48f; + KeepWaterOutVertices[1].objVertex.z = 0.83f; + break; + case MI_PREDATOR: + default: + KeepWaterOutVertices[0].objVertex.x = -1.45f; + KeepWaterOutVertices[0].objVertex.y = 1.9f; + KeepWaterOutVertices[0].objVertex.z = 0.96f; + KeepWaterOutVertices[1].objVertex.x = 1.45f; + KeepWaterOutVertices[1].objVertex.y = 1.9f; + KeepWaterOutVertices[1].objVertex.z = 0.96f; + KeepWaterOutVertices[2].objVertex.x = -1.45f; + KeepWaterOutVertices[2].objVertex.y = -3.75f; + KeepWaterOutVertices[2].objVertex.z = 0.96f; + KeepWaterOutVertices[3].objVertex.x = 1.45f; + KeepWaterOutVertices[3].objVertex.y = -3.75f; + KeepWaterOutVertices[3].objVertex.z = 0.96f; + break; + } + KeepWaterOutVertices[0].u = 0.0f; + KeepWaterOutVertices[0].v = 0.0f; + KeepWaterOutVertices[1].u = 1.0f; + KeepWaterOutVertices[1].v = 0.0f; + KeepWaterOutVertices[2].u = 0.0f; + KeepWaterOutVertices[2].v = 1.0f; + KeepWaterOutVertices[3].u = 1.0f; + KeepWaterOutVertices[3].v = 1.0f; + RwRenderStateSet(rwRENDERSTATETEXTURERASTER, gpWaterRaster); + RwRenderStateSet(rwRENDERSTATEVERTEXALPHAENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)FALSE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDZERO); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDONE); + if (!CVehicle::bWheelsOnlyCheat && RwIm3DTransform(KeepWaterOutVertices, 4, GetMatrix().m_attachment, rwIM3D_VERTEXUV)) { + RwIm3DRenderIndexedPrimitive(rwPRIMTYPETRILIST, KeepWaterOutIndices, 6); + RwIm3DEnd(); + } + RwRenderStateSet(rwRENDERSTATEFOGENABLE, (void*)TRUE); + RwRenderStateSet(rwRENDERSTATESRCBLEND, (void*)rwBLENDSRCALPHA); + RwRenderStateSet(rwRENDERSTATEDESTBLEND, (void*)rwBLENDINVSRCALPHA); +} + +void +CBoat::Teleport(CVector v) +{ + CWorld::Remove(this); + GetPosition() = v; + SetOrientation(0.0f, 0.0f, 0.0f); + SetMoveSpeed(0.0f, 0.0f, 0.0f); + SetTurnSpeed(0.0f, 0.0f, 0.0f); + CWorld::Add(this); +} + +bool +CBoat::IsSectorAffectedByWake(CVector2D sector, float fSize, CBoat **apBoats) { uint8 numVerts = 0; @@ -50,7 +237,8 @@ bool CBoat::IsSectorAffectedByWake(CVector2D sector, float fSize, CBoat **apBoat return numVerts != 0; } -float CBoat::IsVertexAffectedByWake(CVector vecVertex, CBoat *pBoat) +float +CBoat::IsVertexAffectedByWake(CVector vecVertex, CBoat *pBoat) { for ( int i = 0; i < pBoat->m_nNumWakePoints; i++ ) { @@ -67,14 +255,62 @@ float CBoat::IsVertexAffectedByWake(CVector vecVertex, CBoat *pBoat) return 0.0f; } -WRAPPER void CBoat::FillBoatList(void) { EAXJMP(0x542250); } +void +CBoat::SetupModelNodes() +{ + m_aBoatNodes[0] = nil; + m_aBoatNodes[1] = nil; + m_aBoatNodes[2] = nil; + m_aBoatNodes[3] = nil; + CClumpModelInfo::FillFrameArray(GetClump(), m_aBoatNodes); +} + +void +CBoat::FillBoatList() +{ + int16 frameId = 0; + + apFrameWakeGeneratingBoats[0] = nil; + apFrameWakeGeneratingBoats[1] = nil; + apFrameWakeGeneratingBoats[2] = nil; + apFrameWakeGeneratingBoats[3] = nil; + + for (int i = CPools::GetVehiclePool()->GetSize() - 1; i >= 0; i--) { + CBoat *boat = (CBoat *)(CPools::GetVehiclePool()->GetSlot(i)); + if (boat && boat->m_vehType == VEHICLE_TYPE_BOAT) { + int16 nNumWakePoints = boat->m_nNumWakePoints; + if (nNumWakePoints != 0) { + if (frameId >= ARRAY_SIZE(apFrameWakeGeneratingBoats)) { + int16 frameId2 = -1; + for (int16 j = 0; j < ARRAY_SIZE(apFrameWakeGeneratingBoats); j++) { + if (apFrameWakeGeneratingBoats[j]->m_nNumWakePoints < nNumWakePoints) { + frameId2 = j; + nNumWakePoints = apFrameWakeGeneratingBoats[j]->m_nNumWakePoints; + } + } + + if (frameId2 != -1) + apFrameWakeGeneratingBoats[frameId2] = boat; + } else { + apFrameWakeGeneratingBoats[frameId++] = boat; + } + } + } + } +} class CBoat_ : public CBoat { public: + CBoat* ctor(int32 id, uint8 CreatedBy) { return ::new (this) CBoat(id, CreatedBy); } void dtor() { CBoat::~CBoat(); }; }; STARTPATCHES + InjectHook(0x53E3E0, &CBoat_::ctor, PATCH_JUMP); InjectHook(0x53E790, &CBoat_::dtor, PATCH_JUMP); + InjectHook(0x53E7D0, &CBoat::SetupModelNodes, PATCH_JUMP); + InjectHook(0x542370, CBoat::IsSectorAffectedByWake, PATCH_JUMP); + InjectHook(0x5424A0, CBoat::IsVertexAffectedByWake, PATCH_JUMP); + InjectHook(0x542250, CBoat::FillBoatList, PATCH_JUMP); ENDPATCHES diff --git a/src/vehicles/Boat.h b/src/vehicles/Boat.h index 52f3530c..d3a2ac13 100644 --- a/src/vehicles/Boat.h +++ b/src/vehicles/Boat.h @@ -17,7 +17,14 @@ public: float m_fMovingHiRotation; int32 _unk0; RwFrame *m_aBoatNodes[4]; - uint8 m_nBoatFlags; + uint8 m_bBoatFlag1 : 1; + uint8 m_bBoatFlag2 : 1; + uint8 m_bBoatFlag3 : 1; + uint8 m_bBoatFlag4 : 1; + uint8 m_bBoatFlag5 : 1; + uint8 m_bBoatFlag6 : 1; + uint8 m_bBoatFlag7 : 1; + uint8 m_bBoatFlag8 : 1; bool m_bIsAnchored; char _pad0[2]; float field_2C4; @@ -41,9 +48,19 @@ public: float m_afWakePointLifeTime[32]; CBoat(int, uint8); - CBoat* ctor(int, uint8); - void dtor() { this->CBoat::~CBoat(); }; + + virtual void SetModelIndex(uint32 id); + virtual void ProcessControl(); + virtual void Teleport(CVector v); + virtual void PreRender(void) {}; + virtual void Render(void); + virtual void ProcessControlInputs(uint8); + virtual void GetComponentWorldPosition(int32 component, CVector &pos); + virtual bool IsComponentPresent(int32 component) { return true; } + virtual void BlowUpCar(CEntity *ent); + void SetupModelNodes(); + static CBoat *(&apFrameWakeGeneratingBoats)[4]; static bool IsSectorAffectedByWake(CVector2D sector, float fSize, CBoat **apBoats); |