Fixed high score insertion for multiple players.

Refactored high_score.
Issue #131.
This commit is contained in:
Muzychenko Andrey 2022-04-11 10:28:20 +03:00
parent 0f88e43ba2
commit cc06d35bc7
5 changed files with 102 additions and 102 deletions

View File

@ -3148,7 +3148,7 @@ void control::GameoverController(int code, TPinballComponent* caller)
if (missionMsg & 0x200) if (missionMsg & 0x200)
{ {
int highscoreId = missionMsg % 5; int highscoreId = missionMsg % 5;
int highScore = pb::highscore_table[highscoreId].Score; int highScore = high_score::highscore_table[highscoreId].Score;
auto nextHidhscoreId = highscoreId + 1; auto nextHidhscoreId = highscoreId + 1;
if (highScore > 0) if (highScore > 0)
{ {

View File

@ -5,136 +5,114 @@
#include "pinball.h" #include "pinball.h"
#include "score.h" #include "score.h"
int high_score::dlg_enter_name; bool high_score::dlg_enter_name;
int high_score::dlg_score;
int high_score::dlg_position;
char high_score::default_name[32]{};
high_score_struct* high_score::dlg_hst;
bool high_score::ShowDialog = false; bool high_score::ShowDialog = false;
high_score_entry high_score::DlgData;
std::vector<high_score_entry> high_score::ScoreQueue;
high_score_struct high_score::highscore_table[5];
int high_score::read()
int high_score::read(high_score_struct* table)
{ {
char Buffer[20]; char Buffer[20];
int checkSum = 0; int checkSum = 0;
clear_table(table); clear_table();
for (auto position = 0; position < 5; ++position) for (auto position = 0; position < 5; ++position)
{ {
auto tablePtr = &table[position]; auto& tablePtr = highscore_table[position];
snprintf(Buffer, sizeof Buffer, "%d", position); snprintf(Buffer, sizeof Buffer, "%d", position);
strcat(Buffer, ".Name"); strcat(Buffer, ".Name");
auto name = options::get_string(Buffer, ""); auto name = options::get_string(Buffer, "");
strncpy(tablePtr->Name, name.c_str(), sizeof tablePtr->Name); strncpy(tablePtr.Name, name.c_str(), sizeof tablePtr.Name);
snprintf(Buffer, sizeof Buffer, "%d", position); snprintf(Buffer, sizeof Buffer, "%d", position);
strcat(Buffer, ".Score"); strcat(Buffer, ".Score");
tablePtr->Score = options::get_int(Buffer, tablePtr->Score); tablePtr.Score = options::get_int(Buffer, tablePtr.Score);
for (int i = static_cast<int>(strlen(tablePtr->Name)); --i >= 0; checkSum += tablePtr->Name[i]) for (int i = static_cast<int>(strlen(tablePtr.Name)); --i >= 0; checkSum += tablePtr.Name[i])
{ {
} }
checkSum += tablePtr->Score; checkSum += tablePtr.Score;
} }
auto verification = options::get_int("Verification", 7); auto verification = options::get_int("Verification", 7);
if (checkSum != verification) if (checkSum != verification)
clear_table(table); clear_table();
return 0; return 0;
} }
int high_score::write(high_score_struct* table) int high_score::write()
{ {
char Buffer[20]; char Buffer[20];
int checkSum = 0; int checkSum = 0;
for (auto position = 0; position < 5; ++position) for (auto position = 0; position < 5; ++position)
{ {
auto tablePtr = &table[position]; auto& tablePtr = highscore_table[position];
snprintf(Buffer, sizeof Buffer, "%d", position); snprintf(Buffer, sizeof Buffer, "%d", position);
strcat(Buffer, ".Name"); strcat(Buffer, ".Name");
options::set_string(Buffer, tablePtr->Name); options::set_string(Buffer, tablePtr.Name);
snprintf(Buffer, sizeof Buffer, "%d", position); snprintf(Buffer, sizeof Buffer, "%d", position);
strcat(Buffer, ".Score"); strcat(Buffer, ".Score");
options::set_int(Buffer, tablePtr->Score); options::set_int(Buffer, tablePtr.Score);
for (int i = static_cast<int>(strlen(tablePtr->Name)); --i >= 0; checkSum += tablePtr->Name[i]) for (int i = static_cast<int>(strlen(tablePtr.Name)); --i >= 0; checkSum += tablePtr.Name[i])
{ {
} }
checkSum += tablePtr->Score; checkSum += tablePtr.Score;
} }
options::set_int("Verification", checkSum); options::set_int("Verification", checkSum);
return 0; return 0;
} }
void high_score::clear_table(high_score_struct* table) void high_score::clear_table()
{ {
for (int index = 5; index; --index) for (auto& table : highscore_table)
{ {
table->Score = -999; table.Score = -999;
table->Name[0] = 0; table.Name[0] = 0;
++table;
} }
} }
int high_score::get_score_position(high_score_struct* table, int score) int high_score::get_score_position(int score)
{ {
if (score <= 0) if (score <= 0)
return -1; return -1;
for (int position = 0; position < 5; position++) for (int position = 0; position < 5; position++)
{ {
if (table[position].Score < score) if (highscore_table[position].Score < score)
return position; return position;
} }
return -1; return -1;
} }
int high_score::place_new_score_into(high_score_struct* table, int score, LPSTR scoreStr, int position) void high_score::place_new_score_into(high_score_entry data)
{ {
if (position >= 0) if (data.Position >= 0 && data.Position < 5)
{ {
if (position <= 4) for (int i = 4; i > data.Position; i--)
{ {
high_score_struct* tablePtr = table + 4; highscore_table[i] = highscore_table[i - 1];
int index = 5 - position;
do
{
--index;
memcpy(tablePtr, &tablePtr[-1], sizeof(high_score_struct));
--tablePtr;
}
while (index);
} }
high_score_struct* posTable = &table[position];
posTable->Score = score; data.Entry.Name[31] = 0;
if (strlen(scoreStr) >= 31) highscore_table[data.Position] = data.Entry;
scoreStr[31] = 0;
strncpy(posTable->Name, scoreStr, sizeof posTable->Name);
posTable->Name[31] = 0;
} }
return position;
} }
void high_score::show_high_score_dialog(high_score_struct* table) void high_score::show_high_score_dialog()
{ {
dlg_enter_name = 0;
dlg_score = 0;
dlg_hst = table;
ShowDialog = true; ShowDialog = true;
} }
void high_score::show_and_set_high_score_dialog(high_score_struct* table, int score, int pos, LPCSTR defaultName) void high_score::show_and_set_high_score_dialog(high_score_entry score)
{ {
dlg_position = pos; ScoreQueue.insert(ScoreQueue.begin(), score);
dlg_score = score;
dlg_hst = table;
dlg_enter_name = 1;
strncpy(default_name, defaultName, sizeof default_name - 1);
ShowDialog = true; ShowDialog = true;
} }
@ -143,12 +121,27 @@ void high_score::RenderHighScoreDialog()
if (ShowDialog == true) if (ShowDialog == true)
{ {
ShowDialog = false; ShowDialog = false;
if (dlg_position == -1) if (!ImGui::IsPopupOpen("High Scores"))
{ {
dlg_enter_name = 0; dlg_enter_name = false;
return; while (!ScoreQueue.empty())
{
DlgData = ScoreQueue.back();
ScoreQueue.pop_back();
if (DlgData.Position < 0 || DlgData.Position > 4)
{
DlgData.Position = get_score_position(DlgData.Entry.Score);
}
if (DlgData.Position != -1)
{
dlg_enter_name = true;
break;
}
}
ImGui::OpenPopup("High Scores");
} }
ImGui::OpenPopup("High Scores");
} }
bool unused_open = true; bool unused_open = true;
@ -169,15 +162,15 @@ void high_score::RenderHighScoreDialog()
snprintf(buf, sizeof buf, "%d", row + 1); snprintf(buf, sizeof buf, "%d", row + 1);
ImGui::TextUnformatted(buf); ImGui::TextUnformatted(buf);
auto currentRow = &dlg_hst[row + offset]; auto currentRow = &highscore_table[row + offset];
auto score = currentRow->Score; auto score = currentRow->Score;
ImGui::TableNextColumn(); ImGui::TableNextColumn();
if (dlg_enter_name == 1 && dlg_position == row) if (dlg_enter_name && DlgData.Position == row)
{ {
offset = -1; offset = -1;
score = dlg_score; score = DlgData.Entry.Score;
ImGui::PushItemWidth(200); ImGui::PushItemWidth(200);
ImGui::InputText("", default_name, IM_ARRAYSIZE(default_name)); ImGui::InputText("", DlgData.Entry.Name, IM_ARRAYSIZE(DlgData.Entry.Name));
} }
else else
{ {
@ -195,8 +188,7 @@ void high_score::RenderHighScoreDialog()
{ {
if (dlg_enter_name) if (dlg_enter_name)
{ {
default_name[31] = 0; place_new_score_into(DlgData);
place_new_score_into(dlg_hst, dlg_score, default_name, dlg_position);
} }
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
@ -213,7 +205,7 @@ void high_score::RenderHighScoreDialog()
ImGui::TextUnformatted(pinball::get_rc_string(40, 0)); ImGui::TextUnformatted(pinball::get_rc_string(40, 0));
if (ImGui::Button("OK", ImVec2(120, 0))) if (ImGui::Button("OK", ImVec2(120, 0)))
{ {
clear_table(dlg_hst); clear_table();
ImGui::CloseCurrentPopup(); ImGui::CloseCurrentPopup();
} }
ImGui::SetItemDefaultFocus(); ImGui::SetItemDefaultFocus();
@ -226,5 +218,11 @@ void high_score::RenderHighScoreDialog()
} }
ImGui::EndPopup(); ImGui::EndPopup();
// Reenter dialog for the next score in the queue
if (!ImGui::IsPopupOpen("High Scores") && !ScoreQueue.empty())
{
ShowDialog = true;
}
} }
} }

View File

@ -6,24 +6,31 @@ struct high_score_struct
int Score; int Score;
}; };
struct high_score_entry
{
high_score_struct Entry;
int Position;
};
class high_score class high_score
{ {
public: public:
static int read(high_score_struct* table); static high_score_struct highscore_table[5];
static int write(high_score_struct* table);
static void clear_table(high_score_struct* table);
static int get_score_position(high_score_struct* table, int score);
static int place_new_score_into(high_score_struct* table, int score, LPSTR scoreStr, int position);
static void show_high_score_dialog(high_score_struct* table); static int read();
static void show_and_set_high_score_dialog(high_score_struct* table, int score, int pos, LPCSTR defaultName); static int write();
static int get_score_position(int score);
static void show_high_score_dialog();
static void show_and_set_high_score_dialog(high_score_entry score);
static void RenderHighScoreDialog(); static void RenderHighScoreDialog();
private : private:
static int dlg_enter_name; static bool dlg_enter_name;
static int dlg_score; static high_score_entry DlgData;
static int dlg_position;
static char default_name[32];
static high_score_struct* dlg_hst;
static bool ShowDialog; static bool ShowDialog;
static std::vector<high_score_entry> ScoreQueue;
static void clear_table();
static void place_new_score_into(high_score_entry data);
}; };

