Implement/match LegoCarRaceActor::VTable0x1c (#1078)

* Implement/match `LegoCarRaceActor::VTable0x1c`

* Fix formatting

* Fix LegoEdge::CWVertex()

* Fix more CI issues

* Trz to fix lvalue compile issue

* Fix formatting

---------

Co-authored-by: jonschz <jonschz@users.noreply.github.com>
This commit is contained in:
jonschz
2024-08-04 21:13:12 +02:00
committed by GitHub
parent fe1b66938d
commit e09acfcddb
23 changed files with 328 additions and 161 deletions

View File

@@ -40,7 +40,6 @@
#include "legoanimpresenter.h"
#include "legocarbuild.h"
#include "legocarbuildpresenter.h"
#include "legocarraceactor.h"
#include "legoentity.h"
#include "legoentitypresenter.h"
#include "legoflctexturepresenter.h"
@@ -58,6 +57,7 @@
#include "legopathpresenter.h"
#include "legophonemepresenter.h"
#include "legoracers.h"
#include "legoracespecial.h"
#include "legotexturepresenter.h"
#include "legoworld.h"
#include "legoworldpresenter.h"

View File

@@ -61,8 +61,10 @@ LegoAnimationManager* AnimationManager()
}
// FUNCTION: LEGO1 0x10015780
// FUNCTION: BETA10 0x100e49b8
LegoNavController* NavController()
{
assert(LegoOmni::GetInstance());
return LegoOmni::GetInstance()->GetNavController();
}

View File

@@ -1,124 +0,0 @@
#include "legocarraceactor.h"
#include "geom/legounkown100db7f4.h"
#include "legopathboundary.h"
#include "misc.h"
#include "mxmisc.h"
#include "mxvariabletable.h"
DECOMP_SIZE_ASSERT(LegoCarRaceActor, 0x1a0)
// GLOBAL: LEGO1 0x100f7af0
// STRING: LEGO1 0x100f7ae4
const char* g_fuel = "FUEL";
// FUNCTION: LEGO1 0x10080350
// FUNCTION: BETA10 0x100cd6b0
LegoCarRaceActor::LegoCarRaceActor()
{
m_unk0x08 = 1.0f;
m_unk0x70 = 0.0f;
m_unk0x0c = 0;
m_maxLinearVel = 0.0f;
m_frequencyFactor = 1.0f;
m_unk0x1c = 0;
m_unk0x10 = 0.65f;
m_unk0x14 = 0.03f;
m_unk0x18 = 0.6f;
m_unk0x140 = 0.1f;
m_unk0x150 = -5.0f;
m_unk0x148 = 1;
VariableTable()->SetVariable(g_fuel, "0.8");
}
// FUNCTION: LEGO1 0x10080590
// 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
void LegoCarRaceActor::VTable0x1c()
{
}
// FUNCTION: LEGO1 0x10080b40
// FUNCTION: BETA10 0x100cdb3c
void LegoCarRaceActor::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoUnknown100db7f4*& p_edge, float& p_unk0xe4)
{
LegoPathActor::SwitchBoundary(m_boundary, m_destEdge, m_unk0xe4);
}
// STUB: LEGO1 0x10080b70
void LegoCarRaceActor::VTable0x70(float p_float)
{
// TODO
}
// STUB: LEGO1 0x10080be0
MxResult LegoCarRaceActor::VTable0x9c()
{
// TODO
return SUCCESS;
}
// STUB: LEGO1 0x10081840
MxU32 LegoCarRaceActor::VTable0x6c(
LegoPathBoundary* p_boundary,
Vector3& p_v1,
Vector3& p_v2,
float p_f1,
float p_f2,
Vector3& p_v3
)
{
// TODO
return 0;
}

View File

@@ -12,9 +12,10 @@ LegoJetskiRaceActor::LegoJetskiRaceActor()
}
// STUB: LEGO1 0x10081120
void LegoJetskiRaceActor::VTable0x1c()
MxS32 LegoJetskiRaceActor::VTable0x1c(undefined4 p_param1, LegoEdge* p_edge)
{
// TODO
return 0;
}
// STUB: LEGO1 0x10081550

View File

