Implement various infocenter functions (#510)

* Implement various infocenter methods

* fix order

* Update infocenter.cpp

* Update infocenter.cpp

* Update infocenter.cpp

* Update mxcontrolpresenter.cpp

* Rename stuff for consistency

* Add StateStruct to InfocenterState

* Resolve some TODO

* Use MxRect32

* Improve match

* Match Infocenter::UpdateFrameHot

* Fix VTable0x64

* WIP Match

* Match

* Cleanup

---------

Co-authored-by: Christian Semmler <mail@csemmler.com>
This commit is contained in:
Misha
2024-01-31 09:47:15 -05:00
committed by GitHub
parent bad32149ca
commit 9e0b19856c
20 changed files with 486 additions and 118 deletions

View File

@@ -1,5 +1,6 @@
#include "elevatorbottom.h"
#include "act1state.h"
#include "jukebox.h"
#include "legocontrolmanager.h"
#include "legogamestate.h"
@@ -7,9 +8,14 @@
#include "legoomni.h"
#include "mxnotificationmanager.h"
#include "mxomni.h"
#include "mxtransitionmanager.h"
DECOMP_SIZE_ASSERT(ElevatorBottom, 0xfc)
// STRING: LEGO1 0x100f0d34
// GLOBAL: LEGO1 0x100f3a44
char* g_cameraLoc = "CAMERA_LOCATION";
// FUNCTION: LEGO1 0x10017e90
ElevatorBottom::ElevatorBottom()
{
@@ -52,8 +58,8 @@ MxLong ElevatorBottom::Notify(MxParam& p_param)
if (m_worldStarted) {
switch (((MxNotificationParam&) p_param).GetType()) {
case c_notificationType17:
ret = HandleNotification17(p_param);
case c_notificationClick:
ret = HandleClick((LegoControlManagerEvent&) p_param);
break;
case c_notificationTransitioned:
GameState()->SwitchArea(m_unk0xf8);
@@ -72,10 +78,41 @@ void ElevatorBottom::ReadyWorld()
FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen);
}
// STUB: LEGO1 0x100181d0
MxLong ElevatorBottom::HandleNotification17(MxParam& p_param)
// FUNCTION: LEGO1 0x100181d0
MxLong ElevatorBottom::HandleClick(LegoControlManagerEvent& p_param)
{
return 0;
MxLong result = 0;
if (p_param.GetUnknown0x28() == 1) {
switch (p_param.GetClickedObjectId()) {
case 1:
m_unk0xf8 = 3;
TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE);
result = 1;
break;
case 2:
m_unk0xf8 = 2;
TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE);
result = 1;
break;
case 3:
LegoGameState* gs = GameState();
Act1State* state = (Act1State*) gs->GetState("Act1State");
if (state == NULL) {
state = (Act1State*) gs->CreateState("Act1State");
}
state->SetUnknown1c(1);
m_unk0xf8 = 6;
TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE);
VariableTable()->SetVariable(g_cameraLoc, "LCAMZI1,90");
result = 1;
break;
}
}
return result;
}
// FUNCTION: LEGO1 0x100182c0

View File

