Skip to content

Commit

Permalink
Added mission display on gameplay scene
Browse files Browse the repository at this point in the history
  • Loading branch information
123jimin committed Jul 20, 2020
1 parent 98e8dc9 commit dab2fff
Show file tree
Hide file tree
Showing 14 changed files with 271 additions and 68 deletions.
2 changes: 1 addition & 1 deletion Main/include/BaseGameSettingsDialog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class BaseGameSettingsDialog
inline int GetCurrentTab() const { return m_currentTab; }
inline void SetCurrentTab(int tabIndex) { m_currentTab = tabIndex; }

String m_message = "";
String m_message = "Press both FXs to open/close. Use the Start button to press buttons.";
Vector2 m_pos = { 0.5f, 0.5f };

private:
Expand Down
3 changes: 3 additions & 0 deletions Main/include/Game.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,7 @@ class Game : public IAsyncLoadableApplicationTickable
virtual const String& GetChartPath() const = 0;
// Is this a multiplayer game
virtual bool IsMultiplayerGame() const = 0;

virtual int GetRetryCount() const = 0;
virtual String GetMissionStr() const = 0;
};
2 changes: 2 additions & 0 deletions Main/include/GameConfig.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ DefineEnum(GameConfigKeys,
PracticeLeadInTime,
PracticeSetupNavEnabled,
RevertToSetupAfterScoreScreen,
DisplayPracticeInfoInGame,
DisplayPracticeInfoInResult,

// Input device setting per element
LaserInputDevice,
Expand Down
47 changes: 39 additions & 8 deletions Main/include/GameFailCondition.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,23 @@ class Scoring;
class GameFailCondition
{
public:
enum class Type
{
None, Score, Grade, Miss, MissAndNear, Gauge
};

const static char* TYPE_STR[6];

GameFailCondition() noexcept = default;
virtual bool IsFailed(const Scoring&) const { return false; }
virtual Type GetType() const { return Type::None; }
virtual int GetThreshold() const { return 0; }
virtual String GetDescription() const { return ""; }

const char* GetName() const { return TYPE_STR[static_cast<unsigned int>(GetType())]; }

public:

// Fails when the max possible score is lower than the given value
class Score;
// Fails when the max possible grade is lower than the given value
Expand All @@ -26,8 +39,10 @@ class GameFailCondition::Score : public GameFailCondition
public:
Score(uint32 score) noexcept : m_score(score) {}
bool IsFailed(const Scoring&) const override;
Type GetType() const override { return Type::Score; }
String GetDescription() const override { return Utility::Sprintf("Score at least %d", m_score); }

uint32 GetMinAllowed() const { return m_score; }
int GetThreshold() const override { return m_score; }

protected:
uint32 m_score;
Expand All @@ -38,8 +53,10 @@ class GameFailCondition::Grade : public GameFailCondition
public:
Grade(GradeMark grade) noexcept : m_grade(grade) {}
bool IsFailed(const Scoring&) const override;
Type GetType() const override { return Type::Grade; }
String GetDescription() const override { return Utility::Sprintf("Grade at least %s", ToDisplayString(m_grade)); }

GradeMark GetMinAllowed() const { return m_grade; }
int GetThreshold() const override { return static_cast<int>(m_grade); }

protected:
GradeMark m_grade;
Expand All @@ -48,22 +65,30 @@ class GameFailCondition::Grade : public GameFailCondition
class GameFailCondition::Gauge : public GameFailCondition
{
public:
Gauge(float gauge) noexcept : m_gauge(gauge) {}
Gauge(uint32 gauge) noexcept : m_gauge(gauge) {}
bool IsFailed(const Scoring&) const override;
Type GetType() const override { return Type::Gauge; }
String GetDescription() const override { return Utility::Sprintf("Gauge at least %d%%", m_gauge); }

float GetMinAllowed() const { return m_gauge; }
int GetThreshold() const override { return static_cast<int>(m_gauge); }

protected:
float m_gauge;
uint32 m_gauge;
};

class GameFailCondition::MissCount : public GameFailCondition
{
public:
MissCount(uint32 count) : m_count(count) {}
bool IsFailed(const Scoring&) const override;
Type GetType() const override { return Type::Miss; }
String GetDescription() const override {
if (m_count == 0) return "No misses";
if (m_count == 1) return "At most one miss";
return Utility::Sprintf("At most %d misses", m_count);
}

uint32 GetMaxAllowed() const { return m_count; }
int GetThreshold() const override { return static_cast<int>(m_count); }

protected:
uint32 m_count;
Expand All @@ -74,9 +99,15 @@ class GameFailCondition::MissAndNearCount : public GameFailCondition
public:
MissAndNearCount(uint32 count) : m_count(count) {}
bool IsFailed(const Scoring&) const override;
Type GetType() const override { return Type::MissAndNear; }
String GetDescription() const override {
if (m_count == 0) return "No misses or nears";
if (m_count == 1) return "At most one miss or near";
return Utility::Sprintf("At most %d misses or nears", m_count);
}

uint32 GetMaxAllowed() const { return m_count; }
int GetThreshold() const override { return static_cast<int>(m_count); }

protected:
uint32 m_count;
};
};
3 changes: 3 additions & 0 deletions Main/include/PracticeModeSettingsDialog.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class PracticeModeSettingsDialog : public BaseGameSettingsDialog

void m_SetStartTime(MapTime time, int measure = -1);
void m_SetEndTime(MapTime time, int measure = -1);

std::unique_ptr<GameFailCondition> m_CreateGameFailCondition(GameFailCondition::Type type);

ChartIndex* m_chartIndex;
Ref<Beatmap> m_beatmap;
Expand All @@ -51,5 +53,6 @@ class PracticeModeSettingsDialog : public BaseGameSettingsDialog
GradeMark m_condGrade = GradeMark::PUC;
int m_condMiss = 0;
int m_condMissNear = 0;
int m_condGauge = 0;
};

