Refactoring `CTrailer` (#1117)
This commit is contained in:
parent
7282a4644c
commit
0dd2b020cc
|
|
@ -387,7 +387,7 @@ CAutomobile::CAutomobile(int32 modelIndex, eVehicleCreatedBy createdBy, bool set
|
||||||
|
|
||||||
m_fDoomVerticalRotation = 0.0f;
|
m_fDoomVerticalRotation = 0.0f;
|
||||||
m_fDoomHorizontalRotation = 0.05f;
|
m_fDoomHorizontalRotation = 0.05f;
|
||||||
m_fUpDownLightAngle[0] = 0.0f;
|
m_fPropRotate = 0.0f;
|
||||||
m_fForcedOrientation = -1.0f;
|
m_fForcedOrientation = -1.0f;
|
||||||
m_harvesterParticleCounter = 0;
|
m_harvesterParticleCounter = 0;
|
||||||
RightDoorOpenForDriveBys = 0.f;
|
RightDoorOpenForDriveBys = 0.f;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@
|
||||||
#include "eCarWheel.h"
|
#include "eCarWheel.h"
|
||||||
#include "eCarNodes.h"
|
#include "eCarNodes.h"
|
||||||
|
|
||||||
|
constexpr float BILLS_EXTENSION_LIMIT = 1.0f;
|
||||||
|
|
||||||
enum class eSkidmarkType : uint32;
|
enum class eSkidmarkType : uint32;
|
||||||
|
|
||||||
class CVehicleModelInfo;
|
class CVehicleModelInfo;
|
||||||
|
|
@ -108,7 +110,8 @@ public:
|
||||||
float m_fDoomVerticalRotation;
|
float m_fDoomVerticalRotation;
|
||||||
float m_fDoomHorizontalRotation;
|
float m_fDoomHorizontalRotation;
|
||||||
float m_fForcedOrientation;
|
float m_fForcedOrientation;
|
||||||
std::array<float, 2> m_fUpDownLightAngle;
|
float m_fPropRotate;
|
||||||
|
float m_fCumulativeDamage;
|
||||||
uint8 m_nNumContactWheels;
|
uint8 m_nNumContactWheels;
|
||||||
uint8 m_NumDriveWheelsOnGround;
|
uint8 m_NumDriveWheelsOnGround;
|
||||||
uint8 m_NumDriveWheelsOnGroundLastFrame;
|
uint8 m_NumDriveWheelsOnGroundLastFrame;
|
||||||
|
|
|
||||||
|
|
@ -3,28 +3,34 @@
|
||||||
#include "Trailer.h"
|
#include "Trailer.h"
|
||||||
#include "VehicleRecording.h"
|
#include "VehicleRecording.h"
|
||||||
|
|
||||||
static float TRAILER_TOWED_MINRATIO = 0.9f; // 0x8D346C
|
// define?
|
||||||
static float RELINK_TRAILER_DIFF_LIMIT_XY = 0.4f; // 0x8D3470
|
constexpr float BAGGAGE_TRAILER_TOWED_RATIO = -1000.0f;
|
||||||
static float RELINK_TRAILER_DIFF_LIMIT_Z = 1.0f; // 0x8D3474
|
|
||||||
static float m_fTrailerSuspensionForce = 1.5f; // 0x8D3464
|
float TRAILER_TOWED_MINRATIO = 0.9f; // 0x8D346C
|
||||||
static float m_fTrailerDampingForce = 0.1f; // 0x8D3468
|
constexpr float TRAILER_SUPPORT_RETRACTION_RATE = 0.002f; // 0x871C14
|
||||||
|
constexpr float TRAILER_SUPPORT_EXTENSION_RATE = 0.002f; // 0x871C18
|
||||||
|
constexpr float TRAILER_SUPPORT_WAIT_EXTENSION_RATE = 0.0005f; // 0x871C1C
|
||||||
|
|
||||||
|
float TRAILER_TOWBAR_OFFSET_Y = -0.05f; // 0x871C20
|
||||||
|
|
||||||
|
float RELINK_TRAILER_DIFF_LIMIT_XY = 0.4f; // 0x8D3470
|
||||||
|
float RELINK_TRAILER_DIFF_LIMIT_Z = 1.0f; // 0x8D3474
|
||||||
|
|
||||||
void CTrailer::InjectHooks() {
|
void CTrailer::InjectHooks() {
|
||||||
RH_ScopedVirtualClass(CTrailer, 0x871c28, 71);
|
RH_ScopedVirtualClass(CTrailer, 0x871c28, 71);
|
||||||
RH_ScopedCategory("Vehicle");
|
RH_ScopedCategory("Vehicle");
|
||||||
|
|
||||||
RH_ScopedInstall(Constructor, 0x6D03A0);
|
RH_ScopedInstall(Constructor, 0x6D03A0);
|
||||||
|
|
||||||
RH_ScopedInstall(ScanForTowLink, 0x6CF030);
|
RH_ScopedInstall(ScanForTowLink, 0x6CF030);
|
||||||
|
|
||||||
RH_ScopedVMTInstall(SetupSuspensionLines, 0x6CF1A0, { .reversed = false });
|
RH_ScopedVMTInstall(SetupSuspensionLines, 0x6CF1A0);
|
||||||
RH_ScopedVMTInstall(SetTowLink, 0x6CFDF0);
|
RH_ScopedVMTInstall(SetTowLink, 0x6CFDF0);
|
||||||
RH_ScopedVMTInstall(ResetSuspension, 0x6CEE50);
|
RH_ScopedVMTInstall(ResetSuspension, 0x6CEE50);
|
||||||
RH_ScopedVMTInstall(ProcessSuspension, 0x6CF6A0, { .reversed = false });
|
RH_ScopedVMTInstall(ProcessSuspension, 0x6CF6A0);
|
||||||
RH_ScopedVMTInstall(ProcessEntityCollision, 0x6CFFD0);
|
RH_ScopedVMTInstall(ProcessEntityCollision, 0x6CFFD0);
|
||||||
RH_ScopedVMTInstall(ProcessControl, 0x6CED20, { .reversed = false });
|
RH_ScopedVMTInstall(ProcessControl, 0x6CED20);
|
||||||
RH_ScopedVMTInstall(ProcessAI, 0x6CF590, { .reversed = false });
|
RH_ScopedVMTInstall(ProcessAI, 0x6CF590);
|
||||||
RH_ScopedVMTInstall(PreRender, 0x6CFAC0, { .reversed = false });
|
RH_ScopedVMTInstall(PreRender, 0x6CFAC0);
|
||||||
RH_ScopedVMTInstall(GetTowHitchPos, 0x6CEEA0);
|
RH_ScopedVMTInstall(GetTowHitchPos, 0x6CEEA0);
|
||||||
RH_ScopedVMTInstall(GetTowBarPos, 0x6CFD60);
|
RH_ScopedVMTInstall(GetTowBarPos, 0x6CFD60);
|
||||||
RH_ScopedVMTInstall(BreakTowLink, 0x6CEFB0);
|
RH_ScopedVMTInstall(BreakTowLink, 0x6CEFB0);
|
||||||
|
|
@ -34,17 +40,100 @@ void CTrailer::InjectHooks() {
|
||||||
CTrailer::CTrailer(int32 modelIndex, eVehicleCreatedBy createdBy) : CAutomobile(modelIndex, createdBy, false) {
|
CTrailer::CTrailer(int32 modelIndex, eVehicleCreatedBy createdBy) : CAutomobile(modelIndex, createdBy, false) {
|
||||||
m_nVehicleSubType = VEHICLE_TYPE_TRAILER;
|
m_nVehicleSubType = VEHICLE_TYPE_TRAILER;
|
||||||
|
|
||||||
if (m_nModelIndex == MODEL_BAGBOXA || m_nModelIndex == MODEL_BAGBOXB)
|
if (m_nModelIndex == MODEL_BAGBOXA || m_nModelIndex == MODEL_BAGBOXB) {
|
||||||
m_fTrailerTowedRatio = -1000.0f;
|
m_fTrailerTowedRatio = BAGGAGE_TRAILER_TOWED_RATIO;
|
||||||
|
}
|
||||||
|
|
||||||
CTrailer::SetupSuspensionLines();
|
SetupSuspensionLines();
|
||||||
|
SetStatus(eEntityStatus::STATUS_ABANDONED);
|
||||||
m_nStatus = eEntityStatus::STATUS_ABANDONED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x6CF1A0
|
// 0x6CF1A0
|
||||||
void CTrailer::SetupSuspensionLines() {
|
void CTrailer::SetupSuspensionLines() {
|
||||||
plugin::CallMethod<0x6CF1A0, CTrailer*>(this);
|
if (m_fTrailerTowedRatio == BAGGAGE_TRAILER_TOWED_RATIO) {
|
||||||
|
CAutomobile::SetupSuspensionLines();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* mi = CModelInfo::ms_modelInfoPtrs[m_nModelIndex]->AsVehicleModelInfoPtr();
|
||||||
|
CColModel* cl = GetColModel();
|
||||||
|
|
||||||
|
CCollisionData* colData = cl->m_pColData;
|
||||||
|
|
||||||
|
if (!colData->m_pLines) {
|
||||||
|
colData->m_nNumLines = NUM_TRAILER_SUSP_LINES;
|
||||||
|
colData->m_pLines = (CColLine*)CMemoryMgr::Malloc(sizeof(CColLine) * NUM_TRAILER_SUSP_LINES);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int32 i = 0; i < NUM_TRAILER_WHEELS; ++i) {
|
||||||
|
CVector wheelPos;
|
||||||
|
mi->GetWheelPosn(i, wheelPos, false);
|
||||||
|
m_wheelPosition[i] = wheelPos.z;
|
||||||
|
|
||||||
|
CVector lineStart = wheelPos;
|
||||||
|
lineStart.z += m_pHandlingData->m_fSuspensionUpperLimit;
|
||||||
|
colData->m_pLines[i].m_vecStart = lineStart;
|
||||||
|
|
||||||
|
CVector lineEnd = lineStart;
|
||||||
|
lineEnd.z += m_pHandlingData->m_fSuspensionLowerLimit - m_pHandlingData->m_fSuspensionUpperLimit - mi->m_fWheelSizeFront / 2;
|
||||||
|
colData->m_pLines[i].m_vecEnd = lineEnd;
|
||||||
|
|
||||||
|
m_aSuspensionSpringLength[i] = m_pHandlingData->m_fSuspensionUpperLimit - m_pHandlingData->m_fSuspensionLowerLimit;
|
||||||
|
m_aSuspensionLineLength[i] = colData->m_pLines[i].m_vecStart.z - colData->m_pLines[i].m_vecEnd.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
cl->m_boundBox.m_vecMin.z = std::min(cl->m_boundBox.m_vecMin.z, colData->m_pLines[0].m_vecEnd.z);
|
||||||
|
|
||||||
|
// 0x6CF313
|
||||||
|
const float maxDistSq = std::max(cl->m_boundBox.m_vecMin.Magnitude(), cl->m_boundBox.m_vecMax.Magnitude());
|
||||||
|
cl->m_boundSphere.m_fRadius = std::max(cl->m_boundSphere.m_fRadius, maxDistSq);
|
||||||
|
|
||||||
|
if (m_aCarNodes[TRAILER_MISC_A]) {
|
||||||
|
RwMatrix matrix;
|
||||||
|
RwFrame* wheelFront = m_aCarNodes[TRAILER_MISC_A];
|
||||||
|
matrix = *RwFrameGetMatrix(wheelFront);
|
||||||
|
|
||||||
|
if (auto parent = RwFrameGetParent(wheelFront)) {
|
||||||
|
do {
|
||||||
|
RwMatrixTransform(&matrix, RwFrameGetMatrix(parent), rwCOMBINEPOSTCONCAT);
|
||||||
|
parent = RwFrameGetParent(parent);
|
||||||
|
} while (parent != wheelFront && parent);
|
||||||
|
}
|
||||||
|
m_fHeight = matrix.pos.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
CColLine* supportLines = &colData->m_pLines[NUM_TRAILER_WHEELS];
|
||||||
|
for (int32 i = 0; i < NUM_TRAILER_SUPPORTS; ++i) {
|
||||||
|
CVector startPos;
|
||||||
|
startPos.x = (i == 0) ? cl->m_boundBox.m_vecMin.x : -cl->m_boundBox.m_vecMin.x;
|
||||||
|
startPos.y = cl->m_boundBox.m_vecMax.y;
|
||||||
|
startPos.z = cl->m_boundBox.m_vecMax.z;
|
||||||
|
supportLines[i].m_vecStart = startPos;
|
||||||
|
|
||||||
|
CVector endPos = startPos;
|
||||||
|
endPos.z = cl->m_boundBox.m_vecMin.z;
|
||||||
|
supportLines[i].m_vecEnd = endPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
const float supportLegY = fabs(supportLines[0].m_vecStart.y);
|
||||||
|
const float avgWheelY = (fabs(colData->m_pLines[0].m_vecStart.y) + fabs(colData->m_pLines[1].m_vecStart.y)) * 0.5f;
|
||||||
|
const float weightRatio = supportLegY / (avgWheelY + supportLegY);
|
||||||
|
|
||||||
|
const float suspensionForceFactor = m_pHandlingData->m_fSuspensionForceLevel * 4.0f;
|
||||||
|
const float heightAboveRoad = m_aSuspensionSpringLength[0] * (1.0f - weightRatio / suspensionForceFactor)
|
||||||
|
+ mi->m_fWheelSizeFront / 2 - colData->m_pLines[0].m_vecStart.z;
|
||||||
|
|
||||||
|
m_fFrontHeightAboveRoad = heightAboveRoad;
|
||||||
|
m_fRearHeightAboveRoad = heightAboveRoad;
|
||||||
|
|
||||||
|
const float supportForce = CTrailer::m_fTrailerSuspensionForce * 2.0f;
|
||||||
|
const float newEndZ = supportLines[0].m_vecStart.z - (supportLines[0].m_vecStart.z + heightAboveRoad)
|
||||||
|
/ (1.0f - (1.0f - weightRatio) / supportForce);
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_TRAILER_SUPPORTS; ++i) {
|
||||||
|
supportLines[i].m_vecEnd.z = newEndZ;
|
||||||
|
m_wheelPosition[i] = mi->m_fWheelSizeFront / 2 - m_fFrontHeightAboveRoad;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x6CFDF0
|
// 0x6CFDF0
|
||||||
|
|
@ -53,11 +142,12 @@ bool CTrailer::SetTowLink(CVehicle* vehicle, bool setMyPosToTowBar) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_nStatus != STATUS_PHYSICS && m_nStatus != STATUS_IS_TOWED && m_nStatus != STATUS_ABANDONED) {
|
const auto status = GetStatus();
|
||||||
|
if (status != STATUS_PHYSICS && status != STATUS_IS_TOWED && status != STATUS_ABANDONED) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_nStatus = STATUS_IS_TOWED;
|
SetStatus(STATUS_IS_TOWED);
|
||||||
|
|
||||||
m_pTowingVehicle = vehicle;
|
m_pTowingVehicle = vehicle;
|
||||||
m_pTowingVehicle->RegisterReference(m_pTowingVehicle);
|
m_pTowingVehicle->RegisterReference(m_pTowingVehicle);
|
||||||
|
|
@ -71,24 +161,20 @@ bool CTrailer::SetTowLink(CVehicle* vehicle, bool setMyPosToTowBar) {
|
||||||
AddToMovingList();
|
AddToMovingList();
|
||||||
vehicle->AddToMovingList();
|
vehicle->AddToMovingList();
|
||||||
|
|
||||||
vehicle->m_pVehicleBeingTowed->vehicleFlags.bLightsOn = true; // NOTSA | FIX_BUGS
|
|
||||||
|
|
||||||
if (!setMyPosToTowBar) {
|
if (!setMyPosToTowBar) {
|
||||||
UpdateTractorLink(true, false);
|
UpdateTractorLink(true, false);
|
||||||
vehicle->m_vehicleAudio.AddAudioEvent(AE_TRAILER_ATTACH, 0.0f);
|
vehicle->m_vehicleAudio.AddAudioEvent(AE_TRAILER_ATTACH, 0.0f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_fTrailerTowedRatio > -1000.0f) {
|
m_fTrailerTowedRatio = std::clamp(m_fTrailerTowedRatio, 0.0f, BAGGAGE_TRAILER_TOWED_RATIO);
|
||||||
m_fTrailerTowedRatio = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetHeading(GetHeading());
|
SetHeading(GetHeading());
|
||||||
|
|
||||||
auto towBarPos = CVector{};
|
CVector towBarPos{}, towHitchPos{};
|
||||||
auto towHitchPos = CVector{};
|
if (!GetTowHitchPos(towHitchPos, true, this) || !vehicle->GetTowBarPos(towBarPos, true, this)) {
|
||||||
if (!GetTowHitchPos(towHitchPos, true, this) || !vehicle->GetTowBarPos(towBarPos, true, this))
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
towHitchPos -= GetPosition();
|
towHitchPos -= GetPosition();
|
||||||
|
|
||||||
|
|
@ -102,33 +188,34 @@ bool CTrailer::SetTowLink(CVehicle* vehicle, bool setMyPosToTowBar) {
|
||||||
|
|
||||||
// 0x6CF030
|
// 0x6CF030
|
||||||
void CTrailer::ScanForTowLink() {
|
void CTrailer::ScanForTowLink() {
|
||||||
if (m_pTowingVehicle || CVehicleRecording::IsPlaybackGoingOnForCar(this) || m_nModelIndex == MODEL_FARMTR1)
|
if (m_pTowingVehicle || CVehicleRecording::IsPlaybackGoingOnForCar(this) || m_nModelIndex == MODEL_FARMTR1) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CVector towHitchPos;
|
CVector towHitchPos;
|
||||||
if (!GetTowHitchPos(towHitchPos, false, this))
|
if (!GetTowHitchPos(towHitchPos, false, this)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int16 count = 0;
|
int16 count = 0;
|
||||||
CEntity* objects[16]{};
|
std::array<CEntity*, 16> objects{};
|
||||||
CWorld::FindObjectsInRange(towHitchPos, 10.0f, true, &count, int16(std::size(objects)), objects, false, true, false, false, false);
|
CWorld::FindObjectsInRange(towHitchPos, 10.0f, true, &count, int16(objects.size()), objects.data(), false, true, false, false, false);
|
||||||
|
|
||||||
CVector towBarPos;
|
for (const auto& entity : std::span{ objects.data(), (size_t)count }) {
|
||||||
CVehicle* vehicle = nullptr;
|
if (auto* vehicle = entity->AsVehicle()) {
|
||||||
for (auto& obj : std::span{ objects, (size_t)count }) {
|
if (vehicle == this) {
|
||||||
vehicle = obj->AsVehicle();
|
continue;
|
||||||
if (vehicle == this) {
|
}
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!vehicle->GetTowBarPos(towBarPos, false, this)) {
|
CVector towBarPos;
|
||||||
continue;
|
if (!vehicle->GetTowBarPos(towBarPos, false, this)) {
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const auto dist = DistanceBetweenPoints2D(towBarPos, towHitchPos);
|
if (DistanceBetweenPoints2D(towBarPos, towHitchPos) < RELINK_TRAILER_DIFF_LIMIT_XY && std::fabs(towHitchPos.z - towBarPos.z) < RELINK_TRAILER_DIFF_LIMIT_Z) {
|
||||||
if (dist < RELINK_TRAILER_DIFF_LIMIT_XY && std::fabs(towHitchPos.z - towBarPos.z) < RELINK_TRAILER_DIFF_LIMIT_Z) {
|
SetTowLink(vehicle, false);
|
||||||
SetTowLink(vehicle, false);
|
return;
|
||||||
return;
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -137,24 +224,73 @@ void CTrailer::ScanForTowLink() {
|
||||||
void CTrailer::ResetSuspension() {
|
void CTrailer::ResetSuspension() {
|
||||||
CAutomobile::ResetSuspension();
|
CAutomobile::ResetSuspension();
|
||||||
rng::fill(m_supportRatios, 1.f);
|
rng::fill(m_supportRatios, 1.f);
|
||||||
if (m_pTowingVehicle && m_fTrailerTowedRatio > -1000.0f)
|
if (m_pTowingVehicle && m_fTrailerTowedRatio > BAGGAGE_TRAILER_TOWED_RATIO) {
|
||||||
m_fTrailerTowedRatio = 0.0f;
|
m_fTrailerTowedRatio = 0.0f;
|
||||||
else
|
} else {
|
||||||
m_fTrailerTowedRatio = 1.0f;
|
m_fTrailerTowedRatio = 1.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x6CF6A0
|
// 0x6CF6A0
|
||||||
void CTrailer::ProcessSuspension() {
|
void CTrailer::ProcessSuspension() {
|
||||||
plugin::CallMethod<0x6CF6A0, CTrailer*>(this);
|
CAutomobile::ProcessSuspension();
|
||||||
|
if (m_fTrailerTowedRatio == BAGGAGE_TRAILER_TOWED_RATIO) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CVector contactPoints[NUM_TRAILER_SUPPORTS]{};
|
||||||
|
CVector contactSpeeds[NUM_TRAILER_SUPPORTS]{};
|
||||||
|
float impulseMagnitudes[NUM_TRAILER_SUPPORTS]{};
|
||||||
|
|
||||||
|
for (int32 i = 0; i < NUM_TRAILER_SUPPORTS; ++i) {
|
||||||
|
if (m_supportRatios[i] < m_fTrailerTowedRatio2 && m_fTrailerTowedRatio2 > 0.1f) {
|
||||||
|
CVector forceDir = m_matrix->GetDown();
|
||||||
|
|
||||||
|
contactPoints[i] = m_supportCPs[i].m_vecPoint - GetPosition();
|
||||||
|
|
||||||
|
const float compression = m_supportRatios[i] / m_fTrailerTowedRatio2;
|
||||||
|
|
||||||
|
CPhysical::ApplySpringCollisionAlt(m_fTrailerSuspensionForce, forceDir, contactPoints[i], compression, 1.0f, m_supportCPs[i].m_vecNormal, impulseMagnitudes[i]);
|
||||||
|
|
||||||
|
contactSpeeds[i] = GetSpeed(contactPoints[i]);
|
||||||
|
|
||||||
|
CVector dampeningDir = m_supportCPs[i].m_vecNormal.z > 0.35f
|
||||||
|
? -m_supportCPs[i].m_vecNormal
|
||||||
|
: m_matrix->GetDown();
|
||||||
|
|
||||||
|
CPhysical::ApplySpringDampening(m_fTrailerDampingForce, impulseMagnitudes[i], dampeningDir, contactPoints[i], contactSpeeds[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto status = GetStatus();
|
||||||
|
if (status != STATUS_IS_TOWED && status != STATUS_IS_SIMPLE_TOWED) {
|
||||||
|
eCarWheelStatus originalWheelStatus[NUM_TRAILER_SUPPORTS];
|
||||||
|
for (int32 i = 0; i < NUM_TRAILER_SUPPORTS; ++i) {
|
||||||
|
originalWheelStatus[i] = m_damageManager.GetWheelStatus((eCarWheel)i);
|
||||||
|
|
||||||
|
if (m_supportRatios[i] >= m_fTrailerTowedRatio2 || m_fTrailerTowedRatio2 <= 0.1f) {
|
||||||
|
m_damageManager.SetWheelStatus((eCarWheel)i, eCarWheelStatus::WHEEL_STATUS_BURST);
|
||||||
|
} else {
|
||||||
|
contactSpeeds[i] = GetSpeed(contactPoints[i]);
|
||||||
|
m_damageManager.SetWheelStatus((eCarWheel)i, eCarWheelStatus::WHEEL_STATUS_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const float traction = m_pHandlingData->m_fTractionMultiplier * 0.004f * 0.25f;
|
||||||
|
CAutomobile::ProcessCarWheelPair(CAR_WHEEL_FRONT_LEFT, CAR_WHEEL_REAR_LEFT, 0.0f, contactSpeeds, contactPoints, traction, 0.0f, 1000.0f, true);
|
||||||
|
|
||||||
|
m_damageManager.SetWheelStatus(CAR_WHEEL_FRONT_LEFT, originalWheelStatus[0]);
|
||||||
|
m_damageManager.SetWheelStatus(CAR_WHEEL_REAR_LEFT, originalWheelStatus[1]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x6CFFD0
|
// 0x6CFFD0
|
||||||
int32 CTrailer::ProcessEntityCollision(CEntity* entity, CColPoint* outColPoints) {
|
int32 CTrailer::ProcessEntityCollision(CEntity* entity, CColPoint* outColPoints) {
|
||||||
if (m_fTrailerTowedRatio == -1000.f) {
|
if (m_fTrailerTowedRatio == BAGGAGE_TRAILER_TOWED_RATIO) {
|
||||||
return CAutomobile::ProcessEntityCollision(entity, outColPoints);
|
return CAutomobile::ProcessEntityCollision(entity, outColPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_nStatus != STATUS_SIMPLE) {
|
if (GetStatus() != STATUS_SIMPLE) {
|
||||||
vehicleFlags.bVehicleColProcessed = true;
|
vehicleFlags.bVehicleColProcessed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -172,16 +308,16 @@ int32 CTrailer::ProcessEntityCollision(CEntity* entity, CColPoint* outColPoints)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hide triangles in some cases
|
// Hide triangles in some cases
|
||||||
const auto didHideTriangles = m_pTowingVehicle == entity || m_pVehicleBeingTowed == entity;
|
const auto shouldHideTriangles = m_pTowingVehicle == entity || m_pVehicleBeingTowed == entity;
|
||||||
const auto tNumTri = tcd->m_nNumTriangles, // Saving my sanity here, and unconditionally assigning
|
const auto originalTNumTri = tcd->m_nNumTriangles, // Saving my sanity here, and unconditionally assigning
|
||||||
oNumTri = ocd->m_nNumTriangles;
|
originalONumTri = ocd->m_nNumTriangles;
|
||||||
if (didHideTriangles) {
|
if (shouldHideTriangles) {
|
||||||
tcd->m_nNumTriangles = ocd->m_nNumTriangles = 0;
|
tcd->m_nNumTriangles = ocd->m_nNumTriangles = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<CColPoint, NUM_TRAILER_SUSP_LINES> suspLineCPs{};
|
std::array<CColPoint, NUM_TRAILER_SUSP_LINES> suspLineCPs{};
|
||||||
|
|
||||||
std::array<float, NUM_TRAILER_SUSP_LINES> suspLineTouchDists{};
|
std::array<float, NUM_TRAILER_SUSP_LINES> suspLineTouchDists{};
|
||||||
|
|
||||||
rng::copy(m_fWheelsSuspensionCompression, suspLineTouchDists.begin());
|
rng::copy(m_fWheelsSuspensionCompression, suspLineTouchDists.begin());
|
||||||
rng::copy(m_supportRatios, suspLineTouchDists.begin() + m_fWheelsSuspensionCompression.size());
|
rng::copy(m_supportRatios, suspLineTouchDists.begin() + m_fWheelsSuspensionCompression.size());
|
||||||
|
|
||||||
|
|
@ -195,63 +331,58 @@ int32 CTrailer::ProcessEntityCollision(CEntity* entity, CColPoint* outColPoints)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Restore hidden triangles
|
// Restore hidden triangles
|
||||||
if (didHideTriangles) {
|
if (shouldHideTriangles) {
|
||||||
tcd->m_nNumTriangles = tNumTri;
|
tcd->m_nNumTriangles = originalTNumTri;
|
||||||
ocd->m_nNumTriangles = oNumTri;
|
ocd->m_nNumTriangles = originalONumTri;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t numProcessedLines{};
|
size_t numProcessedLines{};
|
||||||
if (tcd->m_nNumLines) {
|
if (tcd->m_nNumLines) {
|
||||||
// Process the real wheel's susp lines
|
// Process the real wheel's susp lines
|
||||||
for (auto i = 0; i < MAX_CARWHEELS; i++) {
|
for (auto i = 0; i < NUM_TRAILER_WHEELS; i++) {
|
||||||
// 0x6AD0D4
|
// 0x6AD0D4
|
||||||
const auto& cp = suspLineCPs[i];
|
const auto& cp = suspLineCPs[i];
|
||||||
|
|
||||||
const auto touchDist = suspLineTouchDists[i];
|
const auto touchDist = suspLineTouchDists[i];
|
||||||
if (touchDist >= 1.f || touchDist >= m_fWheelsSuspensionCompression[i]) {
|
if (touchDist < BILLS_EXTENSION_LIMIT && touchDist < m_fWheelsSuspensionCompression[i]) {
|
||||||
continue;
|
numProcessedLines++;
|
||||||
}
|
m_fWheelsSuspensionCompression[i] = touchDist;
|
||||||
|
m_wheelColPoint[i] = cp;
|
||||||
|
m_anCollisionLighting[i] = cp.m_nLightingB;
|
||||||
|
m_nContactSurface = cp.m_nSurfaceTypeB;
|
||||||
|
|
||||||
numProcessedLines++;
|
switch (entity->GetType()) {
|
||||||
|
case ENTITY_TYPE_VEHICLE:
|
||||||
|
case ENTITY_TYPE_OBJECT: {
|
||||||
|
CEntity::ChangeEntityReference(m_apWheelCollisionEntity[i], entity->AsPhysical());
|
||||||
|
|
||||||
m_fWheelsSuspensionCompression[i] = touchDist;
|
m_vWheelCollisionPos[i] = cp.m_vecPoint - entity->GetPosition();
|
||||||
m_wheelColPoint[i] = cp;
|
if (entity->IsVehicle()) {
|
||||||
|
m_anCollisionLighting[i] = entity->AsVehicle()->m_anCollisionLighting[i];
|
||||||
m_anCollisionLighting[i] = cp.m_nLightingB;
|
}
|
||||||
m_nContactSurface = cp.m_nSurfaceTypeB;
|
break;
|
||||||
|
}
|
||||||
switch (entity->GetType()) {
|
case ENTITY_TYPE_BUILDING: {
|
||||||
case ENTITY_TYPE_VEHICLE:
|
m_pEntityWeAreOn = entity;
|
||||||
case ENTITY_TYPE_OBJECT: {
|
m_bTunnel = entity->m_bTunnel;
|
||||||
CEntity::ChangeEntityReference(m_apWheelCollisionEntity[i], entity->AsPhysical());
|
m_bTunnelTransition = entity->m_bTunnelTransition;
|
||||||
|
break;
|
||||||
m_vWheelCollisionPos[i] = cp.m_vecPoint - entity->GetPosition();
|
}
|
||||||
if (entity->IsVehicle()) {
|
|
||||||
m_anCollisionLighting[i] = entity->AsVehicle()->m_anCollisionLighting[i];
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ENTITY_TYPE_BUILDING: {
|
|
||||||
m_pEntityWeAreOn = entity;
|
|
||||||
m_bTunnel = entity->m_bTunnel;
|
|
||||||
m_bTunnelTransition = entity->m_bTunnelTransition;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process trailer support lines
|
|
||||||
for (auto i = 0; i < NUM_TRAILER_SUPPORTS; i++) {
|
|
||||||
const auto suspLineIdx = NUM_TRAILER_WHEELS + i;
|
|
||||||
|
|
||||||
const auto touchDist = suspLineTouchDists[suspLineIdx];
|
|
||||||
if (touchDist >= 1.f || touchDist >= m_supportRatios[i]) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
numProcessedLines++;
|
// Process trailer support lines
|
||||||
m_supportRatios[i] = touchDist;
|
for (auto i = 0; i < NUM_TRAILER_SUPPORTS; i++) {
|
||||||
m_supportCPs[i] = suspLineCPs[suspLineIdx];
|
const auto suspLineIdx = NUM_TRAILER_WHEELS + i;
|
||||||
|
|
||||||
|
const auto touchDist = suspLineTouchDists[suspLineIdx];
|
||||||
|
if (touchDist >= BILLS_EXTENSION_LIMIT || touchDist >= m_supportRatios[i]) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
numProcessedLines++;
|
||||||
|
m_supportRatios[i] = touchDist;
|
||||||
|
m_supportCPs[i] = suspLineCPs[suspLineIdx];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
tcd->m_nNumLines = NUM_TRAILER_SUSP_LINES;
|
tcd->m_nNumLines = NUM_TRAILER_SUSP_LINES;
|
||||||
|
|
@ -262,12 +393,9 @@ int32 CTrailer::ProcessEntityCollision(CEntity* entity, CColPoint* outColPoints)
|
||||||
if (!entity->IsBuilding()) {
|
if (!entity->IsBuilding()) {
|
||||||
entity->AsPhysical()->AddCollisionRecord(this);
|
entity->AsPhysical()->AddCollisionRecord(this);
|
||||||
}
|
}
|
||||||
if (numColPts > 0) {
|
if (numColPts > 0 && entity->IsBuilding()
|
||||||
if ( entity->IsBuilding()
|
|| (entity->IsObject() && entity->AsPhysical()->physicalFlags.bDisableCollisionForce)) {
|
||||||
|| (entity->IsObject() && entity->AsPhysical()->physicalFlags.bDisableCollisionForce)
|
m_bHasHitWall = true;
|
||||||
) {
|
|
||||||
m_bHasHitWall = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -276,36 +404,126 @@ int32 CTrailer::ProcessEntityCollision(CEntity* entity, CColPoint* outColPoints)
|
||||||
|
|
||||||
// 0x6CED20
|
// 0x6CED20
|
||||||
void CTrailer::ProcessControl() {
|
void CTrailer::ProcessControl() {
|
||||||
plugin::CallMethod<0x6CED20, CTrailer*>(this);
|
CAutomobile::ProcessControl();
|
||||||
|
if ((m_nFlags & 0x40) == 0 && m_fTrailerTowedRatio != BAGGAGE_TRAILER_TOWED_RATIO) {
|
||||||
|
const float timeStep = CTimer::GetTimeStep();
|
||||||
|
float& currentExtension = m_fTrailerTowedRatio;
|
||||||
|
|
||||||
|
if (m_pTowingVehicle && currentExtension > 0.0f) {
|
||||||
|
// up
|
||||||
|
currentExtension = std::max(currentExtension - timeStep * TRAILER_SUPPORT_RETRACTION_RATE, 0.0f);
|
||||||
|
} else if (!m_pTowingVehicle && currentExtension < 1.0f) {
|
||||||
|
// down
|
||||||
|
const float growthRate = (currentExtension <= 0.1f)
|
||||||
|
? timeStep * TRAILER_SUPPORT_WAIT_EXTENSION_RATE
|
||||||
|
: timeStep * TRAILER_SUPPORT_EXTENSION_RATE;
|
||||||
|
currentExtension = std::min(currentExtension + growthRate, 1.0f);
|
||||||
|
m_nFakePhysics = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto status = GetStatus();
|
||||||
|
if ((status == STATUS_IS_TOWED || status == STATUS_IS_SIMPLE_TOWED) && TRAILER_TOWED_MINRATIO > currentExtension) {
|
||||||
|
m_fTrailerTowedRatio2 = TRAILER_TOWED_MINRATIO;
|
||||||
|
} else {
|
||||||
|
m_fTrailerTowedRatio2 = currentExtension;
|
||||||
|
}
|
||||||
|
|
||||||
|
rng::fill(m_supportRatios, m_fTrailerTowedRatio2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x6CF590
|
// 0x6CF590
|
||||||
bool CTrailer::ProcessAI(uint32& extraHandlingFlags) {
|
bool CTrailer::ProcessAI(uint32& extraHandlingFlags) {
|
||||||
return plugin::CallMethodAndReturn<bool, 0x6CF590, CTrailer*, uint32&>(this, extraHandlingFlags);
|
const auto returnValue = CAutomobile::ProcessAI(extraHandlingFlags);
|
||||||
|
|
||||||
|
if (GetStatus() == STATUS_ABANDONED && (m_fTrailerTowedRatio > 0.5f || m_fTrailerTowedRatio == BAGGAGE_TRAILER_TOWED_RATIO)) {
|
||||||
|
ScanForTowLink();
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (GetStatus() != STATUS_REMOTE_CONTROLLED || !m_pTowingVehicle) {
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_fTrailerTowedRatio != BAGGAGE_TRAILER_TOWED_RATIO) {
|
||||||
|
m_BrakePedal = m_pTowingVehicle->m_BrakePedal;
|
||||||
|
return returnValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wheel turning for luggage trailers
|
||||||
|
float headingTow = m_pTowingVehicle->GetHeading();
|
||||||
|
|
||||||
|
float headingSelf = GetHeading();
|
||||||
|
|
||||||
|
// Calculation of the shortest angle difference
|
||||||
|
float angleDiff = headingTow - headingSelf;
|
||||||
|
if (angleDiff > PI) {
|
||||||
|
angleDiff -= TWO_PI;
|
||||||
|
} else if (angleDiff < -PI) {
|
||||||
|
angleDiff += TWO_PI;
|
||||||
|
}
|
||||||
|
m_fSteerAngle = angleDiff;
|
||||||
|
|
||||||
|
return returnValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x6CFAC0
|
// 0x6CFAC0
|
||||||
void CTrailer::PreRender() {
|
void CTrailer::PreRender() {
|
||||||
plugin::CallMethod<0x6CFAC0, CTrailer*>(this);
|
CAutomobile::PreRender();
|
||||||
|
|
||||||
|
// Support animation
|
||||||
|
if (m_aCarNodes[TRAILER_MISC_A]) {
|
||||||
|
auto* colData = CModelInfo::GetModelInfo(m_nModelIndex)->m_pColModel->m_pColData;
|
||||||
|
if (colData->m_nNumLines > NUM_TRAILER_WHEELS && (!m_vecMoveSpeed.IsZero() || !m_vecTurnSpeed.IsZero() || !m_nFakePhysics)) {
|
||||||
|
CMatrix mat;
|
||||||
|
mat.Attach(&m_aCarNodes[TRAILER_MISC_A]->modelling, false);
|
||||||
|
|
||||||
|
const float avgSupportRatio = (m_supportRatios[0] + m_supportRatios[1]) * 0.5f;
|
||||||
|
const float supportExtensionRatio = std::min(avgSupportRatio, m_fTrailerTowedRatio);
|
||||||
|
|
||||||
|
const auto& supportLegLine = colData->m_pLines[NUM_TRAILER_WHEELS];
|
||||||
|
|
||||||
|
const float supportTravel = supportExtensionRatio * (supportLegLine.m_vecEnd.z - supportLegLine.m_vecStart.z);
|
||||||
|
const float verticalPosRatio = mat.GetPosition().y / supportLegLine.m_vecStart.y;
|
||||||
|
|
||||||
|
CVector newPos = mat.GetPosition();
|
||||||
|
const float targetZ = (supportTravel + supportLegLine.m_vecStart.z) * verticalPosRatio
|
||||||
|
- (1.0f - verticalPosRatio) * m_fFrontHeightAboveRoad;
|
||||||
|
newPos.z = std::min(targetZ, m_fHeight);
|
||||||
|
|
||||||
|
mat.SetTranslate(newPos);
|
||||||
|
mat.UpdateRW();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Animation for FARMTR1
|
||||||
|
if (m_nModelIndex == MODEL_FARMTR1) {
|
||||||
|
m_fPropRotate = fmod(m_fPropRotate, TWO_PI);
|
||||||
|
const float forwardSpeed = m_vecMoveSpeed.Dot(m_matrix->GetForward());
|
||||||
|
const float rotationSpeedFactor = std::clamp(forwardSpeed, 0.0f, 0.1f);
|
||||||
|
m_fPropRotate -= rotationSpeedFactor * CTimer::GetTimeStep();
|
||||||
|
CVehicle::SetComponentRotation(m_aCarNodes[TRAILER_MISC_B], AXIS_X, m_fPropRotate, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0x6CEEA0
|
// 0x6CEEA0
|
||||||
bool CTrailer::GetTowHitchPos(CVector& outPos, bool bCheckModelInfo, CVehicle* vehicle) {
|
bool CTrailer::GetTowHitchPos(CVector& outPos, bool bCheckModelInfo, CVehicle* vehicle) {
|
||||||
auto mi = GetVehicleModelInfo();
|
auto mi = GetVehicleModelInfo();
|
||||||
outPos = mi->GetModelDummyPosition(DUMMY_TRAILER_ATTACH);
|
outPos = mi->GetModelDummyPosition(DUMMY_TRAILER_ATTACH);
|
||||||
|
|
||||||
if (vehicle && vehicle->m_nModelIndex == MODEL_TOWTRUCK) {
|
if (vehicle && vehicle->m_nModelIndex == MODEL_TOWTRUCK) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (outPos.IsZero()) {
|
if (outPos.IsZero()) {
|
||||||
if (bCheckModelInfo) {
|
if (!bCheckModelInfo) {
|
||||||
outPos.x = 0.0f;
|
return false;
|
||||||
outPos.y = mi->GetColModel()->GetBoundingBox().m_vecMax.y + 1.0f;
|
|
||||||
outPos.z = 0.5f - m_fFrontHeightAboveRoad;
|
|
||||||
outPos = m_matrix->TransformPoint(outPos);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
outPos.x = 0.0f;
|
||||||
|
outPos.y = mi->GetColModel()->GetBoundingBox().m_vecMax.y + 1.0f;
|
||||||
|
outPos.z = 0.5f - m_fFrontHeightAboveRoad;
|
||||||
|
outPos = m_matrix->TransformPoint(outPos);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
outPos = m_matrix->TransformPoint(outPos);
|
outPos = m_matrix->TransformPoint(outPos);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -321,7 +539,7 @@ bool CTrailer::GetTowBarPos(CVector& outPos, bool bCheckModelInfo, CVehicle* veh
|
||||||
|
|
||||||
auto mi = GetVehicleModelInfo();
|
auto mi = GetVehicleModelInfo();
|
||||||
outPos.x = 0.0f;
|
outPos.x = 0.0f;
|
||||||
outPos.y = mi->GetColModel()->GetBoundingBox().m_vecMin.y - -0.05f;
|
outPos.y = mi->GetColModel()->GetBoundingBox().m_vecMin.y - TRAILER_TOWBAR_OFFSET_Y;
|
||||||
outPos.z = 0.5f - m_fFrontHeightAboveRoad;
|
outPos.z = 0.5f - m_fFrontHeightAboveRoad;
|
||||||
outPos = m_matrix->TransformPoint(outPos);
|
outPos = m_matrix->TransformPoint(outPos);
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -338,10 +556,11 @@ bool CTrailer::BreakTowLink() {
|
||||||
CEntity::ClearReference(m_pTowingVehicle);
|
CEntity::ClearReference(m_pTowingVehicle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_nStatus != STATUS_IS_TOWED && m_nStatus != STATUS_IS_SIMPLE_TOWED) {
|
const auto status = GetStatus();
|
||||||
|
if (status != STATUS_IS_TOWED && status != STATUS_IS_SIMPLE_TOWED) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_nStatus = STATUS_ABANDONED;
|
SetStatus(STATUS_ABANDONED);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,12 +40,16 @@ class NOTSA_EXPORT_VTABLE CTrailer : public CAutomobile {
|
||||||
static constexpr auto NUM_TRAILER_WHEELS = 4;
|
static constexpr auto NUM_TRAILER_WHEELS = 4;
|
||||||
static constexpr auto NUM_TRAILER_SUPPORTS = 2;
|
static constexpr auto NUM_TRAILER_SUPPORTS = 2;
|
||||||
static constexpr auto NUM_TRAILER_SUSP_LINES = NUM_TRAILER_WHEELS + NUM_TRAILER_SUPPORTS;
|
static constexpr auto NUM_TRAILER_SUSP_LINES = NUM_TRAILER_WHEELS + NUM_TRAILER_SUPPORTS;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::array<CColPoint, NUM_TRAILER_SUPPORTS> m_supportCPs{};
|
std::array<CColPoint, NUM_TRAILER_SUPPORTS> m_supportCPs{}; // m_aSupportColPoints
|
||||||
std::array<float, NUM_TRAILER_SUPPORTS> m_supportRatios{ 1.f, 1.f };
|
std::array<float, NUM_TRAILER_SUPPORTS> m_supportRatios{ 1.f, 1.f }; // m_aSupportRatios
|
||||||
float m_fHeight; // 0x6CF3DC, 0x6CFC11
|
float m_fHeight; // m_fSupportStartZ, 0x6CF3DC, 0x6CFC11
|
||||||
float m_fTrailerTowedRatio{ 1.f };
|
float m_fTrailerTowedRatio{ 1.f }; // m_fSupportExtension
|
||||||
float m_fTrailerTowedRatio2{ 1.f };
|
float m_fTrailerTowedRatio2{ 1.f }; // m_fSupportMinRatio
|
||||||
|
|
||||||
|
static constexpr float m_fTrailerSuspensionForce = 1.5f; // 0x8D3464
|
||||||
|
static constexpr float m_fTrailerDampingForce = 0.1f; // 0x8D3468
|
||||||
|
|
||||||
static constexpr auto Type = VEHICLE_TYPE_TRAILER;
|
static constexpr auto Type = VEHICLE_TYPE_TRAILER;
|
||||||
|
|
||||||
|
|
@ -53,28 +57,34 @@ public:
|
||||||
CTrailer(int32 modelIndex, eVehicleCreatedBy createdBy);
|
CTrailer(int32 modelIndex, eVehicleCreatedBy createdBy);
|
||||||
~CTrailer() override = default; // 0x6CED10
|
~CTrailer() override = default; // 0x6CED10
|
||||||
|
|
||||||
bool SetTowLink(CVehicle* tractor, bool setMyPosToTowBar) override;
|
|
||||||
void ScanForTowLink();
|
|
||||||
|
|
||||||
void SetupSuspensionLines() override;
|
void SetupSuspensionLines() override;
|
||||||
void ResetSuspension() override;
|
|
||||||
|
void ProcessControl() override;
|
||||||
|
|
||||||
|
bool ProcessAI(uint32& extraHandlingFlags) override;
|
||||||
void ProcessSuspension() override;
|
void ProcessSuspension() override;
|
||||||
|
|
||||||
|
void PreRender() override;
|
||||||
|
|
||||||
|
void ResetSuspension() override;
|
||||||
|
|
||||||
|
bool GetTowHitchPos(CVector& outPos, bool checkModelInfo, CVehicle* vehicle) override;
|
||||||
|
bool GetTowBarPos(CVector& outPos, bool checkModelInfo, CVehicle* vehicle) override;
|
||||||
|
bool SetTowLink(CVehicle* tractor, bool setMyPosToTowBar) override;
|
||||||
|
bool BreakTowLink() override;
|
||||||
|
|
||||||
|
void ScanForTowLink();
|
||||||
|
|
||||||
int32 ProcessEntityCollision(CEntity* entity, CColPoint* colPoint) override;
|
int32 ProcessEntityCollision(CEntity* entity, CColPoint* colPoint) override;
|
||||||
void ProcessControl() override;
|
|
||||||
bool ProcessAI(uint32& extraHandlingFlags) override;
|
|
||||||
|
|
||||||
void PreRender() override;
|
|
||||||
|
|
||||||
bool GetTowHitchPos(CVector& outPos, bool bCheckModelInfo, CVehicle* vehicle) override;
|
|
||||||
bool GetTowBarPos(CVector& outPos, bool bCheckModelInfo, CVehicle* vehicle) override;
|
|
||||||
bool BreakTowLink() override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend void InjectHooksMain();
|
friend void InjectHooksMain();
|
||||||
static void InjectHooks();
|
static void InjectHooks();
|
||||||
|
|
||||||
CTrailer* Constructor(int32 modelIndex, eVehicleCreatedBy createdBy) { this->CTrailer::CTrailer(modelIndex, createdBy); return this; }
|
CTrailer* Constructor(int32 modelIndex, eVehicleCreatedBy createdBy) {
|
||||||
|
this->CTrailer::CTrailer(modelIndex, createdBy);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
VALIDATE_SIZE(CTrailer, 0x9F4);
|
VALIDATE_SIZE(CTrailer, 0x9F4);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue