--[[
Name: Def Pack
Copyright (C) Levis, 2025
Author: Levis
All Rights Reserved
Date: 22.08.2025
Version: 1.0.0.4
]]

--[[
-- Important:
-- Not to be added to any mods / maps or modified from its current release form.
-- No modifications may be made to this script without written permission from Levis.

-- Wichtig:
-- Darf nicht zu Mods / Karten hinzugefügt oder in seiner aktuellen Veröffentlichungsform geändert werden.
-- Änderungen an diesem Skript dürfen nur mit schriftlicher Genehmigung von Levis vorgenommen werden.

-- Fontos:
-- Nem adható hozzá semmilyen modhoz / térképhez, és nem módosítható az aktuális kiadási formájában.
-- A szkript módosítása csak Levis írásos engedélyével történhet.

-- Important :
-- Ne doit pas être ajouté à des mods / cartes ou modifié sous sa forme de publication actuelle.
-- Aucune modification ne peut être apportée à ce script sans l'autorisation écrite de Levis.

-- Importante:
-- No debe añadirse a ningún mod / mapa ni modificarse desde su versión actual.
-- No se pueden hacer modificaciones a este script sin el permiso por escrito de Levis.

-- Önemli:
-- Hiçbir moda / haritaya eklenemez veya mevcut yayınlanan halinden değiştirilemez.
-- Bu betikte Levis'in yazılı izni olmadan değişiklik yapılamaz.

-- Ważne:
-- Nie może być dodawany do żadnych modów / map ani modyfikowany w swojej obecnej formie.
-- Żadne zmiany nie mogą być dokonywane w tym skrypcie bez pisemnej zgody Levisa.

-- Importante:
-- Non deve essere aggiunto a nessuna mod / mappa né modificato rispetto alla versione attuale.
-- Nessuna modifica può essere apportata a questo script senza il permesso scritto di Levis.

-- Importante:
-- Não deve ser adicionado a nenhum mod / mapa nem modificado em sua versão atual.
-- Nenhuma modificação pode ser feita neste script sem permissão por escrito de Levis.

-- Vigtigt:
-- Må ikke tilføjes til nogen mods / kort eller ændres fra den nuværende udgivelsesform.
-- Ingen ændringer må foretages i dette script uden skriftlig tilladelse fra Levis.

-- Viktig:
-- Skal ikke legges til i noen mods / kart eller endres fra sin nåværende utgivelsesform.
-- Ingen endringer kan gjøres i dette skriptet uten skriftlig tillatelse fra Levis.

-- Viktigt:
-- Får inte läggas till i några mods / kartor eller ändras från sin nuvarande version.
-- Inga ändringar får göras i detta skript utan skriftligt tillstånd från Levis.

-- 重要:
-- このスクリプトは、いかなるModやマップにも追加したり、現在のリリース形態から変更したりすることはできません。
-- Levis の書面による許可なしに、このスクリプトを変更することはできません。

-- Důležité:
-- Nesmí být přidáno do žádných modů / map ani upraveno z aktuální verze.
-- Žádné úpravy tohoto skriptu nejsou povoleny bez písemného souhlasu Levis.
]]