6 changes: 6 additions & 0 deletions Main/include/Scoring.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ class Scoring : public Unique
// The score based on the current pace
uint32 CalculateCurrentAverageScore(uint32 currHit, uint32 currMaxHit) const;

inline uint32 GetMisses() const { return categorizedHits[0]; }
inline uint32 GetGoods() const { return categorizedHits[1]; }
inline uint32 GetPerfects() const { return categorizedHits[2]; }
inline bool IsPerfect() const { return GetMisses() == 0 && GetGoods() == 0; }
inline bool IsFullCombo() const { return GetMisses() == 0; }

// Called when a hit is recorded on a given button index (excluding hold notes)
// (Hit Button, Score, Hit Object(optional))
Delegate<Input::Button, ScoreHitRating, ObjectState*, MapTime> OnButtonHit;
Expand Down
119 changes: 98 additions & 21 deletions Main/src/Game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1384,19 +1384,56 @@ class Game_Impl : public Game

if (!m_isPracticeMode) return;

lua_getglobal(m_lua, "practice_end_run");
if (lua_isfunction(m_lua, -1))
if (g_gameConfig.GetBool(GameConfigKeys::DisplayPracticeInfoInGame))
{
lua_pushinteger(m_lua, m_loopCount);
lua_pushinteger(m_lua, m_loopSuccess);
lua_pushboolean(m_lua, success);

if (lua_pcall(m_lua, 3, 0, 0) != 0)
lua_getglobal(m_lua, "practice_end_run");
if (lua_isfunction(m_lua, -1))
{
Logf("Lua error on calling laser_alert: %s", Logger::Severity::Error, lua_tostring(m_lua, -1));
lua_pushinteger(m_lua, m_loopCount);
lua_pushinteger(m_lua, m_loopSuccess);
lua_pushboolean(m_lua, success);

lua_newtable(m_lua);

lua_pushstring(m_lua, "score");
lua_pushinteger(m_lua, m_scoring.CalculateCurrentDisplayScore());
lua_settable(m_lua, -3);

lua_pushstring(m_lua, "perfects");
lua_pushinteger(m_lua, m_scoring.GetPerfects());
lua_settable(m_lua, -3);

lua_pushstring(m_lua, "goods");
lua_pushinteger(m_lua, m_scoring.GetGoods());
lua_settable(m_lua, -3);

lua_pushstring(m_lua, "misses");
lua_pushinteger(m_lua, m_scoring.GetMisses());
lua_settable(m_lua, -3);

lua_pushstring(m_lua, "medianHitDelta");
lua_pushinteger(m_lua, m_scoring.GetMedianHitDelta(false));
lua_settable(m_lua, -3);

lua_pushstring(m_lua, "meanHitDelta");
lua_pushinteger(m_lua, m_scoring.GetMeanHitDelta(false));
lua_settable(m_lua, -3);

lua_pushstring(m_lua, "medianHitDeltaAbs");
lua_pushinteger(m_lua, m_scoring.GetMedianHitDelta(true));
lua_settable(m_lua, -3);

lua_pushstring(m_lua, "meanHitDeltaAbs");
lua_pushinteger(m_lua, m_scoring.GetMeanHitDelta(true));
lua_settable(m_lua, -3);

if (lua_pcall(m_lua, 4, 0, 0) != 0)
{
Logf("Lua error on calling laser_alert: %s", Logger::Severity::Error, lua_tostring(m_lua, -1));
}
}
lua_settop(m_lua, 0);
}
lua_settop(m_lua, 0);
}