View File

@ -32,7 +32,6 @@ DatFile* pb::record_table = nullptr;
int pb::time_ticks = 0; int pb::time_ticks = 0;
GameModes pb::game_mode = GameModes::GameOver; GameModes pb::game_mode = GameModes::GameOver;
float pb::time_now = 0, pb::time_next = 0, pb::ball_speed_limit, pb::time_ticks_remainder = 0; float pb::time_now = 0, pb::time_next = 0, pb::ball_speed_limit, pb::time_ticks_remainder = 0;
high_score_struct pb::highscore_table[5];
bool pb::FullTiltMode = false, pb::FullTiltDemoMode = false, pb::cheat_mode = false, pb::demo_mode = false; bool pb::FullTiltMode = false, pb::FullTiltDemoMode = false, pb::cheat_mode = false, pb::demo_mode = false;
std::string pb::DatFileName; std::string pb::DatFileName;
@ -98,7 +97,7 @@ int pb::init()
MainTable = new TPinballTable(); MainTable = new TPinballTable();
high_score::read(highscore_table); high_score::read();
ball_speed_limit = MainTable->BallList.at(0)->Offset * 200.0f; ball_speed_limit = MainTable->BallList.at(0)->Offset * 200.0f;
return 0; return 0;
} }
@ -108,7 +107,7 @@ int pb::uninit()
score::unload_msg_font(); score::unload_msg_font();
loader::unload(); loader::unload();
delete record_table; delete record_table;
high_score::write(highscore_table); high_score::write();
delete MainTable; delete MainTable;
MainTable = nullptr; MainTable = nullptr;
timer::uninit(); timer::uninit();
@ -496,10 +495,12 @@ void pb::InputDown(GameInput input)
ball->Acceleration.X = 0.0; ball->Acceleration.X = 0.0;
break; break;
case 'h': case 'h':
char String1[200]; {
strncpy(String1, pinball::get_rc_string(26, 0), sizeof String1 - 1); high_score_struct entry{ {0}, 1000000000 };
high_score::show_and_set_high_score_dialog(highscore_table, 1000000000, 1, String1); strncpy(entry.Name, pinball::get_rc_string(26, 0), sizeof entry.Name - 1);
high_score::show_and_set_high_score_dialog({ entry, 1 });
break; break;
}
case 'r': case 'r':
control::cheat_bump_rank(); control::cheat_bump_rank();
break; break;
@ -522,7 +523,6 @@ void pb::end_game()
{ {
int scores[4]{}; int scores[4]{};
int scoreIndex[4]{}; int scoreIndex[4]{};
char String1[200];
mode_change(GameModes::GameOver); mode_change(GameModes::GameOver);
int playerCount = MainTable->PlayerCount; int playerCount = MainTable->PlayerCount;
@ -556,11 +556,12 @@ void pb::end_game()
{ {
for (auto i = 0; i < playerCount; ++i) for (auto i = 0; i < playerCount; ++i)
{ {
int position = high_score::get_score_position(highscore_table, scores[i]); int position = high_score::get_score_position(scores[i]);
if (position >= 0) if (position >= 0)
{ {
strncpy(String1, pinball::get_rc_string(scoreIndex[i] + 26, 0), sizeof String1 - 1); high_score_struct entry{ {0}, scores[i] };
high_score::show_and_set_high_score_dialog(highscore_table, scores[i], position, String1); strncpy(entry.Name, pinball::get_rc_string(scoreIndex[i] + 26, 0), sizeof entry.Name - 1);
high_score::show_and_set_high_score_dialog({ entry, -1 });
} }
} }
} }
@ -568,7 +569,7 @@ void pb::end_game()
void pb::high_scores() void pb::high_scores()
{ {
high_score::show_high_score_dialog(highscore_table); high_score::show_high_score_dialog();
} }
void pb::tilt_no_more() void pb::tilt_no_more()
@ -583,17 +584,12 @@ bool pb::chk_highscore()
{ {
if (demo_mode) if (demo_mode)
return false; return false;
int playerIndex = MainTable->PlayerCount - 1; for (auto i = 0; i < MainTable->PlayerCount; ++i)
if (playerIndex < 0)
return false;
for (int i = playerIndex;
high_score::get_score_position(highscore_table, MainTable->PlayerScores[i].ScoreStruct->Score) < 0;
--i)
{ {
if (--playerIndex < 0) if (high_score::get_score_position(MainTable->PlayerScores[i].ScoreStruct->Score) >= 0)
return false; return true;
} }
return true; return false;
} }
float pb::collide(float timeNow, float timeDelta, TBall* ball) float pb::collide(float timeNow, float timeDelta, TBall* ball)

View File

@ -45,7 +45,6 @@ public:
static bool cheat_mode; static bool cheat_mode;
static DatFile* record_table; static DatFile* record_table;
static TPinballTable* MainTable; static TPinballTable* MainTable;
static high_score_struct highscore_table[5];
static bool FullTiltMode, FullTiltDemoMode; static bool FullTiltMode, FullTiltDemoMode;
static std::string DatFileName; static std::string DatFileName;