DEFUsageMenu = {} DEFUsageMenu.settings = {ENABLED = true, MULTIPLIER = 4} DEFUsageMenu._PREV_ENABLED = nil DEFUsageMenu._PREV_MULTIPLIER = nil _G.DEFUsageMenu_PENDING_RELOAD = false local defusageHeader = g_i18n:getText("defusage_header") local defusageToggle = g_i18n:getText("defusage_toggle") local defusageHelp = g_i18n:getText("defusage_help") local defusageMultiplier = g_i18n:getText("defusage_multiplier") local defusageMultiplierHelp = g_i18n:getText("defusage_multiplier_help") function DEFUsageMenu:getSettingsFilePath() local dir = getUserProfileAppPath() .. "modSettings/" createFolder(dir) return dir .. "DEFUsage.xml" end function showDialog(message, callback, okText) local dialog = g_gui:showDialog("InfoDialog") if dialog and dialog.target then dialog.target:setDialogType(DialogElement.TYPE_WARNING) dialog.target:setText(message or "OK") dialog.target:setButtonTexts(okText or "OK") if callback then dialog.target:setCallback( function() callback() end ) end else print("Error: Could not show dialog.") if callback then callback() end end end local function stringToBool(val) if type(val) == "boolean" then return val end if type(val) == "string" then val = val:lower() if val == "true" then return true end if val == "false" then return false end end return nil end function DEFUsageMenu:saveSettings() if not g_server then return end local path = self:getSettingsFilePath() if not path then print("[DEFGui] No path for save!") return end local xmlFile = createXMLFile("DEFUsageMenu", path, "settings") setXMLBool(xmlFile, "settings#ENABLED", self.settings.ENABLED == true) setXMLInt(xmlFile, "settings#MULTIPLIER", self.settings.MULTIPLIER or 4) saveXMLFile(xmlFile) delete(xmlFile) end function DEFUsageMenu:loadSettings() if not g_server then return end local path = self:getSettingsFilePath() if not path or not fileExists(path) then return end local xmlFile = loadXMLFile("DEFUsageMenu", path) if xmlFile ~= nil then local enabled = getXMLBool(xmlFile, "settings#ENABLED") if enabled == nil then enabled = getXMLString(xmlFile, "settings#ENABLED") enabled = (enabled and enabled:lower() == "true") or false end self.settings.ENABLED = (enabled ~= false) self.settings.MULTIPLIER = getXMLInt(xmlFile, "settings#MULTIPLIER") or 4 delete(xmlFile) end if _G.DEFUsage then DEFUsage.ENABLED = self.settings.ENABLED DEFUsage.MultiplierIndex = self.settings.MULTIPLIER end end DEFUsageSyncEvent = {} DEFUsageSyncEvent_mt = Class(DEFUsageSyncEvent, Event) InitEventClass(DEFUsageSyncEvent, "DEFUsageSyncEvent") function DEFUsageSyncEvent:emptyNew() return Event.new(DEFUsageSyncEvent_mt) end function DEFUsageSyncEvent:new(enabled, multiplier) local self = DEFUsageSyncEvent:emptyNew() self.enabled = enabled self.multiplier = multiplier return self end function DEFUsageSyncEvent:writeStream(streamId, connection) streamWriteBool(streamId, self.enabled) streamWriteInt8(streamId, self.multiplier or 2) end function DEFUsageSyncEvent:readStream(streamId, connection) self.enabled = streamReadBool(streamId) self.multiplier = streamReadInt8(streamId) self:run(connection) end function DEFUsageSyncEvent:run(connection) if not connection:getIsServer() then DEFUsageMenu.settings.ENABLED = self.enabled DEFUsageMenu.settings.MULTIPLIER = self.multiplier if g_screen and g_screen.currentGui and g_screen.currentGui.frame and g_screen.currentGui.frame.generalSettingsLayout then for _, elem in ipairs(g_screen.currentGui.frame.generalSettingsLayout.elements) do if elem.elements and elem.elements[2] and elem.elements[2]:getText() == "Enable DEF Usage" then elem.elements[1]:setIsChecked(self.enabled) elseif elem.elements and elem.elements[2] and elem.elements[2]:getText() == "DEF Usage Multiplier" then elem.elements[1]:setState(self.multiplier or 4) end end end end end function DEFUsageMenu:broadcastSettings() if g_server ~= nil then g_server:broadcastEvent(DEFUsageSyncEvent:new(self.settings.ENABLED, self.settings.MULTIPLIER)) end end local enableElem, multiElem local multiElemDropdown local function updateEnableStateFromSettings() if enableElem and enableElem.setIsChecked then enableElem:setIsChecked(DEFUsageMenu.settings.ENABLED == true) end if multiElemDropdown then if multiElemDropdown.setState then multiElemDropdown:setState(DEFUsageMenu.settings.MULTIPLIER or 4) end if multiElemDropdown.setDisabled then multiElemDropdown:setDisabled(not DEFUsageMenu.settings.ENABLED) end end DEFUsageMenu._PREV_ENABLED     = DEFUsageMenu.settings.ENABLED DEFUsageMenu._PREV_MULTIPLIER  = DEFUsageMenu.settings.MULTIPLIER end function injectDEFUsageMenu(settingsFrame) DEFUsageMenu._PREV_ENABLED = DEFUsageMenu.settings.ENABLED DEFUsageMenu._PREV_MULTIPLIER = DEFUsageMenu.settings.MULTIPLIER if not settingsFrame.levDefUsageInjected then settingsFrame.levDefUsageInjected = true local layout = settingsFrame.generalSettingsLayout local headerRef, checkboxRef, dropdownRef = nil, settingsFrame.checkInvertYLook, settingsFrame.multiCameraSensitivity for _, elem in ipairs(layout.elements) do if elem.name == "sectionHeader" then headerRef = elem break end end if not (headerRef and checkboxRef and dropdownRef) then return end local header = headerRef:clone() header:setText(g_i18n:getText("defusage_header")) layout:addElement(header) enableElem = checkboxRef.parent:clone().elements[1] layout:addElement(enableElem.parent) enableElem.parent.elements[2]:setText(g_i18n:getText("defusage_toggle")) enableElem.elements[1]:setText(g_i18n:getText("defusage_help")) local multiElemParent = dropdownRef.parent:clone() multiElemParent.elements[2]:setText(g_i18n:getText("defusage_multiplier")) multiElemParent.elements[1]:setTexts({"0.25X", "0.5X", "1X", "1.5X", "2X", "3X", "4X", "5X"}) multiElemParent.elements[1]:setState(DEFUsageMenu.settings.MULTIPLIER or 4) multiElemDropdown = multiElemParent.elements[1] multiElemDropdown.onClickCallback = function(dropdown, state) local value = 4 if dropdown and dropdown.getState then value = dropdown:getState() elseif state then value = state end DEFUsageMenu.settings.MULTIPLIER = value if _G.DEFUsage then DEFUsage.MultiplierIndex = value end end layout:addElement(multiElemParent) if multiElemDropdown.elements and multiElemDropdown.elements[1] then multiElemDropdown.elements[1]:setText(g_i18n:getText("defusage_multiplier_help")) end enableElem.onClickCallback = function(_, _) local enabled = enableElem:getIsChecked() DEFUsageMenu.settings.ENABLED = enabled if _G.DEFUsage then DEFUsage.ENABLED = enabled end if multiElemDropdown and multiElemDropdown.setDisabled then multiElemDropdown:setDisabled(not enabled) end end if multiElemDropdown and multiElemDropdown.setDisabled then multiElemDropdown:setDisabled(not DEFUsageMenu.settings.ENABLED) end updateEnableStateFromSettings() end settingsFrame.generalSettingsLayout:invalidateLayout() local layout = settingsFrame.generalSettingsLayout for _, elem in ipairs(layout.elements) do if elem.elements and elem.elements[2] and elem.elements[2]:getText() == g_i18n:getText("defusage_multiplier") then local dropdown = elem.elements[1] if dropdown and dropdown.setDisabled then dropdown:setDisabled(not DEFUsageMenu.settings.ENABLED) end end end updateEnableStateFromSettings() end InGameMenuSettingsFrame.onFrameOpen = Utils.appendedFunction(InGameMenuSettingsFrame.onFrameOpen, injectDEFUsageMenu) function DEFUsageMenu:updateSettingsFromGui(settingsFrame) local layout = settingsFrame.generalSettingsLayout local enableElem, multiElem for _, elem in ipairs(layout.elements) do if elem.elements and elem.elements[2] then local text = elem.elements[2]:getText() if text == g_i18n:getText("defusage_toggle") then enableElem = elem.elements[1] elseif text == g_i18n:getText("defusage_multiplier") then multiElem = elem.elements[1] end end end local newEnabled = enableElem and enableElem:getIsChecked() or false local newMultiplier = multiElem and multiElem:getState() or 2 if newMultiplier < 1 or newMultiplier > 8 then newMultiplier = 4 end if DEFUsageMenu._PREV_ENABLED ~= nil and newEnabled ~= DEFUsageMenu._PREV_ENABLED and newEnabled then _G.DEFUsageMenu_PENDING_RELOAD = true end DEFUsageMenu.settings.ENABLED = newEnabled DEFUsageMenu.settings.MULTIPLIER = newMultiplier if _G.DEFUsage then DEFUsage.ENABLED = newEnabled DEFUsage.MultiplierIndex = newMultiplier end end InGameMenuSettingsFrame.onFrameClose = Utils.appendedFunction( InGameMenuSettingsFrame.onFrameClose, function(self) DEFUsageMenu:updateSettingsFromGui(self) DEFUsageMenu:saveSettings() if g_server ~= nil then DEFUsageMenu:broadcastSettings() end if _G.DEFUsageMenu_PENDING_RELOAD then _G.DEFUsageMenu_PENDING_RELOAD = false local dialogtext1 = g_i18n:getText("dialog_text1") local dialogtext2 = g_i18n:getText("dialog_text2") local dialogtext = dialogtext1 .. "\n\n" .. dialogtext2 showDialog(dialogtext, nil, "OK") end end ) Mission00.load = Utils.appendedFunction( Mission00.load, function() DEFUsageMenu:loadSettings() end ) Mission00.saveSavegame = Utils.appendedFunction( Mission00.saveSavegame, function() DEFUsageMenu:saveSettings() end ) Mission00.onPlayerJoinedGame = Utils.appendedFunction( Mission00.onPlayerJoinedGame, function(_, connection) if g_server ~= nil and connection ~= nil and not connection:getIsServer() then DEFUsageMenu:broadcastSettings() end end ) 