From e6680522b46c99930ed44ab68f309bff0a459ea2 Mon Sep 17 00:00:00 2001 From: NickCloud Date: Mon, 16 Oct 2023 21:32:53 +0200 Subject: [PATCH] Fix/Changes: Combobox callback fixes/changes With this commit comboboxes won't throw an error for a "nil" callback anymore. For some reason the game can not keep track of callbacks correctly anymore. Also added a "oldValue" to the onSelect/onChange function of the combobox to ensure the previous set value is still sent. --- CHANGELOG.md | 4 +++ .../client/cl_vskin/vgui/dcombobox_ttt2.lua | 29 ++++++++++++++++--- .../client/cl_vskin/vgui/dform_ttt2.lua | 6 ++-- .../menus/gamemode/language/language.lua | 4 +-- 4 files changed, 34 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b3addc7f9..96a115005 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,10 @@ All notable changes to TTT2 will be documented here. Inspired by [keep a changel - Updated file code to read from `data_static` as fallback in new location allowed in .gma (by @EntranceJew) - Scoreboard now sets preferred player volume and mute state in client's new `ttt2_voice` table (by @EntranceJew) - Keyed by steamid64, making it more reliable than UniqueID or the per-session mute and volume levels. +- Added "olValue" to the onSelect/onChange function of comboboxes (by @NickCloudAT) + +### Fixed +- Fixed Comboboxes throwing an invalid callback error in some instances (by @NickCloudAT) ## [v0.11.7b](https://github.com/TTT-2/TTT2/tree/v0.11.7b) (2022-08-27) diff --git a/gamemodes/terrortown/gamemode/client/cl_vskin/vgui/dcombobox_ttt2.lua b/gamemodes/terrortown/gamemode/client/cl_vskin/vgui/dcombobox_ttt2.lua index 5eed77dce..f551240ce 100644 --- a/gamemodes/terrortown/gamemode/client/cl_vskin/vgui/dcombobox_ttt2.lua +++ b/gamemodes/terrortown/gamemode/client/cl_vskin/vgui/dcombobox_ttt2.lua @@ -175,17 +175,19 @@ function PANEL:ChooseOptionID(index, ignoreConVar) local choice = choices[index] local value = choice.value + local oldValue = self.selected and choices[self.selected].value or nil self.selected = index self:SetText(choice.title) - self:OnSelect(index, value, choice.data) self:CloseMenu() - if ignoreConVar then return end + if not ignoreConVar then + self:SetConVarValues(tostring(value)) + end - self:SetConVarValues(tostring(value)) + self:OnSelect(index, value, choice.data, oldValue) end --- @@ -241,8 +243,9 @@ end -- @param number index -- @param string/number value is indexable -- @param any data +-- @param string/number value is indexable -- @realm client -function PANEL:OnSelect(index, value, data) +function PANEL:OnSelect(index, value, data, oldValue) end @@ -357,6 +360,22 @@ local function AddConVarChangeCallback(menu, conVar) cvars.AddChangeCallback(conVar, OnConVarChangeCallback, myIdentifierString) end +--- +-- The game can not keep track of nil callbacks but does not +-- remove them automatically. Here we go over all callbacks and delete them +-- before they get used and throw an error +local function CleanUpConVarCallbacks(conVar) + for k, v in ipairs(cvars.GetConVarCallbacks(conVar)) do + if not istable(v) then continue end + + local identifier = v[2] or "" + + if not string.find(identifier, "TTT2F1MenuConVarChangeCallback") or not isfunction(v[1]) then continue end + + cvars.RemoveChangeCallback(conVar, identifier) + end +end + --- -- @param string conVarName -- @realm client @@ -369,6 +388,7 @@ function PANEL:SetConVar(conVarName) self:SetValue(conVar:GetString(), true) self:SetDefaultValue(conVar:GetDefault()) + CleanUpConVarCallbacks(conVarName) AddConVarChangeCallback(self, conVarName) end @@ -387,6 +407,7 @@ function PANEL:SetServerConVar(conVarName) end end) + CleanUpConVarCallbacks(conVarName) AddConVarChangeCallback(self, conVarName) end diff --git a/gamemodes/terrortown/gamemode/client/cl_vskin/vgui/dform_ttt2.lua b/gamemodes/terrortown/gamemode/client/cl_vskin/vgui/dform_ttt2.lua index 39aabd809..2c2bff124 100644 --- a/gamemodes/terrortown/gamemode/client/cl_vskin/vgui/dform_ttt2.lua +++ b/gamemodes/terrortown/gamemode/client/cl_vskin/vgui/dform_ttt2.lua @@ -291,7 +291,7 @@ end -- @note Structure of data = { -- label, default, choices = { [1] = {title, value, select, icon, additionalData}, [2] = ...}, -- conVar, serverConVar, selectId or selectTitle or selectValue, --- function OnChange(value, additionalData, dropDownPanel), master = { function AddSlave(self, slave) } +-- function OnChange(value, additionalData, oldValue, dropDownPanel), master = { function AddSlave(self, slave) } -- } -- @note If ConVars are used the values are always strings, so make sure, that you used strings for values, when setting up choices -- @return Panel The created combobox @@ -344,9 +344,9 @@ function PANEL:MakeComboBox(data) end end - right.OnSelect = function(slf, index, value, additionalData) + right.OnSelect = function(slf, index, value, additionalData, oldValue) if data and isfunction(data.OnChange) then - data.OnChange(value, additionalData, slf) + data.OnChange(value, additionalData, oldValue, slf) end end diff --git a/lua/terrortown/menus/gamemode/language/language.lua b/lua/terrortown/menus/gamemode/language/language.lua index f2c20dc56..f9245a8c7 100644 --- a/lua/terrortown/menus/gamemode/language/language.lua +++ b/lua/terrortown/menus/gamemode/language/language.lua @@ -25,8 +25,8 @@ function CLGAMEMODESUBMENU:Populate(parent) label = "label_language_set", convar = "ttt_language", choices = choices, - OnChange = function(value) - if value == GetActiveLanguageName() then return end + OnChange = function(value, _, oldValue) + if value == oldValue then return end vguihandler.InvalidateVSkin() vguihandler.Rebuild()