@@ -32,7 +32,7 @@ Infocenter::Infocenter()
m_infocenterState = NULL;
m_frameHotBitmap = 0;
m_unk0x11c = 0;
m_unk0x104 = 0;
m_transitionDestination = 0;
m_currentInfomainScript = c_noInfomain;
m_currentCutscene = e_noIntro;
@@ -126,8 +126,8 @@ MxLong Infocenter::Notify(MxParam& p_param)
((LegoEventNotificationParam&) p_param).GetY()
);
break;
case c_notificationType17:
result = HandleNotification17(p_param);
case c_notificationClick:
result = HandleClick((LegoControlManagerEvent&) p_param);
break;
case c_notificationTransitioned:
StopBookAnimation();
@@ -137,10 +137,10 @@ MxLong Infocenter::Notify(MxParam& p_param)
StartCredits();
m_infocenterState->SetUnknown0x74(0xd);
}
else if (m_unk0x104 != 0) {
else if (m_transitionDestination != 0) {
BackgroundAudioManager()->RaiseVolume();
GameState()->SwitchArea(m_unk0x104);
m_unk0x104 = 0;
GameState()->SwitchArea(m_transitionDestination);
m_transitionDestination = 0;
}
break;
}
@@ -189,7 +189,7 @@ MxLong Infocenter::HandleEndAction(MxParam& p_param)
break;
}
FUN_10070dc0(TRUE);
UpdateFrameHot(TRUE);
}
}
@@ -383,63 +383,82 @@ void Infocenter::InitializeBitmaps()
((MxPresenter*) Find(m_atom, c_radioCtl))->Enable(TRUE);
m_mapAreas[0].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Info_A_Bitmap");
m_mapAreas[0].m_unk0x08 = 391;
m_mapAreas[0].m_unk0x0c = 182;
m_mapAreas[0].m_unk0x10 = 427;
m_mapAreas[0].m_unk0x14 = 230;
m_mapAreas[0].m_area.SetLeft(391);
m_mapAreas[0].m_area.SetTop(182);
m_mapAreas[0].m_area.SetRight(427);
m_mapAreas[0].m_area.SetBottom(230);
m_mapAreas[0].m_unk0x04 = 3;
m_mapAreas[1].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Boat_A_Bitmap");
m_mapAreas[1].m_unk0x08 = 304;
m_mapAreas[1].m_unk0x0c = 225;
m_mapAreas[1].m_unk0x10 = 350;
m_mapAreas[1].m_unk0x14 = 268;
m_mapAreas[1].m_area.SetLeft(304);
m_mapAreas[1].m_area.SetTop(225);
m_mapAreas[1].m_area.SetRight(350);
m_mapAreas[1].m_area.SetBottom(268);
m_mapAreas[1].m_unk0x04 = 10;
m_mapAreas[2].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Race_A_Bitmap");
m_mapAreas[2].m_unk0x08 = 301;
m_mapAreas[2].m_unk0x0c = 133;
m_mapAreas[2].m_unk0x10 = 347;
m_mapAreas[2].m_unk0x14 = 181;
m_mapAreas[2].m_area.SetLeft(301);
m_mapAreas[2].m_area.SetTop(133);
m_mapAreas[2].m_area.SetRight(347);
m_mapAreas[2].m_area.SetBottom(181);
m_mapAreas[2].m_unk0x04 = 11;
m_mapAreas[3].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Pizza_A_Bitmap");
m_mapAreas[3].m_unk0x08 = 289;
m_mapAreas[3].m_unk0x0c = 182;
m_mapAreas[3].m_unk0x10 = 335;
m_mapAreas[3].m_unk0x14 = 225;
m_mapAreas[3].m_area.SetLeft(289);
m_mapAreas[3].m_area.SetTop(182);
m_mapAreas[3].m_area.SetRight(335);
m_mapAreas[3].m_area.SetBottom(225);
m_mapAreas[3].m_unk0x04 = 12;
m_mapAreas[4].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Gas_A_Bitmap");
m_mapAreas[4].m_unk0x10 = 391;
m_mapAreas[4].m_unk0x08 = 350;
m_mapAreas[4].m_unk0x0c = 161;
m_mapAreas[4].m_unk0x14 = 209;
m_mapAreas[4].m_area.SetLeft(350);
m_mapAreas[4].m_area.SetTop(161);
m_mapAreas[4].m_area.SetRight(391);
m_mapAreas[4].m_area.SetBottom(209);
m_mapAreas[4].m_unk0x04 = 13;
m_mapAreas[5].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Med_A_Bitmap");
m_mapAreas[5].m_unk0x08 = 392;
m_mapAreas[5].m_unk0x0c = 130;
m_mapAreas[5].m_unk0x10 = 438;
m_mapAreas[5].m_unk0x14 = 176;
m_mapAreas[5].m_area.SetLeft(392);
m_mapAreas[5].m_area.SetTop(130);
m_mapAreas[5].m_area.SetRight(438);
m_mapAreas[5].m_area.SetBottom(176);
m_mapAreas[5].m_unk0x04 = 14;
m_mapAreas[6].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Cop_A_Bitmap");
m_mapAreas[6].m_unk0x08 = 396;
m_mapAreas[6].m_unk0x0c = 229;
m_mapAreas[6].m_unk0x10 = 442;
m_mapAreas[6].m_unk0x14 = 272;
m_mapAreas[6].m_area.SetLeft(396);
m_mapAreas[6].m_area.SetTop(229);
m_mapAreas[6].m_area.SetRight(442);
m_mapAreas[6].m_area.SetBottom(272);
m_mapAreas[6].m_unk0x04 = 15;
m_frameHotBitmap = (MxStillPresenter*) Find("MxStillPresenter", "FrameHot_Bitmap");
FUN_10070dc0(TRUE);
UpdateFrameHot(TRUE);
}
// STUB: LEGO1 0x1006fd00
// FUNCTION: LEGO1 0x1006fd00
MxU8 Infocenter::HandleMouseMove(MxS32 p_x, MxS32 p_y)
{
return 1;
if (m_unk0x11c) {
if (!m_unk0x11c->IsEnabled()) {
MxS32 oldDisplayZ = m_unk0x11c->GetDisplayZ();
m_unk0x11c->SetDisplayZ(1000);
VideoManager()->SortPresenterList();
m_unk0x11c->Enable(TRUE);
m_unk0x11c->VTable0x88(p_x, p_y);
m_unk0x11c->SetDisplayZ(oldDisplayZ);
}
else {
m_unk0x11c->VTable0x88(p_x, p_y);
}
FUN_10070d10(p_x, p_y);
return 1;
}
return 0;
}
// FUNCTION: LEGO1 0x1006fda0
@@ -492,12 +511,129 @@ MxLong Infocenter::HandleKeyPress(MxS8 p_key)
// STUB: LEGO1 0x1006feb0
MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y)
{
return 1;
return FALSE;
}
// STUB: LEGO1 0x10070370
MxU8 Infocenter::HandleNotification17(MxParam&)
// FUNCTION: LEGO1 0x10070370
MxU8 Infocenter::HandleClick(LegoControlManagerEvent& p_param)
{
if (p_param.GetUnknown0x28() == 1) {
m_infoManDialogueTimer = 0;
InfomainScript actionToPlay = c_noInfomain;
StopCurrentAction();
InfomainScript characterBitmap = c_noInfomain;
GameState();
switch (p_param.GetClickedObjectId()) {
case c_leftArrowCtl:
m_infocenterState->SetUnknown0x74(14);
StopCurrentAction();
if (GameState()->GetUnknown10() == 0) {
m_radio.Stop();
TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE);
m_transitionDestination = 5;
}
else {
MxU32 objectId = m_infocenterState->GetUnknown0x68().FUN_10014d00();
PlayAction((InfomainScript) objectId);
}
break;
case c_rightArrowCtl:
m_infocenterState->SetUnknown0x74(14);
StopCurrentAction();
if (GameState()->GetUnknown10() == 0) {
m_radio.Stop();
TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE);
m_transitionDestination = 13;
}
else {
MxU32 objectId = m_infocenterState->GetUnknown0x68().FUN_10014d00();
PlayAction((InfomainScript) objectId);
}
break;
case c_infoCtl:
m_radio.Stop();
break;
case c_doorCtl:
if (m_infocenterState->GetUnknown0x74() != 8) {
actionToPlay = c_exitConfirmationDialogue;
m_radio.Stop();
m_infocenterState->SetUnknown0x74(8);
}
break;
case c_boatCtl:
actionToPlay = c_boatCtlDescription;
m_radio.Stop();
break;
case c_raceCtl:
actionToPlay = c_raceCtlDescription;
m_radio.Stop();
break;
case c_pizzaCtl:
actionToPlay = c_pizzaCtlDescription;
m_radio.Stop();
break;
case c_gasCtl:
actionToPlay = c_gasCtlDescription;
m_radio.Stop();
break;
case c_medCtl:
actionToPlay = c_medCtlDescription;
m_radio.Stop();
break;
case c_copCtlDescription:
actionToPlay = c_copCtlDescription;
m_radio.Stop();
break;
case c_bigInfoCtl:
// TODO
break;
case c_bookCtl:
m_transitionDestination = 12;
m_infocenterState->SetUnknown0x74(4);
actionToPlay = GameState()->GetUnknown10() ? c_goToRegBookRed : c_goToRegBook;
m_radio.Stop();
GameState()->SetCurrentArea(GameState()->GetPreviousArea());
InputManager()->DisableInputProcessing();
break;
case c_mamaCtl:
characterBitmap = c_mamaSelected;
UpdateFrameHot(FALSE);
break;
case c_papaCtl:
characterBitmap = c_papaSelected;
UpdateFrameHot(FALSE);
break;
case c_pepperCtl:
characterBitmap = c_pepperSelected;
UpdateFrameHot(FALSE);
break;
case c_nickCtl:
characterBitmap = c_nickSelected;
UpdateFrameHot(FALSE);
break;
case c_lauraCtl:
characterBitmap = c_lauraCtl;
UpdateFrameHot(FALSE);
break;
}
if (actionToPlay != c_noInfomain) {
PlayAction(actionToPlay);
}
if (characterBitmap != c_noInfomain) {
m_unk0x11c = (MxStillPresenter*) Find(m_atom, characterBitmap);
}
}
return 1;
}
@@ -601,9 +737,81 @@ MxBool Infocenter::VTable0x5c()
return TRUE;
}
// STUB: LEGO1 0x10070dc0
void Infocenter::FUN_10070dc0(MxBool)
// FUNCTION: LEGO1 0x10070d10
void Infocenter::FUN_10070d10(MxS32 p_x, MxS32 p_y)
{
MxS16 i;
for (i = 0; i < (MxS32) (sizeof(m_mapAreas) / sizeof(m_mapAreas[0])); i++) {
MxS32 right = m_mapAreas[i].m_area.GetRight();
MxS32 bottom = m_mapAreas[i].m_area.GetBottom();
MxS32 left = m_mapAreas[i].m_area.GetLeft();
MxS32 top = m_mapAreas[i].m_area.GetTop();
if (left <= p_x && p_x <= right && top <= p_y && p_y <= bottom)
break;
}
if (i == 7) {
i = -1;
}
if (i != m_unk0x1c8) {
if (m_unk0x1c8 != -1) {
m_mapAreas[i].m_presenter->Enable(FALSE);
}
m_unk0x1c8 = i;
if (i != -1) {
m_mapAreas[i].m_presenter->Enable(TRUE);
}
}
}
// FUNCTION: LEGO1 0x10070dc0
void Infocenter::UpdateFrameHot(MxBool p_display)
{
if (p_display) {
MxS32 x, y;
switch (GameState()->GetUnknownC()) {
case 1:
x = 302;
y = 81;
break;
case 2:
x = 204;
y = 81;
break;
case 3:
x = 253;
y = 81;
break;
case 4:
x = 353;
y = 81;
break;
case 5:
x = 399;
y = 81;
break;
default:
return;
}
MxS32 originalDisplayZ = m_frameHotBitmap->GetDisplayZ();
m_frameHotBitmap->SetDisplayZ(1000);
VideoManager()->SortPresenterList();
m_frameHotBitmap->Enable(TRUE);
m_frameHotBitmap->VTable0x88(x, y);
m_frameHotBitmap->SetDisplayZ(originalDisplayZ);
}
else {
if (m_frameHotBitmap) {
m_frameHotBitmap->Enable(FALSE);
}
}
}
// STUB: LEGO1 0x10070e90
@@ -611,9 +819,33 @@ void Infocenter::FUN_10070e90()
{
}
// STUB: LEGO1 0x10070f60
// FUNCTION: LEGO1 0x10070f60
MxBool Infocenter::VTable0x64()
{
if (m_infocenterState != NULL) {
MxU32 val = m_infocenterState->GetUnknown0x74();
if (val == 0) {
StopCutscene();
m_infocenterState->SetUnknown0x74(1);
}
else if (val == 13) {
StopCredits();
}
else if (val != 8) {
m_infocenterState->SetUnknown0x74(8);
#ifdef COMPAT_MODE
{
MxNotificationParam param(c_notificationType0, NULL);
Notify(param);
}
#else
Notify(MxNotificationParam(c_notificationType0, NULL));
#endif
}
}
return FALSE;
}

