From 5253994f5783535c2347c7fd10a6fc8e5d8a44f6 Mon Sep 17 00:00:00 2001 From: Drewol Date: Wed, 27 Jul 2022 18:39:15 +0200 Subject: [PATCH 01/22] Fix crash on F12 with empty song list --- Main/src/SongSelect.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/Main/src/SongSelect.cpp b/Main/src/SongSelect.cpp index be6f53a9e..38b01f325 100644 --- a/Main/src/SongSelect.cpp +++ b/Main/src/SongSelect.cpp @@ -1559,13 +1559,19 @@ class SongSelect_Impl : public SongSelect } else if (code == SDL_SCANCODE_F12 && m_shiftDown) { - String& hash = m_selectionWheel->GetSelectedChart()->hash; - String replayPath = Path::Normalize(Path::Absolute("replays/" + hash + "/")); - Path::ShowInFileBrowser(replayPath); + ChartIndex* sel = m_selectionWheel->GetSelectedChart(); + if (sel) { + String& hash = sel->hash; + String replayPath = Path::Normalize(Path::Absolute("replays/" + hash + "/")); + Path::ShowInFileBrowser(replayPath); + } } else if (code == SDL_SCANCODE_F12) { - Path::ShowInFileBrowser(m_selectionWheel->GetSelection()->path); + FolderIndex* sel = m_selectionWheel->GetSelection(); + if (sel) { + Path::ShowInFileBrowser(sel->path); + } } else if (code == SDL_SCANCODE_TAB) { From c6ecc7f21d96f0b5dd5a3e276330e250b7b24363 Mon Sep 17 00:00:00 2001 From: Drewol Date: Sat, 17 Sep 2022 13:43:07 +0200 Subject: [PATCH 02/22] Revert "Futile laser tweaks..." This reverts commit 79f7b4b325d722297aeae1411015f6da1352e3f9. --- Main/include/Scoring.hpp | 7 ++----- Main/src/Scoring.cpp | 2 +- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/Main/include/Scoring.hpp b/Main/include/Scoring.hpp index 02e4aa66f..72ddf8a03 100644 --- a/Main/include/Scoring.hpp +++ b/Main/include/Scoring.hpp @@ -317,11 +317,8 @@ class Scoring : public Unique // Decides if the coming tick should be auto completed float m_autoLaserTime[2] = { 0.0f }; const double m_laserDistanceLeniency = 1 / 6.; - const float m_autoLaserDuration = 4.5f / 60.f; - const float m_autoLaserDurationAfterSlam = 8.25f / 60.f; - - //Ehhhh maybe - const MapTime m_offsetLaserConstant = 5; + const float m_autoLaserDuration = 4 / 60.f; + const float m_autoLaserDurationAfterSlam = 8 / 60.f; // Saves the time when a button was hit, used to decide if a button was held before a hold object was active MapTime m_buttonHitTime[6] = { 0, 0, 0, 0, 0, 0 }; diff --git a/Main/src/Scoring.cpp b/Main/src/Scoring.cpp index 3a7fc569d..751394b1c 100755 --- a/Main/src/Scoring.cpp +++ b/Main/src/Scoring.cpp @@ -153,7 +153,7 @@ void Scoring::Reset(const MapTimeRange& range) // Get input offset m_inputOffset = g_gameConfig.GetInt(GameConfigKeys::InputOffset); - m_laserOffset = g_gameConfig.GetInt(GameConfigKeys::LaserOffset) + m_offsetLaserConstant; + m_laserOffset = g_gameConfig.GetInt(GameConfigKeys::LaserOffset); if (m_replay) SetReplayForPlayback(m_replay); From fb239f18e34b50dfcae60c0bdd02c5082f373c57 Mon Sep 17 00:00:00 2001 From: Drewol Date: Sat, 17 Sep 2022 13:44:52 +0200 Subject: [PATCH 03/22] Revert "Merge pull request #454 from ASleepyCat/laser-fix-2" This reverts commit cd86945574917d2dd711c0e8580d70999d3d340c, reversing changes made to afd52a9edc79c532763b335a81d5132342eb1b79. --- Main/src/Scoring.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/Main/src/Scoring.cpp b/Main/src/Scoring.cpp index 751394b1c..36055bf0d 100755 --- a/Main/src/Scoring.cpp +++ b/Main/src/Scoring.cpp @@ -1496,7 +1496,6 @@ void Scoring::m_UpdateLasers(float deltaTime) { MapTime mapTime = m_playback->GetLastTime() + m_laserOffset; bool currentlySlamNextSegmentStraight[2] = { false }; - // Check for new laser segments in laser queue for (auto it = m_laserSegmentQueue.begin(); it != m_laserSegmentQueue.end();) { @@ -1570,6 +1569,7 @@ void Scoring::m_UpdateLasers(float deltaTime) float positionDelta = laserTargetPositions[i] - laserPositions[i]; float laserDir = currentSegment->GetDirection(); float input = m_laserInput[i]; + float inputDir = Math::Sign(input); if (inputDir != 0) { @@ -1605,14 +1605,8 @@ void Scoring::m_UpdateLasers(float deltaTime) timeSinceLaserUsed[i] += deltaTime; // Always snap laser to start sections - auto incomingLaser = m_GetLaserObjectWithinTwoBeats(i); - if (incomingLaser) - { - laserPositions[i] = incomingLaser->points[0]; - m_autoLaserTime[i] = inputDir == incomingLaser->GetDirection() || inputDir == 0 - ? m_autoLaserDuration - : 0; - } + if (m_GetLaserObjectWithinTwoBeats(i)) + m_autoLaserTime[i] = m_autoLaserDuration; } if (currentlySlamNextSegmentStraight[i]) From dbccf3f8dd0f94db2a7fe58f79693253de821edb Mon Sep 17 00:00:00 2001 From: Drewol Date: Sat, 17 Sep 2022 13:45:04 +0200 Subject: [PATCH 04/22] Revert "Merge pull request #453 from ASleepyCat/laser-fix" This reverts commit afd52a9edc79c532763b335a81d5132342eb1b79, reversing changes made to 5284dccd558ce13c8f285e7a32aba5934a2a99bd. --- Main/src/Scoring.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Main/src/Scoring.cpp b/Main/src/Scoring.cpp index 36055bf0d..18b538be9 100755 --- a/Main/src/Scoring.cpp +++ b/Main/src/Scoring.cpp @@ -1301,6 +1301,7 @@ void Scoring::m_UpdateGauges(ScoreHitRating rating, TickFlags flags) return; } + bool isLong = (flags & TickFlags::Hold) != TickFlags::None || ((flags & TickFlags::Laser) != TickFlags::None && (flags & TickFlags::Slam) == TickFlags::None); @@ -1588,8 +1589,11 @@ void Scoring::m_UpdateLasers(float deltaTime) } positionDelta = laserTargetPositions[i] - laserPositions[i]; - if ((inputDir == laserDir || laserDir == 0) && fabsf(positionDelta) <= m_laserDistanceLeniency) - m_autoLaserTime[i] = m_autoLaserDuration; + if (inputDir == laserDir || laserDir == 0) + { + if (fabsf(positionDelta) <= m_laserDistanceLeniency) + m_autoLaserTime[i] = m_autoLaserDuration; + } else m_autoLaserTime[i] -= deltaTime; } From e6336b454c91a77592a5ce9d119c67dc1978497c Mon Sep 17 00:00:00 2001 From: Drewol Date: Sat, 17 Sep 2022 13:59:55 +0200 Subject: [PATCH 05/22] Revert "Merge pull request #434 from ASleepyCat/laser-changes" This reverts commit 65264290c0e17aaf33b267285974545dabb21475, reversing changes made to f9754f4e91b1f2000a3a0813dfbe144cd64b371f. --- Beatmap/include/Beatmap/MapDatabase.hpp | 1 - Beatmap/src/MapDatabase.cpp | 1 - Main/include/ChallengeSelect.hpp | 1 - Main/include/GameConfig.hpp | 5 +- Main/include/HitStat.hpp | 15 +- Main/include/Scoring.hpp | 19 +- Main/src/ChallengeResult.cpp | 2 +- Main/src/Game.cpp | 7 +- Main/src/GameConfig.cpp | 11 +- Main/src/GameplaySettingsDialog.cpp | 3 +- Main/src/HitStat.cpp | 5 +- Main/src/ScoreScreen.cpp | 3 +- Main/src/Scoring.cpp | 219 ++++++++++++++++-------- Main/src/SettingsScreen.cpp | 17 +- 14 files changed, 203 insertions(+), 106 deletions(-) diff --git a/Beatmap/include/Beatmap/MapDatabase.hpp b/Beatmap/include/Beatmap/MapDatabase.hpp index 7149933a2..8dd4e8d2b 100644 --- a/Beatmap/include/Beatmap/MapDatabase.hpp +++ b/Beatmap/include/Beatmap/MapDatabase.hpp @@ -47,7 +47,6 @@ struct ScoreIndex int32 hitWindowGood; int32 hitWindowHold; int32 hitWindowMiss; - int32 hitWindowSlam; }; diff --git a/Beatmap/src/MapDatabase.cpp b/Beatmap/src/MapDatabase.cpp index 1d104591e..2d2b5c85c 100644 --- a/Beatmap/src/MapDatabase.cpp +++ b/Beatmap/src/MapDatabase.cpp @@ -1575,7 +1575,6 @@ class MapDatabase_Impl "window_good INTEGER," "window_hold INTEGER," "window_miss INTEGER," - "window_slam INTEGER," "chart_hash TEXT)"); m_database.Exec("CREATE TABLE Collections" diff --git a/Main/include/ChallengeSelect.hpp b/Main/include/ChallengeSelect.hpp index 1cea0a537..9baa3ff3b 100644 --- a/Main/include/ChallengeSelect.hpp +++ b/Main/include/ChallengeSelect.hpp @@ -107,7 +107,6 @@ struct ChallengeOptions{ v(uint32, crit_judge) \ v(uint32, near_judge) \ v(uint32, hold_judge) \ - v(uint32, slam_judge) \ v(bool, allow_cmod) \ v(bool, allow_excessive) \ v(bool, allow_blastive) \ diff --git a/Main/include/GameConfig.hpp b/Main/include/GameConfig.hpp index 861993f26..fd6c81304 100644 --- a/Main/include/GameConfig.hpp +++ b/Main/include/GameConfig.hpp @@ -39,7 +39,6 @@ DefineEnum(GameConfigKeys, HitWindowPerfect, HitWindowGood, HitWindowHold, - HitWindowSlam, HiSpeed, SpeedMod, ModSpeed, @@ -53,6 +52,10 @@ DefineEnum(GameConfigKeys, Laser0Color, Laser1Color, FPSTarget, + LaserAssistLevel, + LaserPunish, + LaserChangeTime, + LaserChangeExponent, GaugeDrainNormal, GaugeDrainHalf, ResponsiveInputs, diff --git a/Main/include/HitStat.hpp b/Main/include/HitStat.hpp index fcfb84307..ad9aa0066 100644 --- a/Main/include/HitStat.hpp +++ b/Main/include/HitStat.hpp @@ -38,33 +38,32 @@ struct HitWindow enum class Type { None = 0, Normal, Hard }; inline HitWindow(MapTime perfect, MapTime good) noexcept : perfect(perfect), good(good) { Validate(); } - inline HitWindow(MapTime perfect, MapTime good, MapTime hold, MapTime slam) noexcept : perfect(perfect), good(good), hold(hold), slam(slam) { Validate(); } - inline HitWindow(const HitWindow& that) noexcept : perfect(that.perfect), good(that.good), hold(that.hold), miss(that.miss), slam(that.slam) { Validate(); } + inline HitWindow(MapTime perfect, MapTime good, MapTime hold) noexcept : perfect(perfect), good(good), hold(hold) { Validate(); } + inline HitWindow(const HitWindow& that) noexcept : perfect(that.perfect), good(that.good), hold(that.hold), miss(that.miss) { Validate(); } static HitWindow FromConfig(); void SaveConfig() const; void ToLuaTable(struct lua_State* L) const; - inline HitWindow& operator= (const HitWindow& that) noexcept { perfect = that.perfect; good = that.good; hold = that.hold; miss = that.miss; slam = that.slam; return *this; } + inline HitWindow& operator= (const HitWindow& that) noexcept { perfect = that.perfect; good = that.good; hold = that.hold; miss = that.miss; return *this; } - constexpr bool operator== (const HitWindow& that) const noexcept { return perfect == that.perfect && good == that.good && hold == that.hold && miss == that.miss && slam == that.slam; } - constexpr bool operator<= (const HitWindow& that) const noexcept { return perfect <= that.perfect && good <= that.good && hold <= that.hold && miss <= that.miss && slam <= that.slam; } + constexpr bool operator== (const HitWindow& that) const noexcept { return perfect == that.perfect && good == that.good && hold == that.hold && miss == that.miss; } + constexpr bool operator<= (const HitWindow& that) const noexcept { return perfect <= that.perfect && good <= that.good && hold <= that.hold && miss <= that.miss; } constexpr Type GetType() const noexcept { if (*this <= HARD) return Type::Hard; else if (*this <= NORMAL) return Type::Normal; else return Type::None; } inline bool Validate() { - if (perfect <= good && good <= hold && hold <= miss && slam <= NORMAL.slam && miss <= NORMAL.miss) + if (perfect <= good && good <= hold && hold <= miss && miss <= NORMAL.miss) return true; - Logf("Invalid timing window: %d/%d/%d/%d/%d", Logger::Severity::Warning, perfect, good, hold, slam, miss); + Logf("Invalid timing window: %d/%d/%d/%d", Logger::Severity::Warning, perfect, good, hold, miss); if (miss > NORMAL.miss) miss = NORMAL.miss; if (hold > miss) hold = miss; if (good > hold) good = hold; if (perfect > good) perfect = good; - if (slam > NORMAL.slam) slam = NORMAL.slam; return false; } diff --git a/Main/include/Scoring.hpp b/Main/include/Scoring.hpp index 72ddf8a03..385dcacdf 100644 --- a/Main/include/Scoring.hpp +++ b/Main/include/Scoring.hpp @@ -37,6 +37,10 @@ struct ScoreTick ScoreTick() = default; ScoreTick(ObjectState* object) : object(object) {}; + // Returns the time frame in which this tick can be hit + MapTime GetHitWindow(const HitWindow& hitWindow) const; + // Hit rating when hitting object at given time + ScoreHitRating GetHitRating(const HitWindow& hitWindow, MapTime currentTime) const; // Hit rating when hitting object give a delta ScoreHitRating GetHitRatingFromDelta(const HitWindow& hitWindow, MapTime delta) const; // Check a flag @@ -233,6 +237,8 @@ class Scoring : public Unique struct AutoplayInfo autoplayInfo; + float laserDistanceLeniency = 1.0f / 12.0f; + // Actual positions of the laser float laserPositions[2]; // Sampled target position of the lasers in the map @@ -299,8 +305,6 @@ class Scoring : public Unique HitStat* m_AddOrUpdateHitStat(ObjectState* object); void m_CleanupHitStats(); - LaserObjectState* m_GetLaserObjectWithinTwoBeats(uint8 index); - // Updates laser output with or without interpolation bool m_interpolateLaserOutput = false; @@ -315,10 +319,7 @@ class Scoring : public Unique // Input values for laser [-1,1] float m_laserInput[2] = { 0.0f }; // Decides if the coming tick should be auto completed - float m_autoLaserTime[2] = { 0.0f }; - const double m_laserDistanceLeniency = 1 / 6.; - const float m_autoLaserDuration = 4 / 60.f; - const float m_autoLaserDurationAfterSlam = 8 / 60.f; + float m_autoLaserTime[2] = { 0,0 }; // Saves the time when a button was hit, used to decide if a button was held before a hold object was active MapTime m_buttonHitTime[6] = { 0, 0, 0, 0, 0, 0 }; @@ -326,6 +327,12 @@ class Scoring : public Unique // Saves the time when a button was hit or released for bounce guarding MapTime m_buttonGuardTime[6] = { 0, 0, 0, 0, 0, 0 }; + // Max number of ticks to assist + float m_assistLevel = 1.5f; + float m_assistPunish = 1.5f; + float m_assistChangePeriod = 50.0f; + float m_assistChangeExponent = 1.0f; + float m_assistTime = 0.0f; // Offet to use for calculating judge (ms) int32 m_inputOffset = 0; int32 m_laserOffset = 0; diff --git a/Main/src/ChallengeResult.cpp b/Main/src/ChallengeResult.cpp index ff34c00bf..7c7b04f96 100644 --- a/Main/src/ChallengeResult.cpp +++ b/Main/src/ChallengeResult.cpp @@ -203,7 +203,7 @@ class ChallengeResultScreen_Impl : public ChallengeResultScreen m_PushIntToTable("timestamp", score->timestamp); m_PushIntToTable("badge", static_cast(Scoring::CalculateBadge(*score))); lua_pushstring(m_lua, "hitWindow"); - HitWindow(score->hitWindowPerfect, score->hitWindowGood, score->hitWindowHold, score->hitWindowSlam).ToLuaTable(m_lua); + HitWindow(score->hitWindowPerfect, score->hitWindowGood, score->hitWindowHold).ToLuaTable(m_lua); lua_settable(m_lua, -3); lua_settable(m_lua, -3); } diff --git a/Main/src/Game.cpp b/Main/src/Game.cpp index d5f5a1345..90903ebde 100755 --- a/Main/src/Game.cpp +++ b/Main/src/Game.cpp @@ -320,9 +320,6 @@ class Game_Impl : public Game ), m_challengeManager->GetCurrentOptions().hold_judge.Get( g_gameConfig.GetInt(GameConfigKeys::HitWindowHold) - ), - m_challengeManager->GetCurrentOptions().slam_judge.Get( - g_gameConfig.GetInt(GameConfigKeys::HitWindowSlam) ) ); } @@ -371,6 +368,10 @@ class Game_Impl : public Game ) { replay = m_replayForPlayback; + replayReader.Serialize(&(replay.hitWindow.perfect), 4); + replayReader.Serialize(&(replay.hitWindow.good), 4); + replayReader.Serialize(&(replay.hitWindow.hold), 4); + replayReader.Serialize(&(replay.hitWindow.miss), 4); } } if (!replay) diff --git a/Main/src/GameConfig.cpp b/Main/src/GameConfig.cpp index c19551914..c7c1848e0 100644 --- a/Main/src/GameConfig.cpp +++ b/Main/src/GameConfig.cpp @@ -3,7 +3,6 @@ #include "Shared/Log.hpp" #include "HitStat.hpp" -#include "Input.hpp" // When this should change, the UpdateVersion MUST be updated to update the old config files. // If there's no need to update the UpdateVersion, there's no need to touch this too. @@ -78,12 +77,15 @@ void GameConfig::InitDefaults() Set(GameConfigKeys::HitWindowPerfect, HitWindow::NORMAL.perfect); Set(GameConfigKeys::HitWindowGood, HitWindow::NORMAL.good); Set(GameConfigKeys::HitWindowHold, HitWindow::NORMAL.hold); - Set(GameConfigKeys::HitWindowSlam, HitWindow::NORMAL.slam); Set(GameConfigKeys::HiSpeed, 1.0f); Set(GameConfigKeys::GlobalOffset, 0); Set(GameConfigKeys::InputOffset, 0); Set(GameConfigKeys::LaserOffset, 0); Set(GameConfigKeys::FPSTarget, 0); + Set(GameConfigKeys::LaserAssistLevel, 1.05f); + Set(GameConfigKeys::LaserPunish, 1.7f); + Set(GameConfigKeys::LaserChangeTime, 100.0f); + Set(GameConfigKeys::LaserChangeExponent, 1.5f); Set(GameConfigKeys::GaugeDrainNormal, 180); Set(GameConfigKeys::GaugeDrainHalf, 300); Set(GameConfigKeys::ModSpeed, 300.0f); @@ -347,10 +349,13 @@ ConfigBase::KeyList GameConfigProfileSettings = { Key(HitWindowPerfect), Key(HitWindowGood), Key(HitWindowHold), - Key(HitWindowSlam), Key(GlobalOffset), Key(InputOffset), Key(LaserOffset), + Key(LaserAssistLevel), + Key(LaserPunish), + Key(LaserChangeTime), + Key(LaserChangeExponent), Key(HiddenCutoff), Key(HiddenFade), diff --git a/Main/src/GameplaySettingsDialog.cpp b/Main/src/GameplaySettingsDialog.cpp index a3c95fe43..2e09fe1ef 100644 --- a/Main/src/GameplaySettingsDialog.cpp +++ b/Main/src/GameplaySettingsDialog.cpp @@ -63,10 +63,9 @@ void GameplaySettingsDialog::InitTabs() Tab judgeWindowTab = std::make_unique(); judgeWindowTab->name = "Judgement"; - judgeWindowTab->settings.push_back(CreateIntSetting(GameConfigKeys::HitWindowPerfect, "Crit Window", { 0, HitWindow::NORMAL.perfect })); + judgeWindowTab->settings.push_back(CreateIntSetting(GameConfigKeys::HitWindowPerfect, "Crit Window", {0, HitWindow::NORMAL.perfect})); judgeWindowTab->settings.push_back(CreateIntSetting(GameConfigKeys::HitWindowGood, "Near Window", { 0, HitWindow::NORMAL.good })); judgeWindowTab->settings.push_back(CreateIntSetting(GameConfigKeys::HitWindowHold, "Hold Window", { 0, HitWindow::NORMAL.hold })); - judgeWindowTab->settings.push_back(CreateIntSetting(GameConfigKeys::HitWindowSlam, "Slam Window", { 0, HitWindow::NORMAL.slam })); judgeWindowTab->settings.push_back(CreateButton("Set to NORMAL", [](const auto&) { HitWindow::NORMAL.SaveConfig(); })); judgeWindowTab->settings.push_back(CreateButton("Set to HARD", [](const auto&) { HitWindow::HARD.SaveConfig(); })); diff --git a/Main/src/HitStat.cpp b/Main/src/HitStat.cpp index 38b41f989..d9fdc19b5 100644 --- a/Main/src/HitStat.cpp +++ b/Main/src/HitStat.cpp @@ -21,8 +21,7 @@ HitWindow HitWindow::FromConfig() HitWindow hitWindow = HitWindow( g_gameConfig.GetInt(GameConfigKeys::HitWindowPerfect), g_gameConfig.GetInt(GameConfigKeys::HitWindowGood), - g_gameConfig.GetInt(GameConfigKeys::HitWindowHold), - g_gameConfig.GetInt(GameConfigKeys::HitWindowSlam) + g_gameConfig.GetInt(GameConfigKeys::HitWindowHold) ); if (!(hitWindow <= HitWindow::NORMAL)) @@ -40,7 +39,6 @@ void HitWindow::SaveConfig() const g_gameConfig.Set(GameConfigKeys::HitWindowPerfect, perfect); g_gameConfig.Set(GameConfigKeys::HitWindowGood, good); g_gameConfig.Set(GameConfigKeys::HitWindowHold, hold); - g_gameConfig.Set(GameConfigKeys::HitWindowSlam, slam); } void HitWindow::ToLuaTable(lua_State* L) const @@ -58,5 +56,4 @@ void HitWindow::ToLuaTable(lua_State* L) const pushIntToTable("good", good); pushIntToTable("hold", hold); pushIntToTable("miss", miss); - pushIntToTable("slam", slam); } diff --git a/Main/src/ScoreScreen.cpp b/Main/src/ScoreScreen.cpp index 038e17b98..0c85e9aad 100644 --- a/Main/src/ScoreScreen.cpp +++ b/Main/src/ScoreScreen.cpp @@ -342,7 +342,6 @@ class ScoreScreen_Impl : public ScoreScreen newScore->hitWindowGood = m_hitWindow.good; newScore->hitWindowHold = m_hitWindow.hold; newScore->hitWindowMiss = m_hitWindow.miss; - newScore->hitWindowSlam = m_hitWindow.slam; m_mapDatabase.AddScore(newScore); @@ -917,7 +916,7 @@ class ScoreScreen_Impl : public ScoreScreen m_PushStringToTable("playerName", *score->userName); m_PushIntToTable("isLocal", score->localScore); lua_pushstring(m_lua, "hitWindow"); - HitWindow(score->hitWindowPerfect, score->hitWindowGood, score->hitWindowHold, score->hitWindowSlam).ToLuaTable(m_lua); + HitWindow(score->hitWindowPerfect, score->hitWindowGood, score->hitWindowHold).ToLuaTable(m_lua); lua_settable(m_lua, -3); lua_settable(m_lua, -3); } diff --git a/Main/src/Scoring.cpp b/Main/src/Scoring.cpp index 18b538be9..a43666c7c 100755 --- a/Main/src/Scoring.cpp +++ b/Main/src/Scoring.cpp @@ -137,6 +137,7 @@ void Scoring::Reset(const MapTimeRange& range) currentComboCounter = 0; maxComboCounter = 0; comboState = 2; + m_assistTime = m_assistLevel * 0.1f; // Reset laser positions laserTargetPositions[0] = 0.0f; @@ -160,6 +161,11 @@ void Scoring::Reset(const MapTimeRange& range) // Get bounce guard duration m_bounceGuard = g_gameConfig.GetInt(GameConfigKeys::InputBounceGuard); + // Get laser assist level + m_assistLevel = g_gameConfig.GetFloat(GameConfigKeys::LaserAssistLevel); + m_assistPunish = g_gameConfig.GetFloat(GameConfigKeys::LaserPunish); + m_assistChangeExponent = g_gameConfig.GetFloat(GameConfigKeys::LaserChangeExponent); + m_assistChangePeriod = g_gameConfig.GetFloat(GameConfigKeys::LaserChangeTime); // Recalculate maximum score mapTotals = CalculateMapTotals(); @@ -346,26 +352,21 @@ float Scoring::GetLaserRollOutput(uint32 index) { return GetLaserPosition(index, laserTargetPositions[index]); } - // Check if any upcoming lasers are within 2 beats - LaserObjectState* l = m_GetLaserObjectWithinTwoBeats(index); - if (l) - return GetLaserPosition(index, l->points[0]); - return 0.0f; -} - -LaserObjectState* Scoring::m_GetLaserObjectWithinTwoBeats(uint8 index) -{ - for (auto l : m_laserSegmentQueue) + else // Check if any upcoming lasers are within 2 beats { - if (l->index == index && m_IsRoot(l)) + for (auto l : m_laserSegmentQueue) { - if (l->time - m_playback->GetLastTime() <= m_playback->GetCurrentTimingPoint().beatDuration * 2) + if (l->index == index && m_IsRoot(l)) { - return l; + if (l->time - m_playback->GetLastTime() <= m_playback->GetCurrentTimingPoint().beatDuration * 2) + { + return GetLaserPosition(index, l->points[0]); + } } } + } - return nullptr; + return 0.0f; } bool Scoring::GetLaserActive() @@ -1000,7 +1001,7 @@ void Scoring::m_UpdateTicks() // Buttons are handled entirely by m_ConsumeTick, this is here to make sure auto doesn't get misses if (tick->HasFlag(TickFlags::Button) && autoplayInfo.IsAutoplayButtons()) { - m_TickHit(tick, buttonCode); + m_TickHit(tick, buttonCode, 0); processed = true; } @@ -1060,16 +1061,25 @@ void Scoring::m_UpdateTicks() } else { + // Snap to first laser tick + /// TODO: Find better solution + if (tick->HasFlag(TickFlags::Start)) + { + laserPositions[laserObject->index] = laserTargetPositions[laserObject->index]; + m_autoLaserTime[laserObject->index] = m_assistTime; + } + // Check laser input uint8 index = laserObject->index; float laserDelta = fabs(laserPositions[index] - laserTargetPositions[index]); - if (autoplayInfo.autoplay || laserDelta <= m_laserDistanceLeniency) + if (autoplayInfo.autoplay || laserDelta <= laserDistanceLeniency) { m_TickHit(tick, buttonCode); HitStat* stat = new HitStat(tick->object); stat->time = tick->time; stat->rating = ScoreHitRating::Perfect; hitStats.Add(stat); + processed = true; } else { @@ -1244,13 +1254,14 @@ void Scoring::m_TickHit(ScoreTick* tick, uint32 index, MapTime delta /*= 0*/) else if (tick->HasFlag(TickFlags::Laser)) { LaserObjectState* object = (LaserObjectState*)tick->object; + LaserObjectState* rootObject = ((LaserObjectState*)tick->object)->GetRoot(); if (tick->HasFlag(TickFlags::Slam)) { OnLaserSlamHit.Call((LaserObjectState*)tick->object); // Set laser pointer position after hitting slam laserTargetPositions[object->index] = object->points[1]; laserPositions[object->index] = object->points[1]; - m_autoLaserTime[object->index] = m_autoLaserDurationAfterSlam; + m_autoLaserTime[object->index] = m_assistTime; } m_AddScore(2); @@ -1284,6 +1295,9 @@ void Scoring::m_TickMiss(ScoreTick* tick, uint32 index, MapTime delta) } else if (tick->HasFlag(TickFlags::Laser)) { + LaserObjectState* obj = (LaserObjectState*)tick->object; + + m_autoLaserTime[obj->index] = -1.f; stat->rating = ScoreHitRating::Miss; } @@ -1497,51 +1511,73 @@ void Scoring::m_UpdateLasers(float deltaTime) { MapTime mapTime = m_playback->GetLastTime() + m_laserOffset; bool currentlySlamNextSegmentStraight[2] = { false }; - // Check for new laser segments in laser queue - for (auto it = m_laserSegmentQueue.begin(); it != m_laserSegmentQueue.end();) - { - // Reset laser usage timer - timeSinceLaserUsed[(*it)->index] = 0; - if ((*it)->time <= mapTime) + m_assistTime = m_assistLevel * 0.1f; + + for (uint32 i = 0; i < 2; i++) + { + // Check for new laser segments in laser queue + for (auto it = m_laserSegmentQueue.begin(); it != m_laserSegmentQueue.end();) { - const uint8 index = (*it)->index; - // Replace the currently active segment - m_currentLaserSegments[index] = *it; - auto current = m_currentLaserSegments[index]; - if (current != nullptr) + // Reset laser usage timer + timeSinceLaserUsed[(*it)->index] = 0.0f; + + if ((*it)->time <= mapTime) { - // Auto lasers unless current segment is a slam and the next is a straight laser - if (current->next && current->next->GetDirection() == 0 && current->flags & LaserObjectState::flag_Instant) - currentlySlamNextSegmentStraight[index] = true; + auto current = m_currentLaserSegments[(*it)->index]; + auto& currentTicks = m_ticks[6 + (*it)->index]; + if (!currentTicks.empty() && current != nullptr) + { + auto tick = currentTicks.front(); + if ((current->flags & LaserObjectState::flag_Instant) != 0) + { + if ((LaserObjectState*)tick->object == current) { + // Don't continue to next segment before the slam has been decided as hit or not + it++; + continue; + } + } + } + // Replace the currently active segment + m_currentLaserSegments[(*it)->index] = *it; + if (m_currentLaserSegments[(*it)->index]->prev && m_currentLaserSegments[(*it)->index]->GetDirection() != m_currentLaserSegments[(*it)->index]->prev->GetDirection()) + { + //Direction change + //m_autoLaserTime[(*it)->index] = -1; + } + + it = m_laserSegmentQueue.erase(it); + continue; } - it = m_laserSegmentQueue.erase(it); - continue; + it++; } - it++; - } - for (uint32 i = 0; i < 2; i++) - { LaserObjectState* currentSegment = m_currentLaserSegments[i]; if (currentSegment) { lasersAreExtend[i] = (currentSegment->flags & LaserObjectState::flag_Extended) != 0; + MapTime duration = currentSegment->duration; - if (currentSegment->time + currentSegment->duration < mapTime) + if ((currentSegment->time + currentSegment->duration) < mapTime) { - // Apply laser roll ignore when the laser has scrolled past - if (!(currentSegment->flags & LaserObjectState::flag_Instant) && !currentSegment->next) - OnLaserExit.Call(currentSegment); - currentSegment = nullptr; - m_currentLaserSegments[i] = nullptr; - for (auto o : m_laserSegmentQueue) + auto currentTicks = m_ticks[6 + i]; + if ((currentSegment->flags & LaserObjectState::flag_Instant) == 0 + || currentTicks.empty() + || (LaserObjectState*)currentTicks.front()->object != currentSegment) // Don't null slam that hasn't been judged yet { - if (o->index == i) + // Apply laser roll ignore when the laser has scrolled past + if (!(currentSegment->flags & LaserObjectState::flag_Instant) && !currentSegment->next) + OnLaserExit.Call(currentSegment); + currentSegment = nullptr; + m_currentLaserSegments[i] = nullptr; + for (auto o : m_laserSegmentQueue) { - laserTargetPositions[i] = o->points[0]; - lasersAreExtend[i] = o->flags & LaserObjectState::flag_Extended; - break; + if (o->index == i) + { + laserTargetPositions[i] = o->points[0]; + lasersAreExtend[i] = o->flags & LaserObjectState::flag_Extended; + break; + } } } } @@ -1568,19 +1604,38 @@ void Scoring::m_UpdateLasers(float deltaTime) { // Update laser gameplay float positionDelta = laserTargetPositions[i] - laserPositions[i]; + float moveDir = Math::Sign(positionDelta); float laserDir = currentSegment->GetDirection(); float input = m_laserInput[i]; float inputDir = Math::Sign(input); - if (inputDir != 0) + // Always snap laser to start sections if they are completely vertical + if (laserDir == 0.0f && m_IsRoot(currentSegment)) + { + laserPositions[i] = laserTargetPositions[i]; + m_autoLaserTime[i] = m_assistTime; + } + // Lock lasers on straight parts + else if (laserDir == 0.0f && fabs(positionDelta) < laserDistanceLeniency) + { + laserPositions[i] = laserTargetPositions[i]; + m_autoLaserTime[i] = m_assistTime; + } + else if (inputDir != 0.0f) { if (laserDir < 0 && positionDelta < 0) + { laserPositions[i] = Math::Max(laserPositions[i] + input, laserTargetPositions[i]); + } else if (laserDir > 0 && positionDelta > 0) + { laserPositions[i] = Math::Min(laserPositions[i] + input, laserTargetPositions[i]); + } else if ((laserDir < 0 && positionDelta > 0) || (laserDir > 0 && positionDelta < 0)) - laserPositions[i] += input; - else if (laserDir == 0) + { + laserPositions[i] = laserPositions[i] + input; + } + else if (laserDir == 0.0f) { if (positionDelta > 0) laserPositions[i] = Math::Min(laserPositions[i] + input, laserTargetPositions[i]); @@ -1588,29 +1643,33 @@ void Scoring::m_UpdateLasers(float deltaTime) laserPositions[i] = Math::Max(laserPositions[i] + input, laserTargetPositions[i]); } - positionDelta = laserTargetPositions[i] - laserPositions[i]; - if (inputDir == laserDir || laserDir == 0) + + + float punishMult = 1.0f; + //if next segment is the opposite direction then allow for some extra wrong turning + MapTime dirChangeTime = currentSegment->GetTimeToDirectionChange(mapTime, m_assistChangePeriod); + if (dirChangeTime > -1) { - if (fabsf(positionDelta) <= m_laserDistanceLeniency) - m_autoLaserTime[i] = m_autoLaserDuration; + punishMult = Math::Clamp((float)dirChangeTime / m_assistChangePeriod, 0.0f, 1.0f); + punishMult = powf(punishMult, m_assistChangeExponent); + } + + if (inputDir == moveDir && fabs(positionDelta) < laserDistanceLeniency) + { + m_autoLaserTime[i] = m_assistTime; + } + if (inputDir != 0 && inputDir != laserDir) + { + m_autoLaserTime[i] -= deltaTime * m_assistPunish * punishMult; + //m_autoLaserTime[i] = Math::Min(m_autoLaserTime[i], m_assistTime * 0.2f); } - else - m_autoLaserTime[i] -= deltaTime; } - // Lock lasers on straight parts - else if (laserDir == 0 && fabsf(positionDelta) <= m_laserDistanceLeniency) - m_autoLaserTime[i] = m_autoLaserDuration; - else - m_autoLaserTime[i] -= deltaTime; - timeSinceLaserUsed[i] = 0; + timeSinceLaserUsed[i] = 0.0f; } else { timeSinceLaserUsed[i] += deltaTime; - - // Always snap laser to start sections - if (m_GetLaserObjectWithinTwoBeats(i)) - m_autoLaserTime[i] = m_autoLaserDuration; + //laserPositions[i] = laserTargetPositions[i]; } if (currentlySlamNextSegmentStraight[i]) @@ -1627,10 +1686,15 @@ void Scoring::m_UpdateLasers(float deltaTime) // Clamp cursor between 0 and 1 laserPositions[i] = Math::Clamp(laserPositions[i], 0.0f, 1.0f); - if (fabsf(laserPositions[i] - laserTargetPositions[i]) <= m_laserDistanceLeniency && currentSegment) + m_autoLaserTime[i] -= deltaTime; + if (fabsf(laserPositions[i] - laserTargetPositions[i]) < laserDistanceLeniency && currentSegment) + { m_SetHoldObject(*currentSegment->GetRoot(), 6 + i); + } else + { m_ReleaseHoldObject(6 + i); + } } // Interpolate laser output @@ -1806,6 +1870,25 @@ bool Scoring::HoldObjectAvailable(uint32 index, bool checkIfPassedCritLine) return withinHoldStartWindow || holdObjectHittable; } +MapTime ScoreTick::GetHitWindow(const HitWindow& hitWindow) const +{ + // Hold ticks don't have a hit window, but the first ones do + if (HasFlag(TickFlags::Hold) && !HasFlag(TickFlags::Start)) + return 0; + // Laser ticks also don't have a hit window except for the first ticks and slam segments + if (HasFlag(TickFlags::Laser)) + { + if (!HasFlag(TickFlags::Start) && !HasFlag(TickFlags::Slam)) + return 0; + return hitWindow.perfect; + } + return hitWindow.miss; +} +ScoreHitRating ScoreTick::GetHitRating(const HitWindow& hitWindow, MapTime currentTime) const +{ + const MapTime delta = abs(time - currentTime); + return GetHitRatingFromDelta(hitWindow, delta); +} ScoreHitRating ScoreTick::GetHitRatingFromDelta(const HitWindow& hitWindow, MapTime delta) const { delta = abs(delta); diff --git a/Main/src/SettingsScreen.cpp b/Main/src/SettingsScreen.cpp index 26c8b91f4..ff86ff5f8 100644 --- a/Main/src/SettingsScreen.cpp +++ b/Main/src/SettingsScreen.cpp @@ -178,6 +178,17 @@ class SettingsPage_Input : public SettingsPage SectionHeader("Laser Sensitivity"); RenderLaserSensitivitySettings(); + // Note: remove this if #434 gets merged + if (nk_tree_push(m_nctx, NK_TREE_NODE, "Laser Assist", NK_MINIMIZED)) + { + FloatSetting(GameConfigKeys::LaserAssistLevel, "Base Laser Assist", 0.0f, 10.0f, 0.1f); + FloatSetting(GameConfigKeys::LaserPunish, "Base Laser Punish", 0.0f, 10.0f, 0.1f); + FloatSetting(GameConfigKeys::LaserChangeTime, "Direction Change Duration (ms)", 0.0f, 1000.0f, 1.0f); + FloatSetting(GameConfigKeys::LaserChangeExponent, "Direction Change Curve Exponent", 0.0f, 10.0f, 0.1f); + + nk_tree_pop(m_nctx); + } + SectionHeader("In-Game Key Inputs"); EnumSetting(GameConfigKeys::RestartPlayMethod, "Restart with F5:"); @@ -505,7 +516,7 @@ class SettingsPage_Game : public SettingsPage private: inline void RenderTimingWindowSettings() { - LayoutRowDynamic(4); + LayoutRowDynamic(3); const int hitWindowPerfect = IntInput(m_hitWindow.perfect, "Crit", 0, HitWindow::NORMAL.perfect); if (hitWindowPerfect != m_hitWindow.perfect) @@ -537,10 +548,6 @@ class SettingsPage_Game : public SettingsPage m_hitWindow.good = m_hitWindow.hold; } - const int hitWindowSlam = IntInput(m_hitWindow.slam, "Slam", 0, HitWindow::NORMAL.slam); - if (hitWindowSlam != m_hitWindow.slam) - m_hitWindow.slam = hitWindowSlam; - LayoutRowDynamic(2); if (nk_button_label(m_nctx, "Set to NORMAL (default)")) From ed950c09296f501ec7e2a1b65b64b09d51d9b8b6 Mon Sep 17 00:00:00 2001 From: Drewol Date: Sat, 17 Sep 2022 19:56:24 +0200 Subject: [PATCH 06/22] Update some reverted files to latest version --- Beatmap/include/Beatmap/MapDatabase.hpp | 1 + Beatmap/src/MapDatabase.cpp | 1 + Main/include/ChallengeSelect.hpp | 1 + Main/include/HitStat.hpp | 15 ++++++++------- Main/src/ChallengeResult.cpp | 2 +- Main/src/Game.cpp | 14 +++++++------- Main/src/HitStat.cpp | 5 ++++- Main/src/ScoreScreen.cpp | 5 ++--- 8 files changed, 25 insertions(+), 19 deletions(-) diff --git a/Beatmap/include/Beatmap/MapDatabase.hpp b/Beatmap/include/Beatmap/MapDatabase.hpp index 8dd4e8d2b..7149933a2 100644 --- a/Beatmap/include/Beatmap/MapDatabase.hpp +++ b/Beatmap/include/Beatmap/MapDatabase.hpp @@ -47,6 +47,7 @@ struct ScoreIndex int32 hitWindowGood; int32 hitWindowHold; int32 hitWindowMiss; + int32 hitWindowSlam; }; diff --git a/Beatmap/src/MapDatabase.cpp b/Beatmap/src/MapDatabase.cpp index 2d2b5c85c..1d104591e 100644 --- a/Beatmap/src/MapDatabase.cpp +++ b/Beatmap/src/MapDatabase.cpp @@ -1575,6 +1575,7 @@ class MapDatabase_Impl "window_good INTEGER," "window_hold INTEGER," "window_miss INTEGER," + "window_slam INTEGER," "chart_hash TEXT)"); m_database.Exec("CREATE TABLE Collections" diff --git a/Main/include/ChallengeSelect.hpp b/Main/include/ChallengeSelect.hpp index 9baa3ff3b..1cea0a537 100644 --- a/Main/include/ChallengeSelect.hpp +++ b/Main/include/ChallengeSelect.hpp @@ -107,6 +107,7 @@ struct ChallengeOptions{ v(uint32, crit_judge) \ v(uint32, near_judge) \ v(uint32, hold_judge) \ + v(uint32, slam_judge) \ v(bool, allow_cmod) \ v(bool, allow_excessive) \ v(bool, allow_blastive) \ diff --git a/Main/include/HitStat.hpp b/Main/include/HitStat.hpp index ad9aa0066..fcfb84307 100644 --- a/Main/include/HitStat.hpp +++ b/Main/include/HitStat.hpp @@ -38,32 +38,33 @@ struct HitWindow enum class Type { None = 0, Normal, Hard }; inline HitWindow(MapTime perfect, MapTime good) noexcept : perfect(perfect), good(good) { Validate(); } - inline HitWindow(MapTime perfect, MapTime good, MapTime hold) noexcept : perfect(perfect), good(good), hold(hold) { Validate(); } - inline HitWindow(const HitWindow& that) noexcept : perfect(that.perfect), good(that.good), hold(that.hold), miss(that.miss) { Validate(); } + inline HitWindow(MapTime perfect, MapTime good, MapTime hold, MapTime slam) noexcept : perfect(perfect), good(good), hold(hold), slam(slam) { Validate(); } + inline HitWindow(const HitWindow& that) noexcept : perfect(that.perfect), good(that.good), hold(that.hold), miss(that.miss), slam(that.slam) { Validate(); } static HitWindow FromConfig(); void SaveConfig() const; void ToLuaTable(struct lua_State* L) const; - inline HitWindow& operator= (const HitWindow& that) noexcept { perfect = that.perfect; good = that.good; hold = that.hold; miss = that.miss; return *this; } + inline HitWindow& operator= (const HitWindow& that) noexcept { perfect = that.perfect; good = that.good; hold = that.hold; miss = that.miss; slam = that.slam; return *this; } - constexpr bool operator== (const HitWindow& that) const noexcept { return perfect == that.perfect && good == that.good && hold == that.hold && miss == that.miss; } - constexpr bool operator<= (const HitWindow& that) const noexcept { return perfect <= that.perfect && good <= that.good && hold <= that.hold && miss <= that.miss; } + constexpr bool operator== (const HitWindow& that) const noexcept { return perfect == that.perfect && good == that.good && hold == that.hold && miss == that.miss && slam == that.slam; } + constexpr bool operator<= (const HitWindow& that) const noexcept { return perfect <= that.perfect && good <= that.good && hold <= that.hold && miss <= that.miss && slam <= that.slam; } constexpr Type GetType() const noexcept { if (*this <= HARD) return Type::Hard; else if (*this <= NORMAL) return Type::Normal; else return Type::None; } inline bool Validate() { - if (perfect <= good && good <= hold && hold <= miss && miss <= NORMAL.miss) + if (perfect <= good && good <= hold && hold <= miss && slam <= NORMAL.slam && miss <= NORMAL.miss) return true; - Logf("Invalid timing window: %d/%d/%d/%d", Logger::Severity::Warning, perfect, good, hold, miss); + Logf("Invalid timing window: %d/%d/%d/%d/%d", Logger::Severity::Warning, perfect, good, hold, slam, miss); if (miss > NORMAL.miss) miss = NORMAL.miss; if (hold > miss) hold = miss; if (good > hold) good = hold; if (perfect > good) perfect = good; + if (slam > NORMAL.slam) slam = NORMAL.slam; return false; } diff --git a/Main/src/ChallengeResult.cpp b/Main/src/ChallengeResult.cpp index 7c7b04f96..ff34c00bf 100644 --- a/Main/src/ChallengeResult.cpp +++ b/Main/src/ChallengeResult.cpp @@ -203,7 +203,7 @@ class ChallengeResultScreen_Impl : public ChallengeResultScreen m_PushIntToTable("timestamp", score->timestamp); m_PushIntToTable("badge", static_cast(Scoring::CalculateBadge(*score))); lua_pushstring(m_lua, "hitWindow"); - HitWindow(score->hitWindowPerfect, score->hitWindowGood, score->hitWindowHold).ToLuaTable(m_lua); + HitWindow(score->hitWindowPerfect, score->hitWindowGood, score->hitWindowHold, score->hitWindowSlam).ToLuaTable(m_lua); lua_settable(m_lua, -3); lua_settable(m_lua, -3); } diff --git a/Main/src/Game.cpp b/Main/src/Game.cpp index 90903ebde..d7ba3d4bd 100755 --- a/Main/src/Game.cpp +++ b/Main/src/Game.cpp @@ -320,6 +320,9 @@ class Game_Impl : public Game ), m_challengeManager->GetCurrentOptions().hold_judge.Get( g_gameConfig.GetInt(GameConfigKeys::HitWindowHold) + ), + m_challengeManager->GetCurrentOptions().slam_judge.Get( + g_gameConfig.GetInt(GameConfigKeys::HitWindowSlam) ) ); } @@ -368,10 +371,6 @@ class Game_Impl : public Game ) { replay = m_replayForPlayback; - replayReader.Serialize(&(replay.hitWindow.perfect), 4); - replayReader.Serialize(&(replay.hitWindow.good), 4); - replayReader.Serialize(&(replay.hitWindow.hold), 4); - replayReader.Serialize(&(replay.hitWindow.miss), 4); } } if (!replay) @@ -1575,9 +1574,10 @@ class Game_Impl : public Game g_application->SetButtonLights(g_input.GetButtonBits() & 0b111111); } - float brightness = 1.2 - (m_playback.GetBeatTime() * m_currentTiming->beatDuration) / 700.0; - brightness = Math::Clamp(brightness, 0.2f, 1.0f); - + float brightness = 1.0 - (m_playback.GetBeatTime() * 0.8); + brightness = Math::Clamp(brightness, 0.0f, 1.0f); + + Color rgbColor = Color::FromHSV(180, 1.0, brightness); for (size_t i = 0; i < 2; i++) { diff --git a/Main/src/HitStat.cpp b/Main/src/HitStat.cpp index d9fdc19b5..38b41f989 100644 --- a/Main/src/HitStat.cpp +++ b/Main/src/HitStat.cpp @@ -21,7 +21,8 @@ HitWindow HitWindow::FromConfig() HitWindow hitWindow = HitWindow( g_gameConfig.GetInt(GameConfigKeys::HitWindowPerfect), g_gameConfig.GetInt(GameConfigKeys::HitWindowGood), - g_gameConfig.GetInt(GameConfigKeys::HitWindowHold) + g_gameConfig.GetInt(GameConfigKeys::HitWindowHold), + g_gameConfig.GetInt(GameConfigKeys::HitWindowSlam) ); if (!(hitWindow <= HitWindow::NORMAL)) @@ -39,6 +40,7 @@ void HitWindow::SaveConfig() const g_gameConfig.Set(GameConfigKeys::HitWindowPerfect, perfect); g_gameConfig.Set(GameConfigKeys::HitWindowGood, good); g_gameConfig.Set(GameConfigKeys::HitWindowHold, hold); + g_gameConfig.Set(GameConfigKeys::HitWindowSlam, slam); } void HitWindow::ToLuaTable(lua_State* L) const @@ -56,4 +58,5 @@ void HitWindow::ToLuaTable(lua_State* L) const pushIntToTable("good", good); pushIntToTable("hold", hold); pushIntToTable("miss", miss); + pushIntToTable("slam", slam); } diff --git a/Main/src/ScoreScreen.cpp b/Main/src/ScoreScreen.cpp index 0c85e9aad..def469470 100644 --- a/Main/src/ScoreScreen.cpp +++ b/Main/src/ScoreScreen.cpp @@ -342,6 +342,7 @@ class ScoreScreen_Impl : public ScoreScreen newScore->hitWindowGood = m_hitWindow.good; newScore->hitWindowHold = m_hitWindow.hold; newScore->hitWindowMiss = m_hitWindow.miss; + newScore->hitWindowSlam = m_hitWindow.slam; m_mapDatabase.AddScore(newScore); @@ -913,10 +914,8 @@ class ScoreScreen_Impl : public ScoreScreen m_PushIntToTable("misses", score->miss); m_PushIntToTable("timestamp", score->timestamp); m_PushIntToTable("badge", static_cast(Scoring::CalculateBadge(*score))); - m_PushStringToTable("playerName", *score->userName); - m_PushIntToTable("isLocal", score->localScore); lua_pushstring(m_lua, "hitWindow"); - HitWindow(score->hitWindowPerfect, score->hitWindowGood, score->hitWindowHold).ToLuaTable(m_lua); + HitWindow(score->hitWindowPerfect, score->hitWindowGood, score->hitWindowHold, score->hitWindowSlam).ToLuaTable(m_lua); lua_settable(m_lua, -3); lua_settable(m_lua, -3); } From d76e7fbfcd7f978a42121bff72bed09897685a58 Mon Sep 17 00:00:00 2001 From: Drewol Date: Sat, 17 Sep 2022 21:11:26 +0200 Subject: [PATCH 07/22] Forgot some files --- Main/include/GameConfig.hpp | 1 + Main/src/GameConfig.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/Main/include/GameConfig.hpp b/Main/include/GameConfig.hpp index fd6c81304..c0133b156 100644 --- a/Main/include/GameConfig.hpp +++ b/Main/include/GameConfig.hpp @@ -39,6 +39,7 @@ DefineEnum(GameConfigKeys, HitWindowPerfect, HitWindowGood, HitWindowHold, + HitWindowSlam, HiSpeed, SpeedMod, ModSpeed, diff --git a/Main/src/GameConfig.cpp b/Main/src/GameConfig.cpp index c7c1848e0..b3e830301 100644 --- a/Main/src/GameConfig.cpp +++ b/Main/src/GameConfig.cpp @@ -77,6 +77,7 @@ void GameConfig::InitDefaults() Set(GameConfigKeys::HitWindowPerfect, HitWindow::NORMAL.perfect); Set(GameConfigKeys::HitWindowGood, HitWindow::NORMAL.good); Set(GameConfigKeys::HitWindowHold, HitWindow::NORMAL.hold); + Set(GameConfigKeys::HitWindowSlam, HitWindow::NORMAL.slam); Set(GameConfigKeys::HiSpeed, 1.0f); Set(GameConfigKeys::GlobalOffset, 0); Set(GameConfigKeys::InputOffset, 0); From fb63382299c3b5a88b3e229de7831ea3a53ce41b Mon Sep 17 00:00:00 2001 From: Drewol Date: Sun, 18 Sep 2022 10:51:38 +0200 Subject: [PATCH 08/22] Hardcode laser assist with values from Hoshikara's fork --- Main/include/GameConfig.hpp | 4 ---- Main/src/GameConfig.cpp | 8 -------- Main/src/Scoring.cpp | 11 ++++++----- Main/src/SettingsScreen.cpp | 11 ----------- 4 files changed, 6 insertions(+), 28 deletions(-) diff --git a/Main/include/GameConfig.hpp b/Main/include/GameConfig.hpp index c0133b156..861993f26 100644 --- a/Main/include/GameConfig.hpp +++ b/Main/include/GameConfig.hpp @@ -53,10 +53,6 @@ DefineEnum(GameConfigKeys, Laser0Color, Laser1Color, FPSTarget, - LaserAssistLevel, - LaserPunish, - LaserChangeTime, - LaserChangeExponent, GaugeDrainNormal, GaugeDrainHalf, ResponsiveInputs, diff --git a/Main/src/GameConfig.cpp b/Main/src/GameConfig.cpp index b3e830301..406d9254f 100644 --- a/Main/src/GameConfig.cpp +++ b/Main/src/GameConfig.cpp @@ -83,10 +83,6 @@ void GameConfig::InitDefaults() Set(GameConfigKeys::InputOffset, 0); Set(GameConfigKeys::LaserOffset, 0); Set(GameConfigKeys::FPSTarget, 0); - Set(GameConfigKeys::LaserAssistLevel, 1.05f); - Set(GameConfigKeys::LaserPunish, 1.7f); - Set(GameConfigKeys::LaserChangeTime, 100.0f); - Set(GameConfigKeys::LaserChangeExponent, 1.5f); Set(GameConfigKeys::GaugeDrainNormal, 180); Set(GameConfigKeys::GaugeDrainHalf, 300); Set(GameConfigKeys::ModSpeed, 300.0f); @@ -353,10 +349,6 @@ ConfigBase::KeyList GameConfigProfileSettings = { Key(GlobalOffset), Key(InputOffset), Key(LaserOffset), - Key(LaserAssistLevel), - Key(LaserPunish), - Key(LaserChangeTime), - Key(LaserChangeExponent), Key(HiddenCutoff), Key(HiddenFade), diff --git a/Main/src/Scoring.cpp b/Main/src/Scoring.cpp index a43666c7c..6e5c62669 100755 --- a/Main/src/Scoring.cpp +++ b/Main/src/Scoring.cpp @@ -161,11 +161,12 @@ void Scoring::Reset(const MapTimeRange& range) // Get bounce guard duration m_bounceGuard = g_gameConfig.GetInt(GameConfigKeys::InputBounceGuard); - // Get laser assist level - m_assistLevel = g_gameConfig.GetFloat(GameConfigKeys::LaserAssistLevel); - m_assistPunish = g_gameConfig.GetFloat(GameConfigKeys::LaserPunish); - m_assistChangeExponent = g_gameConfig.GetFloat(GameConfigKeys::LaserChangeExponent); - m_assistChangePeriod = g_gameConfig.GetFloat(GameConfigKeys::LaserChangeTime); + // Set laser assist level + // TODO: Move to more obvious location as constants + m_assistLevel = 1.05f; + m_assistPunish = 1.7f; + m_assistChangeExponent = 1.5f; + m_assistChangePeriod = 100.0f; // Recalculate maximum score mapTotals = CalculateMapTotals(); diff --git a/Main/src/SettingsScreen.cpp b/Main/src/SettingsScreen.cpp index ff86ff5f8..ce71dfb74 100644 --- a/Main/src/SettingsScreen.cpp +++ b/Main/src/SettingsScreen.cpp @@ -178,17 +178,6 @@ class SettingsPage_Input : public SettingsPage SectionHeader("Laser Sensitivity"); RenderLaserSensitivitySettings(); - // Note: remove this if #434 gets merged - if (nk_tree_push(m_nctx, NK_TREE_NODE, "Laser Assist", NK_MINIMIZED)) - { - FloatSetting(GameConfigKeys::LaserAssistLevel, "Base Laser Assist", 0.0f, 10.0f, 0.1f); - FloatSetting(GameConfigKeys::LaserPunish, "Base Laser Punish", 0.0f, 10.0f, 0.1f); - FloatSetting(GameConfigKeys::LaserChangeTime, "Direction Change Duration (ms)", 0.0f, 1000.0f, 1.0f); - FloatSetting(GameConfigKeys::LaserChangeExponent, "Direction Change Curve Exponent", 0.0f, 10.0f, 0.1f); - - nk_tree_pop(m_nctx); - } - SectionHeader("In-Game Key Inputs"); EnumSetting(GameConfigKeys::RestartPlayMethod, "Restart with F5:"); From 9c27364734abdd11f5c39ff1a28de3c98bf99077 Mon Sep 17 00:00:00 2001 From: Drewol Date: Sun, 18 Sep 2022 11:28:00 +0200 Subject: [PATCH 09/22] Remove vcpkg from mac build --- .github/workflows/build.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 765291d56..525056036 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -96,6 +96,7 @@ jobs: - name: cmake run: | eval "$(brew shellenv)" + vcpkg integrate remove cmake . -DLibArchive_LIBRARY=$HOMEBREW_PREFIX/opt/libarchive/lib/libarchive.dylib -DLibArchive_INCLUDE_DIR=$HOMEBREW_PREFIX/opt/libarchive/include -DCMAKE_BUILD_TYPE=Release - name: make run: make From 3ae9866867fbd31f150b7069cecd5864823c66e3 Mon Sep 17 00:00:00 2001 From: Drewol Date: Sun, 18 Sep 2022 11:36:22 +0200 Subject: [PATCH 10/22] Remove vcpkg from mac build --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 525056036..423a9bf97 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -96,7 +96,7 @@ jobs: - name: cmake run: | eval "$(brew shellenv)" - vcpkg integrate remove + rm ./vcpkg.json cmake . -DLibArchive_LIBRARY=$HOMEBREW_PREFIX/opt/libarchive/lib/libarchive.dylib -DLibArchive_INCLUDE_DIR=$HOMEBREW_PREFIX/opt/libarchive/include -DCMAKE_BUILD_TYPE=Release - name: make run: make From ccbedaa7167f272ec18a3b2f09bd6a825ce42e89 Mon Sep 17 00:00:00 2001 From: Emil Date: Sat, 21 Jan 2023 21:01:22 +0100 Subject: [PATCH 11/22] Disable werror in pipeline --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 423a9bf97..a0ed77ff6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -59,7 +59,7 @@ jobs: sudo apt-get update sudo apt-get install g++ libegl1-mesa-dev libfreetype6-dev libogg-dev libvorbis-dev libsdl2-dev libarchive-dev zlib1g-dev libjpeg-dev libpng-dev - name: cmake - run: cmake -DCMAKE_BUILD_TYPE=Release -DUSC_GNU_WERROR=On . + run: cmake -DCMAKE_BUILD_TYPE=Release -DUSC_GNU_WERROR=Off . - name: make run: make - name: Prepare for bundling AppImage From 6629139dcb8767d2301664b794c45229adcfac0b Mon Sep 17 00:00:00 2001 From: Emil Date: Sun, 22 Jan 2023 15:16:46 +0100 Subject: [PATCH 12/22] Update build.yml --- .github/workflows/build.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a0ed77ff6..5924f8b57 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -58,6 +58,8 @@ jobs: run: | sudo apt-get update sudo apt-get install g++ libegl1-mesa-dev libfreetype6-dev libogg-dev libvorbis-dev libsdl2-dev libarchive-dev zlib1g-dev libjpeg-dev libpng-dev + sudo add-apt-repository universe + sudo apt install libfuse2 - name: cmake run: cmake -DCMAKE_BUILD_TYPE=Release -DUSC_GNU_WERROR=Off . - name: make From e3ac5c9660663f0515fea53b683f305d60021fbf Mon Sep 17 00:00:00 2001 From: FructoseJuice <116052103+FructoseJuice@users.noreply.github.com> Date: Wed, 2 Aug 2023 02:10:40 -0600 Subject: [PATCH 13/22] Fixed bug #646 Fixed bug where volume will revert to default value instead of user set value when loading into title screen for the first time. --- Main/src/Application.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Main/src/Application.cpp b/Main/src/Application.cpp index f96f3f86e..bcbf4a6aa 100644 --- a/Main/src/Application.cpp +++ b/Main/src/Application.cpp @@ -192,6 +192,7 @@ int32 Application::Run() AddTickable(ss); } else // Start regular game, goto title screen + g_audio->SetGlobalVolume(g_gameConfig.GetFloat(GameConfigKeys::MasterVolume)); AddTickable(TitleScreen::Create()); } } From 93e2a7c467e492477dabc92740064023d3192c45 Mon Sep 17 00:00:00 2001 From: Emil <11597870+Drewol@users.noreply.github.com> Date: Wed, 2 Aug 2023 19:30:58 +0200 Subject: [PATCH 14/22] Add missing brackets to Application::Run case --- Main/src/Application.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Main/src/Application.cpp b/Main/src/Application.cpp index bcbf4a6aa..fad2794dc 100644 --- a/Main/src/Application.cpp +++ b/Main/src/Application.cpp @@ -192,8 +192,10 @@ int32 Application::Run() AddTickable(ss); } else // Start regular game, goto title screen + { g_audio->SetGlobalVolume(g_gameConfig.GetFloat(GameConfigKeys::MasterVolume)); AddTickable(TitleScreen::Create()); + } } } From b244b4ba2d22b73622f08541d5b038b136c36614 Mon Sep 17 00:00:00 2001 From: Drewol Date: Sat, 7 Oct 2023 11:38:35 +0200 Subject: [PATCH 15/22] button_hit lua can return color for lane beam --- Main/src/Game.cpp | 79 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 21 deletions(-) diff --git a/Main/src/Game.cpp b/Main/src/Game.cpp index d7ba3d4bd..c20b6968b 100755 --- a/Main/src/Game.cpp +++ b/Main/src/Game.cpp @@ -2205,12 +2205,42 @@ class Game_Impl : public Game void OnButtonHit(Input::Button button, ScoreHitRating rating, ObjectState* hitObject, MapTime delta) { + auto luaPopInt = [this] { + int a = lua_tonumber(m_lua, lua_gettop(m_lua)); + lua_pop(m_lua, 1); + return a; + }; + ButtonObjectState* st = (ButtonObjectState*)hitObject; uint32 buttonIdx = (uint32)button; Color c = m_track->hitColors[(size_t)rating]; - auto buttonIndex = (uint32) button; + auto buttonIndex = (uint32)button; bool skipEffect = m_scoring.HoldObjectAvailable(buttonIndex, false) && (!m_delayedHitEffects || buttonIndex > 3); + + //call lua button_hit if it exists + lua_getglobal(m_lua, "button_hit"); + if (lua_isfunction(m_lua, -1)) + { + lua_pushnumber(m_lua, buttonIdx); + lua_pushnumber(m_lua, (int)rating); + lua_pushnumber(m_lua, delta); + if (lua_pcall(m_lua, 3, 3, 0) != 0) + { + Logf("Lua error on calling button_hit: %s", Logger::Severity::Error, lua_tostring(m_lua, -1)); + } + + uint8 b = luaPopInt(); + uint8 g = luaPopInt(); + uint8 r = luaPopInt(); + + if ((r | g | b) > 0) { + c = Color(Colori(r, g, b)); + } + + } + lua_settop(m_lua, 0); + if (!skipEffect) m_track->AddHitEffect(buttonIdx, c, st && st->type == ObjectType::Hold); @@ -2257,46 +2287,53 @@ class Game_Impl : public Game } } + + } + + void OnButtonMiss(Input::Button button, bool hitEffect, ObjectState* object) + { + uint32 buttonIdx = (uint32)button; + + auto luaPopInt = [this] { + int a = lua_tonumber(m_lua, lua_gettop(m_lua)); + lua_pop(m_lua, 1); + return a; + }; + Color c = m_track->hitColors[0]; + //call lua button_hit if it exists lua_getglobal(m_lua, "button_hit"); if (lua_isfunction(m_lua, -1)) { lua_pushnumber(m_lua, buttonIdx); - lua_pushnumber(m_lua, (int)rating); - lua_pushnumber(m_lua, delta); - if (lua_pcall(m_lua, 3, 0, 0) != 0) + lua_pushnumber(m_lua, (int)ScoreHitRating::Miss); + lua_pushnumber(m_lua, 0); + if (lua_pcall(m_lua, 3, 3, 0) != 0) { Logf("Lua error on calling button_hit: %s", Logger::Severity::Error, lua_tostring(m_lua, -1)); } + + uint8 b = luaPopInt(); + uint8 g = luaPopInt(); + uint8 r = luaPopInt(); + + if ((r | g | b) > 0) { + c = Color(Colori(r, g, b)); + } } lua_settop(m_lua, 0); - } - void OnButtonMiss(Input::Button button, bool hitEffect, ObjectState* object) - { - uint32 buttonIdx = (uint32)button; + if (hitEffect) { ButtonObjectState* st = (ButtonObjectState*)object; //m_hiddenObjects.insert(object); - Color c = m_track->hitColors[0]; m_track->AddHitEffect(buttonIdx, c); } m_track->AddEffect(new ButtonHitRatingEffect(buttonIdx, ScoreHitRating::Miss)); - lua_getglobal(m_lua, "button_hit"); - if (lua_isfunction(m_lua, -1)) - { - lua_pushnumber(m_lua, buttonIdx); - lua_pushnumber(m_lua, (int)ScoreHitRating::Miss); - lua_pushnumber(m_lua, 0); - if (lua_pcall(m_lua, 3, 0, 0) != 0) - { - Logf("Lua error on calling button_hit: %s", Logger::Severity::Error, lua_tostring(m_lua, -1)); - } - } - lua_settop(m_lua, 0); + } void OnComboChanged(uint32 newCombo) From 669a55d11c2c498a4135880fd81c7edb115fc379 Mon Sep 17 00:00:00 2001 From: Sky Leite Date: Sun, 24 Dec 2023 15:49:16 -0300 Subject: [PATCH 16/22] Set MacOS libraries in CMakeLists.txt Fixes #471 Fixes #654 --- .github/workflows/build.yml | 9 ++++----- CMakeLists.txt | 23 +++++++++++++++++++++++ README.md | 4 ++-- mac-cmake.sh | 2 -- 4 files changed, 29 insertions(+), 9 deletions(-) delete mode 100755 mac-cmake.sh diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5924f8b57..2d44dba44 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -94,12 +94,11 @@ jobs: - name: brew update run: brew update - name: Install packages - run: brew install freetype libvorbis sdl2 libpng jpeg libarchive + run: brew install freetype libvorbis sdl2 libpng jpeg-turbo libarchive - name: cmake - run: | - eval "$(brew shellenv)" - rm ./vcpkg.json - cmake . -DLibArchive_LIBRARY=$HOMEBREW_PREFIX/opt/libarchive/lib/libarchive.dylib -DLibArchive_INCLUDE_DIR=$HOMEBREW_PREFIX/opt/libarchive/include -DCMAKE_BUILD_TYPE=Release + env: + DCMAKE_BUILD_TYPE: Release + run: cmake . - name: make run: make - name: Upload artifact diff --git a/CMakeLists.txt b/CMakeLists.txt index f4275e4a2..e72026b5f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,6 +42,29 @@ endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES ) set(CMAKE_MACOSX_RPATH 1) +# Set library paths for MacOS +if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") + set(MACOSX TRUE) + + # Set homebrew's include dir + execute_process( + COMMAND brew --prefix + OUTPUT_VARIABLE HOMEBREW_PREFIX + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND_ERROR_IS_FATAL ANY + ) + include_directories("${HOMEBREW_PREFIX}/include") + + # Libarchive is shipped as a keg so we must get its path manually + execute_process( + COMMAND brew --prefix libarchive + OUTPUT_VARIABLE LIBARCHIVE_PREFIX + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND_ERROR_IS_FATAL ANY + ) + set(LibArchive_INCLUDE_DIR "${LIBARCHIVE_PREFIX}/include") +endif() + # Set folder where to find FindXXX.cmake and set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake/Modules/") diff --git a/README.md b/README.md index 756033885..5ce312102 100644 --- a/README.md +++ b/README.md @@ -97,8 +97,8 @@ To run from Visual Studio, go to Properties for Main > Debugging > Working Direc ### macOS: 0. Clone the project using `git` and then run `git submodule update --init --recursive` to download the required submodules. 1. Install dependencies - * [Homebrew](https://github.com/Homebrew/brew): `brew install cmake freetype libvorbis sdl2 libpng jpeg libarchive libiconv` -2. Run `mac-cmake.sh` and then `make` from the root of the project. + * [Homebrew](https://github.com/Homebrew/brew): `brew install cmake freetype libvorbis sdl2 libpng jpeg-turbo libarchive libiconv` +2. Run `cmake -DCMAKE_BUILD_TYPE=Release .` and then `make` from the root of the project. 3. Run the executable made in the 'bin' folder. ### Embedded (Raspberry Pi): diff --git a/mac-cmake.sh b/mac-cmake.sh deleted file mode 100755 index b09705bf7..000000000 --- a/mac-cmake.sh +++ /dev/null @@ -1,2 +0,0 @@ -eval "$(brew shellenv)" -cmake . -DLibArchive_LIBRARY=$HOMEBREW_PREFIX/opt/libarchive/lib/libarchive.dylib -DLibArchive_INCLUDE_DIR=$HOMEBREW_PREFIX/opt/libarchive/include -DCMAKE_BUILD_TYPE=Release \ No newline at end of file From 096ef3512ac214378cc54bd5d9d54602f6974abd Mon Sep 17 00:00:00 2001 From: Sky Date: Fri, 5 Jan 2024 21:42:56 -0300 Subject: [PATCH 17/22] Update to CPR 1.10.5 --- .gitmodules | 1 + CMakeLists.txt | 3 +++ Main/include/LuaRequests.hpp | 5 +++++ Main/src/ScoreScreen.cpp | 10 +++++----- Main/src/SkinHttp.cpp | 10 ++-------- Main/src/SkinIR.cpp | 20 ++++---------------- Main/stdafx.h | 2 +- cmake/Modules/FindCPR.cmake | 26 ++++++++++++++++++++++++++ third_party/CMakeLists.txt | 8 ++++++-- 9 files changed, 53 insertions(+), 32 deletions(-) create mode 100644 cmake/Modules/FindCPR.cmake diff --git a/.gitmodules b/.gitmodules index 98b25cafb..2fe666316 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,6 +10,7 @@ [submodule "third_party/cpr"] path = third_party/cpr url = https://github.com/whoshuu/cpr.git + branch = 1.10.x [submodule "third_party/miniaudio"] path = third_party/miniaudio url = https://github.com/dr-soft/miniaudio.git diff --git a/CMakeLists.txt b/CMakeLists.txt index e72026b5f..a05fb587a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ # Root CMake file cmake_minimum_required(VERSION 3.12) +set(CMAKE_CXX_STANDARD 17 CACHE STRING "v") +set(CMAKE_CXX_STANDARD_REQUIRED True) #set(VCPKG_CRT_LINKAGE static) #set(VCPKG_LIBRARY_LINKAGE static) #set(VCPKG_TARGET_TRIPLET "x64-windows-static" CACHE STRING "Vcpkg target triplet (ex. x86-windows)") @@ -14,6 +16,7 @@ endif() option(BUILD_SHARED_LIBS "Build libraries as shared libraries" OFF) option(USC_GNU_WERROR "Set Werror for gcc." OFF) +option(USE_SYSTEM_CPR "Use system CPR" OFF) project(USC VERSION 0.5.0) if(WIN32 AND ${CMAKE_VERSION} VERSION_GREATER "3.12") diff --git a/Main/include/LuaRequests.hpp b/Main/include/LuaRequests.hpp index d31f84863..3aa22ffd8 100644 --- a/Main/include/LuaRequests.hpp +++ b/Main/include/LuaRequests.hpp @@ -5,6 +5,11 @@ struct AsyncRequest struct lua_State* L; cpr::AsyncResponse r; int callback; + + AsyncRequest(struct lua_State* luaState, cpr::AsyncResponse asyncResponse, int callback) + : L(luaState), r(std::move(asyncResponse)), callback(callback) + { + } }; struct CompleteRequest diff --git a/Main/src/ScoreScreen.cpp b/Main/src/ScoreScreen.cpp index def469470..b3b4af7cc 100644 --- a/Main/src/ScoreScreen.cpp +++ b/Main/src/ScoreScreen.cpp @@ -50,7 +50,7 @@ class ScoreScreen_Impl : public ScoreScreen //promote this to higher scope so i can use it in tick String m_replayPath; - cpr::AsyncResponse m_irResponse; + std::unique_ptr m_irResponse; nlohmann::json m_irResponseJson; HitWindow m_hitWindow = HitWindow::NORMAL; @@ -349,7 +349,7 @@ class ScoreScreen_Impl : public ScoreScreen if (g_gameConfig.GetString(GameConfigKeys::IRBaseURL) != "") { m_irState = IR::ResponseState::Pending; - m_irResponse = IR::PostScore(*newScore, m_beatmapSettings); + m_irResponse = std::make_unique(std::move(IR::PostScore(*newScore, m_beatmapSettings))); } const bool cleared = Scoring::CalculateBadge(*newScore) >= ClearMark::NormalClear; @@ -560,7 +560,7 @@ class ScoreScreen_Impl : public ScoreScreen } ScoreScreen_Impl(class Game* game, MultiplayerScreen* multiplayer, - String uid, Vector const* multistats, ChallengeManager* manager) + String uid, Vector const* multistats, ChallengeManager* manager) : m_irResponse(nullptr) { m_challengeManager = manager; m_displayIndex = 0; @@ -1174,9 +1174,9 @@ class ScoreScreen_Impl : public ScoreScreen try { - if(m_irResponse.wait_for(std::chrono::seconds(0)) == std::future_status::ready) + if(m_irResponse->wait_for(std::chrono::seconds(0)) == std::future_status::ready) { - cpr::Response response = m_irResponse.get(); + cpr::Response response = m_irResponse->get(); if(response.status_code != 200) { diff --git a/Main/src/SkinHttp.cpp b/Main/src/SkinHttp.cpp index 06791aa39..d72bb2670 100644 --- a/Main/src/SkinHttp.cpp +++ b/Main/src/SkinHttp.cpp @@ -119,10 +119,7 @@ int SkinHttp::lGetAsync(lua_State * L) String url = luaL_checkstring(L, 2); cpr::Header header = HeaderFromLuaTable(L, 3); int callback = luaL_ref(L, LUA_REGISTRYINDEX); - AsyncRequest* r = new AsyncRequest(); - r->r = cpr::GetAsync(cpr::Url{ url }, header); - r->callback = callback; - r->L = L; + AsyncRequest* r = new AsyncRequest(L, cpr::GetAsync(cpr::Url{ url }, header), callback); m_mutex.lock(); m_requests.push(r); m_mutex.unlock(); @@ -135,10 +132,7 @@ int SkinHttp::lPostAsync(lua_State * L) String payload = luaL_checkstring(L, 3); cpr::Header header = HeaderFromLuaTable(L, 4); int callback = luaL_ref(L, LUA_REGISTRYINDEX); - AsyncRequest* r = new AsyncRequest(); - r->r = cpr::PostAsync(cpr::Url{ url }, cpr::Body{ *payload }, header); - r->callback = callback; - r->L = L; + AsyncRequest* r = new AsyncRequest(L, cpr::PostAsync(cpr::Url{ url }, cpr::Body{ *payload }, header), callback); m_mutex.lock(); m_requests.push(r); m_mutex.unlock(); diff --git a/Main/src/SkinIR.cpp b/Main/src/SkinIR.cpp index 4d82ae002..8f6575c9b 100644 --- a/Main/src/SkinIR.cpp +++ b/Main/src/SkinIR.cpp @@ -141,10 +141,7 @@ SkinIR::~SkinIR() int SkinIR::lHeartbeat(struct lua_State* L) { int callback = luaL_ref(L, LUA_REGISTRYINDEX); - AsyncRequest* r = new AsyncRequest(); - r->r = IR::Heartbeat(); - r->callback = callback; - r->L = L; + AsyncRequest* r = new AsyncRequest(L, IR::Heartbeat(), callback); m_mutex.lock(); m_requests.push(r); m_mutex.unlock(); @@ -155,10 +152,7 @@ int SkinIR::lChartTracked(struct lua_State* L) { String hash = luaL_checkstring(L, 2); int callback = luaL_ref(L, LUA_REGISTRYINDEX); - AsyncRequest* r = new AsyncRequest(); - r->r = IR::ChartTracked(hash); - r->callback = callback; - r->L = L; + AsyncRequest* r = new AsyncRequest(L, IR::ChartTracked(hash), callback); m_mutex.lock(); m_requests.push(r); m_mutex.unlock(); @@ -169,10 +163,7 @@ int SkinIR::lRecord(struct lua_State* L) { String hash = luaL_checkstring(L, 2); int callback = luaL_ref(L, LUA_REGISTRYINDEX); - AsyncRequest* r = new AsyncRequest(); - r->r = IR::Record(hash); - r->callback = callback; - r->L = L; + AsyncRequest* r = new AsyncRequest(L, IR::Record(hash), callback); m_mutex.lock(); m_requests.push(r); m_mutex.unlock(); @@ -185,10 +176,7 @@ int SkinIR::lLeaderboard(struct lua_State* L) String mode = luaL_checkstring(L, 3); int n = luaL_checkinteger(L, 4); int callback = luaL_ref(L, LUA_REGISTRYINDEX); - AsyncRequest* r = new AsyncRequest(); - r->r = IR::Leaderboard(hash, mode, n); - r->callback = callback; - r->L = L; + AsyncRequest* r = new AsyncRequest(L, IR::Leaderboard(hash, mode, n), callback); m_mutex.lock(); m_requests.push(r); m_mutex.unlock(); diff --git a/Main/stdafx.h b/Main/stdafx.h index 1c6da28e2..7c5747eca 100644 --- a/Main/stdafx.h +++ b/Main/stdafx.h @@ -1,6 +1,7 @@ /* Main and precompiled header file for Main project*/ #pragma once +#include "cpr/cpr.h" // OpenGL headers #include @@ -57,7 +58,6 @@ using namespace Graphics; #include "archive.h" #include "archive_entry.h" -#include "cpr/cpr.h" #include "discord_rpc.h" #include "json.hpp" #include "lua.hpp" diff --git a/cmake/Modules/FindCPR.cmake b/cmake/Modules/FindCPR.cmake new file mode 100644 index 000000000..58ab48320 --- /dev/null +++ b/cmake/Modules/FindCPR.cmake @@ -0,0 +1,26 @@ +# - C++ Requests, Curl for People +# This module is a libcurl wrapper written in modern C++. +# It provides an easy, intuitive, and efficient interface to +# a host of networking methods. +# +# Finding this module will define the following variables: +# CPR_FOUND - True if the core library has been found +# CPR_LIBRARIES - Path to the core library archive +# CPR_INCLUDE_DIRS - Path to the include directories. Gives access +# to cpr.h, which must be included in every +# file that uses this interface + +find_path(CPR_INCLUDE_DIR + NAMES cpr.h) + +find_library(CPR_LIBRARY + NAMES cpr + HINTS ${CPR_LIBRARY_ROOT}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(CPR REQUIRED_VARS CPR_LIBRARY CPR_INCLUDE_DIR) + +if(CPR_FOUND) + set(CPR_LIBRARIES ${CPR_LIBRARY}) + set(CPR_INCLUDE_DIRS ${CPR_INCLUDE_DIR}) +endif() diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt index cd82022ea..4fff114fa 100644 --- a/third_party/CMakeLists.txt +++ b/third_party/CMakeLists.txt @@ -8,8 +8,12 @@ set(CPR_ENABLE_SSL ON) #if(MSVC) # set(CPR_FORCE_USE_SYSTEM_CURL ON) #curl should be available through vcpkg #endif(MSVC) -add_subdirectory(cpr) -target_include_directories(cpr PUBLIC ${CPR_INCLUDE_DIRS}) +if(USE_SYSTEM_CPR) + find_package(cpr REQUIRED) +else() + add_subdirectory(cpr) + target_include_directories(cpr PUBLIC ${CPR_INCLUDE_DIRS}) +endif(USE_SYSTEM_CPR) #discord example program option(BUILD_EXAMPLES "Build example apps" OFF) From 9a9dae3e7f8f044a351a69a502fb569699efb1d7 Mon Sep 17 00:00:00 2001 From: Sky Date: Sat, 6 Jan 2024 21:40:05 -0300 Subject: [PATCH 18/22] Set gamedir to $XDG_DATA_HOME and copy assets to it on creation --- Main/src/Application.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/Main/src/Application.cpp b/Main/src/Application.cpp index fad2794dc..d4da2657d 100644 --- a/Main/src/Application.cpp +++ b/Main/src/Application.cpp @@ -992,6 +992,45 @@ bool Application::m_Init() } } + if (Path::gameDir.empty()) { + char* xdgDataDir = std::getenv("XDG_DATA_HOME"); + + if (xdgDataDir) { + String gameDir = Utility::Sprintf("%s%c%s", xdgDataDir, Path::sep, "unnamed-sdvx-clone"); + auto executableDir = Path::RemoveLast(Path::GetExecutablePath()); + + Path::gameDir = gameDir; + + if (!Path::IsDirectory(gameDir)) { + Logf("%s does not yet exist. Creating...", Logger::Severity::Info, *gameDir); + + auto response = Path::CreateDir(gameDir); + if (response == 1) { + Logf("Created: %s", Logger::Severity::Info, *gameDir, response); + } else { + Logf("Failed creating directory %s. The game will probably crash soon.", Logger::Severity::Info, *gameDir, response); + } + + std::list requiredDirectories = { "skins", "fonts", "audio", "LightPlugins" }; + + for (String directory : requiredDirectories) { + auto sourceDir = Utility::Sprintf("%s%c%s", executableDir, Path::sep, directory); + auto destDir = Path::Absolute(directory); + + response = Path::CopyDir(sourceDir, destDir); + if (response == 1) { + Logf("Copied: %s to %s", Logger::Severity::Info, *sourceDir, *destDir, response); + } else { + Logf("Failed copying %s to %s. The game will probably crash soon.", Logger::Severity::Error, *sourceDir, *destDir, response); + } + } + + } else { + Logf("Setting gamedir to $XDG_DATA_HOME (%s). If data is missing, you can either copy the game data in %s to that directory, unset the $XDG_DATA_HOME variable or run the game with -gamedir=%s", Logger::Severity::Warning, *gameDir, *executableDir, *executableDir); + } + } + } + // Set the locale so that functions such as `fopen` use UTF-8. { String prevLocale = setlocale(LC_CTYPE, nullptr); From 861fc14ab013cd88326192d834c523f03d004b32 Mon Sep 17 00:00:00 2001 From: Sky Date: Sat, 6 Jan 2024 21:40:35 -0300 Subject: [PATCH 19/22] Document `-gamedir` flag and asset loading --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5ce312102..a681f46de 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ Just run 'usc-game' or 'usc-game_Debug' from within the 'bin' folder. - `-autoskip` - Skips beginning of song to the first chart note - `-debug` - Used to show relevant debug info in game such as hit timings, and scoring debug info - `-test` - Runs test scene, for development purposes only +- `-gamedir` - Sets the directory the game loads assets from. If unset, attempts reading from `$XDG_DATA_HOME/unnamed-sdvx-clone`. Finally, uses the executable directory if all else fails. ## How to build: From 4532c33ca8d072abf6be5ca86f640e0f54ec7886 Mon Sep 17 00:00:00 2001 From: 0chroma <21014+0chroma@users.noreply.github.com> Date: Sun, 11 Feb 2024 04:34:01 -0800 Subject: [PATCH 20/22] add install targets to cmake, check for data in XDG_DATA_DIRS instead of just the executable path --- CMakeLists.txt | 3 +++ Main/src/Application.cpp | 19 ++++++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a05fb587a..1a8eaf43b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -165,3 +165,6 @@ if(MSVC) set_target_properties(Tests.Game PROPERTIES FOLDER "Tests") endif(MSVC) + +install(TARGETS usc-game RUNTIME) +install(DIRECTORY bin/ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/unnamed-sdvx-clone) diff --git a/Main/src/Application.cpp b/Main/src/Application.cpp index d4da2657d..731573c21 100644 --- a/Main/src/Application.cpp +++ b/Main/src/Application.cpp @@ -997,7 +997,20 @@ bool Application::m_Init() if (xdgDataDir) { String gameDir = Utility::Sprintf("%s%c%s", xdgDataDir, Path::sep, "unnamed-sdvx-clone"); - auto executableDir = Path::RemoveLast(Path::GetExecutablePath()); + + auto gameDataSourceDir = Path::RemoveLast(Path::GetExecutablePath()); + String xdgDataDirs(std::getenv("XDG_DATA_DIRS")); + // iterate over XDG_DATA_DIRS and look for a folder with the correct name + // if it exists, overwrite gameDataSourceDir with it and break + std::stringstream ss (xdgDataDirs); + String dir; + while (getline (ss, dir, ':')) { + String fullDir = Utility::Sprintf("%s%c%s", dir, Path::sep, "unnamed-sdvx-clone"); + if (Path::IsDirectory(fullDir)) { + gameDataSourceDir = fullDir; + break; + } + } Path::gameDir = gameDir; @@ -1014,7 +1027,7 @@ bool Application::m_Init() std::list requiredDirectories = { "skins", "fonts", "audio", "LightPlugins" }; for (String directory : requiredDirectories) { - auto sourceDir = Utility::Sprintf("%s%c%s", executableDir, Path::sep, directory); + auto sourceDir = Utility::Sprintf("%s%c%s", gameDataSourceDir, Path::sep, directory); auto destDir = Path::Absolute(directory); response = Path::CopyDir(sourceDir, destDir); @@ -1026,7 +1039,7 @@ bool Application::m_Init() } } else { - Logf("Setting gamedir to $XDG_DATA_HOME (%s). If data is missing, you can either copy the game data in %s to that directory, unset the $XDG_DATA_HOME variable or run the game with -gamedir=%s", Logger::Severity::Warning, *gameDir, *executableDir, *executableDir); + Logf("Setting gamedir to $XDG_DATA_HOME (%s). If data is missing, you can either copy the game data in %s to that directory, unset the $XDG_DATA_HOME variable or run the game with -gamedir=%s", Logger::Severity::Warning, *gameDir, *gameDataSourceDir, *gameDataSourceDir); } } } From 7a8490abd55621f27887174ebfe415e4e4707980 Mon Sep 17 00:00:00 2001 From: 0chroma <21014+0chroma@users.noreply.github.com> Date: Sun, 11 Feb 2024 06:51:47 -0800 Subject: [PATCH 21/22] be more specific about which folders should be installed in cmake --- CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a8eaf43b..d3615c2d6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -167,4 +167,7 @@ if(MSVC) endif(MSVC) install(TARGETS usc-game RUNTIME) -install(DIRECTORY bin/ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/unnamed-sdvx-clone) +install(DIRECTORY bin/audio DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/unnamed-sdvx-clone/audio) +install(DIRECTORY bin/fonts DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/unnamed-sdvx-clone/fonts) +install(DIRECTORY bin/LightPlugins DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/unnamed-sdvx-clone/LightPlugins) +install(DIRECTORY bin/skins DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/unnamed-sdvx-clone/skins) From 6768effe295f9f631844a92aefc055b3a504295e Mon Sep 17 00:00:00 2001 From: 0chroma <21014+0chroma@users.noreply.github.com> Date: Sat, 24 Feb 2024 19:09:06 -0800 Subject: [PATCH 22/22] fix cmakelists path issue on install --- CMakeLists.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d3615c2d6..a49115cb2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -167,7 +167,7 @@ if(MSVC) endif(MSVC) install(TARGETS usc-game RUNTIME) -install(DIRECTORY bin/audio DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/unnamed-sdvx-clone/audio) -install(DIRECTORY bin/fonts DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/unnamed-sdvx-clone/fonts) -install(DIRECTORY bin/LightPlugins DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/unnamed-sdvx-clone/LightPlugins) -install(DIRECTORY bin/skins DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/unnamed-sdvx-clone/skins) +install(DIRECTORY bin/audio DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/unnamed-sdvx-clone) +install(DIRECTORY bin/fonts DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/unnamed-sdvx-clone) +install(DIRECTORY bin/LightPlugins DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/unnamed-sdvx-clone) +install(DIRECTORY bin/skins DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/unnamed-sdvx-clone)