mirror of
https://github.com/isledecomp/isle.git
synced 2025-10-23 00:14:22 +00:00
Match LegoGameState::History::WriteScoreHistory()
, clear unknowns (#1576)
--------- Co-authored-by: jonschz <jonschz@users.noreply.github.com>
This commit is contained in:
@@ -150,7 +150,18 @@ public:
|
|||||||
MxS16 m_totalScore; // 0x00
|
MxS16 m_totalScore; // 0x00
|
||||||
MxU8 m_scores[5][5]; // 0x02
|
MxU8 m_scores[5][5]; // 0x02
|
||||||
Username m_name; // 0x1c
|
Username m_name; // 0x1c
|
||||||
MxS16 m_unk0x2a; // 0x2a
|
MxS16 m_playerId; // 0x2a
|
||||||
|
|
||||||
|
ScoreItem& operator=(const ScoreItem& p_other)
|
||||||
|
{
|
||||||
|
// MSVC auto-generates an operator=, but LegoGameState::WriteScoreHistory() has a much better match
|
||||||
|
// with a manual implementation.
|
||||||
|
m_totalScore = p_other.m_totalScore;
|
||||||
|
memcpy(m_scores, p_other.m_scores, sizeof(m_scores));
|
||||||
|
m_name = p_other.m_name;
|
||||||
|
m_playerId = p_other.m_playerId;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// SIZE 0x372
|
// SIZE 0x372
|
||||||
@@ -158,7 +169,7 @@ public:
|
|||||||
History();
|
History();
|
||||||
void WriteScoreHistory();
|
void WriteScoreHistory();
|
||||||
MxResult Serialize(LegoStorage* p_storage);
|
MxResult Serialize(LegoStorage* p_storage);
|
||||||
ScoreItem* FUN_1003cc90(Username* p_player, MxS16 p_unk0x24, MxS32& p_unk0x2c);
|
ScoreItem* FindPlayerInScoreHistory(Username* p_player, MxS16 p_unk0x24, MxS32& p_unk0x2c);
|
||||||
|
|
||||||
// FUNCTION: BETA10 0x1002c2b0
|
// FUNCTION: BETA10 0x1002c2b0
|
||||||
MxS16 GetCount() { return m_count; }
|
MxS16 GetCount() { return m_count; }
|
||||||
@@ -167,9 +178,12 @@ public:
|
|||||||
// FUNCTION: BETA10 0x1002c540
|
// FUNCTION: BETA10 0x1002c540
|
||||||
ScoreItem* GetScore(MxS32 p_index) { return p_index >= m_count ? NULL : &m_scores[p_index]; }
|
ScoreItem* GetScore(MxS32 p_index) { return p_index >= m_count ? NULL : &m_scores[p_index]; }
|
||||||
|
|
||||||
MxS16 m_count; // 0x00
|
MxS16 m_count; // 0x00
|
||||||
ScoreItem m_scores[20]; // 0x02
|
#ifdef BETA10
|
||||||
MxS16 m_unk0x372; // 0x372
|
MxS16 m_indices[20]; // 0x02
|
||||||
|
#endif
|
||||||
|
ScoreItem m_scores[20]; // 0x02 (0x22 for BETA10)
|
||||||
|
MxS16 m_nextPlayerId; // 0x372 (0x392 for BETA10)
|
||||||
};
|
};
|
||||||
|
|
||||||
LegoGameState();
|
LegoGameState();
|
||||||
@@ -243,7 +257,7 @@ private:
|
|||||||
// TODO: Most likely getters/setters are not used according to BETA for the following members:
|
// TODO: Most likely getters/setters are not used according to BETA for the following members:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MxS16 m_unk0x24; // 0x24
|
MxS16 m_currentPlayerId; // 0x24
|
||||||
MxS16 m_playerCount; // 0x26
|
MxS16 m_playerCount; // 0x26
|
||||||
Username m_players[9]; // 0x28
|
Username m_players[9]; // 0x28
|
||||||
History m_history; // 0xa6
|
History m_history; // 0xa6
|
||||||
|
@@ -277,7 +277,7 @@ MxResult LegoGameState::Save(MxULong p_slot)
|
|||||||
}
|
}
|
||||||
|
|
||||||
storage.WriteS32(0x1000c);
|
storage.WriteS32(0x1000c);
|
||||||
storage.WriteS16(m_unk0x24);
|
storage.WriteS16(m_currentPlayerId);
|
||||||
storage.WriteU16(m_currentAct);
|
storage.WriteU16(m_currentAct);
|
||||||
storage.WriteU8(m_actorId);
|
storage.WriteU8(m_actorId);
|
||||||
|
|
||||||
@@ -372,7 +372,7 @@ MxResult LegoGameState::Load(MxULong p_slot)
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
storage.ReadS16(m_unk0x24);
|
storage.ReadS16(m_currentPlayerId);
|
||||||
storage.ReadS16(actArea);
|
storage.ReadS16(actArea);
|
||||||
|
|
||||||
SetCurrentAct((Act) actArea);
|
SetCurrentAct((Act) actArea);
|
||||||
@@ -615,8 +615,8 @@ MxResult LegoGameState::AddPlayer(Username& p_player)
|
|||||||
|
|
||||||
m_playerCount++;
|
m_playerCount++;
|
||||||
m_players[0].Set(p_player);
|
m_players[0].Set(p_player);
|
||||||
m_unk0x24 = m_history.m_unk0x372;
|
m_currentPlayerId = m_history.m_nextPlayerId;
|
||||||
m_history.m_unk0x372 = m_unk0x24 + 1;
|
m_history.m_nextPlayerId = m_currentPlayerId + 1;
|
||||||
m_history.WriteScoreHistory();
|
m_history.WriteScoreHistory();
|
||||||
SetCurrentAct(e_act1);
|
SetCurrentAct(e_act1);
|
||||||
|
|
||||||
@@ -1407,7 +1407,7 @@ MxResult LegoGameState::ScoreItem::Serialize(LegoStorage* p_storage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_name.Serialize(p_storage);
|
m_name.Serialize(p_storage);
|
||||||
p_storage->ReadS16(m_unk0x2a);
|
p_storage->ReadS16(m_playerId);
|
||||||
}
|
}
|
||||||
else if (p_storage->IsWriteMode()) {
|
else if (p_storage->IsWriteMode()) {
|
||||||
p_storage->WriteS16(m_totalScore);
|
p_storage->WriteS16(m_totalScore);
|
||||||
@@ -1419,7 +1419,7 @@ MxResult LegoGameState::ScoreItem::Serialize(LegoStorage* p_storage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_name.Serialize(p_storage);
|
m_name.Serialize(p_storage);
|
||||||
p_storage->WriteS16(m_unk0x2a);
|
p_storage->WriteS16(m_playerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SUCCESS;
|
return SUCCESS;
|
||||||
@@ -1430,7 +1430,7 @@ MxResult LegoGameState::ScoreItem::Serialize(LegoStorage* p_storage)
|
|||||||
LegoGameState::History::History()
|
LegoGameState::History::History()
|
||||||
{
|
{
|
||||||
m_count = 0;
|
m_count = 0;
|
||||||
m_unk0x372 = 0;
|
m_nextPlayerId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x1003c870
|
// FUNCTION: LEGO1 0x1003c870
|
||||||
@@ -1441,83 +1441,130 @@ void LegoGameState::History::WriteScoreHistory()
|
|||||||
MxU8 scores[5][5];
|
MxU8 scores[5][5];
|
||||||
|
|
||||||
InfocenterState* state = (InfocenterState*) GameState()->GetState("InfocenterState");
|
InfocenterState* state = (InfocenterState*) GameState()->GetState("InfocenterState");
|
||||||
if (state->m_letters[0]) {
|
|
||||||
JetskiRaceState* jetskiRaceState = (JetskiRaceState*) GameState()->GetState("JetskiRaceState");
|
|
||||||
CarRaceState* carRaceState = (CarRaceState*) GameState()->GetState("CarRaceState");
|
|
||||||
TowTrackMissionState* towTrackMissionState =
|
|
||||||
(TowTrackMissionState*) GameState()->GetState("TowTrackMissionState");
|
|
||||||
PizzaMissionState* pizzaMissionState = (PizzaMissionState*) GameState()->GetState("PizzaMissionState");
|
|
||||||
AmbulanceMissionState* ambulanceMissionState =
|
|
||||||
(AmbulanceMissionState*) GameState()->GetState("AmbulanceMissionState");
|
|
||||||
|
|
||||||
for (MxS32 actor = 1; actor <= 5; actor++) {
|
if (!state->m_letters[0]) {
|
||||||
scores[0][actor - 1] = carRaceState ? carRaceState->GetState(actor)->GetHighScore() : 0;
|
return;
|
||||||
totalScore += scores[0][actor - 1];
|
}
|
||||||
|
|
||||||
scores[1][actor - 1] = jetskiRaceState ? jetskiRaceState->GetState(actor)->GetHighScore() : 0;
|
JetskiRaceState* jetskiRaceState = (JetskiRaceState*) GameState()->GetState("JetskiRaceState");
|
||||||
totalScore += scores[1][actor - 1];
|
CarRaceState* carRaceState = (CarRaceState*) GameState()->GetState("CarRaceState");
|
||||||
|
TowTrackMissionState* towTrackMissionState = (TowTrackMissionState*) GameState()->GetState("TowTrackMissionState");
|
||||||
|
PizzaMissionState* pizzaMissionState = (PizzaMissionState*) GameState()->GetState("PizzaMissionState");
|
||||||
|
AmbulanceMissionState* ambulanceMissionState =
|
||||||
|
(AmbulanceMissionState*) GameState()->GetState("AmbulanceMissionState");
|
||||||
|
|
||||||
scores[2][actor - 1] = pizzaMissionState ? pizzaMissionState->GetHighScore(actor) : 0;
|
for (MxS32 actor = 1; actor <= 5; actor++) {
|
||||||
totalScore += scores[2][actor - 1];
|
scores[0][actor - 1] = carRaceState ? carRaceState->GetState(actor)->GetHighScore() : 0;
|
||||||
|
totalScore += scores[0][actor - 1];
|
||||||
|
|
||||||
scores[3][actor - 1] = towTrackMissionState ? towTrackMissionState->GetHighScore(actor) : 0;
|
#ifdef BETA10
|
||||||
totalScore += scores[3][actor - 1];
|
// likely a bug in BETA10
|
||||||
|
scores[1][actor - 1] = carRaceState ? carRaceState->GetState(actor)->GetHighScore() : 0;
|
||||||
|
#else
|
||||||
|
scores[1][actor - 1] = jetskiRaceState ? jetskiRaceState->GetState(actor)->GetHighScore() : 0;
|
||||||
|
#endif
|
||||||
|
totalScore += scores[1][actor - 1];
|
||||||
|
|
||||||
scores[4][actor - 1] = ambulanceMissionState ? ambulanceMissionState->GetHighScore(actor) : 0;
|
scores[2][actor - 1] = pizzaMissionState ? pizzaMissionState->GetHighScore(actor) : 0;
|
||||||
totalScore += scores[4][actor - 1];
|
totalScore += scores[2][actor - 1];
|
||||||
}
|
|
||||||
|
|
||||||
MxS32 unk0x2c;
|
scores[3][actor - 1] = towTrackMissionState ? towTrackMissionState->GetHighScore(actor) : 0;
|
||||||
ScoreItem* p_scorehist = FUN_1003cc90(&GameState()->m_players[0], GameState()->m_unk0x24, unk0x2c);
|
totalScore += scores[3][actor - 1];
|
||||||
|
|
||||||
if (p_scorehist != NULL) {
|
scores[4][actor - 1] = ambulanceMissionState ? ambulanceMissionState->GetHighScore(actor) : 0;
|
||||||
p_scorehist->m_totalScore = totalScore;
|
totalScore += scores[4][actor - 1];
|
||||||
memcpy(p_scorehist->m_scores, scores, sizeof(p_scorehist->m_scores));
|
}
|
||||||
}
|
|
||||||
else {
|
MxS32 playerScoreHistoryIndex;
|
||||||
if (m_count < (MxS16) sizeOfArray(m_scores)) {
|
ScoreItem* p_scorehist =
|
||||||
m_scores[m_count].m_totalScore = totalScore;
|
FindPlayerInScoreHistory(GameState()->m_players, GameState()->m_currentPlayerId, playerScoreHistoryIndex);
|
||||||
memcpy(m_scores[m_count].m_scores, scores, sizeof(m_scores[m_count].m_scores));
|
|
||||||
m_scores[m_count].m_name = GameState()->m_players[0];
|
#ifdef BETA10
|
||||||
m_scores[m_count].m_unk0x2a = GameState()->m_unk0x24;
|
if (!p_scorehist) {
|
||||||
m_count++;
|
MxS32 playerScoreRank;
|
||||||
}
|
// LINE: BETA10 0x100870ee
|
||||||
else if (m_scores[19].m_totalScore <= totalScore) {
|
for (playerScoreRank = 0; playerScoreRank < m_count; playerScoreRank++) {
|
||||||
m_scores[19].m_totalScore = totalScore;
|
if (totalScore > m_scores[m_indices[playerScoreRank]].m_totalScore) {
|
||||||
memcpy(m_scores[19].m_scores, scores, sizeof(m_scores[19].m_scores));
|
break;
|
||||||
m_scores[19].m_name = GameState()->m_players[0];
|
|
||||||
m_scores[19].m_unk0x2a = GameState()->m_unk0x24;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// LINE: BETA10 0x1008713f
|
||||||
|
if (playerScoreRank < m_count) {
|
||||||
|
if (m_count < 20) {
|
||||||
|
playerScoreHistoryIndex = m_count++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
playerScoreHistoryIndex = m_indices[19];
|
||||||
|
}
|
||||||
|
|
||||||
MxU8 tmpScores[5][5];
|
MxS32 max = m_count - 1;
|
||||||
Username tmpPlayer;
|
for (MxS32 j = max; playerScoreRank < j; j--) {
|
||||||
MxS16 tmpUnk0x2a;
|
m_indices[j - 1] = m_indices[j - 2];
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Match bubble sort loops
|
m_indices[playerScoreRank] = playerScoreHistoryIndex;
|
||||||
for (MxS32 i = m_count - 1; i > 0; i--) {
|
p_scorehist = &m_scores[playerScoreHistoryIndex];
|
||||||
for (MxS32 j = 1; j <= i; j++) {
|
}
|
||||||
if (m_scores[j - 1].m_totalScore < m_scores[j].m_totalScore) {
|
else if (playerScoreRank < 20) {
|
||||||
memcpy(tmpScores, m_scores[j - 1].m_scores, sizeof(tmpScores));
|
m_indices[m_count] = m_count;
|
||||||
tmpPlayer = m_scores[j - 1].m_name;
|
p_scorehist = &m_scores[m_count++];
|
||||||
tmpUnk0x2a = m_scores[j - 1].m_unk0x2a;
|
}
|
||||||
|
}
|
||||||
|
else if (p_scorehist->m_totalScore != totalScore) {
|
||||||
|
assert(totalScore > p_scorehist->m_totalScore);
|
||||||
|
|
||||||
memcpy(m_scores[j - 1].m_scores, m_scores[j].m_scores, sizeof(m_scores[j - 1].m_scores));
|
for (MxS32 i = playerScoreHistoryIndex; i > 0 && m_indices[i - 1] < m_indices[i]; i--) {
|
||||||
m_scores[j - 1].m_name = m_scores[j].m_name;
|
MxU8 tmp = m_indices[i - 1];
|
||||||
m_scores[j - 1].m_unk0x2a = m_scores[j].m_unk0x2a;
|
m_indices[i - 1] = m_indices[i];
|
||||||
|
m_indices[i] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p_scorehist) {
|
||||||
|
p_scorehist->m_totalScore = totalScore;
|
||||||
|
memcpy(p_scorehist->m_scores[0], scores[0], sizeof(scores));
|
||||||
|
p_scorehist->m_name = GameState()->m_players[0];
|
||||||
|
p_scorehist->m_playerId = GameState()->m_currentPlayerId;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (p_scorehist != NULL) {
|
||||||
|
p_scorehist->m_totalScore = totalScore;
|
||||||
|
memcpy(p_scorehist->m_scores, scores, sizeof(p_scorehist->m_scores));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (m_count < (MxS16) sizeOfArray(m_scores)) {
|
||||||
|
assert(totalScore > p_scorehist->m_totalScore);
|
||||||
|
|
||||||
memcpy(m_scores[j].m_scores, tmpScores, sizeof(m_scores[j].m_scores));
|
m_scores[m_count].m_totalScore = totalScore;
|
||||||
m_scores[j].m_name = tmpPlayer;
|
memcpy(m_scores[m_count].m_scores, scores, sizeof(m_scores[m_count].m_scores));
|
||||||
m_scores[j].m_unk0x2a = tmpUnk0x2a;
|
m_scores[m_count].m_name = GameState()->m_players[0];
|
||||||
}
|
m_scores[m_count].m_playerId = GameState()->m_currentPlayerId;
|
||||||
|
m_count++;
|
||||||
|
}
|
||||||
|
else if (m_scores[19].m_totalScore <= totalScore) {
|
||||||
|
m_scores[19].m_totalScore = totalScore;
|
||||||
|
memcpy(m_scores[19].m_scores, scores, sizeof(m_scores[19].m_scores));
|
||||||
|
m_scores[19].m_name = GameState()->m_players[0];
|
||||||
|
m_scores[19].m_playerId = GameState()->m_currentPlayerId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ScoreItem tmpItem;
|
||||||
|
|
||||||
|
for (MxS32 i = m_count - 1; i >= 0; i--) {
|
||||||
|
for (MxS32 j = 1; j <= i; j++) {
|
||||||
|
if (m_scores[j].m_totalScore > m_scores[j - 1].m_totalScore) {
|
||||||
|
tmpItem = m_scores[j - 1];
|
||||||
|
m_scores[j - 1] = m_scores[j];
|
||||||
|
m_scores[j] = tmpItem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// FUNCTION: LEGO1 0x1003cc90
|
// FUNCTION: LEGO1 0x1003cc90
|
||||||
// FUNCTION: BETA10 0x1008732a
|
// FUNCTION: BETA10 0x1008732a
|
||||||
LegoGameState::ScoreItem* LegoGameState::History::FUN_1003cc90(
|
LegoGameState::ScoreItem* LegoGameState::History::FindPlayerInScoreHistory(
|
||||||
LegoGameState::Username* p_player,
|
LegoGameState::Username* p_player,
|
||||||
MxS16 p_unk0x24,
|
MxS16 p_unk0x24,
|
||||||
MxS32& p_unk0x2c
|
MxS32& p_unk0x2c
|
||||||
@@ -1525,7 +1572,7 @@ LegoGameState::ScoreItem* LegoGameState::History::FUN_1003cc90(
|
|||||||
{
|
{
|
||||||
MxS32 i = 0;
|
MxS32 i = 0;
|
||||||
for (; i < m_count; i++) {
|
for (; i < m_count; i++) {
|
||||||
if (!memcmp(p_player, &m_scores[i].m_name, sizeof(*p_player)) && m_scores[i].m_unk0x2a == p_unk0x24) {
|
if (!memcmp(p_player, &m_scores[i].m_name, sizeof(*p_player)) && m_scores[i].m_playerId == p_unk0x24) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1544,7 +1591,7 @@ LegoGameState::ScoreItem* LegoGameState::History::FUN_1003cc90(
|
|||||||
MxResult LegoGameState::History::Serialize(LegoStorage* p_storage)
|
MxResult LegoGameState::History::Serialize(LegoStorage* p_storage)
|
||||||
{
|
{
|
||||||
if (p_storage->IsReadMode()) {
|
if (p_storage->IsReadMode()) {
|
||||||
p_storage->ReadS16(m_unk0x372);
|
p_storage->ReadS16(m_nextPlayerId);
|
||||||
p_storage->ReadS16(m_count);
|
p_storage->ReadS16(m_count);
|
||||||
|
|
||||||
for (MxS16 i = 0; i < m_count; i++) {
|
for (MxS16 i = 0; i < m_count; i++) {
|
||||||
@@ -1554,7 +1601,7 @@ MxResult LegoGameState::History::Serialize(LegoStorage* p_storage)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (p_storage->IsWriteMode()) {
|
else if (p_storage->IsWriteMode()) {
|
||||||
p_storage->WriteS16(m_unk0x372);
|
p_storage->WriteS16(m_nextPlayerId);
|
||||||
p_storage->WriteS16(m_count);
|
p_storage->WriteS16(m_count);
|
||||||
|
|
||||||
for (MxS16 i = 0; i < m_count; i++) {
|
for (MxS16 i = 0; i < m_count; i++) {
|
||||||
|
Reference in New Issue
Block a user