summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/render/WaterLevel.h2
-rw-r--r--src/vehicles/Boat.cpp248
-rw-r--r--src/vehicles/Boat.h23
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);