From 90a3f9d354936f1c907cdf2890ea4fb764e89a6c Mon Sep 17 00:00:00 2001 From: Barinade Date: Sat, 11 Mar 2023 15:47:27 -0600 Subject: [PATCH 01/10] prevent crashing in noteskin preview if noteskin loader has error --- src/Etterna/Singletons/NoteSkinManager.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Etterna/Singletons/NoteSkinManager.cpp b/src/Etterna/Singletons/NoteSkinManager.cpp index 914d89f160..ec79af9f33 100644 --- a/src/Etterna/Singletons/NoteSkinManager.cpp +++ b/src/Etterna/Singletons/NoteSkinManager.cpp @@ -717,6 +717,11 @@ class LunaNoteSkinManager : public Luna LoadActor(p, L); p->SetCurrentNoteSkin(sOldNoteSkin); + if (lua_isnil(L, -1)) { + lua_pushnil(L); + return 1; + } + auto xnode = XmlFileUtil::XNodeFromTable(L); if (xnode == nullptr) { // XNode will warn about the error From 98e23af05af8b450430c7eabf55e36027fa22079 Mon Sep 17 00:00:00 2001 From: Barinade Date: Tue, 21 Mar 2023 19:43:15 -0500 Subject: [PATCH 02/10] prevent crash when garbage tns is sent to setjudgment --- src/Etterna/Actor/Gameplay/Player.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Etterna/Actor/Gameplay/Player.cpp b/src/Etterna/Actor/Gameplay/Player.cpp index b331d11cf7..adf599dbf2 100644 --- a/src/Etterna/Actor/Gameplay/Player.cpp +++ b/src/Etterna/Actor/Gameplay/Player.cpp @@ -3085,7 +3085,15 @@ Player::SetJudgment(int iRow, msg.SetParam("Type", std::string("Tap")); msg.SetParam("TapNoteOffset", tn.result.fTapNoteOffset); if (m_pPlayerStageStats != nullptr) { - msg.SetParam("Val", m_pPlayerStageStats->m_iTapNoteScores[tns] + 1); + if (tns >= NUM_TapNoteScore || tns < 0) { + Locator::getLogger()->fatal( + "Invalid TNS {} sent to SetJudgment. Ignored 'Val' param in " + "JudgmentMessage", + tns); + } else { + msg.SetParam("Val", + m_pPlayerStageStats->m_iTapNoteScores[tns] + 1); + } } if (tns != TNS_Miss) { From adeced76697804d214286e9613a7bb5183ab5a0b Mon Sep 17 00:00:00 2001 From: Barinade Date: Tue, 21 Mar 2023 19:44:36 -0500 Subject: [PATCH 03/10] fix inputdata replays hitting all notes even when "lifting" this caused tap releases to hit notes and give bad judgments this was only reported by 1 person. it happened on every replay. hello??? --- src/Etterna/Actor/Gameplay/PlayerReplay.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/Etterna/Actor/Gameplay/PlayerReplay.cpp b/src/Etterna/Actor/Gameplay/PlayerReplay.cpp index 11c94c293a..05ecae27a8 100644 --- a/src/Etterna/Actor/Gameplay/PlayerReplay.cpp +++ b/src/Etterna/Actor/Gameplay/PlayerReplay.cpp @@ -813,14 +813,17 @@ PlayerReplay::Step(int col, } else { // every other case if (pTN->IsNote() || pTN->type == TapNoteType_Lift) { - score = ReplayManager::GetTapNoteScoreForReplay( - fNoteOffset, GetTimingWindowScale()); - - // taps assigned to notes really far away - // are counted as misses - // but to stop it breaking things, do nothing - if (score == TNS_Miss) { - score = TNS_None; + // make sure lifts are on lifts and taps are on taps... + if ((pTN->type == TapNoteType_Lift) == bRelease) { + score = ReplayManager::GetTapNoteScoreForReplay( + fNoteOffset, GetTimingWindowScale()); + + // taps assigned to notes really far away + // are counted as misses + // but to stop it breaking things, do nothing + if (score == TNS_Miss) { + score = TNS_None; + } } } } From 21a74ad8ded12104cd9518165731bedf74ade2c8 Mon Sep 17 00:00:00 2001 From: Barinade Date: Tue, 21 Mar 2023 20:35:16 -0500 Subject: [PATCH 04/10] Iterate version to 0.72.3 --- CMakeLists.txt | 2 +- Data/splash.png | Bin 17015 -> 17520 bytes Themes/_fallback/Graphics/Common splash.png | Bin 17015 -> 17520 bytes src/Etterna/Singletons/GameState.h | 2 +- 4 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 887d6ac3c5..07137ca98f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") # PROJECT WIDE SETUP project(Etterna - VERSION 0.72.2 + VERSION 0.72.3 HOMEPAGE_URL https://github.com/etternagame/etterna/ LANGUAGES C CXX ASM) diff --git a/Data/splash.png b/Data/splash.png index 9f274cd84fdc72ce85f36acccf9d90ccb66d5eaf..adfdb96064a6d54aaa2aaa47b716ea49845c7e3a 100644 GIT binary patch delta 13067 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 int; - static auto GetEtternaVersion() -> std::string { return "0.72.2"; } + static auto GetEtternaVersion() -> std::string { return "0.72.3"; } /* is this the best place for this? it's not exactly a pref, and we * shouldn't be copying and pasting these values everywhere as needed j1-j4 From febd5ed140bbc165fdb801fca36354b1d505f3fe Mon Sep 17 00:00:00 2001 From: Barinade Date: Tue, 21 Mar 2023 20:56:55 -0500 Subject: [PATCH 05/10] fix mine hits breaking replay playback slightly ??? this misaligned some hits temporarily, which would somehow self correct. this let me hit notes at like 800ms off which made no sense and somehow this little check just fixes it. didnt feel like figuring out why i wrote the function this way which caused the issue in the first place. thats how we do it around here --- src/Etterna/Actor/Gameplay/PlayerReplay.cpp | 23 +++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/Etterna/Actor/Gameplay/PlayerReplay.cpp b/src/Etterna/Actor/Gameplay/PlayerReplay.cpp index 05ecae27a8..a98231bda0 100644 --- a/src/Etterna/Actor/Gameplay/PlayerReplay.cpp +++ b/src/Etterna/Actor/Gameplay/PlayerReplay.cpp @@ -767,13 +767,21 @@ PlayerReplay::Step(int col, fNoteOffset = (fStepSeconds - fPositionSeconds) / REPLAYS->GetActiveReplay()->GetMusicRate(); - NOTESKIN->SetLastSeenColor( - NoteTypeToString(GetNoteType(rowBeingJudged))); - - TapNote* pTN = nullptr; auto closestNR = GetClosestNote( col, rowBeingJudged, MAX_NOTE_ROW, MAX_NOTE_ROW, false, false); + if (closestNR != rowBeingJudged) { + // BANDAID BANDAID BANDAID + // BANDAID BANDAID BANDAID + Locator::getLogger()->trace( + "Dumped PlayerReplay input because it might break something: closestnr {} " + "- beingjudged {} - rowtojudge {}", + closestNR, + rowBeingJudged, + rowToJudge); + return; + } + if (closestNR == -1 && !bRelease) { // the last notes of the file will trigger this due to releases // go ahead and skip releases @@ -786,9 +794,12 @@ PlayerReplay::Step(int col, rowToJudge); return; } - auto iter = m_NoteData.FindTapNote(col, closestNR); - pTN = &iter->second; + NOTESKIN->SetLastSeenColor( + NoteTypeToString(GetNoteType(rowBeingJudged))); + + auto iter = m_NoteData.FindTapNote(col, closestNR); + TapNote* pTN = &iter->second; // We don't really have to care if we are releasing on a non-lift, // right? This fixes a weird noteskin bug with tap explosions. From 7fc8c5017a86cf2ff1edd0980470496dd85a3306 Mon Sep 17 00:00:00 2001 From: Barinade Date: Tue, 21 Mar 2023 21:30:08 -0500 Subject: [PATCH 06/10] add framelimit and framelimitgameplay to graphics options til death and rebirth --- .../BGAnimations/playerInfoFrame/settings.lua | 202 +++++++++++++----- Themes/Rebirth/Languages/en.ini | 7 +- Themes/Rebirth/Languages/ja.ini | 3 +- Themes/_fallback/Languages/en.ini | 4 + Themes/_fallback/Scripts/02 ThemePrefs.lua | 126 +++++++++++ Themes/_fallback/metrics.ini | 4 +- 6 files changed, 285 insertions(+), 61 deletions(-) diff --git a/Themes/Rebirth/BGAnimations/playerInfoFrame/settings.lua b/Themes/Rebirth/BGAnimations/playerInfoFrame/settings.lua index 488b1dfeb5..329d660a14 100644 --- a/Themes/Rebirth/BGAnimations/playerInfoFrame/settings.lua +++ b/Themes/Rebirth/BGAnimations/playerInfoFrame/settings.lua @@ -120,7 +120,8 @@ local translations = { ["CategoryInvalidating Options"] = THEME:GetString("Settings", "CategoryInvalidating Options"), ["CategoryGameplay Elements 1"] = THEME:GetString("Settings", "CategoryGameplay Elements 1"), ["CategoryGameplay Elements 2"] = THEME:GetString("Settings", "CategoryGameplay Elements 2"), - ["CategoryGlobal Options"] = THEME:GetString("Settings", "CategoryGlobal Options"), + ["CategoryGlobal Options 1"] = THEME:GetString("Settings", "CategoryGlobal Options 1"), + ["CategoryGlobal Options 2"] = THEME:GetString("Settings", "CategoryGlobal Options 2"), ["CategoryTheme Options 1"] = THEME:GetString("Settings", "CategoryTheme Options 1"), ["CategoryTheme Options 2"] = THEME:GetString("Settings", "CategoryTheme Options 2"), ["CategorySound Options"] = THEME:GetString("Settings", "CategorySound Options"), @@ -368,6 +369,10 @@ local translations = { TextureResolutionExplanation = THEME:GetString("Settings", "TextureResolutionExplanation"), VSync = THEME:GetString("Settings", "VSync"), VSyncExplanation = THEME:GetString("Settings", "VSyncExplanation"), + FrameLimit = THEME:GetString("Settings", "FrameLimit"), + FrameLimitExplanation = THEME:GetString("Settings", "FrameLimitExplanation"), + FrameLimitGameplay = THEME:GetString("Settings", "FrameLimitGameplay"), + FrameLimitGameplayExplanation = THEME:GetString("Settings", "FrameLimitGameplayExplanation"), FastNoteRendering = THEME:GetString("Settings", "FastNoteRendering"), FastNoteRenderingExplanation = THEME:GetString("Settings", "FastNoteRenderingExplanation"), ShowStats = THEME:GetString("Settings", "ShowStats"), @@ -3555,7 +3560,8 @@ local function rightFrame() "Gameplay Elements 2", }, Graphics = { - "Global Options", + "Global Options 1", + "Global Options 2", "Theme Options 1", "Theme Options 2", }, @@ -5109,7 +5115,7 @@ local function rightFrame() -- ----- -- GLOBAL GRAPHICS OPTIONS - ["Global Options"] = { + ["Global Options 1"] = { { Name = "Language", DisplayName = translations["Language"], @@ -5405,6 +5411,52 @@ local function rightFrame() return choice end, }, + { + Name = "VSync", + DisplayName = translations["VSync"], + Type = "SingleChoice", + Explanation = translations["VSyncExplanation"], + Choices = { + { + Name = "On", + DisplayName = translations["On"], + ChosenFunction = function() + local v = true + PREFSMAN:SetPreference("Vsync", v) + if v == optionData.vsyncBefore then + modsToApplyAtExit["Vsync"] = nil + else + modsToApplyAtExit["Vsync"] = { + Name = "Vsync", + Value = v, + SetGraphics = true, + } + end + end, + }, + { + Name = "Off", + DisplayName = translations["Off"], + ChosenFunction = function() + local v = false + PREFSMAN:SetPreference("Vsync", v) + if v == optionData.vsyncBefore then + modsToApplyAtExit["Vsync"] = nil + else + modsToApplyAtExit["Vsync"] = { + Name = "Vsync", + Value = v, + SetGraphics = true, + } + end + end, + }, + }, + ChoiceIndexGetter = function() + local v = PREFSMAN:GetPreference("Vsync") + if v then return 1 else return 2 end + end, + }, { Name = "Display Color Depth", DisplayName = translations["ColorDepth"], @@ -5617,52 +5669,8 @@ local function rightFrame() end, }, ]] - { - Name = "VSync", - DisplayName = translations["VSync"], - Type = "SingleChoice", - Explanation = translations["VSyncExplanation"], - Choices = { - { - Name = "On", - DisplayName = translations["On"], - ChosenFunction = function() - local v = true - PREFSMAN:SetPreference("Vsync", v) - if v == optionData.vsyncBefore then - modsToApplyAtExit["Vsync"] = nil - else - modsToApplyAtExit["Vsync"] = { - Name = "Vsync", - Value = v, - SetGraphics = true, - } - end - end, - }, - { - Name = "Off", - DisplayName = translations["Off"], - ChosenFunction = function() - local v = false - PREFSMAN:SetPreference("Vsync", v) - if v == optionData.vsyncBefore then - modsToApplyAtExit["Vsync"] = nil - else - modsToApplyAtExit["Vsync"] = { - Name = "Vsync", - Value = v, - SetGraphics = true, - } - end - end, - }, - }, - ChoiceIndexGetter = function() - local v = PREFSMAN:GetPreference("Vsync") - if v then return 1 else return 2 end - end, - }, + }, + ["Global Options 2"] = { { Name = "Fast Note Rendering", DisplayName = translations["FastNoteRendering"], @@ -5672,15 +5680,6 @@ local function rightFrame() Directions = preferenceToggleDirections("FastNoteRendering", true, false), ChoiceIndexGetter = preferenceToggleIndexGetter("FastNoteRendering", true), }, - { - Name = "Show Stats", - DisplayName = translations["ShowStats"], - Type = "SingleChoice", - Explanation = translations["ShowStatsExplanation"], - Choices = choiceSkeleton("On", "Off"), - Directions = preferenceToggleDirections("ShowStats", true, false), - ChoiceIndexGetter = preferenceToggleIndexGetter("ShowStats", true), - }, { Name = "Tap Glow", DisplayName = translations["TapGlow"], @@ -5708,6 +5707,93 @@ local function rightFrame() Directions = optionDataToggleDirectionsFUNC("showBanners", true, false), ChoiceIndexGetter = optionDataToggleIndexGetterFUNC("showBanners", true), }, + { + Name = "Show Stats", + DisplayName = translations["ShowStats"], + Type = "SingleChoice", + Explanation = translations["ShowStatsExplanation"], + Choices = choiceSkeleton("On", "Off"), + Directions = preferenceToggleDirections("ShowStats", true, false), + ChoiceIndexGetter = preferenceToggleIndexGetter("ShowStats", true), + }, + { + Name = "Framelimit", + DisplayName = translations["FrameLimit"], + Type = "SingleChoiceModifier", + Explanation = translations["FrameLimitExplanation"], + Directions = { + Left = function(multiplier) + local x = PREFSMAN:GetPreference("FrameLimit") + if x < 30 then + x = 1000 + else + if multiplier then + x = x - 50 + else + x = x - 1 + end + end + if x < 30 then x = 0 end + PREFSMAN:SetPreference("FrameLimit", x) + end, + Right = function(multiplier) + local x = PREFSMAN:GetPreference("FrameLimit") + if x < 30 then + x = 30 + else + if multiplier then + x = x + 50 + else + x = x + 1 + end + end + if x > 1000 then x = 0 end + PREFSMAN:SetPreference("FrameLimit", x) + end, + }, + ChoiceIndexGetter = function() + return PREFSMAN:GetPreference("FrameLimit") .. "" + end, + }, + { + Name = "FramelimitGameplay", + DisplayName = translations["FrameLimitGameplay"], + Type = "SingleChoiceModifier", + Explanation = translations["FrameLimitGameplayExplanation"], + Directions = { + Left = function(multiplier) + local x = PREFSMAN:GetPreference("FrameLimitGameplay") + if x < 30 then + x = 1000 + else + if multiplier then + x = x - 50 + else + x = x - 1 + end + end + if x < 30 then x = 0 end + PREFSMAN:SetPreference("FrameLimitGameplay", x) + end, + Right = function(multiplier) + local x = PREFSMAN:GetPreference("FrameLimitGameplay") + if x < 30 then + x = 30 + else + if multiplier then + x = x + 50 + else + x = x + 1 + end + end + if x > 1000 then x = 0 end + PREFSMAN:SetPreference("FrameLimitGameplay", x) + end, + }, + ChoiceIndexGetter = function() + return PREFSMAN:GetPreference("FrameLimitGameplay") .. "" + end, + }, }, -- ----- diff --git a/Themes/Rebirth/Languages/en.ini b/Themes/Rebirth/Languages/en.ini index b524f241ca..777eea0a5c 100644 --- a/Themes/Rebirth/Languages/en.ini +++ b/Themes/Rebirth/Languages/en.ini @@ -668,7 +668,8 @@ CategoryAppearance Options=Appearance Options CategoryInvalidating Options=Invalidating Options CategoryGameplay Elements 1=Gameplay Elements 1 CategoryGameplay Elements 2=Gameplay Elements 2 -CategoryGlobal Options=Global Options +CategoryGlobal Options 1=Global Options 1 +CategoryGlobal Options 2=Global Options 2 CategoryTheme Options 1=Theme Options 1 CategoryTheme Options 2=Theme Options 2 CategorySound Options=Sound Options @@ -922,6 +923,10 @@ TextureResolution=Texture Resolution TextureResolutionExplanation=Modify general texture resolution. Lower number will lower quality but may increase FPS. VSync=VSync VSyncExplanation=Restrict the game refresh rate and FPS to the refresh rate you have set. +FrameLimit=Frame Limit +FrameLimitExplanation=Set the FPS Cap for the game outside of gameplay. 0 is unlimited. Only works when VSync is off. +FrameLimitGameplay=Frame Limit Gameplay +FrameLimitGameplayExplanation=Set the FPS Cap for the game inside of gameplay only. 0 is unlimited. Only works when VSync is off. FastNoteRendering=Fast Note Rendering FastNoteRenderingExplanation=Optimize gameplay note rendering. Disable snap based noteskin features (not snaps themselves). Major boost to FPS. ShowStats=Show Stats diff --git a/Themes/Rebirth/Languages/ja.ini b/Themes/Rebirth/Languages/ja.ini index 481536a178..19c93885b5 100644 --- a/Themes/Rebirth/Languages/ja.ini +++ b/Themes/Rebirth/Languages/ja.ini @@ -662,7 +662,8 @@ CategoryAppearance Options=Appearance Options CategoryInvalidating Options=Invalidating Options CategoryGameplay Elements 1=Gameplay Elements 1 CategoryGameplay Elements 2=Gameplay Elements 2 -CategoryGlobal Options=Global Options +CategoryGlobal Options 1=Global Options 1 +CategoryGlobal Options 2=Global Options 2 CategoryTheme Options 1=Theme Options 1 CategoryTheme Options 2=Theme Options 2 CategorySound Options=Sound Options diff --git a/Themes/_fallback/Languages/en.ini b/Themes/_fallback/Languages/en.ini index 9be2e42cc5..50fc7164f7 100644 --- a/Themes/_fallback/Languages/en.ini +++ b/Themes/_fallback/Languages/en.ini @@ -316,6 +316,8 @@ FastLoad=If enabled, don't check songs for changes on load. FastLoadAdditionalSongs=If enabled, don't check songs for changes to Additional Songs on load. FastNoteRendering=If enabled, the Z buffer is not cleared after every note. This causes 3D Noteskins to collide, but substantially improves performance in gameplay. Disabling also enables some extra Noteskin features. Fill Machine Stats= +FrameLimitGlobal=Set the framelimit of the menus. This may not apply when VSync is on. 0 means unlimited. +FrameLimitGameplay=Set the framelimit of just gameplay. This may not apply when VSync is on. 0 means unlimited. FullTapExplosions = Toggle whether to play the full tap explosion animation on taps. Short means that they instantly end when you release your tap. FooBar=This is an example explanation. Game=Change the current game type with this option. @@ -921,6 +923,8 @@ Force Color 2=Force Color 2 Force Effect=Force Effect Force Transition=Force Transition FooBar=FooBar +FrameLimitGlobal=Frame Limit Menu +FrameLimitGameplay=Frame Limit Gameplay Freeze=Freeze Game=Game Get a better editor= Get a better editor diff --git a/Themes/_fallback/Scripts/02 ThemePrefs.lua b/Themes/_fallback/Scripts/02 ThemePrefs.lua index bad2af910a..e6129befa4 100644 --- a/Themes/_fallback/Scripts/02 ThemePrefs.lua +++ b/Themes/_fallback/Scripts/02 ThemePrefs.lua @@ -328,6 +328,132 @@ function InputDebounceTime() return t end +function FrameLimitGlobal() + local delaylist = {"0","30","40","50","60","70","80","90"} + do + local start = 100 + local upper = 1000 + local increment = 50 + while start <= upper do + delaylist[#delaylist+1] = tostring(start) + start = start + increment + end + start = 2000 + upper = 5000 + increment = 1000 + while start <= upper do + delaylist[#delaylist+1] = tostring(start) + start = start + increment + end + end + + local t = { + Name = "FrameLimitGlobal", + LayoutType = "ShowAllInRow", + SelectType = "SelectOne", + OneChoiceForAllPlayers = false, + ExportOnChange = true, + Choices = delaylist, + LoadSelections = function(self, list, pn) + local rateindex = 1 + local diff = 999999999 + local rate = notShit.round(PREFSMAN:GetPreference("FrameLimit"), 0) + for i = 1, #delaylist do + local r = tonumber(delaylist[i]) + if r == rate then + rateindex = i + break + end + if math.abs(r - rate) < diff then + diff = math.abs(r-rate) + rateindex = i + else + -- assuming sorted/sequential, exit early + break + end + end + list[rateindex] = true + end, + SaveSelections = function(self, list, pn) + for i, v in ipairs(list) do + if v == true then + local r = notShit.round(tonumber(delaylist[i]), 0) + PREFSMAN:SetPreference("FrameLimit", r) + break + end + end + end, + NotifyOfSelection = function(self, pn, choice) + MESSAGEMAN:Broadcast("FrameLimitGlobalOptionChanged", {value = PREFSMAN:GetPreference("FrameLimit")}) + end + } + setmetatable(t, t) + return t +end + +function FrameLimitGameplay() + local delaylist = {"0","30","40","50","60","70","80","90"} + do + local start = 100 + local upper = 1000 + local increment = 50 + while start <= upper do + delaylist[#delaylist+1] = tostring(start) + start = start + increment + end + start = 2000 + upper = 5000 + increment = 1000 + while start <= upper do + delaylist[#delaylist+1] = tostring(start) + start = start + increment + end + end + + local t = { + Name = "FrameLimitGameplay", + LayoutType = "ShowAllInRow", + SelectType = "SelectOne", + OneChoiceForAllPlayers = false, + ExportOnChange = true, + Choices = delaylist, + LoadSelections = function(self, list, pn) + local rateindex = 1 + local diff = 999999999 + local rate = notShit.round(PREFSMAN:GetPreference("FrameLimitGameplay"), 0) + for i = 1, #delaylist do + local r = tonumber(delaylist[i]) + if r == rate then + rateindex = i + break + end + if math.abs(r - rate) < diff then + diff = math.abs(r-rate) + rateindex = i + else + -- assuming sorted/sequential, exit early + break + end + end + list[rateindex] = true + end, + SaveSelections = function(self, list, pn) + for i, v in ipairs(list) do + if v == true then + local r = notShit.round(tonumber(delaylist[i]), 0) + PREFSMAN:SetPreference("FrameLimitGameplay", r) + break + end + end + end, + NotifyOfSelection = function(self, pn, choice) + MESSAGEMAN:Broadcast("FrameLimitGameplayOptionChanged", {value = PREFSMAN:GetPreference("FrameLimitGameplay")}) + end + } + setmetatable(t, t) + return t +end + function VisualDelaySeconds() local delaylist = {} do diff --git a/Themes/_fallback/metrics.ini b/Themes/_fallback/metrics.ini index 1ee3a6658d..2508a09588 100644 --- a/Themes/_fallback/metrics.ini +++ b/Themes/_fallback/metrics.ini @@ -2183,7 +2183,7 @@ Line21="conf,Center1Player" Fallback="ScreenOptionsServiceChild" NextScreen="ScreenOptionsService" PrevScreen="ScreenOptionsService" -LineNames="1,2,3,RefreshRate,FSType,4,5,6,7,8,9,11,13,FNR,14,17,19,20,GO" +LineNames="1,2,3,RefreshRate,FSType,4,5,6,7,8,9,11,13,FNR,14,17,FRGlobal,FRGameplay,19,20,GO" Line1="lua,ConfDisplayMode()" Line2="lua,ConfAspectRatio()" Line3="lua,ConfDisplayResolution()" @@ -2203,6 +2203,8 @@ Line14="conf,ShowStats" Line16="conf,AttractSoundFrequency" Line17="conf,SoundVolume" Line19="conf,EnableMineHitSound" +LineFRGlobal="lua,FrameLimitGlobal()" +LineFRGameplay="lua,FrameLimitGameplay()" Line20="lua,VisualDelaySeconds()" LineGO="lua,GlobalOffsetSeconds()" From 4400063b1e6818c16cc2a46787da08ebfcf10f5b Mon Sep 17 00:00:00 2001 From: Barinade Date: Tue, 21 Mar 2023 21:33:43 -0500 Subject: [PATCH 07/10] rebirth fix help screen lua error --- .../ScreenHelpMenu overlay/helpDisplay.lua | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/Themes/Rebirth/BGAnimations/ScreenHelpMenu overlay/helpDisplay.lua b/Themes/Rebirth/BGAnimations/ScreenHelpMenu overlay/helpDisplay.lua index 7b4281c2ee..daf72da3f1 100644 --- a/Themes/Rebirth/BGAnimations/ScreenHelpMenu overlay/helpDisplay.lua +++ b/Themes/Rebirth/BGAnimations/ScreenHelpMenu overlay/helpDisplay.lua @@ -725,10 +725,20 @@ local t = Def.ActorFrame { }, Def.Sprite { Name = "Logo", - Texture = THEME:GetPathG("", "Logo"), + Texture = THEME:GetPathG("", "Logo-E"), InitCommand = function(self) self:xy(actuals.ScrollerWidth + (actuals.ListWidth / 2), actuals.InfoHeight / 2) self:zoomto(logoW, logoH) + registerActorToColorConfigElement(self, "title", "LogoE") + end + }, + Def.Sprite { + Name = "LogoTriangle", + Texture = THEME:GetPathG("", "Logo-Triangle"), + InitCommand = function(self) + self:xy(actuals.ScrollerWidth + (actuals.ListWidth / 2), actuals.InfoHeight / 2) + self:zoomto(logoW, logoH) + registerActorToColorConfigElement(self, "title", "LogoTriangle") end }, LoadColorFont("Menu Bold") .. { From 43eb88a6761a886166789e7de8c6e1f2cc9edb1f Mon Sep 17 00:00:00 2001 From: Barinade Date: Tue, 21 Mar 2023 21:41:30 -0500 Subject: [PATCH 08/10] Update changelog for 0.72.3 --- .changelog/Release_0-72-3.md | 15 +++++++++++++++ CHANGELOG.md | 6 ++++++ 2 files changed, 21 insertions(+) create mode 100644 .changelog/Release_0-72-3.md diff --git a/.changelog/Release_0-72-3.md b/.changelog/Release_0-72-3.md new file mode 100644 index 0000000000..998aa98857 --- /dev/null +++ b/.changelog/Release_0-72-3.md @@ -0,0 +1,15 @@ +# Release Changelog + + +## [0.72.3] - 2023-03-21 - Hotfix + +### Added +- FrameLimit and FrameLimitGameplay added to legacy Graphics Options +- FrameLimit and FrameLimitGameplay added to Rebirth Graphics Options + +### Fixed +- Crashing when hovering a Noteskin in options menu which has broken elements or cmd() use - [90a3f9d](../../../commit/90a3f9d354936f1c907cdf2890ea4fb764e89a6c) +- Crashing when replays catastrophically suck - [98e23af](../../../commit/98e23af05af8b450430c7eabf55e36027fa22079) +- Lua error in Rebirth Help due to logo rename - [4400063](../../../commit/4400063b1e6818c16cc2a46787da08ebfcf10f5b) +- Replays hitting bad judgments when doing "lift" actions - [adeced7](../../../commit/adeced76697804d214286e9613a7bb5183ab5a0b) +- Replays misaligning some hits after hitting mines - [febd5ed](../../../commit/febd5ed140bbc165fdb801fca36354b1d505f3fe) \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index cd7ce5f7e6..1bec9fb59f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Changelog All releases of Etterna are listed in this file as well as links to files detailing all of the changes for each. All changes for each version apply in supplement to the ones below it. Changes are not in chronological order, only versions are. +## [0.72.3] - 2023-03-21 - Hotfix + +Windows x64, Windows i386, and Mac installer release. Linux binary. +- Fixes for replays and other stuff +- [Notes](.changelog/Release_0-72-3.md) + ## [0.72.2] - 2023-03-01 - Hotfix Windows x64, Windows i386, and Mac installer release. Linux binary. From d4b1a098eefa8e56a84dac533a3be58daf9b03e8 Mon Sep 17 00:00:00 2001 From: poco0317 Date: Tue, 21 Mar 2023 21:44:56 -0500 Subject: [PATCH 09/10] update openssl links --- Docs/Building.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Docs/Building.md b/Docs/Building.md index be2e2791f8..9ede95c162 100644 --- a/Docs/Building.md +++ b/Docs/Building.md @@ -50,7 +50,7 @@ cmake -DOPENSSL_ROOT_DIR="/usr/local/opt/openssl" -G "Xcode" .. # macOS - Arch: `pacman -S openssl` - Alpine: `apk add openssl-dev` - macOS: `brew install openssl` - - Windows: A CMake compatible version of OpenSSL is available at [Shining Light Productions](https://slproweb.com/products/Win32OpenSSL.html) website. You will need the 32bit and 64bit installers if you plan on building both versions. It's recommended to uninstall old versions to make sure CMake can find the correct latest version. Direct links: [32bit](https://slproweb.com/download/Win32OpenSSL-1_1_1s.exe), [64bit](https://slproweb.com/download/Win64OpenSSL-1_1_1s.exe). If these links are dead, look for the OpenSSL v1.1.1 install links (EXE or MSI) on the Shining Light Productions site. Typically we use the full versions rather than the Light versions. + - Windows: A CMake compatible version of OpenSSL is available at [Shining Light Productions](https://slproweb.com/products/Win32OpenSSL.html) website. You will need the 32bit and 64bit installers if you plan on building both versions. It's recommended to uninstall old versions to make sure CMake can find the correct latest version. Direct links: [32bit](https://slproweb.com/download/Win32OpenSSL-1_1_1t.exe), [64bit](https://slproweb.com/download/Win64OpenSSL-1_1_1t.exe). If these links are dead, look for the OpenSSL v1.1.1 install links (EXE or MSI) on the Shining Light Productions site. Typically we use the full versions rather than the Light versions. - [depot_tools](https://dev.chromium.org/developers/how-tos/install-depot-tools) - Installation is platform specific. To skip installing this, follow the relevant instructions in [CLI Project Generation](CLI-Project-Generation). ### Linux Dependencies From 862b61c7a9f4bf50ff38195de75b648250a49f2e Mon Sep 17 00:00:00 2001 From: Barinade Date: Tue, 21 Mar 2023 21:49:38 -0500 Subject: [PATCH 10/10] Iterate Rebirth version --- Themes/Rebirth/Scripts/00 ThemeInfo.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Themes/Rebirth/Scripts/00 ThemeInfo.lua b/Themes/Rebirth/Scripts/00 ThemeInfo.lua index e1a49dbd30..d4a421d96c 100644 --- a/Themes/Rebirth/Scripts/00 ThemeInfo.lua +++ b/Themes/Rebirth/Scripts/00 ThemeInfo.lua @@ -1,7 +1,7 @@ THEMEINFO = { Name = "Rebirth", - Version = "5", - Date = "20230301", + Version = "6", + Date = "20230321", Author = "Celebelian, poco0317, and the Etterna Team" }