// Called when game is finished and the score screen should show up
Expand Down Expand Up @@ -2094,6 +2131,9 @@ class Game_Impl : public Game
if (m_manualExit)
return ClearMark::NotPlayed;

if (m_playOptions.failCondition && m_playOptions.failCondition->IsFailed(m_scoring))
return ClearMark::Played;

ScoreIndex scoreData;
scoreData.miss = m_scoring.categorizedHits[0];
scoreData.almost = m_scoring.categorizedHits[1];
Expand Down Expand Up @@ -2191,6 +2231,9 @@ class Game_Impl : public Game
m_practiceSetupRange = m_playOptions.range;
m_playOptions.range = { 0, 0 };

m_playOptions.loopOnSuccess = false;
m_playOptions.loopOnFail = true;

m_playOnDialogClose = true;
m_triggerPause = true;
}
Expand Down Expand Up @@ -2244,17 +2287,20 @@ class Game_Impl : public Game
m_ended = false;
m_outroCompleted = false;

lua_getglobal(m_lua, "practice_end");
if (lua_isfunction(m_lua, -1))
if (g_gameConfig.GetBool(GameConfigKeys::DisplayPracticeInfoInGame))
{
lua_pushinteger(m_lua, m_loopCount);
lua_pushinteger(m_lua, m_loopSuccess);
if (lua_pcall(m_lua, 2, 0, 0) != 0)
lua_getglobal(m_lua, "practice_end");
if (lua_isfunction(m_lua, -1))
{
Logf("Lua error on calling practice_end: %s", Logger::Severity::Error, lua_tostring(m_lua, -1));
lua_pushinteger(m_lua, m_loopCount);
lua_pushinteger(m_lua, m_loopSuccess);
if (lua_pcall(m_lua, 2, 0, 0) != 0)
{
Logf("Lua error on calling practice_end: %s", Logger::Severity::Error, lua_tostring(m_lua, -1));
}
}
lua_settop(m_lua, 0);
}
lua_settop(m_lua, 0);

JumpTo(m_lastMapTime);

Expand All @@ -2280,15 +2326,30 @@ class Game_Impl : public Game
m_loopCount = 0;
m_loopSuccess = 0;

