Added plugins.txt manager to the launcher
This commit is contained in:
parent
734ee8888f
commit
2eaab91a27
@ -10,7 +10,18 @@
|
|||||||
#include <ButtonConstants.au3>
|
#include <ButtonConstants.au3>
|
||||||
#include <StaticConstants.au3>
|
#include <StaticConstants.au3>
|
||||||
#include <ComboConstants.au3>
|
#include <ComboConstants.au3>
|
||||||
|
#include <ListViewConstants.au3>
|
||||||
|
#include <GuiListView.au3>
|
||||||
|
#include <GuiImageList.au3>
|
||||||
|
#include <FileConstants.au3>
|
||||||
|
#include <StructureConstants.au3>
|
||||||
|
#include <WindowsNotifsConstants.au3>
|
||||||
|
#include <WindowsSysColorConstants.au3>
|
||||||
|
#include <APIThemeConstants.au3>
|
||||||
|
#include <Array.au3>
|
||||||
#include <WinAPI.au3>
|
#include <WinAPI.au3>
|
||||||
|
#include <WinAPITheme.au3>
|
||||||
|
#include <WinAPIGdiDC.au3>
|
||||||
#include <WinAPIProc.au3>
|
#include <WinAPIProc.au3>
|
||||||
#include <SendMessage.au3>
|
#include <SendMessage.au3>
|
||||||
|
|
||||||
@ -33,6 +44,22 @@ Global Const $REG_START_STEAM = "Start_Steam"
|
|||||||
Global Const $AA_TAA = "TAA (Best quality)"
|
Global Const $AA_TAA = "TAA (Best quality)"
|
||||||
Global Const $AA_FXAA = "FXAA (Low)"
|
Global Const $AA_FXAA = "FXAA (Low)"
|
||||||
Global Const $AA_OFF = "Off (Best performance)"
|
Global Const $AA_OFF = "Off (Best performance)"
|
||||||
|
; Plugin load order classes - the engine always loads masters before regular plugins
|
||||||
|
Global Const $PLUGIN_CLASS_MASTER = 1
|
||||||
|
Global Const $PLUGIN_CLASS_NORMAL = 2
|
||||||
|
Global Const $PLUGIN_FLAG_MASTER = 0x00000001
|
||||||
|
Global Const $PLUGIN_FLAG_LIGHT = 0x00000200
|
||||||
|
; Check box images of the plugin list (state image indexes)
|
||||||
|
Global Const $PLUGIN_STATE_UNCHECKED = 1
|
||||||
|
Global Const $PLUGIN_STATE_CHECKED = 2
|
||||||
|
Global Const $PLUGIN_STATE_UNCHECKED_DIMMED = 3
|
||||||
|
Global Const $PLUGIN_STATE_CHECKED_DIMMED = 4
|
||||||
|
; Theme parts used to draw them (BUTTON class)
|
||||||
|
Global Const $THEME_BP_CHECKBOX = 3
|
||||||
|
Global Const $THEME_CB_UNCHECKED = 1
|
||||||
|
Global Const $THEME_CB_UNCHECKED_DISABLED = 4
|
||||||
|
Global Const $THEME_CB_CHECKED = 5
|
||||||
|
Global Const $THEME_CB_CHECKED_DISABLED = 8
|
||||||
Global $PLUGINS_DIR = ""
|
Global $PLUGINS_DIR = ""
|
||||||
Global $PLUGINS_FILE = ""
|
Global $PLUGINS_FILE = ""
|
||||||
Global $DOCUMENTS_DIR = ""
|
Global $DOCUMENTS_DIR = ""
|
||||||
@ -71,9 +98,28 @@ Global $chkController, $chkVibration
|
|||||||
Global $chkStartSteam
|
Global $chkStartSteam
|
||||||
Global $grpIniFiles, $btnOpenEnderalIni, $btnOpenEnderalPrefsIni, $btnOpenCustomIni, $btnOpenModIni, $btnOpenSavegames
|
Global $grpIniFiles, $btnOpenEnderalIni, $btnOpenEnderalPrefsIni, $btnOpenCustomIni, $btnOpenModIni, $btnOpenSavegames
|
||||||
|
|
||||||
|
; Plugins tab controls
|
||||||
|
Global $lvPlugins, $hLvPlugins = 0
|
||||||
|
Global $btnPluginUp, $btnPluginDown, $btnPluginsEnableAll, $btnPluginsDisableAll
|
||||||
|
Global $lblPluginsCount, $lblPluginsHint
|
||||||
|
Global $hPluginStateImages = 0
|
||||||
|
|
||||||
|
; Plugin list state
|
||||||
|
; [i][0] = file name, [i][1] = enabled, [i][2] = locked (always loaded by the game),
|
||||||
|
; [i][3] = load order class, [i][4] = type label, [i][5] = present in plugins.txt
|
||||||
|
Global $aPluginList[1][6]
|
||||||
|
Global $iPluginListCount = 0
|
||||||
|
Global $bPluginListLoaded = False
|
||||||
|
Global $bPluginListDirty = False
|
||||||
|
Global $bPluginListUpdating = False
|
||||||
|
Global $bPluginListReadOnly = False
|
||||||
|
|
||||||
; Steam version detection
|
; Steam version detection
|
||||||
Global $bIsSteamVersion = False
|
Global $bIsSteamVersion = False
|
||||||
|
|
||||||
|
; Mod Organizer 2 directory, empty when the launcher was not started by MO2
|
||||||
|
Global $MO2_DIR = ""
|
||||||
|
|
||||||
; ============================================
|
; ============================================
|
||||||
; Helper Functions
|
; Helper Functions
|
||||||
; ============================================
|
; ============================================
|
||||||
@ -562,6 +608,9 @@ Func Main()
|
|||||||
; Register message handler for slider updates
|
; Register message handler for slider updates
|
||||||
GUIRegisterMsg($WM_HSCROLL, "WM_HSCROLL")
|
GUIRegisterMsg($WM_HSCROLL, "WM_HSCROLL")
|
||||||
|
|
||||||
|
; Register message handler for plugin list check boxes
|
||||||
|
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY")
|
||||||
|
|
||||||
; Main loop
|
; Main loop
|
||||||
MainLoop()
|
MainLoop()
|
||||||
|
|
||||||
@ -586,6 +635,80 @@ Func WM_HSCROLL($hWnd, $iMsg, $wParam, $lParam)
|
|||||||
Return $GUI_RUNDEFMSG
|
Return $GUI_RUNDEFMSG
|
||||||
EndFunc
|
EndFunc
|
||||||
|
|
||||||
|
Func WM_NOTIFY($hWnd, $iMsg, $wParam, $lParam)
|
||||||
|
; Handles the plugin list: check box changes send no GUIGetMsg event, and rows that
|
||||||
|
; cannot be changed are drawn dimmed
|
||||||
|
If $hLvPlugins = 0 Then Return $GUI_RUNDEFMSG
|
||||||
|
|
||||||
|
Local $tNMHDR = DllStructCreate($tagNMHDR, $lParam)
|
||||||
|
If @error Then Return $GUI_RUNDEFMSG
|
||||||
|
If HWnd(DllStructGetData($tNMHDR, "hWndFrom")) <> $hLvPlugins Then Return $GUI_RUNDEFMSG
|
||||||
|
|
||||||
|
Switch DllStructGetData($tNMHDR, "Code")
|
||||||
|
Case $NM_CUSTOMDRAW
|
||||||
|
Return DrawPluginRow($lParam)
|
||||||
|
Case $LVN_ITEMCHANGING, $LVN_ITEMCHANGED
|
||||||
|
Return OnPluginStateChange(DllStructGetData($tNMHDR, "Code"), $lParam)
|
||||||
|
EndSwitch
|
||||||
|
|
||||||
|
Return $GUI_RUNDEFMSG
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func DrawPluginRow($lParam)
|
||||||
|
Local $tCustomDraw = DllStructCreate($tagNMLVCUSTOMDRAW, $lParam)
|
||||||
|
If @error Then Return $CDRF_DODEFAULT
|
||||||
|
|
||||||
|
Switch DllStructGetData($tCustomDraw, "dwDrawStage")
|
||||||
|
Case $CDDS_PREPAINT
|
||||||
|
Return $CDRF_NOTIFYITEMDRAW
|
||||||
|
Case $CDDS_ITEMPREPAINT
|
||||||
|
Local $iItem = DllStructGetData($tCustomDraw, "dwItemSpec")
|
||||||
|
If $iItem >= 0 And $iItem < $iPluginListCount And IsPluginRowFixed($iItem) Then
|
||||||
|
DllStructSetData($tCustomDraw, "clrText", _WinAPI_GetSysColor($COLOR_GRAYTEXT))
|
||||||
|
EndIf
|
||||||
|
Return $CDRF_NEWFONT
|
||||||
|
EndSwitch
|
||||||
|
|
||||||
|
Return $CDRF_DODEFAULT
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func OnPluginStateChange($iCode, $lParam)
|
||||||
|
If $bPluginListUpdating Then Return $GUI_RUNDEFMSG
|
||||||
|
|
||||||
|
Local $tNMLV = DllStructCreate($tagNMLISTVIEW, $lParam)
|
||||||
|
If @error Then Return $GUI_RUNDEFMSG
|
||||||
|
If Not BitAND(DllStructGetData($tNMLV, "Changed"), $LVIF_STATE) Then Return $GUI_RUNDEFMSG
|
||||||
|
|
||||||
|
Local $iItem = DllStructGetData($tNMLV, "Item")
|
||||||
|
Local $iOldCheck = BitShift(BitAND(DllStructGetData($tNMLV, "OldState"), $LVIS_STATEIMAGEMASK), 12)
|
||||||
|
Local $iNewCheck = BitShift(BitAND(DllStructGetData($tNMLV, "NewState"), $LVIS_STATEIMAGEMASK), 12)
|
||||||
|
|
||||||
|
; A check state change has both state image indexes set
|
||||||
|
Local $bCheckChanged = ($iOldCheck <> 0 And $iNewCheck <> 0 And $iOldCheck <> $iNewCheck)
|
||||||
|
Local $bValidItem = ($iItem >= 0 And $iItem < $iPluginListCount)
|
||||||
|
|
||||||
|
If $iCode = $LVN_ITEMCHANGING Then
|
||||||
|
; Rows that cannot be changed keep their state
|
||||||
|
If $bCheckChanged And $bValidItem And IsPluginRowFixed($iItem) Then Return True
|
||||||
|
Return $GUI_RUNDEFMSG
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
If $bCheckChanged And $bValidItem Then
|
||||||
|
If IsPluginRowFixed($iItem) Then
|
||||||
|
; Safety net in case the rejection above did not take effect
|
||||||
|
$bPluginListUpdating = True
|
||||||
|
SetPluginRowState($iItem)
|
||||||
|
$bPluginListUpdating = False
|
||||||
|
Else
|
||||||
|
$aPluginList[$iItem][1] = ($iNewCheck = $PLUGIN_STATE_CHECKED)
|
||||||
|
$bPluginListDirty = True
|
||||||
|
EndIf
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
UpdatePluginButtons()
|
||||||
|
Return $GUI_RUNDEFMSG
|
||||||
|
EndFunc
|
||||||
|
|
||||||
; ============================================
|
; ============================================
|
||||||
; Startup Checks
|
; Startup Checks
|
||||||
; ============================================
|
; ============================================
|
||||||
@ -602,6 +725,11 @@ Func StartupChecks()
|
|||||||
; Detect Steam version by checking for steam_api64.dll
|
; Detect Steam version by checking for steam_api64.dll
|
||||||
$bIsSteamVersion = FileExists($LAUNCHER_DIR & "\steam_api64.dll")
|
$bIsSteamVersion = FileExists($LAUNCHER_DIR & "\steam_api64.dll")
|
||||||
|
|
||||||
|
; Detect Mod Organizer 2 while its process is still our parent.
|
||||||
|
; Under MO2 the load order belongs to the active MO2 profile, so the launcher must not touch it.
|
||||||
|
$MO2_DIR = GetMO2Directory()
|
||||||
|
$bPluginListReadOnly = ($MO2_DIR <> "")
|
||||||
|
|
||||||
CheckRegistryPaths()
|
CheckRegistryPaths()
|
||||||
CheckPluginsFile()
|
CheckPluginsFile()
|
||||||
CheckINIFiles()
|
CheckINIFiles()
|
||||||
@ -633,8 +761,24 @@ Func CheckRegistryPaths()
|
|||||||
EndIf
|
EndIf
|
||||||
EndFunc
|
EndFunc
|
||||||
|
|
||||||
|
Func GetRequiredPlugins()
|
||||||
|
; Plugins Enderal cannot run without - always kept enabled
|
||||||
|
Local $aRequired[2] = ["Enderal - Forgotten Stories.esm", "SkyUI_SE.esp"]
|
||||||
|
Return $aRequired
|
||||||
|
EndFunc
|
||||||
|
|
||||||
Func CheckPluginsFile()
|
Func CheckPluginsFile()
|
||||||
Local $requiredLines[2] = ["*Enderal - Forgotten Stories.esm", "*SkyUI_SE.esp"]
|
Local $aRequired = GetRequiredPlugins()
|
||||||
|
Local $requiredLines[UBound($aRequired)]
|
||||||
|
Local $iRequired = 0
|
||||||
|
|
||||||
|
; Only enforce required plugins that are installed (SkyUI may be absent)
|
||||||
|
For $i = 0 To UBound($aRequired) - 1
|
||||||
|
If Not FileExists($LAUNCHER_DIR & "\Data\" & $aRequired[$i]) Then ContinueLoop
|
||||||
|
$requiredLines[$iRequired] = "*" & $aRequired[$i]
|
||||||
|
$iRequired += 1
|
||||||
|
Next
|
||||||
|
ReDim $requiredLines[$iRequired]
|
||||||
|
|
||||||
If Not DirExists($PLUGINS_DIR) Then
|
If Not DirExists($PLUGINS_DIR) Then
|
||||||
DirCreate($PLUGINS_DIR)
|
DirCreate($PLUGINS_DIR)
|
||||||
@ -1036,6 +1180,10 @@ Func CreateSettingsWindow()
|
|||||||
GUICtrlCreateTabItem("General")
|
GUICtrlCreateTabItem("General")
|
||||||
CreateControlsControls()
|
CreateControlsControls()
|
||||||
|
|
||||||
|
; Plugins tab
|
||||||
|
GUICtrlCreateTabItem("Plugins")
|
||||||
|
CreatePluginsControls()
|
||||||
|
|
||||||
; End tab items
|
; End tab items
|
||||||
GUICtrlCreateTabItem("")
|
GUICtrlCreateTabItem("")
|
||||||
|
|
||||||
@ -1146,6 +1294,44 @@ Func CreateControlsControls()
|
|||||||
GUICtrlCreateGroup("", -99, -99, 1, 1)
|
GUICtrlCreateGroup("", -99, -99, 1, 1)
|
||||||
EndFunc
|
EndFunc
|
||||||
|
|
||||||
|
Func CreatePluginsControls()
|
||||||
|
Local $leftMargin = $TAB_LEFT_MARGIN
|
||||||
|
Local $topMargin = 58
|
||||||
|
Local $listWidth = 560
|
||||||
|
Local $listHeight = 340
|
||||||
|
Local $sideX = $leftMargin + $listWidth + 20
|
||||||
|
Local $sideWidth = 198
|
||||||
|
Local $btnHeight = 32
|
||||||
|
|
||||||
|
$lvPlugins = GUICtrlCreateListView("Plugin|Type", $leftMargin, $topMargin, $listWidth, $listHeight, _
|
||||||
|
BitOR($LVS_REPORT, $LVS_SINGLESEL, $LVS_SHOWSELALWAYS, $LVS_NOSORTHEADER), _
|
||||||
|
BitOR($LVS_EX_CHECKBOXES, $LVS_EX_FULLROWSELECT, $LVS_EX_DOUBLEBUFFER))
|
||||||
|
$hLvPlugins = GUICtrlGetHandle($lvPlugins)
|
||||||
|
_GUICtrlListView_SetColumnWidth($hLvPlugins, 0, 420)
|
||||||
|
_GUICtrlListView_SetColumnWidth($hLvPlugins, 1, 120)
|
||||||
|
CreatePluginStateImages()
|
||||||
|
|
||||||
|
$btnPluginUp = GUICtrlCreateButton("Move Up", $sideX, $topMargin, $sideWidth, $btnHeight)
|
||||||
|
GUICtrlSetState(-1, $GUI_DISABLE)
|
||||||
|
$btnPluginDown = GUICtrlCreateButton("Move Down", $sideX, $topMargin + 38, $sideWidth, $btnHeight)
|
||||||
|
GUICtrlSetState(-1, $GUI_DISABLE)
|
||||||
|
$btnPluginsEnableAll = GUICtrlCreateButton("Enable All", $sideX, $topMargin + 90, $sideWidth, $btnHeight)
|
||||||
|
$btnPluginsDisableAll = GUICtrlCreateButton("Disable All", $sideX, $topMargin + 128, $sideWidth, $btnHeight)
|
||||||
|
|
||||||
|
$lblPluginsCount = GUICtrlCreateLabel("", $sideX, $topMargin + 178, $sideWidth, 20)
|
||||||
|
|
||||||
|
Local $hint = "Masters (ESM/ESL) always load before regular plugins." & @CRLF & @CRLF & _
|
||||||
|
"Plugins Enderal requires are loaded by the game itself and cannot be changed."
|
||||||
|
If $bPluginListReadOnly Then
|
||||||
|
$hint = "The load order belongs to the active Mod Organizer profile." & @CRLF & @CRLF & _
|
||||||
|
"Enable, disable and sort plugins in Mod Organizer instead."
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
$lblPluginsHint = GUICtrlCreateLabel($hint, $sideX, $topMargin + 206, $sideWidth, 134)
|
||||||
|
GUICtrlSetFont(-1, 8)
|
||||||
|
GUICtrlSetColor(-1, 0x606060)
|
||||||
|
EndFunc
|
||||||
|
|
||||||
Func PopulateResolutions()
|
Func PopulateResolutions()
|
||||||
Local $aResolutions = GetSupportedResolutions()
|
Local $aResolutions = GetSupportedResolutions()
|
||||||
Local $resolutions = ""
|
Local $resolutions = ""
|
||||||
@ -1229,6 +1415,494 @@ Func GetSupportedResolutions()
|
|||||||
Return $aResult
|
Return $aResult
|
||||||
EndFunc
|
EndFunc
|
||||||
|
|
||||||
|
; ============================================
|
||||||
|
; Plugin Management (plugins.txt)
|
||||||
|
; ============================================
|
||||||
|
Func GetPluginHeaderFlags($filePath)
|
||||||
|
; Reads the record flags of the plugin's TES4 header
|
||||||
|
Local $hFile = FileOpen($filePath, $FO_BINARY)
|
||||||
|
If $hFile = -1 Then Return 0
|
||||||
|
|
||||||
|
Local $header = FileRead($hFile, 12)
|
||||||
|
FileClose($hFile)
|
||||||
|
If BinaryLen($header) < 12 Then Return 0
|
||||||
|
If BinaryToString(BinaryMid($header, 1, 4)) <> "TES4" Then Return 0
|
||||||
|
|
||||||
|
; Record flags are a little endian dword at offset 8
|
||||||
|
Local $hex = StringTrimLeft(String(BinaryMid($header, 9, 4)), 2)
|
||||||
|
Return Dec(StringMid($hex, 7, 2) & StringMid($hex, 5, 2) & StringMid($hex, 3, 2) & StringMid($hex, 1, 2), 2)
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func GetPluginTypeInfo($filePath, $fileName)
|
||||||
|
; Returns [load order class, type label]
|
||||||
|
Local $ext = StringLower(StringRight($fileName, 4))
|
||||||
|
Local $flags = GetPluginHeaderFlags($filePath)
|
||||||
|
Local $bMaster = BitAND($flags, $PLUGIN_FLAG_MASTER) <> 0 Or $ext = ".esm" Or $ext = ".esl"
|
||||||
|
Local $bLight = BitAND($flags, $PLUGIN_FLAG_LIGHT) <> 0 Or $ext = ".esl"
|
||||||
|
|
||||||
|
Local $aInfo[2]
|
||||||
|
$aInfo[0] = $bMaster ? $PLUGIN_CLASS_MASTER : $PLUGIN_CLASS_NORMAL
|
||||||
|
If $bLight Then
|
||||||
|
$aInfo[1] = "Light"
|
||||||
|
ElseIf $bMaster Then
|
||||||
|
$aInfo[1] = "Master"
|
||||||
|
Else
|
||||||
|
$aInfo[1] = "Plugin"
|
||||||
|
EndIf
|
||||||
|
Return $aInfo
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func ScanDataPlugins()
|
||||||
|
; All plugin files present in the Data directory, sorted by name
|
||||||
|
; [i][0] = file name, [i][1] = load order class, [i][2] = type label
|
||||||
|
Local $dataDir = $LAUNCHER_DIR & "\Data"
|
||||||
|
Local $aFiles[64][3]
|
||||||
|
Local $iCount = 0
|
||||||
|
|
||||||
|
Local $hSearch = FileFindFirstFile($dataDir & "\*.es*")
|
||||||
|
If $hSearch <> -1 Then
|
||||||
|
While 1
|
||||||
|
Local $fileName = FileFindNextFile($hSearch)
|
||||||
|
If @error Then ExitLoop
|
||||||
|
If @extended Then ContinueLoop ; skip directories
|
||||||
|
|
||||||
|
Local $ext = StringLower(StringRight($fileName, 4))
|
||||||
|
If $ext <> ".esm" And $ext <> ".esp" And $ext <> ".esl" Then ContinueLoop
|
||||||
|
|
||||||
|
If $iCount >= UBound($aFiles) Then ReDim $aFiles[$iCount + 64][3]
|
||||||
|
|
||||||
|
Local $aInfo = GetPluginTypeInfo($dataDir & "\" & $fileName, $fileName)
|
||||||
|
$aFiles[$iCount][0] = $fileName
|
||||||
|
$aFiles[$iCount][1] = $aInfo[0]
|
||||||
|
$aFiles[$iCount][2] = $aInfo[1]
|
||||||
|
$iCount += 1
|
||||||
|
WEnd
|
||||||
|
FileClose($hSearch)
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
ReDim $aFiles[$iCount][3]
|
||||||
|
If $iCount > 1 Then _ArraySort($aFiles, 0, 0, 0, 0)
|
||||||
|
Return $aFiles
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func ReadPluginsFile()
|
||||||
|
; plugins.txt entries in file order: [i][0] = file name, [i][1] = enabled
|
||||||
|
Local $aListed[1][2]
|
||||||
|
Local $iCount = 0
|
||||||
|
|
||||||
|
If FileExists($PLUGINS_FILE) Then
|
||||||
|
Local $hFile = FileOpen($PLUGINS_FILE, BitOR($FO_READ, $FO_UTF8))
|
||||||
|
If $hFile <> -1 Then
|
||||||
|
Local $content = FileRead($hFile)
|
||||||
|
FileClose($hFile)
|
||||||
|
|
||||||
|
; Drop a byte order mark left over from other tools
|
||||||
|
If StringLeft($content, 1) = ChrW(65279) Then $content = StringTrimLeft($content, 1)
|
||||||
|
|
||||||
|
Local $aLines = StringSplit(StringStripCR($content), @LF)
|
||||||
|
ReDim $aListed[$aLines[0] + 1][2]
|
||||||
|
|
||||||
|
For $i = 1 To $aLines[0]
|
||||||
|
Local $line = StringStripWS($aLines[$i], 3)
|
||||||
|
If $line = "" Or StringLeft($line, 1) = "#" Then ContinueLoop
|
||||||
|
|
||||||
|
Local $bEnabled = (StringLeft($line, 1) = "*")
|
||||||
|
If $bEnabled Then $line = StringStripWS(StringTrimLeft($line, 1), 3)
|
||||||
|
If $line = "" Then ContinueLoop
|
||||||
|
|
||||||
|
$aListed[$iCount][0] = $line
|
||||||
|
$aListed[$iCount][1] = $bEnabled
|
||||||
|
$iCount += 1
|
||||||
|
Next
|
||||||
|
EndIf
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
ReDim $aListed[$iCount][2]
|
||||||
|
Return $aListed
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func GetCCCPlugins()
|
||||||
|
; Skyrim.ccc entries - the game loads these on its own whenever the files exist
|
||||||
|
Local $aEntries[1]
|
||||||
|
Local $iCount = 0
|
||||||
|
Local $cccFile = $LAUNCHER_DIR & "\Skyrim.ccc"
|
||||||
|
|
||||||
|
If FileExists($cccFile) Then
|
||||||
|
Local $aLines = StringSplit(StringStripCR(FileRead($cccFile)), @LF)
|
||||||
|
ReDim $aEntries[$aLines[0] + 1]
|
||||||
|
|
||||||
|
For $i = 1 To $aLines[0]
|
||||||
|
Local $line = StringStripWS($aLines[$i], 3)
|
||||||
|
If $line = "" Or StringLeft($line, 1) = "#" Then ContinueLoop
|
||||||
|
$aEntries[$iCount] = $line
|
||||||
|
$iCount += 1
|
||||||
|
Next
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
ReDim $aEntries[$iCount]
|
||||||
|
Return $aEntries
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func GetImplicitPlugins()
|
||||||
|
; Plugins the game loads by itself, in the order it loads them: the Skyrim masters,
|
||||||
|
; the Skyrim.ccc entries, then the plugins Enderal requires
|
||||||
|
Local $aMasters[5] = ["Skyrim.esm", "Update.esm", "Dawnguard.esm", "HearthFires.esm", "Dragonborn.esm"]
|
||||||
|
Local $aCCC = GetCCCPlugins()
|
||||||
|
Local $aRequired = GetRequiredPlugins()
|
||||||
|
|
||||||
|
Local $aImplicit[UBound($aMasters) + UBound($aCCC) + UBound($aRequired)]
|
||||||
|
Local $iCount = 0
|
||||||
|
|
||||||
|
For $i = 0 To UBound($aMasters) - 1
|
||||||
|
$aImplicit[$iCount] = $aMasters[$i]
|
||||||
|
$iCount += 1
|
||||||
|
Next
|
||||||
|
For $i = 0 To UBound($aCCC) - 1
|
||||||
|
$aImplicit[$iCount] = $aCCC[$i]
|
||||||
|
$iCount += 1
|
||||||
|
Next
|
||||||
|
For $i = 0 To UBound($aRequired) - 1
|
||||||
|
$aImplicit[$iCount] = $aRequired[$i]
|
||||||
|
$iCount += 1
|
||||||
|
Next
|
||||||
|
|
||||||
|
Return $aImplicit
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func IsRequiredPlugin($fileName)
|
||||||
|
Local $aRequired = GetRequiredPlugins()
|
||||||
|
For $i = 0 To UBound($aRequired) - 1
|
||||||
|
If $aRequired[$i] = $fileName Then Return True
|
||||||
|
Next
|
||||||
|
Return False
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func FindPluginFile(ByRef $aFiles, $fileName)
|
||||||
|
For $i = 0 To UBound($aFiles) - 1
|
||||||
|
If $aFiles[$i][0] = $fileName Then Return $i
|
||||||
|
Next
|
||||||
|
Return -1
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func FindListedPlugin(ByRef $aListed, $fileName)
|
||||||
|
For $i = 0 To UBound($aListed) - 1
|
||||||
|
If $aListed[$i][0] = $fileName Then Return $i
|
||||||
|
Next
|
||||||
|
Return -1
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func FindPluginRow(ByRef $aList, $iCount, $fileName)
|
||||||
|
For $i = 0 To $iCount - 1
|
||||||
|
If $aList[$i][0] = $fileName Then Return $i
|
||||||
|
Next
|
||||||
|
Return -1
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func AddPluginRow(ByRef $aList, ByRef $iCount, ByRef $aFiles, $iFile, $bEnabled, $bLocked, $bListed)
|
||||||
|
$aList[$iCount][0] = $aFiles[$iFile][0]
|
||||||
|
$aList[$iCount][1] = $bEnabled
|
||||||
|
$aList[$iCount][2] = $bLocked
|
||||||
|
$aList[$iCount][3] = $aFiles[$iFile][1]
|
||||||
|
$aList[$iCount][4] = $bLocked ? $aFiles[$iFile][2] & " (fixed)" : $aFiles[$iFile][2]
|
||||||
|
$aList[$iCount][5] = $bListed
|
||||||
|
$iCount += 1
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func LoadPluginList()
|
||||||
|
; Keep unsaved changes when the settings are reloaded (e.g. after applying a detail preset)
|
||||||
|
If $bPluginListDirty Then Return
|
||||||
|
|
||||||
|
Local $aFiles = ScanDataPlugins()
|
||||||
|
Local $aListed = ReadPluginsFile()
|
||||||
|
Local $aImplicit = GetImplicitPlugins()
|
||||||
|
Local $iFileCount = UBound($aFiles)
|
||||||
|
|
||||||
|
Local $aList[$iFileCount + 1][6]
|
||||||
|
Local $iCount = 0
|
||||||
|
Local $iFile
|
||||||
|
|
||||||
|
; Plugins loaded by the game itself come first and cannot be changed
|
||||||
|
For $i = 0 To UBound($aImplicit) - 1
|
||||||
|
$iFile = FindPluginFile($aFiles, $aImplicit[$i])
|
||||||
|
If $iFile < 0 Then ContinueLoop ; not installed
|
||||||
|
If FindPluginRow($aList, $iCount, $aFiles[$iFile][0]) >= 0 Then ContinueLoop
|
||||||
|
; The plugins Enderal requires are always written back to plugins.txt as enabled,
|
||||||
|
; the remaining ones only when they were listed there before
|
||||||
|
Local $bListed = IsRequiredPlugin($aFiles[$iFile][0]) Or FindListedPlugin($aListed, $aFiles[$iFile][0]) >= 0
|
||||||
|
AddPluginRow($aList, $iCount, $aFiles, $iFile, True, True, $bListed)
|
||||||
|
Next
|
||||||
|
|
||||||
|
; Then the plugins.txt entries in their current order
|
||||||
|
For $i = 0 To UBound($aListed) - 1
|
||||||
|
$iFile = FindPluginFile($aFiles, $aListed[$i][0])
|
||||||
|
If $iFile < 0 Then ContinueLoop ; entry without a file - drop it
|
||||||
|
If FindPluginRow($aList, $iCount, $aFiles[$iFile][0]) >= 0 Then ContinueLoop
|
||||||
|
AddPluginRow($aList, $iCount, $aFiles, $iFile, $aListed[$i][1], False, True)
|
||||||
|
Next
|
||||||
|
|
||||||
|
; Finally the plugins that are not in plugins.txt yet, masters first
|
||||||
|
For $iClass = $PLUGIN_CLASS_MASTER To $PLUGIN_CLASS_NORMAL
|
||||||
|
For $i = 0 To $iFileCount - 1
|
||||||
|
If $aFiles[$i][1] <> $iClass Then ContinueLoop
|
||||||
|
If FindPluginRow($aList, $iCount, $aFiles[$i][0]) >= 0 Then ContinueLoop
|
||||||
|
AddPluginRow($aList, $iCount, $aFiles, $i, False, False, False)
|
||||||
|
Next
|
||||||
|
Next
|
||||||
|
|
||||||
|
; Keep masters above regular plugins - the engine loads them that way regardless of plugins.txt
|
||||||
|
Local $aSorted[$iFileCount + 1][6]
|
||||||
|
Local $iSorted = 0
|
||||||
|
For $iRank = 0 To 2
|
||||||
|
For $i = 0 To $iCount - 1
|
||||||
|
Local $iRowRank = $aList[$i][2] ? 0 : ($aList[$i][3] = $PLUGIN_CLASS_MASTER ? 1 : 2)
|
||||||
|
If $iRowRank <> $iRank Then ContinueLoop
|
||||||
|
For $c = 0 To 5
|
||||||
|
$aSorted[$iSorted][$c] = $aList[$i][$c]
|
||||||
|
Next
|
||||||
|
$iSorted += 1
|
||||||
|
Next
|
||||||
|
Next
|
||||||
|
|
||||||
|
$aPluginList = $aSorted
|
||||||
|
$iPluginListCount = $iSorted
|
||||||
|
$bPluginListLoaded = True
|
||||||
|
|
||||||
|
FillPluginListView()
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func CreatePluginStateImages()
|
||||||
|
; Check box images for the plugin list: the two extra dimmed ones mark rows that cannot be changed.
|
||||||
|
; Without visual styles the list keeps the check boxes the control provides itself.
|
||||||
|
If Not _WinAPI_IsThemeActive() Then Return
|
||||||
|
|
||||||
|
Local $hTheme = _WinAPI_OpenThemeData($hLvPlugins, "BUTTON")
|
||||||
|
If $hTheme = 0 Then Return
|
||||||
|
|
||||||
|
Local $hWndDC = _WinAPI_GetDC($hLvPlugins)
|
||||||
|
Local $tSize = _WinAPI_GetThemePartSize($hTheme, $THEME_BP_CHECKBOX, $THEME_CB_UNCHECKED, $hWndDC, 0, $TS_TRUE)
|
||||||
|
Local $iError = @error
|
||||||
|
_WinAPI_ReleaseDC($hLvPlugins, $hWndDC)
|
||||||
|
|
||||||
|
Local $iWidth = 16, $iHeight = 16
|
||||||
|
If Not $iError Then
|
||||||
|
$iWidth = DllStructGetData($tSize, "X")
|
||||||
|
$iHeight = DllStructGetData($tSize, "Y")
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
If $iWidth >= 8 And $iHeight >= 8 Then
|
||||||
|
Local $hBitmap = CreateTransparentBitmap($iWidth * 4, $iHeight)
|
||||||
|
If $hBitmap <> 0 Then
|
||||||
|
; Draw the four states next to each other, in state image index order
|
||||||
|
Local $aStates[4] = [$THEME_CB_UNCHECKED, $THEME_CB_CHECKED, _
|
||||||
|
$THEME_CB_UNCHECKED_DISABLED, $THEME_CB_CHECKED_DISABLED]
|
||||||
|
Local $hMemDC = _WinAPI_CreateCompatibleDC(0)
|
||||||
|
Local $hPrevBitmap = _WinAPI_SelectObject($hMemDC, $hBitmap)
|
||||||
|
Local $tRect = DllStructCreate($tagRECT)
|
||||||
|
DllStructSetData($tRect, "Top", 0)
|
||||||
|
DllStructSetData($tRect, "Bottom", $iHeight)
|
||||||
|
|
||||||
|
For $i = 0 To UBound($aStates) - 1
|
||||||
|
DllStructSetData($tRect, "Left", $i * $iWidth)
|
||||||
|
DllStructSetData($tRect, "Right", ($i + 1) * $iWidth)
|
||||||
|
_WinAPI_DrawThemeBackground($hTheme, $THEME_BP_CHECKBOX, $aStates[$i], $hMemDC, $tRect)
|
||||||
|
Next
|
||||||
|
|
||||||
|
_WinAPI_SelectObject($hMemDC, $hPrevBitmap)
|
||||||
|
_WinAPI_DeleteDC($hMemDC)
|
||||||
|
|
||||||
|
$hPluginStateImages = _GUIImageList_Create($iWidth, $iHeight, 5, 0, 4, 4)
|
||||||
|
If $hPluginStateImages <> 0 Then
|
||||||
|
_GUIImageList_Add($hPluginStateImages, $hBitmap)
|
||||||
|
_GUICtrlListView_SetImageList($hLvPlugins, $hPluginStateImages, 2) ; 2 = LVSIL_STATE
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
_WinAPI_DeleteObject($hBitmap)
|
||||||
|
EndIf
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
_WinAPI_CloseThemeData($hTheme)
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func CreateTransparentBitmap($iWidth, $iHeight)
|
||||||
|
; Top down 32 bit device independent bitmap, cleared to fully transparent
|
||||||
|
Local $tBitmapInfo = DllStructCreate("dword Size;long Width;long Height;ushort Planes;ushort BitCount;" & _
|
||||||
|
"dword Compression;dword SizeImage;long XPelsPerMeter;long YPelsPerMeter;dword ClrUsed;dword ClrImportant")
|
||||||
|
DllStructSetData($tBitmapInfo, "Size", DllStructGetSize($tBitmapInfo))
|
||||||
|
DllStructSetData($tBitmapInfo, "Width", $iWidth)
|
||||||
|
DllStructSetData($tBitmapInfo, "Height", -$iHeight)
|
||||||
|
DllStructSetData($tBitmapInfo, "Planes", 1)
|
||||||
|
DllStructSetData($tBitmapInfo, "BitCount", 32)
|
||||||
|
DllStructSetData($tBitmapInfo, "Compression", 0) ; BI_RGB
|
||||||
|
|
||||||
|
Local $aCall = DllCall("gdi32.dll", "handle", "CreateDIBSection", "handle", 0, "struct*", $tBitmapInfo, _
|
||||||
|
"uint", 0, "ptr*", 0, "handle", 0, "dword", 0)
|
||||||
|
If @error Or Not IsArray($aCall) Then Return 0
|
||||||
|
Return $aCall[0]
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func IsPluginRowFixed($iIndex)
|
||||||
|
; True when the row cannot be toggled: plugins the game loads itself, or MO2 owning the load order
|
||||||
|
If $bPluginListReadOnly Then Return True
|
||||||
|
Return $aPluginList[$iIndex][2]
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func SetPluginRowState($iIndex)
|
||||||
|
If $hPluginStateImages = 0 Then
|
||||||
|
; No dimmed images available - fall back to the plain check box
|
||||||
|
_GUICtrlListView_SetItemChecked($hLvPlugins, $iIndex, $aPluginList[$iIndex][1])
|
||||||
|
Return
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
Local $iState
|
||||||
|
If IsPluginRowFixed($iIndex) Then
|
||||||
|
$iState = $aPluginList[$iIndex][1] ? $PLUGIN_STATE_CHECKED_DIMMED : $PLUGIN_STATE_UNCHECKED_DIMMED
|
||||||
|
Else
|
||||||
|
$iState = $aPluginList[$iIndex][1] ? $PLUGIN_STATE_CHECKED : $PLUGIN_STATE_UNCHECKED
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
_GUICtrlListView_SetItemState($hLvPlugins, $iIndex, BitShift($iState, -12), $LVIS_STATEIMAGEMASK)
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func FillPluginListView()
|
||||||
|
$bPluginListUpdating = True
|
||||||
|
_GUICtrlListView_BeginUpdate($hLvPlugins)
|
||||||
|
_GUICtrlListView_DeleteAllItems($hLvPlugins)
|
||||||
|
|
||||||
|
For $i = 0 To $iPluginListCount - 1
|
||||||
|
_GUICtrlListView_AddItem($hLvPlugins, $aPluginList[$i][0])
|
||||||
|
_GUICtrlListView_AddSubItem($hLvPlugins, $i, $aPluginList[$i][4], 1)
|
||||||
|
SetPluginRowState($i)
|
||||||
|
Next
|
||||||
|
|
||||||
|
_GUICtrlListView_EndUpdate($hLvPlugins)
|
||||||
|
$bPluginListUpdating = False
|
||||||
|
|
||||||
|
UpdatePluginColumnWidths()
|
||||||
|
UpdatePluginButtons()
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func UpdatePluginColumnWidths()
|
||||||
|
; Fit both columns into the visible area, with or without a scroll bar
|
||||||
|
Local $tRect = _WinAPI_GetClientRect($hLvPlugins)
|
||||||
|
If @error Then Return
|
||||||
|
|
||||||
|
Local $iClientWidth = DllStructGetData($tRect, "Right") - DllStructGetData($tRect, "Left")
|
||||||
|
Local $iTypeWidth = 120
|
||||||
|
If $iClientWidth < $iTypeWidth * 2 Then Return
|
||||||
|
|
||||||
|
_GUICtrlListView_SetColumnWidth($hLvPlugins, 1, $iTypeWidth)
|
||||||
|
_GUICtrlListView_SetColumnWidth($hLvPlugins, 0, $iClientWidth - $iTypeWidth)
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func UpdatePluginRow($iIndex)
|
||||||
|
$bPluginListUpdating = True
|
||||||
|
_GUICtrlListView_SetItemText($hLvPlugins, $iIndex, $aPluginList[$iIndex][0], 0)
|
||||||
|
_GUICtrlListView_SetItemText($hLvPlugins, $iIndex, $aPluginList[$iIndex][4], 1)
|
||||||
|
SetPluginRowState($iIndex)
|
||||||
|
$bPluginListUpdating = False
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func GetSelectedPluginIndex()
|
||||||
|
If $hLvPlugins = 0 Then Return -1
|
||||||
|
|
||||||
|
Local $aIndices = _GUICtrlListView_GetSelectedIndices($hLvPlugins, True)
|
||||||
|
If UBound($aIndices) < 2 Or $aIndices[0] < 1 Then Return -1
|
||||||
|
Return $aIndices[1]
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func CanMovePlugin($iIndex, $iTarget)
|
||||||
|
If $bPluginListReadOnly Then Return False
|
||||||
|
If $iIndex < 0 Or $iIndex >= $iPluginListCount Then Return False
|
||||||
|
If $iTarget < 0 Or $iTarget >= $iPluginListCount Then Return False
|
||||||
|
; Plugins loaded by the game itself keep their position
|
||||||
|
If $aPluginList[$iIndex][2] Or $aPluginList[$iTarget][2] Then Return False
|
||||||
|
; Masters cannot be mixed with regular plugins
|
||||||
|
If $aPluginList[$iIndex][3] <> $aPluginList[$iTarget][3] Then Return False
|
||||||
|
Return True
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func MoveSelectedPlugin($iDirection)
|
||||||
|
Local $iIndex = GetSelectedPluginIndex()
|
||||||
|
Local $iTarget = $iIndex + $iDirection
|
||||||
|
If Not CanMovePlugin($iIndex, $iTarget) Then Return
|
||||||
|
|
||||||
|
For $c = 0 To 5
|
||||||
|
Local $swap = $aPluginList[$iIndex][$c]
|
||||||
|
$aPluginList[$iIndex][$c] = $aPluginList[$iTarget][$c]
|
||||||
|
$aPluginList[$iTarget][$c] = $swap
|
||||||
|
Next
|
||||||
|
|
||||||
|
UpdatePluginRow($iIndex)
|
||||||
|
UpdatePluginRow($iTarget)
|
||||||
|
|
||||||
|
$bPluginListUpdating = True
|
||||||
|
_GUICtrlListView_SetItemSelected($hLvPlugins, $iIndex, False)
|
||||||
|
_GUICtrlListView_SetItemSelected($hLvPlugins, $iTarget, True, True)
|
||||||
|
$bPluginListUpdating = False
|
||||||
|
_GUICtrlListView_EnsureVisible($hLvPlugins, $iTarget)
|
||||||
|
|
||||||
|
$bPluginListDirty = True
|
||||||
|
UpdatePluginButtons()
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func SetAllPluginsEnabled($bEnabled)
|
||||||
|
If $bPluginListReadOnly Then Return
|
||||||
|
|
||||||
|
For $i = 0 To $iPluginListCount - 1
|
||||||
|
If $aPluginList[$i][2] Then ContinueLoop ; locked plugins stay enabled
|
||||||
|
If $aPluginList[$i][1] = $bEnabled Then ContinueLoop
|
||||||
|
$aPluginList[$i][1] = $bEnabled
|
||||||
|
UpdatePluginRow($i)
|
||||||
|
$bPluginListDirty = True
|
||||||
|
Next
|
||||||
|
|
||||||
|
UpdatePluginButtons()
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func UpdatePluginButtons()
|
||||||
|
Local $iIndex = GetSelectedPluginIndex()
|
||||||
|
GUICtrlSetState($btnPluginUp, CanMovePlugin($iIndex, $iIndex - 1) ? $GUI_ENABLE : $GUI_DISABLE)
|
||||||
|
GUICtrlSetState($btnPluginDown, CanMovePlugin($iIndex, $iIndex + 1) ? $GUI_ENABLE : $GUI_DISABLE)
|
||||||
|
|
||||||
|
Local $iEnabled = 0
|
||||||
|
Local $iChangeable = 0
|
||||||
|
For $i = 0 To $iPluginListCount - 1
|
||||||
|
If $aPluginList[$i][1] Then $iEnabled += 1
|
||||||
|
If Not IsPluginRowFixed($i) Then $iChangeable += 1
|
||||||
|
Next
|
||||||
|
|
||||||
|
GUICtrlSetData($lblPluginsCount, $iEnabled & " of " & $iPluginListCount & " enabled")
|
||||||
|
GUICtrlSetState($btnPluginsEnableAll, $iChangeable > 0 ? $GUI_ENABLE : $GUI_DISABLE)
|
||||||
|
GUICtrlSetState($btnPluginsDisableAll, $iChangeable > 0 ? $GUI_ENABLE : $GUI_DISABLE)
|
||||||
|
EndFunc
|
||||||
|
|
||||||
|
Func SavePluginsFile()
|
||||||
|
; Under MO2 the load order is owned by the active profile
|
||||||
|
If $bPluginListReadOnly Then Return
|
||||||
|
If Not $bPluginListLoaded Or Not $bPluginListDirty Or $iPluginListCount = 0 Then Return
|
||||||
|
|
||||||
|
Local $content = ""
|
||||||
|
For $i = 0 To $iPluginListCount - 1
|
||||||
|
; Plugins the game loads on its own are only written back when they were listed before
|
||||||
|
If $aPluginList[$i][2] And Not $aPluginList[$i][5] Then ContinueLoop
|
||||||
|
Local $bEnabled = $aPluginList[$i][2] ? True : $aPluginList[$i][1]
|
||||||
|
$content &= ($bEnabled ? "*" : "") & $aPluginList[$i][0] & @CRLF
|
||||||
|
Next
|
||||||
|
|
||||||
|
If Not DirExists($PLUGINS_DIR) Then DirCreate($PLUGINS_DIR)
|
||||||
|
|
||||||
|
Local $hFile = FileOpen($PLUGINS_FILE, BitOR($FO_OVERWRITE, $FO_UTF8_NOBOM))
|
||||||
|
If $hFile = -1 Then
|
||||||
|
MsgBox(16, "Error", "Unable to write the plugin list:" & @CRLF & $PLUGINS_FILE)
|
||||||
|
Return
|
||||||
|
EndIf
|
||||||
|
|
||||||
|
FileWrite($hFile, $content)
|
||||||
|
FileClose($hFile)
|
||||||
|
|
||||||
|
$bPluginListDirty = False
|
||||||
|
EndFunc
|
||||||
|
|
||||||
; ============================================
|
; ============================================
|
||||||
; Main Loop
|
; Main Loop
|
||||||
; ============================================
|
; ============================================
|
||||||
@ -1313,6 +1987,18 @@ Func MainLoop()
|
|||||||
Case $btnOpenSavegames
|
Case $btnOpenSavegames
|
||||||
OpenSavegamesDirectory()
|
OpenSavegamesDirectory()
|
||||||
|
|
||||||
|
Case $btnPluginUp
|
||||||
|
MoveSelectedPlugin(-1)
|
||||||
|
|
||||||
|
Case $btnPluginDown
|
||||||
|
MoveSelectedPlugin(1)
|
||||||
|
|
||||||
|
Case $btnPluginsEnableAll
|
||||||
|
SetAllPluginsEnabled(True)
|
||||||
|
|
||||||
|
Case $btnPluginsDisableAll
|
||||||
|
SetAllPluginsEnabled(False)
|
||||||
|
|
||||||
EndSwitch
|
EndSwitch
|
||||||
WEnd
|
WEnd
|
||||||
EndFunc
|
EndFunc
|
||||||
@ -1332,6 +2018,8 @@ Func ShowSettings()
|
|||||||
EndFunc
|
EndFunc
|
||||||
|
|
||||||
Func HideSettings()
|
Func HideSettings()
|
||||||
|
; Drop unsaved plugin changes so the list is read again the next time
|
||||||
|
$bPluginListDirty = False
|
||||||
GUISetState(@SW_HIDE, $hSettingsGUI)
|
GUISetState(@SW_HIDE, $hSettingsGUI)
|
||||||
EndFunc
|
EndFunc
|
||||||
|
|
||||||
@ -1464,6 +2152,9 @@ Func LoadSettings()
|
|||||||
If @error Then $startSteam = 1
|
If @error Then $startSteam = 1
|
||||||
SetCheckboxState($chkStartSteam, $startSteam)
|
SetCheckboxState($chkStartSteam, $startSteam)
|
||||||
EndIf
|
EndIf
|
||||||
|
|
||||||
|
; Load the plugin list
|
||||||
|
LoadPluginList()
|
||||||
EndFunc
|
EndFunc
|
||||||
|
|
||||||
Func SaveSettings()
|
Func SaveSettings()
|
||||||
@ -1530,6 +2221,9 @@ Func SaveSettings()
|
|||||||
Local $startSteam = (GUICtrlRead($chkStartSteam) = $GUI_CHECKED) ? 1 : 0
|
Local $startSteam = (GUICtrlRead($chkStartSteam) = $GUI_CHECKED) ? 1 : 0
|
||||||
RegWrite($REG_KEY, $REG_START_STEAM, "REG_DWORD", $startSteam)
|
RegWrite($REG_KEY, $REG_START_STEAM, "REG_DWORD", $startSteam)
|
||||||
EndIf
|
EndIf
|
||||||
|
|
||||||
|
; Save the plugin list
|
||||||
|
SavePluginsFile()
|
||||||
EndFunc
|
EndFunc
|
||||||
|
|
||||||
Func ApplyDetailPreset($presetName)
|
Func ApplyDetailPreset($presetName)
|
||||||
@ -1645,9 +2339,8 @@ Func OpenSavegamesDirectory()
|
|||||||
EndIf
|
EndIf
|
||||||
|
|
||||||
; Check if running under Mod Organizer (parent process is ModOrganizer.exe)
|
; Check if running under Mod Organizer (parent process is ModOrganizer.exe)
|
||||||
Local $mo2Dir = GetMO2Directory()
|
If $MO2_DIR <> "" Then
|
||||||
If $mo2Dir <> "" Then
|
Local $explorerPPPath = $MO2_DIR & "\explorer++\Explorer++.exe"
|
||||||
Local $explorerPPPath = $mo2Dir & "\explorer++\Explorer++.exe"
|
|
||||||
If FileExists($explorerPPPath) Then
|
If FileExists($explorerPPPath) Then
|
||||||
Run('"' & $explorerPPPath & '" "' & $fullSavePath & '"')
|
Run('"' & $explorerPPPath & '" "' & $fullSavePath & '"')
|
||||||
Return
|
Return
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user