-- Copyright (c) 2019-2024 David Vogel -- -- This software is released under the MIT License. -- https://opensource.org/licenses/MIT ----------------------- -- Load global stuff -- ----------------------- -------------------------- -- Load library modules -- -------------------------- local Coords = require("coordinates") local DebugAPI = require("noita-api.debug") ---------- -- Code -- ---------- ---Removes all messages with the AutoClose flag. ---Use this before you recreate all auto closing messages. function Message:CloseAutoClose() self.List = self.List or {} for k, message in pairs(self.List) do if message.AutoClose then self.List[k] = nil end end end ---Add a general runtime error message to the message list. ---This will always overwrite the last runtime error with the same id. ---@param id string ---@param ... string function Message:ShowRuntimeError(id, ...) self.List = self.List or {} self.List["RuntimeError" .. id] = { Type = "error", Lines = { ... }, } end ---Calls func and catches any exception. ---If there is one, a runtime error message will be shown to the user. ---@param id string ---@param func function function Message:CatchException(id, func) local ok, err = xpcall(func, debug.traceback) if not ok then print(string.format("An exception happened in %s: %s", id, err)) self:ShowRuntimeError(id, string.format("An exception happened in %s", id), err) end end ---Request the user to let the addon automatically reset some Noita settings. function Message:ShowResetNoitaSettings() self.List = self.List or {} self.List["ResetNoitaSettings"] = { Type = "info", Lines = { "You requested to reset some game settings like:", "- Custom resolutions", "- Screen-shake intensity", " ", "Press the following button to reset the settings and close Noita automatically:", }, Actions = { { Name = "Reset and close (May corrupt current save!)", Hint = nil, HintDesc = nil, Callback = function() Modification:Reset() end }, }, } end ---Request the user to let the addon automatically set Noita settings based on the given callback. ---@param callback function ---@param desc string -- What's wrong. function Message:ShowSetNoitaSettings(callback, desc) self.List = self.List or {} self.List["SetNoitaSettings"] = { Type = "warning", Lines = { "It seems that not all requested settings are applied to Noita:", desc or "", " ", "Press the button at the bottom to set up and close Noita automatically.", " ", "You can always reset any custom settings by right clicking the `start capture`", "button at the top left.", }, Actions = { { Name = "Setup and close (May corrupt current save!)", Hint = nil, HintDesc = nil, Callback = callback }, }, AutoClose = true, -- This message will automatically close. } end ---Request the user to restart Noita. ---@param desc string -- What's wrong. function Message:ShowRequestRestart(desc) self.List = self.List or {} self.List["RequestRestart"] = { Type = "warning", Lines = { "It seems that not all requested settings are applied to Noita:", desc or "", " ", "To resolve this issue, restart the game.", }, AutoClose = true, -- This message will automatically close. } end ---Request the user to let the addon automatically set Noita settings based on the given callback. ---@param callback function ---@param desc string -- What's wrong. function Message:ShowWrongResolution(callback, desc) self.List = self.List or {} self.List["WrongResolution"] = { Type = "warning", Lines = { "The resolution changed:", desc or "", " ", "Press the button at the bottom to set up and close Noita automatically.", " ", "You can always reset any custom settings by right clicking the `start capture`", "button at the top left.", }, Actions = { { Name = "Setup and close (May corrupt current save!)", Hint = nil, HintDesc = nil, Callback = callback }, }, AutoClose = true, -- This message will automatically close. } end ---Tell the user that there are files in the output directory. function Message:ShowOutputNonEmpty() self.List = self.List or {} self.List["OutputNonEmpty"] = { Type = "hint", Lines = { "There are already files in the output directory.", "If you are continuing a capture session, ignore this message.", " ", "If you are about to capture a new map, make sure to delete all files in the output directory first." }, Actions = { { Name = "Open output directory", Hint = nil, HintDesc = nil, Callback = function() os.execute("start .\\mods\\noita-mapcap\\output\\") end }, }, } end ---Tell the user that some settings are not optimal. ---@param ... string function Message:ShowGeneralSettingsProblem(...) self.List = self.List or {} self.List["GeneralSettingsProblem"] = { Type = "hint", Lines = { ... }, AutoClose = true, -- This message will automatically close. } end ---Tell the user that there is something wrong with the mod installation. ---@param ... string function Message:ShowGeneralInstallationProblem(...) self.List = self.List or {} self.List["GeneralInstallationProblem"] = { Type = "error", Lines = { ... }, } end ---Tell the user that some modification couldn't be applied because it is unsupported. ---@param realm "config"|"magicNumbers"|"processMemory"|"filePatches" ---@param name string ---@param value any function Message:ShowModificationUnsupported(realm, name, value) self.List = self.List or {} self.List["ModificationFailed"] = self.List["ModificationFailed"] or { Type = "warning", } -- Create or append to list of modifications. -- We have to prevent duplicate entries. self.List["ModificationFailed"].ModificationEntries = self.List["ModificationFailed"].ModificationEntries or {} local found for _, modEntry in ipairs(self.List["ModificationFailed"].ModificationEntries) do if modEntry.realm == realm and modEntry.name == name then found = true break end end if not found then table.insert(self.List["ModificationFailed"].ModificationEntries, {realm = realm, name = name, value = value}) end -- Build message lines. self.List["ModificationFailed"].Lines = {"The mod couldn't apply the following changes:"} table.insert(self.List["ModificationFailed"].Lines, " ") for _, modEntry in ipairs(self.List["ModificationFailed"].ModificationEntries) do table.insert(self.List["ModificationFailed"].Lines, string.format("- %q in %q realm", modEntry.name, modEntry.realm)) end table.insert(self.List["ModificationFailed"].Lines, " ") table.insert(self.List["ModificationFailed"].Lines, "This simply means that the mod can't automatically apply this change in the Noita version you are using.") table.insert(self.List["ModificationFailed"].Lines, "If you are running a non-beta version of Noita, feel free to open an issue at https://github.com/Dadido3/noita-mapcap.") -- Tell the user to change some settings manually, if possible. local manuallyWithF7 = {} local possibleManualWithF7 = {mPostFxDisabled = true, mGuiDisabled = true, mGuiHalfSize = true, mFogOfWarOpenEverywhere = true, mTrailerMode = true, mDayTimeRotationPause = true, mPlayerNeverDies = true, mFreezeAI = true} for _, modEntry in ipairs(self.List["ModificationFailed"].ModificationEntries) do if modEntry.realm == "processMemory" and possibleManualWithF7[modEntry.name] then table.insert(manuallyWithF7, modEntry) end end if #manuallyWithF7 > 0 then table.insert(self.List["ModificationFailed"].Lines, " ") table.insert(self.List["ModificationFailed"].Lines, "You can apply the setting manually:") table.insert(self.List["ModificationFailed"].Lines, " ") table.insert(self.List["ModificationFailed"].Lines, "- Press F7 to open the debug menu.") for _, modEntry in ipairs(manuallyWithF7) do table.insert(self.List["ModificationFailed"].Lines, string.format("- Change %q to %q.", modEntry.name, modEntry.value)) end table.insert(self.List["ModificationFailed"].Lines, "- Press F7 again to close the menu.") table.insert(self.List["ModificationFailed"].Lines, "- Close this warning when you are done.") end end