@@ -64,7 +64,7 @@ LegoPathActor::~LegoPathActor()
}
// FUNCTION: LEGO1 0x1002d8d0
MxResult LegoPathActor::VTable0x80(Vector3& p_point1, Vector3& p_point2, Vector3& p_point3, Vector3& p_point4)
MxResult LegoPathActor::VTable0x80(const Vector3& p_point1, Vector3& p_point2, Vector3& p_point3, Vector3& p_point4)
{
Mx3DPointFloat p1, p2, p3;

View File

@@ -19,13 +19,15 @@ MxU32 g_unk0x100d7cc8[] = {2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0};
MxU32 g_unk0x100d7d08[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// GLOBAL: LEGO1 0x100f42e8
LegoPathController::CtrlBoundary* g_ctrlBoundariesA = NULL;
// GLOBAL: BETA10 0x101f25f0
LegoPathController::CtrlBoundary* LegoPathController::g_ctrlBoundariesA = NULL;
// GLOBAL: LEGO1 0x100f42ec
LegoPathController::CtrlEdge* g_ctrlEdgesA = NULL;
// GLOBAL: BETA10 0x101f25f4
LegoPathController::CtrlEdge* LegoPathController::g_ctrlEdgesA = NULL;
// GLOBAL: LEGO1 0x100f42f0
const char* g_unk0x100f42f0[] = {
const char* LegoPathController::g_unk0x100f42f0[] = {
"edg03_21",
"edg03_23",
"edg03_30",
@@ -45,7 +47,7 @@ const char* g_unk0x100f42f0[] = {
};
// GLOBAL: LEGO1 0x100f4330
const char* g_unk0x100f4330[] = {
const char* LegoPathController::g_unk0x100f4330[] = {
"edg03_06",
"edg03_21",
"edg03_30",
@@ -59,10 +61,10 @@ const char* g_unk0x100f4330[] = {
};
// GLOBAL: LEGO1 0x100f4358
LegoPathController::CtrlBoundary* g_ctrlBoundariesB = NULL;
LegoPathController::CtrlBoundary* LegoPathController::g_ctrlBoundariesB = NULL;
// GLOBAL: LEGO1 0x100f435c
LegoPathController::CtrlEdge* g_ctrlEdgesB = NULL;
LegoPathController::CtrlEdge* LegoPathController::g_ctrlEdgesB = NULL;
// FUNCTION: LEGO1 0x10044f40
// FUNCTION: BETA10 0x100b6860
@@ -620,7 +622,7 @@ MxResult LegoPathController::ReadBoundaries(LegoStorage* p_storage)
boundary.m_edgeNormals = new Mx4DPointFloat[numE];
LegoEdge** edges = new LegoEdge*[numE];
LegoUnknown100db7f4** edges = new LegoUnknown100db7f4*[numE];
boundary.SetEdges(edges, numE);
for (j = 0; j < numE; j++) {

View File

@@ -266,13 +266,13 @@ void LegoRaceCar::FUN_10012ff0(float p_param)
if (a->GetDuration() <= deltaTime || deltaTime < 0.0) {
if (m_userState == LEGORACECAR_KICK1) {
LegoEdge** edges = m_kick1B->GetEdges();
m_destEdge = (LegoUnknown100db7f4*) (edges[2]);
LegoUnknown100db7f4** edges = m_kick1B->GetEdges();
m_destEdge = edges[2];
m_boundary = m_kick1B;
}
else {
LegoEdge** edges = m_kick1B->GetEdges();
m_destEdge = (LegoUnknown100db7f4*) (edges[1]);
LegoUnknown100db7f4** edges = m_kick1B->GetEdges();
m_destEdge = edges[1];
m_boundary = m_kick2B;
}

View File

@@ -0,0 +1,228 @@
#include "legoracespecial.h"
#include "geom/legounkown100db7f4.h"
#include "legonavcontroller.h"
#include "legopathboundary.h"
#include "legopathcontroller.h"
#include "misc.h"
#include "mxmisc.h"
#include "mxvariabletable.h"
// File name verified by BETA10 0x100cedf7
DECOMP_SIZE_ASSERT(LegoCarRaceActor, 0x1a0)
// GLOBAL: LEGO1 0x100f7af0
// STRING: LEGO1 0x100f7ae4
const char* g_fuel = "FUEL";
// GLOBAL: LEGO1 0x100f7aec
MxFloat LegoCarRaceActor::g_unk0x100f7aec = 8.0f;
// FUNCTION: LEGO1 0x10080350
// FUNCTION: BETA10 0x100cd6b0
LegoCarRaceActor::LegoCarRaceActor()
{
m_unk0x08 = 1.0f;
m_unk0x70 = 0.0f;
m_unk0x0c = 0;
m_maxLinearVel = 0.0f;
m_frequencyFactor = 1.0f;
m_unk0x1c = 0;
m_unk0x10 = 0.65f;
m_unk0x14 = 0.03f;
m_unk0x18 = 0.6f;
m_unk0x140 = 0.1f;
m_unk0x150 = -5.0f;
m_unk0x148 = 1;
VariableTable()->SetVariable(g_fuel, "0.8");
}
// FUNCTION: LEGO1 0x10080590
// 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);
}
// FUNCTION: LEGO1 0x10080740
// FUNCTION: BETA10 0x100cece0
MxS32 LegoCarRaceActor::VTable0x1c(undefined4 p_param1, LegoEdge* p_edge)
{
Mx3DPointFloat pointUnknown;
Mx3DPointFloat destEdgeUnknownVector;
Mx3DPointFloat crossProduct;
if (m_state == 1) {
m_boundary = NULL;
// Not sure where the upper bound of 11 comes from, the underlying array has a size of 16
for (MxS32 i = 0; i < 11; i += 2) {
if (LegoPathController::GetControlEdgeA(i + 1) == m_destEdge) {
m_boundary = LegoPathController::GetControlBoundaryA(i + 1);
break;
}
}
assert(m_boundary);
m_state = 0;
m_unk0x7c = 0;
if (m_userNavFlag) {
NavController()->SetLinearVel(m_worldSpeed);
return 0;
}
else {
return 1;
}
}
else {
for (MxS32 i = 0; i < 11; i += 2) {
if (LegoPathController::GetControlEdgeA(i) == p_edge) {
m_state = 1;
if (m_worldSpeed < g_unk0x100f7aec) {
m_worldSpeed = g_unk0x100f7aec;
}
m_destEdge = LegoPathController::GetControlEdgeA(i + 1);
m_boundary = LegoPathController::GetControlBoundaryA(i + 1);
break;
}
}
if (m_state == 1) {
if (m_userNavFlag) {
m_unk0xe4 = 0.5f;
}
// variable names verified by BETA10
Vector3* v1 = m_destEdge->CCWVertex(*m_boundary);
Vector3* v2 = m_destEdge->CWVertex(*m_boundary);
assert(v1 && v2);
pointUnknown[0] = (*v1)[0] + ((*v2)[0] - (*v1)[0]) * m_unk0xe4;
pointUnknown[1] = (*v1)[1] + ((*v2)[1] - (*v1)[1]) * m_unk0xe4;
pointUnknown[2] = (*v1)[2] + ((*v2)[2] - (*v1)[2]) * m_unk0xe4;
m_destEdge->FUN_1002ddc0(*m_boundary, destEdgeUnknownVector);
crossProduct.EqualsCross(m_boundary->GetUnknown0x14(), &destEdgeUnknownVector);
crossProduct.Unitize();
Mx3DPointFloat worldDirection(Vector3(m_roi->GetWorldDirection()));
if (!m_userNavFlag) {
((Vector3*) &worldDirection)->Mul(-1.0f);
}
((Vector3*) &worldDirection)->Mul(5.0f);
((Vector3*) &crossProduct)->Mul(5.0f);
MxResult callResult =
VTable0x80(Vector3(m_roi->GetWorldPosition()), worldDirection, pointUnknown, crossProduct);
if (callResult) {
m_unk0x7c = 0;
return 0;
}
else {
m_unk0x7c = 0;
assert(0);
return 0; // BETA10 returns -1 here
}
}
else {
// This `for` loop does not exist in BETA10
for (MxS32 i = 0; i < 10; i++) {
if (LegoPathController::GetControlEdgeB(i) == p_edge &&
LegoPathController::GetControlBoundaryB(i) == m_boundary) {
return 0;
}
}
return 1;
}
}
}
// FUNCTION: LEGO1 0x10080b40
// FUNCTION: BETA10 0x100cdb3c
void LegoCarRaceActor::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoUnknown100db7f4*& p_edge, float& p_unk0xe4)
{
LegoPathActor::SwitchBoundary(m_boundary, m_destEdge, m_unk0xe4);
}
// STUB: LEGO1 0x10080b70
void LegoCarRaceActor::VTable0x70(float p_float)
{
// TODO
}
// STUB: LEGO1 0x10080be0
MxResult LegoCarRaceActor::VTable0x9c()
{
// TODO
return SUCCESS;
}
// STUB: LEGO1 0x10081840
MxU32 LegoCarRaceActor::VTable0x6c(
LegoPathBoundary* p_boundary,
Vector3& p_v1,
Vector3& p_v2,
float p_f1,
float p_f2,
Vector3& p_v3
)
{
// TODO
return 0;
}