will_b_gaming Posted March 14, 2025 Share Posted March 14, 2025 I am trying to make a simple client mod that removes Wes from the pool of random characters. I have: AddClassPostConstruct("screens/redux/lobbyscreen", SelectRandomCharacter) since "screens/lobbyscreen" didn't result in any functions being executed. However, I cannot find the name of the random button, and I am unfamiliar with how AddClassPostConstruct works. Link to comment https://forums.kleientertainment.com/forums/topic/164875-cant-find-random-button-on-screensreduxlobbyscreen/ Share on other sites More sharing options...
oregu Posted March 17, 2025 Share Posted March 17, 2025 (edited) Old solution (leaving it here to illustrate my process) I decided to annotate it because you said you wanted help modding: Spoiler Spoiler local IsCharacterOwned_old = GLOBAL.IsCharacterOwned -- Almost any global function can be overwritten. We are using _old to declare this as a base for our hook local lockedlist = {} local function LockCharacter(data) -- Holding a fn hook for IsCharacterOwned for later (a fn hook is basically adding onto an already existing fn) if type(data) == "string" then -- if we only have a string as our data, add it to the lockedlist table.insert(lockedlist, data) else for _,character in pairs(data) do -- if we have a table as an argument, annex the whole table to the lockedlist table.insert(lockedlist, character) end end -- if you want to make sure people aren't misuing the function you can do GLOBAL.assert(type(data) == "string" or type(data) == "table", "Must be string or table") but i think the usecase for this fn is obvious enough GLOBAL.IsCharacterOwned = function(character) -- rewriting the global IsCharacterOwned fn for _,lockedchar in pairs(lockedlist) do -- adding a new check and ending the function with false early if we have a character we want to not be in the random pool if character == lockedchar then return false end end return IsCharacterOwned_old(character) -- returning and executing the old fn's results end end local function UnlockCharacters() -- resetting the table and IsCharacterOwned fn to it's original state lockedlist = {} GLOBAL.IsCharacterOwned = IsCharacterOwned_old end AddClassPostConstruct("screens/redux/lobbyscreen", function(self) local OnControl_old = self.OnControl self.OnControl = function(self, ...) -- using self.OnControl as a listener. this will be explained later local character = self.lobbycharacter -- print(character) -- currently selected character if character == "random" then LockCharacter("wes") end if character ~= "random" then UnlockCharacters() end local result = OnControl_old(self, ...) if character == "random" then UnlockCharacters() end return result end end) This works, but the main issue with this solution was If you select random but go back, the character will show as locked, but you can still select it. Unfortunately doing the same thing with GLOBAL.MODCHARACTEREXCEPTIONS_DST makes the characters removed permanently once random is selected, making it a worse option for this. New solution that I found no issues with (use this): You told me you wanted help understanding modding, so I decided to annotate it Spoiler local IsCharacterOwned_old = GLOBAL.IsCharacterOwned local lockedlist = {} local function LockCharacter(data) if type(data) == "string" then table.insert(lockedlist, data) else for _,character in pairs(data) do table.insert(lockedlist, character) end end GLOBAL.IsCharacterOwned = function(character) for _,lockedchar in pairs(lockedlist) do if character == lockedchar then return false end end return IsCharacterOwned_old(character) end end local function UnlockCharacters() lockedlist = {} GLOBAL.IsCharacterOwned = IsCharacterOwned_old end local function NewNextButton(self) -- self is meant to be the LoadoutPanel local OnNextButton_old = self.OnNextButton self.OnNextButton = function(self, ...) LockCharacter("wes") -- ante-hooking the locked character state so the random result is different. OnNextButton uses IsCharacterOwned as one of its determiners to which character is selected. locked characters will not be selected. local result = OnNextButton_old(self, ...) -- saving the result of the original next button function and executing it, by the time this is done, the randomization has been done. UnlockCharacters() -- we are post-hooking OnNextButton because we want the locked character check to be the same as before right after the nextbutton fn is dealt with return result -- now we can finish the function and return the result end end AddClassPostConstruct("screens/redux/lobbyscreen", function(self) local OnControl_old = self.OnControl self.OnControl = function(self, ...) -- we are using OnControl as a listener, because if we aren't controlling in the menu, no point in overwriting anything if tostring(self.panel) == "LoadoutPanel" and self.lobbycharacter == "random" then -- getting the current panel name and selected lobby character NewNextButton(self.panel) -- we must overwrite the next button each time we encounter it, otherwise the LoadoutPanel fn could be different end return OnControl_old(self, ...) -- execute the original function and return it at the same time. generally good practice for fn hooks is returning the original function's result, but it's not always necessary. since this returns an actual result, it's crucial, though end end) I would like to use CHARACTEREXCEPTIONS but because of the possibility of using a moon rock idol and the characters not being reloaded, I have to stick with IsCharacterLocked instead. I couldn't find a way to overwrite the panel directly so I listened for when the current panel is LoadoutPanel. If you want to test if it really works, do this. The expected result is that you are Wigfrid each time. LockCharacter({"wes", "wortox", "willow", "wilson", "wendy", "waxwell", "wanda", "wolfgang", "wx78", "wickerbottom", "woodie", "warly", "webber", "winona", "wormwood", "wurt", "walter"}) Edited March 17, 2025 by oregu Link to comment https://forums.kleientertainment.com/forums/topic/164875-cant-find-random-button-on-screensreduxlobbyscreen/#findComment-1807693 Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now