Implement/match LegoCarRaceActor::FUN_10080590 (#1070)

* Implement/match `LegoCarRaceActor::FUN_10080590`

* Add vbtable annotations

* disable formatter for assertion

* Fix BETA10 annotations

* Address review comments

---------

Co-authored-by: jonschz <jonschz@users.noreply.github.com>
This commit is contained in:
jonschz 2024-07-28 20:13:18 +02:00 committed by GitHub
parent f436b9365b
commit 1f251ff817
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 100 additions and 12 deletions

View File

@ -7,12 +7,17 @@
// VTABLE: LEGO1 0x100da0c8 LegoAnimActor // VTABLE: LEGO1 0x100da0c8 LegoAnimActor
// VTABLE: LEGO1 0x100da0d8 LegoPathActor // VTABLE: LEGO1 0x100da0d8 LegoPathActor
// VTABLE: LEGO1 0x100da1a8 LegoCarRaceActor // VTABLE: LEGO1 0x100da1a8 LegoCarRaceActor
// VTABLE: BETA10 0x101bea74 LegoRaceActor
// VTABLE: BETA10 0x101bea78 LegoAnimActor
// VTABLE: BETA10 0x101bea90 LegoPathActor
// VTABLE: BETA10 0x101beb80 LegoCarRaceActor
// SIZE 0x1a0 // SIZE 0x1a0
class LegoCarRaceActor : public virtual LegoRaceActor { class LegoCarRaceActor : public virtual LegoRaceActor {
public: public:
LegoCarRaceActor(); LegoCarRaceActor();
// FUNCTION: LEGO1 0x10081660 // FUNCTION: LEGO1 0x10081660
// FUNCTION: BETA10 0x100aab10
const char* ClassName() const override // vtable+0x0c const char* ClassName() const override // vtable+0x0c
{ {
// STRING: LEGO1 0x100f0568 // STRING: LEGO1 0x100f0568
@ -20,6 +25,7 @@ public:
} }
// FUNCTION: LEGO1 0x10081680 // FUNCTION: LEGO1 0x10081680
// FUNCTION: BETA10 0x100aa9e0
MxBool IsA(const char* p_name) const override // vtable+0x10 MxBool IsA(const char* p_name) const override // vtable+0x10
{ {
return !strcmp(p_name, LegoCarRaceActor::ClassName()) || LegoRaceActor::IsA(p_name); return !strcmp(p_name, LegoCarRaceActor::ClassName()) || LegoRaceActor::IsA(p_name);
@ -38,7 +44,7 @@ public:
override; // vtable+0x98 override; // vtable+0x98
MxResult VTable0x9c() override; // vtable+0x9c MxResult VTable0x9c() override; // vtable+0x9c
virtual void FUN_10080590(float); virtual void FUN_10080590(float p_float);
// FUNCTION: LEGO1 0x10012bb0 // FUNCTION: LEGO1 0x10012bb0
virtual void FUN_10012bb0(float p_unk0x14) { m_unk0x14 = p_unk0x14; } virtual void FUN_10012bb0(float p_unk0x14) { m_unk0x14 = p_unk0x14; }
@ -67,12 +73,28 @@ public:
// LegoCarRaceActor::`scalar deleting destructor' // LegoCarRaceActor::`scalar deleting destructor'
protected: protected:
float m_unk0x08; // 0x08 MxFloat m_unk0x08; // 0x08
MxU8 m_unk0x0c; // 0x0c MxU8 m_unk0x0c; // 0x0c
float m_unk0x10; // 0x10
float m_unk0x14; // 0x14 // Could be a multiplier for the maximum speed when going straight
float m_unk0x18; // 0x18 MxFloat m_unk0x10; // 0x10
undefined4 m_unk0x1c; // 0x1c
// Could be the acceleration
MxFloat m_unk0x14; // 0x14
MxFloat m_unk0x18; // 0x18
// Could be the current timestamp for time-based movement
MxFloat m_unk0x1c; // 0x1c
}; };
// GLOBAL: LEGO1 0x100da0b0
// LegoCarRaceActor::`vbtable'
// GLOBAL: LEGO1 0x100da0a8
// LegoCarRaceActor::`vbtable'{for `LegoAnimActor'}
// GLOBAL: LEGO1 0x100da098
// LegoCarRaceActor::`vbtable'{for `LegoRaceActor'}
#endif // LEGOCARRACEACTOR_H #endif // LEGOCARRACEACTOR_H

View File

@ -67,8 +67,10 @@ LegoNavController* NavController()
} }
// FUNCTION: LEGO1 0x10015790 // FUNCTION: LEGO1 0x10015790
// FUNCTION: BETA10 0x100e49ff
LegoPathActor* UserActor() LegoPathActor* UserActor()
{ {
assert(LegoOmni::GetInstance());
return LegoOmni::GetInstance()->GetUserActor(); return LegoOmni::GetInstance()->GetUserActor();
} }

View File

@ -1,5 +1,8 @@
#include "legocarraceactor.h" #include "legocarraceactor.h"
#include "geom/legounkown100db7f4.h"
#include "legopathboundary.h"
#include "misc.h"
#include "mxmisc.h" #include "mxmisc.h"
#include "mxvariabletable.h" #include "mxvariabletable.h"
@ -10,6 +13,7 @@ DECOMP_SIZE_ASSERT(LegoCarRaceActor, 0x1a0)
const char* g_fuel = "FUEL"; const char* g_fuel = "FUEL";
// FUNCTION: LEGO1 0x10080350 // FUNCTION: LEGO1 0x10080350
// FUNCTION: BETA10 0x100cd6b0
LegoCarRaceActor::LegoCarRaceActor() LegoCarRaceActor::LegoCarRaceActor()
{ {
m_unk0x08 = 1.0f; m_unk0x08 = 1.0f;
@ -27,9 +31,57 @@ LegoCarRaceActor::LegoCarRaceActor()
VariableTable()->SetVariable(g_fuel, "0.8"); VariableTable()->SetVariable(g_fuel, "0.8");
} }
// STUB: LEGO1 0x10080590 // FUNCTION: LEGO1 0x10080590
void LegoCarRaceActor::FUN_10080590(float) // FUNCTION: BETA10 0x100cd8cf
void LegoCarRaceActor::FUN_10080590(float p_float)
{ {
MxFloat maxSpeed = m_maxLinearVel;
Mx3DPointFloat destEdgeUnknownVector;
Mx3DPointFloat worldDirection = Mx3DPointFloat(m_roi->GetWorldDirection());
m_destEdge->FUN_1002ddc0(*m_boundary, destEdgeUnknownVector);
if (abs(destEdgeUnknownVector.Dot(destEdgeUnknownVector.GetData(), worldDirection.GetData())) > 0.5) {
maxSpeed *= m_unk0x10;
}
MxS32 deltaUnk0x70;
LegoPathActor* userActor = UserActor();
if (userActor) {
// All known implementations of LegoPathActor->VTable0x5c() return LegoPathActor::m_unk0x70
deltaUnk0x70 = m_unk0x70 - userActor->VTable0x5c();
}
else {
deltaUnk0x70 = 0;
}
if (deltaUnk0x70 > 1) {
if (deltaUnk0x70 > 3) {
deltaUnk0x70 = 3;
}
maxSpeed *= (m_unk0x18 * (--deltaUnk0x70) * -0.25f + 1.0f);
}
else if (deltaUnk0x70 < -1) {
maxSpeed *= 1.3;
}
MxFloat deltaSpeed = maxSpeed - m_worldSpeed;
MxFloat changeInSpeed = (p_float - m_unk0x1c) * m_unk0x14;
m_unk0x1c = p_float;
if (deltaSpeed < 0.0f) {
changeInSpeed = -changeInSpeed;
}
MxFloat newWorldSpeed = changeInSpeed + m_worldSpeed;
if (newWorldSpeed > maxSpeed) {
newWorldSpeed = maxSpeed;
}
SetWorldSpeed(newWorldSpeed);
} }
// STUB: LEGO1 0x10080740 // STUB: LEGO1 0x10080740
@ -37,10 +89,11 @@ void LegoCarRaceActor::VTable0x1c()
{ {
} }
// STUB: LEGO1 0x10080b40 // FUNCTION: LEGO1 0x10080b40
// FUNCTION: BETA10 0x100cdb3c
void LegoCarRaceActor::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoUnknown100db7f4*& p_edge, float& p_unk0xe4) void LegoCarRaceActor::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoUnknown100db7f4*& p_edge, float& p_unk0xe4)
{ {
// TODO LegoPathActor::SwitchBoundary(m_boundary, m_destEdge, m_unk0xe4);
} }
// STUB: LEGO1 0x10080b70 // STUB: LEGO1 0x10080b70