View File

@@ -1,11 +1,15 @@
#include "infocenterdoor.h"
#include "infocenterstate.h"
#include "jukebox.h"
#include "legocontrolmanager.h"
#include "legogamestate.h"
#include "legoinputmanager.h"
#include "legoomni.h"
#include "mxactionnotificationparam.h"
#include "mxbackgroundaudiomanager.h"
#include "mxnotificationmanager.h"
#include "mxtransitionmanager.h"
DECOMP_SIZE_ASSERT(InfocenterDoor, 0xfc)
@@ -45,11 +49,31 @@ MxResult InfocenterDoor::Create(MxDSAction& p_dsAction)
return result;
}
// STUB: LEGO1 0x100379e0
// FUNCTION: LEGO1 0x100379e0
MxLong InfocenterDoor::Notify(MxParam& p_param)
{
// TODO
return LegoWorld::Notify(p_param);
MxLong result = 0;
LegoWorld::Notify(p_param);
if (m_worldStarted) {
switch (((MxNotificationParam&) p_param).GetType()) {
case c_notificationEndAction:
if (((MxEndActionNotificationParam&) p_param).GetAction()->GetAtomId() == m_atom) {
BackgroundAudioManager()->RaiseVolume();
result = 1;
}
break;
case c_notificationClick:
result = HandleClick((LegoControlManagerEvent&) p_param);
break;
case c_notificationTransitioned:
GameState()->SwitchArea(m_unk0xf8);
result = 1;
break;
}
}
return result;
}
// FUNCTION: LEGO1 0x10037a70
@@ -60,6 +84,61 @@ void InfocenterDoor::ReadyWorld()
FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen);
}
// FUNCTION: LEGO1 0x10037a90
MxLong InfocenterDoor::HandleClick(LegoControlManagerEvent& p_param)
{
MxLong result = 0;
if (p_param.GetUnknown0x28() == 1) {
DeleteObjects(&m_atom, 500, 510);
switch (p_param.GetClickedObjectId()) {
case 1:
m_unk0xf8 = 13;
TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE);
result = 1;
break;
case 2:
m_unk0xf8 = 5;
TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE);
result = 1;
break;
case 3:
m_unk0xf8 = 2;
TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE);
result = 1;
break;
case 4:
if (GameState()->GetUnknownC()) {
InfocenterState* state = (InfocenterState*) GameState()->GetState("InfocenterState");
if (state->GetInfocenterBufferElement(0) != NULL) {
m_unk0xf8 = 4;
}
else {
MxDSAction action;
action.SetObjectId(503);
action.SetAtomId(*g_infodoorScript);
BackgroundAudioManager()->LowerVolume();
Start(&action);
}
}
else {
MxDSAction action;
action.SetObjectId(500);
action.SetAtomId(*g_infodoorScript);
BackgroundAudioManager()->LowerVolume();
Start(&action);
}
TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE);
result = 1;
break;
}
}
return result;
}
// FUNCTION: LEGO1 0x10037c80
void InfocenterDoor::VTable0x68(MxBool p_add)
{

View File

@@ -91,7 +91,7 @@ MxLong Score::Notify(MxParam& p_param)
DeleteScript(); // Shutting down
ret = 1;
break;
case c_notificationType17:
case c_notificationClick:
ret = FUN_100016d0((LegoControlManagerEvent&) p_param);
break;
case c_notificationTransitioned: