From 07def56326a40edeef72dfb9ea4f59bb22b89917 Mon Sep 17 00:00:00 2001
From: jonschz <17198703+jonschz@users.noreply.github.com>
Date: Mon, 9 Dec 2024 22:05:08 +0100
Subject: [PATCH] Implement `Act2Actor::VTable0x70` (#1201)

* Implement draft of `Act2Actor::VTable0x70`

* Fix CI errors

* Implement `Act2Actor::FUN_100199f0`

* WIP: cleanup

* Address review comments

* Run formatter

---------

Co-authored-by: jonschz <jonschz@users.noreply.github.com>
---
 LEGO1/lego/legoomni/include/act2actor.h       |  13 +-
 LEGO1/lego/legoomni/include/legoact2.h        |  19 +-
 LEGO1/lego/legoomni/src/actors/act2actor.cpp  | 282 +++++++++++++++++-
 LEGO1/lego/legoomni/src/entity/legoworld.cpp  |   1 +
 LEGO1/lego/legoomni/src/main/legomain.cpp     |   4 +-
 .../lego/legoomni/src/paths/legoanimactor.cpp |   5 +-
 .../lego/legoomni/src/paths/legopathactor.cpp |   1 +
 .../legoomni/src/video/legoanimpresenter.cpp  |   1 +
 LEGO1/lego/legoomni/src/worlds/legoact2.cpp   |  14 +
 LEGO1/lego/sources/3dmanager/lego3dview.h     |   2 +-
 LEGO1/mxgeometry/mxmatrix.h                   |   1 +
 LEGO1/viewmanager/viewmanager.h               |   2 +
 12 files changed, 325 insertions(+), 20 deletions(-)

diff --git a/LEGO1/lego/legoomni/include/act2actor.h b/LEGO1/lego/legoomni/include/act2actor.h
index cf8ed507..905743fb 100644
--- a/LEGO1/lego/legoomni/include/act2actor.h
+++ b/LEGO1/lego/legoomni/include/act2actor.h
@@ -28,8 +28,11 @@ class Act2Actor : public LegoAnimActor {
 	MxS32 VTable0xa0() override;                                            // vtable+0xa0
 
 	void FUN_10018980();
+	void FUN_10019250(MxFloat p_speed, MxFloat p_param2);
 	void FUN_10019520();
 	void FUN_10019560();
+	undefined4 FUN_10019700(MxFloat p_param);
+	void FUN_100199f0(MxS8 p_param);
 	void FUN_100192a0(undefined4 p_param);
 
 	// SYNTHETIC: LEGO1 0x1001a0a0
@@ -44,16 +47,16 @@ class Act2Actor : public LegoAnimActor {
 	MxS8 m_unk0x1d;                   // 0x1d
 	undefined m_unk0x1e;              // 0x1e
 	MxBool m_unk0x1f;                 // 0x1f
-	undefined4 m_unk0x20;             // 0x20
-	undefined4 m_unk0x24;             // 0x24
+	MxFloat m_unk0x20;                // 0x20
+	MxFloat m_unk0x24;                // 0x24
 	MxS8 m_unk0x28;                   // 0x28
-	undefined4 m_unk0x2c;             // 0x2c
-	undefined4 m_unk0x30;             // 0x30
+	MxFloat m_unk0x2c;                // 0x2c
+	MxFloat m_unk0x30;                // 0x30
 	LegoAnimActorStruct* m_shootAnim; // 0x34
 	LegoCacheSound* m_unk0x38;        // 0x38
 	undefined4 m_unk0x3c;             // 0x3c
 	undefined m_unk0x40;              // 0x40
-	undefined4 m_unk0x44;             // 0x44
+	MxFloat m_unk0x44;                // 0x44
 	MxS8 m_unk0x48;                   // 0x48
 	undefined4 m_unk0x4c;             // 0x4c
 };
diff --git a/LEGO1/lego/legoomni/include/legoact2.h b/LEGO1/lego/legoomni/include/legoact2.h
index 797b2249..e43c3a7a 100644
--- a/LEGO1/lego/legoomni/include/legoact2.h
+++ b/LEGO1/lego/legoomni/include/legoact2.h
@@ -68,6 +68,17 @@ class LegoAct2 : public LegoWorld {
 	void SetUnknown0x1138(Act2Actor* p_unk0x1138) { m_unk0x1138 = p_unk0x1138; }
 	void SetDestLocation(LegoGameState::Area p_destLocation) { m_destLocation = p_destLocation; }
 
+	MxResult FUN_100516b0();
+	void FUN_100517b0();
+	MxResult FUN_10052560(
+		Act2mainScript::Script p_objectId,
+		MxBool p_param2,
+		MxBool p_param3,
+		Mx3DPointFloat* p_location,
+		Mx3DPointFloat* p_direction,
+		Mx3DPointFloat* p_param6
+	);
+
 	// SYNTHETIC: LEGO1 0x1004fe20
 	// LegoAct2::`scalar deleting destructor'
 
@@ -83,14 +94,6 @@ class LegoAct2 : public LegoWorld {
 	void SpawnBricks();
 	void FUN_10051fa0(MxS32 p_param1);
 	void FUN_100521f0(MxS32 p_param1);
-	MxResult FUN_10052560(
-		Act2mainScript::Script p_objectId,
-		MxBool p_param2,
-		MxBool p_param3,
-		Mx3DPointFloat* p_location,
-		Mx3DPointFloat* p_direction,
-		Mx3DPointFloat* p_param6
-	);
 	MxResult FUN_10052800();
 
 	Act2Brick m_bricks[10];        // 0x00f8
diff --git a/LEGO1/lego/legoomni/src/actors/act2actor.cpp b/LEGO1/lego/legoomni/src/actors/act2actor.cpp
index 1d29f18b..f70788d5 100644
--- a/LEGO1/lego/legoomni/src/actors/act2actor.cpp
+++ b/LEGO1/lego/legoomni/src/actors/act2actor.cpp
@@ -1,11 +1,19 @@
 #include "act2actor.h"
 
+#include "3dmanager/lego3dmanager.h"
+#include "act2main_actions.h"
+#include "legoact2.h"
 #include "legocachesoundmanager.h"
 #include "legopathcontroller.h"
 #include "legopathedgecontainer.h"
 #include "legosoundmanager.h"
+#include "legovideomanager.h"
+#include "legoworld.h"
 #include "misc.h"
 #include "roi/legoroi.h"
+#include "viewmanager/viewmanager.h"
+
+#include <vec.h>
 
 DECOMP_SIZE_ASSERT(Act2Actor, 0x1a8)
 DECOMP_SIZE_ASSERT(Act2Actor::UnknownListStructure, 0x20)
@@ -26,6 +34,21 @@ Act2Actor::UnknownListStructure g_unk0x100f0db8[] = {
 	{{-44.6, 0.1, 45.3}, {0.95, 0.0, -0.3}, "edg00_154", FALSE},
 };
 
+// GLOBAL: LEGO1 0x100f0f1c
+MxFloat g_unk0x100f0f1c = 0.0f;
+
+// GLOBAL: LEGO1 0x10102b1c
+// GLOBAL: BETA10 0x10209f60
+undefined4 g_nextHeadWavIndex = 0;
+
+// GLOBAL: LEGO1 0x10102b20
+// GLOBAL: BETA10 0x10209f64
+undefined4 g_nextBehindWavIndex = 0;
+
+// GLOBAL: LEGO1 0x10102b24
+// GLOBAL: BETA10 0x10209f68
+undefined4 g_nextInterruptWavIndex = 0;
+
 // FUNCTION: LEGO1 0x100187e0
 // FUNCTION: BETA10 0x1000c7fb
 Act2Actor::Act2Actor()
@@ -115,11 +138,186 @@ MxResult Act2Actor::VTable0x9c()
 	}
 }
 
-// STUB: LEGO1 0x10018c30
-// STUB: BETA10 0x1000cb52
+// FUNCTION: LEGO1 0x10018c30
+// FUNCTION: BETA10 0x1000cb52
 void Act2Actor::VTable0x70(float p_time)
 {
-	// TODO
+	int dummy1; // for BETA10, not sure what it is being used for
+
+#ifdef NDEBUG
+	MxFloat local48float = 0.0f;
+	if (g_unk0x100f0f1c != 0.0f) {
+		local48float = p_time - g_unk0x100f0f1c;
+	}
+
+	g_unk0x100f0f1c = p_time;
+#endif
+
+	LegoAnimActor::VTable0x70(p_time);
+
+	if (m_unk0x44 != 0.0f && m_unk0x44 < p_time) {
+		SetWorldSpeed(m_unk0x28);
+	}
+
+	if (m_unk0x1f) {
+		if (m_unk0x20 > 600.0f) {
+			m_unk0x1f = FALSE;
+			m_unk0x20 = 0;
+		}
+		else {
+#ifdef NDEBUG
+			m_unk0x20 += local48float;
+#endif
+			MxMatrix matrix = m_roi->GetLocal2World();
+			matrix[3][1] += 3.0f;
+			m_roi->UpdateTransformationRelativeToParent(matrix);
+
+#ifdef NDEBUG
+			LegoROI* brickstrROI = FindROI("brickstr");
+			MxMatrix brickstrMatrix = brickstrROI->GetLocal2World();
+			brickstrMatrix[3][1] += 3.0f;
+			brickstrROI->UpdateTransformationRelativeToParent(brickstrMatrix);
+#endif
+			return;
+		}
+	}
+
+	if (!m_grec) {
+		if (m_unk0x1e == 2) {
+			m_unk0x1e = 0;
+			m_unk0x2c = m_shootAnim->GetDuration() + p_time;
+			m_unk0x30 = m_unk0x2c - 1300.0f;
+			SetWorldSpeed(0);
+			m_unk0x1c = FALSE;
+		}
+		else if (m_unk0x1e == 1) {
+			FindROI("pwrbrik")->SetVisibility(FALSE);
+			FindROI("debrick")->SetVisibility(FALSE);
+			FindROI("ray")->SetVisibility(FALSE);
+			m_unk0x4c = 0;
+			m_unk0x1e = 2;
+			VTable0xa0();
+			FUN_10019250(m_unk0x28 + 3, p_time + 3000.0f);
+		}
+		else if (m_unk0x1e == 0) {
+			if (m_unk0x40) {
+				m_unk0x40 = 0;
+				m_unk0x2c = m_shootAnim->GetDuration() + p_time;
+				m_unk0x30 = m_unk0x2c - 1300.0f;
+			}
+
+			if (FUN_10019700(p_time) == 1) {
+				return;
+			}
+		}
+		else if (m_unk0x1e == 5) {
+			FindROI("brickstr")->SetVisibility(FALSE);
+			GetROI()->SetVisibility(FALSE);
+			CurrentWorld()->RemoveActor(this);
+			return;
+		}
+#ifdef NDEBUG
+		else if (m_unk0x1e == 4) {
+			if (m_worldSpeed == 0.0f) {
+				return;
+			}
+
+			SetWorldSpeed(0.0f);
+			((LegoAct2*) CurrentWorld())->FUN_100517b0();
+			return;
+		}
+#endif
+	}
+
+	if (m_unk0x1e == 5 || m_unk0x1e == 4) {
+		return;
+	}
+
+	if (m_unk0x1e == 3) {
+		if (p_time - m_unk0x24 > 600.0f) {
+			m_unk0x1e = 2;
+			FUN_10019250(m_unk0x28 + 4, p_time + 15000.0f);
+		}
+	}
+	else {
+		LegoROI* roiPepper = FindROI("pepper");
+
+		if (roiPepper) {
+			ViewManager* vm = VideoManager()->Get3DManager()->GetLego3DView()->GetViewManager();
+			assert(vm);
+
+			MxU32 inFrustum = vm->IsBoundingBoxInFrustum(m_roi->GetWorldBoundingBox());
+
+			if (inFrustum) {
+				Mx3DPointFloat local18(roiPepper->GetWorldDirection());
+				Mx3DPointFloat local30(m_roi->GetWorldPosition());
+				Mx3DPointFloat local60(roiPepper->GetWorldPosition());
+				local30 -= local60;
+				local30.Unitize();
+
+				MxFloat dotproduct = local18.Dot(&local30, &local18);
+
+				if (dotproduct >= 0.0) {
+					const MxFloat* pepperWorldPosition = roiPepper->GetWorldPosition();
+					const MxFloat* worldPosition = m_roi->GetWorldPosition();
+
+					MxFloat distance1 = DISTSQRD3(pepperWorldPosition, worldPosition);
+
+					if (distance1 < 75.0f) {
+						if (!m_unk0x1c) {
+							m_unk0x1c = 1;
+
+							if (!m_unk0x1e) {
+								FUN_100199f0(2);
+								m_unk0x1e = 1;
+							}
+							else {
+								LegoROI* childROI = m_roi->FindChildROI("windsd", m_roi);
+								const MxFloat* childPosition = childROI->GetWorldPosition();
+								MxFloat distance2 = DISTSQRD3(pepperWorldPosition, childPosition);
+
+								childROI = m_roi->FindChildROI("reardr", m_roi);
+								childPosition = childROI->GetWorldPosition();
+								MxFloat distance3 = DISTSQRD3(pepperWorldPosition, childPosition);
+
+								if (distance3 > distance2) {
+									FUN_100199f0(0);
+								}
+								else
+#ifdef NDEBUG
+									if (p_time - m_unk0x24 > 3000.0f) {
+#endif
+									SetWorldSpeed(m_unk0x28 - 1);
+									m_unk0x1e = 3;
+									m_unk0x24 = p_time;
+
+									if (!((LegoAct2*) CurrentWorld())->FUN_100516b0()) {
+										FUN_100199f0(1);
+									}
+#ifdef NDEBUG
+								}
+#endif
+							}
+						}
+					}
+					else {
+						if (m_unk0x1c) {
+							m_unk0x1c = 0;
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
+// FUNCTION: LEGO1 0x10019250
+// FUNCTION: BETA10 0x1000d45c
+void Act2Actor::FUN_10019250(MxFloat p_speed, MxFloat p_param2)
+{
+	// The arguments have been changed from BETA10 to LEGO1
+	SetWorldSpeed(p_speed);
+	m_unk0x44 = p_param2;
 }
 
 // FUNCTION: LEGO1 0x10019280
@@ -298,6 +496,84 @@ MxS32 Act2Actor::VTable0xa0()
 	}
 }
 
+// STUB: LEGO1 0x10019700
+// STUB: BETA10 0x1000dd27
+undefined4 Act2Actor::FUN_10019700(MxFloat p_param)
+{
+	// TODO
+	return 0;
+}
+
+// FUNCTION: LEGO1 0x100199f0
+// FUNCTION: BETA10 0x1000e11a
+void Act2Actor::FUN_100199f0(MxS8 p_param)
+{
+	switch (p_param) {
+	case 0:
+		switch (g_nextHeadWavIndex) {
+		case 0:
+			((LegoAct2*) CurrentWorld())
+				->FUN_10052560(Act2mainScript::c_VOhead0_PlayWav, FALSE, FALSE, NULL, NULL, NULL);
+
+			g_nextHeadWavIndex++;
+			break;
+		default:
+			((LegoAct2*) CurrentWorld())
+				->FUN_10052560(Act2mainScript::c_VOhead1_PlayWav, FALSE, FALSE, NULL, NULL, NULL);
+			g_nextHeadWavIndex = 0;
+			break;
+		}
+		break;
+	case 1:
+		switch (g_nextBehindWavIndex) {
+		case 0:
+			((LegoAct2*) CurrentWorld())
+				->FUN_10052560(Act2mainScript::c_VObehind0_PlayWav, FALSE, TRUE, NULL, NULL, NULL);
+			g_nextBehindWavIndex++;
+			break;
+		case 1:
+			((LegoAct2*) CurrentWorld())
+				->FUN_10052560(Act2mainScript::c_VObehind1_PlayWav, FALSE, TRUE, NULL, NULL, NULL);
+			g_nextBehindWavIndex++;
+			break;
+		case 2:
+			((LegoAct2*) CurrentWorld())
+				->FUN_10052560(Act2mainScript::c_VObehind2_PlayWav, FALSE, TRUE, NULL, NULL, NULL);
+			g_nextBehindWavIndex++;
+			break;
+		default:
+			((LegoAct2*) CurrentWorld())
+				->FUN_10052560(Act2mainScript::c_VObehind3_PlayWav, FALSE, TRUE, NULL, NULL, NULL);
+			g_nextBehindWavIndex = 0;
+			break;
+		}
+		break;
+	case 2:
+		switch (g_nextInterruptWavIndex) {
+		case 0:
+			((LegoAct2*) CurrentWorld())
+				->FUN_10052560(Act2mainScript::c_VOinterrupt0_PlayWav, FALSE, FALSE, NULL, NULL, NULL);
+			g_nextInterruptWavIndex++;
+			break;
+		case 1:
+			((LegoAct2*) CurrentWorld())
+				->FUN_10052560(Act2mainScript::c_VOinterrupt1_PlayWav, FALSE, FALSE, NULL, NULL, NULL);
+			g_nextInterruptWavIndex++;
+			break;
+		case 2:
+			((LegoAct2*) CurrentWorld())
+				->FUN_10052560(Act2mainScript::c_VOinterrupt2_PlayWav, FALSE, FALSE, NULL, NULL, NULL);
+			g_nextInterruptWavIndex++;
+			break;
+		default:
+			((LegoAct2*) CurrentWorld())
+				->FUN_10052560(Act2mainScript::c_VOinterrupt3_PlayWav, FALSE, FALSE, NULL, NULL, NULL);
+			g_nextInterruptWavIndex = 0;
+			break;
+		}
+	}
+}
+
 // FUNCTION: LEGO1 0x1001a180
 MxS32 Act2Actor::VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3)
 {
diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp
index 88023db9..2dbcce2e 100644
--- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp
+++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp
@@ -339,6 +339,7 @@ MxResult LegoWorld::PlaceActor(
 }
 
 // FUNCTION: LEGO1 0x1001fc80
+// FUNCTION: BETA10 0x100da4bf
 void LegoWorld::RemoveActor(LegoPathActor* p_actor)
 {
 	LegoPathControllerListCursor cursor(&m_list0x68);
diff --git a/LEGO1/lego/legoomni/src/main/legomain.cpp b/LEGO1/lego/legoomni/src/main/legomain.cpp
index 7fc35185..4a751ab7 100644
--- a/LEGO1/lego/legoomni/src/main/legomain.cpp
+++ b/LEGO1/lego/legoomni/src/main/legomain.cpp
@@ -408,8 +408,8 @@ void LegoOmni::DeleteObject(MxDSAction& p_dsAction)
 // FUNCTION: BETA10 0x1008ea6d
 LegoROI* LegoOmni::FindROI(const char* p_name)
 {
-	ViewManager* viewManager = GetVideoManager()->Get3DManager()->GetLego3DView()->GetViewManager();
-	const CompoundObject& rois = viewManager->GetROIs();
+	const CompoundObject& rois =
+		((LegoVideoManager*) m_videoManager)->Get3DManager()->GetLego3DView()->GetViewManager()->GetROIs();
 
 	if (p_name != NULL && *p_name != '\0' && rois.size() > 0) {
 		for (CompoundObject::const_iterator it = rois.begin(); it != rois.end(); it++) {
diff --git a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp
index 6001212b..234bf344 100644
--- a/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp
+++ b/LEGO1/lego/legoomni/src/paths/legoanimactor.cpp
@@ -30,7 +30,7 @@ LegoAnimActorStruct::~LegoAnimActorStruct()
 }
 
 // FUNCTION: LEGO1 0x1001c130
-// FUNCTION: BETA10 0x1003df5f
+// FUNCTION: BETA10 0x1003df3a
 float LegoAnimActorStruct::GetDuration()
 {
 	assert(m_AnimTreePtr);
@@ -70,8 +70,11 @@ void LegoAnimActor::VTable0x74(Matrix4& p_transform)
 }
 
 // FUNCTION: LEGO1 0x1001c290
+// FUNCTION: BETA10 0x1003e144
 void LegoAnimActor::VTable0x70(float p_time)
 {
+	assert(m_roi);
+
 	if (m_lastTime == 0) {
 		m_lastTime = p_time - 1.0f;
 	}
diff --git a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp
index 1d5bb959..3c859936 100644
--- a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp
+++ b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp
@@ -380,6 +380,7 @@ void LegoPathActor::VTable0x74(Matrix4& p_transform)
 }
 
 // FUNCTION: LEGO1 0x1002e790
+// FUNCTION: BETA10 0x100af208
 void LegoPathActor::VTable0x70(float p_time)
 {
 	MxMatrix transform;
diff --git a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp
index 15140eca..c827043f 100644
--- a/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp
+++ b/LEGO1/lego/legoomni/src/video/legoanimpresenter.cpp
@@ -289,6 +289,7 @@ void LegoAnimPresenter::FUN_100692b0()
 }
 
 // FUNCTION: LEGO1 0x100695c0
+// FUNCTION: BETA10 0x1004f359
 void LegoAnimPresenter::FUN_100695c0()
 {
 	m_unk0x70 = new LegoROIList();
diff --git a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp
index 9119eb1b..f25a77ab 100644
--- a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp
+++ b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp
@@ -659,6 +659,20 @@ MxLong LegoAct2::HandlePathStruct(LegoPathStructNotificationParam& p_param)
 	return 0;
 }
 
+// STUB: LEGO1 0x100516b0
+// STUB: BETA10 0x1003bcbc
+MxResult LegoAct2::FUN_100516b0()
+{
+	// TODO
+	return SUCCESS;
+}
+
+// STUB: LEGO1 0x100517b0
+void LegoAct2::FUN_100517b0()
+{
+	// TODO
+}
+
 // FUNCTION: LEGO1 0x10051840
 void LegoAct2::PlayMusic(JukeboxScript::Script p_objectId)
 {
diff --git a/LEGO1/lego/sources/3dmanager/lego3dview.h b/LEGO1/lego/sources/3dmanager/lego3dview.h
index 9e0f69eb..1f878a53 100644
--- a/LEGO1/lego/sources/3dmanager/lego3dview.h
+++ b/LEGO1/lego/sources/3dmanager/lego3dview.h
@@ -46,7 +46,7 @@ class Lego3DView : public LegoView1 {
 //
 // Lego3DView implementation
 
-// FUNCTION: BETA10 0x100576b0
+// FUNCTION: BETA10 0x10011810
 inline ViewManager* Lego3DView::GetViewManager()
 {
 	return m_pViewManager;
diff --git a/LEGO1/mxgeometry/mxmatrix.h b/LEGO1/mxgeometry/mxmatrix.h
index 55a17da1..9f1aa59f 100644
--- a/LEGO1/mxgeometry/mxmatrix.h
+++ b/LEGO1/mxgeometry/mxmatrix.h
@@ -13,6 +13,7 @@ class MxMatrix : public Matrix4 {
 	MxMatrix() : Matrix4(m_elements) {}
 
 	// FUNCTION: LEGO1 0x10032770
+	// FUNCTION: BETA10 0x1001ff30
 	MxMatrix(const MxMatrix& p_matrix) : Matrix4(m_elements) { Equals(p_matrix); }
 
 	// FUNCTION: BETA10 0x1000fc20
diff --git a/LEGO1/viewmanager/viewmanager.h b/LEGO1/viewmanager/viewmanager.h
index 92236873..051fe0fa 100644
--- a/LEGO1/viewmanager/viewmanager.h
+++ b/LEGO1/viewmanager/viewmanager.h
@@ -39,7 +39,9 @@ class ViewManager {
 	inline static int CalculateLODLevel(float p_und1, float p_und2, ViewROI* p_roi);
 	inline static int IsROIVisibleAtLOD(ViewROI* p_roi);
 
+	// FUNCTION: BETA10 0x100576b0
 	const CompoundObject& GetROIs() { return rois; }
+
 	void Add(ViewROI* p_roi) { rois.push_back(p_roi); }
 
 	// SYNTHETIC: LEGO1 0x100a6000