View File

@ -1,6 +1,6 @@
#include "raceskel.h" #include "raceskel.h"
#include <cassert> #include <assert.h>
DECOMP_SIZE_ASSERT(RaceSkel, 0x178) DECOMP_SIZE_ASSERT(RaceSkel, 0x178)

View File

@ -5,6 +5,8 @@
#include "legowegedge.h" #include "legowegedge.h"
#include "mxgeometry/mxgeometry3d.h" #include "mxgeometry/mxgeometry3d.h"
#include <assert.h>
// VTABLE: LEGO1 0x100db7f4 // VTABLE: LEGO1 0x100db7f4
// SIZE 0x40 // SIZE 0x40
struct LegoUnknown100db7f4 : public LegoEdge { struct LegoUnknown100db7f4 : public LegoEdge {
@ -28,6 +30,10 @@ public:
p_point[2] = -m_unk0x28[2]; p_point[2] = -m_unk0x28[2];
} }
else { else {
// clang-format off
// FIXME: There is no * dereference in the original assertion
assert(p_f.IsEqual( *m_faceB ));
// clang-format on
p_point = m_unk0x28; p_point = m_unk0x28;
} }

View File

@ -20,6 +20,8 @@ public:
// FUNCTION: BETA10 0x1001cc30 // FUNCTION: BETA10 0x1001cc30
LegoEdge** GetEdges() { return m_edges; } LegoEdge** GetEdges() { return m_edges; }
// TODO: The assertion at BETA10 0x10037352 suggests that this function might take a pointer instead of a reference
// FUNCTION: BETA10 0x100373f0
LegoU32 IsEqual(LegoWEEdge& p_other) { return this == &p_other; } LegoU32 IsEqual(LegoWEEdge& p_other) { return this == &p_other; }
void SetEdges(LegoEdge** p_edges, LegoU8 p_numEdges) void SetEdges(LegoEdge** p_edges, LegoU8 p_numEdges)

View File

@ -43,7 +43,10 @@ public:
const Matrix4& GetLocal2World() const { return m_local2world; } const Matrix4& GetLocal2World() const { return m_local2world; }
const float* GetWorldPosition() const { return m_local2world[3]; } const float* GetWorldPosition() const { return m_local2world[3]; }
// FUNCTION: BETA10 0x10011780
const float* GetWorldDirection() const { return m_local2world[2]; } const float* GetWorldDirection() const { return m_local2world[2]; }
const float* GetWorldUp() const { return m_local2world[1]; } const float* GetWorldUp() const { return m_local2world[1]; }
OrientableROI* GetParentROI() const { return m_parentROI; } OrientableROI* GetParentROI() const { return m_parentROI; }