Clear unknowns in LegoCarRaceActor

This commit is contained in:
Fabian Neundorf 2025-08-08 22:53:17 +02:00
parent a6ee94b680
commit 72ed4d4a40
3 changed files with 82 additions and 75 deletions

View File

@ -53,27 +53,33 @@ class LegoCarRaceActor : public virtual LegoRaceActor {
// LegoCarRaceActor vtable // LegoCarRaceActor vtable
virtual void FUN_10080590(float p_time); // vtable+0x00 virtual void UpdateWorldSpeed(float p_time); // vtable+0x00
// FUNCTION: LEGO1 0x10012bb0 // FUNCTION: LEGO1 0x10012bb0
virtual void FUN_10012bb0(float p_unk0x14) { m_unk0x14 = p_unk0x14; } // vtable+0x04 virtual void SetAcceleration(float p_acceleration) { m_acceleration = p_acceleration; } // vtable+0x04
// FUNCTION: LEGO1 0x10012bc0 // FUNCTION: LEGO1 0x10012bc0
virtual float FUN_10012bc0() { return m_unk0x14; } // vtable+0x08 virtual float GetAcceleration() { return m_acceleration; } // vtable+0x08
// FUNCTION: LEGO1 0x10012bd0 // FUNCTION: LEGO1 0x10012bd0
virtual void FUN_10012bd0(float p_unk0x10) { m_unk0x10 = p_unk0x10; } // vtable+0x0c virtual void SetCurveSpeedFactor(float p_curveSpeedFactor)
{
m_curveSpeedFactor = p_curveSpeedFactor;
} // vtable+0x0c
// FUNCTION: LEGO1 0x10012be0 // FUNCTION: LEGO1 0x10012be0
virtual float FUN_10012be0() { return m_unk0x10; } // vtable+0x10 virtual float GetCurveSpeedFactor() { return m_curveSpeedFactor; } // vtable+0x10
// FUNCTION: LEGO1 0x10012bf0 // FUNCTION: LEGO1 0x10012bf0
virtual void FUN_10012bf0(float p_unk0x18) { m_unk0x18 = p_unk0x18; } // vtable+0x14 virtual void SetRubberBandFactor(float p_rubberBandFactor)
{
m_rubberBandFactor = p_rubberBandFactor;
} // vtable+0x14
// FUNCTION: LEGO1 0x10012c00 // FUNCTION: LEGO1 0x10012c00
virtual float FUN_10012c00() { return m_unk0x18; } // vtable+0x18 virtual float GetRubberBandFactor() { return m_rubberBandFactor; } // vtable+0x18
virtual MxS32 VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edge); // vtable+0x1c virtual MxS32 HandleJump(LegoPathBoundary* p_boundary, LegoEdge* p_edge); // vtable+0x1c
// SYNTHETIC: LEGO1 0x10012c30 // SYNTHETIC: LEGO1 0x10012c30
// LegoCarRaceActor::`vbase destructor' // LegoCarRaceActor::`vbase destructor'
@ -88,18 +94,18 @@ class LegoCarRaceActor : public virtual LegoRaceActor {
MxFloat m_unk0x08; // 0x08 MxFloat m_unk0x08; // 0x08
MxU8 m_animState; // 0x0c MxU8 m_animState; // 0x0c
// Could be a multiplier for the maximum speed when going straight // A multiplier for the maximum speed when going around a curve
MxFloat m_unk0x10; // 0x10 MxFloat m_curveSpeedFactor; // 0x10
// Could be the acceleration // Could be the acceleration
MxFloat m_unk0x14; // 0x14 MxFloat m_acceleration; // 0x14
MxFloat m_unk0x18; // 0x18 MxFloat m_rubberBandFactor; // 0x18
// Could be the current timestamp for time-based movement // Could be the current timestamp for time-based movement
MxFloat m_unk0x1c; // 0x1c MxFloat m_lastAcceleration; // 0x1c
static MxFloat g_unk0x100f7aec; static MxFloat g_maxSpeed;
}; };
// VTABLE: LEGO1 0x100da208 LegoCarRaceActor // VTABLE: LEGO1 0x100da208 LegoCarRaceActor
@ -139,7 +145,7 @@ class LegoJetskiRaceActor : public virtual LegoCarRaceActor {
Vector3& p_intersectionPoint Vector3& p_intersectionPoint
) override; // vtable+0x6c ) override; // vtable+0x6c
void Animate(float p_time) override; // vtable+0x70 void Animate(float p_time) override; // vtable+0x70
MxS32 VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edge) override; // vtable+0x1c MxS32 HandleJump(LegoPathBoundary* p_boundary, LegoEdge* p_edge) override; // vtable+0x1c
// SYNTHETIC: LEGO1 0x10013a80 // SYNTHETIC: LEGO1 0x10013a80
// LegoJetskiRaceActor::`vbase destructor' // LegoJetskiRaceActor::`vbase destructor'

View File

@ -414,7 +414,7 @@ void LegoRaceCar::Animate(float p_time)
UpdateMapLocatorPosition(); UpdateMapLocatorPosition();
if (!m_userNavFlag) { if (!m_userNavFlag) {
FUN_10080590(p_time); UpdateWorldSpeed(p_time);
return; return;
} }
@ -613,7 +613,7 @@ void LegoJetski::Animate(float p_time)
UpdateMapLocatorPosition(); UpdateMapLocatorPosition();
if (!m_userNavFlag) { if (!m_userNavFlag) {
FUN_10080590(p_time); UpdateWorldSpeed(p_time);
return; return;
} }

View File

@ -32,11 +32,11 @@ const char* g_fuel = "FUEL";
const char* g_racing = "RACING"; const char* g_racing = "RACING";
// GLOBAL: LEGO1 0x100f7aec // GLOBAL: LEGO1 0x100f7aec
MxFloat LegoCarRaceActor::g_unk0x100f7aec = 8.0f; MxFloat LegoCarRaceActor::g_maxSpeed = 8.0f;
// GLOBAL: LEGO1 0x100da044 // GLOBAL: LEGO1 0x100da044
// GLOBAL: BETA10 0x101be9fc // GLOBAL: BETA10 0x101be9fc
MxFloat g_unk0x100da044 = 8.0f; MxFloat g_maxWorldSpeed = 8.0f;
// FUNCTION: LEGO1 0x10080350 // FUNCTION: LEGO1 0x10080350
// FUNCTION: BETA10 0x100cd6b0 // FUNCTION: BETA10 0x100cd6b0
@ -47,10 +47,10 @@ LegoCarRaceActor::LegoCarRaceActor()
m_animState = 0; m_animState = 0;
m_maxLinearVel = 0.0f; m_maxLinearVel = 0.0f;
m_frequencyFactor = 1.0f; m_frequencyFactor = 1.0f;
m_unk0x1c = 0; m_lastAcceleration = 0;
m_unk0x10 = 0.65f; m_curveSpeedFactor = 0.65f;
m_unk0x14 = 0.03f; m_acceleration = 0.03f;
m_unk0x18 = 0.6f; m_rubberBandFactor = 0.6f;
m_wallHitDirectionFactor = 0.1f; m_wallHitDirectionFactor = 0.1f;
m_linearRotationRatio = -5.0f; m_linearRotationRatio = -5.0f;
m_canRotate = 1; m_canRotate = 1;
@ -59,43 +59,43 @@ LegoCarRaceActor::LegoCarRaceActor()
// FUNCTION: LEGO1 0x10080590 // FUNCTION: LEGO1 0x10080590
// FUNCTION: BETA10 0x100cd8cf // FUNCTION: BETA10 0x100cd8cf
void LegoCarRaceActor::FUN_10080590(float p_time) void LegoCarRaceActor::UpdateWorldSpeed(float p_time)
{ {
MxFloat maxSpeed = m_maxLinearVel; MxFloat maxSpeed = m_maxLinearVel;
Mx3DPointFloat destEdgeUnknownVector; Mx3DPointFloat edgeNormal;
Mx3DPointFloat worldDirection = Mx3DPointFloat(m_roi->GetWorldDirection()); Mx3DPointFloat worldDirection = Mx3DPointFloat(m_roi->GetWorldDirection());
m_destEdge->GetFaceNormal(*m_boundary, destEdgeUnknownVector); m_destEdge->GetFaceNormal(*m_boundary, edgeNormal);
if (abs(destEdgeUnknownVector.Dot(destEdgeUnknownVector.GetData(), worldDirection.GetData())) > 0.5) { if (abs(edgeNormal.Dot(edgeNormal.GetData(), worldDirection.GetData())) > 0.5) {
maxSpeed *= m_unk0x10; maxSpeed *= m_curveSpeedFactor;
} }
MxS32 deltaUnk0x70; MxS32 deltaPathStructs;
LegoPathActor* userActor = UserActor(); LegoPathActor* userActor = UserActor();
if (userActor) { if (userActor) {
// All known implementations of LegoPathActor->GetLastPathStruct() return LegoPathActor::m_lastPathStruct // All known implementations of LegoPathActor->GetLastPathStruct() return LegoPathActor::m_lastPathStruct
deltaUnk0x70 = m_lastPathStruct - userActor->GetLastPathStruct(); deltaPathStructs = m_lastPathStruct - userActor->GetLastPathStruct();
} }
else { else {
deltaUnk0x70 = 0; deltaPathStructs = 0;
} }
if (deltaUnk0x70 > 1) { if (deltaPathStructs > 1) {
if (deltaUnk0x70 > 3) { if (deltaPathStructs > 3) {
deltaUnk0x70 = 3; deltaPathStructs = 3;
} }
maxSpeed *= (m_unk0x18 * (--deltaUnk0x70) * -0.25f + 1.0f); maxSpeed *= (m_rubberBandFactor * (--deltaPathStructs) * -0.25f + 1.0f);
} }
else if (deltaUnk0x70 < -1) { else if (deltaPathStructs < -1) {
maxSpeed *= 1.3; maxSpeed *= 1.3;
} }
MxFloat deltaSpeed = maxSpeed - m_worldSpeed; MxFloat deltaSpeed = maxSpeed - m_worldSpeed;
MxFloat changeInSpeed = (p_time - m_unk0x1c) * m_unk0x14; MxFloat changeInSpeed = (p_time - m_lastAcceleration) * m_acceleration;
m_unk0x1c = p_time; m_lastAcceleration = p_time;
if (deltaSpeed < 0.0f) { if (deltaSpeed < 0.0f) {
changeInSpeed = -changeInSpeed; changeInSpeed = -changeInSpeed;
@ -112,16 +112,17 @@ void LegoCarRaceActor::FUN_10080590(float p_time)
// FUNCTION: LEGO1 0x10080740 // FUNCTION: LEGO1 0x10080740
// FUNCTION: BETA10 0x100cece0 // FUNCTION: BETA10 0x100cece0
MxS32 LegoCarRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edge) MxS32 LegoCarRaceActor::HandleJump(LegoPathBoundary* p_boundary, LegoEdge* p_edge)
{ {
Mx3DPointFloat pointUnknown; Mx3DPointFloat targetPosition;
Mx3DPointFloat destEdgeUnknownVector; Mx3DPointFloat destEdgeUnknownVector;
Mx3DPointFloat crossProduct; Mx3DPointFloat targetDirection;
if (m_actorState == c_ready) { if (m_actorState == c_ready) {
m_boundary = NULL; m_boundary = NULL;
// Not sure where the upper bound of 11 comes from, the underlying array has a size of 16 // The first 12 elements are used for the car race, the other 4 for jetski
// As it increments by 2, counting to 10 or 11 is the same.
for (MxS32 i = 0; i < 11; i += 2) { for (MxS32 i = 0; i < 11; i += 2) {
if (LegoPathController::GetControlEdgeA(i + 1) == m_destEdge) { if (LegoPathController::GetControlEdgeA(i + 1) == m_destEdge) {
m_boundary = LegoPathController::GetControlBoundaryA(i + 1); m_boundary = LegoPathController::GetControlBoundaryA(i + 1);
@ -147,8 +148,8 @@ MxS32 LegoCarRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edg
if (LegoPathController::GetControlEdgeA(i) == p_edge) { if (LegoPathController::GetControlEdgeA(i) == p_edge) {
m_actorState = c_ready; m_actorState = c_ready;
if (m_worldSpeed < g_unk0x100f7aec) { if (m_worldSpeed < g_maxSpeed) {
m_worldSpeed = g_unk0x100f7aec; m_worldSpeed = g_maxSpeed;
} }
m_destEdge = LegoPathController::GetControlEdgeA(i + 1); m_destEdge = LegoPathController::GetControlEdgeA(i + 1);
@ -167,12 +168,12 @@ MxS32 LegoCarRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edg
Vector3* v2 = m_destEdge->CWVertex(*m_boundary); Vector3* v2 = m_destEdge->CWVertex(*m_boundary);
assert(v1 && v2); assert(v1 && v2);
LERP3(pointUnknown, *v1, *v2, m_destScale); LERP3(targetPosition, *v1, *v2, m_destScale);
m_destEdge->GetFaceNormal(*m_boundary, destEdgeUnknownVector); m_destEdge->GetFaceNormal(*m_boundary, destEdgeUnknownVector);
crossProduct.EqualsCross(*m_boundary->GetUp(), destEdgeUnknownVector); targetDirection.EqualsCross(*m_boundary->GetUp(), destEdgeUnknownVector);
crossProduct.Unitize(); targetDirection.Unitize();
Mx3DPointFloat worldDirection(Vector3(m_roi->GetWorldDirection())); Mx3DPointFloat worldDirection(Vector3(m_roi->GetWorldDirection()));
@ -181,10 +182,10 @@ MxS32 LegoCarRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edg
} }
worldDirection *= 5.0f; worldDirection *= 5.0f;
crossProduct *= 5.0f; targetDirection *= 5.0f;
MxResult callResult = MxResult callResult =
SetSpline(Vector3(m_roi->GetWorldPosition()), worldDirection, pointUnknown, crossProduct); SetSpline(Vector3(m_roi->GetWorldPosition()), worldDirection, targetPosition, targetDirection);
if (callResult) { if (callResult) {
m_traveledDistance = 0; m_traveledDistance = 0;
@ -230,7 +231,7 @@ void LegoCarRaceActor::Animate(float p_time)
if (strcmpi(value, g_racing) == 0) { if (strcmpi(value, g_racing) == 0) {
m_animState = 1; m_animState = 1;
m_transformTime = p_time - 1.0f; m_transformTime = p_time - 1.0f;
m_unk0x1c = p_time; m_lastAcceleration = p_time;
} }
} }
@ -245,7 +246,7 @@ MxResult LegoCarRaceActor::CalculateSpline()
{ {
LegoOrientedEdge* d = m_destEdge; LegoOrientedEdge* d = m_destEdge;
if (VTable0x1c(m_boundary, m_destEdge)) { if (HandleJump(m_boundary, m_destEdge)) {
LegoPathBoundary* b = m_boundary; LegoPathBoundary* b = m_boundary;
SwitchBoundary(m_boundary, m_destEdge, m_destScale); SwitchBoundary(m_boundary, m_destEdge, m_destScale);
@ -256,27 +257,27 @@ MxResult LegoCarRaceActor::CalculateSpline()
Vector3* v2 = m_destEdge->CCWVertex(*m_boundary); Vector3* v2 = m_destEdge->CCWVertex(*m_boundary);
assert(v1 && v2); assert(v1 && v2);
Mx3DPointFloat point1; Mx3DPointFloat end;
LERP3(point1, *v1, *v2, m_destScale); LERP3(end, *v1, *v2, m_destScale);
Mx3DPointFloat point2; Mx3DPointFloat startEdgeNormal;
Mx3DPointFloat point3; Mx3DPointFloat endEdgeNormal;
Mx3DPointFloat point4; Mx3DPointFloat startDirection;
Mx3DPointFloat point5; Mx3DPointFloat endDirection;
d->GetFaceNormal(*b, point2); d->GetFaceNormal(*b, startEdgeNormal);
m_destEdge->GetFaceNormal(*m_boundary, point3); m_destEdge->GetFaceNormal(*m_boundary, endEdgeNormal);
point4.EqualsCross(point2, *m_boundary->GetUp()); startDirection.EqualsCross(startEdgeNormal, *m_boundary->GetUp());
point5.EqualsCross(*m_boundary->GetUp(), point3); endDirection.EqualsCross(*m_boundary->GetUp(), endEdgeNormal);
point4.Unitize(); startDirection.Unitize();
point5.Unitize(); endDirection.Unitize();
point4 *= 5.0f; startDirection *= 5.0f;
point5 *= 5.0f; endDirection *= 5.0f;
MxResult res = SetSpline(m_roi->GetWorldPosition(), point4, point1, point5); MxResult res = SetSpline(m_roi->GetWorldPosition(), startDirection, end, endDirection);
#ifdef BETA10 #ifdef BETA10
if (res) { if (res) {
@ -295,15 +296,15 @@ MxResult LegoCarRaceActor::CalculateSpline()
// FUNCTION: BETA10 0x100a8990 // FUNCTION: BETA10 0x100a8990
LegoJetskiRaceActor::LegoJetskiRaceActor() LegoJetskiRaceActor::LegoJetskiRaceActor()
{ {
m_unk0x10 = 0.95f; m_curveSpeedFactor = 0.95f;
m_unk0x14 = 0.04f; m_acceleration = 0.04f;
m_unk0x18 = 0.5f; m_rubberBandFactor = 0.5f;
m_linearRotationRatio = 1.5f; m_linearRotationRatio = 1.5f;
} }
// FUNCTION: LEGO1 0x10081120 // FUNCTION: LEGO1 0x10081120
// FUNCTION: BETA10 0x100ce19f // FUNCTION: BETA10 0x100ce19f
MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_edge) MxS32 LegoJetskiRaceActor::HandleJump(LegoPathBoundary* p_boundary, LegoEdge* p_edge)
{ {
// These are almost certainly not the correct names, but they produce the correct BETA10 stack // These are almost certainly not the correct names, but they produce the correct BETA10 stack
Mx3DPointFloat a; Mx3DPointFloat a;
@ -337,8 +338,8 @@ MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_
if (p_edge == LegoPathController::GetControlEdgeA(12)) { if (p_edge == LegoPathController::GetControlEdgeA(12)) {
m_actorState = c_ready; m_actorState = c_ready;
if (m_worldSpeed < g_unk0x100da044) { if (m_worldSpeed < g_maxWorldSpeed) {
m_worldSpeed = g_unk0x100da044; m_worldSpeed = g_maxWorldSpeed;
} }
m_destEdge = LegoPathController::GetControlEdgeA(13); m_destEdge = LegoPathController::GetControlEdgeA(13);
@ -347,8 +348,8 @@ MxS32 LegoJetskiRaceActor::VTable0x1c(LegoPathBoundary* p_boundary, LegoEdge* p_
else if (p_edge == LegoPathController::GetControlEdgeA(14)) { else if (p_edge == LegoPathController::GetControlEdgeA(14)) {
m_actorState = c_ready; m_actorState = c_ready;
if (m_worldSpeed < g_unk0x100da044) { if (m_worldSpeed < g_maxWorldSpeed) {
m_worldSpeed = g_unk0x100da044; m_worldSpeed = g_maxWorldSpeed;
} }
m_destEdge = LegoPathController::GetControlEdgeA(15); m_destEdge = LegoPathController::GetControlEdgeA(15);
@ -403,7 +404,7 @@ void LegoJetskiRaceActor::Animate(float p_time)
if (!stricmp(raceState, g_racing)) { if (!stricmp(raceState, g_racing)) {
m_animState = 1; m_animState = 1;
m_transformTime = p_time - 1.0f; m_transformTime = p_time - 1.0f;
m_unk0x1c = p_time; m_lastAcceleration = p_time;
} }
else if (!m_userNavFlag) { else if (!m_userNavFlag) {
LegoAnimActor::Animate(m_transformTime + 1.0f); LegoAnimActor::Animate(m_transformTime + 1.0f);