Merge branch 'isledecomp:master' into master

This commit is contained in:
MasterTimeThief 2025-06-19 23:23:28 -04:00 committed by GitHub
commit 1efd880871
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
48 changed files with 607 additions and 723 deletions

View File

@ -15,8 +15,6 @@ To access the Ghidra repository, use the following details:
- Address: `server.mattkc.com`
- Port: `13100`
**Please note that at the time of writing, much of the information found on the Ghidra server is severely outdated**. Generally, the source code found in this repository represents the latest "source of truth" and should be referenced whenever possible.
## General Guidelines
If you feel fit to contribute, feel free to create a pull request! Someone will review and merge it (or provide feedback) as soon as possible.

View File

@ -14,6 +14,19 @@ class MxStillPresenter;
// SIZE 0x24
class GasStationState : public LegoState {
public:
enum {
e_unknown0 = 0,
e_newState = 1,
e_beforeExitingForQuest = 2,
e_unknown3 = 3,
e_unknown4 = 4,
e_introduction = 5,
e_explainQuest = 6,
e_waitAcceptingQuest = 7,
e_afterAcceptingQuest = 8,
e_cancelQuest = 9,
};
GasStationState();
// FUNCTION: LEGO1 0x100061d0
@ -42,7 +55,7 @@ class GasStationState : public LegoState {
// TODO: Most likely getters/setters are not used according to BETA.
GarageScript::Script m_actions[3]; // 0x08
undefined4 m_unk0x14; // 0x14
MxS32 m_state; // 0x14
MxS16 m_pepperAction; // 0x18
MxS16 m_mamaAction; // 0x1a
MxS16 m_papaAction; // 0x1c
@ -88,6 +101,13 @@ class GasStation : public LegoWorld {
// GasStation::`scalar deleting destructor'
private:
enum {
e_finished = 0,
e_start = 1,
e_started = 2,
e_canceled = 3,
};
inline void PlayAction(GarageScript::Script p_objectId);
inline void StopAction(GarageScript::Script p_objectId);
@ -99,13 +119,13 @@ class GasStation : public LegoWorld {
undefined2 m_unk0xfa; // 0xfa
LegoGameState::Area m_destLocation; // 0xfc
GasStationState* m_state; // 0x100
undefined2 m_unk0x104; // 0x104
undefined2 m_unk0x106; // 0x106
MxS16 m_waitingState; // 0x104
MxS16 m_setWithCurrentAction; // 0x106
MxStillPresenter* m_trackLedBitmap; // 0x108
MxLong m_unk0x10c; // 0x10c
MxLong m_lastIdleAnimation; // 0x10c
MxLong m_trackLedTimer; // 0x110
MxBool m_unk0x114; // 0x114
MxBool m_unk0x115; // 0x115
MxBool m_waiting; // 0x114
MxBool m_flashingLeds; // 0x115
Radio m_radio; // 0x118
};

View File

@ -26,10 +26,10 @@ struct LegoBuildingInfo {
MxU32 m_sound; // 0x08
MxU32 m_move; // 0x0c
MxU8 m_mood; // 0x10
MxS8 m_unk0x11; // 0x11
MxS8 m_initialUnk0x11; // 0x12 - initial value loaded to m_unk0x11
MxS8 m_counter; // 0x11
MxS8 m_initialCounter; // 0x12 - initial value loaded to m_counter
MxU8 m_flags; // 0x13
float m_unk0x14; // 0x14
float m_adjustedY; // 0x14
const char* m_boundaryName; // 0x18
float m_x; // 0x1c
float m_y; // 0x20
@ -46,7 +46,7 @@ class LegoBuildingManager : public MxCore {
LegoEntity* m_entity; // 0x00
LegoROI* m_roi; // 0x04
MxLong m_time; // 0x08
float m_unk0x0c; // 0x0c
float m_y; // 0x0c
MxBool m_muted; // 0x10
};
@ -79,16 +79,16 @@ class LegoBuildingManager : public MxCore {
MxBool SwitchMood(LegoEntity* p_entity);
MxU32 GetAnimationId(LegoEntity* p_entity);
MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_state);
MxBool FUN_10030000(LegoEntity* p_entity);
MxBool FUN_10030030(MxS32 p_index);
MxBool FUN_10030110(LegoBuildingInfo* p_data);
void ScheduleAnimation(LegoEntity* p_entity, MxLong p_length, MxBool p_haveSound, MxBool p_unk0x28);
void FUN_10030590();
MxBool DecrementCounter(LegoEntity* p_entity);
MxBool DecrementCounter(MxS32 p_index);
MxBool DecrementCounter(LegoBuildingInfo* p_data);
void ScheduleAnimation(LegoEntity* p_entity, MxLong p_length, MxBool p_haveSound, MxBool p_hideAfterAnimation);
void ClearCounters();
void AdjustHeight(MxS32 p_index);
MxResult FUN_10030630();
MxResult DetermineBoundaries();
LegoBuildingInfo* GetInfoArray(MxS32& p_length);
void FUN_100307b0(LegoEntity* p_entity, MxS32 p_adjust);
void FUN_10030800();
void AdjustCounter(LegoEntity* p_entity, MxS32 p_adjust);
void SetInitialCounters();
static const char* GetCustomizeAnimFile() { return g_customizeAnimFile; }
@ -100,13 +100,13 @@ class LegoBuildingManager : public MxCore {
static MxS32 g_maxMove[16];
static MxU32 g_maxSound;
MxU8 m_nextVariant; // 0x08
MxBool m_unk0x09; // 0x09
AnimEntry* m_entries[5]; // 0x0c
MxS8 m_numEntries; // 0x20
LegoCacheSound* m_sound; // 0x24
MxBool m_unk0x28; // 0x28
LegoWorld* m_world; // 0x2c
MxU8 m_nextVariant; // 0x08
MxBool m_boundariesDetermined; // 0x09
AnimEntry* m_entries[5]; // 0x0c
MxS8 m_numEntries; // 0x20
LegoCacheSound* m_sound; // 0x24
MxBool m_hideAfterAnimation; // 0x28
LegoWorld* m_world; // 0x2c
};
#endif // LEGOBUILDINGMANAGER_H

View File

@ -67,7 +67,7 @@ class LegoGameState {
e_isle,
e_infomain,
e_infodoor,
e_unk4,
e_infocenterExited,
e_elevbott,
e_elevride,
e_elevride2,
@ -80,10 +80,10 @@ class LegoGameState {
e_jetrace,
e_jetrace2,
e_jetraceExterior,
e_unk17,
e_jetskibuildExited,
e_carrace,
e_carraceExterior,
e_unk20,
e_racecarbuildExited,
e_unk21,
e_pizzeriaExterior,
e_unk23,
@ -91,12 +91,12 @@ class LegoGameState {
e_garageExterior,
e_garage,
e_garadoor,
e_unk28,
e_garageExited,
e_hospitalExterior,
e_hospital,
e_unk31,
e_hospitalExited,
e_policeExterior,
e_unk33,
e_policeExited,
e_police,
e_polidoor,
e_copterbuild,
@ -129,7 +129,7 @@ class LegoGameState {
e_towtrack,
e_jetski,
e_unk66 = 66
e_vehicleExited = 66
};
// SIZE 0x0e

View File

@ -52,11 +52,11 @@ class LegoPlantManager : public MxCore {
MxU32 GetSoundId(LegoEntity* p_entity, MxBool p_state);
LegoPlantInfo* GetInfoArray(MxS32& p_length);
LegoEntity* CreatePlant(MxS32 p_index, LegoWorld* p_world, LegoOmni::World p_worldId);
MxBool FUN_10026c50(LegoEntity* p_entity);
MxBool DecrementCounter(LegoEntity* p_entity);
void ScheduleAnimation(LegoEntity* p_entity, MxLong p_length);
MxResult FUN_10026410();
void FUN_10027120();
void FUN_10027200();
void ClearCounters();
void SetInitialCounters();
static void SetCustomizeAnimFile(const char* p_value);
@ -68,10 +68,10 @@ class LegoPlantManager : public MxCore {
private:
void RemovePlant(MxS32 p_index, LegoOmni::World p_worldId);
void FUN_10026860(MxS32 p_index);
void AdjustHeight(MxS32 p_index);
LegoPlantInfo* GetInfo(LegoEntity* p_entity);
MxBool FUN_10026c80(MxS32 p_index);
void FUN_100271b0(LegoEntity* p_entity, MxS32 p_adjust);
MxBool DecrementCounter(MxS32 p_index);
void AdjustCounter(LegoEntity* p_entity, MxS32 p_adjust);
static char* g_customizeAnimFile;
static MxS32 g_maxMove[4];

View File

@ -41,8 +41,8 @@ struct LegoPlantInfo {
MxU32 m_move; // 0x10
MxU8 m_mood; // 0x14
MxU8 m_color; // 0x15 - see enum for possible values
MxS8 m_unk0x16; // 0x16
MxS8 m_initialUnk0x16; // 0x17 - initial value loaded to m_unk0x16
MxS8 m_counter; // 0x16
MxS8 m_initialCounter; // 0x17 - initial value loaded to m_counter
const char* m_name; // 0x18
undefined4 m_unk0x1c; // 0x1c
float m_x; // 0x20

View File

@ -125,10 +125,10 @@ class PizzaMissionState : public LegoState {
MxResult Serialize(LegoStorage* p_storage) override; // vtable+0x1c
// FUNCTION: BETA10 0x100ef470
void SetUnknown0xb0(MxU32 p_unk0xb0) { m_unk0xb0 = p_unk0xb0; }
void SetPlayedAction(MxU32 p_playedAction) { m_playedAction = p_playedAction; }
// FUNCTION: BETA10 0x100ef850
MxU32 GetUnknown0xb0() { return m_unk0xb0; }
MxU32 GetPlayedAction() { return m_playedAction; }
// FUNCTION: BETA10 0x10088850
MxS16 GetHighScore(MxU8 p_actorId) { return GetMission(p_actorId)->m_hiScore; }
@ -137,12 +137,12 @@ class PizzaMissionState : public LegoState {
// PizzaMissionState::`scalar deleting destructor'
Mission* GetMission(MxU8 p_actorId);
MxS16 FUN_10039540();
MxS16 GetActorState();
PizzeriaState* m_pizzeriaState; // 0x08
undefined4 m_unk0x0c; // 0x0c
Mission m_missions[5]; // 0x10
MxU32 m_unk0xb0; // 0xb0
MxU32 m_playedAction; // 0xb0
static IsleScript::Script g_pepperActions[];
static IsleScript::Script g_mamaActions[];
@ -202,9 +202,9 @@ class Pizza : public IsleActor {
PizzaMissionState::Mission* m_mission; // 0x80
SkateBoard* m_skateBoard; // 0x84
Act1State* m_act1state; // 0x88
IsleScript::Script m_unk0x8c; // 0x8c
MxLong m_unk0x90; // 0x90
MxLong m_unk0x94; // 0x94
IsleScript::Script m_speechAction; // 0x8c
MxLong m_startTime; // 0x90
MxLong m_duration; // 0x94
MxBool m_unk0x98; // 0x98
};

View File

@ -34,11 +34,11 @@ class PizzeriaState : public LegoState {
// SYNTHETIC: LEGO1 0x10017ce0
// PizzeriaState::`scalar deleting destructor'
MxS16 FUN_10017d50();
MxS16 GetActorState();
MxU32 NextAction();
Playlist m_unk0x08[5]; // 0x08
MxS32 m_unk0x44[5]; // 0x44
Playlist m_playerPlaylists[5]; // 0x08
MxS32 m_states[5]; // 0x44
static IsleScript::Script g_pepperActions[];
static IsleScript::Script g_mamaActions[];

View File

@ -39,14 +39,14 @@ class RadioState : public LegoState {
void SetActive(MxBool p_active) { m_active = p_active; }
undefined4 FUN_1002d090();
MxBool FUN_1002d0c0(const MxAtomId& p_atom, MxU32 p_objectId);
MxU32 NextPlaylistObjectId();
MxBool IsRadioObjectId(const MxAtomId& p_atom, MxU32 p_objectId);
// TODO: Most likely getters/setters are not used according to BETA.
Playlist m_unk0x08[3]; // 0x08
MxS16 m_unk0x2c; // 0x2c
MxBool m_active; // 0x2e
Playlist m_playlists[3]; // 0x08
MxS16 m_activePlaylist; // 0x2c
MxBool m_active; // 0x2e
};
// VTABLE: LEGO1 0x100d6d10
@ -85,7 +85,7 @@ class Radio : public MxCore {
private:
RadioState* m_state; // 0x08
MxBool m_unk0x0c; // 0x0c
MxBool m_enabled; // 0x0c
MxBool m_audioEnabled; // 0x0d
MxLong HandleEndAction(MxEndActionNotificationParam& p_param);

View File

@ -718,17 +718,17 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
switch (m_unk0x1d) {
case 0:
if (buildingInfo[12].m_unk0x11) {
if (buildingInfo[12].m_counter) {
result = buildingInfo[12].m_entity;
*p_param = TRUE;
}
else if (buildingInfo[14].m_unk0x11) {
else if (buildingInfo[14].m_counter) {
result = buildingInfo[14].m_entity;
*p_param = TRUE;
}
else {
for (i = 0; g_unk0x100f0f30[i] != -1; i++) {
if (plantInfo[g_unk0x100f0f30[i]].m_unk0x16) {
if (plantInfo[g_unk0x100f0f30[i]].m_counter) {
result = plantInfo[g_unk0x100f0f30[i]].m_entity;
break;
}
@ -736,13 +736,13 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
}
break;
case 1:
if (buildingInfo[13].m_unk0x11) {
if (buildingInfo[13].m_counter) {
result = buildingInfo[13].m_entity;
*p_param = TRUE;
}
else {
for (i = 0; g_unk0x100f0f50[i] != -1; i++) {
if (plantInfo[g_unk0x100f0f50[i]].m_unk0x16) {
if (plantInfo[g_unk0x100f0f50[i]].m_counter) {
result = plantInfo[g_unk0x100f0f50[i]].m_entity;
break;
}
@ -750,17 +750,17 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
}
break;
case 2:
if (buildingInfo[9].m_unk0x11) {
if (buildingInfo[9].m_counter) {
result = buildingInfo[9].m_entity;
*p_param = TRUE;
}
else if (buildingInfo[11].m_unk0x11) {
else if (buildingInfo[11].m_counter) {
result = buildingInfo[11].m_entity;
*p_param = TRUE;
}
else {
for (i = 0; g_unk0x100f0f90[i] != -1; i++) {
if (plantInfo[g_unk0x100f0f90[i]].m_unk0x16) {
if (plantInfo[g_unk0x100f0f90[i]].m_counter) {
result = plantInfo[g_unk0x100f0f90[i]].m_entity;
break;
}
@ -768,21 +768,21 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
}
break;
case 3:
if (buildingInfo[7].m_unk0x11) {
if (buildingInfo[7].m_counter) {
result = buildingInfo[7].m_entity;
*p_param = TRUE;
}
else if (buildingInfo[8].m_unk0x11) {
else if (buildingInfo[8].m_counter) {
result = buildingInfo[8].m_entity;
*p_param = TRUE;
}
else if (buildingInfo[3].m_unk0x11) {
else if (buildingInfo[3].m_counter) {
result = buildingInfo[3].m_entity;
*p_param = TRUE;
}
else {
for (i = 0; g_unk0x100f0fa8[i] != -1; i++) {
if (plantInfo[g_unk0x100f0fa8[i]].m_unk0x16) {
if (plantInfo[g_unk0x100f0fa8[i]].m_counter) {
result = plantInfo[g_unk0x100f0fa8[i]].m_entity;
break;
}
@ -790,17 +790,17 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
}
break;
case 4:
if (buildingInfo[5].m_unk0x11) {
if (buildingInfo[5].m_counter) {
result = buildingInfo[5].m_entity;
*p_param = TRUE;
}
else if (buildingInfo[10].m_unk0x11) {
else if (buildingInfo[10].m_counter) {
result = buildingInfo[10].m_entity;
*p_param = TRUE;
}
else {
for (i = 0; g_unk0x100f0fb8[i] != -1; i++) {
if (plantInfo[g_unk0x100f0fb8[i]].m_unk0x16) {
if (plantInfo[g_unk0x100f0fb8[i]].m_counter) {
result = plantInfo[g_unk0x100f0fb8[i]].m_entity;
break;
}
@ -808,13 +808,13 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
}
break;
case 5:
if (buildingInfo[4].m_unk0x11) {
if (buildingInfo[4].m_counter) {
result = buildingInfo[4].m_entity;
*p_param = TRUE;
}
else {
for (i = 0; g_unk0x100f0fe8[i] != -1; i++) {
if (plantInfo[g_unk0x100f0fe8[i]].m_unk0x16) {
if (plantInfo[g_unk0x100f0fe8[i]].m_counter) {
result = plantInfo[g_unk0x100f0fe8[i]].m_entity;
break;
}
@ -822,13 +822,13 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
}
break;
case 6:
if (buildingInfo[2].m_unk0x11) {
if (buildingInfo[2].m_counter) {
result = buildingInfo[2].m_entity;
*p_param = TRUE;
}
else {
for (i = 0; g_unk0x100f1000[i] != -1; i++) {
if (plantInfo[g_unk0x100f1000[i]].m_unk0x16) {
if (plantInfo[g_unk0x100f1000[i]].m_counter) {
result = plantInfo[g_unk0x100f1000[i]].m_entity;
break;
}
@ -836,13 +836,13 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
}
break;
case 7:
if (buildingInfo[6].m_unk0x11) {
if (buildingInfo[6].m_counter) {
result = buildingInfo[6].m_entity;
*p_param = TRUE;
}
else {
for (i = 0; g_unk0x100f1018[i] != -1; i++) {
if (plantInfo[g_unk0x100f1018[i]].m_unk0x16) {
if (plantInfo[g_unk0x100f1018[i]].m_counter) {
result = plantInfo[g_unk0x100f1018[i]].m_entity;
break;
}
@ -851,7 +851,7 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
break;
case 8:
for (i = 0; g_unk0x100f1030[i] != -1; i++) {
if (plantInfo[g_unk0x100f1030[i]].m_unk0x16) {
if (plantInfo[g_unk0x100f1030[i]].m_counter) {
result = plantInfo[g_unk0x100f1030[i]].m_entity;
break;
}
@ -861,7 +861,7 @@ LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param)
return result;
}
if (buildingInfo[15].m_unk0x11) {
if (buildingInfo[15].m_counter) {
result = buildingInfo[15].m_entity;
*p_param = TRUE;
}

View File

@ -607,8 +607,8 @@ void Act3Brickster::Animate(float p_time)
assert(m_shootAnim && m_pInfo);
if (m_unk0x50 < p_time) {
while (m_pInfo->m_unk0x16) {
PlantManager()->FUN_10026c50(m_pInfo->m_entity);
while (m_pInfo->m_counter) {
PlantManager()->DecrementCounter(m_pInfo->m_entity);
}
assert(SoundManager()->GetCacheSoundManager());
@ -653,8 +653,8 @@ void Act3Brickster::Animate(float p_time)
assert(SoundManager()->GetCacheSoundManager());
SoundManager()->GetCacheSoundManager()->Play("thpt", NULL, FALSE);
while (m_bInfo->m_unk0x11 > 0 || m_bInfo->m_unk0x11 == -1) {
if (!BuildingManager()->FUN_10030110(m_bInfo)) {
while (m_bInfo->m_counter > 0 || m_bInfo->m_counter == -1) {
if (!BuildingManager()->DecrementCounter(m_bInfo)) {
break;
}
}
@ -865,7 +865,7 @@ MxResult Act3Brickster::FUN_100417c0()
float local124;
for (MxS32 i = 0; i < length; i++) {
if (bInfo[i].m_unk0x11 < 0 && bInfo[i].m_boundary != NULL && bInfo[i].m_entity != NULL && i != 0 &&
if (bInfo[i].m_counter < 0 && bInfo[i].m_boundary != NULL && bInfo[i].m_entity != NULL && i != 0 &&
(local120 == -1 || i != 15)) {
Mx3DPointFloat local188(bInfo[i].m_x, bInfo[i].m_y, bInfo[i].m_z);

View File

@ -70,7 +70,9 @@ MxResult Act3Ammo::Remove()
// FUNCTION: BETA10 0x1001d8b3
MxResult Act3Ammo::Create(Act3* p_world, MxU32 p_isPizza, MxS32 p_index)
{
#ifdef BETA10
assert(m_ammoFlag);
#endif
char name[12];
if (p_isPizza) {

View File

@ -221,7 +221,7 @@ MxLong Ambulance::HandleEndAction(MxEndActionNotificationParam& p_param)
else if (objectId == IsleScript::c_hps117bd_RunAnim) {
CurrentWorld()->PlaceActor(UserActor());
HandleClick();
SpawnPlayer(LegoGameState::e_unk33, TRUE, 0);
SpawnPlayer(LegoGameState::e_policeExited, TRUE, 0);
m_unk0x172 = 0;
TickleManager()->RegisterClient(this, 40000);
@ -388,7 +388,7 @@ MxLong Ambulance::HandleClick()
ControlManager()->Register(this);
if (m_state->m_unk0x08 == 1) {
SpawnPlayer(LegoGameState::e_unk31, TRUE, 0);
SpawnPlayer(LegoGameState::e_hospitalExited, TRUE, 0);
m_state->m_startTime = Timer()->GetTime();
InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_pns018rd_RunAnim, NULL);
}
@ -441,14 +441,14 @@ MxLong Ambulance::HandleControl(LegoControlManagerNotificationParam& p_param)
switch (p_param.m_clickedObjectId) {
case IsleScript::c_AmbulanceArms_Ctl:
Exit();
GameState()->m_currentArea = LegoGameState::e_unk66;
GameState()->m_currentArea = LegoGameState::e_vehicleExited;
result = 1;
break;
case IsleScript::c_AmbulanceInfo_Ctl:
((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::e_infomain);
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
Exit();
GameState()->m_currentArea = LegoGameState::e_unk66;
GameState()->m_currentArea = LegoGameState::e_vehicleExited;
result = 1;
break;
case IsleScript::c_AmbulanceHorn_Ctl:

View File

@ -85,7 +85,7 @@ MxLong Bike::HandleControl(LegoControlManagerNotificationParam& p_param)
switch (p_param.m_clickedObjectId) {
case IsleScript::c_BikeArms_Ctl:
Exit();
GameState()->m_currentArea = LegoGameState::e_unk66;
GameState()->m_currentArea = LegoGameState::e_vehicleExited;
result = 1;
break;
case IsleScript::c_BikeInfo_Ctl:

View File

@ -125,7 +125,7 @@ MxLong DuneBuggy::HandleControl(LegoControlManagerNotificationParam& p_param)
switch (p_param.m_clickedObjectId) {
case IsleScript::c_DuneCarArms_Ctl:
Exit();
GameState()->m_currentArea = LegoGameState::e_unk66;
GameState()->m_currentArea = LegoGameState::e_vehicleExited;
result = 1;
break;
case IsleScript::c_DuneCarInfo_Ctl:

View File

@ -203,7 +203,7 @@ MxLong Helicopter::HandleControl(LegoControlManagerNotificationParam& p_param)
}
Exit();
GameState()->m_currentArea = LegoGameState::e_unk66;
GameState()->m_currentArea = LegoGameState::e_vehicleExited;
result = 1;
break;
case IsleScript::c_Helicopter_TakeOff_Ctl: {

View File

@ -148,7 +148,7 @@ void IslePathActor::Exit()
}
m_previousActor->SetActorState(c_initial);
GameState()->m_currentArea = LegoGameState::Area::e_unk66;
GameState()->m_currentArea = LegoGameState::Area::e_vehicleExited;
}
FUN_1001b660();
@ -199,7 +199,7 @@ void IslePathActor::RegisterSpawnLocations()
JukeboxScript::c_Quiet_Audio
);
g_spawnLocations[3] = SpawnLocation(
LegoGameState::e_unk4,
LegoGameState::e_infocenterExited,
g_isleScript,
0,
"int46",
@ -223,7 +223,7 @@ void IslePathActor::RegisterSpawnLocations()
JukeboxScript::c_Beach_Music
);
g_spawnLocations[5] = SpawnLocation(
LegoGameState::e_unk17,
LegoGameState::e_jetskibuildExited,
g_isleScript,
0,
"EDG00_46",
@ -259,7 +259,7 @@ void IslePathActor::RegisterSpawnLocations()
JukeboxScript::c_CentralNorthRoad_Music
);
g_spawnLocations[8] = SpawnLocation(
LegoGameState::e_unk20,
LegoGameState::e_racecarbuildExited,
g_isleScript,
0,
"INT16",
@ -295,7 +295,7 @@ void IslePathActor::RegisterSpawnLocations()
JukeboxScript::c_GarageArea_Music
);
g_spawnLocations[11] = SpawnLocation(
LegoGameState::e_unk28,
LegoGameState::e_garageExited,
g_isleScript,
0,
"INT24",
@ -319,7 +319,7 @@ void IslePathActor::RegisterSpawnLocations()
JukeboxScript::c_Hospital_Music
);
g_spawnLocations[13] = SpawnLocation(
LegoGameState::e_unk31,
LegoGameState::e_hospitalExited,
g_isleScript,
0,
"EDG02_28",
@ -343,7 +343,7 @@ void IslePathActor::RegisterSpawnLocations()
JukeboxScript::c_PoliceStation_Music
);
g_spawnLocations[15] = SpawnLocation(
LegoGameState::e_unk33,
LegoGameState::e_policeExited,
g_isleScript,
0,
"EDG02_64",

View File

@ -143,7 +143,7 @@ MxLong Jetski::HandleControl(LegoControlManagerNotificationParam& p_param)
Exit();
((IslePathActor*) UserActor())
->SpawnPlayer(LegoGameState::e_jetraceExterior, TRUE, c_spawnBit1 | c_playMusic | c_spawnBit3);
GameState()->m_currentArea = LegoGameState::e_unk66;
GameState()->m_currentArea = LegoGameState::e_vehicleExited;
return 1;
case IsleScript::c_JetskiInfo_Ctl:
((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::e_infomain);

View File

@ -119,7 +119,7 @@ MxLong Motocycle::HandleControl(LegoControlManagerNotificationParam& p_param)
switch (p_param.m_clickedObjectId) {
case IsleScript::c_MotoBikeArms_Ctl:
Exit();
GameState()->m_currentArea = LegoGameState::e_unk66;
GameState()->m_currentArea = LegoGameState::e_vehicleExited;
result = 1;
break;
case IsleScript::c_MotoBikeInfo_Ctl:

View File

@ -136,9 +136,9 @@ Pizza::Pizza()
m_mission = NULL;
m_skateBoard = NULL;
m_act1state = NULL;
m_unk0x8c = IsleScript::c_noneIsle;
m_speechAction = IsleScript::c_noneIsle;
m_unk0x98 = FALSE;
m_unk0x90 = INT_MIN;
m_startTime = INT_MIN;
}
// FUNCTION: LEGO1 0x10038100
@ -188,7 +188,7 @@ void Pizza::FUN_10038220(IsleScript::Script p_objectId)
AnimationManager()->EnableCamAnims(FALSE);
AnimationManager()->FUN_1005f6d0(FALSE);
PlayAction(p_objectId, FALSE);
m_unk0x8c = IsleScript::c_noneIsle;
m_speechAction = IsleScript::c_noneIsle;
}
// FUNCTION: LEGO1 0x100382b0
@ -196,8 +196,8 @@ void Pizza::FUN_10038220(IsleScript::Script p_objectId)
void Pizza::FUN_100382b0()
{
if (m_state->m_unk0x0c != 8) {
if (m_unk0x8c != IsleScript::c_noneIsle) {
InvokeAction(Extra::e_stop, *g_isleScript, m_unk0x8c, NULL);
if (m_speechAction != IsleScript::c_noneIsle) {
InvokeAction(Extra::e_stop, *g_isleScript, m_speechAction, NULL);
}
m_act1state->m_unk0x018 = 0;
@ -209,10 +209,10 @@ void Pizza::FUN_100382b0()
m_mission->m_startTime = INT_MIN;
m_mission = NULL;
m_unk0x98 = FALSE;
m_unk0x8c = IsleScript::c_noneIsle;
m_speechAction = IsleScript::c_noneIsle;
BackgroundAudioManager()->RaiseVolume();
TickleManager()->UnregisterClient(this);
m_unk0x90 = INT_MIN;
m_startTime = INT_MIN;
m_skateBoard->EnableScenePresentation(FALSE);
m_skateBoard->SetPizzaVisible(FALSE);
MxTrace("Pizza mission: idle\n");
@ -254,7 +254,7 @@ MxLong Pizza::HandleClick()
IsleScript::Script action;
switch (m_state->FUN_10039540()) {
switch (m_state->GetActorState()) {
case 0:
action = m_mission->m_actions[m_mission->m_numActions + 3];
break;
@ -284,7 +284,7 @@ MxLong Pizza::HandlePathStruct(LegoPathStructNotificationParam& p_param)
if (p_param.GetTrigger() == LegoPathStruct::c_s && p_param.GetData() == 0x12e &&
GameState()->GetActorId() == LegoActor::c_pepper) {
m_state->m_unk0x0c = 5;
m_state->SetUnknown0xb0(SndanimScript::c_TRS302_OpenJailDoor);
m_state->SetPlayedAction(SndanimScript::c_TRS302_OpenJailDoor);
if (time < m_mission->GetRedFinishTime()) {
m_mission->UpdateScore(LegoState::e_red);
@ -325,26 +325,26 @@ MxLong Pizza::HandlePathStruct(LegoPathStructNotificationParam& p_param)
case IsleScript::c_pps025ni_RunAnim:
case IsleScript::c_pps026ni_RunAnim:
case IsleScript::c_pps027ni_RunAnim:
m_unk0x90 = Timer()->GetTime();
m_unk0x94 = 3800;
m_startTime = Timer()->GetTime();
m_duration = 3800;
break;
case IsleScript::c_pgs050nu_RunAnim:
case IsleScript::c_pgs051nu_RunAnim:
case IsleScript::c_pgs052nu_RunAnim:
m_unk0x90 = Timer()->GetTime();
m_unk0x94 = 6400;
m_startTime = Timer()->GetTime();
m_duration = 6400;
break;
case IsleScript::c_prt072sl_RunAnim:
case IsleScript::c_prt073sl_RunAnim:
case IsleScript::c_prt074sl_RunAnim:
m_unk0x90 = Timer()->GetTime();
m_unk0x94 = 7000;
m_startTime = Timer()->GetTime();
m_duration = 7000;
break;
case IsleScript::c_pho104re_RunAnim:
case IsleScript::c_pho105re_RunAnim:
case IsleScript::c_pho106re_RunAnim:
m_unk0x90 = Timer()->GetTime();
m_unk0x94 = 6500;
m_startTime = Timer()->GetTime();
m_duration = 6500;
break;
}
@ -376,8 +376,8 @@ MxResult Pizza::Tickle()
{
MxLong time = Timer()->GetTime();
if (m_unk0x90 != INT_MIN && m_unk0x94 + m_unk0x90 <= time) {
m_unk0x90 = INT_MIN;
if (m_startTime != INT_MIN && m_duration + m_startTime <= time) {
m_startTime = INT_MIN;
m_skateBoard->EnableScenePresentation(FALSE);
m_skateBoard->SetPizzaVisible(FALSE);
TickleManager()->UnregisterClient(this);
@ -395,29 +395,29 @@ MxResult Pizza::Tickle()
InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_Avo917In_PlayWav, NULL);
MxTrace("Pizza mission: timeout, stop\n");
}
else if (time >= m_mission->m_startTime + 35000 && m_unk0x8c == IsleScript::c_noneIsle) {
else if (time >= m_mission->m_startTime + 35000 && m_speechAction == IsleScript::c_noneIsle) {
switch (GameState()->GetActorId()) {
case LegoActor::c_pepper:
m_unk0x8c = IsleScript::c_Avo914In_PlayWav;
m_speechAction = IsleScript::c_Avo914In_PlayWav;
break;
case LegoActor::c_mama:
m_unk0x8c = IsleScript::c_Avo910In_PlayWav;
m_speechAction = IsleScript::c_Avo910In_PlayWav;
break;
case LegoActor::c_papa:
m_unk0x8c = IsleScript::c_Avo912In_PlayWav;
m_speechAction = IsleScript::c_Avo912In_PlayWav;
break;
case LegoActor::c_nick:
m_unk0x8c = IsleScript::c_Avo911In_PlayWav;
m_speechAction = IsleScript::c_Avo911In_PlayWav;
break;
case LegoActor::c_laura:
m_unk0x8c = IsleScript::c_Avo913In_PlayWav;
m_speechAction = IsleScript::c_Avo913In_PlayWav;
break;
}
BackgroundAudioManager()->LowerVolume();
if (m_unk0x8c != IsleScript::c_noneIsle) {
InvokeAction(Extra::e_start, *g_isleScript, m_unk0x8c, NULL);
if (m_speechAction != IsleScript::c_noneIsle) {
InvokeAction(Extra::e_start, *g_isleScript, m_speechAction, NULL);
}
}
}
@ -447,14 +447,14 @@ MxLong Pizza::HandleEndAction(MxEndActionNotificationParam& p_param)
MxLong result = 0;
MxU32 objectId = p_param.GetAction()->GetObjectId();
if (m_unk0x8c == objectId) {
if (m_speechAction == objectId) {
BackgroundAudioManager()->RaiseVolume();
return 1;
}
switch (m_state->m_unk0x0c) {
case 1:
if (m_state->GetUnknown0xb0() == objectId) {
if (m_state->GetPlayedAction() == objectId) {
m_state->m_unk0x0c = 2;
m_mission->m_startTime = Timer()->GetTime();
TickleManager()->RegisterClient(this, 200);
@ -462,7 +462,7 @@ MxLong Pizza::HandleEndAction(MxEndActionNotificationParam& p_param)
}
break;
case 3:
if (m_state->GetUnknown0xb0() == objectId) {
if (m_state->GetPlayedAction() == objectId) {
m_mission->m_startTime = Timer()->GetTime();
PizzaMissionState::Mission* mission = m_mission;
@ -471,7 +471,7 @@ MxLong Pizza::HandleEndAction(MxEndActionNotificationParam& p_param)
}
m_state->m_unk0x0c = 4;
m_state->SetUnknown0xb0(IsleScript::c_noneIsle);
m_state->SetPlayedAction(IsleScript::c_noneIsle);
UserActor()->SetActorState(LegoPathActor::c_initial);
m_skateBoard->SetPizzaVisible(TRUE);
m_world->PlaceActor(m_skateBoard, "int37", 2, 0.5, 3, 0.5);
@ -490,7 +490,7 @@ MxLong Pizza::HandleEndAction(MxEndActionNotificationParam& p_param)
}
break;
case 5:
if (m_state->GetUnknown0xb0() == objectId) {
if (m_state->GetPlayedAction() == objectId) {
StopActions();
if (GameState()->GetActorId() == LegoActor::c_pepper) {
@ -506,24 +506,24 @@ MxLong Pizza::HandleEndAction(MxEndActionNotificationParam& p_param)
break;
case 2:
action = IsleScript::c_pja129br_RunAnim;
m_unk0x90 = Timer()->GetTime();
m_unk0x94 = 500;
m_startTime = Timer()->GetTime();
m_duration = 500;
m_mission->m_unk0x14++;
m_state->m_unk0x0c = 6;
MxTrace("Pizza mission: succeeds\n");
break;
case 3:
action = IsleScript::c_pja131br_RunAnim;
m_unk0x90 = Timer()->GetTime();
m_unk0x94 = 500;
m_startTime = Timer()->GetTime();
m_duration = 500;
m_state->m_unk0x0c = 6;
break;
}
}
else {
action = IsleScript::c_pja132br_RunAnim;
m_unk0x90 = Timer()->GetTime();
m_unk0x94 = 2300;
m_startTime = Timer()->GetTime();
m_duration = 2300;
m_state->m_unk0x0c = 8;
InputManager()->DisableInputProcessing();
InputManager()->SetUnknown336(TRUE);
@ -535,16 +535,16 @@ MxLong Pizza::HandleEndAction(MxEndActionNotificationParam& p_param)
else {
FUN_100382b0();
m_state->m_unk0x0c = 0;
m_state->SetUnknown0xb0(IsleScript::c_noneIsle);
m_state->SetPlayedAction(IsleScript::c_noneIsle);
}
}
break;
case 6:
if (m_state->GetUnknown0xb0() == objectId) {
if (m_state->GetPlayedAction() == objectId) {
if (objectId == IsleScript::c_pja126br_RunAnim) {
PlayAction(IsleScript::c_pja127br_RunAnim, TRUE);
m_unk0x90 = Timer()->GetTime();
m_unk0x94 = 700;
m_startTime = Timer()->GetTime();
m_duration = 700;
}
else if (objectId == IsleScript::c_pja129br_RunAnim) {
PlayAction(IsleScript::c_pja130br_RunAnim, TRUE);
@ -552,12 +552,12 @@ MxLong Pizza::HandleEndAction(MxEndActionNotificationParam& p_param)
else {
FUN_100382b0();
m_state->m_unk0x0c = 0;
m_state->SetUnknown0xb0(IsleScript::c_noneIsle);
m_state->SetPlayedAction(IsleScript::c_noneIsle);
}
}
break;
case 8:
if (m_state->GetUnknown0xb0() == objectId) {
if (m_state->GetPlayedAction() == objectId) {
m_act1state->m_unk0x018 = 0;
m_state->m_unk0x0c = 0;
GameState()->m_currentArea = LegoGameState::e_isle;
@ -567,7 +567,7 @@ MxLong Pizza::HandleEndAction(MxEndActionNotificationParam& p_param)
}
break;
case 9:
if (m_state->GetUnknown0xb0() == objectId) {
if (m_state->GetPlayedAction() == objectId) {
FUN_100382b0();
}
break;
@ -580,10 +580,10 @@ MxLong Pizza::HandleEndAction(MxEndActionNotificationParam& p_param)
// FUNCTION: BETA10 0x100ef520
void Pizza::PlayAction(MxU32 p_objectId, MxBool p_param7)
{
m_state->SetUnknown0xb0(p_objectId);
m_state->SetPlayedAction(p_objectId);
if (m_unk0x8c != IsleScript::c_noneIsle) {
InvokeAction(Extra::e_stop, *g_isleScript, m_unk0x8c, NULL);
if (m_speechAction != IsleScript::c_noneIsle) {
InvokeAction(Extra::e_stop, *g_isleScript, m_speechAction, NULL);
}
AnimationManager()
@ -601,7 +601,7 @@ PizzaMissionState::PizzaMissionState()
m_missions[3] = Mission(LegoActor::c_nick, 2, g_nickFinishTimes, g_nickActions, 4);
m_missions[4] = Mission(LegoActor::c_laura, 2, g_lauraFinishTimes, g_lauraActions, 4);
m_pizzeriaState = (PizzeriaState*) GameState()->GetState("PizzeriaState");
m_unk0xb0 = IsleScript::c_noneIsle;
m_playedAction = IsleScript::c_noneIsle;
}
// FUNCTION: LEGO1 0x100393c0
@ -645,7 +645,7 @@ PizzaMissionState::Mission* PizzaMissionState::GetMission(MxU8 p_actorId)
}
// FUNCTION: LEGO1 0x10039540
MxS16 PizzaMissionState::FUN_10039540()
MxS16 PizzaMissionState::GetActorState()
{
return m_pizzeriaState->FUN_10017d50();
return m_pizzeriaState->GetActorState();
}

View File

@ -89,18 +89,18 @@ MxLong Pizzeria::HandleClick()
// FUNCTION: BETA10 0x100efd14
PizzeriaState::PizzeriaState()
{
m_unk0x08[0] = Playlist((MxU32*) g_pepperActions, sizeOfArray(g_pepperActions), Playlist::e_once);
m_unk0x08[1] = Playlist((MxU32*) g_mamaActions, sizeOfArray(g_mamaActions), Playlist::e_once);
m_unk0x08[2] = Playlist((MxU32*) g_papaActions, sizeOfArray(g_papaActions), Playlist::e_once);
m_unk0x08[3] = Playlist((MxU32*) g_nickActions, sizeOfArray(g_nickActions), Playlist::e_once);
m_unk0x08[4] = Playlist((MxU32*) g_lauraActions, sizeOfArray(g_lauraActions), Playlist::e_once);
memset(m_unk0x44, -1, sizeof(m_unk0x44));
m_playerPlaylists[0] = Playlist((MxU32*) g_pepperActions, sizeOfArray(g_pepperActions), Playlist::e_once);
m_playerPlaylists[1] = Playlist((MxU32*) g_mamaActions, sizeOfArray(g_mamaActions), Playlist::e_once);
m_playerPlaylists[2] = Playlist((MxU32*) g_papaActions, sizeOfArray(g_papaActions), Playlist::e_once);
m_playerPlaylists[3] = Playlist((MxU32*) g_nickActions, sizeOfArray(g_nickActions), Playlist::e_once);
m_playerPlaylists[4] = Playlist((MxU32*) g_lauraActions, sizeOfArray(g_lauraActions), Playlist::e_once);
memset(m_states, -1, sizeof(m_states));
}
// FUNCTION: LEGO1 0x10017d50
MxS16 PizzeriaState::FUN_10017d50()
MxS16 PizzeriaState::GetActorState()
{
return m_unk0x44[GameState()->GetActorId() - 1];
return m_states[GameState()->GetActorId() - 1];
}
// FUNCTION: LEGO1 0x10017d70
@ -109,11 +109,11 @@ MxU32 PizzeriaState::NextAction()
{
MxU8 actorId = GameState()->GetActorId();
if (m_unk0x44[actorId - 1] < 2) {
m_unk0x44[actorId - 1]++;
if (m_states[actorId - 1] < 2) {
m_states[actorId - 1]++;
}
return m_unk0x08[actorId - 1].Next();
return m_playerPlaylists[actorId - 1].Next();
}
// FUNCTION: LEGO1 0x10017da0
@ -124,12 +124,12 @@ MxResult PizzeriaState::Serialize(LegoStorage* p_storage)
if (p_storage->IsReadMode()) {
for (MxS16 i = 0; i < 5; i++) {
p_storage->ReadS16(m_unk0x08[i].m_nextIndex);
p_storage->ReadS16(m_playerPlaylists[i].m_nextIndex);
}
}
else {
for (MxS16 i = 0; i < 5; i++) {
p_storage->WriteS16(m_unk0x08[i].m_nextIndex);
p_storage->WriteS16(m_playerPlaylists[i].m_nextIndex);
}
}

View File

@ -18,7 +18,7 @@ DECOMP_SIZE_ASSERT(Radio, 0x10)
DECOMP_SIZE_ASSERT(RadioState, 0x30)
// GLOBAL: LEGO1 0x100f3218
JukeboxScript::Script g_unk0x100f3218[] = {
JukeboxScript::Script g_jingles[] = {
JukeboxScript::c_sns002ra_Audio,
JukeboxScript::c_sns001ja_Audio,
JukeboxScript::c_snsc01js_Audio,
@ -28,7 +28,7 @@ JukeboxScript::Script g_unk0x100f3218[] = {
};
// GLOBAL: LEGO1 0x100f3230
JukeboxScript::Script g_unk0x100f3230[] = {
JukeboxScript::Script g_news[] = {
JukeboxScript::c_ham035ra_Audio,
JukeboxScript::c_ham039ra_Audio,
JukeboxScript::c_sns005ra_Audio,
@ -46,7 +46,7 @@ JukeboxScript::Script g_unk0x100f3230[] = {
};
// GLOBAL: LEGO1 0x100f3268
JukeboxScript::Script g_unk0x100f3268[] = {
JukeboxScript::Script g_songs[] = {
JukeboxScript::c_CentralRoads_Music,
JukeboxScript::c_BeachBlvd_Music,
JukeboxScript::c_ResidentalArea_Music,
@ -64,7 +64,7 @@ Radio::Radio()
NotificationManager()->Register(this);
ControlManager()->Register(this);
m_unk0x0c = TRUE;
m_enabled = TRUE;
CreateState();
}
@ -86,7 +86,7 @@ MxLong Radio::Notify(MxParam& p_param)
{
MxLong result = 0;
if (m_unk0x0c) {
if (m_enabled) {
MxNotificationParam& param = (MxNotificationParam&) p_param;
switch (param.GetNotification()) {
case c_notificationEndAction:
@ -108,7 +108,7 @@ void Radio::Play()
CurrentWorld();
MxDSAction action;
action.SetObjectId(m_state->FUN_1002d090());
action.SetObjectId(m_state->NextPlaylistObjectId());
action.SetAtomId(*g_jukeboxScript);
action.SetLoopCount(1);
@ -174,11 +174,11 @@ MxLong Radio::HandleControl(LegoControlManagerNotificationParam& p_param)
MxLong Radio::HandleEndAction(MxEndActionNotificationParam& p_param)
{
if (m_state->IsActive() &&
m_state->FUN_1002d0c0(p_param.GetAction()->GetAtomId(), p_param.GetAction()->GetObjectId())) {
m_state->IsRadioObjectId(p_param.GetAction()->GetAtomId(), p_param.GetAction()->GetObjectId())) {
MxDSAction action;
action.SetAtomId(*g_jukeboxScript);
action.SetObjectId(m_state->FUN_1002d090());
action.SetObjectId(m_state->NextPlaylistObjectId());
action.SetLoopCount(1);
BackgroundAudioManager()->PlayMusic(action, 3, MxPresenter::e_repeating);
@ -191,8 +191,8 @@ MxLong Radio::HandleEndAction(MxEndActionNotificationParam& p_param)
// FUNCTION: LEGO1 0x1002cdc0
void Radio::Initialize(MxBool p_und)
{
if (m_unk0x0c != p_und) {
m_unk0x0c = p_und;
if (m_enabled != p_und) {
m_enabled = p_und;
CreateState();
}
}
@ -216,39 +216,39 @@ RadioState::RadioState()
srand(Timer()->GetTime());
MxS32 random = rand();
m_unk0x2c = random % 3;
m_activePlaylist = random % 3;
m_unk0x08[0] = Playlist((MxU32*) g_unk0x100f3218, sizeOfArray(g_unk0x100f3218), Playlist::e_loop);
m_unk0x08[0].m_nextIndex = (rand() % sizeOfArray(g_unk0x100f3218));
m_playlists[0] = Playlist((MxU32*) g_jingles, sizeOfArray(g_jingles), Playlist::e_loop);
m_playlists[0].m_nextIndex = (rand() % sizeOfArray(g_jingles));
m_unk0x08[1] = Playlist((MxU32*) g_unk0x100f3230, sizeOfArray(g_unk0x100f3230), Playlist::e_loop);
m_unk0x08[1].m_nextIndex = (rand() % sizeOfArray(g_unk0x100f3230));
m_playlists[1] = Playlist((MxU32*) g_news, sizeOfArray(g_news), Playlist::e_loop);
m_playlists[1].m_nextIndex = (rand() % sizeOfArray(g_news));
m_unk0x08[2] = Playlist((MxU32*) g_unk0x100f3268, sizeOfArray(g_unk0x100f3268), Playlist::e_loop);
m_unk0x08[2].m_nextIndex = (rand() % sizeOfArray(g_unk0x100f3268));
m_playlists[2] = Playlist((MxU32*) g_songs, sizeOfArray(g_songs), Playlist::e_loop);
m_playlists[2].m_nextIndex = (rand() % sizeOfArray(g_songs));
m_active = FALSE;
}
// FUNCTION: LEGO1 0x1002d090
MxU32 RadioState::FUN_1002d090()
MxU32 RadioState::NextPlaylistObjectId()
{
if (m_unk0x2c == 2) {
m_unk0x2c = 0;
if (m_activePlaylist == 2) {
m_activePlaylist = 0;
}
else {
m_unk0x2c++;
m_activePlaylist++;
}
return m_unk0x08[m_unk0x2c].Next();
return m_playlists[m_activePlaylist].Next();
}
// FUNCTION: LEGO1 0x1002d0c0
MxBool RadioState::FUN_1002d0c0(const MxAtomId& p_atom, MxU32 p_objectId)
MxBool RadioState::IsRadioObjectId(const MxAtomId& p_atom, MxU32 p_objectId)
{
if (*g_jukeboxScript == p_atom) {
for (MxS16 i = 0; i < 3; i++) {
if (m_unk0x08[i].Contains(p_objectId)) {
if (m_playlists[i].Contains(p_objectId)) {
return TRUE;
}
}

View File

@ -112,7 +112,7 @@ MxLong SkateBoard::HandleControl(LegoControlManagerNotificationParam& p_param)
if (p_param.m_unk0x28 == 1 && p_param.m_clickedObjectId == IsleScript::c_SkateArms_Ctl) {
Exit();
GameState()->m_currentArea = LegoGameState::Area::e_unk66;
GameState()->m_currentArea = LegoGameState::Area::e_vehicleExited;
result = 1;
}

View File

@ -435,7 +435,7 @@ MxLong TowTrack::HandleClick()
FindROI("rcred")->SetVisibility(FALSE);
}
else {
SpawnPlayer(LegoGameState::e_unk28, TRUE, 0);
SpawnPlayer(LegoGameState::e_garageExited, TRUE, 0);
m_lastAction = IsleScript::c_noneIsle;
m_lastAnimation = IsleScript::c_noneIsle;
m_state->m_startTime = Timer()->GetTime();
@ -486,14 +486,14 @@ MxLong TowTrack::HandleControl(LegoControlManagerNotificationParam& p_param)
switch (p_param.m_clickedObjectId) {
case IsleScript::c_TowTrackArms_Ctl:
Exit();
GameState()->m_currentArea = LegoGameState::e_unk66;
GameState()->m_currentArea = LegoGameState::e_vehicleExited;
result = 1;
break;
case IsleScript::c_TowInfo_Ctl:
((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::e_infomain);
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
Exit();
GameState()->m_currentArea = LegoGameState::e_unk66;
GameState()->m_currentArea = LegoGameState::e_vehicleExited;
result = 1;
break;
case IsleScript::c_TowHorn_Ctl:

View File

@ -784,11 +784,11 @@ void LegoCarBuild::FUN_100243a0()
TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE);
break;
case Jetski_Actor:
m_destLocation = LegoGameState::Area::e_unk17;
m_destLocation = LegoGameState::Area::e_jetskibuildExited;
TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE);
break;
case RaceCar_Actor:
m_destLocation = LegoGameState::Area::e_unk20;
m_destLocation = LegoGameState::Area::e_racecarbuildExited;
TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE);
}
}

View File

@ -253,10 +253,10 @@ void LegoBuildingManager::Init()
}
m_nextVariant = 0;
m_unk0x09 = FALSE;
m_boundariesDetermined = FALSE;
m_numEntries = 0;
m_sound = NULL;
m_unk0x28 = FALSE;
m_hideAfterAnimation = FALSE;
}
// FUNCTION: LEGO1 0x1002fa00
@ -274,7 +274,7 @@ void LegoBuildingManager::LoadWorldInfo()
LegoEntity* entity = (LegoEntity*) world->Find("MxEntity", g_buildingInfoVariants[0]);
if (entity) {
entity->GetROI()->SetVisibility(TRUE);
m_unk0x09 = FALSE;
m_boundariesDetermined = FALSE;
}
}
else {
@ -286,7 +286,7 @@ void LegoBuildingManager::LoadWorldInfo()
}
}
m_unk0x09 = FALSE;
m_boundariesDetermined = FALSE;
}
// FUNCTION: LEGO1 0x1002fa90
@ -301,7 +301,7 @@ void LegoBuildingManager::CreateBuilding(MxS32 p_index, LegoWorld* p_world)
LegoROI* roi = entity->GetROI();
AdjustHeight(p_index);
MxMatrix mat = roi->GetLocal2World();
mat[3][1] = g_buildingInfo[p_index].m_unk0x14;
mat[3][1] = g_buildingInfo[p_index].m_adjustedY;
roi->UpdateTransformationRelativeToParent(mat);
VideoManager()->Get3DManager()->Moved(*roi);
}
@ -316,7 +316,7 @@ void LegoBuildingManager::Reset()
g_buildingInfo[i].m_entity = NULL;
}
m_unk0x09 = FALSE;
m_boundariesDetermined = FALSE;
for (i = 0; i < m_numEntries; i++) {
delete m_entries[i];
@ -343,7 +343,7 @@ MxResult LegoBuildingManager::Write(LegoStorage* p_storage)
if (p_storage->Write(&info->m_mood, sizeof(MxU8)) != SUCCESS) {
goto done;
}
if (p_storage->Write(&info->m_initialUnk0x11, sizeof(MxS8)) != SUCCESS) {
if (p_storage->Write(&info->m_initialCounter, sizeof(MxS8)) != SUCCESS) {
goto done;
}
}
@ -376,11 +376,11 @@ MxResult LegoBuildingManager::Read(LegoStorage* p_storage)
if (p_storage->Read(&info->m_mood, sizeof(MxU8)) != SUCCESS) {
goto done;
}
if (p_storage->Read(&info->m_unk0x11, sizeof(MxS8)) != SUCCESS) {
if (p_storage->Read(&info->m_counter, sizeof(MxS8)) != SUCCESS) {
goto done;
}
info->m_initialUnk0x11 = info->m_unk0x11;
info->m_initialCounter = info->m_counter;
AdjustHeight(i);
}
@ -402,15 +402,15 @@ MxResult LegoBuildingManager::Read(LegoStorage* p_storage)
// FUNCTION: BETA10 0x10063f1a
void LegoBuildingManager::AdjustHeight(MxS32 p_index)
{
if (g_buildingInfo[p_index].m_unk0x11 > 0) {
float value = g_buildingInfoDownshift[p_index] - g_buildingInfo[p_index].m_unk0x11;
g_buildingInfo[p_index].m_unk0x14 =
g_buildingInfoInit[p_index].m_unk0x14 - value * g_buildingInfoDownshiftScale[p_index];
if (g_buildingInfo[p_index].m_counter > 0) {
float value = g_buildingInfoDownshift[p_index] - g_buildingInfo[p_index].m_counter;
g_buildingInfo[p_index].m_adjustedY =
g_buildingInfoInit[p_index].m_adjustedY - value * g_buildingInfoDownshiftScale[p_index];
}
else if (g_buildingInfo[p_index].m_unk0x11 == 0) {
float value = g_buildingInfoDownshift[p_index] - g_buildingInfo[p_index].m_unk0x11;
g_buildingInfo[p_index].m_unk0x14 =
g_buildingInfoInit[p_index].m_unk0x14 - value * g_buildingInfoDownshiftScale[p_index];
else if (g_buildingInfo[p_index].m_counter == 0) {
float value = g_buildingInfoDownshift[p_index] - g_buildingInfo[p_index].m_counter;
g_buildingInfo[p_index].m_adjustedY =
g_buildingInfoInit[p_index].m_adjustedY - value * g_buildingInfoDownshiftScale[p_index];
if (g_buildingInfo[p_index].m_entity != NULL) {
LegoROI* roi = g_buildingInfo[p_index].m_entity->GetROI();
@ -420,7 +420,7 @@ void LegoBuildingManager::AdjustHeight(MxS32 p_index)
}
}
else {
g_buildingInfo[p_index].m_unk0x14 = g_buildingInfoInit[p_index].m_unk0x14;
g_buildingInfo[p_index].m_adjustedY = g_buildingInfoInit[p_index].m_adjustedY;
}
}
@ -453,7 +453,7 @@ MxBool LegoBuildingManager::SwitchVariant(LegoEntity* p_entity)
LegoBuildingInfo* info = GetInfo(p_entity);
if (info != NULL && info->m_flags & LegoBuildingInfo::c_hasVariants && info->m_unk0x11 == -1) {
if (info != NULL && info->m_flags & LegoBuildingInfo::c_hasVariants && info->m_counter == -1) {
LegoROI* roi = p_entity->GetROI();
if (++m_nextVariant >= sizeOfArray(g_buildingInfoVariants)) {
m_nextVariant = 0;
@ -587,7 +587,7 @@ void LegoBuildingManager::SetCustomizeAnimFile(const char* p_value)
}
// FUNCTION: LEGO1 0x10030000
MxBool LegoBuildingManager::FUN_10030000(LegoEntity* p_entity)
MxBool LegoBuildingManager::DecrementCounter(LegoEntity* p_entity)
{
LegoBuildingInfo* info = GetInfo(p_entity);
@ -595,7 +595,7 @@ MxBool LegoBuildingManager::FUN_10030000(LegoEntity* p_entity)
return FALSE;
}
return FUN_10030030(info - g_buildingInfo);
return DecrementCounter(info - g_buildingInfo);
}
inline LegoBuildingInfo* GetBuildingInfo(MxS32 p_index)
@ -608,7 +608,7 @@ inline LegoBuildingInfo* GetBuildingInfo(MxS32 p_index)
}
// FUNCTION: LEGO1 0x10030030
MxBool LegoBuildingManager::FUN_10030030(MxS32 p_index)
MxBool LegoBuildingManager::DecrementCounter(MxS32 p_index)
{
if (p_index >= sizeOfArray(g_buildingInfo)) {
return FALSE;
@ -621,25 +621,25 @@ MxBool LegoBuildingManager::FUN_10030030(MxS32 p_index)
MxBool result = TRUE;
if (info->m_unk0x11 < 0) {
info->m_unk0x11 = g_buildingInfoDownshift[p_index];
if (info->m_counter < 0) {
info->m_counter = g_buildingInfoDownshift[p_index];
}
if (info->m_unk0x11 <= 0) {
if (info->m_counter <= 0) {
result = FALSE;
}
else {
LegoROI* roi = info->m_entity->GetROI();
info->m_unk0x11 -= 2;
if (info->m_unk0x11 == 1) {
info->m_unk0x11 = 0;
info->m_counter -= 2;
if (info->m_counter == 1) {
info->m_counter = 0;
roi->SetVisibility(FALSE);
}
else {
AdjustHeight(p_index);
MxMatrix mat = roi->GetLocal2World();
mat[3][1] = g_buildingInfo[p_index].m_unk0x14;
mat[3][1] = g_buildingInfo[p_index].m_adjustedY;
roi->UpdateTransformationRelativeToParent(mat);
VideoManager()->Get3DManager()->Moved(*roi);
}
@ -649,11 +649,11 @@ MxBool LegoBuildingManager::FUN_10030030(MxS32 p_index)
}
// FUNCTION: LEGO1 0x10030110
MxBool LegoBuildingManager::FUN_10030110(LegoBuildingInfo* p_data)
MxBool LegoBuildingManager::DecrementCounter(LegoBuildingInfo* p_data)
{
for (MxS32 i = 0; i < sizeOfArray(g_buildingInfo); i++) {
if (&g_buildingInfo[i] == p_data) {
return FUN_10030030(i);
return DecrementCounter(i);
}
}
@ -661,7 +661,12 @@ MxBool LegoBuildingManager::FUN_10030110(LegoBuildingInfo* p_data)
}
// FUNCTION: LEGO1 0x10030150
void LegoBuildingManager::ScheduleAnimation(LegoEntity* p_entity, MxLong p_length, MxBool p_haveSound, MxBool p_unk0x28)
void LegoBuildingManager::ScheduleAnimation(
LegoEntity* p_entity,
MxLong p_length,
MxBool p_haveSound,
MxBool p_hideAfterAnimation
)
{
m_world = CurrentWorld();
@ -671,7 +676,7 @@ void LegoBuildingManager::ScheduleAnimation(LegoEntity* p_entity, MxLong p_lengt
}
if (m_numEntries == 0) {
m_unk0x28 = p_unk0x28;
m_hideAfterAnimation = p_hideAfterAnimation;
TickleManager()->RegisterClient(this, 50);
}
@ -685,9 +690,9 @@ void LegoBuildingManager::ScheduleAnimation(LegoEntity* p_entity, MxLong p_lengt
time += p_length;
entry->m_time = time + 1000;
entry->m_unk0x0c = entry->m_roi->GetWorldPosition()[1];
entry->m_y = entry->m_roi->GetWorldPosition()[1];
entry->m_muted = p_haveSound == FALSE;
FUN_100307b0(p_entity, -2);
AdjustCounter(p_entity, -2);
}
// FUNCTION: LEGO1 0x10030220
@ -724,33 +729,33 @@ MxResult LegoBuildingManager::Tickle()
MxMatrix local48;
MxMatrix locald8;
MxMatrix local120(entry->m_roi->GetLocal2World());
Mx3DPointFloat local134(local120[3]);
MxMatrix transformationMatrix(entry->m_roi->GetLocal2World());
Mx3DPointFloat position(transformationMatrix[3]);
ZEROVEC3(local120[3]);
ZEROVEC3(transformationMatrix[3]);
locald8.SetIdentity();
local48 = local120;
local48 = transformationMatrix;
local134[1] = sin(((entry->m_time - time) * 10) * 0.0062831999f) * 0.4 + (entry->m_unk0x0c -= 0.05);
SET3(local120[3], local134);
position[1] = sin(((entry->m_time - time) * 10) * 0.0062831999f) * 0.4 + (entry->m_y -= 0.05);
SET3(transformationMatrix[3], position);
entry->m_roi->UpdateTransformationRelativeToParent(local120);
entry->m_roi->UpdateTransformationRelativeToParent(transformationMatrix);
VideoManager()->Get3DManager()->Moved(*entry->m_roi);
if (entry->m_time < time) {
LegoBuildingInfo* info = GetInfo(entry->m_entity);
if (info->m_unk0x11 && !m_unk0x28) {
if (info->m_counter && !m_hideAfterAnimation) {
MxS32 index = info - g_buildingInfo;
AdjustHeight(index);
MxMatrix mat = entry->m_roi->GetLocal2World();
mat[3][1] = g_buildingInfo[index].m_unk0x14;
mat[3][1] = g_buildingInfo[index].m_adjustedY;
entry->m_roi->UpdateTransformationRelativeToParent(mat);
VideoManager()->Get3DManager()->Moved(*entry->m_roi);
}
else {
info->m_unk0x11 = 0;
info->m_counter = 0;
entry->m_roi->SetVisibility(FALSE);
}
@ -774,17 +779,17 @@ MxResult LegoBuildingManager::Tickle()
// FUNCTION: LEGO1 0x10030590
// FUNCTION: BETA10 0x1006474c
void LegoBuildingManager::FUN_10030590()
void LegoBuildingManager::ClearCounters()
{
for (MxS32 i = 0; i < sizeOfArray(g_buildingInfo); i++) {
g_buildingInfo[i].m_unk0x11 = -1;
g_buildingInfo[i].m_initialUnk0x11 = -1;
g_buildingInfo[i].m_counter = -1;
g_buildingInfo[i].m_initialCounter = -1;
AdjustHeight(i);
if (g_buildingInfo[i].m_entity != NULL) {
LegoROI* roi = g_buildingInfo[i].m_entity->GetROI();
MxMatrix mat = roi->GetLocal2World();
mat[3][1] = g_buildingInfo[i].m_unk0x14;
mat[3][1] = g_buildingInfo[i].m_adjustedY;
roi->UpdateTransformationRelativeToParent(mat);
VideoManager()->Get3DManager()->Moved(*roi);
}
@ -793,7 +798,7 @@ void LegoBuildingManager::FUN_10030590()
// FUNCTION: LEGO1 0x10030630
// FUNCTION: BETA10 0x100648ab
MxResult LegoBuildingManager::FUN_10030630()
MxResult LegoBuildingManager::DetermineBoundaries()
{
LegoWorld* world = CurrentWorld();
@ -859,7 +864,7 @@ MxResult LegoBuildingManager::FUN_10030630()
}
}
m_unk0x09 = TRUE;
m_boundariesDetermined = TRUE;
return SUCCESS;
}
@ -867,8 +872,8 @@ MxResult LegoBuildingManager::FUN_10030630()
// FUNCTION: BETA10 0x10064db9
LegoBuildingInfo* LegoBuildingManager::GetInfoArray(MxS32& p_length)
{
if (!m_unk0x09) {
FUN_10030630();
if (!m_boundariesDetermined) {
DetermineBoundaries();
}
p_length = sizeOfArray(g_buildingInfo);
@ -876,28 +881,28 @@ LegoBuildingInfo* LegoBuildingManager::GetInfoArray(MxS32& p_length)
}
// FUNCTION: LEGO1 0x100307b0
void LegoBuildingManager::FUN_100307b0(LegoEntity* p_entity, MxS32 p_adjust)
void LegoBuildingManager::AdjustCounter(LegoEntity* p_entity, MxS32 p_adjust)
{
LegoBuildingInfo* info = GetInfo(p_entity);
if (info != NULL) {
if (info->m_unk0x11 < 0) {
info->m_unk0x11 = g_buildingInfoDownshift[info - g_buildingInfo];
if (info->m_counter < 0) {
info->m_counter = g_buildingInfoDownshift[info - g_buildingInfo];
}
if (info->m_unk0x11 > 0) {
info->m_unk0x11 += p_adjust;
if (info->m_unk0x11 <= 1 && p_adjust < 0) {
info->m_unk0x11 = 0;
if (info->m_counter > 0) {
info->m_counter += p_adjust;
if (info->m_counter <= 1 && p_adjust < 0) {
info->m_counter = 0;
}
}
}
}
// FUNCTION: LEGO1 0x10030800
void LegoBuildingManager::FUN_10030800()
void LegoBuildingManager::SetInitialCounters()
{
for (MxU32 i = 0; i < sizeOfArray(g_buildingInfo); i++) {
g_buildingInfo[i].m_initialUnk0x11 = g_buildingInfo[i].m_unk0x11;
g_buildingInfo[i].m_initialCounter = g_buildingInfo[i].m_counter;
}
}

View File

@ -643,7 +643,7 @@ MxBool LegoCharacterManager::SetHeadTexture(LegoROI* p_roi, LegoTextureInfo* p_t
lodList->Release();
lodList = dupLodList;
if (head->GetUnknown0xe0() >= 0) {
if (head->GetLodLevel() >= 0) {
VideoManager()->Get3DManager()->GetLego3DView()->GetViewManager()->RemoveROIDetailFromScene(head);
}
@ -844,7 +844,7 @@ MxBool LegoCharacterManager::SwitchVariant(LegoROI* p_roi)
lodList->Release();
lodList = dupLodList;
if (childROI->GetUnknown0xe0() >= 0) {
if (childROI->GetLodLevel() >= 0) {
VideoManager()->Get3DManager()->GetLego3DView()->GetViewManager()->RemoveROIDetailFromScene(childROI);
}

View File

@ -868,17 +868,17 @@ void LegoGameState::SwitchArea(Area p_area)
VideoManager()->SetUnk0x554(TRUE);
InvokeAction(Extra::ActionType::e_opendisk, *g_infodoorScript, InfodoorScript::c__StartUp, NULL);
break;
case e_unk4:
case e_infocenterExited:
case e_jetrace2:
case e_jetraceExterior:
case e_unk17:
case e_jetskibuildExited:
case e_carraceExterior:
case e_unk20:
case e_racecarbuildExited:
case e_unk21:
case e_pizzeriaExterior:
case e_garageExterior:
case e_hospitalExterior:
case e_unk31:
case e_hospitalExited:
case e_policeExterior:
case e_bike:
case e_dunecar:
@ -886,7 +886,7 @@ void LegoGameState::SwitchArea(Area p_area)
case e_copter:
case e_skateboard:
case e_jetski:
case e_unk66:
case e_vehicleExited:
LoadIsle();
break;
case e_elevbott:
@ -948,7 +948,7 @@ void LegoGameState::SwitchArea(Area p_area)
VideoManager()->Get3DManager()->SetFrustrum(90, 0.1f, 250.0f);
InvokeAction(Extra::ActionType::e_start, *g_isleScript, IsleScript::c_GaraDoor, NULL);
break;
case e_unk28: {
case e_garageExited: {
Act1State* state = (Act1State*) GameState()->GetState("Act1State");
LoadIsle();
@ -973,7 +973,7 @@ void LegoGameState::SwitchArea(Area p_area)
VideoManager()->SetUnk0x554(TRUE);
InvokeAction(Extra::ActionType::e_opendisk, *g_hospitalScript, HospitalScript::c__StartUp, NULL);
break;
case e_unk33:
case e_policeExited:
LoadIsle();
SetCameraControllerFromIsle();
UserActor()->ResetWorldTransform(TRUE);

View File

@ -31,10 +31,10 @@ const char* g_plantLodNames[4][5] = {
};
// GLOBAL: LEGO1 0x100f16b0
float g_unk0x100f16b0[] = {0.1f, 0.7f, 0.5f, 0.9f};
float g_heightPerCount[] = {0.1f, 0.7f, 0.5f, 0.9f};
// GLOBAL: LEGO1 0x100f16c0
MxU8 g_unk0x100f16c0[] = {1, 2, 2, 3};
MxU8 g_counters[] = {1, 2, 2, 3};
// GLOBAL: LEGO1 0x100f315c
MxU32 LegoPlantManager::g_maxSound = 8;
@ -217,7 +217,7 @@ LegoEntity* LegoPlantManager::CreatePlant(MxS32 p_index, LegoWorld* p_world, Leg
if (p_index < sizeOfArray(g_plantInfo)) {
MxU32 world = 1 << (MxU8) p_worldId;
if (g_plantInfo[p_index].m_worlds & world && g_plantInfo[p_index].m_unk0x16 != 0) {
if (g_plantInfo[p_index].m_worlds & world && g_plantInfo[p_index].m_counter != 0) {
if (g_plantInfo[p_index].m_entity == NULL) {
char name[256];
char lodName[256];
@ -285,7 +285,7 @@ MxResult LegoPlantManager::Write(LegoStorage* p_storage)
if (p_storage->Write(&info->m_color, sizeof(info->m_color)) != SUCCESS) {
goto done;
}
if (p_storage->Write(&info->m_initialUnk0x16, sizeof(info->m_initialUnk0x16)) != SUCCESS) {
if (p_storage->Write(&info->m_initialCounter, sizeof(info->m_initialCounter)) != SUCCESS) {
goto done;
}
}
@ -320,12 +320,12 @@ MxResult LegoPlantManager::Read(LegoStorage* p_storage)
if (p_storage->Read(&info->m_color, sizeof(MxU8)) != SUCCESS) {
goto done;
}
if (p_storage->Read(&info->m_unk0x16, sizeof(MxS8)) != SUCCESS) {
if (p_storage->Read(&info->m_counter, sizeof(MxS8)) != SUCCESS) {
goto done;
}
info->m_initialUnk0x16 = info->m_unk0x16;
FUN_10026860(i);
info->m_initialCounter = info->m_counter;
AdjustHeight(i);
}
result = SUCCESS;
@ -336,13 +336,13 @@ MxResult LegoPlantManager::Read(LegoStorage* p_storage)
// FUNCTION: LEGO1 0x10026860
// FUNCTION: BETA10 0x100c5be0
void LegoPlantManager::FUN_10026860(MxS32 p_index)
void LegoPlantManager::AdjustHeight(MxS32 p_index)
{
MxU8 variant = g_plantInfo[p_index].m_variant;
if (g_plantInfo[p_index].m_unk0x16 >= 0) {
float value = g_unk0x100f16c0[variant] - g_plantInfo[p_index].m_unk0x16;
g_plantInfo[p_index].m_position[1] = g_plantInfoInit[p_index].m_position[1] - value * g_unk0x100f16b0[variant];
if (g_plantInfo[p_index].m_counter >= 0) {
float value = g_counters[variant] - g_plantInfo[p_index].m_counter;
g_plantInfo[p_index].m_position[1] = g_plantInfoInit[p_index].m_position[1] - value * g_heightPerCount[variant];
}
else {
g_plantInfo[p_index].m_position[1] = g_plantInfoInit[p_index].m_position[1];
@ -394,7 +394,7 @@ MxBool LegoPlantManager::SwitchColor(LegoEntity* p_entity)
ViewLODList* lodList = GetViewLODListManager()->Lookup(g_plantLodNames[info->m_variant][info->m_color]);
if (roi->GetUnknown0xe0() >= 0) {
if (roi->GetLodLevel() >= 0) {
VideoManager()->Get3DManager()->GetLego3DView()->GetViewManager()->RemoveROIDetailFromScene(roi);
}
@ -410,7 +410,7 @@ MxBool LegoPlantManager::SwitchVariant(LegoEntity* p_entity)
{
LegoPlantInfo* info = GetInfo(p_entity);
if (info == NULL || info->m_unk0x16 != -1) {
if (info == NULL || info->m_counter != -1) {
return FALSE;
}
@ -423,7 +423,7 @@ MxBool LegoPlantManager::SwitchVariant(LegoEntity* p_entity)
ViewLODList* lodList = GetViewLODListManager()->Lookup(g_plantLodNames[info->m_variant][info->m_color]);
if (roi->GetUnknown0xe0() >= 0) {
if (roi->GetLodLevel() >= 0) {
VideoManager()->Get3DManager()->GetLego3DView()->GetViewManager()->RemoveROIDetailFromScene(roi);
}
@ -550,7 +550,7 @@ void LegoPlantManager::SetCustomizeAnimFile(const char* p_value)
// FUNCTION: LEGO1 0x10026c50
// FUNCTION: BETA10 0x100c6349
MxBool LegoPlantManager::FUN_10026c50(LegoEntity* p_entity)
MxBool LegoPlantManager::DecrementCounter(LegoEntity* p_entity)
{
LegoPlantInfo* info = GetInfo(p_entity);
@ -558,12 +558,12 @@ MxBool LegoPlantManager::FUN_10026c50(LegoEntity* p_entity)
return FALSE;
}
return FUN_10026c80(info - g_plantInfo);
return DecrementCounter(info - g_plantInfo);
}
// FUNCTION: LEGO1 0x10026c80
// FUNCTION: BETA10 0x100c63eb
MxBool LegoPlantManager::FUN_10026c80(MxS32 p_index)
MxBool LegoPlantManager::DecrementCounter(MxS32 p_index)
{
if (p_index >= sizeOfArray(g_plantInfo)) {
return FALSE;
@ -577,23 +577,23 @@ MxBool LegoPlantManager::FUN_10026c80(MxS32 p_index)
MxBool result = TRUE;
if (info->m_unk0x16 < 0) {
info->m_unk0x16 = g_unk0x100f16c0[info->m_variant];
if (info->m_counter < 0) {
info->m_counter = g_counters[info->m_variant];
}
if (info->m_unk0x16 > 0) {
if (info->m_counter > 0) {
LegoROI* roi = info->m_entity->GetROI();
info->m_unk0x16--;
info->m_counter--;
if (info->m_unk0x16 == 1) {
info->m_unk0x16 = 0;
if (info->m_counter == 1) {
info->m_counter = 0;
}
if (info->m_unk0x16 == 0) {
if (info->m_counter == 0) {
roi->SetVisibility(FALSE);
}
else {
FUN_10026860(info - g_plantInfo);
AdjustHeight(info - g_plantInfo);
info->m_entity->SetLocation(info->m_position, info->m_direction, info->m_up, FALSE);
}
}
@ -623,7 +623,7 @@ void LegoPlantManager::ScheduleAnimation(LegoEntity* p_entity, MxLong p_length)
time += p_length;
entry->m_time = time + 1000;
FUN_100271b0(p_entity, -1);
AdjustCounter(p_entity, -1);
}
// FUNCTION: LEGO1 0x10026e00
@ -672,11 +672,11 @@ MxResult LegoPlantManager::Tickle()
if (entry->m_time < time) {
LegoPlantInfo* info = GetInfo(entry->m_entity);
if (info->m_unk0x16 == 0) {
if (info->m_counter == 0) {
entry->m_roi->SetVisibility(FALSE);
}
else {
FUN_10026860(info - g_plantInfo);
AdjustHeight(info - g_plantInfo);
info->m_entity->SetLocation(info->m_position, info->m_direction, info->m_up, FALSE);
}
@ -699,14 +699,14 @@ MxResult LegoPlantManager::Tickle()
}
// FUNCTION: LEGO1 0x10027120
void LegoPlantManager::FUN_10027120()
void LegoPlantManager::ClearCounters()
{
LegoWorld* world = CurrentWorld();
for (MxS32 i = 0; i < sizeOfArray(g_plantInfo); i++) {
g_plantInfo[i].m_unk0x16 = -1;
g_plantInfo[i].m_initialUnk0x16 = -1;
FUN_10026860(i);
g_plantInfo[i].m_counter = -1;
g_plantInfo[i].m_initialCounter = -1;
AdjustHeight(i);
if (g_plantInfo[i].m_entity != NULL) {
g_plantInfo[i].m_entity->SetLocation(
@ -720,28 +720,28 @@ void LegoPlantManager::FUN_10027120()
}
// FUNCTION: LEGO1 0x100271b0
void LegoPlantManager::FUN_100271b0(LegoEntity* p_entity, MxS32 p_adjust)
void LegoPlantManager::AdjustCounter(LegoEntity* p_entity, MxS32 p_adjust)
{
LegoPlantInfo* info = GetInfo(p_entity);
if (info != NULL) {
if (info->m_unk0x16 < 0) {
info->m_unk0x16 = g_unk0x100f16c0[info->m_variant];
if (info->m_counter < 0) {
info->m_counter = g_counters[info->m_variant];
}
if (info->m_unk0x16 > 0) {
info->m_unk0x16 += p_adjust;
if (info->m_unk0x16 <= 1 && p_adjust < 0) {
info->m_unk0x16 = 0;
if (info->m_counter > 0) {
info->m_counter += p_adjust;
if (info->m_counter <= 1 && p_adjust < 0) {
info->m_counter = 0;
}
}
}
}
// FUNCTION: LEGO1 0x10027200
void LegoPlantManager::FUN_10027200()
void LegoPlantManager::SetInitialCounters()
{
for (MxU32 i = 0; i < sizeOfArray(g_plantInfo); i++) {
g_plantInfo[i].m_initialUnk0x16 = g_plantInfo[i].m_unk0x16;
g_plantInfo[i].m_initialCounter = g_plantInfo[i].m_counter;
}
}

View File

@ -500,10 +500,10 @@ MxLong LegoEntity::Notify(MxParam& p_param)
case e_unk1:
break;
case e_plant:
PlantManager()->FUN_10026c50(this);
PlantManager()->DecrementCounter(this);
break;
case e_building:
BuildingManager()->FUN_10030000(this);
BuildingManager()->DecrementCounter(this);
break;
case e_autoROI:
break;

View File

@ -701,7 +701,7 @@ MxLong LegoNavController::Notify(MxParam& p_param)
Mx3DPointFloat roiPosition(roi->GetWorldPosition());
roiPosition -= viewPosition;
if (roiPosition.LenSquared() < 2000.0 || roi->GetUnknown0xe0() > 0) {
if (roiPosition.LenSquared() < 2000.0 || roi->GetLodLevel() > 0) {
entity->ClickAnimation();
}
}

View File

@ -559,27 +559,32 @@ MxResult LegoPathController::ReadEdges(LegoStorage* p_storage)
if (p_storage->Read(&s, sizeof(MxU16)) != SUCCESS) {
return FAILURE;
}
assert(s < m_numN);
edge.m_pointA = &m_nodes[s];
if (p_storage->Read(&s, sizeof(MxU16)) != SUCCESS) {
return FAILURE;
}
assert(s < m_numN);
edge.m_pointB = &m_nodes[s];
if (edge.m_flags & LegoOrientedEdge::c_hasFaceA) {
if (p_storage->Read(&s, sizeof(MxU16)) != SUCCESS) {
return FAILURE;
}
assert(s < m_numL);
edge.m_faceA = &m_boundaries[s];
if (p_storage->Read(&s, sizeof(MxU16)) != SUCCESS) {
return FAILURE;
}
assert(s < m_numE);
edge.m_ccwA = &m_edges[s];
if (p_storage->Read(&s, sizeof(MxU16)) != SUCCESS) {
return FAILURE;
}
assert(s < m_numE);
edge.m_cwA = &m_edges[s];
}
@ -587,16 +592,19 @@ MxResult LegoPathController::ReadEdges(LegoStorage* p_storage)
if (p_storage->Read(&s, sizeof(MxU16)) != SUCCESS) {
return FAILURE;
}
assert(s < m_numL);
edge.m_faceB = &m_boundaries[s];
if (p_storage->Read(&s, sizeof(MxU16)) != SUCCESS) {
return FAILURE;
}
assert(s < m_numE);
edge.m_ccwB = &m_edges[s];
if (p_storage->Read(&s, sizeof(MxU16)) != SUCCESS) {
return FAILURE;
}
assert(s < m_numE);
edge.m_cwB = &m_edges[s];
}
@ -617,6 +625,9 @@ MxResult LegoPathController::ReadEdges(LegoStorage* p_storage)
MxResult LegoPathController::ReadBoundaries(LegoStorage* p_storage)
{
for (MxS32 i = 0; i < m_numL; i++) {
#ifdef BETA10
Mx4DPointFloat unused;
#endif
LegoPathBoundary& boundary = m_boundaries[i];
MxU8 numE;
MxU16 s;
@ -626,6 +637,8 @@ MxResult LegoPathController::ReadBoundaries(LegoStorage* p_storage)
return FAILURE;
}
assert(numE > 2);
boundary.m_edgeNormals = new Mx4DPointFloat[numE];
LegoOrientedEdge** edges = new LegoOrientedEdge*[numE];
@ -636,6 +649,8 @@ MxResult LegoPathController::ReadBoundaries(LegoStorage* p_storage)
return FAILURE;
}
assert(s < m_numE);
edges[j] = &m_edges[s];
}
@ -693,6 +708,8 @@ MxResult LegoPathController::ReadBoundaries(LegoStorage* p_storage)
return FAILURE;
}
assert(s < m_numT);
boundary.m_pathTrigger[j].m_pathStruct = &m_structs[s];
if (p_storage->Read(&boundary.m_pathTrigger[j].m_data, sizeof(boundary.m_pathTrigger[j].m_data)) !=

View File

@ -588,7 +588,7 @@ MxLong Act3::Notify(MxParam& p_param)
m_unk0x421e = 0;
while (--length >= 0) {
if (info[length].m_unk0x11 < 0 && info[length].m_boundary != NULL &&
if (info[length].m_counter < 0 && info[length].m_boundary != NULL &&
info[length].m_entity != NULL) {
m_unk0x421e++;
}
@ -664,8 +664,8 @@ MxLong Act3::HandleTransitionEnd()
// FUNCTION: LEGO1 0x10073270
void Act3::ReadyWorld()
{
PlantManager()->FUN_10027200();
BuildingManager()->FUN_10030800();
PlantManager()->SetInitialCounters();
BuildingManager()->SetInitialCounters();
AnimationManager()->FUN_1005f6d0(FALSE);
VideoManager()->Get3DManager()->SetFrustrum(90.0f, 0.1f, 125.0f);

View File

@ -26,7 +26,7 @@ DECOMP_SIZE_ASSERT(GasStation, 0x128)
DECOMP_SIZE_ASSERT(GasStationState, 0x24)
// GLOBAL: LEGO1 0x100f0160
undefined4 g_unk0x100f0160 = 3;
MxS32 g_animationSkipCounterGasStation = 3;
// GLOBAL: LEGO1 0x100f0164
MxBool g_trackLedEnabled = FALSE;
@ -38,11 +38,11 @@ GasStation::GasStation()
m_state = NULL;
m_destLocation = LegoGameState::e_undefined;
m_trackLedBitmap = NULL;
m_unk0x104 = 0;
m_unk0x114 = FALSE;
m_unk0x106 = 0;
m_unk0x10c = 0;
m_unk0x115 = FALSE;
m_waitingState = e_finished;
m_waiting = FALSE;
m_setWithCurrentAction = 0;
m_lastIdleAnimation = 0;
m_flashingLeds = FALSE;
m_trackLedTimer = 0;
NotificationManager()->Register(this);
@ -59,7 +59,7 @@ GasStation::~GasStation()
ControlManager()->Unregister(this);
TickleManager()->UnregisterClient(this);
NotificationManager()->Unregister(this);
g_unk0x100f0160 = 3;
g_animationSkipCounterGasStation = 3;
}
// FUNCTION: LEGO1 0x10004990
@ -77,13 +77,13 @@ MxResult GasStation::Create(MxDSAction& p_dsAction)
m_state = (GasStationState*) GameState()->GetState("GasStationState");
if (!m_state) {
m_state = (GasStationState*) GameState()->CreateState("GasStationState");
m_state->m_unk0x14 = 1;
m_state->m_state = GasStationState::e_newState;
}
else if (m_state->m_unk0x14 == 4) {
m_state->m_unk0x14 = 4;
else if (m_state->m_state == GasStationState::e_unknown4) {
m_state->m_state = GasStationState::e_unknown4;
}
else {
m_state->m_unk0x14 = 3;
m_state->m_state = GasStationState::e_unknown3;
}
GameState()->m_currentArea = LegoGameState::e_garage;
@ -139,25 +139,25 @@ void GasStation::ReadyWorld()
case LegoActor::c_pepper:
switch (m_state->m_pepperAction) {
case 0:
m_state->m_unk0x14 = 5;
m_state->m_state = GasStationState::e_introduction;
PlayAction(GarageScript::c_wgs002nu_RunAnim);
m_unk0x106 = 1;
m_setWithCurrentAction = 1;
break;
case 1:
m_state->m_unk0x14 = 5;
m_state->m_state = GasStationState::e_introduction;
PlayAction(GarageScript::c_wgs003nu_RunAnim);
m_unk0x106 = 1;
m_setWithCurrentAction = 1;
break;
case 2:
m_state->m_unk0x14 = 5;
m_state->m_state = GasStationState::e_introduction;
PlayAction(GarageScript::c_wgs004nu_RunAnim);
m_unk0x106 = 1;
m_setWithCurrentAction = 1;
break;
default:
m_state->m_unk0x14 = 6;
m_state->m_state = GasStationState::e_explainQuest;
PlayAction(GarageScript::c_wgs008nu_RunAnim);
m_unk0x106 = 1;
m_unk0x104 = 1;
m_setWithCurrentAction = 1;
m_waitingState = e_start;
break;
}
@ -168,20 +168,20 @@ void GasStation::ReadyWorld()
case LegoActor::c_mama:
switch (m_state->m_mamaAction) {
case 0:
m_state->m_unk0x14 = 5;
m_state->m_state = GasStationState::e_introduction;
PlayAction(GarageScript::c_wgs006nu_RunAnim);
m_unk0x106 = 1;
m_setWithCurrentAction = 1;
break;
case 1:
m_state->m_unk0x14 = 5;
m_state->m_state = GasStationState::e_introduction;
PlayAction(GarageScript::c_wgs007nu_RunAnim);
m_unk0x106 = 1;
m_setWithCurrentAction = 1;
break;
default:
m_state->m_unk0x14 = 6;
m_state->m_state = GasStationState::e_explainQuest;
PlayAction(GarageScript::c_wgs008nu_RunAnim);
m_unk0x106 = 1;
m_unk0x104 = 1;
m_setWithCurrentAction = 1;
m_waitingState = e_start;
break;
}
@ -192,20 +192,20 @@ void GasStation::ReadyWorld()
case LegoActor::c_nick:
switch (m_state->m_nickAction) {
case 0:
m_state->m_unk0x14 = 5;
m_state->m_state = GasStationState::e_introduction;
PlayAction(GarageScript::c_wgs009nu_RunAnim);
m_unk0x106 = 1;
m_setWithCurrentAction = 1;
break;
case 1:
m_state->m_unk0x14 = 5;
m_state->m_state = GasStationState::e_introduction;
PlayAction(GarageScript::c_wgs010nu_RunAnim);
m_unk0x106 = 1;
m_setWithCurrentAction = 1;
break;
default:
m_state->m_unk0x14 = 6;
m_state->m_state = GasStationState::e_explainQuest;
PlayAction(GarageScript::c_wgs008nu_RunAnim);
m_unk0x106 = 1;
m_unk0x104 = 1;
m_setWithCurrentAction = 1;
m_waitingState = e_start;
break;
}
@ -216,20 +216,20 @@ void GasStation::ReadyWorld()
case LegoActor::c_papa:
switch (m_state->m_papaAction) {
case 0:
m_state->m_unk0x14 = 5;
m_state->m_state = GasStationState::e_introduction;
PlayAction(GarageScript::c_wgs012nu_RunAnim);
m_unk0x106 = 1;
m_setWithCurrentAction = 1;
break;
case 1:
m_state->m_unk0x14 = 5;
m_state->m_state = GasStationState::e_introduction;
PlayAction(GarageScript::c_wgs014nu_RunAnim);
m_unk0x106 = 1;
m_setWithCurrentAction = 1;
break;
default:
m_state->m_unk0x14 = 6;
m_state->m_state = GasStationState::e_explainQuest;
PlayAction(GarageScript::c_wgs017nu_RunAnim);
m_unk0x106 = 1;
m_unk0x104 = 1;
m_setWithCurrentAction = 1;
m_waitingState = e_start;
break;
}
@ -240,20 +240,20 @@ void GasStation::ReadyWorld()
case LegoActor::c_laura:
switch (m_state->m_lauraAction) {
case 0:
m_state->m_unk0x14 = 5;
m_state->m_state = GasStationState::e_introduction;
PlayAction(GarageScript::c_wgs020nu_RunAnim);
m_unk0x106 = 1;
m_setWithCurrentAction = 1;
break;
case 1:
m_state->m_unk0x14 = 5;
m_state->m_state = GasStationState::e_introduction;
PlayAction(GarageScript::c_wgs021nu_RunAnim);
m_unk0x106 = 1;
m_setWithCurrentAction = 1;
break;
default:
m_state->m_unk0x14 = 6;
m_state->m_state = GasStationState::e_explainQuest;
PlayAction(GarageScript::c_wgs022nu_RunAnim);
m_unk0x106 = 1;
m_unk0x104 = 1;
m_setWithCurrentAction = 1;
m_waitingState = e_start;
break;
}
@ -301,35 +301,35 @@ MxLong GasStation::HandleEndAction(MxEndActionNotificationParam& p_param)
if (action->GetAtomId() == m_atomId && action->GetObjectId()) {
m_state->StopAction((GarageScript::Script) action->GetObjectId());
m_unk0x106 = 0;
m_setWithCurrentAction = 0;
switch (m_state->m_unk0x14) {
case 5:
g_unk0x100f0160 = 0;
m_state->m_unk0x14 = 6;
m_unk0x115 = TRUE;
switch (m_state->m_state) {
case GasStationState::e_introduction:
g_animationSkipCounterGasStation = 0;
m_state->m_state = GasStationState::e_explainQuest;
m_flashingLeds = TRUE;
PlayAction(GarageScript::c_wgs023nu_RunAnim);
m_unk0x106 = 1;
m_unk0x104 = 1;
m_setWithCurrentAction = 1;
m_waitingState = e_start;
break;
case 6:
g_unk0x100f0160 = 0;
m_unk0x115 = TRUE;
case GasStationState::e_explainQuest:
g_animationSkipCounterGasStation = 0;
m_flashingLeds = TRUE;
if (m_unk0x104 == 3) {
m_state->m_unk0x14 = 8;
if (m_waitingState == e_canceled) {
m_state->m_state = GasStationState::e_afterAcceptingQuest;
PlayAction(GarageScript::c_wgs029nu_RunAnim);
m_unk0x106 = 1;
m_setWithCurrentAction = 1;
}
else {
m_state->m_unk0x14 = 7;
m_unk0x114 = TRUE;
m_state->m_state = GasStationState::e_waitAcceptingQuest;
m_waiting = TRUE;
}
break;
case 8:
m_state->m_unk0x14 = 2;
case GasStationState::e_afterAcceptingQuest:
m_state->m_state = GasStationState::e_beforeExitingForQuest;
((Act1State*) GameState()->GetState("Act1State"))->m_unk0x018 = 7;
m_destLocation = LegoGameState::e_unk28;
m_destLocation = LegoGameState::e_garageExited;
m_radio.Stop();
BackgroundAudioManager()->Stop();
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
@ -346,7 +346,7 @@ MxLong GasStation::HandleEndAction(MxEndActionNotificationParam& p_param)
// FUNCTION: LEGO1 0x10005920
MxLong GasStation::HandleKeyPress(MxS8 p_key)
{
if (p_key == VK_SPACE && g_unk0x100f0160 == 0 && m_unk0x106 != 0) {
if (p_key == VK_SPACE && g_animationSkipCounterGasStation == 0 && m_setWithCurrentAction != 0) {
m_state->StopActions();
return 1;
}
@ -358,18 +358,18 @@ MxLong GasStation::HandleKeyPress(MxS8 p_key)
// FUNCTION: BETA10 0x10029319
MxLong GasStation::HandleButtonDown(LegoControlManagerNotificationParam& p_param)
{
if (m_unk0x104 == 1 || m_unk0x104 == 2) {
if (m_waitingState == e_start || m_waitingState == e_started) {
LegoROI* roi = PickROI(p_param.GetX(), p_param.GetY());
if (roi != NULL) {
if (!strnicmp(roi->GetName(), "capdb", 5) || !strnicmp(roi->GetName(), "*capdb", 6)) {
m_unk0x104 = 3;
m_unk0x114 = FALSE;
m_waitingState = e_canceled;
m_waiting = FALSE;
if (m_state->m_unk0x14 == 7) {
m_state->m_unk0x14 = 8;
if (m_state->m_state == GasStationState::e_waitAcceptingQuest) {
m_state->m_state = GasStationState::e_afterAcceptingQuest;
PlayAction(GarageScript::c_wgs029nu_RunAnim);
m_unk0x106 = 1;
m_setWithCurrentAction = 1;
}
else {
StopAction(GarageScript::c_wgs023nu_RunAnim);
@ -393,7 +393,7 @@ MxLong GasStation::HandleControl(LegoControlManagerNotificationParam& p_param)
switch (p_param.m_clickedObjectId) {
case GarageScript::c_LeftArrow_Ctl:
case GarageScript::c_RightArrow_Ctl:
m_state->m_unk0x14 = 0;
m_state->m_state = GasStationState::e_unknown0;
m_destLocation = LegoGameState::Area::e_garadoor;
m_state->StopActions();
@ -402,7 +402,7 @@ MxLong GasStation::HandleControl(LegoControlManagerNotificationParam& p_param)
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
break;
case GarageScript::c_Info_Ctl:
m_state->m_unk0x14 = 0;
m_state->m_state = GasStationState::e_unknown0;
m_destLocation = LegoGameState::Area::e_infomain;
m_state->StopActions();
@ -411,7 +411,7 @@ MxLong GasStation::HandleControl(LegoControlManagerNotificationParam& p_param)
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
break;
case GarageScript::c_Buggy_Ctl:
m_state->m_unk0x14 = 0;
m_state->m_state = GasStationState::e_unknown0;
m_destLocation = LegoGameState::Area::e_dunecarbuild;
m_state->StopActions();
@ -451,29 +451,29 @@ MxResult GasStation::Tickle()
return SUCCESS;
}
if (g_unk0x100f0160 != 0) {
g_unk0x100f0160--;
if (g_animationSkipCounterGasStation != 0) {
g_animationSkipCounterGasStation--;
}
MxLong time = Timer()->GetTime();
if (m_unk0x114) {
if (time - m_unk0x10c > 15000) {
m_unk0x10c = time;
if (m_unk0x104 == 1) {
m_unk0x104 = 2;
if (m_waiting) {
if (time - m_lastIdleAnimation > 15000) {
m_lastIdleAnimation = time;
if (m_waitingState == e_start) {
m_waitingState = e_started;
}
else if (m_unk0x104 != 0) {
m_unk0x104 = 0;
else if (m_waitingState != e_finished) {
m_waitingState = e_finished;
MxDSAction action;
m_state->m_unk0x14 = 9;
m_state->m_state = GasStationState::e_cancelQuest;
PlayAction(GarageScript::c_wgs031nu_RunAnim);
m_unk0x106 = 1;
m_setWithCurrentAction = 1;
}
}
}
if (m_unk0x115) {
if (m_flashingLeds) {
if (time - m_trackLedTimer > 300) {
m_trackLedTimer = time;
g_trackLedEnabled = !g_trackLedEnabled;
@ -489,7 +489,7 @@ MxBool GasStation::Escape()
{
m_radio.Stop();
m_state->StopActions();
m_state->m_unk0x14 = 0;
m_state->m_state = GasStationState::e_unknown0;
m_destLocation = LegoGameState::Area::e_infomain;
return TRUE;
}

View File

@ -24,7 +24,7 @@ DECOMP_SIZE_ASSERT(Hospital, 0x12c)
DECOMP_SIZE_ASSERT(HospitalState, 0x18)
// GLOBAL: LEGO1 0x100f7918
undefined4 g_animationSkipCounter = 3;
undefined4 g_animationSkipCounterHospital = 3;
// GLOBAL: LEGO1 0x100f791c
MxBool g_copLedEnabled = FALSE;
@ -64,7 +64,7 @@ Hospital::~Hospital()
m_hospitalState->m_state = HospitalState::e_unknown3;
NotificationManager()->Unregister(this);
g_animationSkipCounter = 3;
g_animationSkipCounterHospital = 3;
}
// FUNCTION: LEGO1 0x100748c0
@ -222,7 +222,7 @@ MxLong Hospital::HandleKeyPress(MxS8 p_key)
{
MxLong result = 0;
if (p_key == VK_SPACE && g_animationSkipCounter == 0) {
if (p_key == VK_SPACE && g_animationSkipCounterHospital == 0) {
DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim);
result = 1;
}
@ -251,7 +251,7 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param)
m_currentAction = HospitalScript::c_hho006cl_RunAnim;
m_setWithCurrentAction = 1;
m_flashingLeds = 1;
g_animationSkipCounter = 0;
g_animationSkipCounterHospital = 0;
break;
case HospitalState::e_explainQuestShort:
m_time = Timer()->GetTime();
@ -369,7 +369,7 @@ MxLong Hospital::HandleEndAction(MxEndActionNotificationParam& p_param)
case HospitalState::e_exitToFront:
if (m_unk0x128 == 0) {
m_unk0x128 = 1;
m_destLocation = LegoGameState::e_unk31;
m_destLocation = LegoGameState::e_hospitalExited;
DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim);
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
@ -421,7 +421,7 @@ MxLong Hospital::HandleButtonDown(LegoControlManagerNotificationParam& p_param)
act1State->m_unk0x018 = 9;
m_destLocation = LegoGameState::e_unk31;
m_destLocation = LegoGameState::e_hospitalExited;
DeleteObjects(
&m_atomId,
HospitalScript::c_hho002cl_RunAnim,
@ -590,7 +590,7 @@ MxBool Hospital::HandleControl(LegoControlManagerNotificationParam& p_param)
else if (m_unk0x128 == 0) {
m_unk0x128 = 1;
m_hospitalState->m_state = HospitalState::e_exitImmediately;
m_destLocation = LegoGameState::e_unk31;
m_destLocation = LegoGameState::e_hospitalExited;
DeleteObjects(&m_atomId, HospitalScript::c_hho002cl_RunAnim, HospitalScript::c_hho006cl_RunAnim);
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
@ -637,8 +637,8 @@ MxResult Hospital::Tickle()
return SUCCESS;
}
if (g_animationSkipCounter != 0) {
g_animationSkipCounter -= 1;
if (g_animationSkipCounterHospital != 0) {
g_animationSkipCounterHospital -= 1;
}
MxLong time = Timer()->GetTime();

View File

@ -1385,8 +1385,8 @@ void Infocenter::Reset()
break;
}
PlantManager()->FUN_10027120();
BuildingManager()->FUN_10030590();
PlantManager()->ClearCounters();
BuildingManager()->ClearCounters();
AnimationManager()->Reset(FALSE);
CharacterManager()->ReleaseAllActors();
GameState()->SetCurrentAct(LegoGameState::e_act1);

View File

@ -119,7 +119,7 @@ MxLong InfocenterDoor::HandleControl(LegoControlManagerNotificationParam& p_para
if (GameState()->GetActorId() != LegoActor::c_none) {
InfocenterState* state = (InfocenterState*) GameState()->GetState("InfocenterState");
if (state->HasRegistered()) {
m_destLocation = LegoGameState::e_unk4;
m_destLocation = LegoGameState::e_infocenterExited;
}
else {
MxDSAction action;

View File

@ -430,7 +430,7 @@ MxLong Isle::HandleControl(LegoControlManagerNotificationParam& p_param)
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
break;
case IsleScript::c_PoliDoor_Door_Ctl:
m_destLocation = LegoGameState::e_unk33;
m_destLocation = LegoGameState::e_policeExited;
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
break;
case IsleScript::c_GaraDoor_LeftArrow_Ctl:
@ -440,7 +440,7 @@ MxLong Isle::HandleControl(LegoControlManagerNotificationParam& p_param)
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
break;
case IsleScript::c_GaraDoor_Door_Ctl:
m_destLocation = LegoGameState::e_unk28;
m_destLocation = LegoGameState::e_garageExited;
TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE);
break;
}
@ -712,7 +712,7 @@ void Isle::Enable(MxBool p_enable)
if (GameState()->m_currentArea == LegoGameState::e_pizzeriaExterior) {
AnimationManager()->FUN_10064740(NULL);
}
else if (GameState()->m_currentArea == LegoGameState::e_unk66) {
else if (GameState()->m_currentArea == LegoGameState::e_vehicleExited) {
Mx3DPointFloat position(UserActor()->GetROI()->GetWorldPosition());
Mx3DPointFloat sub(-21.375f, 0.0f, -41.75f);
@ -820,7 +820,7 @@ void Isle::Enable(MxBool p_enable)
TRUE,
IslePathActor::c_spawnBit1 | IslePathActor::c_playMusic | IslePathActor::c_spawnBit3
);
GameState()->m_currentArea = LegoGameState::e_unk66;
GameState()->m_currentArea = LegoGameState::e_vehicleExited;
EnableAnimations(TRUE);
m_jukebox->StartAction();
break;
@ -863,21 +863,21 @@ void Isle::FUN_10032620()
VideoManager()->Get3DManager()->SetFrustrum(90.0, 0.1, 250.0);
switch (GameState()->m_currentArea) {
case LegoGameState::e_unk66: {
case LegoGameState::e_vehicleExited: {
MxMatrix mat(UserActor()->GetROI()->GetLocal2World());
LegoPathBoundary* boundary = UserActor()->GetBoundary();
((IslePathActor*) UserActor())->VTable0xec(mat, boundary, TRUE);
break;
}
case LegoGameState::e_unk4:
case LegoGameState::e_infocenterExited:
case LegoGameState::e_jetraceExterior:
case LegoGameState::e_unk17:
case LegoGameState::e_jetskibuildExited:
case LegoGameState::e_carraceExterior:
case LegoGameState::e_unk20:
case LegoGameState::e_racecarbuildExited:
case LegoGameState::e_pizzeriaExterior:
case LegoGameState::e_garageExterior:
case LegoGameState::e_hospitalExterior:
case LegoGameState::e_unk31:
case LegoGameState::e_hospitalExited:
case LegoGameState::e_policeExterior:
((IslePathActor*) UserActor())
->SpawnPlayer(
@ -885,7 +885,7 @@ void Isle::FUN_10032620()
TRUE,
IslePathActor::c_spawnBit1 | IslePathActor::c_playMusic | IslePathActor::c_spawnBit3
);
GameState()->m_currentArea = LegoGameState::e_unk66;
GameState()->m_currentArea = LegoGameState::e_vehicleExited;
break;
}
}
@ -955,7 +955,7 @@ MxLong Isle::HandleTransitionEnd()
VariableTable()->SetVariable("VISIBILITY", "Hide Gas");
FUN_10032d30(IsleScript::c_GaraDoor_Background_Bitmap, JukeboxScript::c_JBMusic2, "LCAMZG1,90", FALSE);
break;
case LegoGameState::e_unk28:
case LegoGameState::e_garageExited:
GameState()->SwitchArea(m_destLocation);
GameState()->StopArea(LegoGameState::e_previousArea);
m_destLocation = LegoGameState::e_undefined;
@ -965,7 +965,7 @@ MxLong Isle::HandleTransitionEnd()
SetAppCursor(e_cursorArrow);
SetIsWorldActive(TRUE);
break;
case LegoGameState::e_unk33:
case LegoGameState::e_policeExited:
GameState()->SwitchArea(m_destLocation);
GameState()->StopArea(LegoGameState::e_previousArea);
m_destLocation = LegoGameState::e_undefined;

View File

@ -25,6 +25,7 @@ class LegoWEEdge {
// FUNCTION: BETA10 0x100373f0
LegoU32 IsEqual(LegoWEEdge* p_other) { return this == p_other; }
// FUNCTION: BETA10 0x100bd410
void SetEdges(LegoOrientedEdge** p_edges, LegoU8 p_numEdges)
{
m_edges = p_edges;

View File

@ -16,7 +16,7 @@ DECOMP_SIZE_ASSERT(LegoLOD::Mesh, 0x08)
LPDIRECT3DRMMATERIAL g_unk0x101013d4 = NULL;
// GLOBAL: LEGO1 0x101013dc
const char* g_unk0x101013dc = "inh";
const char* g_InhPrefix = "inh";
inline IDirect3DRM2* GetD3DRM(Tgl::Renderer* pRenderer);
inline BOOL GetMeshData(IDirect3DRMMesh*& mesh, D3DRMGROUPINDEX& index, Tgl::Mesh* pMesh);
@ -66,7 +66,7 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text
LegoU32(*textureIndices)[3] = NULL;
LegoTextureInfo* textureInfo = NULL;
LegoU32 i, meshUnd1, meshUnd2, tempNumVertsAndNormals;
LegoU32 i, indexBackwards, indexForwards, tempNumVertsAndNormals;
unsigned char paletteEntries[256];
if (p_storage->Read(&m_unk0x08, sizeof(undefined4)) != SUCCESS) {
@ -93,8 +93,8 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text
m_melems = new Mesh[m_numMeshes];
memset(m_melems, 0, sizeof(*m_melems) * m_numMeshes);
meshUnd1 = m_numMeshes - 1;
meshUnd2 = 0;
indexBackwards = m_numMeshes - 1;
indexForwards = 0;
if (p_storage->Read(&tempNumVertsAndNormals, sizeof(LegoU32)) != SUCCESS) {
goto done;
@ -184,13 +184,13 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text
textureName = mesh->GetTextureName();
materialName = mesh->GetMaterialName();
if (FUN_100aae20(textureName) || FUN_100aae20(materialName)) {
meshIndex = meshUnd1;
meshUnd1--;
if (HasInhPrefix(textureName) || HasInhPrefix(materialName)) {
meshIndex = indexBackwards;
indexBackwards--;
}
else {
meshIndex = meshUnd2;
meshUnd2++;
meshIndex = indexForwards;
indexForwards++;
}
m_melems[meshIndex].m_tglMesh = m_meshBuilder->CreateMesh(
@ -211,7 +211,7 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text
m_melems[meshIndex].m_tglMesh->SetShadingModel(shadingModel);
if (textureName != NULL) {
if (mesh->GetUnknown0x21()) {
if (mesh->GetUseAlias()) {
LegoROI::GetPaletteEntries(textureName, paletteEntries, sizeOfArray(paletteEntries));
}
@ -231,7 +231,7 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text
LegoFloat blue = 1.0F;
LegoFloat alpha = 0.0F;
if (mesh->GetUnknown0x21()) {
if (mesh->GetUseAlias()) {
LegoROI::GetRGBAColor(materialName, red, green, blue, alpha);
}
else {
@ -265,7 +265,7 @@ LegoResult LegoLOD::Read(Tgl::Renderer* p_renderer, LegoTextureContainer* p_text
}
}
m_meshOffset = meshUnd2;
m_meshOffset = indexForwards;
if (textureVertices != NULL) {
delete[] textureVertices;
@ -377,10 +377,10 @@ LegoResult LegoLOD::GetTextureInfo(LegoTextureInfo*& p_textureInfo)
}
// FUNCTION: LEGO1 0x100aae20
LegoBool LegoLOD::FUN_100aae20(const LegoChar* p_name)
LegoBool LegoLOD::HasInhPrefix(const LegoChar* p_name)
{
if (p_name != NULL) {
if (!strnicmp(p_name, g_unk0x101013dc, strlen(g_unk0x101013dc))) {
if (!strnicmp(p_name, g_InhPrefix, strlen(g_InhPrefix))) {
return TRUE;
}
}

View File

@ -35,7 +35,7 @@ class LegoLOD : public ViewLOD {
void ClearMeshOffset();
LegoResult GetTextureInfo(LegoTextureInfo*& p_textureInfo);
static LegoBool FUN_100aae20(const LegoChar* p_name);
static LegoBool HasInhPrefix(const LegoChar* p_name);
// SYNTHETIC: LEGO1 0x100aa430
// LegoLOD::`scalar deleting destructor'

View File

@ -15,7 +15,7 @@ LegoMesh::LegoMesh()
m_unk0x0d = 0;
m_unk0x10 = NULL;
m_unk0x20 = 0;
m_unk0x21 = FALSE;
m_useAlias = FALSE;
m_materialName = NULL;
}
@ -55,7 +55,7 @@ LegoResult LegoMesh::Read(LegoStorage* p_storage)
if ((result = p_storage->Read(&m_unk0x20, sizeof(undefined))) != SUCCESS) {
return result;
}
if ((result = p_storage->Read(&m_unk0x21, sizeof(LegoU8))) != SUCCESS) {
if ((result = p_storage->Read(&m_useAlias, sizeof(LegoU8))) != SUCCESS) {
return result;
}

View File

@ -56,7 +56,7 @@ class LegoMesh {
LegoU8 GetUnknown0x0d() { return m_unk0x0d; }
const LegoChar* GetTextureName() { return m_textureName; }
const LegoChar* GetMaterialName() { return m_materialName; }
LegoBool GetUnknown0x21() { return m_unk0x21; }
LegoBool GetUseAlias() { return m_useAlias; }
LegoResult Read(LegoStorage* p_storage);
// SYNTHETIC: LEGO1 0x100d3840
@ -72,7 +72,7 @@ class LegoMesh {
LegoChar* m_textureName; // 0x18
LegoChar* m_materialName; // 0x1c
undefined m_unk0x20; // 0x20 - unused
LegoBool m_unk0x21; // 0x21
LegoBool m_useAlias; // 0x21
};
#endif // __LEGOMESH_H

View File

@ -25,7 +25,7 @@ float g_minLODThreshold = 0.00097656297;
int g_maxLODLevels = 6;
// GLOBAL: LEGO1 0x1010105c
float g_unk0x1010105c = 0.000125F;
float g_viewDistance = 0.000125F;
// GLOBAL: LEGO1 0x10101060
float g_elapsedSeconds = 0;
@ -65,19 +65,19 @@ unsigned int ViewManager::IsBoundingBoxInFrustum(const BoundingBox& p_bounding_b
{
const Vector3* box[] = {&p_bounding_box.Min(), &p_bounding_box.Max()};
float und[8][3];
float box_corners[8][3];
int i, j, k;
for (i = 0; i < 8; i++) {
for (j = 0; j < 3; j++) {
und[i][j] = box[g_boundingBoxCornerMap[i][j]]->operator[](j);
box_corners[i][j] = box[g_boundingBoxCornerMap[i][j]]->operator[](j);
}
}
for (i = 0; i < 6; i++) {
for (k = 0; k < 8; k++) {
if (frustum_planes[i][0] * und[k][0] + frustum_planes[i][2] * und[k][2] + frustum_planes[i][1] * und[k][1] +
frustum_planes[i][3] >=
if (frustum_planes[i][0] * box_corners[k][0] + frustum_planes[i][2] * box_corners[k][2] +
frustum_planes[i][1] * box_corners[k][1] + frustum_planes[i][3] >=
0.0f) {
break;
}
@ -98,7 +98,7 @@ void ViewManager::Remove(ViewROI* p_roi)
if (*it == p_roi) {
rois.erase(it);
if (p_roi->GetUnknown0xe0() >= 0) {
if (p_roi->GetLodLevel() >= 0) {
RemoveROIDetailFromScene(p_roi);
}
@ -106,7 +106,7 @@ void ViewManager::Remove(ViewROI* p_roi)
if (comp != NULL) {
for (CompoundObject::const_iterator it = comp->begin(); !(it == comp->end()); it++) {
if (((ViewROI*) *it)->GetUnknown0xe0() >= 0) {
if (((ViewROI*) *it)->GetLodLevel() >= 0) {
RemoveROIDetailFromScene((ViewROI*) *it);
}
}
@ -128,11 +128,11 @@ void ViewManager::RemoveAll(ViewROI* p_roi)
rois.erase(rois.begin(), rois.end());
}
else {
if (p_roi->GetUnknown0xe0() >= 0) {
if (p_roi->GetLodLevel() >= 0) {
RemoveROIDetailFromScene(p_roi);
}
p_roi->SetUnknown0xe0(-1);
p_roi->SetLodLevel(ViewROI::c_lodLevelUnset);
const CompoundObject* comp = p_roi->GetComp();
if (comp != NULL) {
@ -146,15 +146,15 @@ void ViewManager::RemoveAll(ViewROI* p_roi)
}
// FUNCTION: LEGO1 0x100a65b0
void ViewManager::UpdateROIDetailBasedOnLOD(ViewROI* p_roi, int p_und)
void ViewManager::UpdateROIDetailBasedOnLOD(ViewROI* p_roi, int p_lodLevel)
{
if (p_roi->GetLODCount() <= p_und) {
p_und = p_roi->GetLODCount() - 1;
if (p_roi->GetLODCount() <= p_lodLevel) {
p_lodLevel = p_roi->GetLODCount() - 1;
}
int unk0xe0 = p_roi->GetUnknown0xe0();
int lodLevel = p_roi->GetLodLevel();
if (unk0xe0 == p_und) {
if (lodLevel == p_lodLevel) {
return;
}
@ -162,8 +162,8 @@ void ViewManager::UpdateROIDetailBasedOnLOD(ViewROI* p_roi, int p_und)
Tgl::MeshBuilder* meshBuilder;
ViewLOD* lod;
if (unk0xe0 < 0) {
lod = (ViewLOD*) p_roi->GetLOD(p_und);
if (lodLevel < 0) {
lod = (ViewLOD*) p_roi->GetLOD(p_lodLevel);
if (lod->GetUnknown0x08() & ViewLOD::c_bit4) {
scene->Add((Tgl::MeshBuilder*) group);
@ -171,7 +171,7 @@ void ViewManager::UpdateROIDetailBasedOnLOD(ViewROI* p_roi, int p_und)
}
}
else {
lod = (ViewLOD*) p_roi->GetLOD(unk0xe0);
lod = (ViewLOD*) p_roi->GetLOD(lodLevel);
if (lod != NULL) {
meshBuilder = lod->GetMeshBuilder();
@ -181,7 +181,7 @@ void ViewManager::UpdateROIDetailBasedOnLOD(ViewROI* p_roi, int p_und)
}
}
lod = (ViewLOD*) p_roi->GetLOD(p_und);
lod = (ViewLOD*) p_roi->GetLOD(p_lodLevel);
}
if (lod->GetUnknown0x08() & ViewLOD::c_bit4) {
@ -190,18 +190,18 @@ void ViewManager::UpdateROIDetailBasedOnLOD(ViewROI* p_roi, int p_und)
if (meshBuilder != NULL) {
group->Add(meshBuilder);
SetAppData(p_roi, reinterpret_cast<LPD3DRM_APPDATA>(p_roi));
p_roi->SetUnknown0xe0(p_und);
p_roi->SetLodLevel(p_lodLevel);
return;
}
}
p_roi->SetUnknown0xe0(-1);
p_roi->SetLodLevel(ViewROI::c_lodLevelUnset);
}
// FUNCTION: LEGO1 0x100a66a0
void ViewManager::RemoveROIDetailFromScene(ViewROI* p_roi)
{
const ViewLOD* lod = (const ViewLOD*) p_roi->GetLOD(p_roi->GetUnknown0xe0());
const ViewLOD* lod = (const ViewLOD*) p_roi->GetLOD(p_roi->GetLodLevel());
if (lod != NULL) {
const Tgl::MeshBuilder* meshBuilder = NULL;
@ -216,58 +216,61 @@ void ViewManager::RemoveROIDetailFromScene(ViewROI* p_roi)
scene->Remove(roiGeometry);
}
p_roi->SetUnknown0xe0(-1);
p_roi->SetLodLevel(ViewROI::c_lodLevelUnset);
}
// FUNCTION: LEGO1 0x100a66f0
inline void ViewManager::ManageVisibilityAndDetailRecursively(ViewROI* p_roi, int p_und)
// FUNCTION: BETA10 0x1017297f
inline void ViewManager::ManageVisibilityAndDetailRecursively(ViewROI* p_from, int p_lodLevel)
{
if (!p_roi->GetVisibility() && p_und != -2) {
ManageVisibilityAndDetailRecursively(p_roi, -2);
assert(p_from);
if (!p_from->GetVisibility() && p_lodLevel != ViewROI::c_lodLevelInvisible) {
ManageVisibilityAndDetailRecursively(p_from, ViewROI::c_lodLevelInvisible);
}
else {
const CompoundObject* comp = p_roi->GetComp();
const CompoundObject* comp = p_from->GetComp();
if (p_und == -1) {
if (p_roi->GetWorldBoundingSphere().Radius() > 0.001F) {
float und = ProjectedSize(p_roi->GetWorldBoundingSphere());
if (p_lodLevel == ViewROI::c_lodLevelUnset) {
if (p_from->GetWorldBoundingSphere().Radius() > 0.001F) {
float projectedSize = ProjectedSize(p_from->GetWorldBoundingSphere());
if (und < seconds_allowed * g_unk0x1010105c) {
if (p_roi->GetUnknown0xe0() == -2) {
return;
if (projectedSize < seconds_allowed * g_viewDistance) {
if (p_from->GetLodLevel() != ViewROI::c_lodLevelInvisible) {
ManageVisibilityAndDetailRecursively(p_from, ViewROI::c_lodLevelInvisible);
}
ManageVisibilityAndDetailRecursively(p_roi, -2);
return;
}
p_und = CalculateLODLevel(und, RealtimeView::GetUserMaxLodPower() * seconds_allowed, p_roi);
else {
p_lodLevel =
CalculateLODLevel(projectedSize, RealtimeView::GetUserMaxLodPower() * seconds_allowed, p_from);
}
}
}
if (p_und == -2) {
if (p_roi->GetUnknown0xe0() >= 0) {
RemoveROIDetailFromScene(p_roi);
p_roi->SetUnknown0xe0(-2);
if (p_lodLevel == ViewROI::c_lodLevelInvisible) {
if (p_from->GetLodLevel() >= 0) {
RemoveROIDetailFromScene(p_from);
p_from->SetLodLevel(ViewROI::c_lodLevelInvisible);
}
if (comp != NULL) {
for (CompoundObject::const_iterator it = comp->begin(); !(it == comp->end()); it++) {
ManageVisibilityAndDetailRecursively((ViewROI*) *it, p_und);
for (CompoundObject::const_iterator it = comp->begin(); it != comp->end(); it++) {
ManageVisibilityAndDetailRecursively((ViewROI*) *it, p_lodLevel);
}
}
}
else if (comp == NULL) {
if (p_roi->GetLODs() != NULL && p_roi->GetLODCount() > 0) {
UpdateROIDetailBasedOnLOD(p_roi, p_und);
return;
if (p_from->GetLODs() != NULL && p_from->GetLODCount() > 0) {
UpdateROIDetailBasedOnLOD(p_from, p_lodLevel);
}
}
else {
p_roi->SetUnknown0xe0(-1);
p_from->SetLodLevel(ViewROI::c_lodLevelUnset);
for (CompoundObject::const_iterator it = comp->begin(); !(it == comp->end()); it++) {
ManageVisibilityAndDetailRecursively((ViewROI*) *it, p_und);
for (CompoundObject::const_iterator it = comp->begin(); it != comp->end(); it++) {
ManageVisibilityAndDetailRecursively((ViewROI*) *it, p_lodLevel);
}
}
}
@ -290,7 +293,7 @@ void ViewManager::Update(float p_previousRenderTime, float)
}
for (CompoundObject::iterator it = rois.begin(); it != rois.end(); it++) {
ManageVisibilityAndDetailRecursively((ViewROI*) *it, -1);
ManageVisibilityAndDetailRecursively((ViewROI*) *it, ViewROI::c_lodLevelUnset);
}
stopWatch.Stop();
@ -306,7 +309,7 @@ inline int ViewManager::CalculateFrustumTransformations()
}
else {
float fVar7 = tan(view_angle / 2.0F);
view_area_at_one = view_angle * view_angle * 4.0F;
view_area_at_one = fVar7 * fVar7 * 4.0F;
float fVar1 = front * fVar7;
float fVar2 = (width / height) * fVar1;
@ -350,30 +353,38 @@ inline int ViewManager::CalculateFrustumTransformations()
}
}
inline int ViewManager::CalculateLODLevel(float p_und1, float p_und2, ViewROI* p_roi)
// FUNCTION: BETA10 0x10172be5
inline int ViewManager::CalculateLODLevel(float p_maximumScale, float p_initialScale, ViewROI* from)
{
int result;
float i;
int lodLevel;
if (IsROIVisibleAtLOD(p_roi) != 0) {
if (p_und1 < g_minLODThreshold) {
assert(from);
if (GetFirstLODIndex(from) != 0) {
if (p_maximumScale < g_minLODThreshold) {
return 0;
}
result = 1;
else {
lodLevel = 1;
}
}
else {
result = 0;
lodLevel = 0;
}
for (i = p_und2; result < g_maxLODLevels && p_und1 >= i; i *= g_LODScaleFactor) {
result++;
for (float i = p_initialScale; lodLevel < g_maxLODLevels; lodLevel++) {
if (i >= p_maximumScale) {
break;
}
i *= g_LODScaleFactor;
}
return result;
return lodLevel;
}
inline int ViewManager::IsROIVisibleAtLOD(ViewROI* p_roi)
// FUNCTION: BETA10 0x10172cb0
inline int ViewManager::GetFirstLODIndex(ViewROI* p_roi)
{
const LODListBase* lods = p_roi->GetLODs();
@ -381,22 +392,24 @@ inline int ViewManager::IsROIVisibleAtLOD(ViewROI* p_roi)
if (((ViewLOD*) p_roi->GetLOD(0))->GetUnknown0x08Test8()) {
return 1;
}
return 0;
else {
return 0;
}
}
const CompoundObject* comp = p_roi->GetComp();
if (comp != NULL) {
for (CompoundObject::const_iterator it = comp->begin(); !(it == comp->end()); it++) {
for (CompoundObject::const_iterator it = comp->begin(); it != comp->end(); it++) {
const LODListBase* lods = ((ViewROI*) *it)->GetLODs();
if (lods != NULL && lods->Size() > 0) {
if (((ViewLOD*) ((ViewROI*) *it)->GetLOD(0))->GetUnknown0x08Test8()) {
return 1;
}
return 0;
else {
return 0;
}
}
}
}
@ -480,7 +493,7 @@ float ViewManager::ProjectedSize(const BoundingSphere& p_bounding_sphere)
// is then the ratio of the area of that projected circle to the view surface area
// at Z == 1.0.
//
float sphere_projected_area = 3.14159265359 * (p_bounding_sphere.Radius() * p_bounding_sphere.Radius());
float sphere_projected_area = 3.14159265359 * p_bounding_sphere.Radius() * p_bounding_sphere.Radius();
float square_dist_to_sphere = DISTSQRD3(p_bounding_sphere.Center(), pov[3]);
return sphere_projected_area / view_area_at_one / square_dist_to_sphere;
}

View File

@ -24,20 +24,20 @@ class ViewManager {
void Remove(ViewROI* p_roi);
void RemoveAll(ViewROI* p_roi);
unsigned int IsBoundingBoxInFrustum(const BoundingBox& p_bounding_box);
void UpdateROIDetailBasedOnLOD(ViewROI* p_roi, int p_und);
void UpdateROIDetailBasedOnLOD(ViewROI* p_roi, int p_lodLevel);
void RemoveROIDetailFromScene(ViewROI* p_roi);
void SetPOVSource(const OrientableROI* point_of_view);
float ProjectedSize(const BoundingSphere& p_bounding_sphere);
ViewROI* Pick(Tgl::View* p_view, unsigned long x, unsigned long y);
void SetResolution(int width, int height);
void SetFrustrum(float fov, float front, float back);
inline void ManageVisibilityAndDetailRecursively(ViewROI* p_roi, int p_und);
inline void ManageVisibilityAndDetailRecursively(ViewROI* p_from, int p_lodLevel);
void Update(float p_previousRenderTime, float);
inline int CalculateFrustumTransformations();
void UpdateViewTransformations();
inline static int CalculateLODLevel(float p_und1, float p_und2, ViewROI* p_roi);
inline static int IsROIVisibleAtLOD(ViewROI* p_roi);
inline static int CalculateLODLevel(float p_maximumScale, float p_initalScale, ViewROI* from);
inline static int GetFirstLODIndex(ViewROI* p_roi);
// FUNCTION: BETA10 0x100576b0
const CompoundObject& GetROIs() { return rois; }

View File

@ -16,11 +16,16 @@
// SIZE 0xe4
class ViewROI : public OrientableROI {
public:
enum {
c_lodLevelUnset = -1,
c_lodLevelInvisible = -2,
};
ViewROI(Tgl::Renderer* pRenderer, ViewLODList* lodList)
{
SetLODList(lodList);
geometry = pRenderer->CreateGroup();
m_unk0xe0 = -1;
m_lodLevel = c_lodLevelUnset;
}
// FUNCTION: LEGO1 0x100a9e20
@ -56,8 +61,8 @@ class ViewROI : public OrientableROI {
virtual Tgl::Group* GetGeometry(); // vtable+0x30
virtual const Tgl::Group* GetGeometry() const; // vtable+0x34
int GetUnknown0xe0() { return m_unk0xe0; }
void SetUnknown0xe0(int p_unk0xe0) { m_unk0xe0 = p_unk0xe0; }
int GetLodLevel() { return m_lodLevel; }
void SetLodLevel(int p_lodLevel) { m_lodLevel = p_lodLevel; }
static unsigned char SetLightSupport(unsigned char p_lightSupport);
@ -65,7 +70,7 @@ class ViewROI : public OrientableROI {
void UpdateWorldDataWithTransformAndChildren(const Matrix4& parent2world) override; // vtable+0x28
Tgl::Group* geometry; // 0xdc
int m_unk0xe0; // 0xe0
int m_lodLevel; // 0xe0
};
// SYNTHETIC: LEGO1 0x100aa250

View File

@ -38,3 +38,8 @@ targets:
- 0x100fb080
# memset etc.
- 0x100f9570
ALPHA:
filename: ALPHA.DLL
source-root: LEGO1
hash:
sha256: dc7e5ed8ec9d96851126a40c4d23755f1783a8df61def44c667dfaa992ac509e

View File

@ -2,202 +2,15 @@
Accuracy to the game's original code is the main goal of this project. To facilitate the decompilation effort and maintain overall quality, we have devised a set of annotations, to be embedded in the source code, which allow us to automatically verify the accuracy of re-compiled functions' assembly, virtual tables, variable offsets and more.
In order for contributions to be accepted, the annotations must be used in accordance to the rules outlined here. Proper use is enforced by [GitHub Actions](/.github/workflows) which run the Python tools found in this folder. It is recommended to integrate these tools into your local development workflow as well.
The tooling we have developed has been moved to the [reccmp](https://github.com/isledecomp/reccmp) repo to facilitate its use in other decompilation projects.
* See the [README](https://github.com/isledecomp/reccmp?tab=readme-ov-file#getting-started) on how to get started.
* Familiarize yourself with the available [annotations](https://github.com/isledecomp/reccmp/blob/master/docs/annotations.md) and the [best practices](https://github.com/isledecomp/reccmp/blob/master/docs/recommendations.md) we have established.
# Overview
We are continually working on extending the capabilities of our "decompilation language" and the toolset around it. Some of the following annotations have not made it into formal verification and thus are not technically enforced on the source code level yet (marked as **WIP**). Nevertheless, it is recommended to use them since it is highly likely they will eventually be fully integrated.
## Functions
All non-inlined functions in the code base with the exception of [3rd party code](/3rdparty) must be annotated with one of the following markers, which include the module name and address of the function as found in the original binaries. This information is then used to compare the recompiled assembly with the original assembly, resulting in an accuracy score. Functions in a given compilation unit must be ordered by their address in ascending order.
The annotations can be attached to the function implementation, which is the most common case, or use the "comment" syntax (see examples below) for functions that cannot be referred to directly (such as templated, synthetic or non-inlined inline functions). The latter should only ever appear in `.h` files.
### `FUNCTION`
Functions with a reasonably complete implementation which are not templated or synthetic (see below) should be annotated with `FUNCTION`.
```
// FUNCTION: LEGO1 0x100b12c0
MxCore* MxObjectFactory::Create(const char* p_name)
{
// implementation
}
// FUNCTION: LEGO1 0x100140d0
// MxCore::IsA
```
### `STUB`
Functions with no or a very incomplete implementation should be annotated with `STUB`. These will not be compared to the original assembly.
```
// STUB: LEGO1 0x10011d50
LegoCameraController::LegoCameraController()
{
// TODO
}
```
### `TEMPLATE`
Templated functions should be annotated with `TEMPLATE`. Since the goal is to eventually have a full accounting of all the functions present in the binaries, please make an effort to find and annotate every function of a templated class.
```
// TEMPLATE: LEGO1 0x100c0ee0
// list<MxNextActionDataStart *,allocator<MxNextActionDataStart *> >::_Buynode
// TEMPLATE: LEGO1 0x100c0fc0
// MxStreamListMxDSSubscriber::~MxStreamListMxDSSubscriber
// TEMPLATE: LEGO1 0x100c1010
// MxStreamListMxDSAction::~MxStreamListMxDSAction
```
### `SYNTHETIC`
Synthetic functions should be annotated with `SYNTHETIC`. A synthetic function is generated by the compiler; most common is the "scalar deleting destructor" found in virtual tables. Other cases include default destructors and assignment operators. Note: `SYNTHETIC` takes precedence over `TEMPLATE`.
```
// SYNTHETIC: LEGO1 0x10003210
// Helicopter::`scalar deleting destructor'
// SYNTHETIC: LEGO1 0x100c4f50
// MxCollection<MxRegionLeftRight *>::`scalar deleting destructor'
// SYNTHETIC: LEGO1 0x100c4fc0
// MxList<MxRegionLeftRight *>::`scalar deleting destructor'
```
### `LIBRARY`
Functions located in 3rd party libraries should be annotated with `LIBRARY`. Since the goal is to eventually have a full accounting of all the functions present in the binaries, please make an effort to find and annotate every function of every statically linked library, including the MSVC standard libraries.
```
// LIBRARY: ISLE 0x4061b0
// _MemPoolInit@4
// LIBRARY: ISLE 0x406520
// _MemPoolSetPageSize@8
// LIBRARY: ISLE 0x406630
// _MemPoolSetBlockSizeFS@8
```
## Virtual tables
Classes with a virtual table should be annotated using the `VTABLE` marker, which includes the module name and address of the virtual table. Additionally, virtual function declarations should be annotated with a comment indicating their relative offset. Please use the following example as a reference.
```
// VTABLE: LEGO1 0x100dc900
class MxEventManager : public MxMediaManager {
public:
MxEventManager();
virtual ~MxEventManager() override;
virtual void Destroy() override; // vtable+0x18
virtual MxResult Create(MxU32 p_frequencyMS, MxBool p_createThread); // vtable+0x28
```
## Class size
Classes should be annotated using the `SIZE` marker to indicate their size. If you are unsure about the class size in the original binary, please use the currently available information (known member variables) and detail the circumstances in an extra comment if necessary.
```
// SIZE 0x1c
class MxCriticalSection {
public:
MxCriticalSection();
~MxCriticalSection();
static void SetDoMutex();
```
Furthermore, add `DECOMP_SIZE_ASSERT(MxCriticalSection, 0x1c)` to the respective `.cpp` file (if the class has no dedicated `.cpp` file, use any appropriate `.cpp` file where the class is used).
## Member variables
Member variables should be annotated with their relative offsets.
```
class MxDSObject : public MxCore {
private:
MxU32 m_sizeOnDisk; // 0x8
MxU16 m_type; // 0xc
char* m_sourceName; // 0x10
undefined4 m_unk0x14; // 0x14
```
## Global variables
Global variables should be annotated using the `GLOBAL` marker, which includes the module name and address of the variable.
```
// GLOBAL: LEGO1 0x100f456c
MxAtomId* g_jukeboxScript = NULL;
// GLOBAL: LEGO1 0x100f4570
MxAtomId* g_pz5Script = NULL;
// GLOBAL: LEGO1 0x100f4574
MxAtomId* g_introScript = NULL;
```
## Strings
String values should be annotated using the `STRING` marker, which includes the module name and address of the string.
```
inline virtual const char* ClassName() const override // vtable+0x0c
{
// STRING: LEGO1 0x100f03fc
return "Act2PoliceStation";
}
```
# Tooling
Use `pip` to install the required packages to be able to use the Python tools found in this folder:
```sh
pip install -r tools/requirements.txt
```
Run the following command to allow reccmp to detect the original LEGO binaries:
```sh
reccmp-project detect --what original --search-path <paths-to-directories0containing-lego-binaries>
```
After building recompiled binaries, run the following command in this repository's root:
```sh
reccmp-project detect --what recompiled --search-path <paths-to-build-directories>
```
The example usages below assume that the current working directory is this repository's root and that the retail binaries have been copied to `./legobin`.
* `reccmp-decomplint`: Checks the decompilation annotations (see above)
* e.g. `reccmp-decomplint --module LEGO1 LEGO1`
* [`ncc`](/tools/ncc): Checks naming conventions based on a set of rules
* `reccmp-reccmp`: Compares an original binary with a recompiled binary, provided a PDB file. For example:
* Display the diff for a single function: `py -m tools.reccmp.reccmp --verbose 0x100ae1a0 legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB .`
* Generate an HTML report: `py -m tools.reccmp.reccmp --html output.html legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB .`
* Create a base file for diffs: `py -m tools.reccmp.reccmp --json base.json --silent legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB .`
* Diff against a base file: `py -m tools.reccmp.reccmp --diff base.json legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB .`
* `reccmp-stackcmp`: Compares the stack layout for a given function that almost matches.
* e.g. `reccmp-stackcmp legobin/BETA10.DLL build_debug/LEGO1.DLL build_debug/LEGO1.pdb . 0x1007165d`
* `reccmp-roadmap`: Compares symbol locations in an original binary with the same symbol locations of a recompiled binary
* `reccmp-verexp`: Verifies exports by comparing the exports of the original DLL and the recompiled DLL
* `reccmp-vtable`: Asserts virtual table correctness by comparing a recompiled binary with the original
* e.g. `reccmp-vtable legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB .`
* `reccmp-datacmp`: Compares global data found in the original with the recompiled version
* e.g. `reccmp-datacmp legobin/LEGO1.DLL build/LEGO1.DLL build/LEGO1.PDB .`
* [`patch_c2.py`](/tools/patch_c2.py): Patches `C2.EXE` (part of MSVC 4.20) to get rid of a bugged warning
The following scripts are specific to LEGO Island and have thus remained here:
* [`patch_c2.py`](/tools/patch_c2.py): Patches `C2.EXE` (part of MSVC 4.20) to get rid of a bugged warning.
# Modules
The following is a list of all the modules found in the annotations (e.g. `// FUNCTION: [module] [address]`) and which binaries they refer to. See [this list of all known versions of the game](https://www.legoisland.org/wiki/LEGO_Island#Download).
The following is a list of all the modules found in the annotations (e.g. `// FUNCTION: [module] [address]`) and which binaries they refer to. See also [this list of all known versions of the game](https://www.legoisland.org/wiki/LEGO_Island#Download).
## Retail v1.1.0.0 (v1.1)
* `LEGO1` -> `LEGO1.DLL`
@ -219,23 +32,28 @@ It is therefore advisable to search for the corresponding function in `BETA10` w
Unfortunately, some code has been changed after this beta version was created. Therefore, we are not aiming for a perfect binary match of `BETA10`. In case of discrepancies, `LEGO1` (as defined above) is our "gold standard" for matching.
### Re-compiling a beta build (**WIP**)
## Pre-Alpha
* `ALPHA` -> `LEGO1D.DLL`
This debug build is hardly used since it has little benefit over `BETA10`.
# Re-compiling a beta build
If you want to match the code against `BETA10`, use the following `cmake` setup to create a debug build:
```
cmake <path-to-source> -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_BUILD_TYPE=Debug -DISLE_USE_SMARTHEAP=OFF
cmake <path-to-source> -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_BUILD_TYPE=Debug -DISLE_USE_SMARTHEAP=OFF -DISLE_BUILD_BETA10=ON -DISLE_BUILD_LEGO1=OFF
```
**TODO**: If you can figure out how to make a debug build with SmartHeap enabled, please add it here.
If you want to run scripts to compare your debug build to `BETA10` (e.g. `reccmp-reccmp`), it is advisable to add a copy of `LEGO1D.DLL` to `/legobin` and rename it to `BETA10.DLL`.
If you can figure out how to make a debug build with SmartHeap enabled, please add it here.
### Finding matching functions
If you want to run scripts to compare your debug build to `BETA10` (e.g. `reccmp-reccmp`), it is advisable to add a copy of `LEGO1D.DLL` from Beta 1.0 to `/legobin` and rename it to `BETA10.DLL`. Analogously, you can add `LEGO1D.DLL` from the Pre-Alpha and rename it to `ALPHA.DLL`.
# Finding matching functions
This is not a recipe, but rather a list of things you can try.
* If you are working on a virtual function in a class, try to find the class' vtable. Many (but not all) classes implement `ClassName()`. These functions are usually easy to find by searching the memory for the string consisting of the class name. Keep in mind that not all child classes overwrite this function, so if the function you found is used in multiple vtables (or if you found multiple `ClassName()`-like functions), make sure you actually have the parent's vtable.
* If that does not help, you can try to walk up the call tree and try to locate a function that calls the function you are interested in.
* Assertions can also help you - most `.cpp` file names have already been matched based on `BETA10`, so you can search for the name of your `.cpp` file and check all the assertions in that file. While that does not find all functions in a given source file, it usually finds the more complex ones.
* _If you have found any other strategies, please add them here._
## Others (**WIP**)
* `ALPHA` (only used twice)