lua_getglobal(m_lua, "practice_start");
if (lua_isfunction(m_lua, -1))
if (g_gameConfig.GetBool(GameConfigKeys::DisplayPracticeInfoInGame))
{
if (lua_pcall(m_lua, 0, 0, 0) != 0)
lua_getglobal(m_lua, "practice_start");
if (lua_isfunction(m_lua, -1))
{
Logf("Lua error on calling practice_start: %s", Logger::Severity::Error, lua_tostring(m_lua, -1));
if (const auto& failCondition = m_playOptions.failCondition)
{
lua_pushstring(m_lua, failCondition->GetName());
lua_pushinteger(m_lua, failCondition->GetThreshold());
lua_pushstring(m_lua, failCondition->GetDescription().c_str());
}
else
{
lua_pushstring(m_lua, "None");
lua_pushinteger(m_lua, 0);
lua_pushstring(m_lua, "None");
}
if (lua_pcall(m_lua, 3, 0, 0) != 0)
{
Logf("Lua error on calling practice_start: %s", Logger::Severity::Error, lua_tostring(m_lua, -1));
}
}
lua_settop(m_lua, 0);
}
lua_settop(m_lua, 0);

Restart();
}
Expand Down Expand Up @@ -2368,6 +2429,14 @@ class Game_Impl : public Game
{
return m_audioPlayback.GetPlaybackSpeed();
}
virtual int GetRetryCount() const override
{
return m_loopCount;
}
virtual String GetMissionStr() const override
{
return m_playOptions.failCondition ? m_playOptions.failCondition->GetDescription() : "";
}
virtual const String& GetChartRootPath() const
{
return m_chartRootPath;
Expand Down Expand Up @@ -2639,6 +2708,14 @@ class Game_Impl : public Game
lua_pushboolean(L, m_scoring.autoplay);
lua_settable(L, -3);

if (m_isPracticeMode)
{
// Existence of this field implies that the game's in the practice mode.
lua_pushstring(L, "practice_setup");
lua_pushboolean(L, m_isPracticeSetup);
lua_settable(L, -3);
}

//set hidden/sudden
pushFloatToTable("hiddenFade", m_track->hiddenFadewindow);
pushFloatToTable("hiddenCutoff", m_track->hiddenCutoff);
Expand Down
2 changes: 2 additions & 0 deletions Main/src/GameConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ void GameConfig::InitDefaults()
Set(GameConfigKeys::PracticeLeadInTime, 1500);
Set(GameConfigKeys::PracticeSetupNavEnabled, true);
Set(GameConfigKeys::RevertToSetupAfterScoreScreen, false);
Set(GameConfigKeys::DisplayPracticeInfoInGame, true);
Set(GameConfigKeys::DisplayPracticeInfoInResult, true);

SetEnum<Logger::Enum_Severity>(GameConfigKeys::LogLevel, Logger::Severity::Normal);

Expand Down
9 changes: 8 additions & 1 deletion Main/src/GameFailCondition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include "Scoring.hpp"

const char* GameFailCondition::TYPE_STR[6] = { "None", "Score", "Grade", "Miss", "MissAndNear", "Gauge" };

bool GameFailCondition::Score::IsFailed(const Scoring& scoring) const
{
return scoring.CalculateCurrentMaxPossibleScore() < m_score;
Expand All @@ -15,7 +17,12 @@ bool GameFailCondition::Grade::IsFailed(const Scoring& scoring) const

bool GameFailCondition::Gauge::IsFailed(const Scoring& scoring) const
{
return scoring.currentGauge < m_gauge;
if (scoring.IsPerfect()) return false;

if (m_gauge == 0) return false;
if (m_gauge == 100) return scoring.currentGauge < 1.0f;

return scoring.currentGauge * 100 < m_gauge;
}

bool GameFailCondition::MissCount::IsFailed(const Scoring& scoring) const
Expand Down
1 change: 0 additions & 1 deletion Main/src/GameplaySettingsDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

GameplaySettingsDialog::GameplaySettingsDialog()
{
m_message = "Press both FX keys to open/close.";
}

void GameplaySettingsDialog::InitTabs()
Expand Down
Loading

0 comments on commit dab2fff

Please sign in to comment.