diff --git a/installer/.gitignore b/installer/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/installer/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/installer/Contrib/Graphics/Assets/banner-t7x-title.bmp b/installer/Contrib/Graphics/Assets/banner-t7x-title.bmp
new file mode 100644
index 00000000..3f079778
Binary files /dev/null and b/installer/Contrib/Graphics/Assets/banner-t7x-title.bmp differ
diff --git a/installer/Contrib/Graphics/Assets/logo-cropped.bmp b/installer/Contrib/Graphics/Assets/logo-cropped.bmp
new file mode 100644
index 00000000..73ee0d9e
Binary files /dev/null and b/installer/Contrib/Graphics/Assets/logo-cropped.bmp differ
diff --git a/installer/Contrib/Graphics/Icons/icon.ico b/installer/Contrib/Graphics/Icons/icon.ico
new file mode 100644
index 00000000..c142c5e1
Binary files /dev/null and b/installer/Contrib/Graphics/Icons/icon.ico differ
diff --git a/installer/Contrib/Graphics/Icons/modern-uninstall.ico b/installer/Contrib/Graphics/Icons/modern-uninstall.ico
new file mode 100644
index 00000000..c142c5e1
Binary files /dev/null and b/installer/Contrib/Graphics/Icons/modern-uninstall.ico differ
diff --git a/installer/Contrib/Language files/English.nlf b/installer/Contrib/Language files/English.nlf
new file mode 100644
index 00000000..4568a1b5
--- /dev/null
+++ b/installer/Contrib/Language files/English.nlf
@@ -0,0 +1,191 @@
+# Header, don't edit
+NLF v6
+# Start editing here
+# Language ID
+1033
+# Font and size - dash (-) means default
+-
+-
+# Codepage - dash (-) means ASCII code page
+-
+# RTL - anything else than RTL means LTR
+-
+# Translation by ..... (any credits should go here)
+# ^Branding
+t7x Installer - Free and Open Source Software
+# ^SetupCaption
+$(^Name) Setup
+# ^UninstallCaption
+$(^Name) Uninstall
+# ^LicenseSubCaption
+: License Agreement
+# ^ComponentsSubCaption
+: Installation Options
+# ^DirSubCaption
+: Installation Folder
+# ^InstallingSubCaption
+: Installing
+# ^CompletedSubCaption
+: Completed
+# ^UnComponentsSubCaption
+: Uninstallation Options
+# ^UnDirSubCaption
+: Uninstallation Folder
+# ^ConfirmSubCaption
+: Confirmation
+# ^UninstallingSubCaption
+: Uninstalling
+# ^UnCompletedSubCaption
+: Completed
+# ^BackBtn
+< &Back
+# ^NextBtn
+&Next >
+# ^AgreeBtn
+I &Agree
+# ^AcceptBtn
+I &accept the terms of the License Agreement
+# ^DontAcceptBtn
+I &do not accept the terms of the License Agreement
+# ^InstallBtn
+&Install
+# ^UninstallBtn
+&Uninstall
+# ^CancelBtn
+Cancel
+# ^CloseBtn
+&Close
+# ^BrowseBtn
+B&rowse...
+# ^ShowDetailsBtn
+Show &details
+# ^ClickNext
+Click Next to continue.
+# ^ClickInstall
+Click Install to start the installation.
+# ^ClickUninstall
+Click Uninstall to start the uninstallation.
+# ^Name
+Name
+# ^Completed
+Completed
+# ^LicenseText
+Please review the license agreement before installing $(^NameDA). If you accept all terms of the agreement, click I Agree.
+# ^LicenseTextCB
+Please review the license agreement before installing $(^NameDA). If you accept all terms of the agreement, click the check box below. $_CLICK
+# ^LicenseTextRB
+Please review the license agreement before installing $(^NameDA). If you accept all terms of the agreement, select the first option below. $_CLICK
+# ^UnLicenseText
+Please review the license agreement before uninstalling $(^NameDA). If you accept all terms of the agreement, click I Agree.
+# ^UnLicenseTextCB
+Please review the license agreement before uninstalling $(^NameDA). If you accept all terms of the agreement, click the check box below. $_CLICK
+# ^UnLicenseTextRB
+Please review the license agreement before uninstalling $(^NameDA). If you accept all terms of the agreement, select the first option below. $_CLICK
+# ^Custom
+Custom
+# ^ComponentsText
+Check the components you want to install and uncheck the components you don't want to install. $_CLICK
+# ^ComponentsSubText1
+Select the type of install:
+# ^ComponentsSubText2_NoInstTypes
+Select components to install:
+# ^ComponentsSubText2
+Or, select the optional components you wish to install:
+# ^UnComponentsText
+Check the components you want to uninstall and uncheck the components you don't want to uninstall. $_CLICK
+# ^UnComponentsSubText1
+Select the type of uninstall:
+# ^UnComponentsSubText2_NoInstTypes
+Select components to uninstall:
+# ^UnComponentsSubText2
+Or, select the optional components you wish to uninstall:
+# ^DirText
+Setup will install $(^NameDA) in the following folder. Enter the path to your Call of Duty Black Ops III game folder, or click Browse and select the game folder. $_CLICK
+# ^DirSubText
+Destination Folder
+# ^DirBrowseText
+Select the folder to install $(^NameDA) in:
+# ^UnDirText
+Setup will uninstall $(^NameDA) from the following folder. To uninstall from a different folder, click Browse and select another folder. $_CLICK
+# ^UnDirSubText
+""
+# ^UnDirBrowseText
+Select the folder to uninstall $(^NameDA) from:
+# ^SpaceAvailable
+"Space available: "
+# ^SpaceRequired
+"Space required: "
+# ^UninstallingText
+$(^NameDA) will be uninstalled from the following folder. $_CLICK
+# ^UninstallingSubText
+Uninstalling from:
+# ^FileError
+Error opening file for writing: \r\n\r\n$0\r\n\r\nClick Abort to stop the installation,\r\nRetry to try again, or\r\nIgnore to skip this file.
+# ^FileError_NoIgnore
+Error opening file for writing: \r\n\r\n$0\r\n\r\nClick Retry to try again, or\r\nCancel to stop the installation.
+# ^CantWrite
+"Can't write: "
+# ^CopyFailed
+Copy failed
+# ^CopyTo
+"Copy to "
+# ^Registering
+"Registering: "
+# ^Unregistering
+"Unregistering: "
+# ^SymbolNotFound
+"Could not find symbol: "
+# ^CouldNotLoad
+"Could not load: "
+# ^CreateFolder
+"Create folder: "
+# ^CreateShortcut
+"Create shortcut: "
+# ^CreatedUninstaller
+"Created uninstaller: "
+# ^Delete
+"Delete file: "
+# ^DeleteOnReboot
+"Delete on reboot: "
+# ^ErrorCreatingShortcut
+"Error creating shortcut: "
+# ^ErrorCreating
+"Error creating: "
+# ^ErrorDecompressing
+Error decompressing data! Corrupted installer?
+# ^ErrorRegistering
+Error registering DLL
+# ^ExecShell
+"ExecShell: "
+# ^Exec
+"Execute: "
+# ^Extract
+"Extract: "
+# ^ErrorWriting
+"Extract: error writing to file "
+# ^InvalidOpcode
+Installer corrupted: invalid opcode
+# ^NoOLE
+"No OLE for: "
+# ^OutputFolder
+"Output folder: "
+# ^RemoveFolder
+"Remove folder: "
+# ^RenameOnReboot
+"Rename on reboot: "
+# ^Rename
+"Rename: "
+# ^Skipped
+"Skipped: "
+# ^CopyDetails
+Copy Details To Clipboard
+# ^LogInstall
+Log install process
+# ^Byte
+B
+# ^Kilo
+ K
+# ^Mega
+ M
+# ^Giga
+ G
diff --git a/installer/Contrib/Language files/English.nsh b/installer/Contrib/Language files/English.nsh
new file mode 100644
index 00000000..eed4c5fc
--- /dev/null
+++ b/installer/Contrib/Language files/English.nsh
@@ -0,0 +1,129 @@
+;Language: English (1033)
+;By Joost Verburg
+
+!insertmacro LANGFILE "English" "English" "English" "English" ; See \Include\LangFile.nsh for a description of these parameters
+
+!ifdef MUI_WELCOMEPAGE
+ ${LangFileString} MUI_TEXT_WELCOME_INFO_TITLE "Welcome to the $(^NameDA) Setup"
+ ${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "Setup will guide you through the installation of the $(^NameDA) Client for Call of Duty Black Ops III.$\r$\n$\r$\nIt is recommended that you close all other applications before installing.$\r$\n$\r$\nYou will not need to restart your computer after installation.$\r$\n$\r$\n$_CLICK"
+!endif
+
+!ifdef MUI_UNWELCOMEPAGE
+ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TITLE "$(^NameDA) Uninstaller"
+ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Setup will guide you through the uninstallation of $(^NameDA).$\r$\n$\r$\nBefore starting the uninstallation, make sure $(^NameDA) is not running.$\r$\n$\r$\n$_CLICK"
+!endif
+
+!ifdef MUI_LICENSEPAGE
+ ${LangFileString} MUI_TEXT_LICENSE_TITLE "License Agreement"
+ ${LangFileString} MUI_TEXT_LICENSE_SUBTITLE "Please review the license terms before installing $(^NameDA)."
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM "If you accept the terms of the agreement, click I Agree to continue. You must accept the agreement to install $(^NameDA)."
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM_CHECKBOX "If you accept the terms of the agreement, click the check box below. You must accept the agreement to install $(^NameDA). $_CLICK"
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS "If you accept the terms of the agreement, select the first option below. You must accept the agreement to install $(^NameDA). $_CLICK"
+!endif
+
+!ifdef MUI_UNLICENSEPAGE
+ ${LangFileString} MUI_UNTEXT_LICENSE_TITLE "License Agreement"
+ ${LangFileString} MUI_UNTEXT_LICENSE_SUBTITLE "Please review the license terms before uninstalling $(^NameDA)."
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM "If you accept the terms of the agreement, click I Agree to continue. You must accept the agreement to uninstall $(^NameDA)."
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM_CHECKBOX "If you accept the terms of the agreement, click the check box below. You must accept the agreement to uninstall $(^NameDA). $_CLICK"
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS "If you accept the terms of the agreement, select the first option below. You must accept the agreement to uninstall $(^NameDA). $_CLICK"
+!endif
+
+!ifdef MUI_LICENSEPAGE | MUI_UNLICENSEPAGE
+ ${LangFileString} MUI_INNERTEXT_LICENSE_TOP "Press Page Down to see the rest of the agreement."
+!endif
+
+!ifdef MUI_COMPONENTSPAGE
+ ${LangFileString} MUI_TEXT_COMPONENTS_TITLE "Choose Components"
+ ${LangFileString} MUI_TEXT_COMPONENTS_SUBTITLE "Choose which features of $(^NameDA) you want to install."
+!endif
+
+!ifdef MUI_UNCOMPONENTSPAGE
+ ${LangFileString} MUI_UNTEXT_COMPONENTS_TITLE "Choose Components"
+ ${LangFileString} MUI_UNTEXT_COMPONENTS_SUBTITLE "Choose which features of $(^NameDA) you want to uninstall."
+!endif
+
+!ifdef MUI_COMPONENTSPAGE | MUI_UNCOMPONENTSPAGE
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_TITLE "Description"
+ !ifndef NSIS_CONFIG_COMPONENTPAGE_ALTERNATIVE
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO "Position your mouse over a component to see its description."
+ !else
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO "Select a component to see its description."
+ !endif
+!endif
+
+!ifdef MUI_DIRECTORYPAGE
+ ${LangFileString} MUI_TEXT_DIRECTORY_TITLE "Choose Game Location"
+ ${LangFileString} MUI_TEXT_DIRECTORY_SUBTITLE "Choose your Call of Duty Black Ops III game folder in which to install $(^NameDA)."
+!endif
+
+!ifdef MUI_UNDIRECTORYPAGE
+ ${LangFileString} MUI_UNTEXT_DIRECTORY_TITLE "Choose Uninstall Location"
+ ${LangFileString} MUI_UNTEXT_DIRECTORY_SUBTITLE "Choose the folder from which to uninstall $(^NameDA)."
+!endif
+
+!ifdef MUI_INSTFILESPAGE
+ ${LangFileString} MUI_TEXT_INSTALLING_TITLE "Installing"
+ ${LangFileString} MUI_TEXT_INSTALLING_SUBTITLE "Please wait while $(^NameDA) is being installed."
+ ${LangFileString} MUI_TEXT_FINISH_TITLE "Installation Complete"
+ ${LangFileString} MUI_TEXT_FINISH_SUBTITLE "Setup was completed successfully."
+ ${LangFileString} MUI_TEXT_ABORT_TITLE "Installation Aborted"
+ ${LangFileString} MUI_TEXT_ABORT_SUBTITLE "Setup was not completed successfully."
+!endif
+
+!ifdef MUI_UNINSTFILESPAGE
+ ${LangFileString} MUI_UNTEXT_UNINSTALLING_TITLE "Uninstalling"
+ ${LangFileString} MUI_UNTEXT_UNINSTALLING_SUBTITLE "Please wait while $(^NameDA) is being uninstalled."
+ ${LangFileString} MUI_UNTEXT_FINISH_TITLE "Uninstallation Complete"
+ ${LangFileString} MUI_UNTEXT_FINISH_SUBTITLE "Uninstall was completed successfully."
+ ${LangFileString} MUI_UNTEXT_ABORT_TITLE "Uninstallation Aborted"
+ ${LangFileString} MUI_UNTEXT_ABORT_SUBTITLE "Uninstall was not completed successfully."
+!endif
+
+!ifdef MUI_FINISHPAGE
+ ${LangFileString} MUI_TEXT_FINISH_INFO_TITLE "Completing $(^NameDA) Setup"
+ ${LangFileString} MUI_TEXT_FINISH_INFO_TEXT "$(^NameDA) has been installed on your computer.$\r$\n$\r$\nClick Finish to close Setup."
+ ${LangFileString} MUI_TEXT_FINISH_INFO_REBOOT "Your computer must be restarted in order to complete the installation of $(^NameDA). Do you want to reboot now?"
+!endif
+
+!ifdef MUI_UNFINISHPAGE
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_TITLE "Completing $(^NameDA) Uninstall"
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_TEXT "$(^NameDA) has been uninstalled from your computer.$\r$\n$\r$\nClick Finish to close Setup."
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_REBOOT "Your computer must be restarted in order to complete the uninstallation of $(^NameDA). Do you want to reboot now?"
+!endif
+
+!ifdef MUI_FINISHPAGE | MUI_UNFINISHPAGE
+ ${LangFileString} MUI_TEXT_FINISH_REBOOTNOW "Reboot now"
+ ${LangFileString} MUI_TEXT_FINISH_REBOOTLATER "I want to manually reboot later"
+ ${LangFileString} MUI_TEXT_FINISH_RUN "&Run $(^NameDA)"
+ ${LangFileString} MUI_TEXT_FINISH_SHOWREADME "&Show Readme"
+ ${LangFileString} MUI_BUTTONTEXT_FINISH "&Finish"
+!endif
+
+!ifdef MUI_STARTMENUPAGE
+ ${LangFileString} MUI_TEXT_STARTMENU_TITLE "Choose Start Menu Folder"
+ ${LangFileString} MUI_TEXT_STARTMENU_SUBTITLE "Choose a Start Menu folder for the $(^NameDA) shortcuts."
+ ${LangFileString} MUI_INNERTEXT_STARTMENU_TOP "Select the Start Menu folder in which you would like to create the program's shortcuts. You can also enter a name to create a new folder."
+ ${LangFileString} MUI_INNERTEXT_STARTMENU_CHECKBOX "Do not create shortcuts"
+!endif
+
+!ifdef MUI_UNCONFIRMPAGE
+ ${LangFileString} MUI_UNTEXT_CONFIRM_TITLE "Uninstall $(^NameDA)"
+ ${LangFileString} MUI_UNTEXT_CONFIRM_SUBTITLE "Remove $(^NameDA) from your computer."
+!endif
+
+!ifdef MUI_ABORTWARNING
+ ${LangFileString} MUI_TEXT_ABORTWARNING "Are you sure you want to quit $(^Name) Setup?"
+!endif
+
+!ifdef MUI_UNABORTWARNING
+ ${LangFileString} MUI_UNTEXT_ABORTWARNING "Are you sure you want to quit $(^Name) Uninstall?"
+!endif
+
+!ifdef MULTIUSER_INSTALLMODEPAGE
+ ${LangFileString} MULTIUSER_TEXT_INSTALLMODE_TITLE "Choose Users"
+ ${LangFileString} MULTIUSER_TEXT_INSTALLMODE_SUBTITLE "Choose for which users you want to install $(^NameDA)."
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_TOP "Select whether you want to install $(^NameDA) only for yourself or for all users of this computer. $(^ClickNext)"
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_ALLUSERS "Install for anyone using this computer"
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_CURRENTUSER "Install just for me"
+!endif
diff --git a/installer/Contrib/License.txt b/installer/Contrib/License.txt
new file mode 100644
index 00000000..3028fb28
--- /dev/null
+++ b/installer/Contrib/License.txt
@@ -0,0 +1 @@
+SAMPLELICENSEAGREEMENT
\ No newline at end of file
diff --git a/installer/README.md b/installer/README.md
new file mode 100644
index 00000000..3d8a0c3a
--- /dev/null
+++ b/installer/README.md
@@ -0,0 +1,23 @@
+## Scriptable installer for Call of Duty game clients
+
+- Please feel free to contribute
+
+### Prerequisites
+
+- ~~[Nullsoft Scriptable Install System](https://nsis.sourceforge.io/Download)~~ (*Tools now included*)
+
+| Game | Official |
+|---------------------------------------------|:--------:|
+| Call of Duty: World at War (T4) | ❌ |
+| Call of Duty: Modern Warfare 2 (IW4x) | ❌ |
+| Call of Duty: Black Ops (T5) | ❌ |
+| Call of Duty: Modern Warfare 3 (IW5) | ❌ |
+| Call of Duty: Black Ops 2 (T6) | ❌ |
+| Call of Duty: Ghosts (IW6x) | ❌ |
+| Call of Duty: Advanced Warfare (S1x) | ❌ |
+| Call of Duty: Modern Warfare Remastered (H1) | ❌ |
+| Call of Duty: Black Ops III (T7) | ☑️ |
+| Call of Duty: Infinite Warfare (IW7) | ❌ |
+| Call of Duty: Black Ops 4 (T8) | ☑️ |
+| Call of Duty: Modern Warfare (2019) (IW8x) | ❌ |
+| Call of Duty: Cold War (T9D) | ❌ |
diff --git a/installer/Readme.txt b/installer/Readme.txt
new file mode 100644
index 00000000..0a8d96e4
--- /dev/null
+++ b/installer/Readme.txt
@@ -0,0 +1,15 @@
+T7x will no longer receive updates
+
+It is with deep regret that I must inform you that I have received a formal complaint from the original copyright holder of the source code. T7x is a project that utilizes source code from another defunct project called "boiii," licensed under the GPLv3.
+
+I hold deep respect for the immense amount of work and time invested by the previous developer in reverse-engineering and enabling the game to be modded to the extent this client allows. Therefore, I am honoring the claim that I cannot use boiii's technology.
+
+As part of the agreement, this project is to be ARCHIVED IMMEDIATELY, and it will no longer receive any updates or support.
+
+It was also a agreed that this notice shall remain, informing the public that I am not discontinuing this client due to an action by a specific American video game corporation.
+
+All the involved parties wish that any further attempts at creating a modded client for Black Ops 3 allocate time and effort into developing their own technology rather than utilizing boiii's source code.
+
+No other services provided by AlterWare are subject to change.
+
+- T7x Developer(s)
\ No newline at end of file
diff --git a/installer/compile.bat b/installer/compile.bat
new file mode 100644
index 00000000..17166410
--- /dev/null
+++ b/installer/compile.bat
@@ -0,0 +1,4 @@
+@echo off
+
+if not exist "build" mkdir "build"
+tools\makensis.exe "t7x_Installer.nsi"
\ No newline at end of file
diff --git a/installer/game/base_game_dir/README.md b/installer/game/base_game_dir/README.md
new file mode 100644
index 00000000..4653115d
--- /dev/null
+++ b/installer/game/base_game_dir/README.md
@@ -0,0 +1,40 @@
+# T7 Server Config
+Config for T7 Dedicated Servers for use with the T7x Client.
+
+# How to use
+1. Download the BO3 Unranked Dedicated Server via Steam (It's located in the "Tools" section in your steam library.)
+2. Open the Unranked Server folder in windows explorer (if you own BO3 on Steam and have it installed it will be in your BO3 Game Folder)
+3. Add t7x.exe to the UnrankedServer Folder
+4. Download this repository and extract startup batch files as well as the t7x and zone folder to the UnrankedServer Folder
+5. Edit the config(s) in /zone to your liking.
+6. (Optional) Edit your game rules under boiii/gamesettings/mp.
+6. Port forward UDP 27017.
+7. Start the Server using BOIII_MP_Server.bat or T7x_ZM_Server.bat
+
+# Additional Steps required for hosting Zombies Dedicated Servers
+As of right now you need to take additional Steps to host Zombies Servers.
+For Zombie Dedis to work they need to have the Zombies Maps and common FastFiles, these do not come with the UnrankedServer Files. This means you need to copy those over from your installed BO3 game folder.
+
+Copy common fastfiles that is needed for zombies.
+
+```
+zone/en_zm_patch.ff
+zone/en_zm_common.ff
+zone/zm_patch.ff
+zone/zm_common.fd
+zone/zm_common.ff
+zone/zm_levelcommon.ff
+```
+
+Now for the map. Shadows of Evil is zm_zod.
+
+```
+zone/en_zm_zod.ff
+zone/en_zm_zod_patch.ff
+zone/zm_zod.ff
+zone/zm_zod_patch.ff
+```
+
+from your BO3 Game folder into the UnrankedServer's ```zone``` Folder. Do the same with the FastFiles of the Maps you want to host on the Server, you do not need to copy the .xpak files, those hold Textures and Sounds which the Server doesn't need. You can use the zm_server.cfg as a short name references if you want to grab the others.
+
+You are now ready to start the Server using T7x_ZM_Server.bat. If the server still instantly closes while opening the T7x_ZM_Server.bat or T7x_CP_Server.bat. Check the console_mp.log from identities\dedicatedpc\ folder. Scroll down until you see "Could not find zone: xxxx".
diff --git a/installer/game/base_game_dir/T7x_CP_Server.bat b/installer/game/base_game_dir/T7x_CP_Server.bat
new file mode 100644
index 00000000..7b9f7b54
--- /dev/null
+++ b/installer/game/base_game_dir/T7x_CP_Server.bat
@@ -0,0 +1,36 @@
+@echo off
+::///////////////////////////////////////////////////////////////////////
+::/// T7x Dedicated Server Configuration start-up file ///
+::///////////////////////////////////////////////////////////////////////
+::// //
+::// Your Game Server Port. //
+::// Make sure you Port Forward both UDP & TCP //
+::///////////////////////////////////////////////////////////////////////
+
+set GamePort=27017
+
+::///////////////////////////////////////////////////////////////////////
+::// Below edits are optional unless you run multiable servers or mods.//
+::///////////////////////////////////////////////////////////////////////
+::// Load a mod on your server //
+::// Example: ModfolderName=mods/bots //
+::// //
+::// UNLOAD a mod on your server //
+::// Example: ModfolderName= //
+::///////////////////////////////////////////////////////////////////////
+
+set ModFolderName=
+
+::///////////////////////////////////////////////////////////////////////
+::// Your edited server.cfg in the "zone" folder goes here... //
+::// This is were you edit your hostname, rcon, inactivity, etc //
+::// (Optional) //
+::///////////////////////////////////////////////////////////////////////
+
+set ServerFilename=server_cp.cfg
+
+::///////////////////////////////////////////////////////////////////////
+:://DONE!! WARNING! Don't mess with anything below this line. SEROUSLY!//
+::///////////////////////////////////////////////////////////////////////
+
+start t7x.exe -dedicated +set fs_game "%ModFolderName%" +set net_port "%GamePort%" +set logfile 2 +exec %ServerFilename%
\ No newline at end of file
diff --git a/installer/game/base_game_dir/T7x_MP_Server.bat b/installer/game/base_game_dir/T7x_MP_Server.bat
new file mode 100644
index 00000000..6e870d6e
--- /dev/null
+++ b/installer/game/base_game_dir/T7x_MP_Server.bat
@@ -0,0 +1,36 @@
+@echo off
+::///////////////////////////////////////////////////////////////////////
+::/// T7x Dedicated Server Configuration start-up file ///
+::///////////////////////////////////////////////////////////////////////
+::// //
+::// Your Game Server Port. //
+::// Make sure you Port Forward both UDP & TCP //
+::///////////////////////////////////////////////////////////////////////
+
+set GamePort=27017
+
+::///////////////////////////////////////////////////////////////////////
+::// Below edits are optional unless you run multiable servers or mods.//
+::///////////////////////////////////////////////////////////////////////
+::// Load a mod on your server //
+::// Example: ModfolderName=mods/bots //
+::// //
+::// UNLOAD a mod on your server //
+::// Example: ModfolderName= //
+::///////////////////////////////////////////////////////////////////////
+
+set ModFolderName=
+
+::///////////////////////////////////////////////////////////////////////
+::// Your edited server.cfg in the "zone" folder goes here... //
+::// This is were you edit your hostname, rcon, inactivity, etc //
+::// (Optional) //
+::///////////////////////////////////////////////////////////////////////
+
+set ServerFilename=server.cfg
+
+::///////////////////////////////////////////////////////////////////////
+:://DONE!! WARNING! Don't mess with anything below this line. SEROUSLY!//
+::///////////////////////////////////////////////////////////////////////
+
+start t7x.exe -dedicated +set fs_game "%ModFolderName%" +set net_port "%GamePort%" +set logfile 2 +exec %ServerFilename%
\ No newline at end of file
diff --git a/installer/game/base_game_dir/T7x_ZM_Server.bat b/installer/game/base_game_dir/T7x_ZM_Server.bat
new file mode 100644
index 00000000..16f03667
--- /dev/null
+++ b/installer/game/base_game_dir/T7x_ZM_Server.bat
@@ -0,0 +1,36 @@
+@echo off
+::///////////////////////////////////////////////////////////////////////
+::/// T7x Dedicated Server Configuration start-up file ///
+::///////////////////////////////////////////////////////////////////////
+::// //
+::// Your Game Server Port. //
+::// Make sure you Port Forward both UDP & TCP //
+::///////////////////////////////////////////////////////////////////////
+
+set GamePort=27017
+
+::///////////////////////////////////////////////////////////////////////
+::// Below edits are optional unless you run multiable servers or mods.//
+::///////////////////////////////////////////////////////////////////////
+::// Load a mod on your server //
+::// Example: ModfolderName=mods/bots //
+::// //
+::// UNLOAD a mod on your server //
+::// Example: ModfolderName= //
+::///////////////////////////////////////////////////////////////////////
+
+set ModFolderName=
+
+::///////////////////////////////////////////////////////////////////////
+::// Your edited server.cfg in the "zone" folder goes here... //
+::// This is were you edit your hostname, rcon, inactivity, etc //
+::// (Optional) //
+::///////////////////////////////////////////////////////////////////////
+
+set ServerFilename=server_zm.cfg
+
+::///////////////////////////////////////////////////////////////////////
+:://DONE!! WARNING! Don't mess with anything below this line. SEROUSLY!//
+::///////////////////////////////////////////////////////////////////////
+
+start t7x.exe -dedicated +set fs_game "%ModFolderName%" +set net_port "%GamePort%" +set logfile 2 +exec %ServerFilename%
\ No newline at end of file
diff --git a/installer/game/base_game_dir/t7x/bots.txt b/installer/game/base_game_dir/t7x/bots.txt
new file mode 100644
index 00000000..a8682ed4
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/bots.txt
@@ -0,0 +1,19 @@
+Snake,BOT
+Diamante,BOT
+Dss0,BOT
+st0rm,BOT
+Louvenarde,BOT
+serious,BOT
+JariK,BOT
+xensik,BOT
+Jebus3211,BOT
+FragsAreUs,BOT
+Fry,BOT
+X3RX35,BOT
+Brent,BOT
+Joel,BOT
+RektInator,BOT
+Doctor,BOT
+Jimbo,BOT
+Laupetin,BOT
+
diff --git a/installer/game/base_game_dir/t7x/gamesettings/cp/gamesettings_coop.cfg b/installer/game/base_game_dir/t7x/gamesettings/cp/gamesettings_coop.cfg
new file mode 100644
index 00000000..2744acb8
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/cp/gamesettings_coop.cfg
@@ -0,0 +1,16 @@
+gametype_setting scorelimit 7500
+gametype_setting timelimit 10
+gametype_setting prematchperiod 0
+gametype_setting roundlimit 1
+gametype_setting playerNumlives 0
+gametype_setting playerrespawndelay 0
+gametype_setting waverespawndelay 0
+gametype_setting disableweapondrop 1
+gametype_setting allowAnnouncer 0
+gametype_setting startRound 1
+gametype_setting magic 1
+gametype_setting headshotsonly 0
+gametype_setting allowdogs 0
+gametype_setting disableClassSelection 0
+gametype_setting disableCompass 1
+gametype_setting characterCustomization 0
diff --git a/installer/game/base_game_dir/t7x/gamesettings/cp/gamesettings_cpzm.cfg b/installer/game/base_game_dir/t7x/gamesettings/cp/gamesettings_cpzm.cfg
new file mode 100644
index 00000000..97938222
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/cp/gamesettings_cpzm.cfg
@@ -0,0 +1,16 @@
+gametype_setting scorelimit 7500
+gametype_setting timelimit 10
+gametype_setting prematchperiod 0
+gametype_setting roundlimit 1
+gametype_setting playerNumlives 0
+gametype_setting playerrespawndelay 0
+gametype_setting waverespawndelay 0
+gametype_setting disableweapondrop 1
+gametype_setting allowAnnouncer 0
+gametype_setting startRound 1
+gametype_setting magic 1
+gametype_setting headshotsonly 0
+gametype_setting allowdogs 0
+gametype_setting disableClassSelection 1
+gametype_setting disableCompass 1
+gametype_setting characterCustomization 0
diff --git a/installer/game/base_game_dir/t7x/gamesettings/cp/gamesettings_default.cfg b/installer/game/base_game_dir/t7x/gamesettings/cp/gamesettings_default.cfg
new file mode 100644
index 00000000..39d51090
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/cp/gamesettings_default.cfg
@@ -0,0 +1,108 @@
+gametype_setting allowAnnouncer 1
+gametype_setting allowBattleChatter 1
+gametype_setting allowFinalKillcam 1
+gametype_setting allowHitMarkers 2
+gametype_setting allowInGameTeamChange 0
+gametype_setting allowKillcam 1
+gametype_setting allowSpectating 0
+gametype_setting autoDestroyTime 0
+gametype_setting autoTeamBalance 0
+gametype_setting bombTimer 0
+gametype_setting bulletDamageScalar 1.0
+gametype_setting captureTime 10
+gametype_setting crateCaptureTime 3
+gametype_setting cumulativeRoundScores 0
+gametype_setting deathPointLoss 0
+gametype_setting defuseTime 0
+gametype_setting delayPlayer 0
+gametype_setting destroyTime 0
+gametype_setting disableAmbientFx 0
+gametype_setting disableAttachments 0
+gametype_setting disableCAC 0
+gametype_setting disableContracts 0
+gametype_setting disableTacInsert 0
+gametype_setting disableweapondrop 1
+gametype_setting disallowaimslowdown 0
+gametype_setting disallowprone 0
+gametype_setting enemyCarrierVisible 0
+gametype_setting extraTime 0
+gametype_setting flagCaptureGracePeriod 0
+gametype_setting flagDecayTime 0
+gametype_setting flagRespawnTime 0
+gametype_setting forceRadar 0
+gametype_setting friendlyfiretype 0
+gametype_setting hardcoremode 0
+gametype_setting hotPotato 0
+gametype_setting idleFlagDecay 0
+gametype_setting idleFlagResetTime 0
+gametype_setting inactivityKick 0
+gametype_setting kothMode 0
+gametype_setting leaderBonus 0
+gametype_setting loadoutKillstreaksEnabled 0
+gametype_setting maxAllocation 10
+gametype_setting maxObjectiveEventsPerMinute 0
+gametype_setting maxPlayerDefensive 0
+gametype_setting maxPlayerEventsPerMinute 0
+gametype_setting maxPlayerOffensive 0
+gametype_setting multiBomb 0
+gametype_setting objectivePingTime 6
+gametype_setting objectiveSpawnTime 0
+gametype_setting onlyHeadshots 0
+gametype_setting perksEnabled 0
+gametype_setting plantTime 0
+gametype_setting playerForceRespawn 1
+gametype_setting playerHealthRegenTime 5
+gametype_setting playerKillsMax 0
+gametype_setting playerMaxHealth 100
+gametype_setting playerNumlives 0
+gametype_setting playerObjectiveHeldRespawnDelay 0
+gametype_setting playerQueuedRespawn 0
+gametype_setting playerRespawnDelay 0
+gametype_setting playerSprintTime 4
+gametype_setting pregameAlwaysShowCACEdit 1
+gametype_setting pregameAlwaysShowStreakEdit 1
+gametype_setting pregameCACModifyTime 0
+gametype_setting pregameDraftEnabled 0
+gametype_setting pregameDraftRoundTime 0
+gametype_setting pregameItemMaxVotes 0
+gametype_setting pregameItemVoteEnabled 0
+gametype_setting pregameItemVoteRoundTime 0
+gametype_setting pregamePositionShuffleMethod 0
+gametype_setting pregamePositionSortType 0
+gametype_setting pregamePostRoundTime 0
+gametype_setting pregamePostStageTime 0
+gametype_setting pregamePreStageTime 0
+gametype_setting pregameScorestreakModifyTime 0
+gametype_setting randomObjectiveLocations 0
+gametype_setting roundlimit 1
+gametype_setting roundStartExplosiveDelay 5
+gametype_setting roundStartKillstreakDelay 0
+gametype_setting roundswitch 1 // rounds between switching teams
+gametype_setting roundwinlimit 0
+gametype_setting scoreHeroPowerGainFactor 1.0
+gametype_setting scoreHeroPowerTimeFactor 1.0
+gametype_setting scorelimit 100
+gametype_setting spectateType 1
+gametype_setting teamCount 1
+gametype_setting teamKillPenalty 2
+gametype_setting teamKillPointLoss 0
+gametype_setting teamKillPunishCount 3
+gametype_setting teamKillReducedPenalty 0.25
+gametype_setting teamKillScore 4
+gametype_setting teamKillSpawnDelay 20
+gametype_setting timelimit 10
+gametype_setting totalKillsMax 0
+gametype_setting vehiclesEnabled 1
+gametype_setting vehiclesTimed 1
+gametype_setting voipDeadChatWithDead 0
+gametype_setting voipDeadChatWithTeam 1
+gametype_setting voipDeadHearAllLiving 0
+gametype_setting voipDeadHearKiller 0
+gametype_setting voipDeadHearTeamLiving 1
+gametype_setting voipEveryoneHearsEveryone 0
+gametype_setting voipKillersHearVictim 1
+gametype_setting waverespawndelay 0
+gametype_setting zmDifficulty 1
+
+// player movement
+gametype_setting trm_maxHeight 144.0
diff --git a/installer/game/base_game_dir/t7x/gamesettings/cp/gamesettings_doa.cfg b/installer/game/base_game_dir/t7x/gamesettings/cp/gamesettings_doa.cfg
new file mode 100644
index 00000000..ffeae293
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/cp/gamesettings_doa.cfg
@@ -0,0 +1,4 @@
+gametype_setting disableClassSelection 1
+gametype_setting disableCompass 1
+gametype_setting characterCustomization 1
+gametype_setting spectateType 0
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_ball.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_ball.cfg
new file mode 100644
index 00000000..9eae389f
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_ball.cfg
@@ -0,0 +1,59 @@
+//Don't touch the first 2 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "15" // The amount of time before the game starts.
+gts preroundperiod "5" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts allowSpectating "1" // Allow players to spectate other players or CODcasting.
+gts spectateType "1" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+gts allowInGameTeamChange "1" // Allow players to switch teams?
+gts autoTeamBalance "1" // Automatically assign players to teams
+gts allowFinalKillcam "1" // Controls whether the final killcam is played.
+
+gts timelimit "5" // Time limit of the game.
+gts roundScoreLimit "10" // Round score limit reach
+gts scorelimit "0" // Score limit.
+gts roundlimit "2" // The number of rounds that will be played before the game ends.
+
+gts ballCount "1" // How many balls you can handle?
+gts carryScore "2"
+gts throwScore "1"
+gts carrierArmor "100"
+gts idleFlagResetTime "15" // The time before a ball is automatically returned to base. (0-60 seconds)
+
+//gts loadoutKillstreaksEnabled "1" // Disable Killstreaks by setting this to 0
+//gts perksEnabled "1" // Disable Perks by setting this to 0
+//gts disableVehicleSpawners "0" // This should disable robots from the DLC map Rupture by setting this to 1
+//gts disableweapondrop "0" // No weapons on the ground.
+//gts disallowprone "0" // Don't allow players to lay down.
+
+//Hardcore Mode
+//gts hardcoreMode "1" // Enable hardcore mode.
+//gts friendlyfiretype "1" // Enable or Disable Friendly Fire. 1 on, 2 reflect, 3 shared.
+//gts playerHealthRegenTime "0" // Time it takes you to recover damage.
+//gts playerMaxHealth "30" // Percent of Health players will have on Respawn.
+//gts onlyHeadshots "0" // Headshots only
+//gts allowKillcam "0" // Allow Killcam.
+//gts allowbattlechatter "0" // Shut the fucking player dialogues up.
+//gts teamKillPointLoss "1" // Points per Kill - The number of points for each kill. (0-25)
+//gts teamKillPunishCount "3" // Kick constant Team killers out of your server.
+
+
+gts scoreHeroPowerGainFactor "0.684" //Score earned towards Hero Weapons and Abilities are multiplied by this factor in BALL
+gts scoreHeroPowerTimeFactor "0.684"
+
+gts enemyCarrierVisible "2" // delayed can see person with ball on map
+
+gts captureTime "0" // Pickup Time. The amount of time it takes to pickup the ball.
+gts defuseTime "0" // Return Time. How long it takes to return ball. (-1 = off. 0 = Instant. (Default) 10 = limit of seconds.)
+
+gts spawntraptriggertime "10"
+
+gts gameAdvertisementRuleTimeLeft "4"
+gts gameAdvertisementRuleRound "3"
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_clean.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_clean.cfg
new file mode 100644
index 00000000..0c93de98
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_clean.cfg
@@ -0,0 +1,29 @@
+//Don't touch the first 2 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "15" // The amount of time before the game starts.
+gts preroundperiod "5" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts allowSpectating "1" // Allow players to spectate other players or CODcasting.
+gts spectateType "1" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+gts allowInGameTeamChange "1" // Allow players to switch teams?
+gts autoTeamBalance "1" // Automatically assign players to teams
+gts allowFinalKillcam "1" // Controls whether the final killcam is played.
+
+gts timelimit "10" // Time limit of the game.
+gts scorelimit "60" // Score limit reach to end the game.
+gts teamCount "2"
+gts teamScorePerKill "0"
+gts teamScorePerCleanDeposit "1" // Points awarded to the team when depositing a fragment.
+gts cleanDepositOfflineTime "0"
+gts cleanDepositOnlineTime "60" // The amount of team each fracture site is active.
+gts cleanDepositRotation "1"
+
+gts scoreHeroPowerGainFactor "0.646" // Score earned towards Hero Weapons and Abilities are multiplied by this factor
+gts scoreHeroPowerTimeFactor "0.646"
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_conf.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_conf.cfg
new file mode 100644
index 00000000..0c7d8978
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_conf.cfg
@@ -0,0 +1,53 @@
+//Don't touch the first 2 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "15" // The amount of time before the game starts.
+gts preroundperiod "5" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts spectateType "1" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+gts allowInGameTeamChange "1" // Allow players to switch teams?
+gts allowFinalKillcam "1" // Controls whether the final killcam is played.
+
+
+gts timelimit "10" // Time limit of the game.
+gts scorelimit "100" // Score limit reach to end the game.
+gts teamCount "2" // Set this higher if you want Multi-Team Deathmatch that was cut from playlist. (2-6)
+//gts roundLimit "1" // The number of rounds that will be played before the game ends.
+gts teamScorePerKill "0" // Points per Kill - The number of points for each kill. (0-25)
+//gts teamScorePerKillConfirmed "1" // Points per Kills Confirmed. - The number of points for each kill confirmed. (0-25)
+//gts teamScorePerKillDenied "0" // Points per Kill Denied - The number of points for each kill denied. (0-25)
+//gts teamScorePerHeadshot "0" // Headshot Bonus Points - Extra points awarded if the kill is a headshot in addition to the points per kill. (0-25)
+//gts playerNumLives "0" // Number of Lives - The number of times each player can die before they are no longer allowed to respawn. (0-25)
+
+gts antiBoostDistance "100"
+//gts loadoutKillstreaksEnabled "1" // Disable Killstreaks by setting this to 0
+//gts perksEnabled "1" // Disable Perks by setting this to 0
+//gts disableVehicleSpawners "0" // This should disable robots from the DLC map Rupture by setting this to 1
+//gts disableweapondrop "0" // No weapons on the ground.
+//gts disallowprone "0" // Don't allow players to lay down.
+//gts allowHitMarkers "2" // Rather or not to show hitmakers?
+//gts allowAnnouncer "1" // Annouce enemy team actions
+
+//Hardcore Mode
+//gts hardcoreMode "1" // Enable hardcore mode.
+//gts friendlyfiretype "1" // Enable or Disable Friendly Fire. 1 on, 2 reflect, 3 shared.
+//gts playerHealthRegenTime "0" // Time it takes you to recover damage.
+//gts playerMaxHealth "30" // Percent of Health players will have on Respawn.
+//gts onlyHeadshots "0" // Headshots only
+//gts allowKillcam "0" // Allow Killcam.
+//gts allowbattlechatter "0" // Shut the fucking player dialogues up.
+//gts teamKillPointLoss "1" // Points per Kill - The number of points for each kill. (0-25)
+//gts teamKillPunishCount "3" // Kick constant Team killers out of your server.
+
+
+gts scoreHeroPowerGainFactor "0.646" //Score earned towards Hero Weapons and Abilities are multiplied by this factor
+gts scoreHeroPowerTimeFactor "0.646"
+
+gts gameAdvertisementRuleScorePercent "15"
+gts gameAdvertisementRuleTimeLeft "2"
\ No newline at end of file
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_ctf.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_ctf.cfg
new file mode 100644
index 00000000..5a77bab5
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_ctf.cfg
@@ -0,0 +1,50 @@
+//Don't touch the first 2 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "15" // The amount of time before the game starts.
+gts preroundperiod "5" // The amount of time before the round start.
+gts allowSpectating "1" // Allow players to spectate other players or CODcasting.
+gts spectateType "1" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+gts inactivityKick "120" // Kick players that's AFK
+gts allowInGameTeamChange "1" // Allow players to switch teams?
+gts allowFinalKillcam "1" // Controls whether the final killcam is played
+
+gts timelimit "5" // Time limit of the game.
+gts scorelimit "3" // The number of flags needed to win the round.
+gts roundLimit "2" // The number of rounds that will be played before the game ends.
+gts roundwinlimit "2" // Round Win Limit. The number of rounds a team needs to win before the game ends.
+gts enemyCarrierVisible "2" // Enemy Carrier. How and if the enemy appears on the minimap. (0 = No. 1 = Yes. 2 = Delayed)
+gts idleFlagResetTime "30" // The time before a flag is automatically returned to base. (0-60 seconds)
+gts captureTime "0" // Pickup Time. The amount of time it takes to pickup the enemy flag.
+gts defuseTime "0" // Return Time. How long it takes to return a flag. (-1 = off. 0 = Instant. (Default) 10 = limit of seconds.)
+gts playerRespawnDelay "5" // The amount of time a player has to wait before respawning.
+
+//gts loadoutKillstreaksEnabled "1" // Disable Killstreaks by setting this to 0
+//gts perksEnabled "1" // Disable Perks by setting this to 0
+//gts disableVehicleSpawners "0" // This should disable robots from the DLC map Rupture by setting this to 1
+//gts disableweapondrop "0" // No weapons on the ground.
+//gts disallowprone "0" // Don't allow players to lay down.
+//gts allowHitMarkers "2" // Rather or not to show hitmakers?
+//gts allowAnnouncer "1" // Annouce enemy team actions
+
+//Hardcore Mode
+//gts hardcoreMode "1" // Enable hardcore mode.
+//gts friendlyfiretype "1" // Enable or Disable Friendly Fire. 1 on, 2 reflect, 3 shared.
+//gts playerHealthRegenTime "0" // Time it takes you to recover damage.
+//gts playerMaxHealth "30" // Percent of Health players will have on Respawn.
+//gts onlyHeadshots "0" // Headshots only
+//gts allowKillcam "0" // Allow Killcam.
+//gts allowbattlechatter "0" // Shut the fucking player dialogues up.
+//gts teamKillPointLoss "1" // Points per Kill - The number of points for each kill. (0-25)
+//gts teamKillPunishCount "3" // Kick constant Team killers out of your server.
+
+gts scoreHeroPowerGainFactor "0.835" //Score earned towards Hero Weapons and Abilities are multiplied by this factor in CTF
+gts scoreHeroPowerTimeFactor "0.835"
+gts gameAdvertisementRuleTimeLeft "4"
+gts gameAdvertisementRuleRound "3"
\ No newline at end of file
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_default.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_default.cfg
new file mode 100644
index 00000000..da999e6f
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_default.cfg
@@ -0,0 +1,175 @@
+
+gametype_setting allowAnnouncer 1
+gametype_setting allowBattleChatter 1
+gametype_setting allowFinalKillcam 1
+gametype_setting allowHitMarkers 2
+gametype_setting allowInGameTeamChange 1
+gametype_setting allowKillcam 1
+gametype_setting allowMapScripting 1
+gametype_setting allowSpectating 1
+gametype_setting antiBoostDistance 100
+gametype_setting autoDestroyTime 0
+gametype_setting autoTeamBalance 0
+gametype_setting ballCount 1
+gametype_setting bombTimer 0
+gametype_setting bootTime 5
+gametype_setting bulletDamageScalar 1.0
+gametype_setting captureTime 10
+gametype_setting carryScore 0
+gametype_setting carrierArmor 100
+gametype_setting crateCaptureTime 3
+gametype_setting cumulativeRoundScores 1
+gametype_setting deathPointLoss 0
+gametype_setting defuseTime 0
+gametype_setting delayPlayer 0
+gametype_setting destroyTime 0
+gametype_setting disableAmbientFx 0
+gametype_setting disableAttachments 0
+gametype_setting disableCAC 0
+gametype_setting disableClassSelection 0
+gametype_setting disableContracts 0
+gametype_setting disableTacInsert 0
+gametype_setting disableThirdPersonSpectating 0
+gametype_setting disableVehicleSpawners 0
+gametype_setting disableweapondrop 0
+gametype_setting disallowaimslowdown 0
+gametype_setting disallowprone 0
+gametype_setting droppedTagRespawn 0
+gametype_setting enemyCarrierVisible 2
+gametype_setting extraTime 0
+gametype_setting flagCanBeNeutralized 0
+gametype_setting flagCaptureCondition 1
+gametype_setting flagCaptureGracePeriod 0
+gametype_setting flagDecayTime 0
+gametype_setting flagRespawnTime 0
+gametype_setting forceRadar 0
+gametype_setting friendlyfiretype 0
+gametype_setting gameAdvertisementRuleScorePercent 0
+gametype_setting gameAdvertisementRuleTimeLeft 0
+gametype_setting gameAdvertisementRuleRound 0
+gametype_setting gameAdvertisementRuleRoundsWon 0
+gametype_setting gunSelection 0
+gametype_setting hardcoremode 0
+gametype_setting hotPotato 0
+gametype_setting idleFlagDecay 0
+gametype_setting idleFlagResetTime 0
+gametype_setting inactivityKick 0
+gametype_setting incrementalSpawnDelay 0
+gametype_setting infectionMode 0
+gametype_setting killEventScoreMultiplier 1
+gametype_setting kothMode 0
+gametype_setting leaderBonus 0
+gametype_setting loadoutKillstreaksEnabled 1
+gametype_setting killstreaksGiveGameScore 1
+gametype_setting maxAllocation 10
+gametype_setting maxObjectiveEventsPerMinute 0
+gametype_setting maxPlayerDefensive 0
+gametype_setting maxPlayerEventsPerMinute 0
+gametype_setting maxPlayerOffensive 0
+gametype_setting maxSuicidesBeforeKick 0
+gametype_setting movePlayers 1
+gametype_setting multiBomb 0
+gametype_setting objectivePingTime 4
+gametype_setting objectiveSpawnTime 0
+gametype_setting oldschoolMode 0
+gametype_setting classicMode 0
+gametype_setting onlyHeadshots 0
+gametype_setting OvertimetimeLimit 2
+gametype_setting perksEnabled 1
+gametype_setting plantTime 0
+gametype_setting playerForceRespawn 1
+gametype_setting playerHealthRegenTime 5
+gametype_setting playerKillsMax 0
+gametype_setting playerMaxHealth 100
+gametype_setting playerNumlives 0
+gametype_setting playerObjectiveHeldRespawnDelay 0
+gametype_setting playerQueuedRespawn 0
+gametype_setting playerRespawnDelay 0
+gametype_setting playerSprintTime 4
+gametype_setting pointsForSurvivalBonus 0
+gametype_setting pointsPerMeleeKill 0
+gametype_setting pointsPerPrimaryGrenadeKill 0
+gametype_setting pointsPerPrimaryKill 0
+gametype_setting pointsPerSecondaryKill 0
+gametype_setting pointsPerWeaponKill 0
+gametype_setting pregameAlwaysShowCACEdit 1
+gametype_setting pregameAlwaysShowStreakEdit 1
+gametype_setting pregameCACModifyTime 90
+gametype_setting pregameDraftEnabled 0
+gametype_setting pregameDraftRoundTime 30
+gametype_setting pregameDraftType 0
+gametype_setting pregameItemMaxVotes 1
+gametype_setting pregameItemVoteEnabled 0
+gametype_setting pregameItemVoteRoundTime 30
+gametype_setting pregamePositionShuffleMethod 0
+gametype_setting pregamePositionSortType 0
+gametype_setting pregamePostRoundTime 3
+gametype_setting pregamePostStageTime 3
+gametype_setting pregamePreStageTime 5
+gametype_setting pregameScorestreakModifyTime 30
+gametype_setting prematchperiod 15
+gametype_setting preroundperiod 5
+gametype_setting prematchrequirement 0
+gametype_setting prematchrequirementtime 0
+gametype_setting randomObjectiveLocations 0
+gametype_setting rebootPlayers 0
+gametype_setting rebootTime 15
+gametype_setting robotSpeed 1
+gametype_setting robotShield 0
+gametype_setting roundlimit 1
+gametype_setting roundScoreLimit 0
+gametype_setting roundStartExplosiveDelay 10
+gametype_setting roundStartKillstreakDelay 15
+gametype_setting roundswitch 1 // rounds between switching teams
+gametype_setting roundwinlimit 0
+gametype_setting scoreHeroPowerGainFactor 1.0
+gametype_setting scoreHeroPowerTimeFactor 1.0
+gametype_setting scoreThiefPowerGainFactor 1.0
+gametype_setting scorelimit 100
+gametype_setting scorePerPlayer 0
+gametype_setting scoreResetOnDeath 1
+gametype_setting setbacks 0
+gametype_setting shutdownDamage 2
+gametype_setting silentPlant 0
+gametype_setting spawnprotectiontime 3
+gametype_setting spawnsuicidepenalty 0
+gametype_setting spawnteamkilledpenalty 0
+gametype_setting spawntraptriggertime 5
+gametype_setting spectateType 1
+gametype_setting cleanDepositOnlineTime 60
+gametype_setting cleanDepositRotation 1
+gametype_setting teamAssignment 2
+gametype_setting teamCount 2
+gametype_setting teamKillPenalty 2
+gametype_setting teamKillPointLoss 1
+gametype_setting teamKillPunishCount 0
+gametype_setting teamKillReducedPenalty 1
+gametype_setting teamKillScore 4
+gametype_setting teamKillSpawnDelay 20
+gametype_setting teamNumLives 0
+gametype_setting teamScorePerCleanDeposit 1
+gametype_setting teamScorePerDeath 0
+gametype_setting teamScorePerHeadshot 0
+gametype_setting teamScorePerKill 1
+gametype_setting teamScorePerKillConfirmed 1
+gametype_setting teamScorePerKillDenied 0
+gametype_setting throwScore 0
+gametype_setting timelimit 10
+gametype_setting timelimit 10
+gametype_setting timePausesWhenInZone 0
+gametype_setting useEmblemInsteadOfFactionIcon 0
+gametype_setting vehiclesEnabled 1
+gametype_setting vehiclesTimed 1
+gametype_setting voipDeadChatWithDead 0
+gametype_setting voipDeadChatWithTeam 1
+gametype_setting voipDeadHearAllLiving 0
+gametype_setting voipDeadHearKiller 0
+gametype_setting voipDeadHearTeamLiving 1
+gametype_setting voipEveryoneHearsEveryone 0
+gametype_setting voipKillersHearVictim 1
+gametype_setting waverespawndelay 0
+gametype_setting weaponCount 0
+gametype_setting weaponTimer 0
+
+// player movement
+gametype_setting trm_maxHeight 95.0
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_dem.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_dem.cfg
new file mode 100644
index 00000000..b57cc7eb
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_dem.cfg
@@ -0,0 +1,56 @@
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "15" // The amount of time before the game starts.
+gts preroundperiod "5" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts allowInGameTeamChange "1" // Allow players to switch teams?
+gts allowFinalKillcam "1" // Controls whether the final killcam is played
+
+
+gts timelimit "2.5" // Time limit of the game.
+gts scorelimit "2" // Score limit reach to end the game.
+gts roundlimit "0" // The number of rounds that will be played before the game ends.
+gts bombTimer "45" // Bomb Timer. The amount of time before the bomb detonates. (2.5-150 seconds)
+gts plantTime "5" // Plant Time. The amount of time it takes to plant the bomb. (1-10 seconds)
+gts defuseTime "5" // Defuse Time. The amount of time it takes to defuse the bomb.(1-10 seconds)
+gts extraTime "2" // Extra Time. The amount of time added on to the current time when a bomb site is destroyed.
+gts OvertimetimeLimit "2" // Overtime. The amount of time the Overtime round will last before it ends.
+gts silentPlant "0" // Silent Plant. Players can hear the bomb being planted.
+gts roundStartExplosiveDelay "2" // Delay explosive weapon use at the start of the round.
+gts roundStartKillstreakDelay "15" // Delay scorestreaks start of the round.
+
+gts maxObjectiveEventsPerMinute "5" // Used to determine whether a player is scoreboosting.
+gts maxPlayerDefensive "128" // Used to determine whether a player is scoreboosting.
+gts maxPlayerEventsPerMinute "2.5" // Used to determine whether a player is scoreboosting.
+
+gts spawntraptriggertime "10"
+//gts loadoutKillstreaksEnabled "1" // Disable Killstreaks by setting this to 0
+//gts perksEnabled "1" // Disable Perks by setting this to 0
+//gts disableVehicleSpawners "0" // This should disable robots from the DLC map Rupture by setting this to 1
+//gts disableweapondrop "0" // No weapons on the ground.
+//gts disallowprone "0" // Don't allow players to lay down.
+//gts allowHitMarkers "2" // Rather or not to show hitmakers?
+//gts allowAnnouncer "1" // Annouce enemy team actions
+
+
+//Hardcore Mode
+//gts hardcoreMode "1" // Enable hardcore mode.
+//gts friendlyfiretype "1" // Enable or Disable Friendly Fire. 1 on, 2 reflect, 3 shared.
+//gts playerHealthRegenTime "0" // Time it takes you to recover damage.
+//gts playerMaxHealth "30" // Percent of Health players will have on Respawn.
+//gts allowKillcam "0" // Allow Killcam.
+//gts allowbattlechatter "0" // Shut the fucking player dialogues up.
+//gts teamKillPointLoss "1" // Points per Kill - The number of points for each kill. (0-25)
+//gts teamKillPunishCount "3" // Kick constant Team killers out of your server.
+
+gts scoreHeroPowerGainFactor "0.679" //Score earned towards Hero Weapons and Abilities are multiplied by this factor in Demolition
+gts scoreHeroPowerTimeFactor "0.679"
+
+gts gameAdvertisementRuleRound "3"
+gts gameAdvertisementRuleTimeLeft "1"
\ No newline at end of file
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_dm.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_dm.cfg
new file mode 100644
index 00000000..f6c8490a
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_dm.cfg
@@ -0,0 +1,51 @@
+//Don't touch the first 2 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "15" // The amount of time before the game starts.
+gts preroundperiod "5" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts spectateType "1" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+gts allowInGameTeamChange "1" // Allow players to switch teams?
+gts allowFinalKillcam "1" // Controls whether the final killcam is played.
+
+gts timelimit "10" // Time limit of the game.
+gts scorelimit "30" // Score limit reach to end the game.
+gts disableTacInsert "1" // Disable Tactical Insertion. 3arc have this set 1 by default to keep players for boosting.
+//gts roundLimit "1" // The number of rounds that will be played before the game ends.
+//gts teamScorePerKill "1" // Points per Kill - The number of points for each kill. (0-25)
+//gts teamScorePerDeath "0" // Points per Death - The number of points your team loses for each death. Points can never be lower than zero. (0-25)
+//gts teamScorePerHeadshot "0" // Headshot Bonus Points - Extra points awarded if the kill is a headshot in addition to the points per kill. (0-25)
+//gts playerNumLives "0" // Number of Lives - The number of times each player can die before they are no longer allowed to respawn. (0-25)
+//gts roundStartExplosiveDelay "2" // Delay explosive weapon use at the start of the round.
+//gts roundStartKillstreakDelay "0" // Delay killstreaks at the start of the round.
+
+//gts loadoutKillstreaksEnabled "1" // Disable Killstreaks by setting this to 0
+//gts perksEnabled "1" // Disable Perks by setting this to 0
+//gts disableVehicleSpawners "0" // This should disable robots from the DLC map Rupture by setting this to 1
+//gts disableweapondrop "0" // No weapons on the ground.
+//gts disallowprone "0" // Don't allow players to lay down.
+
+//Hardcore Mode
+//gts hardcoreMode "1" // Enable hardcore mode.
+//gts friendlyfiretype "1" // Enable or Disable Friendly Fire. 1 on, 2 reflect, 3 shared.
+//gts playerHealthRegenTime "0" // Time it takes you to recover damage.
+//gts playerMaxHealth "30" // Percent of Health players will have on Respawn.
+//gts onlyHeadshots "0" // Headshots only
+//gts allowKillcam "0" // Allow Killcam.
+//gts allowbattlechatter "0" // Shut the fucking player dialogues up.
+//gts teamKillPointLoss "1" // Points per Kill - The number of points for each kill. (0-25)
+//gts teamKillPunishCount "3" // Kick constant Team killers out of your server.
+
+gts useEmblemInsteadOfFactionIcon "1" // Show player's art on scoreboard
+gts voipEveryoneHearsEveryone "1" // Everyone on voice chat hear you.
+
+
+gts gameAdvertisementRuleScorePercent 50
+gts gameAdvertisementRuleTimeLeft 2
+gts teamCount 1
\ No newline at end of file
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_dom.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_dom.cfg
new file mode 100644
index 00000000..ad235cd4
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_dom.cfg
@@ -0,0 +1,55 @@
+//Don't touch the first 2 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "15" // The amount of time before the game starts.
+gts preroundperiod "5" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts allowSpectating "1" // Allow players to spectate other players or CODcasting.
+gts spectateType "1" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+gts allowInGameTeamChange "1" // Allow players to switch teams?
+gts autoTeamBalance "1" // Automatically assign players to teams
+gts allowFinalKillcam "1" // Controls whether the final killcam is played.
+
+gts timelimit "10" // Time limit of the game.
+gts scorelimit "100" // Score limit.
+gts roundScoreLimit "100" // Round score limit reach
+
+gts captureTime "10" // Capture Time. The amount of time it takes to capture an objective.
+gts roundlimit "2" // The number of rounds that will be played before the game ends.
+gts maxObjectiveEventsPerMinute "3"
+gts maxPlayerDefensive "128"
+gts maxPlayerOffensive "128"
+gts maxPlayerEventsPerMinute "3"
+
+gts flagCanBeNeutralized "0"
+
+//gts loadoutKillstreaksEnabled "1" // Disable Killstreaks by setting this to 0
+//gts perksEnabled "1" // Disable Perks by setting this to 0
+//gts disableVehicleSpawners "0" // This should disable robots from the DLC map Rupture by setting this to 1
+//gts disableweapondrop "0" // No weapons on the ground.
+//gts disallowprone "0" // Don't allow players to lay down.
+//gts allowHitMarkers "2" // Rather or not to show hitmakers?
+//gts allowAnnouncer "1" // Annouce enemy team actions
+
+gts scoreHeroPowerGainFactor "0.616" //Score earned towards Hero Weapons and Abilities are multiplied by this factor
+gts scoreHeroPowerTimeFactor "0.616"
+
+//Hardcore Mode
+//gts hardcoreMode "1" // Enable hardcore mode.
+//gts friendlyfiretype "1" // Enable or Disable Friendly Fire. 1 on, 2 reflect, 3 shared.
+//gts playerHealthRegenTime "0" // Time it takes you to recover damage.
+//gts playerMaxHealth "30" // Percent of Health players will have on Respawn.
+//gts onlyHeadshots "0" // Headshots only
+//gts allowKillcam "0" // Allow Killcam.
+//gts allowbattlechatter "0" // Shut the fucking player dialogues up.
+//gts teamKillPointLoss "1" // Points per Kill - The number of points for each kill. (0-25)
+//gts teamKillPunishCount "3" // Kick constant Team killers out of your server.
+
+gts gameAdvertisementRuleScorePercent 10
+gts gameAdvertisementRuleRound 3
\ No newline at end of file
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_escort.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_escort.cfg
new file mode 100644
index 00000000..b98cd20e
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_escort.cfg
@@ -0,0 +1,64 @@
+//Don't touch the first 2 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "15" // The amount of time before the game starts.
+gts preroundperiod "5" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts allowSpectating "1" // Allow players to spectate other players or CODcasting.
+gts spectateType "1" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+gts allowInGameTeamChange "1" // Allow players to switch teams?
+gts autoTeamBalance "1" // Automatically assign players to teams
+gts allowFinalKillcam "1" // Controls whether the final killcam is played.
+
+
+gts timelimit "5" // Time limit of the game.
+gts scorelimit "0" // Score limit.
+gts roundscorelimit "1" // Round score limit reach
+gts roundwinlimit "2"
+gts roundlimit "2" // The number of rounds that will be played before the game ends.
+gts teamCount "2"
+
+gts shutdownDamage "3"
+gts bootTime "5"
+gts rebootTime "15" // How long it takes the robot to reboot after being shut down
+gts rebootPlayers "0"
+gts movePlayers "1"
+gts robotSpeed "1" // Movment speed of the robot
+gts robotShield "0"
+
+//gts teamScorePerDeath "0" // Points per Death - The number of points your team loses for each death. Points can never be lower than zero. (0-25)
+//gts teamScorePerHeadshot "0" // Headshot Bonus Points - Extra points awarded if the kill is a headshot in addition to the points per kill. (0-25)
+//gts playerNumLives "0" // Number of Lives - The number of times each player can die before they are no longer allowed to respawn. (0-25)
+//gts loadoutKillstreaksEnabled "1" // Disable Killstreaks by setting this to 0
+//gts perksEnabled "1" // Disable Perks by setting this to 0
+gts disableVehicleSpawners "1" // This should disable robots from the DLC map Rupture by setting this to 1
+//gts disableweapondrop "0" // No weapons on the ground.
+//gts disallowprone "0" // Don't allow players to lay down.
+//gts allowHitMarkers "2" // Rather or not to show hitmakers?
+//gts allowAnnouncer "1" // Annouce enemy team actions
+
+//Hardcore Mode
+//gts hardcoreMode "1" // Enable hardcore mode.
+//gts friendlyfiretype "1" // Enable or Disable Friendly Fire. 1 on, 2 reflect, 3 shared.
+//gts playerHealthRegenTime "0" // Time it takes you to recover damage.
+//gts playerMaxHealth "30" // Percent of Health players will have on Respawn.
+//gts onlyHeadshots "0" // Headshots only
+//gts allowKillcam "0" // Allow Killcam.
+//gts allowbattlechatter "0" // Shut the fucking player dialogues up.
+//gts teamKillPointLoss "1" // Points per Kill - The number of points for each kill. (0-25)
+//gts teamKillPunishCount "3" // Kick constant Team killers out of your server.
+
+
+gts scoreHeroPowerGainFactor "0.788" // Score earned towards Hero Weapons and Abilities are multiplied by this factor
+gts scoreHeroPowerTimeFactor "0.788"
+
+gts spawntraptriggertime "5"
+
+gts gameAdvertisementRuleTimeLeft "3.5"
+gts gameAdvertisementRuleRound "3"
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_fr.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_fr.cfg
new file mode 100644
index 00000000..db023717
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_fr.cfg
@@ -0,0 +1,33 @@
+//Don't touch the first 2 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "0" // The amount of time before the game starts.
+gts preroundperiod "10" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts allowSpectating "1" // Allow players to spectate other players or CODcasting. (Could be used as screen cheating)
+//gts spectateType "1" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+gts allowInGameTeamChange "0" // Allow players to switch teams?
+gts autoTeamBalance "1" // Automatically assign players to teams
+gts allowFinalKillcam "0" // Controls whether the final killcam is played.
+gts disableCAC "0"
+gts disableClassSelection "1"
+gts loadoutKillstreaksEnabled "0" // Disable Killstreaks by setting this to 0
+//gts perksEnabled "1" // Disable Perks by setting this to 0
+//gts disableVehicleSpawners "0" // This should disable robots from the DLC map Rupture by setting this to 1
+//gts disableweapondrop "0" // No weapons on the ground.
+//gts disallowprone "0" // Don't allow players to lay down.
+gts disableTacInsert "1" // Disable Tactical Insertion.
+
+
+
+gts timelimit "15" // Time limit of the game.
+gts scorelimit "0" // Score limit reach to end the game.
+gts roundswitch "0"
+gts teamCount "1"
+
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_gun.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_gun.cfg
new file mode 100644
index 00000000..17cb9b08
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_gun.cfg
@@ -0,0 +1,38 @@
+//Don't touch the first 3 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+gts wagermatchhud "1"
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+
+gts gunSelection 3 // Ladder. Determines which set of weapons the game uses (0 = Normal. 1 = Close Quarters. 2 = Marksman. 3 = Random.)
+set black_market_gun_game "0" // Toggle 1 if you want Blackjack's GunGame. leave it 0 for regular. (This might conflect with gunselection set)
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod 20 // The amount of time before the game starts. (Give weak potato players a chance to load in and not spawn.)
+gts preroundperiod "10" // The amount of time before a round starts.
+gts disableClassSelection "1" // Disable CAC for GunGame.
+gts allowSpectating "1" // Allow players to spectate other players or CODcasting.
+gts spectateType "1" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+
+gts timelimit "10" // Time limit of the game.
+gts scorelimit "30" // Score limit reach to end the game.
+
+
+gts setbacks 1 // Setbacks. How much weapon progression a player loses when knifed. (1-10)
+gts forceRadar "1" // Enable UAV all the time
+gts loadoutKillstreaksEnabled "0" // Disable Killstreaks for GunGame.
+gts disableVehicleSpawners "1" // This should disable robots from the DLC map Rupture by setting this to 1
+gts disableweapondrop "1" // No weapons on the ground for GunGame.
+gts perksEnabled "0" // Disable Perks on GunGame
+//gts disallowprone "0" // Don't allow players to lay down.
+//gts allowHitMarkers "2" // Rather or not to show hitmakers?
+gts playerNumLives "0" // Number of Lives - The number of times each player can die before they are no longer allowed to respawn. (0-25)
+//gts playerMaxHealth "100" // Percent of Health players will have on Respawn.
+//gts onlyHeadshots "0" // Headshots only
+
+gts useEmblemInsteadOfFactionIcon "1" // Show player's art on scoreboard
+gts voipEveryoneHearsEveryone "1" // Everyone on voice chat hear you.
+teamCount 1
\ No newline at end of file
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_infect.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_infect.cfg
new file mode 100644
index 00000000..0eecd2df
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_infect.cfg
@@ -0,0 +1,32 @@
+//Don't touch the first 2 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "15" // The amount of time before the game starts.
+gts preroundperiod "10" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts allowSpectating "1" // Allow players to spectate other players or CODcasting. (Could be used as screen cheating)
+gts allowInGameTeamChange "1" // Allow players to switch teams?
+gts autoTeamBalance "1" // Automatically assign players to teams
+gts allowFinalKillcam "1" // Controls whether the final killcam is played.
+
+gts timelimit "2" // Time limit of the game.
+gts scorelimit "0" // Score limit reach to end the game.
+gts teamCount "2"
+
+gts loadoutKillstreaksEnabled "0" // Disable Killstreaks by setting this to 0.
+gts disableVehicleSpawners "1" // This should disable robots from the DLC map Rupture by setting this to 1.
+//gts disallowprone "0" // Don't allow players to lay down.
+//gts disableTacInsert "1" // Disable Tactical Insertion. Now that would be a dick move for the infected players.
+//gts allowHitMarkers "2" // Rather or not to show hitmakers?
+//gts allowAnnouncer "1" // Annouce enemy team actions
+
+gts gameAdvertisementRuleScorePercent "15"
+gts gameAdvertisementRuleTimeLeft "2"
+gts gameAdvertisementRuleRound "0"
+gts gameAdvertisementRuleRoundsWon "0"
\ No newline at end of file
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_koth.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_koth.cfg
new file mode 100644
index 00000000..01d258b8
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_koth.cfg
@@ -0,0 +1,55 @@
+//Don't touch the first 3 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+gts kothMode "1"
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "15" // The amount of time before the game starts.
+gts preroundperiod "5" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts allowSpectating "1" // Allow players to spectate other players or CODcasting.
+gts spectateType "1" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+gts allowInGameTeamChange "1" // Allow players to switch teams?
+gts autoTeamBalance "1" // Automatically assign players to teams
+gts allowFinalKillcam "1" // Controls whether the final killcam is played.
+
+gts timelimit "5" // Time limit of the game.
+gts scorelimit "250" // Score limit reach to end the game.
+gts teamCount "2"
+
+//gts loadoutKillstreaksEnabled "1" // Disable Killstreaks by setting this to 0
+//gts perksEnabled "1" // Disable Perks by setting this to 0
+//gts disableVehicleSpawners "0" // This should disable robots from the DLC map Rupture by setting this to 1
+//gts disableweapondrop "0" // No weapons on the ground.
+//gts disallowprone "0" // Don't allow players to lay down.
+
+gts maxPlayerEventsPerMinute "8"
+
+gts autoDestroyTime "60" // Lifetime. The amount of time hardpoint is active.
+gts captureTime "0" // Capture Time. The amount of time it takes to capture hardpoint.
+gts objectiveSpawnTime "0" // Activation Delay Time. The amount of time before the next objective becomes active.
+gts randomObjectiveLocations "0" // Hardpoint Locations. The order in which the hardpoint will appear. (0 = Liner 2 = Random After First)
+gts scorePerPlayer "0" // Scoring. Determines if the team gets score at a constant rate or if more points are awarded when more players occupy the hardpoint.
+gts timePausesWhenInZone "1" // timelimit pauses when you capture the hardpoint.
+
+
+//Hardcore Mode
+//gts hardcoreMode "1" // Enable hardcore mode.
+//gts friendlyfiretype "1" // Enable or Disable Friendly Fire. 1 on, 2 reflect, 3 shared.
+//gts playerHealthRegenTime "0" // Time it takes you to recover damage.
+//gts playerMaxHealth "30" // Percent of Health players will have on Respawn.
+//gts onlyHeadshots "0" // Headshots only
+//gts allowKillcam "0" // Allow Killcam.
+//gts allowbattlechatter "0" // Shut the fucking player dialogues up.
+//gts teamKillPointLoss "1" // Points per Kill - The number of points for each kill. (0-25)
+//gts teamKillPunishCount "3" // Kick constant Team killers out of your server.
+
+gts scoreHeroPowerGainFactor "0.45" //Score earned towards Hero Weapons and Abilities are multiplied by this factor in Hardpoint
+gts scoreHeroPowerTimeFactor "0.45"
+
+gts gameAdvertisementRuleScorePercent "20"
+gts gameAdvertisementRuleTimeLeft "1.5"
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_prop.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_prop.cfg
new file mode 100644
index 00000000..6af4a209
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_prop.cfg
@@ -0,0 +1,47 @@
+//Don't touch the first 2 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+
+////////////////////////////////////////////////////////////////
+// Please note that only these maps support Prop Hunt //
+// Make sure to change your sv_maprotation to only them! //
+////////////////////////////////////////////////////////////////
+// //
+// Aquarium - mp_biodome //
+// Combine - mp_sector //
+// Evac - mp_apartments //
+// Exodus - mp_chinatown //
+// Fringe - mp_veiled //
+// Hunted - mp_ethiopia //
+// Infection - mp_infection //
+// Redwood - mp_redwood //
+// Spire - mp_aerospace //
+// //
+////////////////////////////////////////////////////////////////
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "15" // The amount of time before the game starts.
+gts preroundperiod "10" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts allowFinalKillcam "1" // Controls whether the final killcam is played.
+gts spectateType "3" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+gts disableClassSelection "1" // Disable CAC for prop hunt.
+gts allowInGameTeamChange "0" // Keep it 0
+
+gts timelimit "4" // Time limit of the game.
+gts scorelimit "0" // Score limit reach to end the game.
+gts teamCount "2"
+gts roundLimit "4" // The number of rounds that will be played before the game ends.
+gts roundwinlimit "3"
+gts roundSwitch "1"
+gts playerNumLives "1" // Number of Lives - Keep it 1!
+
+gts disableVehicleSpawners "1" // This should disable robots from the DLC map Rupture by setting this to 1 - keep it 1!
+
+gts voipDeadChatWithDead "1"
+gts voipDeadChatWithTeam "0"
+gts voipDeadHearTeamLiving "0"
\ No newline at end of file
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_sas.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_sas.cfg
new file mode 100644
index 00000000..0f28a6bc
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_sas.cfg
@@ -0,0 +1,48 @@
+//Don't touch the first 3 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+gts wagermatchhud "1"
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts gunSelection "1" // Setback Weapon. The weapon that will set players back in points. (0 = None 1 = Combat Axe 2 = Crossbow 3 = Ballistic Knife)
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod 20 // The amount of time before the game starts. (Give weak potato players a chance to load in and not spawn.)
+gts preroundperiod "10" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts allowInGameTeamChange "0" // Allow team change..not sure why this is on SAS
+gts disableClassSelection "1" // Disable CAC for GunGame.
+gts allowSpectating "1" // Allow players to spectate other players or CODcasting.
+gts spectateType "1" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+
+gts timelimit "5" // Time limit of the game.
+gts scorelimit "0" // Score limit reach to end the game.
+gts roundlimit "1"
+
+
+gts forceRadar "1" // Enable UAV all the time
+gts timecount "1"
+gts loadoutKillstreaksEnabled "0" // Disable Killstreaks for SAS.
+gts disableVehicleSpawners "1" // This should disable robots from the DLC map Rupture by setting this to 1
+gts disableweapondrop "1" // No weapons on the ground for SAS.
+gts perksEnabled "0" // Disable Perks on SAS
+//gts disallowprone "0" // Don't allow players to lay down.
+gts playerNumLives "0" // Number of Lives - The number of times each player can die before they are no longer allowed to respawn. (0-25)
+//gts playerMaxHealth "100" // Percent of Health players will have on Respawn.
+//gts onlyHeadshots "0" // Headshots only
+
+gts useEmblemInsteadOfFactionIcon "1" // Show player's art on scoreboard
+gts voipEveryoneHearsEveryone "1" // Everyone on voice chat hear you.
+
+
+gts pointsPerPrimaryKill "10"
+gts pointsPerSecondaryKill "10"
+gts pointsPerPrimaryGrenadeKill "5"
+gts pointsPerMeleeKill "5"
+gts roundStartExplosiveDelay "0"
+
+gts gameAdvertisementRuleScorePercent "35"
+gts gameAdvertisementRuleTimeLeft "1.5"
+teamCount 1
\ No newline at end of file
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_sd.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_sd.cfg
new file mode 100644
index 00000000..f2901ed3
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_sd.cfg
@@ -0,0 +1,62 @@
+//Don't touch the first 2 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "15" // The amount of time before the game starts.
+gts preroundperiod "3" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts allowSpectating "1" // Allow players to spectate other players or CODcasting. (Could be used as screen cheating)
+gts allowInGameTeamChange "1" // Allow players to switch teams?
+gts autoTeamBalance "1" // Automatically assign players to teams
+gts allowFinalKillcam "1" // Controls whether the final killcam is played.
+gts spectateType "3" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+
+gts timelimit "2 // Time limit of the game.
+gts scorelimit "4" // Score limit reach to end the game.
+
+gts bombTimer 45 // Bomb Timer. The amount of time before the bomb detonates.
+gts plantTime 5 // Plant Time. The amount of time it takes to plant the bomb.
+gts defuseTime 5 // Defuse Time. The amount of time it takes to defuse the bomb.
+gts multiBomb 0 // Multi Bomb. Every attacking player gets a bomb.
+gts roundswitch 1 // The number of rounds to play before teams switch sides.
+gts roundlimit 0
+//gts silentPlant 0 // Players can hear the bomb being planted.
+
+//gts loadoutKillstreaksEnabled "1" // Disable Killstreaks by setting this to 0
+//gts perksEnabled "1" // Disable Perks by setting this to 0
+gts disableVehicleSpawners "1" // This should disable robots from the DLC map Rupture by setting this to 1
+//gts disableweapondrop "0" // No weapons on the ground.
+//gts disallowprone "0" // Don't allow players to lay down.
+//gts allowHitMarkers "2" // Rather or not to show hitmakers?
+//gts allowAnnouncer "1" // Annouce enemy team actions
+
+gts playerLives "1"
+gts playerNumLives "1" // Correct gts to configure amount of respawns
+gts playerKillsMax "6"
+gts totalKillsMax "11"
+gts teamKillScore "4"
+
+gts voipDeadChatWithDead "1"
+gts voipDeadChatWithTeam "0"
+gts voipDeadHearTeamLiving "0"
+
+gts scoreHeroPowerGainFactor "0.8"
+gts scoreHeroPowerTimeFactor "0.3"
+
+//Hardcore Mode
+//gts hardcoreMode "1" // Enable hardcore mode.
+//gts friendlyfiretype "1" // Enable or Disable Friendly Fire. 1 on, 2 reflect, 3 shared.
+//gts playerHealthRegenTime "0" // Time it takes you to recover damage.
+//gts playerMaxHealth "30" // Percent of Health players will have on Respawn.
+//gts onlyHeadshots "0" // Headshots only
+//gts allowKillcam "0" // Allow Killcam.
+//gts allowbattlechatter "0" // Shut the fucking player dialogues up.
+//gts teamKillPointLoss "1" // Points per Kill - The number of points for each kill. (0-25)
+//gts teamKillPunishCount "3" // Kick constant Team killers out of your server.
+
+gts gameAdvertisementRuleRoundsWon 3
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_sniperonly.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_sniperonly.cfg
new file mode 100644
index 00000000..0411f98c
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_sniperonly.cfg
@@ -0,0 +1,229 @@
+//Don't touch the first 2 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "15" // The amount of time before the game starts.
+gts preroundperiod "5" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts allowSpectating "1" // Allow players to spectate other players or CODcasting
+gts spectateType "1" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+gts allowInGameTeamChange "1" // Allow players to switch teams?
+gts autoTeamBalance "1" // Automatically assign players to teams
+gts allowFinalKillcam "1" // Controls whether the final killcam is played.
+
+gts timelimit "10" // Time limit of the game.
+gts scorelimit "75" // Score limit reach to end the game.
+gts teamCount "2"
+
+//gts teamScorePerDeath "0" // Points per Death - The number of points your team loses for each death. Points can never be lower than zero. (0-25)
+//gts teamScorePerHeadshot "0" // Headshot Bonus Points - Extra points awarded if the kill is a headshot in addition to the points per kill. (0-25)
+gts playerNumLives "0" // Number of Lives - The number of times each player can die before they are no longer allowed to respawn. (0-25)
+gts loadoutKillstreaksEnabled "0" // Disable Killstreaks by setting this to 0
+//gts perksEnabled "1" // Disable Perks by setting this to 0
+gts disableVehicleSpawners "1" // This should disable robots from the DLC map Rupture by setting this to 1
+//gts disableweapondrop "0" // No weapons on the ground.
+//gts disallowprone "0" // Don't allow players to lay down.
+//gts allowHitMarkers "2" // Rather or not to show hitmakers?
+//gts allowAnnouncer "1" // Annouce enemy team actions
+
+
+//Hardcore Mode
+//gts hardcoreMode "1" // Enable hardcore mode.
+//gts friendlyfiretype "1" // Enable or Disable Friendly Fire. 1 on, 2 reflect, 3 shared.
+//gts playerHealthRegenTime "0" // Time it takes you to recover damage.
+//gts playerMaxHealth "30" // Percent of Health players will have on Respawn.
+//gts onlyHeadshots "0" // Headshots only
+//gts allowKillcam "0" // Allow Killcam.
+//gts allowbattlechatter "0" // Shut the fucking player dialogues up.
+//gts teamKillPointLoss "1" // Points per Kill - The number of points for each kill. (0-25)
+//gts teamKillPunishCount "3" // Kick constant Team killers out of your server.
+
+gts gameAdvertisementRuleScorePercent "15"
+gts gameAdvertisementRuleTimeLeft "2"
+gts gameAdvertisementRuleRound "0"
+gts gameAdvertisementRuleRoundsWon "0"
+
+//Unsure about this. Maybe someone figure out what restricted items of each weapon is..Would be useful for other game modes..
+//Please PR on Github if you have a list!
+
+// SNIPER ONLY
+
+// Unknown items restrictions
+gts restrictedItems 0 1
+gts restrictedItems 4 1
+gts restrictedItems 5 1
+gts restrictedItems 6 1
+gts restrictedItems 9 1
+gts restrictedItems 49 1
+gts restrictedItems 55 1
+gts restrictedItems 60 1
+gts restrictedItems 69 1
+gts restrictedItems 73 1
+gts restrictedItems 79 1
+gts restrictedItems 93 1
+gts restrictedItems 100 1
+gts restrictedItems 101 1
+gts restrictedItems 102 1
+gts restrictedItems 104 1
+gts restrictedItems 106 1
+gts restrictedItems 107 1
+gts restrictedItems 131 1
+gts restrictedItems 132 1
+gts restrictedItems 133 1
+gts restrictedItems 134 1
+gts restrictedItems 135 1
+gts restrictedItems 136 1
+gts restrictedItems 137 1
+gts restrictedItems 138 1
+gts restrictedItems 139 1
+gts restrictedItems 140 1
+gts restrictedItems 141 1
+gts restrictedItems 142 1
+gts restrictedItems 143 1
+gts restrictedItems 144 1
+gts restrictedItems 145 1
+gts restrictedItems 146 1
+
+// Submachine guns restrictions
+gts restrictedItems 10 1 // kuda
+gts restrictedItems 11 1 // pharo
+gts restrictedItems 12 1 // vesper
+gts restrictedItems 13 1 // razorback
+gts restrictedItems 14 1 // vmp
+gts restrictedItems 15 1 // weevil
+gts restrictedItems 16 1 // AK-74u
+gts restrictedItems 17 1 // HG40
+gts restrictedItems 18 1 // HLX4
+gts restrictedItems 19 1 // nail gun
+gts restrictedItems 34 1 // xmc
+gts restrictedItems 38 1 // ppsh
+gts restrictedItems 110 1 // sten
+
+// Assault rifles restrictions
+gts restrictedItems 7 1 // Peacekeeper MK2
+gts restrictedItems 20 1 // kn-44
+gts restrictedItems 21 1 // icr-1
+gts restrictedItems 22 1 // hvk-30
+gts restrictedItems 23 1 // man-o-war
+gts restrictedItems 24 1 // xr-2
+gts restrictedItems 25 1 // M8A7
+gts restrictedItems 26 1 // sheiva
+gts restrictedItems 27 1 // kvk99m
+gts restrictedItems 28 1 // MX Garand
+gts restrictedItems 29 1 // FFAR
+gts restrictedItems 37 1 // M16
+gts restrictedItems 36 1 // LV8 Basilisk
+gts restrictedItems 126 1 // Galil
+gts restrictedItems 129 1 // M14
+
+// Machine guns restrictions
+gts restrictedItems 30 1 // Dingo
+gts restrictedItems 31 1 // Dredge
+gts restrictedItems 32 1 // BRM
+gts restrictedItems 33 1 // Gorgon
+gts restrictedItems 35 1 // R70-Ajax
+gts restrictedItems 128 1 // RPK
+
+// Shotguns restrictions
+gts restrictedItems 44 1 // Olympia
+gts restrictedItems 50 1 // Haymaker
+gts restrictedItems 51 1 // Argus
+gts restrictedItems 52 1 // KRM-262
+gts restrictedItems 53 1 // Brecci
+gts restrictedItems 56 1 // Banshii
+
+
+// Melee weapons restrictions
+gts restrictedItems 67 1 // fury's song
+gts restrictedItems 68 1 // Skull splitter
+gts restrictedItems 77 1 // Baseball bat
+gts restrictedItems 83 1 // Carver
+gts restrictedItems 84 1 // Malice
+gts restrictedItems 85 1 // Iron jim
+gts restrictedItems 94 1 // Slash N' Burn
+gts restrictedItems 95 1 // Brass knuckles
+gts restrictedItems 96 1 // Butterfly knife
+gts restrictedItems 97 1 // Wrench
+gts restrictedItems 99 1 // Combat nife
+gts restrictedItems 103 1 // Nightbreaker
+gts restrictedItems 105 1 // Buzzcut
+gts restrictedItems 108 1 // Enforcer
+gts restrictedItems 109 1 // Nunchucks
+gts restrictedItems 120 1 // Prizefighters
+gts restrictedItems 121 1 // Katana
+gts restrictedItems 122 1 // Ace of spades
+gts restrictedItems 124 1 // L3FT.E
+gts restrictedItems 125 1 // Bushwhacker
+gts restrictedItems 147 1 // Raven's eye
+
+
+// Special weapons restrictions
+gts restrictedItems 54 1 // NX-Shadowclaw
+gts restrictedItems 127 1 // Ballistic knife
+gts restrictedItems 123 1 // D13-Sector
+
+
+// Launchers restrictions
+gts restrictedItems 39 1 // Max-GL
+gts restrictedItems 57 1 // L4-Siege
+gts restrictedItems 58 1 // XM53
+gts restrictedItems 59 1 // Blackcell
+
+
+// Pistols restrictions
+gts restrictedItems 1 1 // MR6
+gts restrictedItems 2 1 // RK5
+gts restrictedItems 3 1 // L-CAR 9
+gts restrictedItems 8 1 // Marshall 16
+gts restrictedItems 47 1 // Rift-E9
+gts restrictedItems 48 1 // 1911
+
+
+// Lethal specialists restrictions
+gts restrictedItems 111 1 // Scythe
+gts restrictedItems 112 1 // Tempest
+gts restrictedItems 113 1 // Gravity spikes
+gts restrictedItems 114 1 // Ripper
+gts restrictedItems 115 1 // Annihilator
+gts restrictedItems 116 1 // War machine
+gts restrictedItems 117 1 // Sparrow
+gts restrictedItems 118 1 // HIVE
+gts restrictedItems 119 1 // Purifier
+
+
+// Lethal grenades restrictions
+gts restrictedItems 61 1 // frag
+gts restrictedItems 62 1 // combat axe
+gts restrictedItems 63 1 // semtex
+gts restrictedItems 64 1 // c4
+gts restrictedItems 65 1 // trip mine
+gts restrictedItems 66 1 // thermite
+
+
+// Tactical grenades restrictions
+gts restrictedItems 70 1 // smoke screen
+gts restrictedItems 71 1 // concussion
+gts restrictedItems 72 1 // emp
+gts restrictedItems 74 1 // flash bang
+gts restrictedItems 75 1 // shock charge
+gts restrictedItems 76 1 // black hat
+gts restrictedItems 78 1 // trophy system
+
+
+// Sniper scope restrictions
+gts restrictedattachments 32 weaponindex 40 1 // Locus
+gts restrictedattachments 32 weaponindex 41 1 // Drakon
+gts restrictedattachments 32 weaponindex 42 1 // SVG-100
+gts restrictedattachments 32 weaponindex 43 1 // P0-6
+gts restrictedattachments 32 weaponindex 45 1 // Interdiction-RSA
+gts restrictedattachments 22 weaponindex 46 1 // DBSR -> 22 unknown scope id
+gts restrictedattachments 32 weaponindex 46 1 // DBSR no elo sight
+gts restrictedattachments 33 weaponindex 46 1 // DBSR -> 33 unknown scope id
+gts restrictedattachments 32 weaponindex 98 1 // XPR-50
+gts restrictedattachments 32 weaponindex 130 1 // Dragoon
diff --git a/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_tdm.cfg b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_tdm.cfg
new file mode 100644
index 00000000..5da80d2f
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/mp/gamesettings_tdm.cfg
@@ -0,0 +1,50 @@
+//Don't touch the first 2 lines below here.
+exec "gamedata/gamesettings/mp/gamesettings_default.cfg"
+exec "gamedata/configs/common/default_xboxlive.cfg"
+
+
+// Below this line you may uncomment the " // " commands and edit to your liking.
+// If you unsure the default command. you can always " // " them back for later custom gameplay.
+
+gts prematchrequirement "0" // (0-10) Number of players on each team or the total number of players before the pre-match countdown will start.
+gts prematchrequirementtime "0" // (0-60) The amount of time before the match will start.
+gts prematchperiod "15" // The amount of time before the game starts.
+gts preroundperiod "5" // The amount of time before a round starts.
+gts inactivityKick "120" // Kick players that's AFK
+gts allowSpectating "1" // Allow players to spectate other players or CODcasting.
+gts spectateType "1" // 0 disabled, 1 team only, 2 freelook, 3 team only spectate splitscreen players only
+gts allowInGameTeamChange "1" // Allow players to switch teams?
+gts autoTeamBalance "1" // Automatically assign players to teams
+gts allowFinalKillcam "1" // Controls whether the final killcam is played.
+
+gts timelimit "10" // Time limit of the game.
+gts scorelimit "100" // Score limit reach to end the game.
+gts teamCount "2"
+gts roundLimit "1" // The number of rounds that will be played before the game ends.
+
+//gts teamScorePerDeath "0" // Points per Death - The number of points your team loses for each death. Points can never be lower than zero. (0-25)
+//gts teamScorePerHeadshot "0" // Headshot Bonus Points - Extra points awarded if the kill is a headshot in addition to the points per kill. (0-25)
+//gts playerNumLives "0" // Number of Lives - The number of times each player can die before they are no longer allowed to respawn. (0-25)
+//gts loadoutKillstreaksEnabled "1" // Disable Killstreaks by setting this to 0
+//gts perksEnabled "1" // Disable Perks by setting this to 0
+//gts disableVehicleSpawners "0" // This should disable robots from the DLC map Rupture by setting this to 1
+//gts disableweapondrop "0" // No weapons on the ground.
+//gts disallowprone "0" // Don't allow players to lay down.
+//gts allowHitMarkers "2" // Rather or not to show hitmakers?
+//gts allowAnnouncer "1" // Annouce enemy team actions
+
+//Hardcore Mode
+//gts hardcoreMode "1" // Enable hardcore mode.
+//gts friendlyfiretype "1" // Enable or Disable Friendly Fire. 1 on, 2 reflect, 3 shared.
+//gts playerHealthRegenTime "0" // Time it takes you to recover damage.
+//gts playerMaxHealth "30" // Percent of Health players will have on Respawn.
+//gts onlyHeadshots "0" // Headshots only
+//gts allowKillcam "0" // Allow Killcam.
+//gts allowbattlechatter "0" // Shut the fucking player dialogues up.
+//gts teamKillPointLoss "1" // Points per Kill - The number of points for each kill. (0-25)
+//gts teamKillPunishCount "3" // Kick constant Team killers out of your server.
+
+gts gameAdvertisementRuleScorePercent "15"
+gts gameAdvertisementRuleTimeLeft "2"
+gts gameAdvertisementRuleRound "0"
+gts gameAdvertisementRuleRoundsWon "0"
\ No newline at end of file
diff --git a/installer/game/base_game_dir/t7x/gamesettings/zm/gamesettings_default.cfg b/installer/game/base_game_dir/t7x/gamesettings/zm/gamesettings_default.cfg
new file mode 100644
index 00000000..40a92ded
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/zm/gamesettings_default.cfg
@@ -0,0 +1,104 @@
+
+gametype_setting allowAnnouncer 1
+gametype_setting allowBattleChatter 1
+gametype_setting allowFinalKillcam 1
+gametype_setting allowHitMarkers 2
+gametype_setting allowInGameTeamChange 0
+gametype_setting allowKillcam 1
+gametype_setting allowSpectating 0
+gametype_setting autoDestroyTime 0
+gametype_setting autoTeamBalance 0
+gametype_setting bombTimer 0
+gametype_setting bulletDamageScalar 1.0
+gametype_setting captureTime 10
+gametype_setting crateCaptureTime 3
+gametype_setting cumulativeRoundScores 0
+gametype_setting deathPointLoss 0
+gametype_setting defuseTime 0
+gametype_setting delayPlayer 0
+gametype_setting destroyTime 0
+gametype_setting disableAmbientFx 0
+gametype_setting disableAttachments 0
+gametype_setting disableCAC 1
+gametype_setting disableContracts 0
+gametype_setting disableTacInsert 0
+gametype_setting disableweapondrop 1
+gametype_setting disallowaimslowdown 0
+gametype_setting disallowprone 0
+gametype_setting enemyCarrierVisible 0
+gametype_setting extraTime 0
+gametype_setting flagCaptureGracePeriod 0
+gametype_setting flagDecayTime 0
+gametype_setting flagRespawnTime 0
+gametype_setting forceRadar 0
+gametype_setting friendlyfiretype 0
+gametype_setting hardcoremode 0
+gametype_setting hotPotato 0
+gametype_setting idleFlagDecay 0
+gametype_setting idleFlagResetTime 0
+gametype_setting inactivityKick 0
+gametype_setting kothMode 0
+gametype_setting leaderBonus 0
+gametype_setting loadoutKillstreaksEnabled 1
+gametype_setting maxObjectiveEventsPerMinute 0
+gametype_setting maxPlayerDefensive 0
+gametype_setting maxPlayerEventsPerMinute 0
+gametype_setting maxPlayerOffensive 0
+gametype_setting multiBomb 0
+gametype_setting objectiveSpawnTime 0
+gametype_setting onlyHeadshots 0
+gametype_setting perksEnabled 0
+gametype_setting plantTime 0
+gametype_setting playerForceRespawn 1
+gametype_setting playerHealthRegenTime 5
+gametype_setting playerKillsMax 0
+gametype_setting playerMaxHealth 100
+gametype_setting playerNumlives 0
+gametype_setting playerObjectiveHeldRespawnDelay 0
+gametype_setting playerQueuedRespawn 0
+gametype_setting playerRespawnDelay 0
+gametype_setting playerSprintTime 4
+gametype_setting pregameAlwaysShowCACEdit 1
+gametype_setting pregameAlwaysShowStreakEdit 1
+gametype_setting pregameCACModifyTime 0
+gametype_setting pregameDraftEnabled 0
+gametype_setting pregameDraftRoundTime 0
+gametype_setting pregameItemMaxVotes 0
+gametype_setting pregameItemVoteEnabled 0
+gametype_setting pregameItemVoteRoundTime 0
+gametype_setting pregamePositionShuffleMethod 0
+gametype_setting pregamePositionSortType 0
+gametype_setting pregamePostRoundTime 0
+gametype_setting pregamePostStageTime 0
+gametype_setting pregamePreStageTime 0
+gametype_setting pregameScorestreakModifyTime 0
+gametype_setting randomObjectiveLocations 0
+gametype_setting roundlimit 1
+gametype_setting roundStartExplosiveDelay 5
+gametype_setting roundStartKillstreakDelay 0
+gametype_setting roundswitch 1 // rounds between switching teams
+gametype_setting roundwinlimit 0
+gametype_setting scoreHeroPowerGainFactor 1.0
+gametype_setting scoreHeroPowerTimeFactor 1.0
+gametype_setting scorelimit 100
+gametype_setting spectateType 1
+gametype_setting teamCount 1
+gametype_setting teamKillPenalty 2
+gametype_setting teamKillPointLoss 0
+gametype_setting teamKillPunishCount 3
+gametype_setting teamKillReducedPenalty 0.25
+gametype_setting teamKillScore 4
+gametype_setting teamKillSpawnDelay 20
+gametype_setting timelimit 10
+gametype_setting totalKillsMax 0
+gametype_setting vehiclesEnabled 1
+gametype_setting vehiclesTimed 1
+gametype_setting voipDeadChatWithDead 0
+gametype_setting voipDeadChatWithTeam 1
+gametype_setting voipDeadHearAllLiving 0
+gametype_setting voipDeadHearKiller 0
+gametype_setting voipDeadHearTeamLiving 1
+gametype_setting voipEveryoneHearsEveryone 0
+gametype_setting voipKillersHearVictim 1
+gametype_setting waverespawndelay 0
+gametype_setting zmDifficulty 1
diff --git a/installer/game/base_game_dir/t7x/gamesettings/zm/gamesettings_zclassic.cfg b/installer/game/base_game_dir/t7x/gamesettings/zm/gamesettings_zclassic.cfg
new file mode 100644
index 00000000..8b3d86de
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/gamesettings/zm/gamesettings_zclassic.cfg
@@ -0,0 +1,12 @@
+gametype_setting scorelimit 7500
+gametype_setting timelimit 10
+gametype_setting roundlimit 1
+gametype_setting playerNumlives 0
+gametype_setting playerrespawndelay 0
+gametype_setting waverespawndelay 0
+gametype_setting disableweapondrop 1
+gametype_setting allowAnnouncer 0
+gametype_setting startRound 1
+gametype_setting magic 1
+gametype_setting headshotsonly 0
+gametype_setting allowdogs 1
diff --git a/installer/game/base_game_dir/t7x/lobby_scripts/server_lobby_selector/__init__.lua b/installer/game/base_game_dir/t7x/lobby_scripts/server_lobby_selector/__init__.lua
new file mode 100644
index 00000000..f0cf3540
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/lobby_scripts/server_lobby_selector/__init__.lua
@@ -0,0 +1,71 @@
+Lobby.Process.CreateDedicatedModsLobby = function (controller, toTarget)
+ local lobby_mode = Engine.DvarString( nil, "sv_lobby_mode" )
+ if lobby_mode ~= "" then
+ if lobby_mode == "zm" then
+ toTarget = LobbyData.UITargets.UI_ZMLOBBYONLINECUSTOMGAME
+ elseif lobby_mode == "cp" then
+ toTarget = LobbyData.UITargets.UI_CPLOBBYONLINECUSTOMGAME
+ elseif lobby_mode == "cpzm" then
+ toTarget = LobbyData.UITargets.UI_CP2LOBBYONLINECUSTOMGAME
+ elseif lobby_mode == "fr" then
+ toTarget = LobbyData.UITargets.UI_FRLOBBYONLINEGAME
+ toTarget.maxClients = Engine.DvarInt( nil, "com_maxclients" )
+ elseif lobby_mode == "doa" then
+ toTarget = LobbyData.UITargets.UI_DOALOBBYONLINE
+ elseif lobby_mode == "mp" then
+ toTarget = LobbyData.UITargets.UI_MPLOBBYONLINEMODGAME
+ elseif lobby_mode == "arena" then
+ toTarget = LobbyData.UITargets.UI_MPLOBBYONLINEARENAGAME
+ end
+ end
+ local playlistID = Dvar.sv_playlist
+ Engine.SetPlaylistID(playlistID:get())
+ local lobbyInit = Lobby.Actions.ExecuteScript(function ()
+ Lobby.ProcessNavigate.SetupLobbyMapAndGameType(controller, toTarget)
+ end)
+ local setNetworkMode = Lobby.Actions.SetNetworkMode(controller, Enum.LobbyNetworkMode.LOBBY_NETWORKMODE_LIVE)
+ local lobbySettings = Lobby.Actions.LobbySettings(controller, toTarget)
+ local updateUI = Lobby.Actions.UpdateUI(controller, toTarget)
+ local createGameHost = Lobby.Actions.LobbyHostStart(controller, toTarget.mainMode, toTarget.lobbyType, toTarget.lobbyMode, toTarget.maxClients)
+ local lobbyAdvertise = Lobby.Actions.AdvertiseLobby(true)
+ local hostingEvent = Lobby.Actions.ExecuteScript(function ()
+ Engine.QoSProbeListenerEnable(toTarget.lobbyType, true)
+ Engine.SetDvar("live_dedicatedReady", 1)
+ Engine.RunPlaylistRules(controller)
+ Engine.RunPlaylistSettings(controller)
+ Lobby.Timer.HostingLobby({controller = controller, lobbyType = toTarget.lobbyType, mainMode = toTarget.mainMode, lobbyTimerType = toTarget.lobbyTimerType})
+ if Engine.DvarInt( nil, "sv_skip_lobby" ) == 1 then
+ -- Engine.ComError( Enum.errorCode.ERROR_SCRIPT, "Using sv_skip_lobby" )
+ local map_rotation_string = Engine.DvarString( nil, "sv_maprotation" )
+ if map_rotation_string ~= "" then
+ local map_rotation_tokens = split_string( map_rotation_string, " " )
+ if map_rotation_tokens[ 1 ] == "gametype" then
+ Engine.Exec(0, "lobby_setgametype " .. map_rotation_tokens[ 2 ] )
+ -- Engine.ComError( Enum.errorCode.ERROR_SCRIPT, "Set gametype to " .. map_rotation_tokens[ 2 ] .. " based on map rotation" )
+ if map_rotation_tokens[ 3 ] == "map" then
+ Engine.Exec(0, "lobby_setmap " .. map_rotation_tokens[ 4 ] )
+ -- Engine.ComError( Enum.errorCode.ERROR_SCRIPT, "Set map to " .. map_rotation_tokens[ 4 ] .. " based on map rotation" )
+ end
+ end
+ end
+ Engine.Exec(0, "launchgame")
+ end
+ end)
+ Lobby.Process.AddActions(setNetworkMode, lobbySettings)
+ Lobby.Process.AddActions(lobbySettings, lobbyInit)
+ Lobby.Process.AddActions(lobbyInit, updateUI)
+ Lobby.Process.AddActions(updateUI, createGameHost)
+ Lobby.Process.AddActions(createGameHost, lobbyAdvertise)
+ Lobby.Process.AddActions(lobbyAdvertise, hostingEvent)
+ Lobby.Process.AddActions(hostingEvent, nil)
+ return {head = setNetworkMode, interrupt = Lobby.Interrupt.NONE, force = true, cancellable = true}
+end
+
+function split_string(str, delimiter)
+ local tokens = {}
+ local pattern = string.format("([^%s]+)", delimiter)
+ for token in string.gmatch(str, pattern) do
+ table.insert(tokens, token)
+ end
+ return tokens
+ end
\ No newline at end of file
diff --git a/installer/game/base_game_dir/t7x/players/properties.json b/installer/game/base_game_dir/t7x/players/properties.json
new file mode 100644
index 00000000..b158581d
--- /dev/null
+++ b/installer/game/base_game_dir/t7x/players/properties.json
@@ -0,0 +1 @@
+{"playerName":"Unknown Soldier"}
\ No newline at end of file
diff --git a/installer/game/base_game_dir/zone/server.cfg b/installer/game/base_game_dir/zone/server.cfg
new file mode 100644
index 00000000..9ca24fc1
--- /dev/null
+++ b/installer/game/base_game_dir/zone/server.cfg
@@ -0,0 +1,141 @@
+//////////////////////////////////////////////////
+/// T7x Server Configuration //
+//////////////////////////////////////////////////
+
+//////////////////////////////////////////////////
+// SERVER NAME & COLORS TIPS //
+//////////////////////////////////////////////////
+// //
+// ^1 Red //
+// ^2 Green //
+// ^3 Yellow //
+// ^4 Blue //
+// ^5 Cyan //
+// ^6 Pink //
+// ^7 White //
+// ^8 Depends on the team colors playing. //
+// ^9 Orange //
+// ^0 Black //
+// //
+//////////////////////////////////////////////////
+
+set live_steam_server_name "Default T7x Server" // Sets the server hostname.
+set live_steam_server_description "My longest YEA T7x ever" // Sets a server description visible on the serverlist
+
+//////////////////////////////////////////////////
+// NON-GAMEPLAY CONFIGURATION //
+//////////////////////////////////////////////////
+
+set com_maxclients "18" // Max players in your server.
+set rcon_password "" // Access to your server to change stuff remotely or ingame. (Empty = disabled)
+set g_password "" // Password Protected Server. Leave blank if you want players to join or set password if you want to keep public out.
+set sv_privateClients "0" // Maximum number of private clients allowed on the server (range 0-18 (clamped to sv_maxclients) )
+set sv_timeout "30" // Timeout time period. You will timeout after (30) seconds when attempting to connect or if you are getting connection interruptions
+set sv_reconnectlimit "3" // How many times you can try to reconnect
+set sv_pure "0" // verifying cilent files
+set sv_floodProtect "1" // Chat Spam Protection
+set g_log "t7x/games_mp.log" // Gamelog filename. If you edit this, Make sure you change B3.xml if you have bigbrotherbot.
+set sv_lobby_mode "mp" // Sets the lobby type to multiplayer.
+set sv_skip_lobby "1" // Makes the server load the map immediately instead of waiting at the lobby. Turn this off if you want to use playlists instead(currently required for custom maps).
+set sv_lanonly "0" // Keep your server from bordcasting to the public list and Local LAN only.
+
+
+//////////////////////////////////////////////////
+// BOT CONFIGURATION //
+//////////////////////////////////////////////////
+
+set bot_maxallies "0" // Amount of Bots on the Friendly Team
+set bot_maxAxis "0" // Amount of Bots on the Enemy Team
+set bot_maxFree "0" // Bots free-for-all based modes? Untested.
+set bot_difficulty "1" // Bot Skill. (0 - Easy, 1 - Normal, 2 - Hard, 3 - Veteran)
+
+//////////////////////////////////////////////////
+// BASE GAME CONFIGURATION //
+//////////////////////////////////////////////////
+// //
+// dm - Free-for-all //
+// tdm - Team Deathmatch //
+// ball - Uplink //
+// sd - Search and Destroy //
+// sr - Search and Rescue //
+// dom - Domination //
+// dem - Demolition //
+// conf - Kill Confirmed //
+// ctf - Capture the Flag //
+// shrp - Sharpshooter //
+// gun - GunGame //
+// sas - Sticks and Stones //
+// koth - Hardpoint //
+// escort - Safeguard //
+// clean - Fracture //
+// prop - Prop Hunt //
+// infect - Infected //
+// sniperonly - Snipers Only //
+// //
+//////////////////////////////////////////////////
+
+exec "gamedata/gamesettings/mp/gamesettings_tdm.cfg" // Change this to the gametype config of the mode you want to run (e.g. ../gamesettings_conf.cfg, ../gamesettings_escort.cfg)
+//set gametype "tdm" // Set the gametype in the map rotation for now
+
+set scr_teambalance "1" // Enable or Disable auto balance.
+set cg_thirdPerson "0" // third-person mode
+set g_deadChat "0" // Dead Players' Chat Messages can be seen by everyone
+
+/////////////////////////////////////////////////////
+// MAP SHORT NAMES ROTATION LIST //
+/////////////////////////////////////////////////////
+// //
+// * - Maps that support Prop Hunt //
+// //
+///////////Base Maps/////////////////////////////////
+// //
+// Aquarium* - mp_biodome //
+// Breach - mp_spire //
+// Combine* - mp_sector //
+// Evac* - mp_apartments //
+// Exodus* - mp_chinatown //
+// Fringe* - mp_veiled //
+// Havoc - mp_havoc //
+// Hunted* - mp_ethiopia //
+// Infection* - mp_infection //
+// Metro - mp_metro //
+// Redwood* - mp_redwood //
+// Stronghold - mp_stronghold //
+// Nuk3town* - mp_nuketown_x //
+// //
+///////////Awakening DLC/////////////////////////////
+// //
+// Gauntlet - mp_crucible //
+// Rise - mp_rise //
+// Skyjacked - mp_skyjacked //
+// Splash - mp_waterpark //
+// //
+///////////Eclipse DLC///////////////////////////////
+// //
+// Knockout - mp_kung_fu //
+// Rift - mp_conduit //
+// Spire* - mp_aerospace //
+// Verge - mp_banzai //
+// //
+///////////Descent DLC///////////////////////////////
+// //
+// Berserk - mp_shrine //
+// Cryogen - mp_cryogen //
+// Empire - mp_rome //
+// Rumble - mp_arena //
+// //
+///////////Salvation DLC/////////////////////////////
+// //
+// Citadel - mp_ruins //
+// Micro - mp_miniature //
+// Outlaw - mp_western //
+// Rupture - mp_city //
+// //
+///////////Bonus Maps////////////////////////////////
+// //
+// Fringe Night - mp_veiled_heyday //
+// Redwood Snow - mp_redwood_ice //
+// //
+/////////////////////////////////////////////////////
+
+set sv_maprotation "gametype tdm map mp_biodome map mp_spire map mp_sector map mp_apartments map mp_chinatown map mp_veiled map mp_havoc map mp_ethiopia map mp_infection map mp_metro map mp_redwood map mp_stronghold map mp_nuketown_x map mp_shrine map mp_ruins map mp_cryogen map mp_rome map mp_crucible map mp_kung_fu map mp_miniature map mp_western map mp_conduit map mp_rise map mp_arena map mp_city map mp_skyjacked map mp_aerospace map mp_waterpark map mp_banzai map mp_veiled_heyday map mp_redwood_ice"
diff --git a/installer/game/base_game_dir/zone/server_cp.cfg b/installer/game/base_game_dir/zone/server_cp.cfg
new file mode 100644
index 00000000..8ab8c0a5
--- /dev/null
+++ b/installer/game/base_game_dir/zone/server_cp.cfg
@@ -0,0 +1,80 @@
+//////////////////////////////////////////////////
+/// T7x Server Configuration //
+//////////////////////////////////////////////////
+
+//////////////////////////////////////////////////
+// SERVER NAME & COLORS TIPS //
+//////////////////////////////////////////////////
+// //
+// ^1 Red //
+// ^2 Green //
+// ^3 Yellow //
+// ^4 Blue //
+// ^5 Cyan //
+// ^6 Pink //
+// ^7 White //
+// ^8 Depends on the team colors playing. //
+// ^9 Orange //
+// ^0 Black //
+// //
+//////////////////////////////////////////////////
+
+set live_steam_server_name "Default T7x Campaign Server" // Sets the server hostname.
+set live_steam_server_description "My longest YEA T7x CAMPAIGN ever" // Sets a server description visible on the serverlist
+
+//////////////////////////////////////////////////
+// NON-GAMEPLAY CONFIGURATION //
+//////////////////////////////////////////////////
+
+set com_maxclients "4" // Max players in your server.
+set lobby_min_players "1" // Minimum amount of players for the Match to start.
+set rcon_password "" // Access to your server to change stuff remotely or ingame. (Empty = disabled)
+set g_password "" // Password Protected Server. Leave blank if you want players to join or set password if you want to keep public out.
+set sv_privateClients "0" // Maximum number of private clients allowed on the server (range 0-18 (clamped to sv_maxclients) )
+set sv_timeout "30" // Timeout time period. You will timeout after (30) seconds when attempting to connect or if you are getting connection interruptions
+set sv_reconnectlimit "3" // How many times you can try to reconnect
+set sv_pure "0" // verifying cilent files
+set sv_floodProtect "1" // Chat Spam Protection
+set g_log "t7x/games_cp.log" // Gamelog filename. If you edit this, Make sure you change B3.xml if you have bigbrotherbot.
+set sv_lobby_mode "cp" // Sets the lobby type to camapaign
+set sv_skip_lobby "1" // Makes the server load the map immediately instead of waiting at the lobby. Turn this off if you want to use playlists instead(currently required for custom maps).
+set sv_lanonly "0" // Keep your server from bordcasting to the public list and Local LAN only.
+
+//////////////////////////////////////////////////
+// BASE GAME CONFIGURATION //
+//////////////////////////////////////////////////
+
+exec "gamedata/gamesettings/cp/gamesettings_default.cfg" // Leave this as is
+exec "gamedata/configs/common/default_xboxlive.cfg" // Leave this as is
+exec "gamedata/gamesettings/cp/gamesettings_coop.cfg" // Leave this as is
+
+set cg_thirdPerson "0" // third-person mode
+set g_deadChat "0" // Dead Players' Chat Messages can be seen by everyone
+
+//////////////////////////////////////////////////////////////
+// MAP SHORT NAMES ROTATION LIST //
+//////////////////////////////////////////////////////////////
+// //
+///////Safehouses/////////////////////////////////////////////
+// //
+// Mobile - cp_sh_mobile //
+// Singapore - cp_sh_singapore //
+// Cairo - cp_sh_cairo //
+// //
+///////Missions///////////////////////////////////////////////
+// //
+// Black Ops - cp_mi_eth_prologue //
+// New World - cp_mi_zurich_newworld //
+// In Darkness - cp_mi_sing_blackstation //
+// Provocation - cp_mi_sing_biodomes //
+// Hypocenter - cp_mi_sing_sgen //
+// Vengeance - cp_mi_sing_vengeance //
+// Rise & Fall - cp_mi_cairo_ramses //
+// Demon Within - cp_mi_cairo_infection //
+// Sand Castle - cp_mi_cairo_aquifer //
+// Lotus Towers - cp_mi_cairo_lotus //
+// Life - cp_mi_zurich_coalescence //
+// //
+//////////////////////////////////////////////////////////////
+
+set sv_maprotation "gametype coop map cp_mi_eth_prologue"
\ No newline at end of file
diff --git a/installer/game/base_game_dir/zone/server_zm.cfg b/installer/game/base_game_dir/zone/server_zm.cfg
new file mode 100644
index 00000000..bbb6d179
--- /dev/null
+++ b/installer/game/base_game_dir/zone/server_zm.cfg
@@ -0,0 +1,93 @@
+//////////////////////////////////////////////////
+/// T7x Server Configuration //
+//////////////////////////////////////////////////
+
+//////////////////////////////////////////////////
+// SERVER NAME & COLORS TIPS //
+//////////////////////////////////////////////////
+// //
+// ^1 Red //
+// ^2 Green //
+// ^3 Yellow //
+// ^4 Blue //
+// ^5 Cyan //
+// ^6 Pink //
+// ^7 White //
+// ^8 Depends on the team colors playing. //
+// ^9 Orange //
+// ^0 Black //
+// //
+//////////////////////////////////////////////////
+
+set live_steam_server_name "Default T7x Zombies Server" // Sets the server hostname.
+set live_steam_server_description "My longest YEA T7x ZOMBIES ever" // Sets a server description visible on the serverlist
+
+//////////////////////////////////////////////////
+// NON-GAMEPLAY CONFIGURATION //
+//////////////////////////////////////////////////
+
+set com_maxclients "4" // Max players in your server.
+set lobby_min_players "1" // Minimum amount of players for the Match to start.
+set rcon_password "" // Access to your server to change stuff remotely or ingame. (Empty = disabled)
+set g_password "" // Password Protected Server. Leave blank if you want players to join or set password if you want to keep public out.
+set sv_privateClients "0" // Maximum number of private clients allowed on the server (range 0-18 (clamped to sv_maxclients) )
+set sv_timeout "30" // Timeout time period. You will timeout after (30) seconds when attempting to connect or if you are getting connection interruptions
+set sv_reconnectlimit "3" // How many times you can try to reconnect
+set sv_pure "0" // verifying cilent files
+set sv_floodProtect "1" // Chat Spam Protection
+set g_log "t7x/games_zm.log" // Gamelog filename. If you edit this, Make sure you change B3.xml if you have bigbrotherbot.
+set sv_lobby_mode "zm" // Sets the lobby type to zombies
+set sv_skip_lobby "1" // Makes the server load the map immediately instead of waiting at the lobby. Turn this off if you want to use playlists instead(currently required for custom maps).
+set sv_lanonly "0" // Keep your server from bordcasting to the public list and Local LAN only.
+
+//////////////////////////////////////////////////
+// BASE GAME CONFIGURATION //
+//////////////////////////////////////////////////
+
+exec "gamedata/gamesettings/zm/gamesettings_default.cfg" // Leave this as is
+exec "gamedata/configs/common/default_xboxlive.cfg" // Leave this as is
+exec "gamedata/gamesettings/zm/gamesettings_zclassic.cfg" // Leave this as is
+
+set cg_thirdPerson "0" // third-person mode
+set g_deadChat "0" // Dead Players' Chat Messages can be seen by everyone
+set scr_firstGumFree "1" // Price of first Gobblegum (1 = free, 0 = 500)
+
+///////////////////////////////////////////////////
+// MAP SHORT NAMES ROTATION LIST //
+///////////////////////////////////////////////////
+// //
+/////////Base Maps/////////////////////////////////
+// //
+// Shadows of Evil - zm_zod //
+// //
+/////////Awakening DLC/////////////////////////////
+// //
+// Der Eisendrache - zm_castle //
+// //
+/////////Eclipse DLC///////////////////////////////
+// //
+// Zetsubou No Shima - zm_island //
+// //
+/////////Descent DLC///////////////////////////////
+// //
+// Gorod Krovi - zm_stalingrad //
+// //
+/////////Salvation DLC/////////////////////////////
+// //
+// Revelations - zm_genesis //
+// //
+/////////Zombies Chronicles DLC////////////////////
+// //
+// Ascension - zm_cosmodrome //
+// Kino der Toten - zm_theater //
+// Moon - zm_moon //
+// Nacht der Untoten - zm_prototype //
+// Origins - zm_tomb //
+// Shangri-La - zm_temple //
+// Shi No Numa - zm_sumpf //
+// The Giant - zm_factory //
+// Verrückt - zm_asylum //
+// //
+///////////////////////////////////////////////////
+
+set sv_maprotation "gametype zclassic map zm_tomb"
\ No newline at end of file
diff --git a/installer/game/localappdata/T7x/data/gamesettings/mp/gamesettings_escort.cfg b/installer/game/localappdata/T7x/data/gamesettings/mp/gamesettings_escort.cfg
new file mode 100644
index 00000000..5b713e17
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/gamesettings/mp/gamesettings_escort.cfg
@@ -0,0 +1,26 @@
+gametype_setting timelimit 5
+gametype_setting scorelimit 0
+gametype_setting roundscorelimit 1
+gametype_setting roundwinlimit 2
+gametype_setting roundlimit 2
+gametype_setting preroundperiod 10
+gametype_setting teamCount 2
+
+gametype_setting shutdownDamage 3
+gametype_setting bootTime 5
+gametype_setting rebootTime 15
+gametype_setting rebootPlayers 0
+gametype_setting movePlayers 1
+gametype_setting robotSpeed 1
+gametype_setting robotShield 0
+
+
+gametype_setting scoreHeroPowerGainFactor 0.788 //Score earned towards Hero Weapons and Abilities are multiplied by this factor
+gametype_setting scoreHeroPowerTimeFactor 0.788
+
+gametype_setting spawntraptriggertime 5
+
+gametype_setting disableVehicleSpawners 1
+
+gametype_setting gameAdvertisementRuleTimeLeft 3.5
+gametype_setting gameAdvertisementRuleRound 3
diff --git a/installer/game/localappdata/T7x/data/launcher/bigboiii.jpg b/installer/game/localappdata/T7x/data/launcher/bigboiii.jpg
new file mode 100644
index 00000000..40f207c9
Binary files /dev/null and b/installer/game/localappdata/T7x/data/launcher/bigboiii.jpg differ
diff --git a/installer/game/localappdata/T7x/data/launcher/main.html b/installer/game/localappdata/T7x/data/launcher/main.html
new file mode 100644
index 00000000..e6fd12b1
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/launcher/main.html
@@ -0,0 +1,144 @@
+
+
+
+
+
+ T7x
+
+
+
+
+
+
+
+
+
+ T7x
+
+
Play
+
+ About
+
+
+
+
+
+
diff --git a/installer/game/localappdata/T7x/data/launcher/noise.jpg b/installer/game/localappdata/T7x/data/launcher/noise.jpg
new file mode 100644
index 00000000..073a7025
Binary files /dev/null and b/installer/game/localappdata/T7x/data/launcher/noise.jpg differ
diff --git a/installer/game/localappdata/T7x/data/lookup_tables/dvar_list.txt b/installer/game/localappdata/T7x/data/lookup_tables/dvar_list.txt
new file mode 100644
index 00000000..b1187112
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/lookup_tables/dvar_list.txt
@@ -0,0 +1,7026 @@
+AmmoBoxPickupTime
+BotCount
+ClickToContinue
+GameDescription
+HTTPD_CmdFence
+HTTPD_Port
+HTTPD_StaticRoot
+MapName
+MaxPlayerCount
+ParallaxHUD
+ServerName
+ServerPassword
+ShakeHUD
+TestIntervalJitter
+UI_enabled
+UI_highlightScaledText
+UI_safeAreaOverride
+UI_showSafeArea
+ViewAngleOverride_cameraInputDeadTimeMs
+ViewAngleOverride_cameraInputThreshold
+accelspeed
+actors_walkable
+addMapPackFlagsUserInfo
+addfavourite
+adsZeroSpread
+ai_ShowCanSeeChecks
+ai_ShowCanshootChecks
+ai_accu_player_lateral_speed
+ai_accuracyDistScale
+ai_accuracy_attackerCountDecrease
+ai_accuracy_attackerCountMax
+ai_adjustOffMeshNodes
+ai_allowCachedConditions
+ai_allowFrameLimitedApi
+ai_allowLerpedCooldownTimers
+ai_angularYawAccelRate
+ai_angularYawDecelFactor
+ai_angularYawEnabled
+ai_arrivalLookaheadDistance
+ai_avoidNavBoundaries
+ai_avoidOthersAtCloseDist
+ai_awarenessEnabled
+ai_badPathSpam
+ai_clampToNavMeshEnabled
+ai_clientFacialCullDist
+ai_codeGameskill
+ai_corpseCount
+ai_coverDistanceOffset
+ai_coverFlankCheckRad
+ai_coverFlankDistToCover
+ai_coverFlankMaxAngle
+ai_coverHeightOffset
+ai_coverScore_coverType
+ai_coverScore_dangerousNode
+ai_coverScore_distance
+ai_coverScore_engagement
+ai_coverScore_flanking
+ai_coverScore_nodeAngle
+ai_coverScore_playerLos
+ai_coverScore_priority
+ai_coverScore_targetDir
+ai_coverScore_visibility
+ai_coverSearchInterval
+ai_coverSpacingDistance
+ai_debugAccuracy
+ai_debugAnimDeltas
+ai_debugAnimScripted
+ai_debugArrivals
+ai_debugCodeBehaviorTree
+ai_debugCoverEntityNum
+ai_debugCoverSelection
+ai_debugCoverTool
+ai_debugEntIndex
+ai_debugEntLock
+ai_debugFindPath
+ai_debugFindPathDirect
+ai_debugFindPathLock
+ai_debugFindPathWidth
+ai_debugFlyingPath
+ai_debugGrenadeHintArc
+ai_debugMayMove
+ai_debugMeleeAttackSpots
+ai_debugTargets
+ai_debugThreatSelection
+ai_debugTurnRate
+ai_debugVolumeTool
+ai_debug_dynamic_nodes
+ai_disableSpawn
+ai_doNotDamageTeammates
+ai_dogMeleeHeight
+ai_dogMeleeRange
+ai_dogMeleeWidth
+ai_enableBadPlaces
+ai_eventDistBadPlace
+ai_exitLookaheadDistance
+ai_findNavExternalFaces
+ai_foliageIngoreDist
+ai_foliageSeeThroughDist
+ai_friendlyFireBlockDuration
+ai_friendlySuppression
+ai_friendlySuppressionDist
+ai_generateNavmeshRegions
+ai_instantNoSolidOnDeath
+ai_maxAttackerCount
+ai_meleeDamage
+ai_meleeHeight
+ai_meleeRange
+ai_meleeWidth
+ai_moveOrientMode
+ai_navDisplay_Alpha
+ai_navDisplay_FontSize
+ai_navDisplay_X
+ai_navDisplay_Y
+ai_navDraw_DepthTest
+ai_navDraw_Height
+ai_navVolumeLayerIndex
+ai_navVolume_Cave
+ai_navVolume_fillCells
+ai_navVolume_labelCells
+ai_navVolume_showCellBorders
+ai_navVolume_showEdgeConnections
+ai_navVoume_colorCellsRandomly
+ai_noDodge
+ai_pathChokePointCost
+ai_pathMomentum
+ai_pathNegotiationOverlapCost
+ai_pathRandomPercent
+ai_pathSuppressionEnabled
+ai_perfInfoSortType
+ai_playerFarAccuracy
+ai_playerFarRange
+ai_playerLOSHalfWidth
+ai_playerNearAccuracy
+ai_playerNearRange
+ai_scaleSightUpdateLatency
+ai_secondaryThreats
+ai_showClaimedNode
+ai_showClearanceCeiling
+ai_showCount
+ai_showCoverScore
+ai_showDodge
+ai_showExternalFaceByIndex
+ai_showExternalFaceWithEdge
+ai_showExternalFaces
+ai_showLastKnownEnemyPos
+ai_showNavMemory
+ai_showNavMesh
+ai_showNavMeshBadEdges
+ai_showNavMeshRegions
+ai_showNavMeshSeeds
+ai_showNavMeshSilhouettes
+ai_showNavMeshTriggers
+ai_showNavPaths
+ai_showNavStats
+ai_showNavVolume
+ai_showNavVolumeStats
+ai_showNearestNode
+ai_showNodes
+ai_showNodesDist
+ai_showOffMeshNodes
+ai_showPathFindNodes
+ai_showPaths
+ai_showPerfInfo
+ai_showPotentialCoverLocations
+ai_showPotentialThreatDir
+ai_showSuppression
+ai_showVisData
+ai_showVisDataDist
+ai_showVolume
+ai_simplifyExternalEdges
+ai_slowdownMaxYawDiff
+ai_slowdownMinRate
+ai_slowdownMinYawDiff
+ai_slowdownRateBlendFactor
+ai_stumbleSightFOV
+ai_stumbleSightRange
+ai_tacticalInfluencersDebug
+ai_tacticalInfluencersThreatDebug
+ai_testEdgeForCover
+ai_testVertexForNearbyFaces
+ai_threatUpdateInterval
+ai_trim_path_zigzags
+ai_useBetterLookahead
+ai_useFacingTranslation
+ai_useLeanRunAnimations
+ai_useTacticalInfluencers
+ai_validateBehaviorTree
+ai_warnMissingNavVolume
+ai_weaponCamoEnabled
+aim_DebugTopDownAssist
+aim_accel_turnrate_debug
+aim_accel_turnrate_enabled
+aim_accel_turnrate_lerp
+aim_aimAssistRangeScale
+aim_alternate_lockon_deflection
+aim_alternate_lockon_pitch_strength
+aim_alternate_lockon_region_height
+aim_alternate_lockon_region_width
+aim_alternate_lockon_strength
+aim_assist_min_target_distance
+aim_assist_script_disable
+aim_assist_sniperADS_lock_on
+aim_autoAimRangeScale
+aim_autoaim_debug
+aim_autoaim_enabled
+aim_autoaim_lerp
+aim_autoaim_region_height
+aim_autoaim_region_width
+aim_autograpple_lerp
+aim_automelee_armblade_lunge_region_height
+aim_automelee_armblade_lunge_region_width
+aim_automelee_debug
+aim_automelee_enabled
+aim_automelee_lerp
+aim_automelee_move_limit
+aim_automelee_move_limit_angle
+aim_automelee_move_limit_range
+aim_automelee_region_height
+aim_automelee_region_width
+aim_input_graph_debug
+aim_input_graph_enabled
+aim_input_graph_index
+aim_linkto_autorecenter_delay
+aim_linkto_autorecenter_rate
+aim_lockon_debug
+aim_lockon_deflection
+aim_lockon_enabled
+aim_lockon_height_change_strength
+aim_lockon_pitch_strength
+aim_lockon_region_height
+aim_lockon_region_width
+aim_lockon_strength
+aim_scale_view_axis
+aim_slowdown_debug
+aim_slowdown_enabled
+aim_slowdown_pitch_scale
+aim_slowdown_pitch_scale_ads
+aim_slowdown_region_extended_height
+aim_slowdown_region_extended_width
+aim_slowdown_region_height
+aim_slowdown_region_width
+aim_slowdown_yaw_scale
+aim_slowdown_yaw_scale_ads
+aim_t7_assassinationmode_lerp
+aim_t7_strongautomelee_lerp
+aim_t7_weakautomelee_lerp
+aim_target_actor_min_distance
+aim_target_aim_tag_fast_update_interval
+aim_target_aim_tag_slow_update_interval
+aim_target_alternate_frustum_min_distance
+aim_target_closest_first
+aim_target_fixed_actor_size
+aim_target_frustum_expand_fast_updates
+aim_target_frustum_min_distance
+aim_target_ignore_team_checking
+aim_target_player_enabled
+aim_target_sentient_half_height
+aim_target_sentient_radius
+aim_target_smp
+aim_turnrate_pitch
+aim_turnrate_pitch_ads
+aim_turnrate_yaw
+aim_turnrate_yaw_ads
+aim_view_sensitivity_component
+aim_view_sensitivity_override
+airburstAdjustDistance
+allClientDvarsEnabled
+allCollectiblesUnlocked
+allEmblemsPurchased
+allEmblemsUnlocked
+allItemsPurchased
+allItemsUnlocked
+all_players_are_connected
+allocTracker_log
+allocTracker_print
+allocTracker_printstack
+allocTracker_track
+allowAllNAT
+allowDLCWeaponsByOwnership
+allowGuestSplitScreenOnline
+allowHost_matchesHostedRatio
+allowHost_matchesHostedStreak
+allowHost_matchesPlayedRatio
+allowHost_matchesPlayedStreak
+allowTaskManagerRSU
+allow_weapon_switch_during_swimming
+amd_useShaderExtension
+animScript_listAnims
+anim_debugSpeeds
+anim_deltas_debug
+anim_intro
+anim_visualization_enable
+animscript_debug
+animscript_xcam_debug
+arena_bonusStarStreak
+arena_defaultPlaylist
+arena_enableArenaChallenges
+arena_enableListenHosting
+arena_giveBonusStar
+arena_lobbyReloadSearchDelayMax
+arena_lobbyReloadSearchDelayMin
+arena_maintenance
+arena_maxPregameCryptoSeconds
+arena_minHostSkillRange
+arena_minPlayTime
+arena_minPregameCryptoSeconds
+arena_qosBrodenSkillFrequency
+arena_qosBrodenSkillStep
+arena_qosSkillStart
+arena_seasonOverride
+arena_seasonVetChallengeWins
+arena_unfairTeamGap
+armblade_lunge_region_height
+armblade_lunge_region_width
+art_review
+asm_animDeltaParamsThresh
+asm_codeLevel
+asm_debugAimLayer
+asm_debugLevel
+asm_debugPrimaryDeltaLayer
+asm_debugShootLayer
+asm_disableTransitions
+asm_footMatching
+asm_useNetworkFrameDelta
+assassination
+assassination_cinematic
+assassination_counter
+assassination_debug
+assassination_debug_slowmo
+assassination_default
+assassination_height_limit
+assassination_max_height_displacement
+assassination_mode
+attachment_exclusion_0
+autoExecDemoConfig
+autojoin
+balances_fakeFail
+balances_retry_delay
+balances_retry_max
+banclient
+bandwidth_retry_interval
+banuser
+beamDrawCurveVerts
+beamDrawNodes
+beamDrawSlackInfo
+beamDrawWaveVerts
+beamKillBeam
+beamLaunchBeam
+beamReset
+beast_blur_radius_inner
+beast_blur_radius_outer
+beast_blur_time_in
+beast_blur_time_out
+beast_jump_blur_amount
+behaviorTrackerVersionNumber
+beta_special
+betty_activation_delay
+betty_damage_cylinder_height
+betty_damage_max
+betty_damage_min
+betty_damage_radius
+betty_detect_radius
+betty_grace_period
+betty_jump_height_onground
+betty_jump_height_wall
+betty_jump_time
+betty_onground_angle_threshold
+bgCachePrintValues
+bg_ads
+bg_aimSpreadMoveSpeedThreshold
+bg_allowPlayerRoleTemplateButtonOverrides
+bg_anim_blend_angle
+bg_anim_blend_anim1
+bg_anim_blend_anim2
+bg_anim_blend_force_time
+bg_anim_blend_fudge_time_offset
+bg_anim_blend_ratio
+bg_anim_blend_set
+bg_anim_blend_speed_frac
+bg_anim_blend_timing1a
+bg_anim_blend_timing1b
+bg_anim_blend_timing2a
+bg_anim_blend_timing2b
+bg_anim_blend_turn_speed
+bg_anim_blend_turn_speed_max
+bg_anim_blend_use_dvar_timings
+bg_aqs
+bg_aqsStyle
+bg_arenaSlot
+bg_blendTimeOverride
+bg_bobMax
+bg_bobTransTime
+bg_bobcycleResetThreshold
+bg_bulletPenetrationTreatVoidsAsSolid
+bg_chargeShotAutoDischargeDelay
+bg_chargeShotAutoFireDelay
+bg_chargeShotCenterSpeedReductionPerBullet
+bg_chargeShotDamageIncreasePerBullet
+bg_chargeShotDischargeWhenQueueReachesMax
+bg_chargeShotExponentialAmmoPerChargeLevel
+bg_chargeShotMaxBulletQueueOnEMP
+bg_chargeShotMaxViewKick
+bg_chargeShotMinCenterSpeed
+bg_chargeShotPenetrationMultiplier
+bg_chargeShotUseOneAmmoForMultipleBullets
+bg_chargeShotViewKickIncreasePerBullet
+bg_counterMeleeTime
+bg_debugNotifies
+bg_deferScriptMissileDetonation
+bg_disablePaintshopBaseIconTransform
+bg_disableWeaponPlantingGroundTrace
+bg_disableWeaponPlantingInWater
+bg_dog_swim_enabled
+bg_dog_swim_water_max
+bg_dog_swim_water_min
+bg_drawGrenadeInHand
+bg_drawProximity
+bg_enableIKActiveFix
+bg_fallDamageMaxHeight
+bg_fallDamageMinHeight
+bg_foliagesnd_fastinterval
+bg_foliagesnd_maxspeed
+bg_foliagesnd_minspeed
+bg_foliagesnd_resetinterval
+bg_foliagesnd_slowinterval
+bg_forceAnimOverrideTimerCheck
+bg_forceDurationOverride
+bg_forceExplosiveBullets
+bg_force_idle_scale
+bg_freeCamClipToHeliPatch
+bg_friendlyFire
+bg_friendlyFireMode
+bg_friendlyfireDist
+bg_grappleRequiresEquippedWeapon
+bg_gravity
+bg_grenadeMinimumThrowbackTime
+bg_gunXOffset
+bg_heavyWeaponsAlwaysPlayFirstRaise
+bg_isolateDamageFlash
+bg_legYawCrouchTolerance
+bg_legYawProneTolerance
+bg_legYawTolerance
+bg_limitGrenadeImpacts
+bg_lowGravity
+bg_maxGrenadeIndicatorSpeed
+bg_maxWeaponAnimScale
+bg_meleePreLungeTime
+bg_moonGravity
+bg_movingPlatformPitchScale
+bg_overridePlayerEmblemIcon
+bg_perksCacheTestOld
+bg_plantInWaterDepth
+bg_playStandToCrouchAnims
+bg_playerAnimStanceAllowMovementInteruptTime
+bg_proneSwingSpeed
+bg_prone_yawcap
+bg_scriptCanDisableStances
+bg_serverDelayDamageKickForPing
+bg_shieldHitEncodeHeightVM
+bg_shieldHitEncodeHeightWorld
+bg_shieldHitEncodeWidthVM
+bg_shieldHitEncodeWidthWorld
+bg_slopeFrames
+bg_specialOffhandInventoryAllowBallSwitch
+bg_specialOffhandInventorySwitch
+bg_swingSpeed
+bg_t7BlockMeleeUsageTime
+bg_t7MeleeControlScheme
+bg_t7MeleeHeightCheck
+bg_t7MeleeQuadrantMaxAngle
+bg_t7MeleeQuadrantMinAngle
+bg_t7MeleeUseAssassinationState
+bg_teleportAlignTime
+bg_ufospeedscale
+bg_ufoviewscale
+bg_useCharacterTable
+bg_useClientDamageKick
+bg_useT7Melee
+bg_useThrowButtonForDetonatorGrenades
+bg_vehicle_gravity
+bg_vehicle_ground_max_normal
+bg_vehicle_ground_min_normal
+bg_vehicle_helicopter_dogfight_roll_control_scale
+bg_vehicle_helicopter_focus_target_control_leeway
+bg_vehicle_helicopter_focus_target_damping_angle
+bg_vehicle_helicopter_focus_target_damping_exponent
+bg_vehicle_max_body_pitch
+bg_vehicle_max_body_roll
+bg_vehicle_max_pitch
+bg_vehicle_max_roll
+bg_vehicle_overclip
+bg_vehicle_pitch_track
+bg_vehicle_placement_debug
+bg_vehicle_plane_invert_pitch
+bg_vehicle_plane_jet_controls
+bg_vehicle_plane_turn_assist_decay_rate
+bg_vehicle_roll_track
+bg_vehicle_slide_min_normal
+bg_vehicle_sphere_bounds_offset_z
+bg_vehicle_stepsize
+bg_vehicle_tangential_clip_max_scale
+bg_vehicle_tangential_clip_vel_scale
+bg_vehicle_trace_offset
+bg_viewBobAmplitudeDtp
+bg_viewBobAmplitudeDucked
+bg_viewBobAmplitudeDuckedAds
+bg_viewBobAmplitudeJuke
+bg_viewBobAmplitudeJukeAds
+bg_viewBobAmplitudeProne
+bg_viewBobAmplitudeRoll
+bg_viewBobAmplitudeSlide
+bg_viewBobAmplitudeSprinting
+bg_viewBobAmplitudeStanding
+bg_viewBobAmplitudeStandingAds
+bg_viewBobAmplitudeSwimming
+bg_viewBobAmplitudeWallRun
+bg_viewKickDeflectTime
+bg_viewKickDeflectTimeAds
+bg_viewKickMax
+bg_viewKickMaxAds
+bg_viewKickMin
+bg_viewKickMinAds
+bg_viewKickRandom
+bg_viewKickRecoverTime
+bg_viewKickRecoverTimeAds
+bg_viewKickScale
+bg_viewKickScaleAds
+bg_viewanglesDebug
+bg_vsmode_hud
+bg_warmode_version
+bg_waterGravity
+bg_weaponBobAmplitudeBase
+bg_weaponBobFrequencySwimming
+bg_weaponButtMeleeCharge
+bg_weaponCompatibleIfSharedAmmo
+bg_weaponOffscreenReloadScale
+bg_weaponSubtractFrameTimeRemainder
+bg_weaponSwitchHero
+bg_weaponSwitchHeroHoldTime
+bg_zm_dlc1_chargeShotMultipleBulletsForFullCharge
+bg_zombiePlayerUsesUtilityClip
+bgcache_checksum_validation
+bgcache_checksum_validation_demo
+bgcache_disablewarninghints
+bgcache_displaychecksum
+bgcache_loaddevitems
+bgcache_mark_used_assets
+bgcache_skip_mychanges
+bind
+bind2
+blackboxBandwidthLimited
+blackboxHighVolumeProbability
+blackboxMode
+blurpain
+boostcheatBitchHKRatioCoef
+boostcheatBitchHKRatioMean
+boostcheatBitchHKRatioStddev
+boostcheatBitchKillTimestampsAnomalyCoef
+boostcheatBitchKillTimestampsAnomalyMean
+boostcheatBitchKillTimestampsAnomalyStddev
+boostcheatBitchKillsRatioCoef
+boostcheatBitchKillsRatioMean
+boostcheatBitchKillsRatioStddev
+boostcheatBitchKillsTotalCoef
+boostcheatBitchKillsTotalMean
+boostcheatBitchKillsTotalStddev
+boostcheatHeadshotsTotalCoef
+boostcheatHeadshotsTotalMean
+boostcheatHeadshotsTotalStddev
+boostcheatIntercept
+boostcheatKillerXAnomalyCoef
+boostcheatKillerXAnomalyMean
+boostcheatKillerXAnomalyStddev
+boostcheatKillerYAnomalyCoef
+boostcheatKillerYAnomalyMean
+boostcheatKillerYAnomalyStddev
+boostcheatMeanBitchLifetimeMillisecondsCoef
+boostcheatMeanBitchLifetimeMillisecondsMean
+boostcheatMeanBitchLifetimeMillisecondsStddev
+boostcheatMeanDistanceBitchTraveledCoef
+boostcheatMeanDistanceBitchTraveledMean
+boostcheatMeanDistanceBitchTraveledStddev
+boostcheatMeanDistanceVictimTraveledCoef
+boostcheatMeanDistanceVictimTraveledMean
+boostcheatMeanDistanceVictimTraveledStddev
+boostcheatVictimXAnomalyCoef
+boostcheatVictimXAnomalyMean
+boostcheatVictimXAnomalyStddev
+boostcheatVictimYAnomalyCoef
+boostcheatVictimYAnomalyMean
+boostcheatVictimYAnomalyStddev
+bot_AllowAiming
+bot_AllowAttack
+bot_AllowGrenades
+bot_AllowHeroGadgets
+bot_AllowKillstreaks
+bot_AllowMelee
+bot_AllowMeleeCharge
+bot_AllowMovement
+bot_AllowSprint
+bot_Debug
+bot_DebugX
+bot_DebugY
+bot_DrawPerks
+bot_ForceCrouch
+bot_ForceFire
+bot_ForceMelee
+bot_ForceProne
+bot_ForceStand
+bot_Fov
+bot_FovAds
+bot_PitchSensitivity
+bot_PitchSpeed
+bot_PitchSpeedAds
+bot_PredictCorners
+bot_PressAttackBtn
+bot_PressMeleeBtn
+bot_SnapshotDebug
+bot_UseFriendNames
+bot_YawSensitivity
+bot_YawSpeed
+bot_YawSpeedAds
+bot_difficulty
+bot_enableWallrun
+bot_enemies
+bot_friends
+bot_maxAllies
+bot_maxAxis
+bot_maxFree
+bot_maxJumpDistance
+bot_maxMantleHeight
+bot_maxWaterMantleHeight
+bot_recordButtons
+bot_recordGoal
+bot_recordGoalInfo
+bot_recordHealth
+bot_recordPathing
+bot_recordPlayerFlags
+bot_recordThreat
+bot_supported
+bot_traverseUnderwater
+bow_launcher_bounce_max_scale
+bow_launcher_charge_snap_percent
+bow_launcher_minimum_reticle_scale
+bow_launcher_rebound_scale
+breadcrumbDistanceImportance
+breadcrumbThreshold
+breadcrumbTimeImportance
+bullet_enterWater
+bullet_penetrationEnabled
+bullet_penetrationMinFxDist
+bullet_ricochetBaseChance
+bulletrange
+cameraShakeRemoteHelo_Angles
+cameraShakeRemoteHelo_Freqs
+cameraShakeRemoteHelo_SpeedRange
+cameraShakeRemoteMissile_Angles
+cameraShakeRemoteMissile_Freqs
+cameraShakeRemoteMissile_SpeedRange
+cg_BallisticArc_BeginAlpha
+cg_BallisticArc_BeginWidth
+cg_BallisticArc_Debug
+cg_BallisticArc_DrawDelay
+cg_BallisticArc_EndAlpha
+cg_BallisticArc_EndWidth
+cg_BallisticArc_ForceHitIndicator
+cg_BallisticArc_ImpactRadius
+cg_BallisticArc_MaxBounces
+cg_BallisticArc_MinBounces
+cg_BallisticArc_Offset
+cg_BallisticArc_PerpStep
+cg_BallisticArc_VerticalOffset
+cg_DrawOnScreenFriendlyAI
+cg_DrawOnlyFriendlyPlayerNamesWhileInVehicle
+cg_DrawPlayerNamesWhileInVehicle
+cg_DrawRemoteVehiclePlayerNames
+cg_EnableAdaptiveSkinLodScale
+cg_InfraredFadeoutTime
+cg_ScoresColor_Free
+cg_ScoresColor_Gamertag_0
+cg_ScoresColor_Gamertag_1
+cg_ScoresColor_Gamertag_2
+cg_ScoresColor_Gamertag_3
+cg_ScoresColor_Spectator
+cg_ScoresPing_Interval
+cg_ScoresPing_MaxBars
+cg_VelocityArrow_MaxSegmentLength
+cg_VelocityArrow_MinSegmentLength
+cg_VelocityArrow_RateOfChange
+cg_WeaponButtAttackerCameraShakeDuration
+cg_WeaponButtAttackerHitCameraShakeScale
+cg_WeaponButtAttackerMissCameraShakeScale
+cg_WeaponButtVictimCameraShakeDuration
+cg_WeaponButtVictimCameraShakeScale
+cg_adsZScaleMax
+cg_adsZoomToggleStyle
+cg_aggressiveCullRadius
+cg_ai_useServerAnims
+cg_allPlayerNamesVisible
+cg_altDofTrace
+cg_animInfoCornerOffset
+cg_animMonitorEnt
+cg_animMonitorFilter
+cg_artilleryKillCamBackDist
+cg_artilleryKillCamFov
+cg_artilleryKillCamGroundBackDist
+cg_artilleryKillCamGroundUpDist
+cg_artilleryKillCamUpDist
+cg_artilleryKillCamWallOutDist
+cg_artilleryKillCamWallSideDist
+cg_assignRandomPaintshops
+cg_bloodLimit
+cg_bloodLimitMsec
+cg_blur_time
+cg_brass
+cg_cameraRollOverride
+cg_cameraSpikeEnemyColor
+cg_cameraSpikeHighlightBrightness
+cg_cameraUnderwaterLens
+cg_cameraVehicleExitTweenTime
+cg_cameraVzoomToggleTime
+cg_cameraWaterClip
+cg_canSeeFriendlyFrustumExpand
+cg_canSeeFriendlyFrustumMinDistance
+cg_canSeeFriendlyFrustumUpdateInterval
+cg_cancelChargeShotTime
+cg_centertime
+cg_chatHeight
+cg_cinematicFullscreen
+cg_circularMinimapWhenSquare
+cg_clampFrameInterpolation
+cg_clanNameDebug
+cg_clientSideGlassTouch
+cg_combatRobotKillCamDistFromEyes
+cg_combatRobotKillCamForwardDist
+cg_combatRobotKillCamFov
+cg_combatRobotKillCamSideDist
+cg_combatRobotKillCamUpDist
+cg_combatRobotKillMinDistFromTarget
+cg_connectionIconSize
+cg_constantSizeHeadIcons
+cg_corpseHighlightFadeTime
+cg_cropFactor
+cg_crosshairAlpha
+cg_crosshairAlphaMin
+cg_crosshairDynamic
+cg_crosshairEnemyColor
+cg_crosshairVehicleSentientCheck
+cg_cullBulletAngle
+cg_cullBullets
+cg_cursorHints
+cg_damageIndicatorAngle
+cg_damageIndicatorMinDelay
+cg_damageIndicatorShowAfterDeathTime
+cg_deathCamAboveWater
+cg_deathScreenFadeInTime
+cg_deathScreenFadeOutTime
+cg_debugCacheEnabled
+cg_debugCinematicCamera
+cg_debugDrawSafeAreas
+cg_debugDynamicLadderSight
+cg_debugEllipsesOffset
+cg_debugEntCount
+cg_debugEvents
+cg_debugFace
+cg_debugInfoCornerOffset
+cg_debugMounting
+cg_debugPosition
+cg_debugTargetEntNumber
+cg_debugThirdPersonCamera
+cg_debug_exploders
+cg_debug_overlay_viewport
+cg_debug_triggers
+cg_debugevents
+cg_debugposition
+cg_descriptiveText
+cg_destructibleKillCamCloseXYDist
+cg_destructibleKillCamCloseZDist
+cg_destructibleKillCamFarBlur
+cg_destructibleKillCamFarBlurDist
+cg_destructibleKillCamFarBlurStart
+cg_destructibleKillCamFov
+cg_destructibleKillCamNearBlur
+cg_destructibleKillCamNearBlurEnd
+cg_destructibleKillCamNearBlurStart
+cg_destructibleKillCamRegularHeight
+cg_destructibleKillCamZIncrease
+cg_destructible_radius_damage_enabled
+cg_development
+cg_disableearthquake
+cg_disableplayernames
+cg_dogKillCamDistFromEyes
+cg_dogKillCamForwardDist
+cg_dogKillCamFov
+cg_dogKillCamSideDist
+cg_dogKillCamUpDist
+cg_dogKillMinDistFromTarget
+cg_draw2D
+cg_draw2d
+cg_drawAnimAttachTags
+cg_drawArtFPS
+cg_drawBonesEntNum
+cg_drawBreathHint
+cg_drawBudgets
+cg_drawBulletHitPosNormal
+cg_drawBulletPenetration
+cg_drawCrosshair
+cg_drawCrosshairCooker
+cg_drawCrosshairNames
+cg_drawCrosshairNamesPosX
+cg_drawCrosshairNamesPosY
+cg_drawDecalSort
+cg_drawFPS
+cg_drawFPSLabels
+cg_drawFPSScale
+cg_drawFramePerformanceWarnings
+cg_drawFriendlyNames
+cg_drawGun
+cg_drawHoldBreathHint
+cg_drawIdentifierDebug
+cg_drawJobsPerf
+cg_drawLagometer
+cg_drawLightingDebugText
+cg_drawMantleHint
+cg_drawMaterial
+cg_drawMaterialImageName
+cg_drawMaterialImageNum
+cg_drawMemoryInfo
+cg_drawMinimap
+cg_drawModelAxis
+cg_drawNetTiming
+cg_drawPerformanceSweepInfo
+cg_drawPerformanceWarnings
+cg_drawPhotosensorOverlay
+cg_drawRenderFrame
+cg_drawRumbleDebug
+cg_drawScriptUsage
+cg_drawShellshock
+cg_drawSnapshot
+cg_drawSpectatorMessages
+cg_drawTalk
+cg_drawThroughWalls
+cg_drawVersion
+cg_drawVersionX
+cg_drawVersionY
+cg_drawVisibleCounts
+cg_drawWVisDebug
+cg_drawWaterTrail
+cg_drawXCamInfo
+cg_drawYouInKillCamAsWaypoint
+cg_drawfps
+cg_drawgun
+cg_drawlagometer
+cg_drawpaused
+cg_drawrumbledebug
+cg_droneKillCamBackDist
+cg_droneKillCamUpDist
+cg_dumpAnims
+cg_enableHelicopterNoCullLodOut
+cg_enemyNameFadeIn
+cg_enemyNameFadeOut
+cg_errorDecay
+cg_explosiveKillCamBackDist
+cg_explosiveKillCamGroundBackDist
+cg_explosiveKillCamGroundUpDist
+cg_explosiveKillCamStopDecelDist
+cg_explosiveKillCamStopDist
+cg_explosiveKillCamUpDist
+cg_explosiveKillCamWallOutDist
+cg_explosiveKillCamWallSideDist
+cg_fakefireWizbyChance
+cg_fastApe
+cg_fastFakeApe
+cg_fast_lui
+cg_firstPersonTracerChance
+cg_flareVisionSetFadeDuration
+cg_flipTeamVisuals
+cg_focalDistance
+cg_focalDistanceChangeSpeed
+cg_focalLength
+cg_footprints
+cg_footprintsDebug
+cg_footprintsDistortWater
+cg_footsteps
+cg_forceEmp
+cg_forceInfrared
+cg_forceInvalidPaintshops
+cg_forceNoCullLodOut
+cg_fov
+cg_fovExtraCam
+cg_fovMin
+cg_fovScale
+cg_fov_comp_max
+cg_fov_default
+cg_fov_default_nocomp
+cg_fov_default_thirdperson
+cg_friendlyNameFadeIn
+cg_friendlyNameFadeOut
+cg_fstop
+cg_fullscreenFinalKillcam
+cg_gameBoldMessageWidth
+cg_gameMessageWidth
+cg_gamemessageiconscale
+cg_gun_fovcomp_x
+cg_gun_fovcomp_y
+cg_gun_fovcomp_z
+cg_gun_move_f
+cg_gun_move_minspeed
+cg_gun_move_r
+cg_gun_move_rate
+cg_gun_move_u
+cg_gun_ofs_f
+cg_gun_ofs_r
+cg_gun_ofs_u
+cg_gun_pitch
+cg_gun_roll
+cg_gun_rot_minspeed
+cg_gun_rot_p
+cg_gun_rot_r
+cg_gun_rot_rate
+cg_gun_rot_y
+cg_gun_x
+cg_gun_y
+cg_gun_yaw
+cg_gun_z
+cg_headIconMinScreenRadius
+cg_healthPerBar
+cg_heliKillCamFarBlur
+cg_heliKillCamFarBlurDist
+cg_heliKillCamFarBlurStart
+cg_heliKillCamFov
+cg_heliKillCamNearBlur
+cg_heliKillCamNearBlurEnd
+cg_heliKillCamNearBlurStart
+cg_hideHighDetail
+cg_hideViewmodelInUFOMode
+cg_hintFadeTime
+cg_hitmarkerFrameSpacing
+cg_hudChatIntermissionPosition
+cg_hudChatPosition
+cg_hudDamageDirectionalIconTime
+cg_hudDamageIconHeight
+cg_hudDamageIconInScope
+cg_hudDamageIconOffset
+cg_hudDamageIconTime
+cg_hudDamageIconWidth
+cg_hudFriendlyIndicatorHeight
+cg_hudFriendlyIndicatorWidth
+cg_hudGrenadeIconEnabledFlash
+cg_hudGrenadeIconHeight
+cg_hudGrenadeIconInScope
+cg_hudGrenadeIconMaxHeight
+cg_hudGrenadeIconMaxRangeFlash
+cg_hudGrenadeIconMaxRangeFrag
+cg_hudGrenadeIconMaxScale
+cg_hudGrenadeIconMaxScaleDistance
+cg_hudGrenadeIconMinScale
+cg_hudGrenadeIconMinScaleDistance
+cg_hudGrenadeIconOffset
+cg_hudGrenadeIconWidth
+cg_hudGrenadeIndicatorFadeUp
+cg_hudGrenadeIndicatorStartColor
+cg_hudGrenadeIndicatorTargetColor
+cg_hudGrenadePointerHeight
+cg_hudGrenadePointerPivot
+cg_hudGrenadePointerPulseFreq
+cg_hudGrenadePointerPulseMax
+cg_hudGrenadePointerPulseMin
+cg_hudGrenadePointerWidth
+cg_hudLegacySplitscreenScale
+cg_hudMapBorderWidth
+cg_hudMapFriendlyHeight
+cg_hudMapFriendlyWidth
+cg_hudMapPlayerHeight
+cg_hudMapPlayerWidth
+cg_hudMapRadarLineThickness
+cg_hudProneY
+cg_hudSayPosition
+cg_hudSplitscreenBannerScoreboardScale
+cg_hudSplitscreenCompassElementScale
+cg_hudSplitscreenCompassScale
+cg_hudSplitscreenOffsetsUseScale
+cg_hudSplitscreenScoreboardScale
+cg_hudSplitscreenStanceScale
+cg_hudStanceHintPrints
+cg_hudVotePosition
+cg_infraredBlur
+cg_infraredBlurTime
+cg_infraredFriendlies
+cg_infraredHighlightOffset
+cg_infraredHighlightScale
+cg_infraredUseDefaultMaterial
+cg_ingnoreValidateWeaponOnDeath
+cg_inputLagTestAvgThreshold
+cg_inputLagTestMaxThreshold
+cg_inputLagTestNumRuns
+cg_inputLagTestTimePerRun
+cg_invalidCmdHintBlinkInterval
+cg_invalidCmdHintDelay
+cg_invalidCmdHintDuration
+cg_isGameplayActive
+cg_killcamdebug
+cg_lagometer_pos
+cg_laserLight
+cg_laserSightMaxDistance
+cg_lastSpectatorSelectedThirdPerson
+cg_latencyTestMode
+cg_loadScripts
+cg_luiDebug
+cg_mapLocationSelectionCursorSpeed
+cg_mapLocationSelectionRotationSpeed
+cg_marks_ents_player_only
+cg_marqueeTimeScale
+cg_maxExplosionRadius
+cg_maxPlayerHighlightTargetSize
+cg_minCullBulletDist
+cg_minicon
+cg_minimapCorruptionMaskScale
+cg_minimapMaskPadding
+cg_minimapPadding
+cg_minimapPopOutZoom
+cg_missile_FOV
+cg_noPlayerShadows
+cg_objectiveIndicatorColor
+cg_objectiveIndicatorFarDist
+cg_objectiveIndicatorFarFadeDist
+cg_objectiveIndicatorFarScale
+cg_objectiveIndicatorNearDist
+cg_objectiveIndicatorNearFadeDist
+cg_objectiveIndicatorNoDrawDistance
+cg_objectiveIndicatorPerkFarFadeDist
+cg_objectiveIndicatorSize
+cg_objectiveListWrapCountStandard
+cg_objectiveListWrapCountWidescreen
+cg_oneFriendlyHeadTracePerFrame
+cg_onscreenErrors
+cg_opticAttachmentViewmodelSwitch
+cg_opticCamoHidesShadow
+cg_overheadArmorHeight
+cg_overheadArmorOffset
+cg_overheadHealthDebug
+cg_overheadHealthHeight
+cg_overheadHealthOffset
+cg_overheadHealthWidth
+cg_overheadIconSize
+cg_overheadNamesDamagedEntityNameRetainTime
+cg_overheadNamesDrawOnADS
+cg_overheadNamesDrawOnDamage
+cg_overheadNamesFarDist
+cg_overheadNamesFarScale
+cg_overheadNamesFont
+cg_overheadNamesGlow
+cg_overheadNamesMaxDist
+cg_overheadNamesNearDist
+cg_overheadNamesSize
+cg_overheadNamesTagUpdateInterval
+cg_overheadRankSize
+cg_overheadiconsize
+cg_overheadnamessize
+cg_overheadranksize
+cg_packetAnalysisClient
+cg_packetAnalysisEntTextScale
+cg_packetAnalysisEntTextY
+cg_packetAnalysisEntityIndex
+cg_packetAnalysisEntitySelectionDepth
+cg_packetAnalysisEntityTypeIndex
+cg_packetAnalysisPaused
+cg_packetAnalysisServerMode
+cg_packetAnalysisTextScale
+cg_packetAnalysisTextY
+cg_paintshopCalcTweaks
+cg_paintshopEnableCompression
+cg_paintshopEnableTweaks
+cg_paintshopForceClearDiskCache
+cg_paintshopImageHeight
+cg_paintshopImagePosition
+cg_paintshopImageScale
+cg_paintshopImageWidth
+cg_paintshopIncreasePlayerRes
+cg_paintshopReadDiskCache
+cg_paintshopShowGrid
+cg_paintshopShowGridEdge
+cg_paintshopShowImages
+cg_paintshopShowTweaks
+cg_paintshopWriteDiskCache
+cg_playerBeastGrapHintSizeMax
+cg_playerBeastGrapHintSizeMin
+cg_playerBeastHintSizeMax
+cg_playerBeastHintSizeMin
+cg_playerFrustumHalfHeight
+cg_playerHighlightBlinkTime
+cg_playerHighlightBrightness
+cg_playerHighlightEnemyColor
+cg_playerHighlightMinFade
+cg_playerHighlightPivotLineFlash
+cg_playerHighlightPivotLineWidth
+cg_playerHighlightPivotScale
+cg_playerHighlightSpreadExp
+cg_playerHighlightSpreadScale
+cg_playerHighlightTargetInner
+cg_playerHighlightTargetOuter
+cg_playerHighlightTargetScale
+cg_playerHighlightTargetSize
+cg_playerLockonReticleSize
+cg_playerRenderSmp
+cg_playerVRGame
+cg_playersInViewMinDot
+cg_predictItems
+cg_profile_physics
+cg_proneFeetCollisionHull
+cg_rangeFinderActiveColor
+cg_rangeFinderActiveHeight
+cg_rangeFinderActiveReticleIndex
+cg_rangeFinderActiveWidth
+cg_rangeFinderColorChangeDelay
+cg_rangeFinderDefaultColor
+cg_rangeFinderDefaultDisplayStr
+cg_rangeFinderDefaultReticleIndex
+cg_rangeFinderDiamondIndicator
+cg_rangeFinderDiamondSize
+cg_rangeFinderMinEnemySpottingDist
+cg_rangeFinderPlayerTargetSize
+cg_rangeFinderSelectActors
+cg_rangeFinderSelectPlayers
+cg_rangefinderIndicatorGap
+cg_rangefinderIndicatorSize
+cg_reflect_impactfx
+cg_reflect_impactfx_mindotclamp
+cg_resetWeaponPaintshops
+cg_retrieveHintTime
+cg_retrieveHintTimeStuck
+cg_rocketKillCamBackDist
+cg_rocketKillCamUpDist
+cg_rumble_devgui_duration
+cg_rumble_devgui_loop
+cg_scoreboardBannerHeight
+cg_scoreboardHeight
+cg_scoreboardItemHeight
+cg_scoreboardPingGraph
+cg_scoreboardPingHeight
+cg_scoreboardPingText
+cg_scoreboardPingWidth
+cg_scoreboardQuarterscreenWidth
+cg_scoreboardScrollStep
+cg_scoreboardSplitscreenWidth
+cg_scoreboardWidth
+cg_scriptIconSize
+cg_scriptedKillCamCloseXYDist
+cg_scriptedKillCamCloseZDist
+cg_scriptedKillCamFarBlur
+cg_scriptedKillCamFarBlurDist
+cg_scriptedKillCamFarBlurStart
+cg_scriptedKillCamFov
+cg_scriptedKillCamNearBlur
+cg_scriptedKillCamNearBlurEnd
+cg_scriptedKillCamNearBlurStart
+cg_scriptmover_useServerAnims
+cg_seatHintFadeTime
+cg_sensorGrenadeCrouchZOffset
+cg_sensorGrenadeExplosionTrackTimeMs
+cg_sensorGrenadeLaserActiveTimeMs
+cg_sensorGrenadeLaserRadius
+cg_sensorGrenadeProneZOffset
+cg_sensorGrenadePulsePeriodMs
+cg_sensorGrenadeRampAlpha
+cg_sensorGrenadeRange
+cg_sensorGrenadeZOffset
+cg_showLoadedFF
+cg_showQosResults
+cg_showZombieControls
+cg_showZombieMap
+cg_showmiss
+cg_smp_weapon_visibility
+cg_speedBlurScaleBeast
+cg_speedBlurScaleDoubleJump
+cg_speedBlurScaleGrapple
+cg_speedBlurScaleJuke
+cg_speedBlurScaleLunge
+cg_speedBlurScaleSlam
+cg_speedBlurScaleSlide
+cg_speedBlurScaleSpeedBurst
+cg_splitscreen2pOffset
+cg_splitscreenLetterboxSize
+cg_splitscreenSpectatorScaleIncrease
+cg_sprintMeterDisabledColor
+cg_sprintMeterEmptyColor
+cg_sprintMeterFullColor
+cg_streamLowDetailCamos
+cg_subtitleMinTime
+cg_subtitleWidthStandard
+cg_subtitleWidthWidescreen
+cg_t7HealthOverlay
+cg_t7HealthOverlay_Threshold1
+cg_t7HealthOverlay_Threshold2
+cg_t7HealthOverlay_Threshold3
+cg_tagCacheEnabled
+cg_teamChatsOnly
+cg_thirdPerson
+cg_thirdPersonAngle
+cg_thirdPersonCamLerpScale
+cg_thirdPersonCamOffsetUp
+cg_thirdPersonFocusDist
+cg_thirdPersonFocusOffsetUp
+cg_thirdPersonFootstepsFromNotetracks
+cg_thirdPersonLastStand
+cg_thirdPersonMode
+cg_thirdPersonPaintshop
+cg_thirdPersonRange
+cg_thirdPersonRoll
+cg_thirdPersonSideOffset
+cg_thirdPersonUpOffset
+cg_threatDetectorDebug
+cg_threatDetectorRadius
+cg_timedDamageDuration
+cg_traversalLerpInTime
+cg_traversalLerpOutTime
+cg_treadmarks
+cg_turretBipodOffset
+cg_updateScoreboardAfterGameEnded
+cg_usNewEventQueueScheme
+cg_useNewEventQueueScheme
+cg_useSafeSpectatorCam
+cg_useWeaponBasedVariableZoom
+cg_useWeaponSwitchReloadCancel
+cg_use_colored_smoke
+cg_usercmdBursting
+cg_usingClientScripts
+cg_vehNPCThrottleMultiplier
+cg_vehicleCamAboveWater
+cg_vehicleFocusEntDistanceMax
+cg_vehicleFocusEntDistanceMin
+cg_vehicleFocusEntFocalLengthMax
+cg_vehicleFocusEntFocalLengthMin
+cg_vehicleFocusEntFocalLengthSpeedAdjust
+cg_vehicleFocusEntFstop
+cg_vehicleFocusEntLerpTime
+cg_vehicleVRMechGame
+cg_vehicle_piece_damagesfx_threshold
+cg_viewVehicleInfluenceGunner
+cg_viewVehicleInfluenceGunnerFiring
+cg_viewVehicleInfluenceGunner_mode
+cg_viewZSmoothingMax
+cg_viewZSmoothingMin
+cg_viewZSmoothingTime
+cg_viewmodelAnimatedFalls
+cg_viewmodelAnimatedJumps
+cg_visionSetLerpMaxDecreasePerFrame
+cg_visionSetLerpMaxIncreasePerFrame
+cg_voiceIconSize
+cg_waterPerturbForceScale
+cg_waterPerturbRadiusScale
+cg_waterTrailRippleFrequency
+cg_waterTrailRippleVariance
+cg_watersheeting
+cg_weaponCycleDelay
+cg_weaponHeat
+cg_weaponHintsCoD1Style
+cg_weaponSimulateFireAnims
+cg_youInKillCamSize
+cg_zbarrierStreamAllWeapons
+cgprintentities
+chain_melee_attack_angle_cosine_limit
+chain_melee_chargeThroughVelocity
+chain_melee_enabled
+chain_melee_endAnimEarlyTime
+challenge
+challengeResponseResendBackoffInterval
+challengeResponseResendInterval
+charge_melee_finishCloseThreshold
+chatClientEnabled
+cheapSpawns
+checkEmblemForRank
+checkXUIDBeforeStatsUpload
+cl_allowDownload
+cl_analog_attack_threshold
+cl_anglespeedkey
+cl_autojoin
+cl_avidemo
+cl_bitfieldmismatchFatal
+cl_bspmismatchFatal
+cl_compositeDebugStringMode
+cl_connectTimeout
+cl_connectionAttempts
+cl_dblTapMaxDelayTime
+cl_dblTapMaxHoldTime
+cl_deathMessageWidth
+cl_debugMessageKey
+cl_disableHeroRenders
+cl_disablePaintshopBaseIconTransform
+cl_dpadLeftHeavyWeapon
+cl_dtpHoldTime
+cl_fakeLagMS
+cl_forceavidemo
+cl_freelook
+cl_gamepadCheatsEnabled
+cl_hudDrawsBehindUI
+cl_ingame
+cl_jqprof_continuous
+cl_jqprof_enabled
+cl_jqprof_frequency
+cl_jqprof_profileCheckpointFrames
+cl_jqprof_threshold
+cl_maxPing
+cl_maxpackets
+cl_migrationPingTime
+cl_motdString
+cl_mouseAccel
+cl_nodelta
+cl_noprint
+cl_packetdup
+cl_paused
+cl_pitchspeed
+cl_playerPrestige
+cl_playerRank
+cl_profileTextHeight
+cl_profileTextY
+cl_profileWriteLimiter
+cl_rumble
+cl_secondaryPlayerMenuControlDisable
+cl_serverStatusResendTime
+cl_showMouseRate
+cl_showSend
+cl_showServerCommands
+cl_showTimeDelta
+cl_shownet
+cl_shownuments
+cl_smoothSnapInterval
+cl_socketpool_enabled
+cl_socketpool_size
+cl_specialOffhand
+cl_specialOffhandDelay
+cl_specialOffhandInput
+cl_specialOffhandInventorySwitch
+cl_splitscreenGamestateHack
+cl_sprintOnStick
+cl_sprintOnStick_threshold
+cl_stanceHoldTime
+cl_tacticalHud
+cl_timeout
+cl_useMapPreloading
+cl_userTestBuild
+cl_voice
+cl_weapNextHoldEnable
+cl_weapNextHoldTime
+cl_wwwDownload
+cl_yawspeed
+clanAbbrev
+clanAbbrev_IsEliteValidated
+clear
+clearAllLoadoutSlots
+clearAllLoadoutSlotsCPOffline
+clearAllLoadoutSlotsMPCustom
+clearAllLoadoutSlotsMPOffline
+clearAllLoadoutSlotsZMOffline
+clearKeyStates
+clearLoadoutSlot
+clearLoadoutSlotCPOffline
+clearLoadoutSlotMPCustom
+clearLoadoutSlotMPOffline
+clearLoadoutSlotZMOffline
+clientkick
+climb_cameraAlignmentEaseMode
+climb_cameraRotateTimeMs
+climb_centerAllowedThreshold
+climb_centerTranslateSpeed
+climb_ladderMoveDefaultSpeed
+climb_ladderMoveScale
+climb_ladderSlideDownDefaultSpeed
+climb_ladderSlideDownThreshold
+climb_pitchDownClamp
+climb_pitchUpClamp
+climb_yawClamp
+cmdlist
+com_allowModeSpecificBitFields
+com_animCheck
+com_clientFieldsDebug
+com_cpu_profile
+com_desiredMenu
+com_developer
+com_disable_popups
+com_drawFPS_PC
+com_enablePaintshopInCP
+com_fixedtime
+com_fixedtime_float
+com_forceSVLockStep
+com_freemoveScale
+com_introPlayed
+com_logfile
+com_maxFrameTime
+com_maxclients
+com_maxfps
+com_pauseSupported
+com_pgraph_mode
+com_profileLoadingForceSend
+com_report_syserrors
+com_saveSnapshotProfile
+com_script_debugger_smoke_test
+com_script_error_recovery
+com_script_recordeventintervalms
+com_script_recordeventprobability_client
+com_script_recordeventprobability_server
+com_skipMovies
+com_smoothFrames
+com_sortteamclientsbyname
+com_statmon
+com_sv_running
+com_timescale
+com_useEmptyBitFields
+com_voip_bandwidth_restricted
+com_voip_disable_threshold
+com_voip_resume_time
+com_waitForInitial
+com_waitForInitialFrontend
+com_waitForStreamer
+com_wideScreen
+comerror_enableDelayedComError
+comerror_enableTaskCallbackSysError
+compass
+compassAlwaysShowEnemyVehicles
+compassBehaviorAwarenessEnabled
+compassClampIcons
+compassCloneColor
+compassCoords
+compassDebug
+compassDoubleJumpAlpha
+compassDrawHackerPing
+compassDrawLastStandIcon
+compassECoordCutoff
+compassEnableColorBlindPlayerIcons
+compassEnemyFootstepEnabled
+compassEnemyFootstepMaxRange
+compassEnemyFootstepMaxZ
+compassEnemyFootstepMinSpeed
+compassForcePlayerIcon
+compassFriendlyAIColor
+compassFriendlyColor
+compassFriendlyFogVisionBrightness
+compassFriendlyHeight
+compassFriendlyWidth
+compassGridAlign
+compassGridCols
+compassGridEnabled
+compassGridRows
+compassIconOtherVehHeight
+compassIconOtherVehWidth
+compassIconTankHeight
+compassIconTankScale
+compassIconTankWidth
+compassLocalRadarRadius
+compassLocalRadarUpdateTime
+compassMaxRange
+compassMinRadius
+compassMinRange
+compassObituaryHeight
+compassObituaryWidth
+compassObjectiveHeight
+compassObjectiveIconHeight
+compassObjectiveIconWidth
+compassObjectiveMaxHeight
+compassObjectiveMaxRange
+compassObjectiveMinAlpha
+compassObjectiveMinDistRange
+compassObjectiveMinHeight
+compassObjectiveNearbyDist
+compassObjectiveWidth
+compassPartialType
+compassPingFiringTime
+compassPingGunnerFiringTime
+compassPlayerColor
+compassPlayerHeight
+compassPlayerWidth
+compassRadarLineThickness
+compassRadarPingFadeTime
+compassRadarUpdateFastTime
+compassRadarUpdateTime
+compassRotation
+compassSatellitePingFadeTime
+compassSatelliteScanTime
+compassSatelliteStaticImageFadeTime
+compassShowAIWhileFiring
+compassShowEnemies
+compassSize
+compassSoundPingFadeTime
+compassSpectatorsSeeEnemies
+compassStaticImageUpdateTime
+compassmaxrange
+comscore_backoff
+comscore_debug
+comscore_enabled
+comscore_eventThreshholdSize
+comscore_filtercategories
+con_MiniConSplitscreenScale
+con_channelhide
+con_channelshow
+con_default_console_filter
+con_echo
+con_errormessagetime
+con_gameMsgWindow0FadeInTime
+con_gameMsgWindow0FadeOutTime
+con_gameMsgWindow0Filter
+con_gameMsgWindow0LineCount
+con_gameMsgWindow0MsgTime
+con_gameMsgWindow0ScrollTime
+con_gameMsgWindow0SplitscreenScale
+con_gameMsgWindow1FadeInTime
+con_gameMsgWindow1FadeOutTime
+con_gameMsgWindow1Filter
+con_gameMsgWindow1LineCount
+con_gameMsgWindow1MsgTime
+con_gameMsgWindow1ScrollTime
+con_gameMsgWindow1SplitscreenScale
+con_gameMsgWindow2FadeInTime
+con_gameMsgWindow2FadeOutTime
+con_gameMsgWindow2Filter
+con_gameMsgWindow2LineCount
+con_gameMsgWindow2MsgTime
+con_gameMsgWindow2ScrollTime
+con_gameMsgWindow2SplitscreenScale
+con_gameMsgWindow3FadeInTime
+con_gameMsgWindow3FadeOutTime
+con_gameMsgWindow3Filter
+con_gameMsgWindow3LineCount
+con_gameMsgWindow3MsgTime
+con_gameMsgWindow3ScrollTime
+con_gameMsgWindow3SplitscreenScale
+con_hidelabel
+con_inputBoxColor
+con_inputHintBoxColor
+con_label_filter_mask
+con_labellist
+con_matchPrefixOnly
+con_miniconlines
+con_minicontime
+con_outputBarColor
+con_outputSliderColor
+con_outputWindowColor
+con_restricted
+con_restricted_access
+con_showlabel
+con_typewriterColorBase
+con_typewriterColorGlowCheckpoint
+con_typewriterColorGlowCompleted
+con_typewriterColorGlowFailed
+con_typewriterColorGlowUpdated
+con_typewriterDecayDuration
+con_typewriterDecayStartTime
+con_typewriterEnabledSounds
+con_typewriterPrintSpeed
+connect
+consoleGame
+constBaseline_allow
+constBaseline_bigEndian
+constBaseline_throwError
+content_trialcontentpackbits
+contracts_daily_duration
+contracts_disable_schedule
+contracts_enabled_mp
+contracts_now
+contracts_rows_in_set
+contracts_start_time
+contracts_verbose
+cookbookDebug
+cookbookUseTestData
+counterDownloadInterval
+counterUploadInterval
+cp_queued_level
+creditsScrollScale
+ctx_cover_ads_walk_speed_scale
+ctx_cover_angle_threshold
+ctx_cover_control_scheme
+ctx_cover_debug
+ctx_cover_enable
+ctx_cover_ls_engage_threshold
+ctx_cover_ls_maintain_threshold
+ctx_cover_play3rdPersonAnims
+ctx_cover_post_move_pause
+ctx_cover_test_high
+ctx_cover_test_high_length
+ctx_cover_test_low
+ctx_cover_test_low_length
+ctx_cover_test_radius
+ctx_cover_walk_speed_scale
+cullGlassShards
+currentDifficulty
+currentLiveEvent
+curveBallBackFactor
+curveBallDownFactor
+curveBallForwardFactor
+curveBallUpFactor
+custom_killstreak_mode
+cybercom_enabled
+cybercom_fastswitch_enabled
+daily_contract_cryptokey_reward_count
+db_keyserver1
+db_keyserver2
+db_warnformissingasset
+db_xassetdebug
+db_xassetdebugname
+db_xassetdebugtype
+dbg_switch_00
+dbg_switch_01
+dbg_switch_02
+dbg_switch_03
+dbg_switch_04
+dbg_switch_05
+dbg_switch_06
+dbg_switch_07
+dcacheSimulateNoHDD
+dcache_enabled
+ddlAssertOnMismatch
+ddlRatDone
+debugAnimScript
+debugCurves
+debugOverlay
+debugOverlayClient
+debugRenderCollision
+debugRenderCollisionDistance
+debugRenderMask
+debugRenderPlayerCollision
+debugSplit
+debug_anim_shared
+debug_audio
+debug_brushClipTintVariation
+debug_brushClipTinting
+debug_bulletPenetration
+debug_color_pallete
+debug_crash_type
+debug_litBrushes
+debug_missileImpactNoDamage
+debug_missileStickAngle
+debug_mover
+debug_physicsGunObjCount
+debug_protocol
+debug_ragdollSpawnObjCount
+debug_reflection
+debug_reflection_matte
+debug_rope
+debug_scene
+debug_scene_skip
+debug_show_viewpos
+debug_trace
+debug_triggers
+defaultClassSetCount
+defaultDamageDuration
+defaultDamageInterval
+defaultHitDamage
+default_emblems_max_count
+defragGlassIndices
+defragGlassMemory
+demigod
+demoRenderDuration
+demoRenderSizeX
+demoRenderSizeY
+demo_autoDollyCameraPathFrequency
+demo_bookmarkEventThresholdTime
+demo_bytesPerSecondMax
+demo_bytesPerSecondMin
+demo_cameraLensFStop
+demo_cameraLensFocalDistance
+demo_cameraLensFocalLength
+demo_client
+demo_debug
+demo_desiredClient
+demo_desiredTime
+demo_desiredclient
+demo_desiredtime
+demo_dollycamHighlightThreshholdDistance
+demo_dollycamLeaveAtPreviousMarker
+demo_dollycamMarkerInformationFarDist
+demo_dollycamMarkerInformationFarScale
+demo_dollycamMarkerInformationNearDist
+demo_dollycamMarkerInformationThreshholdDistance
+demo_dollycamMarkerTimeScaleMode
+demo_dollycamMarkerTimeScaleValue
+demo_dollycamTrackWidth
+demo_downloadEntireFile
+demo_downloadLiveStreamThrottleTime
+demo_downloadStreamDataBlockRequestSize
+demo_downloadStreamDataBlockThrottleTime
+demo_downloadStreamMaxRetryAttemps
+demo_downloadStreamRetryWaitTime
+demo_downloadStreamThrottleTime
+demo_drawdebuginformation
+demo_enableAdvancedCameraControls
+demo_enableAutoDollyCameraPath
+demo_enableCameraLens
+demo_enableClipRecordEvent
+demo_enableDeferredMatchRecord
+demo_enableDollyCam
+demo_enableSvBandwidthLimitThrottle
+demo_enabled
+demo_errormessage
+demo_errortitle
+demo_extraNetworkProfileData
+demo_fileblockWriteRate
+demo_filesizeLimit
+demo_filmStartInformationScreenStayTime
+demo_filmStartInformationScreenStayTime_Freerun
+demo_freeCameraLockOnHighlightThreshholdDistance
+demo_freeCameraLockOnMissileAllowed
+demo_freeCameraLockOnOrbitRadius
+demo_freeCameraShowLockableObjectsAlways
+demo_freeCameraUseHeliHeightLockAsCeiling
+demo_hide3rdPersonPlayerModel
+demo_highlightReelGameResultFilter
+demo_highlightReelMinimumStarsFilter
+demo_highlightReelNumberOfSegments
+demo_highlightReelPlayerFilter
+demo_highlightReelStylesFilter
+demo_highlightReelTransitionFilter
+demo_inGameThrottleBandwidthPercent
+demo_inLobbyThrottleBandwidthPercent
+demo_keyframerate
+demo_lightmanMarkerLightAttenuation
+demo_lightmanMarkerLightColorB
+demo_lightmanMarkerLightColorG
+demo_lightmanMarkerLightColorR
+demo_lightmanMarkerLightIntensity
+demo_lightmanMarkerLightMode
+demo_lightmanMarkerLightRange
+demo_livestreaming
+demo_matchRecordEventOnPlaylists
+demo_maxTimeScale
+demo_nodeath
+demo_oldposInsteadOfMapCenter
+demo_packetsPerSecondMax
+demo_packetsPerSecondMin
+demo_pause
+demo_pauseOnNextSnapshot
+demo_playbackClientXUID
+demo_profiling
+demo_recordOfflineMatch
+demo_recordPrivateMatch
+demo_recordStaticEntityPositions
+demo_recordSystemlinkMatch
+demo_recordingrate
+demo_refreshDollyCamFxEveryFrame
+demo_save_smp
+demo_selectedSegmentIndex
+demo_sendEventOnFailure
+demo_skipBuildingDemoSnapshotDuringCinematicPlayback
+demo_streamUploadKeepAliveFrequency
+demo_streamingAdjustmentFactor
+demo_streamingSendSocketBuffSizeForOtherUploads
+demo_streamingSendSocketBuffSizeForRecording
+demo_summaryReadEnabled
+demo_svBandwidthLimitThrottleMaxBytesPercent
+demo_svBandwidthLimitThrottleTimeout
+demo_useDefaultVehicleDefIndexIfInvalid
+demo_useMapNameAsDefaultName
+demo_usefilesystem
+demo_viewTraceMask
+demo_writePaintShopInformation
+demoname
+dev_timescale
+devdlc
+developer
+devgui_bevelShade
+devgui_colorBgnd
+devgui_colorBgndGray
+devgui_colorBgndGraySel
+devgui_colorBgndSel
+devgui_colorGraphKnotEditing
+devgui_colorGraphKnotNormal
+devgui_colorGraphKnotSelected
+devgui_colorSliderBgnd
+devgui_colorSliderKnob
+devgui_colorSliderKnobSel
+devgui_colorText
+devgui_colorTextGray
+devgui_colorTextGraySel
+devgui_colorTextSel
+devgui_favMenuEnabled
+devgui_scale
+devgui_showOnlyFavMenu
+devgui_warningSpam
+devgui_warningSpan
+devgui_zoomEnabled
+devmap
+devmaponline
+disableHost_matchesHostedRatio
+disableHost_matchesHostedStreak
+disableHost_matchesPlayedRatio
+disableHost_matchesPlayedStreak
+disableLookAtEntityLogic
+disable_aivsai_melee
+disable_fx
+disable_rope
+disconnect
+disconnected_ctrls
+dive_debug
+dive_enabled
+dive_groundTraceDist
+dive_min_distance_ratio
+dive_traceForward
+dlc2_fix_scripted_looping_linked_animations
+dlc2_show_damage_feedback_when_drowning
+dlc3_veh_UpdateYawEvenWhileStationary
+doAutoExecDevConfig
+doAutoExecUserConfig
+doMaintenance
+dog_MeleeDamage
+dog_checkObstaceInPathWhenMoving
+dog_checkShouldTurnWhenMoving
+dog_repathDistSq
+dog_traceMask
+dog_turn180_angle
+dog_turn90_angle
+dog_turn_min_goal_dist
+door_breach_weapondrop
+doubleJump_accel
+doubleJump_accelerationThreshold
+doubleJump_ads_enabled
+doubleJump_allow_while_swimming
+doubleJump_fire_disabled_angles
+doubleJump_fire_enabled
+doubleJump_frictionMax
+doubleJump_frictionMin
+doubleJump_frictionScale
+doubleJump_fx_enabled
+doubleJump_hud_border
+doubleJump_hud_is_vertical
+doubleJump_maxUpwardsVelocity
+doubleJump_minimapClip
+doubleJump_minimapFadeTime
+doubleJump_minimapRevealEnabled
+doubleJump_minimapRevealEnemies
+doubleJump_minimapRevealFriendlies
+doubleJump_minimapRevealMaxDistance
+doubleJump_minimapRevealSelf
+doubleJump_minimapRevealSpeed
+doubleJump_minimapRevealTime
+doubleJump_requirejump
+doubleJump_rumble_enabled
+doubleJump_shake_duration
+doubleJump_shake_duration_ads
+doubleJump_shake_duration_ads_spam
+doubleJump_shake_duration_spam
+doubleJump_shake_enabled
+doubleJump_shake_scale
+doubleJump_shake_scale_ads
+doubleJump_shake_scale_ads_spam
+doubleJump_shake_scale_spam
+doubleJump_shellshocked_accel
+doubleJump_shellshocked_maxUpwardsVelocity
+doubleJump_shellshocked_speed
+doubleJump_shellshocked_upBoostAccel
+doubleJump_speed
+doubleJump_tap_enabled
+doubleJump_upBoostAccel
+doubleJump_viewAngleMaxPitch
+doubleJump_viewAngleMaxRoll
+doubleJump_viewAnglePitchSpeed
+doubleJump_viewAngleRollSpeed
+doubleJump_viewMovementEnabled
+doubleJump_viewmodel_anim_enabled
+doublejump_animCosAngle
+doublejump_blur_amount
+doublejump_blur_enabled
+doublejump_blur_radius_inner
+doublejump_blur_radius_outer
+doublejump_blur_time_in
+doublejump_blur_time_out
+doublejump_control_scheme
+doublejump_enabled
+doublejump_hud
+doublejump_rechargeInAir
+doublejump_rechargeInWater
+doublejump_requirekeyup
+doublejump_requirekeyup_in_water
+doublejump_time_before_recharge
+doublejump_time_before_recharge_emp
+doublejump_time_before_recharge_fast
+doublescreen
+doublesided_raycasts
+drawEntityCount
+drawEntityCountPos
+drawEntityCountSize
+drawGlassBBox
+drawGlassDebug
+drawKillcamData
+drawKillcamDataPos
+drawKillcamDataSize
+drawLagometer
+drawServerBandwidth
+drawServerBandwidthPos
+drawServerBandwidthSize
+drawShardOutline
+dtp
+dtp_debug
+dtp_exhaustion_window
+dtp_fall_damage_max_height
+dtp_fall_damage_min_height
+dtp_max_apex_duration
+dtp_max_slide_addition
+dtp_max_slide_duration
+dtp_min_speed
+dtp_new_trajectory
+dtp_new_trajectory_multiplier
+dtp_post_move_pause
+dtp_startup_delay
+dumpimages
+dumpmateriallist
+dumpmodels
+durangoGame
+dvarConfigEnabled
+dvarConfigFatal
+dvar_maxCallbackTimeMS
+dvardump
+dvarlist
+dvr_enable
+dwConsideredConnectedTime
+dwFileFetchTryIntervalBase
+dwFileFetchTryIntervalMax
+dwFileFetchTryMaxAttempts
+dwKVSWriteLocally
+dwNetMaxWaitMs
+dwStreamingSendSocketBuffSize
+dwTitle
+dw_defaultDTLSAssociationTimeout
+dw_popup
+dw_sendBufSize
+dynEnt_bulletForce
+dynEnt_damageRadiusScale
+dynEnt_delete_expensive
+dynEnt_disable_rb_collision
+dynEnt_explodeForce
+dynEnt_explodeMaxEnts
+dynEnt_explodeMinForce
+dynEnt_explodeSpinScale
+dynEnt_explodeUpbias
+dynEnt_sentientAutoActivate
+dynEnt_shouldCullEntitiesForSplitscreen
+dynEnt_small_cylinder_dimension
+dynEnt_small_cylinder_max_avel
+dynEnt_spawnedLimit
+dynsnaps_debugspew
+emblem
+emblemVersion
+emblem_scroll_delay_first
+emblem_scroll_delay_rest
+emblems_enabled
+emblems_max_count
+enableChallengeResponse
+enableDLCWeapons
+enableTacticalArrival
+enable_camo_materials_tab
+enable_cheap_ents
+enable_frame_sampling
+enable_global_wind
+enable_grass_wind
+enable_moving_paths
+enable_new_prone_check
+enable_retail_incentive
+enable_season_pass_incentive
+enable_sp_exploit_check
+enable_weapon_contract
+energyShieldActorMagneticAccuracy
+energyShieldReflectDamageMultiplier
+energyShieldReflectLerpToNormalFrac
+entitlementsActive
+entitycount
+equipClass
+equipDefaultClass
+equipDefaultClassToProfile
+equipDefaultCustomMatchClass
+equipDefaultItemToSlot
+equipLoadoutSlot
+equipLoadoutSlotCPOffline
+equipLoadoutSlotMPCustom
+equipLoadoutSlotMPOffline
+equipLoadoutSlotZMOffline
+equipLoadoutWeaponSlot
+equipLoadoutWeaponSlotCPOffline
+equipLoadoutWeaponSlotMPCustom
+equipLoadoutWeaponSlotMPOffline
+equipLoadoutWeaponSlotZMOffline
+equipmentAltModeEnabled
+equipmentAsGadgets
+equipmentMods
+equipment_enable_threat_detector
+excellentPing
+exec
+facepaintLodDist
+fakeEmblemCount
+fast_restart
+fastfile_allowNoAuth
+fastfile_warnMeWhenOutOfSync
+ffotdtempfixHostLaunchPump
+fileshareAllowDownload
+fileshareAllowDownloadingOthersFiles
+fileshareAllowEmblemDownload
+fileshareAllowPaintjobDownload
+fileshareAllowVariantDownload
+fileshareRetry
+fileshareShowFailure
+fileshareXuidOverride
+fileshare_enabled
+fileshare_fakeFail
+fileshare_tier
+filterdedicatedserverresults
+fire_audio_random_max_duration
+fire_audio_repeat_duration
+fire_burn_time
+fire_debug
+fire_world_damage
+fire_world_damage_duration
+fire_world_damage_rate
+firstPersonLegs
+firstPersonLegsInWater
+firstPersonLegsOffset
+firstPersonLegsOffsetMax
+firstPersonLegsOffsetMin
+firstPersonLegsZmax
+firstPersonLegsZmin
+firstPersonShadow
+fixNegativeLosses
+fixedtime
+fixedtime_float
+flameVar_editingFlameTable
+flameVar_lastFlameTable
+flame_debug_render
+flame_kick_offset
+flame_kick_recover_speed
+flame_kick_speed
+flame_render
+flame_team_damage
+flame_test
+flame_use_new_beam_system
+flareDisableEffects
+footstep_sounds_cutoff
+forceEliteFounder
+forceElitePopups
+forceEliteSubscription
+forceFullScreenMap
+forceHost
+forceLiveEvent
+force_cac
+force_no_cac
+fpsTool_drawInfo
+fpsTool_drawPoints
+fpsTool_forceAsyncCompute
+fpsTool_headings
+fpsTool_includeMapSamplePoints
+fpsTool_loadTest
+fpsTool_maxSamples
+fpsTool_note
+fpsTool_randomRotate
+fpsTool_receiveSamples
+fpsTool_run
+fpsTool_showGun")"
+fpsTool_showGun
+fpsTool_takeScreenshots
+frame_sampling_rate
+freezeShards
+friction
+friendlyContentOutlines
+friendlyNameFontColor
+friendlyNameFontGlowColor
+friendlyNameFontObjective
+friendlyNameSplitScreenFontSize
+friendlyfire_enabled
+friendsNewsLastFetchTime
+fsShowStreamingGraph
+fsSlotEmptyHiddenColor
+fsSlotEmptyMainColor
+fsSlotEmptyNotSubscribedColor
+fsSlotEmptyShowColor
+fsSlotEmptyShowColorBg
+fsSlotHighlightedColor
+fsSlotHighlightedColorNoSel
+fsSlotMainColor
+fsSlotNumMainColor
+fsSlotNumNoSubsribeColor
+fsStarAvgColor
+fsStarHighlightColor
+fs_basegame
+fs_basepath
+fs_debug
+fs_game
+fs_homepath
+fs_ignoreLocalized
+fs_restrict
+fs_usedevdir
+fshCustomGameName
+fshEnableRender
+fshFileDebug
+fshMtxName
+fshOldItemColor
+fshRecentsXUID
+fshRenderSuccessURL
+fshRenderWriteTimeout
+fshRetryDelay
+fshSearchTaskDelay
+fshSkipFileStats
+fshStaffXuid
+fshSummaryDelay
+fshThrottleEnabled
+fshThrottleKBytesPerSec
+fudgefactor
+fx_alphacull_enable
+fx_attempt_trail_reconstruction
+fx_attempt_trail_reconstruction_debug
+fx_attempt_trail_reconstruction_lerp_ratio
+fx_attempt_trail_reconstruction_lerp_time_ms
+fx_compute_sprites_debug_draw
+fx_compute_sprites_enable
+fx_compute_sprites_enable_all
+fx_compute_sprites_only
+fx_compute_sprites_shadow
+fx_compute_sprites_show_lmap
+fx_count
+fx_cull_effect_spawn
+fx_cull_elem_draw
+fx_cull_elem_spawn
+fx_debugBolt
+fx_depth_test_bounding_boxes
+fx_disable_exclusion_volumes
+fx_draw
+fx_drawClouds
+fx_draw_dvar
+fx_draw_exclusion_volumes
+fx_draw_weapon_tags
+fx_enable
+fx_enable_bounding_boxes
+fx_enable_portal_culling
+fx_force_bounding_boxes
+fx_force_portal_culling
+fx_freeze
+fx_gpufx_debug_enable
+fx_gpufx_draw_enable
+fx_gpufx_elem_limit
+fx_gpufx_library_enable
+fx_gpufx_no_water
+fx_gpufx_sort_enable
+fx_gpufx_sprite_limit
+fx_gpufx_update_enable
+fx_limit_spawn_workers
+fx_liveupdate
+fx_liveupdate_kb
+fx_liveupdate_verbose
+fx_logging
+fx_mark_profile
+fx_marks
+fx_marks_debug_text
+fx_marks_draw
+fx_marks_draw_impact_axis
+fx_marks_ents
+fx_marks_forward_vol_marks_enable
+fx_marks_grid_debug
+fx_marks_grid_enable
+fx_marks_range
+fx_marks_smodels
+fx_max_per_frame_distance
+fx_occlusion_max_player_count
+fx_occlusion_query_profile
+fx_priority_debug
+fx_priority_enable
+fx_process_clouds
+fx_profile
+fx_show_bounding_boxes
+fx_show_distances
+fx_show_names_range
+fx_use_ground_entity
+fx_visMinTraceDist
+fx_warn_on_version
+fxfrustumCutoff
+g_FactionName_Allies
+g_FactionName_Axis
+g_FactionName_allies
+g_FactionName_axis
+g_FactionName_free
+g_ScoresColor_Allies
+g_ScoresColor_Axis
+g_ScoresColor_EnemyTeam
+g_ScoresColor_Free
+g_ScoresColor_MyTeam
+g_ScoresColor_Spectator
+g_TeamColor_Allies
+g_TeamColor_Axis
+g_TeamColor_EnemyTeam
+g_TeamColor_EnemyTeamAlt
+g_TeamColor_Free
+g_TeamColor_MyTeam
+g_TeamColor_MyTeamAlt
+g_TeamColor_MyTeamAlt_Party
+g_TeamColor_Party
+g_TeamColor_Spectator
+g_TeamIcon_Allies
+g_TeamIcon_Axis
+g_TeamIcon_Free
+g_TeamIcon_Spectator
+g_TeamName_Allies
+g_TeamName_Axis
+g_TeamName_Three
+g_TeamName_allies
+g_TeamName_axis
+g_TeamName_free
+g_actorAndVehicleAntilag
+g_actorAndVehicleAntilagDebug
+g_ai
+g_aiEventDump
+g_allowLastStandForActiveClients
+g_allowVote
+g_allowvote
+g_animMonitorEnt
+g_animMonitorFilter
+g_antilag
+g_antilagRestoreOnDamage
+g_antilagTimeCap
+g_avoidEnabled
+g_bDebugGrappleTrace
+g_bDebugRenderBrushes
+g_bDebugRenderBulletCollision
+g_bDebugRenderBulletMeshes
+g_bDebugRenderCollision
+g_bDebugRenderCollisionDistance
+g_bDebugRenderColoredPatches
+g_bDebugRenderEntityBrushes
+g_bDebugRenderMeshType
+g_bDebugRenderPatches
+g_bDebugRenderStaticModelsBounds
+g_banIPs
+g_broadcastLocalSound
+g_campaign_mode
+g_changelevel_time
+g_clientSideLinkingEnabled
+g_clonePlayerMaxVelocity
+g_compassShowEnemies
+g_customTeamName_Allies
+g_customTeamName_Axis
+g_customTeamName_Three
+g_deadChat
+g_deathDelay
+g_deathcameratraceheight
+g_debugAccuracy
+g_debugBehaviorStateMachine
+g_debugBulletDuration
+g_debugBulletEntityType
+g_debugBullets
+g_debugCacheEnabled
+g_debugDamage
+g_debugHitBrush
+g_debugHitSurface
+g_debugLocDamage
+g_debugLocDamageEntity
+g_debugLocHit
+g_debugLocHitTime
+g_debugPlayerAnimScript
+g_debugRankXP
+g_debugRenderGjkTraceGeom
+g_debugRenderMask
+g_debugServerAiming
+g_debugWeaponXP
+g_destructibleDraw
+g_drawDebugInfoVolumes
+g_drawDebugInfoVolumesInverse
+g_drawGrenadeHints
+g_dropForwardSpeed
+g_dropHorzSpeedRand
+g_dropUpSpeedBase
+g_dropUpSpeedRand
+g_droppedWeaponPhysics
+g_dumpAIEvents
+g_dumpAnims
+g_dumpAnimsCommands
+g_dumpAnimsReduceSpam
+g_dumpStaticModels
+g_entinfo
+g_entinfo_AItext
+g_entinfo_maxdist
+g_entinfo_scale
+g_entinfo_type
+g_entsInSnapshot
+g_erroronpathsnotconnected
+g_fast_devmap
+g_fogColorReadOnly
+g_fogHalfDistReadOnly
+g_fogStartDistReadOnly
+g_friendlyNameDist
+g_gameEnded
+g_gametype
+g_knockback
+g_lagged_damage_threshold
+g_listEntity
+g_listEntityCounts
+g_loadScripts
+g_log
+g_logSync
+g_logTimeStampInSeconds
+g_mantleBlockTimeBuffer
+g_maxDroppedWeapons
+g_maxEntsInSnapshot
+g_minGrenadeDamageSpeed
+g_minimumAvgCollisionArea
+g_motd
+g_oldAnimCmdNetwork
+g_password
+g_pickupPromptsForDroppedWeapons
+g_playerCollisionEjectSpeed
+g_playerRespawnTime
+g_playerVRGame
+g_processDamageAfterFullBullet
+g_quadrotorFlyHeight
+g_redCrosshairs
+g_reviveTime
+g_scrDebugHudElems
+g_smoothClients
+g_spawnai
+g_speed
+g_synchronousClients
+g_tagCacheEnabled
+g_teamColor_EnemyTeam
+g_teamColor_EnemyTeamAlt
+g_teamColor_MyTeam
+g_teamColor_MyTeamAlt
+g_teamColor_Squad
+g_throttleTempEnts
+g_turretBipodOffset
+g_turretServerPitchMax
+g_turretServerPitchMin
+g_useholdspawndelay
+g_useholdtime
+g_validateBehaviorStateMachine
+g_vehicleBypassFriendlyFire
+g_vehicleDebug
+g_vehicleDrawPath
+g_vehicleDrawSplines
+g_vehiclePlaneCurveTime
+g_vehicleVRMechGame
+g_voiceChatTalkingDuration
+g_voteAbstainWeight
+gadgetActivateDuringWeaponChange
+gadgetEnabled
+gadgetFlickerDurationDefault
+gadgetFlickerWhizbyMaxDistance
+gadgetPowerInitEmpty
+gadgetPowerOverchargePerkScoreFactor
+gadgetPowerOverchargePerkTimeFactor
+gadgetPowerOverrideFactor
+gadgetPowerUnlimited
+gadgetPulseOrbShareEnemy
+gadgetPulseOrbShareFriendly
+gadgetThiefKillFullPowerMultiplier
+gadgetThiefKillPowerGain
+gadgetThiefRechargeRate
+gadgetThiefShutdownFullCharge
+gadget_blur_enabled
+gadget_castShaderDuration
+gadget_flashbackMinimapFudgeFactor
+gadget_flashbackResetsWallrunTime
+gadget_flashbackUsesPriorAngles
+gadget_flashbackWhiteAlphaRatio
+gadget_flashbackWhiteFlash
+gadget_force_slots
+gadget_resurrectHeavyWeaponsFatal
+gadget_resurrectHeroWeaponsFatal
+gadget_speedBurstBaseGlow
+gadget_speedBurstBaseGlowScalar
+gadget_speedBurstBlurScalar
+gadget_speedBurstDesatClamp
+gadget_speedBurstDesatRampSpeed
+gadget_speedBurstDoesJuke
+gadget_speedBurstGlowPulseDuration
+gadget_speedBurstWallRunJumpVelocity
+gadget_visionPulseFriendlyMinimap
+gadget_visionPulseFriendlyMinimapColor
+gadget_visionPulseMinimapFadeTime
+gadget_visionPulseRevealsCamo
+gamedate
+gamename
+gamesettings_generateconfig
+gametype_setting
+geographicalMatchmakingOverride
+give
+glassBroom
+glassCanBreakFromSlide
+glassCanBreakFromSprint
+glassCanBreakFromWallrun
+glassCrackedDamageRateRange
+glassDamageMultiplier
+glassExtraAngVelocity
+glassExtraLinVelocity
+glassForceAttenuation
+glassForceMultiplier
+glassForceOriginMult
+glassFreeBuffersDelay
+glassLinVelMultiplier
+glassLowLodDist
+glassMaxShardLife
+glassMinVelocityLowest
+glassMinVelocityToBreakFromJump
+glassMinVelocityToBreakFromSlide
+glassMinVelocityToBreakFromSprint
+glassMinVelocityToBreakFromWallrun
+glassPlayShatterFX
+glassPlayerPredictTime
+glassPredictTime
+god
+goodPing
+gpad_button_deadzone
+gpad_button_lstick_deflect_max
+gpad_button_rstick_deflect_max
+gpad_debug
+gpad_enabled
+gpad_fake_vita
+gpad_lightbar_test
+gpad_menu_scroll_delay_first
+gpad_menu_scroll_delay_rest
+gpad_stick_deadzone_max
+gpad_stick_deadzone_min
+gpad_stick_pressed
+gpad_stick_pressed_hysteresis
+grapple_blur_amount
+grapple_blur_radius_inner
+grapple_blur_radius_outer
+grapple_blur_time_in
+grapple_blur_time_out
+grapple_early_yank_anim_start_time
+grenadeAllowRigidBodyPhysics
+grenadeAnimatedFlatCosine
+grenadeAnimatedFrictionHigh
+grenadeAnimatedFrictionLow
+grenadeAnimatedMinDotBeforeRolling
+grenadeAnimatedMinDotBeforeRollingOnFlat
+grenadeAnimatedRollDegree
+grenadeBounceRestitutionMax
+grenadeBumpFreq
+grenadeBumpMag
+grenadeBumpMax
+grenadeCurveMax
+grenadeFrictionHigh
+grenadeFrictionLow
+grenadeFrictionMaxThresh
+grenadeMinDotBeforeRolling
+grenadeParallelBounceOverride
+grenadePerpendicularBounceOverride
+grenadeRestThreshold
+grenadeRollDegree
+grenadeRollRadius
+grenadeRollingEnabled
+grenadeUseRigidBodyPhysics
+grenadeVelocityDampFactor
+grenadeWaterFrictionHigh
+grenadeWaterFrictionLow
+grenadeWaterFrictionThresh
+grenadeWobbleFreq
+grenadeWobbleFwdMag
+grenadeWobbleSideDamp
+grenadeWobbleSideMag
+grenade_indicators_enabled
+grenade_waterDebug
+grenade_waterEnterRotationScalar
+grenade_waterEnterScalar
+grenade_waterExitRotationScalar
+grenade_waterExitScalar
+grenade_waterSpawnRotationScalar
+grenade_waterSpawnScalar
+groupCountsVisible
+groupDownloadInterval
+groupUploadInterval
+groupZeroCountsVisible
+groups_admins_refresh_time
+groups_applications_refresh_time
+groups_enabled
+groups_invites_refresh_time
+groups_presence_refresh_time
+groups_quickjoin_players_refresh_time
+groups_self_groups_refresh_time
+groups_service_failure_backoff_time
+groups_wait_on_dw
+gts_validation_enabled
+gunXPGroups
+gunsmithVersion
+gunsmith_enable_toggle_variant
+gunsmith_enabled
+gunsmith_totalvariants
+h
+hackMultiLauncherHorizontalOffset
+hackMultiLauncherVerticleOffset
+hackerTool_debug
+hatch_check_enable
+hatch_mantle_fwd
+hatch_mantle_up
+hiDef
+highlightedPlayerName
+hkai_actorClampToNavMeshFudgeFactor
+hkai_additionalPathfindIterationLimit
+hkai_badPlaceEdgeCostMultiplier
+hkai_debugActors
+hkai_debugAvoidanceCollisionPenalty
+hkai_debugAvoidanceDodgingPenalty
+hkai_debugAvoidanceGoalDistToleranceScale
+hkai_debugAvoidanceLeftTurnRadiusScale
+hkai_debugAvoidanceMaxAccel
+hkai_debugAvoidanceMaxDecel
+hkai_debugAvoidanceMaxNeighbors
+hkai_debugAvoidanceMaxSpeed
+hkai_debugAvoidanceMinSpeed
+hkai_debugAvoidancePenetrationPenalty
+hkai_debugAvoidanceRadius
+hkai_debugAvoidanceRightTurnRadiusScale
+hkai_debugAvoidanceSensorSizeScale
+hkai_debugAvoidanceSidednessChangingPenalty
+hkai_debugAvoidanceVelocityHysteresis
+hkai_debugAvoidanceWallFollowingAngle
+hkai_debugBadPlaces
+hkai_debugCharacterParameters
+hkai_debugCharacters
+hkai_debugCornerPredictor
+hkai_debugFailedPathFind
+hkai_debugManualControl
+hkai_debugObstacleSizeScale
+hkai_debugObstacles
+hkai_debugPointNearBoundary
+hkai_debugPositionQuery
+hkai_debugPositionqueryPerformance_cellLength
+hkai_debugPositionqueryPerformance_faceLength
+hkai_debugTurnRate
+hkai_debugTurnVelocityScale
+hkai_deferredPathfindsEnabled
+hkai_dumpMemoryLeaks
+hkai_maxClearanceRecalcFaces
+hkai_maxPathLengthChecksEnabled
+hkai_maxPathLengthMultiplier
+hkai_navMeshTriggersEnabled
+hkai_navMeshUseHierarchialPathFind
+hkai_pathfindIterationLimit
+hkai_recordWorldAndPath
+hkai_recordWorldAndPathTimeLimit
+hkai_repathUsingIncompleteRepathSegments
+hkai_resetTimers
+hkai_showTimers
+hkai_stairsEdgeCostMultiplier
+hkai_storeClearanceRecalcStats
+hkai_storePathfindResults
+hkai_timerTestActive
+hkai_warnPathFindFailures
+hkai_warningPopupsEnabled
+hls_anti_dos_sites
+hls_anti_dos_time
+hls_audio_volume
+hls_debug_draw
+hls_quality
+hls_quality_autodetected
+hls_quality_available
+hls_reserved_bandwidth
+hls_start_offset
+hopper_enabled
+hostileNameFontColor
+hostileNameFontGlowColor
+httpnetfs
+hudElemPausedBrightness
+hud_deathQuoteFadeTime
+hud_enable
+hud_fade_ammoDisplay
+hud_fade_compass
+hud_fade_healthbar
+hud_fade_offhand
+hud_fade_stance
+hud_fade_vehiclecontrols
+hud_flash_period_offhand
+hud_flash_time_offhand
+hud_healthOverlay_phaseEnd_fromAlpha
+hud_healthOverlay_phaseEnd_pulseDuration
+hud_healthOverlay_phaseEnd_toAlpha
+hud_healthOverlay_phaseOne_pulseDuration
+hud_healthOverlay_phaseOne_toAlphaAdd
+hud_healthOverlay_phaseThree_pulseDuration
+hud_healthOverlay_phaseThree_toAlphaMultiplier
+hud_healthOverlay_phaseTwo_pulseDuration
+hud_healthOverlay_phaseTwo_toAlphaMultiplier
+hud_healthOverlay_pulseStart
+hud_healthOverlay_pulseStop
+hud_healthOverlay_regenPauseTime
+hud_health_startpulse_injured
+i
+ik_ai_hand_get_data
+ik_ai_hand_offset_vec
+ik_ai_hand_rotation_vec
+ik_ai_hand_tuning
+ik_ai_pool_size
+ik_ai_range_max
+ik_debug
+ik_dvar_ai_aim_tracking_rate
+ik_dvar_lookatentity_eyes_scale
+ik_dvar_lookatentity_notorso
+ik_dvar_lookatentity_tracking_rate
+ik_dvar_lookatpos_eyes_scale
+ik_dvar_lookatpos_notorso
+ik_dvar_lookatpos_tracking_rate
+ik_enable
+ik_enable_ai_hand
+ik_enable_ai_terrain
+ik_enable_player_hand
+ik_enable_player_terrain
+ik_foot_test
+ik_hand_test
+ik_left_hand_lerp_test
+ik_lookatentity_head_scale
+ik_lookatpos_head_scale
+ik_paranoid_matrix_checks
+ik_pelvis_test
+ik_pitch_limit_max
+ik_pitch_limit_thresh
+ik_right_hand_lerp_test
+ik_roll_limit_max
+ik_roll_limit_thresh
+ik_yaw_limit_max
+ik_yaw_limit_thresh
+in_mouse
+incentive_rare_drop_id
+incentive_weapon_drop_id
+initial_cod_points_id
+interactivePromptAnimLen
+interactivePromptNearToDist
+interactivePromptNextToDist
+inventory_blocking
+inventory_enabled
+inventory_fakeExtraSlots
+inventory_fakeFail
+inventory_fetch_cooloff
+inventory_itemsPerPage
+inventory_maxPages
+inventory_retry_delay
+inventory_retry_max
+inventory_test_button_visible
+invited
+item_exclusion_0
+join_agreementWindow
+join_completionWindow
+join_devHostBusyChance
+join_devSloMo
+join_devSloMoFrame
+join_handshakeWindow
+join_infoProbeWindow
+join_reservationWindow
+join_retryCount
+join_retryDelay
+juke_air_accel
+juke_air_enabled
+juke_air_frictionMax
+juke_air_frictionMin
+juke_air_maxUpwardsVelocity
+juke_air_speed
+juke_air_upBoostAccel
+juke_anim_offset
+juke_blur_amount
+juke_blur_enabled
+juke_blur_radius_inner
+juke_blur_radius_outer
+juke_blur_time_in
+juke_blur_time_out
+juke_buttonup_jump
+juke_buttonup_sprint
+juke_clearance_check_dist
+juke_clearance_check_radius
+juke_cybercom
+juke_debug
+juke_debug_distance
+juke_enabled
+juke_forward_no_stick_input
+juke_fx_enabled
+juke_ms_for_deceleration
+juke_ms_to_fullspeed
+juke_player_trace_offset
+juke_programmatic_animation
+juke_rumble_enabled
+juke_slide_enabled
+juke_snap_angle_backward
+juke_snap_angle_forward
+juke_snap_angle_side
+juke_speed
+juke_sprintspeedratio
+juke_stick_intensity_threshold
+juke_time_ms
+juke_wallrun_enabled
+juke_weapon_angles_backward
+juke_weapon_angles_forward
+juke_weapon_angles_left
+juke_weapon_angles_right
+juke_weapon_side_movement
+jump_height
+jump_ladderPushVel
+jump_max_velocity
+jump_slowdownEnable
+jump_spreadAdd
+jump_stepSize
+key_bindsDebug
+keyarchiveWriteDelay
+kick
+kill
+killOnlyTrailFX
+killserver
+ks_emp_ammowidget_maxRadiusMinStatic
+ks_emp_ammowidget_maxStaticValue
+ks_emp_ammowidget_minRadiusMaxStatic
+ks_emp_ammowidget_minStaticValue
+ks_emp_fullscreen_maxRadiusMinStatic
+ks_emp_fullscreen_maxStaticValue
+ks_emp_fullscreen_minRadiusMaxStatic
+ks_emp_fullscreen_minStaticValue
+ks_emp_minimap_maxRadiusMinStatic
+ks_emp_minimap_maxStaticValue
+ks_emp_minimap_minRadiusMaxStatic
+ks_emp_minimap_minStaticValue
+ks_emp_scorewidget_maxRadiusMinStatic
+ks_emp_scorewidget_maxStaticValue
+ks_emp_scorewidget_minRadiusMaxStatic
+ks_emp_scorewidget_minStaticValue
+laggedDamageTagThreshold
+lagometer_pos
+landing_crouchViewDip
+language
+laserAlpha
+laserDebug
+laserFadeADS
+laserFlarePct
+laserForceOn
+laserKillImpactDelta
+laserLightBeginOffset
+laserLightBodyTweak
+laserLightEndOffset
+laserLightRadius
+laserLightRadius_alt
+laserLightRangePlayer
+laserRadius
+laserRadius_alt
+lastStandSwayAccel
+lastStandSwayMaxDrift
+lastStandSwayMaxDriftVel
+lastStand_cameraAlignmentEaseMode
+lastStand_cameraPitchOffset
+lastStand_cameraRotateTimeMs
+launchGame
+lbTaskDelay
+leaveWithPartyEnabled
+listallassets
+listassetpool
+listcustomgametypes
+listdefaultassets
+liveDedicatedOnly
+liveDedicatedonly
+liveNeverHostServer
+liveNewsMaxCounters
+liveSessionTaskTimeoutCreate
+liveSessionTaskTimeoutDelete
+liveSessionTaskTimeoutSearch
+liveSessionTaskTimeoutUpdate
+liveVoteErrorBackoff
+liveVoteTaskDelay
+live_CODPointCheckRequired
+live_LPCFFOTDMode
+live_allowDisconnectOnSignOut
+live_anticheatBoostingPolicy
+live_anticheatGlitchingPolicy
+live_anticheatLootRecoveryPolicy
+live_anticheatOffensiveBehaviorPolicy
+live_anticheatOffensiveUGCPolicy
+live_anticheatPeripheralsPolicy
+live_anticheatPiracyPolicy
+live_anticheatThirdPartyPolicy
+live_anticheatUnlockableContentPolicy
+live_autoEventEnabled
+live_autoEventPumpDelay
+live_autoEventPumpTime
+live_connect_mode
+live_connectionStatusChange_timeout
+live_debugDailyChallengesDay
+live_debugDailyChallengesHour
+live_debugDailyChallengesMinute
+live_dedicatedLookForPlatformPlaylists
+live_disconnected_timeout
+live_enableCounters
+live_enableDailyChallengeUpdate
+live_enableDailyChallengesDebugTimestamp
+live_enablePolls
+live_exchange_enable
+live_exchange_enableErrorMessages
+live_exchange_enableExchangeFailureTracking
+live_exchange_enableTracking
+live_exchange_processProductAttempts
+live_exchange_processProductInterval
+live_exchange_processProductIntervalMultiplier
+live_experimentsEnabled
+live_fakeReportConsoleFailure
+live_featuredEnabled
+live_friends_batch_size
+live_friends_enabled
+live_friends_features
+live_friends_max
+live_friends_sort
+live_friends_unified
+live_friends_update_interval
+live_groups_min_task_callback_ms
+live_inSyncDDLsRequired
+live_leaderboardResetTime
+live_leaderboardisRowEmptyCheck
+live_motdEnabled
+live_newsAddOwnNewsToTicker
+live_presence_debug
+live_presence_features
+live_presence_incremental_fail_delay
+live_presence_max_ms_between_updates
+live_presence_min_ms_between_updates
+live_presence_party
+live_presence_platform
+live_pubSemaphoreCheckIntervalSeconds
+live_pubSemaphoreForceChange
+live_pubSemaphoreJitterSeconds
+live_pubSemaphoreUserTriggerTime
+live_publishervariables_maxupdateattempts
+live_readPublisherStorageLocally
+live_readSplitFfotd
+live_readUserStorageLocally
+live_registrationEndURL
+live_registrationEndURL_DEV
+live_registrationEndURL_RETAIL
+live_registrationStartURL
+live_registrationStartURL_DEV
+live_registrationStartURL_RETAIL
+live_social_quickjoin
+live_social_quickjoin_cache
+live_social_quickjoin_count
+live_statscaching
+live_steam_server_client_checks_interval
+live_steam_server_description
+live_steam_server_name
+live_steam_server_password
+live_store_disable_lang
+live_store_disable_region
+live_store_enable
+live_store_enable_inventory
+live_store_entitlementcheck_enable
+live_store_show_details
+live_systemSurveyCaptureDelta
+live_systemsurvey
+live_testValue
+live_timewarp
+live_umbrella_maxUmbrellaLoginAttempts
+live_useInGameRegistration
+live_useLPC
+live_usePublisherVariables
+live_useUmbrella
+live_useUno
+live_username
+live_whitelistFatal
+livestats_checkNonPrimaryXUIDPS3
+livestats_giveCPXP
+livestats_skipFirstTime
+livestorage_fakeNoob
+livestorage_waitOnContent
+livestorage_waitOnContentTimeout
+loadoutVersion
+loadoutVersionCP
+loadoutVersionMP
+loadoutVersionZM
+lobbyAdvertiseConfig
+lobbyAdvertiseDirty
+lobbyAdvertiseEmptySlots
+lobbyAdvertiseGameType
+lobbyAdvertiseGeo1
+lobbyAdvertiseGeo2
+lobbyAdvertiseGeo3
+lobbyAdvertiseGeo4
+lobbyAdvertiseIsEmpty
+lobbyAdvertiseLatencyBand
+lobbyAdvertiseMap
+lobbyAdvertiseMapPacks
+lobbyAdvertiseMaxPlayers
+lobbyAdvertiseNetcodeVersion
+lobbyAdvertiseNumPlayers
+lobbyAdvertisePin
+lobbyAdvertisePlaylistNumber
+lobbyAdvertisePlaylistVersion
+lobbyAdvertiseServerLocation
+lobbyAdvertiseServerName
+lobbyAdvertiseServerType
+lobbyAdvertiseShowInMatchmaking
+lobbyAdvertiseSkill
+lobbyAdvertiseSkip
+lobbyAdvertiseTeamSizeMax
+lobbyCPTimerStartInterval
+lobbyCPZMTimerStartInterval
+lobbyDebugLogJoinSuccess
+lobbyDebugLogJoins
+lobbyDedicatedSearchSkip
+lobbyLaunch_fadeToBlackDelay
+lobbyLaunch_fadeToBlackDelayOnConnect
+lobbyLaunch_gameLaunchDelay
+lobbyLaunch_gameLaunchDelayOnConnect
+lobbyLaunch_waitForClientAckDelay
+lobbyMapVotePrevMapPlayCount
+lobbyMergeDedicatedEnabled
+lobbyMergeEnabled
+lobbyMergeInterval
+lobbyMigrate_Enabled
+lobbyMigrate_EnabledLAN
+lobbyMigrate_considerStreamingForHostMigration
+lobbyMigrate_dedicatedOnly
+lobbyMigrate_migrateToBestGameHostEnabled
+lobbyProbedXuidOverride
+lobbySearchBaseSkillRange
+lobbySearchDatacenterType
+lobbySearchDatacenterTypeGeo
+lobbySearchDatacenterTypeOverride
+lobbySearchDediUnparkPingLimit
+lobbySearchDedicatedGeoMin
+lobbySearchDelay
+lobbySearchExperimentDatacenter
+lobbySearchForceLocation
+lobbySearchForceUnparkLobbySize
+lobbySearchForceXuid
+lobbySearchGameSecurityId
+lobbySearchGeo1
+lobbySearchGeo1Weight
+lobbySearchGeo2
+lobbySearchGeo2Weight
+lobbySearchGeo3
+lobbySearchGeo3Weight
+lobbySearchGeo4
+lobbySearchGeo4Weight
+lobbySearchGeoMin
+lobbySearchIsEmpty
+lobbySearchMapPacks
+lobbySearchMaxLatencyBandDiff
+lobbySearchMinDediSearchClientAdd
+lobbySearchMinDediSearchTime
+lobbySearchNetcodeVersion
+lobbySearchPingBand
+lobbySearchPingBandEnabled
+lobbySearchPingBandWeight1
+lobbySearchPingBandWeight2
+lobbySearchPingBandWeight3
+lobbySearchPingBandWeight4
+lobbySearchPingBandWeight5
+lobbySearchPlaylistNumber
+lobbySearchPlaylistVersion
+lobbySearchQueryId
+lobbySearchServerLocation1
+lobbySearchServerLocation2
+lobbySearchServerLocation3
+lobbySearchServerLocation4
+lobbySearchServerLocation5
+lobbySearchServerType
+lobbySearchShowInMatchmaking
+lobbySearchSkill
+lobbySearchSkillRangeMultiplier
+lobbySearchSkillWeight
+lobbySearchSkip
+lobbySearchSkipDLCProbability
+lobbySearchSkipUnparkProbability
+lobbySearchTeamSize
+lobbyTimerStartInterval
+lobbyTimerStatusBeginInterval
+lobbyTimerStatusPostGameInterval
+lobbyTimerStatusStartInterval
+lobbyTimerStatusVotingInterval
+lobbyTimerStatusVotingInterval_Arena
+lobbyTimerZMStartInterval
+lobby_MatchmakingLoggingChance
+lobby_MatchmakingLoggingLevel
+lobby_ban
+lobby_beginPlay
+lobby_clientContentTimeout
+lobby_clientEndCooloffTime
+lobby_clientEndFakeSendLoss
+lobby_clientLoadingIntoUICheck
+lobby_clientTimeout
+lobby_clientWarnTimeout
+lobby_enableLoadoutDataStreamingInGame
+lobby_enablePSDataStreamingInGame
+lobby_enablePSDataStreamingInLobby
+lobby_fillserverlist
+lobby_forceLAN
+lobby_forceOffline
+lobby_hostBots
+lobby_hostContentTimeout
+lobby_hostIntervalHeartbeat
+lobby_hostIntervalState
+lobby_hostJoinRequestReject
+lobby_hostPSFragmentRetryInterval
+lobby_hostTimeout
+lobby_ingamePSDataStreamingBW
+lobby_kick
+lobby_list
+lobby_maxLocalPlayers
+lobby_moveLobby
+lobby_nextmap
+lobby_ptptimeout
+lobby_readyUpPercentRequired
+lobby_setgametype
+lobby_setmap
+lobby_showSVDebug
+lobby_unban
+lobbymigrate_HostWaitMS
+lobbymigrate_MaxBWPackets
+lobbymigrate_MaxPacketWaitTime
+lobbymigrate_MinScoreDiff
+lobbymigrate_NomineeRecalcInterval
+lobbymigrate_NomineeWaitMS
+lobbymigrate_TestInterval
+lobbymigrate_TestIntervalJitter
+lobbymigrate_WirelessLatencyIncrease
+lobbymigrate_useStdDev
+lobbymsg_prints
+lobbyvm_forceGC
+loc_availableLanguages
+loc_forceEnglish
+loc_language
+loc_languageSaved
+loc_systemLanguage
+loc_translate
+loc_warnings
+loc_warningsAsErrors
+local_media_tier
+log_append
+log_filename
+logfile
+long_blocking_call
+loot_bribeCrate_dwid
+loot_burnBatchSize
+loot_burnCommonRefund
+loot_burnCooloff
+loot_burnEpicRefund
+loot_burnLegendaryRefund
+loot_burnMinMegaRequired
+loot_burnMinRareRequired
+loot_burnMinUltraRequired
+loot_burnRareRefund
+loot_burnRefetchOnSuccess
+loot_commonCrate_dwid
+loot_cryptoCheckDelay
+loot_cryptokeyCost
+loot_cryptokeySku
+loot_earnMax
+loot_earnMin
+loot_earnPlayThreshold
+loot_earnTime
+loot_emblems_max_count
+loot_enabled
+loot_experimentpromo_active
+loot_fakeAll
+loot_fakeItem
+loot_fakeNoBonus
+loot_fakeRarity
+loot_missedIMChance
+loot_mpItemVersions
+loot_rareCrate_dwid
+loot_recipe_distill_cost
+loot_taskMaxAttempts
+loot_taskWindow
+loot_testAll
+loot_testIndex
+loot_winBonusPercent
+loot_zmItemVersions
+lootxp_bonus_multiplier
+lootxp_multiplier
+lowAmmoWarningPulseFreq
+lowAmmoWarningPulseMax
+lowAmmoWarningPulseMin
+lpc_forceDownloadFiles
+lpc_maxattempts
+ls_demoauthor
+ls_demoduration
+ls_demotitle
+ls_gametype
+ls_maplocation
+ls_mapname
+ls_status
+lua_systemTest
+lunge_blur_amount
+lunge_blur_enabled
+lunge_blur_radius_inner
+lunge_blur_radius_outer
+lunge_blur_time_in
+lunge_blur_time_out
+lunge_debug
+m_filter
+m_forward
+m_mouseAcceleration
+m_mouseFilter
+m_mouseSensitivity
+m_pitch
+m_side
+m_yaw
+magic_chest_movable
+manifestfs
+mantle_adjustment_mp
+mantle_check_angle
+mantle_check_glass_extra_range
+mantle_check_radius
+mantle_check_range
+mantle_check_range_mp
+mantle_debug
+mantle_enable
+mantle_enabled
+mantle_view_yawcap
+mantle_weapon_anim_height
+mantle_weapon_height
+map
+map_restart
+map_rotate
+mapcrc
+mapname
+marketing_autorefresh
+marketing_enabled
+marketing_refreshTime
+marketing_simulatefakemotd
+marketing_waitTimeOnLogin
+matchmaking_debug
+maxAIGlassHits
+maxAttachmentsPerWeapon
+maxDailyZMDoubleXP
+maxGlassShatters
+maxLossesValue
+maxMetPlayerListCount
+maxShardSplit
+maxSplitSizeRatio
+maxStatsBackupInterval
+maxVoicePacketsPerFrame
+melee_allowQueuedMelee
+melee_attachmentMultiplier
+melee_cameraSway_enabled
+melee_debug
+melee_debug_fromBehind
+melee_fromBehindDebug
+melee_fromBehindMaxAngle
+melee_fromBehindUseBonesForDirection
+melee_maxAutoPitch
+melee_maxAutoYaw
+melee_victimCamSwayAngle
+melee_victimCameraLerpTime
+melee_victimEffectDuration
+melee_victimMoveScale
+melee_victimPitchSpeed
+melee_victimTransScale
+melee_victimYawSpeed
+menuMapMaxRange
+metPlayerInGameOnly
+metPlayerListCleanupInterval
+metPlayerListRemoveFriends
+metPlayerListUpdateInterval
+metPlayerListUploadInterval
+metPlayerPlatformGamertag
+metPlayerPlatformPresence
+microwave_turret_placement_trace_maxs
+microwave_turret_placement_trace_mins
+microwave_turretplacement_traceOffset
+migrating
+migration_blocksperframe
+migration_forceHost
+migration_limit
+migration_minclientcount
+migration_msgtimeout
+migration_soak
+migration_timeBetween
+minDelayForOtherPlayerStatsFetch
+miniscoreboardhide
+missileDebugAttractors
+missileDebugDraw
+missileDebugText
+missileDroneAccelClimb
+missileDroneAccelDescend
+missileDroneClimbAngleDirect
+missileDroneClimbAngleTop
+missileDroneClimbCeilingDirect
+missileDroneClimbCeilingTop
+missileDroneClimbHeightDirect
+missileDroneClimbHeightTop
+missileDroneClimbMaxDist
+missileDroneClimbToOwner
+missileDroneDistSqTargetAvoidanceDisabled
+missileDroneDistanceAvoidance
+missileDroneDistanceAvoidanceSec
+missileDroneSpeedLimitClimb
+missileDroneSpeedLimitDescend
+missileDroneSpeedMin
+missileDroneTurnDecel
+missileDroneTurnMaxRate
+missileDroneTurnMaxRoll
+missileDroneTurnMaxRollChange
+missileDroneTurnRateAscent
+missileDroneTurnRateAvoidance
+missileDroneTurnRateDecent
+missileDroneTurnRateSmallAdjustments
+missileDroneflattenRollRatio
+missileHellfireMaxSlope
+missileHellfireUpAccel
+missileJavAccelClimb
+missileJavAccelDescend
+missileJavClimbAngleDirect
+missileJavClimbAngleTop
+missileJavClimbCeilingDirect
+missileJavClimbCeilingTop
+missileJavClimbHeightDirect
+missileJavClimbHeightTop
+missileJavClimbToOwner
+missileJavSpeedLimitClimb
+missileJavSpeedLimitDescend
+missileJavTurnDecel
+missileJavTurnRateDirect
+missileJavTurnRateTop
+missileMolotovBlobNum
+missileMolotovBlobTime
+missilePlantableSize
+missileSoftLaunchSpeedScale
+missileTVGuidedBoost
+missileTVGuidedBoostSpeedDown
+missileTVGuidedBoostSpeedUp
+missileTVGuidedFlatteningRollAccel
+missileTVGuidedMPSpecific
+missileTVGuidedMaxRollAngle
+missileTVGuidedStickDeadzone
+missileTVGuidedTurnRate
+missileTVGuidedTurningRollAccel
+missingCommandWillError
+mlg_active_stream_query_interval
+mlg_audio_volume
+mlg_client_id
+mlg_config_query_interval
+mlg_enable
+mlg_google_analythics_id
+mlg_google_analythics_perc
+mlg_google_analythics_url
+mlg_inactive_stream_query_interval
+mlg_league
+mlg_metadata_title_entry
+mlg_min_islive_interval
+mlg_mixpanel_token
+mlg_mixpanel_url
+mlg_platform_name
+mlg_show_hidden
+mm_KeyframeMeterDebug
+mm_KeyframeUsageDebug
+mm_KeyframeUsageReset
+mm_animation_driven_movement
+mm_debug
+mm_debugKeyframe
+mm_doLegYawOffset
+mm_enable
+mm_inputSet
+mm_keyframeInterval
+mm_keyframeMeterIsClient
+mm_keyframeMeter_clientNum
+mm_keyframeMeter_pos
+mm_keyframeUsageAnimIndex
+mm_keyframeUsage_pos
+mm_optimizations
+mm_simulateClientPmoves
+modPrvAnimDumpInTime
+modPrvAnimDumpOutTime
+modPrvCurrAndMaxFrameIndexes
+modPrvUseAnimDump
+mods_DisableStats
+mods_SavePlayerBindingsToMod
+mods_enabled
+modvar
+mortarStrikesLeft
+motdDelay
+motd_enabled
+mp_blackjack_consumable_wait
+mp_prototype
+msg_dumpEnts
+msg_hudelemspew
+msg_logPredictionPositionErrors
+msg_printEntityNums
+msg_zlibCompress
+msg_zlibCompressOutput
+n
+name
+narrowShardRatio
+neo_PTELimit
+net_broadcast
+net_broadcast_ip
+net_debug_server_time_error
+net_emu_client
+net_emu_jitter
+net_emu_latency
+net_emu_packet_loss
+net_emu_server
+net_ip
+net_logSnapshotTiming
+net_minigraph
+net_noudp
+net_port
+net_profile
+net_showprofile
+net_socksEnabled
+net_socksPassword
+net_socksPort
+net_socksServer
+net_socksUsername
+netchan_ackInterval
+netchan_debugSpew
+netchan_debugSpewChan
+netchan_doSwap
+netchan_drawGraph
+netchan_dropFragChance
+netchan_emergencyFreePercent
+netchan_fakeLoad
+netchan_firstAckWait
+netchan_jqprofEnabled
+netchan_jqprofThreshold
+netchan_logToFile
+netchan_mainThreadWaitMs
+netchan_msgLifeTime
+netchan_nackWaitMs
+netchan_statsResetInterval
+netfieldchk
+netstats_dummy_tracker_data
+nextarena
+nextmap
+noCheapSpawns
+noDW
+noai
+noclip
+notarget
+nv_textureReleaseFrameDelay
+nv_textureReleaseMaxPerFrame
+oldShotgunSpread
+onlinegame
+onlykick
+oob_damage_interval_ms
+oob_damage_per_interval
+oob_max_distance_before_black
+oob_time_remaining_before_black
+oob_timekeep_ms
+oob_timelimit_ms
+orbisGame
+orbis_PTELimit
+orbis_authBypass
+orbis_checkpsn_interval
+orbis_checkpsplus_interval
+orbislive_reduceCheckNetConnection
+p
+packetDebug
+paintjobVersion
+partyChatDisallowed
+partyMigrate_NomineeRecalcInterval
+partyMigrate_TestInterval
+partyMigrate_maxBWPackets
+partyPrivacyCheckInterval
+partyPrivacyEnabled
+partyPrivacyPumpEnabled
+party_autoteams
+party_debug
+party_debugMembers
+party_maxplayers
+party_minplayers
+party_reliableMigrate
+password
+path_alwaysFindNearestNode
+path_boundsFudge
+path_checkDangerousNodes
+path_double_wide_checks
+path_minzBias
+pc_newversionavailable
+pcache_privacy
+pclive_updateFriends
+penetrationCount
+penetrationCount_allies
+penetrationCount_axis
+perk_armorPiercing
+perk_armorVest
+perk_armorpiercing
+perk_blackbirdShowsGpsJammer
+perk_bulletDamage
+perk_bulletPenetrationMultiplier
+perk_damageKickReduction
+perk_deathStreakCountRequired
+perk_delayExplosiveTime
+perk_directionalfire_clipped_show_direction
+perk_disarmExplosiveTime
+perk_dogsAttackGhost
+perk_extraBreath
+perk_fastLadderClimbMultiplier
+perk_fireproof
+perk_flakJacket
+perk_flakJacket_hardcore
+perk_gpsjammer_alpha
+perk_gpsjammer_fade_time
+perk_gpsjammer_graceperiods
+perk_gpsjammer_min_distance
+perk_gpsjammer_min_speed
+perk_gpsjammer_time_period
+perk_grenadeDeath
+perk_grenadeTossBackTimer
+perk_healthRegenMultiplier
+perk_interactSpeedMultiplier
+perk_killstreakAnteUpResetValue
+perk_killstreakDeathPenaltyMultiplier
+perk_killstreakMomentumMultiplier
+perk_killstreakReduction
+perk_mantleReduction
+perk_marksmanEnemyNameFadeIn
+perk_marksmanEnemyNameFadeOut
+perk_nottargetedbyai_graceperiod
+perk_nottargetedbyai_min_speed
+perk_requireScavengerPerk
+perk_scavenger_clip_multiplier
+perk_scavenger_lethal_proc
+perk_scavenger_tactical_proc
+perk_sgjammer_alpha
+perk_sgjammer_fade_time
+perk_sgjammer_graceperiods
+perk_sgjammer_min_distance
+perk_sgjammer_min_speed
+perk_sgjammer_time_period
+perk_shellShockReduction
+perk_spawn_ping_duration_ms
+perk_speedMultiplier
+perk_sprintFireRecoveryMultiplier
+perk_sprintMultiplier
+perk_sprintMultiplierExtra
+perk_sprintRecoveryMultiplier
+perk_throwbackInnerRadius
+perk_tracker_fx_fly_height
+perk_tracker_fx_foot_height
+perk_weapAdsMultiplier
+perk_weapEquipmentUseMultiplier
+perk_weapMeleeMultiplier
+perk_weapRateMultiplier
+perk_weapReloadMultiplier
+perk_weapSpreadMultiplier
+perk_weapSwitchMultiplier
+perk_weapTossMultiplier
+phys_ai_collision_mode
+phys_bulletSpinScale
+phys_bulletUpBias
+phys_buoyancy
+phys_buoyancyDistanceCutoff
+phys_buoyancyFastComputation
+phys_buoyancyFloatHeightOffset
+phys_buoyancyRippleFrequency
+phys_buoyancyRippleVariance
+phys_debugBigQueries
+phys_debugCallback
+phys_debugDangerousRigidBodies
+phys_debugExceededGjkPrims
+phys_debugExpensivePushout
+phys_disableEntsAndDynEntsCollision
+phys_dragAngular
+phys_dragLinear
+phys_drawCollisionObj
+phys_drawConstraints
+phys_drawNitrousVehicle
+phys_drawNitrousVehicleEffects
+phys_drawNitrousVehicleEngine
+phys_drawcontacts
+phys_entityCollision
+phys_floatTimeVariance
+phys_fluid
+phys_gravity
+phys_gravity_dir
+phys_impact_distance_cutoff
+phys_impact_fx
+phys_impact_intensity_limit
+phys_impact_max_pfx_per_frame
+phys_impact_max_sfx_per_frame
+phys_impact_render
+phys_impact_silence_window
+phys_maxFloatTime
+phys_msecStep
+phys_piecesSpawnDistanceCutoff
+phys_player_collision_adjust_height
+phys_player_collision_mode
+phys_player_step_on_actors
+phys_player_step_on_actors_zm
+phys_ragdoll_buoyancy
+phys_ragdoll_joint_damp_scale
+phys_reeval_frequency
+phys_usePhysicsForLocalClientIfPossible
+phys_userRigidBodies
+phys_vehicleDamageFroceScale
+phys_vehicleFriction
+phys_vehicleGravityMultiplier
+phys_vehicleWheelEntityCollision
+phys_verbose
+phys_waterDragAngular
+phys_waterDragLinear
+phys_wind_debug
+phys_wind_distance_cutoff
+phys_wind_enabled
+phys_wind_force_direction
+phys_wind_force_speed
+phys_wind_vehicle_scale
+pickShards
+pickupPrints
+pitchAccelerationTime
+pitchDecelerationThreshold
+platformSessionDebugInfo
+platformSessionEnabled
+platformSessionImg
+platformSessionImgPath
+platformSessionInviteMessage
+platformSessionLaunchInviteJoinProcessDelay
+platformSessionName
+platformSessionOrbisCreateTimeout
+platformSessionOrbisGetInviteInfoTimeout
+platformSessionOrbisGetSessionInfoTimeout
+platformSessionOrbisImg
+platformSessionOrbisImgPath
+platformSessionOrbisInviteMessage
+platformSessionOrbisInviteTimeout
+platformSessionOrbisJoinTimeout
+platformSessionOrbisLeaveTimeout
+platformSessionOrbisLockFlag
+platformSessionOrbisMigrationFlag
+platformSessionOrbisName
+platformSessionOrbisSearchTimeout
+platformSessionOrbisSessionTypeFlag
+platformSessionOrbisStatus
+platformSessionOrbisUpdateTimeout
+platformSessionPartyPrivacy
+platformSessionShowErrorCodes
+platformSessionStatus
+platformSessionUpdateIntervalOrbis
+platformSessionsOrbis
+platformSessionsOrbisPlayTogetherEnabled
+playedWithUpdateInterval
+playerCount
+playerEnenergy_enabled
+playerEnergy_EMPAffectsBoost
+playerEnergy_EMPDrain
+playerEnergy_boostUpRate
+playerEnergy_boostUpRate_emp
+playerEnergy_boostUpRate_fast
+playerEnergy_doubleJumpCostRatio
+playerEnergy_enabled
+playerEnergy_jukeCostRatio
+playerEnergy_jukeEnergyEnabled
+playerEnergy_maxReserve
+playerEnergy_minReserve
+playerEnergy_rechargeDuringSprint
+playerEnergy_restRate
+playerEnergy_restRate_emp
+playerEnergy_restRate_fast
+playerEnergy_restRate_sprint
+playerEnergy_restRate_sprintEmp
+playerEnergy_restRate_sprintFast
+playerEnergy_slideCostRatio
+playerEnergy_slideCostRatio_emp
+playerEnergy_slideEnergyEnabled
+playerEnergy_slowRechargeDuringSprint
+playerEnergy_sprintEnergyEnabled
+playerEnergy_sprintRate
+playerEnergy_sprintRate_emp
+playerEnergy_sprintRate_fast
+playerEnergy_sprintRechargeDelayMs
+playerEnergy_wallRunDelayMs
+playerEnergy_wallRunEnergyEnabled
+playerEnergy_wallRunRate
+playerJetEnergy_boostDownRate
+playerJetEnergy_boostUpRate
+playerJetEnergy_deployCost
+playerJetEnergy_enabled
+playerJetEnergy_hoverRate
+playerJetEnergy_maxReserve
+playerJetEnergy_minReserve
+playerJetEnergy_restRate
+playerJet_accel
+playerJet_downBoostAccel
+playerJet_enabled
+playerJet_frictionMax
+playerJet_frictionMin
+playerJet_fx_a
+playerJet_fx_b
+playerJet_fx_c
+playerJet_fx_d
+playerJet_hoverAccel
+playerJet_initHeight
+playerJet_preHoverAccel
+playerJet_speed
+playerJet_tag_left_back
+playerJet_tag_left_front
+playerJet_tag_right_back
+playerJet_tag_right_front
+playerJet_upBoostAccel
+playerJet_upSaveBoostAccel
+playerPushAmount
+playerSounds_rotationAngleThresholdLoop
+playerSounds_rotationAngleThresholdStep
+playerWeaponRaisePostIGC
+player_AimBlend_Back_Low
+player_AimBlend_Back_Mid
+player_AimBlend_Back_Up
+player_AimBlend_Head
+player_AimBlend_Neck
+player_AimBlend_Pelvis
+player_MGUseRadius
+player_ProneLaststandFreeMove
+player_ProneMinPitchDiff
+player_ZVelocityThresholdThirdPerson
+player_ZVelocityThreshold_fast
+player_ZVelocityThreshold_med
+player_ZVelocityThreshold_rapid
+player_ZVelocityThreshold_slow
+player_adsExitDelay
+player_animRunThreshhold
+player_animWalkThreshhold
+player_armPulseEnabled
+player_backSpeedScale
+player_bodylights
+player_bodylightsCorpseFadeTime
+player_bodylightshdr
+player_breath_fire_delay
+player_breath_gasp_lerp
+player_breath_gasp_scale
+player_breath_gasp_time
+player_breath_hold_lerp
+player_breath_hold_time
+player_breath_snd_delay
+player_breath_snd_lerp
+player_chestWaterFrictionScale
+player_clipSizeMultiplier
+player_deathInvulnerableTime
+player_debug
+player_debugHeadOffset
+player_debugHeadOffsetTolerance
+player_debugHealth
+player_debugSprint
+player_deepWaterWadeScale
+player_disableUnderwaterVisionset
+player_disableWeaponsInWater
+player_disableWeaponsOnVehicle
+player_dmgtimer_flinchTime
+player_dmgtimer_maxTime
+player_dmgtimer_minScale
+player_dmgtimer_stumbleTime
+player_dmgtimer_timePerPoint
+player_dpad_gadget_scheme
+player_enableShuffleAnims
+player_enduranceSpeedScale
+player_fallImpact_camImpact_enabled
+player_fallImpact_camLateralTranslateScale
+player_fallImpact_camSwingDuration
+player_fallImpact_camUpTranslateScale
+player_fallImpact_rumble_enabled
+player_fallImpact_shake_base_scale
+player_fallImpact_shake_duration
+player_fallImpact_shake_enabled
+player_fallImpact_viewMovementPitch
+player_fallImpact_viewMovementRoll
+player_fallImpact_viewMovementYaw
+player_fallWindZVelocityThreshold
+player_fallWindZVelocityThresholdThirdPerson
+player_fall_rumble_enabled
+player_firstPersonDeaths
+player_floatSpeed
+player_footstepsThreshhold
+player_forceGibs
+player_forceRedCrosshair
+player_idleToMoveAnimSpeed
+player_knockbackMoveThreshhold
+player_lastStandBleedoutTime
+player_lastStandBleedoutTimeNoRevive
+player_lastStandCrawlTransition
+player_lastStandDistScale
+player_lastStandHealthOverlayTime
+player_lastStandSuicideDelay
+player_lean_rotate
+player_lean_rotate_crouch
+player_lean_shift
+player_lean_shift_crouch
+player_lens_enabled
+player_lookAtEntityAllowChildren
+player_meleeChargeCancelOnVictimDeath
+player_meleeChargeFriction
+player_meleeChargeHeightTolerance
+player_meleeChargeMaxSpeed
+player_meleeChargeMinSpeed
+player_meleeHeight
+player_meleeHeightChargeAir
+player_meleeIdealEndDistance
+player_meleeInterruptFrac
+player_meleeLungeAcceleration
+player_meleeLungeDamageScalar
+player_meleeLungeDeviationCutoff
+player_meleeLungeSpeedCutoff
+player_meleeLungeTimeCutoff
+player_meleeLungeUnderwaterSpeedScale
+player_meleeRangeChargeAirDefault
+player_meleeRangeChargeDefault
+player_meleeRangeDefault
+player_meleeWidth
+player_meleeWidthChargeAir
+player_moveSoundThresholdAccel
+player_moveSoundThresholdDecel
+player_moveSoundThresholdRatio
+player_moveThreshhold
+player_move_factor_on_torso
+player_name
+player_revivePlayerListCycleTime
+player_reviveTriggerRadius
+player_runThreshhold
+player_runbkThreshhold
+player_scopeExitOnDamage
+player_shallowWaterFrictionScale
+player_shallowWaterHeightRatio
+player_shallowWaterWadeScale
+player_slick_accel
+player_slick_invspeed
+player_slick_wishspeed
+player_sliding_friction
+player_sliding_velocity_cap
+player_sliding_wishspeed
+player_slopeAnimAngle
+player_spectateSpeedScale
+player_sprintCameraBob
+player_sprintFallAnim
+player_sprintForwardMinimum
+player_sprintJumpAnimRate
+player_sprintJumpDropWeaponScaler
+player_sprintMinTime
+player_sprintRechargePause
+player_sprintSpeedScale
+player_sprintStrafeSpeedScale
+player_sprintTime
+player_sprintUnlimited
+player_standingViewHeight
+player_strafeAnimCosAngle
+player_strafeSpeedScale
+player_sustainAmmo
+player_swimAcceleration
+player_swimAllowGrenades
+player_swimAnimMinSpeed
+player_swimCombatOutADSStopAnimRatio
+player_swimDamage
+player_swimDamagerInterval
+player_swimFallOffAngle
+player_swimFocalLength
+player_swimFootstepWaterDuration
+player_swimForwardAnimCatchupMax
+player_swimForwardAnimCatchupMin
+player_swimForwardMinAngle
+player_swimForwardMinSpeed
+player_swimForwardSettleTime
+player_swimForwardWarmupTime
+player_swimFrictionHigh
+player_swimFrictionLow
+player_swimFrictionVerticalThreshold
+player_swimHeightRatio
+player_swimLensEnabled
+player_swimLensInTransRate
+player_swimMaxMovePitchWhileTreading
+player_swimMaxSprintPitchWhileTreading
+player_swimMaxZ
+player_swimMovementShellshockScale
+player_swimMovingAnimSpeed
+player_swimMovingStopAnimRatio
+player_swimSpeed
+player_swimSpeedupIdleAnimMinSpeed
+player_swimSprintAnimSpeed
+player_swimSprintFocalLength
+player_swimSprintLensEnabled
+player_swimSprintLensInTransRate
+player_swimSprintSpeedScale
+player_swimSprintStopAnimRatio
+player_swimSurfaceSmoothingDepth
+player_swimSurfaceSmoothingScalar
+player_swimTime
+player_swimUnderwaterHeightRatio
+player_swimVerticalAcceleration
+player_swimVerticalSpeedMax
+player_swimViewHeight
+player_swimWaterPlaneDistance
+player_swimallowshooting
+player_swimallowshootingmoving
+player_swimcantraverse
+player_swimforcesurface
+player_swimming_control_scheme
+player_swimming_enabled
+player_t7MeleeDeathFromAboveRange
+player_throwbackInnerRadius
+player_throwbackOuterRadius
+player_tmodeSightEnabled
+player_topDownCursorDist
+player_topDownCursorPos
+player_turnAnims
+player_turnRateScale
+player_underwaterWalkJumpHeight
+player_underwaterWalkSpeedScale
+player_underwaterWalkSprint
+player_underwatercantraverse
+player_useRadius
+player_useRadius_zm
+player_useSlopeAnims
+player_useTouchScore
+player_useWaterFriction
+player_useWaterWadeScale
+player_viewLockEnt
+player_viewRateScale
+player_view_pitch_down
+player_view_pitch_up
+player_view_swim_pitch_down
+player_view_swim_pitch_up
+player_waistWaterFrictionScale
+player_waistWaterWadeScale
+player_waterSpeedScale
+player_waterWadeScaleUnderwater
+player_zombieMeleeHeight
+player_zombieMeleeRange
+player_zombieMeleeWidth
+player_zombieSpeedScale
+player_zombieSprintSpeedScale
+playgo_profiling
+playgo_refreshinterval
+playlist_allowdevmaps
+playlist_autoEvent
+playlist_autoEventsEnabled
+playlist_autoevent
+playlist_debug
+playlist_excludeGametype
+playlist_excludeGametypeMap
+playlist_excludeMap
+playlist_forceEvent
+playlist_linearMapCycle
+playlist_linearMapCycleRandom
+popInLetterFXTime
+printCACValidationErrors
+printCACValidationSuccesses
+printentities
+probation_league_dashboardScalar
+probation_league_enabled
+probation_league_forgiveCount
+probation_league_kickScalar
+probation_league_kickcalar
+probation_league_matchHistoryWindow
+probation_league_probationThreshold
+probation_league_probationTime
+probation_league_quitScalar
+probation_league_timeoutScalar
+probation_league_warningThreshold
+probation_public_enabled
+probation_public_forgiveCount
+probation_public_kickScalar
+probation_public_matchHistoryWindow
+probation_public_probationThreshold
+probation_public_probationTime
+probation_public_quitScalar
+probation_public_timeoutScalar
+probation_public_warningThreshold
+probation_version
+prof_disableGameplayGfx
+prof_gameplayGfx
+prof_selectCameraPosition
+prof_selectCameraPositionTeleport
+profileDirtyInterval
+profileDwUpdateInterval
+profileGetInterval
+profile_reset
+profile_show_loading
+prone_bipod_enable
+prone_crawlLoopTime
+protocol
+ps3Game
+ps4_swapcirclex
+purchasedClassSetCount
+qosLocklessQueue
+qosMaxAllowedPing
+qosPreferredPing
+qos_echo_chance
+qos_firstUpdateMS
+qos_lastUpdateMS
+qos_maxProbeWait
+qos_minEchoServers
+qos_minPercent
+qos_minProbes
+qos_packetLossPercent
+qos_simulateLongQoS
+qport
+queue_actions_enabled
+quit
+quit_on_error
+r_DFE
+r_EOTF1886
+r_EOTFLb
+r_EOTFLw
+r_EOTFgamma
+r_FilmIsoMax
+r_FilmIsoMin
+r_FilmIsoNoise
+r_FilmIsoNoiseEnable
+r_LensAbbe
+r_LensDistortionGL
+r_LensDistortionK1
+r_LensDistortionK2
+r_LensDistortionK3
+r_LensDistortionKS
+r_LensOpticalLength
+r_MaterialParameterTweak
+r_OIT
+r_OIT_Debug
+r_OIT_MaxEntries
+r_POMLODEnd
+r_POMLODStart
+r_PurkinjeHue
+r_PurkinjeMax
+r_PurkinjeMin
+r_ST2084
+r_ST2084debug
+r_ST2084debugWipe
+r_ST2084debugWipeWhite
+r_ST2084debugWipeWhiteMeasure
+r_aaAllowTemporalMultiGpu
+r_aaTechnique
+r_aberrationFX_enable
+r_activeLensID
+r_actorShadowCount
+r_actorShadowFade
+r_addLightWorker
+r_adsBloomDownsample
+r_adsWorldFocalDistanceMax
+r_adsWorldFocalDistanceMin
+r_adsWorldFocalDistanceTrackBackScale
+r_alphaMap
+r_anaglyphFX_enable
+r_applyOIT
+r_asyncCompute
+r_atmosphere_densityM
+r_atmosphere_densityR
+r_atmosphere_enable
+r_atmosphere_groundLevel
+r_atmosphere_scatterG
+r_atmosphereextinctionstrength
+r_atmospherefogcolor
+r_atmospherefogdensity
+r_atmospherehazebasedist
+r_atmospherehazecolor
+r_atmospherehazedensity
+r_atmospherehazefadedist
+r_atmospherehazespread
+r_atmosphereinscatterstrength
+r_atmospherepbramount
+r_atmospheresunstrength
+r_autoLodCullRadius
+r_autoLodScale
+r_autoResolutionControllerIdle
+r_autoResolutionScale
+r_autoResolutionThreshold
+r_autoResolutionTune
+r_autoResolutionUIThreshold
+r_autoResolutionUITune
+r_backBufferCount
+r_backendSwapBuffersAssistRelease
+r_bc7CompressAsync
+r_blinkCullNone
+r_blinkForwardSSS
+r_blinkGbuffer
+r_blinkGbufferDecal
+r_blinkGbufferEnt
+r_blinkGbufferViewmodel
+r_blinkGbufferViewmodelDecal
+r_blinkGbufferVolDecal
+r_blinkOIT
+r_blinkTrans
+r_bloomEnable
+r_bloomUseLutALT
+r_blur
+r_blurAndTintEnable
+r_blurAndTintLevel
+r_brushLimit
+r_cachedSpotShadowCopyMode
+r_cameraInfo
+r_catsEyeAberation
+r_catsEyeBlur
+r_catsEyeBlurTint
+r_catsEyeDecolor
+r_catsEyeDistortion
+r_catsEyeFX_enable
+r_catsEyeNoise
+r_catsEyeReset
+r_catsEyeTexture
+r_chaserFX_enable
+r_chkbDiffWeight
+r_chkbMode
+r_chkbSameWeight
+r_chkbTexLodBias
+r_circleMaskRadius
+r_classifyAsync
+r_clear
+r_clearAllGBuffers
+r_clearColor
+r_clearColor2
+r_clearView
+r_clothPrimaryTint
+r_clothSecondaryTint
+r_cmdbuf_worker
+r_cmdlistChain
+r_codeImageDrawDebug
+r_codeImageDrawDebugInfo
+r_codeImageDrawImage
+r_codeImageDrawImageSize
+r_colorMap
+r_computeSpritesAsync
+r_convergence
+r_createLutAsync
+r_cubicUpsampleParam
+r_cullLightsAsync
+r_cullLightsAsyncHighPriority
+r_currentMonitor
+r_deadOps
+r_deadOpsActive
+r_debugDisableLocalProbes
+r_debugImage
+r_debugImageAdvanced
+r_debugImageInfo
+r_debugMaterial
+r_debugMetalStorm
+r_debugModel
+r_debugShowCoronas
+r_debugShowDynamicLights
+r_debugShowLightBoundsSelect
+r_debugShowPrimaryLights
+r_debugShowProbeBlends
+r_debugShowProbes
+r_debugShowProbesBoundsSelect
+r_dedicatedPlayerShadow
+r_dedicatedPlayerShadowCull
+r_dedicatedPlayerShadowCullAngle
+r_dedicatedPlayerSpotOmniShadowResolution
+r_dedicatedPlayerSunShadowPenumbraScale
+r_dedicatedPlayerSunShadowResolution
+r_dedicatedShadowsUmbra
+r_deferredBilateralUpsampleSSAO
+r_deferredBlurBacklit
+r_deferredCullLights
+r_deferredDebugDrawAttenuationVolumes
+r_deferredDrawPrimaries
+r_deferredDrawPrimaryIndex
+r_deferredDrawPrimaryOmnis
+r_deferredDrawPrimarySpots
+r_deferredDrawProbeIndex
+r_deferredDrawProbes
+r_deferredDrawSceneLights
+r_deferredEnableAO
+r_deferredForceShadowNeverUpdate
+r_deferredIgnoreShadowUpdate
+r_deferredMaxVisibleLights
+r_deferredMaxVisibleProbes
+r_deferredPermuteShowClassification
+r_deferredPermuteTiles
+r_deferredPermuteTilesSwizzle
+r_deferredSSTOptims
+r_deferredShowAO
+r_deferredShowInfo
+r_deferredShowSunVis
+r_deferredUseAttenuationVolumes
+r_deferredViewmodel
+r_depthPrime
+r_diffuseProbeDebug
+r_disableGenericFilter
+r_dobjLimit
+r_dofFocusPeaking
+r_dofMode
+r_dofQuality
+r_dofTweak
+r_dof_aperture_override
+r_dof_enable
+r_dof_farBlur
+r_dof_farEnd
+r_dof_farStart
+r_dof_max_override
+r_dof_min_override
+r_dof_nearBlur
+r_dof_nearEnd
+r_dof_nearStart
+r_dof_showdebug
+r_dof_tweak
+r_dof_viewModelEnd
+r_dof_viewModelStart
+r_drawBModels
+r_drawBsp
+r_drawDebugFogParams
+r_drawDynEnts
+r_drawFrameDurationGraph
+r_drawFxOnProbes
+r_drawInfo
+r_drawModelsGobo
+r_drawPlayersInDynamicProbe
+r_drawPrimCap
+r_drawPrimFloor
+r_drawPrimHistogram
+r_drawSModels
+r_drawSceneEnts
+r_drawSceneModels
+r_drawSun
+r_drawTerrain
+r_drawWorld
+r_drawXModels
+r_dualPlayEnable
+r_dumpRenderTargetFormats
+r_dynamicProbeDebugColors
+r_dynamicProbeInitBounceCount
+r_dynamicProbePrefilter
+r_dynamicSceneResolution
+r_dynamicSceneResolutionMode
+r_eacPathFX_enable
+r_eacPath_Posn
+r_eacPath_Radius
+r_eacPath_Step
+r_emulateSlowOrHitchyPresent
+r_enableCubicUpsample
+r_enableGlassDpvs
+r_enableOccluders
+r_enablePlayerShadow
+r_enableVolDecals
+r_ev_distance
+r_ev_edgethickness
+r_ev_edgewidth
+r_ev_geometryrange
+r_ev_random_edge
+r_ev_random_ground
+r_ev_rate
+r_ev_screen_scale
+r_ev_screen_threshold
+r_ev_targetrange
+r_ev_targetwidth
+r_ev_testenable
+r_ev_width
+r_expAWB
+r_expAuto
+r_expCmp
+r_expMax
+r_expMin
+r_expSigma
+r_expSigmaAlpha
+r_expSigmaBeta
+r_expSigmaMax
+r_expSigmaMin
+r_expandInstancesToDrawIndirect
+r_exposureAdaptation
+r_exposureAdaptationTweak
+r_exposureAsync
+r_exposureEyeWeight
+r_exposureTweak
+r_exposureValue
+r_extracamDisable
+r_extracam_add_debug_cam
+r_extracam_add_debug_cam_width
+r_extracam_custom_aspectratio
+r_extracam_remove_debug_cam
+r_extracam_show_axis
+r_extracam_show_render_targets
+r_farClip
+r_filmLut
+r_filmTweakEnable
+r_filmTweakLut
+r_filmUseTweaks
+r_finalShiftX
+r_finalShiftY
+r_flameFX_FPS
+r_flameFX_distortionScaleFactor
+r_flameFX_enable
+r_flameFX_fadeDuration
+r_flameFX_magnitude
+r_flameScaler
+r_flame_allowed
+r_fog
+r_fogBaseDist
+r_fogBaseHeight
+r_fogColor
+r_fogHalfDist
+r_fogHalfHeight
+r_fogIntensity
+r_fogOpacity
+r_fogSkyHalfHeightOffset
+r_fogSunColor
+r_fogSunInner
+r_fogSunIntensity
+r_fogSunOpacity
+r_fogSunOuter
+r_fogSunPitchOffset
+r_fogSunYawOffset
+r_fogTweak
+r_fog_disable
+r_fontResolution
+r_font_cache_debug_display
+r_forceAdapter
+r_forceGbufferVertexOnly
+r_forceLod
+r_forceMaxTextureSize
+r_forceMonitorTV
+r_forceTextureAniso
+r_forcedModelLods
+r_foveaAcuityColorMax
+r_foveaAcuityColorMin
+r_foveaAcuityVisualMax
+r_foveaAcuityVisualMin
+r_framesyncThreshold
+r_fullHDRrendering
+r_fullbright
+r_fullscreen
+r_fuzzSceneWidth
+r_fxShadows
+r_fx_backlighting_amount
+r_fxaaContrastThreshold
+r_fxaaDebug
+r_fxaaSubpixelRemoval
+r_gbufferDepthSort
+r_gbufferDepthSortStaticModels
+r_gbufferOccluderMinSize
+r_gbufferShowContent
+r_genericFilter_enable
+r_genericSceneVector0
+r_genericSceneVector1
+r_genericSceneVector2
+r_genericSceneVector3
+r_genericSceneVector_debug
+r_glossMap
+r_gpuCullingDebugShowDepth
+r_gpuCullingDisableDepthTest
+r_gpuCullingUseGpuResultForPrimaryLight
+r_gpuCullingUseLateDepth
+r_gpuCullingUseWorker
+r_gpuFrameHistogram
+r_gpuTimers
+r_graphicContentBlur
+r_grassEnable
+r_heatPulseFX_enable
+r_hotZone_angle1
+r_hotZone_angle2
+r_hotZone_fadedn
+r_hotZone_fadeup
+r_hotZone_heightlim
+r_hotZone_radius1
+r_hotZone_radius2
+r_hotZone_zgradiant
+r_hybridPreferDeferred
+r_ignore
+r_ignorehwgamma
+r_instancedVolumeDecals
+r_jqprof_capture
+r_lateAllocLimit
+r_lensAbberation
+r_lensApertureAngle
+r_lensApertureBlade
+r_lensFlaresDebug
+r_lightPickerFreeze
+r_lightingDebugOverlay
+r_lightingDebugOverlayAlpha
+r_lightingDebugOverlayScale
+r_lightingEnableAggressiveShadowEviction
+r_lightingOmniShadowForceSize
+r_lightingOmniShadowPenumbraOverride
+r_lightingReflectionProbeMipDrop
+r_lightingShadowFiltering
+r_lightingSpotOmniShadowMaxQuality
+r_lightingSpotShadowDropSizeDistance
+r_lightingSpotShadowForceSize
+r_lightingSpotShadowPenumbraOverride
+r_lightingSunShadowCacheDynamicSiegeDistance
+r_lightingSunShadowCacheEnable
+r_lightingSunShadowCacheEnableUmbra
+r_lightingSunShadowCacheEnableUnusedTracking
+r_lightingSunShadowCacheForceOff
+r_lightingSunShadowCullingToggle
+r_lightingSunShadowDebugDrawAABBs
+r_lightingSunShadowDisableDynamicDraw
+r_lightingSunShadowDobjMovementTracking
+r_lightingSunShadowDynamicSplitCount
+r_lightingSunShadowDynentMovementTracking
+r_lightingSunShadowEnableAsync
+r_lightingSunShadowForceSSTOnly
+r_lightingSunShadowPenumbraOverride
+r_lightingSunShadowSSTMipDrop
+r_lightingSunShadowSkipSplits
+r_lightingSunShadowSplitScreenEmulate
+r_litfog_bank_select
+r_litfog_max_visible_volume_count
+r_litfog_volume_count
+r_litfog_volume_start
+r_lockFrameRateTo30Hz
+r_lockFrameRateTo30Hz_dynResOff
+r_lockFrameRateTo30Hz_enable
+r_lockFrameRateTo30Hz_force
+r_lockPvs
+r_lockPvsInCode
+r_lodBiasRigid
+r_lodScaleRigid
+r_lodThresholdPixelArea
+r_lodUseDynamicResolution
+r_lowResolutionMode
+r_makeDark_enable
+r_marksDebugWorldbrushNormal
+r_materialLab
+r_materialXYZ
+r_maxPOMSamples
+r_maxSpotShadowUpdates
+r_mode
+r_modelLimit
+r_modelLodBias
+r_modelLodLimit
+r_modelSkelWorker
+r_monitor
+r_monitorCalibrate
+r_monitorCount
+r_monitorTV
+r_motionBlurEnable
+r_motionBlurMode
+r_motionBlurQuality
+r_motionBlurStrength
+r_motionVectorDebugDisplay
+r_motionVectorGenerateEnable
+r_motionVectorStaticComputeAsync
+r_motionVectorStaticWithMB
+r_newLensFlares
+r_newLensFlares_offscreen_buffer_size
+r_newLensFlares_show_outlines
+r_newLensFlares_show_sources
+r_norefresh
+r_normalMap
+r_num_viewports
+r_objSpaceViewModelDObj
+r_occQueryDebug
+r_occlusionMap
+r_oit
+r_omniShadowRes
+r_p4x_capture
+r_paperWhite
+r_pbgBank
+r_pbgFogBank
+r_pbrfog_enable
+r_picmip
+r_pix_material
+r_pix_sortkey
+r_pixelShaderGPRReallocation
+r_poisonFX_blurMax
+r_poisonFX_blurMin
+r_poisonFX_debug_amount
+r_poisonFX_debug_enable
+r_poisonFX_dvisionA
+r_poisonFX_dvisionX
+r_poisonFX_dvisionY
+r_poisonFX_pulse
+r_poisonFX_warpX
+r_poisonFX_warpY
+r_polygonOffsetBiasInt
+r_polygonOffsetClamp
+r_polygonOffsetScale
+r_polygonOffsetTweakEnable
+r_portalOccluderTest
+r_postFxIndex
+r_postFxKeylineFrontEnd
+r_postFxSubIndex
+r_postFxUseTweaks
+r_postFxWobble
+r_previousFullscreen
+r_primaryLightTweakDiffuseStrength
+r_primaryLightTweakSpecularStrength
+r_primaryLightUseTweaks
+r_qrcode_debug_display
+r_qrcode_debug_display_size
+r_radioactiveBlur
+r_radioactiveFX_enable
+r_radioactiveIntensity
+r_radioactiveSpeed
+r_refreshRate
+r_removeSystemReservation
+r_rendertarget_debug_display
+r_resetLightingDebug
+r_resolveMethod
+r_reviveFX_debug
+r_reviveFX_edgeAmount
+r_reviveFX_edgeColorTemp
+r_reviveFX_edgeContrast
+r_reviveFX_edgeMaskAdjust
+r_reviveFX_edgeOffset
+r_reviveFX_edgeSaturation
+r_reviveFX_edgeScale
+r_saveDefaultRenderImages
+r_scaleViewport
+r_sceneGamma
+r_sceneResolution
+r_sceneResolutionMultiplier
+r_shaderDebug
+r_shader_constant_set_debug_range
+r_shader_constant_set_enable
+r_showBModelNamesDist
+r_showBounds
+r_showCollision
+r_showCollisionDepthTest
+r_showCollisionDist
+r_showCollisionGroups
+r_showCollisionPolyType
+r_showCullBModels
+r_showCullDistDebug
+r_showCullSModels
+r_showCullXModels
+r_showCullXmodelsEntNum
+r_showDObjModelNamesDist
+r_showDuplicateRenderInfoDist
+r_showDynEntModelNames
+r_showEntModelNamesDist
+r_showExposureZones
+r_showForceNoCull
+r_showImpactVolDecalDebug
+r_showLodInfo
+r_showLodInfoMaxDistance
+r_showModelNamesPlacement
+r_showOccluders
+r_showOverdraw
+r_showOverdrawAlpha
+r_showOverdrawMax
+r_showOverdrawNumLayers
+r_showPBRCheck
+r_showPenetration
+r_showSModelNames
+r_showSiegeDObjModleNames
+r_showSiegeModelNames
+r_showSunDirectionDebug
+r_showSurfCounts
+r_showTextureOverrideInfo
+r_showTriCounts
+r_showTriDensity
+r_showTris
+r_showVertCounts
+r_showWorldVolDecalDebug
+r_siege_debug_scale
+r_siege_info
+r_siege_notetrack_debug
+r_skipDrawTris
+r_skipPvs
+r_skipXModelZeroSizedBones
+r_skyBoxColorIDX
+r_skyRotation
+r_skyTransition
+r_smaa
+r_smaaCompute
+r_smaaHighQuality
+r_smaaQuincunx
+r_smodel_combineWorkers
+r_smodel_partialSortWorkers
+r_smodel_splitWorkers
+r_smp_backend
+r_smp_worker_threads
+r_sortBackToFront
+r_sortDrawSurfsBsp
+r_sortDrawSurfsStaticModel
+r_sortTrans
+r_specularGlossMap
+r_specularMap
+r_speedBlurAmount
+r_speedBlurFX_enable
+r_splitScreenExpandFull
+r_splitscreenBlurEdges
+r_spotLightEntityShadows
+r_spotLightSModelShadows
+r_spotLightShadows
+r_spotMeter
+r_spotShadowRes
+r_ssaoAsync
+r_ssaoCompareRefTechnique
+r_ssaoEnable
+r_ssaoRefTechnique
+r_ssaoShowDebug
+r_ssaoTechnique
+r_ssao_gtaoHigh
+r_ssao_gtaoLow
+r_ssao_gtaoMid
+r_ssao_gtaoStrength
+r_ssao_gtaoTweak
+r_ssao_hbaoFalloff
+r_ssao_hbaoIntensity
+r_ssao_hbaoNormalScale
+r_ssao_hbaoRadius
+r_ssao_hbaoSharpness
+r_ssao_hbaoTanAngleBias
+r_ssao_hdaoAcceptAngle
+r_ssao_hdaoAcceptRadius
+r_ssao_hdaoIntensity
+r_ssao_hdaoNormalScale
+r_ssao_hdaoRadius
+r_ssao_hdaoRejectRadius
+r_ssao_hdaoSharpness
+r_ssao_hemiAOBlurTolerance
+r_ssao_hemiAOCombineBeforeBlur
+r_ssao_hemiAOCombineResWithMul
+r_ssao_hemiAOHierarchyDepth
+r_ssao_hemiAONoiseFilterTolerance
+r_ssao_hemiAOQuality
+r_ssao_hemiAORejectionFalloff
+r_ssao_hemiAOSensitivity
+r_ssao_hemiAOUpsampleTolerance
+r_ssao_ohaoIntensity
+r_ssao_ohaoRadius
+r_ssao_ohaoSharpness
+r_ssao_s1aoDepthScale
+r_ssao_s1aoGapFalloff
+r_ssao_s1aoGradiantFalloff
+r_ssao_s1aoIntensity
+r_ssao_s1aoRadius
+r_ssao_s1aoSharpness
+r_ssao_saoBias
+r_ssao_saoEpsilon
+r_ssao_saoIntensity
+r_ssao_saoRadius
+r_ssao_saoSharpness
+r_ssao_saov2Bias
+r_ssao_saov2Falloff
+r_ssao_saov2Intensity
+r_ssao_saov2Radius
+r_ssao_saov2Sharpness
+r_ssao_t7aoFalloff
+r_ssao_t7aoIntensity
+r_ssao_t7aoRadius
+r_ssao_t7aoSelfOcclusion
+r_ssao_t7aoSharpness
+r_ssao_voaoFalloff
+r_ssao_voaoIntensity
+r_ssao_voaoRadius
+r_ssao_voaoSharpness
+r_ssao_voaoThickness
+r_sssblurEnable
+r_stereo3DAvailable
+r_stereo3DEyeSeparation
+r_stereo3DEyeSeparationScaler
+r_stereo3DMode
+r_stereo3DOn
+r_stereo3DRightEyeReuseLeftEyeShadows
+r_stereoFocusDepth
+r_stereoGunShift
+r_stereoTurretShift
+r_stream
+r_streamCheckAabb
+r_streamClear
+r_streamDistanceMax
+r_streamDumpCurrentUsage
+r_streamDumpDistance
+r_streamDumpImageUsage
+r_streamDumpInitial
+r_streamDumpSortedImageList
+r_streamFreezeState
+r_streamHiddenPush
+r_streamHidePlayer
+r_streamHighPriorityThreshold
+r_streamLowDetail
+r_streamPaintDiffuse
+r_streamProfile
+r_streamReadLog
+r_streamReflectionProbes
+r_streamRemoveHimips
+r_streamShowHints
+r_streamShowLoadingMaterial
+r_streamShowReadSpeeds
+r_streamShowVolumes
+r_streamTextureMemoryMax
+r_streamTouchLookahead
+r_submitDoneThreshold
+r_sunColor
+r_sunFilterInches
+r_sunFlareTint
+r_sunPitch
+r_sunShadowSplitDistance
+r_sunStops
+r_sunTweak
+r_tacScanFX_enable
+r_tacScan_Eps
+r_tacScan_FadeEnd
+r_tacScan_FadeStart
+r_tacScan_HotZone
+r_tacScan_Layout
+r_tacScan_Paths
+r_tacScan_Popups
+r_tacScan_Scale
+r_tacScan_Traces
+r_takeScreenShot
+r_texFilterQuality
+r_textureMipLodBias
+r_textureMode
+r_tilingHighlight
+r_tilingLightCount
+r_tilingProbeCount
+r_tilingSunShadow
+r_tmodeServerActive
+r_triDensityPointAlpha
+r_triDensityPointOnSmallTris
+r_triDensityPointOnTriCenter
+r_triDensityPointOnVerts
+r_triDensityPointSize
+r_triDensityScalePointAlpha
+r_triDensityScalePointSize
+r_triDensityShowOriginalGeo
+r_triDensitySmallTriArea
+r_uberResolveAsync
+r_uhdMode
+r_ui3d_debug_display
+r_ui3d_h
+r_ui3d_use_debug_values
+r_ui3d_w
+r_ui3d_x
+r_ui3d_y
+r_uiHudFX_enable
+r_umbraAccurateOcclusionThreshold
+r_umbraAllowDatabaseThread
+r_umbraDisableForScene
+r_umbraDisableForSceneZeroUmbraWork
+r_umbraDisableForSpotOmniShadow
+r_umbraDistanceScale
+r_umbraDrawDebug
+r_umbraEnable
+r_umbraEnableDebugDisplay
+r_umbraEnableParameterVolumes
+r_umbraFilter
+r_umbraGridHeight
+r_umbraGridWidth
+r_umbraLightVis
+r_umbraMinRelativeContribution
+r_umbraNearDistance
+r_umbraQueryLocalLights
+r_umbraTomeTriggerDebug
+r_umbraVerbose
+r_umrbaEnableParameterVolumes
+r_underwaterAbsorptionRGB
+r_underwaterHalfDistance
+r_underwaterOutputMix
+r_underwaterTweak
+r_updateDynamicProbes
+r_updateSingleDynamicProbe
+r_updateSingleDynamicProbeFace
+r_useBindlessMaterialKeyMerge
+r_useBindlessTechnique
+r_useCachedSpotShadow
+r_useDynamicProbeTextures
+r_useHidePartbits
+r_useLensFov
+r_useSimpleDObj
+r_useStrict30HzConditions
+r_validateCommandBuffers
+r_vid_align
+r_videoMode
+r_viewModelSpotOmniShadowResolution
+r_viewModelSunShadowResolution
+r_viewmodelSelfShadow
+r_viewportBackingColor
+r_volumetric_lighting_blur_depth_threshold
+r_volumetric_lighting_buffers_size_ratio
+r_volumetric_lighting_density_scaler
+r_volumetric_lighting_enable_probes
+r_volumetric_lighting_enable_spot
+r_volumetric_lighting_enable_sun
+r_volumetric_lighting_enable_tweaks
+r_volumetric_lighting_enabled
+r_volumetric_lighting_fog_base_distance
+r_volumetric_lighting_fog_base_height
+r_volumetric_lighting_fog_half_distance
+r_volumetric_lighting_fog_half_height
+r_volumetric_lighting_force
+r_volumetric_lighting_half_res_apply
+r_volumetric_lighting_lights_skip_samples
+r_volumetric_lighting_max_lit_omni_spot_fog_distance
+r_volumetric_lighting_max_lit_sun_fog_distance
+r_volumetric_lighting_max_spot_samples
+r_volumetric_lighting_max_sun_samples
+r_volumetric_lighting_mode
+r_volumetric_lighting_phase_distribution
+r_volumetric_lighting_probe_contribution_scaler
+r_volumetric_lighting_scattering_albedo
+r_volumetric_lighting_sun_intensity_scale
+r_volumetric_lighting_sun_skip_samples
+r_volumetric_lighting_sun_step_size
+r_volumetric_lighting_uber_depth_resolve_enabled
+r_volumetric_lighting_upsample_depth_threshold
+r_vsync
+r_vsync_tear_window_enable
+r_vsync_tear_window_lower
+r_vsync_tear_window_upper
+r_warningRepeatDelay
+r_waterFogTest
+r_waterSheetingFX_allowed
+r_waterSheetingFX_distortionScaleFactor
+r_waterSheetingFX_enable
+r_waterSheetingFX_magnitude
+r_waterSheetingFX_radius
+r_watersim_enabled
+r_waveWaterActors
+r_waveWaterDebugDraw
+r_waveWaterDrawOnlyLevel
+r_waveWaterFreeze
+r_waveWaterGeneratorTweakIndex
+r_waveWaterHeightOverride
+r_waveWaterHeightOverrideEnable
+r_waveWaterPoke
+r_waveWaterPokeSize
+r_waveWaterPrint
+r_waveWaterTweakEnable
+r_waveWaterZero
+r_worldfogskysize
+r_xanim_disableCosmeticBones
+r_xanim_disableExtraChannel
+r_xanim_drawBones
+r_xcamsEnabled
+r_xdebug
+r_zfar
+r_znear_depthhack
+r_zombieNameAllowDevList
+r_zombieNameAllowFriendsList
+r_zombiesShooterSpotted
+radius_damage_debug
+ragdoll_activationVelocitySq
+ragdoll_baselerp_time
+ragdoll_bullet_force
+ragdoll_bullet_upbias
+ragdoll_debug
+ragdoll_dump_anims
+ragdoll_enable
+ragdoll_explode_force
+ragdoll_explode_upbias
+ragdoll_fps
+ragdoll_gravityScale
+ragdoll_jitter_scale
+ragdoll_jointlerp_time
+ragdoll_max_life
+ragdoll_max_simulating
+ragdoll_musclePowerScale
+ragdoll_reactivation_cutoff
+ragdoll_rotvel_scale
+ragdoll_self_collision_scale
+rare_crate_bundle_id
+rat_hostdir
+rat_instanceid
+rat_playback_enabled
+rat_testid
+rate
+rb_drawCullWorkerDebugText
+rb_drawSonarDebugText
+rcon
+rcon_password
+reconnect
+recordPointsSpent
+recorder_bufferSize
+recorder_channelAccuracy
+recorder_channelAiCode
+recorder_channelAiProfile
+recorder_channelAlex
+recorder_channelAnimation
+recorder_channelAnimscript
+recorder_channelCover
+recorder_channelGrenades
+recorder_channelMessaging
+recorder_channelNone
+recorder_channelPathFind
+recorder_channelPerception
+recorder_channelPhysics
+recorder_channelScript
+recorder_channelScriptedAnim
+recorder_channelSpawning
+recorder_channelSuppression
+recorder_channelThreat
+recorder_debugMemory
+recorder_enableRec
+recorder_recordAllVehicles
+recorder_streamDObjects
+recorder_stringScaleBase
+recorder_textScale
+recorder_textScaleDistBase
+recorder_textScaleDistMax
+redactionDisplayTime
+redactionFadeDuration
+redactionStartStrokeTime
+redactionStrokeTime
+reliableResendTime
+reliableTimeoutTime
+remote_missile_boost_acceleration
+remote_missile_boost_shake_duration
+remote_missile_boost_shake_radius
+remote_missile_boost_shake_scale
+remote_missile_boost_speed
+remote_missile_brake_deceleration
+remote_missile_brake_shake_duration
+remote_missile_brake_shake_radius
+remote_missile_brake_shake_scale
+remote_missile_brake_speed
+remote_missile_coast_speed
+remote_missile_speed
+render_actor_collision
+render_bpi_env_collision
+render_fake_ents
+render_player_collision
+render_script_movers
+reportUserInterval
+restrict_attachment
+restrict_item
+retail_incentive_id
+reviveWidgetClampedScale
+reviveWidgetEndDistance
+reviveWidgetEndScale
+reviveWidgetOffset
+reviveWidgetRevivingScale
+reviveWidgetStartDistance
+reviveWidgetStartScale
+revive_time_taken
+revive_trigger_radius
+riotshield_assist_time
+riotshield_bullet_damage_scale
+riotshield_damage_score_max
+riotshield_damage_score_threshold
+riotshield_debug
+riotshield_deploy_limit_radius
+riotshield_deploy_pitch_max
+riotshield_deploy_roll_max
+riotshield_deploy_zdiff_max
+riotshield_deployed_health
+riotshield_destroyed_cleanup_time
+riotshield_explosive_damage_scale
+riotshield_melee_damage_scale
+riotshield_placement_foffset
+riotshield_placement_maxs
+riotshield_projectile_damage_scale
+rootMotion_debugMode
+s
+safeArea_horizontal
+safeArea_vertical
+saveLocalMatchRecordBinaryFile
+saved_gameskill
+say
+say_team
+scene_debug_player
+scene_hide_player
+scrFatalScriptErrors
+scrShowStrUsage
+scrShowVarUseage
+scrVmEnableScripts
+scr_RequiredMapAspectratio
+scr_airsupportHeightScale
+scr_allies
+scr_allow_killstreak_building
+scr_axis
+scr_codPointsCap
+scr_codpointsmatchscale
+scr_codpointsperchallenge
+scr_codpointsxpscale
+scr_coop_friendlyFireDelayTime
+scr_coop_hud_showobjicons
+scr_coop_score_accolade_infection_score
+scr_coop_score_assist_amws_25
+scr_coop_score_assist_amws_50
+scr_coop_score_assist_amws_75
+scr_coop_score_assist_aqu_quadtank_25
+scr_coop_score_assist_aqu_quadtank_50
+scr_coop_score_assist_aqu_quadtank_75
+scr_coop_score_assist_aqu_vtol_25
+scr_coop_score_assist_aqu_vtol_50
+scr_coop_score_assist_aqu_vtol_75
+scr_coop_score_assist_assault_25
+scr_coop_score_assist_assault_50
+scr_coop_score_assist_assault_75
+scr_coop_score_assist_concussion
+scr_coop_score_assist_cqb_25
+scr_coop_score_assist_cqb_50
+scr_coop_score_assist_cqb_75
+scr_coop_score_assist_dannyli_25
+scr_coop_score_assist_dannyli_50
+scr_coop_score_assist_dannyli_75
+scr_coop_score_assist_depth_charge_25
+scr_coop_score_assist_depth_charge_50
+scr_coop_score_assist_depth_charge_75
+scr_coop_score_assist_direwolf_25
+scr_coop_score_assist_direwolf_50
+scr_coop_score_assist_direwolf_75
+scr_coop_score_assist_emp
+scr_coop_score_assist_flash
+scr_coop_score_assist_gomin_25
+scr_coop_score_assist_gomin_50
+scr_coop_score_assist_gomin_75
+scr_coop_score_assist_goxiulan_25
+scr_coop_score_assist_goxiulan_50
+scr_coop_score_assist_goxiulan_75
+scr_coop_score_assist_hunter_25
+scr_coop_score_assist_hunter_50
+scr_coop_score_assist_hunter_75
+scr_coop_score_assist_lotus_gunship_25
+scr_coop_score_assist_lotus_gunship_50
+scr_coop_score_assist_lotus_gunship_75
+scr_coop_score_assist_macv_25
+scr_coop_score_assist_macv_50
+scr_coop_score_assist_macv_75
+scr_coop_score_assist_pamws_25
+scr_coop_score_assist_pamws_50
+scr_coop_score_assist_pamws_75
+scr_coop_score_assist_parasite_25
+scr_coop_score_assist_parasite_50
+scr_coop_score_assist_parasite_75
+scr_coop_score_assist_prologue_robot_25
+scr_coop_score_assist_prologue_robot_50
+scr_coop_score_assist_prologue_robot_75
+scr_coop_score_assist_prologue_vtol_25
+scr_coop_score_assist_prologue_vtol_50
+scr_coop_score_assist_prologue_vtol_75
+scr_coop_score_assist_proximity
+scr_coop_score_assist_quadtank_25
+scr_coop_score_assist_quadtank_50
+scr_coop_score_assist_quadtank_75
+scr_coop_score_assist_raps_25
+scr_coop_score_assist_raps_50
+scr_coop_score_assist_raps_75
+scr_coop_score_assist_robotcqb_25
+scr_coop_score_assist_robotcqb_50
+scr_coop_score_assist_robotcqb_75
+scr_coop_score_assist_robotdemo_25
+scr_coop_score_assist_robotdemo_50
+scr_coop_score_assist_robotdemo_75
+scr_coop_score_assist_robotrocketeer_25
+scr_coop_score_assist_robotrocketeer_50
+scr_coop_score_assist_robotrocketeer_75
+scr_coop_score_assist_robotsapper_25
+scr_coop_score_assist_robotsapper_50
+scr_coop_score_assist_robotsapper_75
+scr_coop_score_assist_robotsniper_25
+scr_coop_score_assist_robotsniper_50
+scr_coop_score_assist_robotsniper_75
+scr_coop_score_assist_robotsoldier_25
+scr_coop_score_assist_robotsoldier_50
+scr_coop_score_assist_robotsoldier_75
+scr_coop_score_assist_robotsuppressor_25
+scr_coop_score_assist_robotsuppressor_50
+scr_coop_score_assist_robotsuppressor_75
+scr_coop_score_assist_rocketeer_25
+scr_coop_score_assist_rocketeer_50
+scr_coop_score_assist_rocketeer_75
+scr_coop_score_assist_siegebot_25
+scr_coop_score_assist_siegebot_50
+scr_coop_score_assist_siegebot_75
+scr_coop_score_assist_sniper_25
+scr_coop_score_assist_sniper_50
+scr_coop_score_assist_sniper_75
+scr_coop_score_assist_suppressor_25
+scr_coop_score_assist_suppressor_50
+scr_coop_score_assist_suppressor_75
+scr_coop_score_assist_technical_25
+scr_coop_score_assist_technical_50
+scr_coop_score_assist_technical_75
+scr_coop_score_assist_theia_25
+scr_coop_score_assist_theia_50
+scr_coop_score_assist_theia_75
+scr_coop_score_assist_tiger_tank_25
+scr_coop_score_assist_tiger_tank_50
+scr_coop_score_assist_tiger_tank_75
+scr_coop_score_assist_turret_25
+scr_coop_score_assist_turret_50
+scr_coop_score_assist_turret_75
+scr_coop_score_assist_vtol_25
+scr_coop_score_assist_vtol_50
+scr_coop_score_assist_vtol_75
+scr_coop_score_assist_warlord_25
+scr_coop_score_assist_warlord_50
+scr_coop_score_assist_warlord_75
+scr_coop_score_assist_wasp_25
+scr_coop_score_assist_wasp_50
+scr_coop_score_assist_wasp_75
+scr_coop_score_assist_zombie_25
+scr_coop_score_assist_zombie_50
+scr_coop_score_assist_zombie_75
+scr_coop_score_award_accolade
+scr_coop_score_award_calling_card
+scr_coop_score_complete_mission_hardened
+scr_coop_score_complete_mission_heroic
+scr_coop_score_complete_mission_recruit
+scr_coop_score_complete_mission_regular
+scr_coop_score_complete_mission_veteran
+scr_coop_score_completed_match
+scr_coop_score_completed_training_sim_rating
+scr_coop_score_death
+scr_coop_score_debug_give_score
+scr_coop_score_kill_amws
+scr_coop_score_kill_aqu_quadtank
+scr_coop_score_kill_aqu_vtol
+scr_coop_score_kill_assault
+scr_coop_score_kill_cqb
+scr_coop_score_kill_dannyli
+scr_coop_score_kill_depth_charge
+scr_coop_score_kill_direwolf
+scr_coop_score_kill_gomin
+scr_coop_score_kill_goxiulan
+scr_coop_score_kill_hunter
+scr_coop_score_kill_lotus_gunship
+scr_coop_score_kill_macv
+scr_coop_score_kill_meatball
+scr_coop_score_kill_pamws
+scr_coop_score_kill_parasite
+scr_coop_score_kill_prologue_robot
+scr_coop_score_kill_prologue_vtol
+scr_coop_score_kill_quadtank
+scr_coop_score_kill_raps
+scr_coop_score_kill_robotcqb
+scr_coop_score_kill_robotdemo
+scr_coop_score_kill_robotrocketeer
+scr_coop_score_kill_robotsapper
+scr_coop_score_kill_robotsniper
+scr_coop_score_kill_robotsoldier
+scr_coop_score_kill_robotsuppressor
+scr_coop_score_kill_rocketeer
+scr_coop_score_kill_siegebot
+scr_coop_score_kill_sniper
+scr_coop_score_kill_spider
+scr_coop_score_kill_suppressor
+scr_coop_score_kill_technical
+scr_coop_score_kill_theia
+scr_coop_score_kill_tiger_tank
+scr_coop_score_kill_turret
+scr_coop_score_kill_vtol
+scr_coop_score_kill_warlord
+scr_coop_score_kill_wasp
+scr_coop_score_kill_zombie
+scr_coop_score_killnone
+scr_coop_score_melee_kill_amws
+scr_coop_score_melee_kill_aqu_quadtank
+scr_coop_score_melee_kill_aqu_vtol
+scr_coop_score_melee_kill_assault
+scr_coop_score_melee_kill_cqb
+scr_coop_score_melee_kill_dannyli
+scr_coop_score_melee_kill_depth_charge
+scr_coop_score_melee_kill_direwolf
+scr_coop_score_melee_kill_gomin
+scr_coop_score_melee_kill_goxiulan
+scr_coop_score_melee_kill_hunter
+scr_coop_score_melee_kill_lotus_gunship
+scr_coop_score_melee_kill_macv
+scr_coop_score_melee_kill_meatball
+scr_coop_score_melee_kill_pamws
+scr_coop_score_melee_kill_parasite
+scr_coop_score_melee_kill_prologue_robot
+scr_coop_score_melee_kill_prologue_vtol
+scr_coop_score_melee_kill_quadtank
+scr_coop_score_melee_kill_raps
+scr_coop_score_melee_kill_robotcqb
+scr_coop_score_melee_kill_robotdemo
+scr_coop_score_melee_kill_robotrocketeer
+scr_coop_score_melee_kill_robotsapper
+scr_coop_score_melee_kill_robotsniper
+scr_coop_score_melee_kill_robotsoldier
+scr_coop_score_melee_kill_robotsuppressor
+scr_coop_score_melee_kill_rocketeer
+scr_coop_score_melee_kill_siegebot
+scr_coop_score_melee_kill_sniper
+scr_coop_score_melee_kill_suppressor
+scr_coop_score_melee_kill_technical
+scr_coop_score_melee_kill_theia
+scr_coop_score_melee_kill_tiger_tank
+scr_coop_score_melee_kill_turret
+scr_coop_score_melee_kill_vtol
+scr_coop_score_melee_kill_warlord
+scr_coop_score_melee_kill_wasp
+scr_coop_score_melee_kill_zombie
+scr_coop_score_multikill_2
+scr_coop_score_multikill_3
+scr_coop_score_multikill_4
+scr_coop_score_multikill_5
+scr_coop_score_multikill_6
+scr_coop_score_multikill_7
+scr_coop_score_multikill_8
+scr_coop_score_multikill_more_than_8
+scr_coop_score_picked_up_collectible
+scr_coop_score_player_did_revived
+scr_coop_score_scavenger_assist
+scr_coop_score_scavenger_pickup
+scr_coop_score_scavenger_streak
+scr_coop_score_shield_blocked_damage
+scr_coop_score_shield_blocked_damage_reduced
+scr_coop_score_suicide
+scr_coop_weapon_allowbetty
+scr_coop_weapon_allowflash
+scr_coop_weapon_allowfrag
+scr_coop_weapon_allowrpgs
+scr_coop_weapon_allowsatchel
+scr_coop_weapon_allowsmoke
+scr_csmode
+scr_custom_score_assist
+scr_debug_heat_wave_traces
+scr_debug_leaks
+scr_deleteexplosivesonspawn
+scr_dirt_enable_explosion
+scr_dirt_enable_fall_damage
+scr_dirt_enable_gravity_spikes
+scr_dirt_enable_slide
+scr_disableChallenges
+scr_disableSetDStat
+scr_disableStatTracking
+scr_disable_air_death_ragdoll
+scr_disable_team_selection
+scr_disable_weapondrop
+scr_disableunifiedspawning
+scr_drawfriend
+scr_dynamic_source_loading
+scr_emergency_reserve_timer
+scr_emergency_reserve_timer_upgraded
+scr_fireflyPartialMovePercent
+scr_fireflyPodActivationTime
+scr_fireflyPodDetectionRadius
+scr_fireflyPodGracePeriod
+scr_firefly_attack_attack_speed_scale
+scr_firefly_collision_check_interval
+scr_firefly_debug
+scr_firefly_emit_time
+scr_firefly_min_speed
+scr_firefly_pod_timeout
+scr_firstGumFree
+scr_free
+scr_game_arcadescoring
+scr_game_difficulty
+scr_game_friendlyFireDelay
+scr_game_medalsenabled
+scr_game_pinups
+scr_game_rankenabled
+scr_gunxpscale
+scr_gunxpscaleCP
+scr_gunxpscaleMP
+scr_gunxpscaleZM
+scr_gunxpscalecp
+scr_gunxpscalemp
+scr_gunxpscalezm
+scr_hardcore
+scr_hardpoint_allowauto_turret
+scr_hardpoint_allowcounteruav
+scr_hardpoint_allowdogs
+scr_hardpoint_allowhelicopter_comlink
+scr_hardpoint_allowradar
+scr_hardpoint_allowradardirection
+scr_hardpoint_allowrcbomb
+scr_hardpoint_allowuav
+scr_health_debug
+scr_heli_armor
+scr_heli_armor_bulletdamage
+scr_heli_armored_maxhealth
+scr_heli_attract_range
+scr_heli_attract_strength
+scr_heli_debug
+scr_heli_debug_crash
+scr_heli_dest_wait
+scr_heli_health_degrade
+scr_heli_loopmax
+scr_heli_maxhealth
+scr_heli_missile_friendlycare
+scr_heli_missile_max
+scr_heli_missile_range
+scr_heli_missile_regen_time
+scr_heli_missile_reload_time
+scr_heli_missile_rof
+scr_heli_missile_target_cone
+scr_heli_missile_valid_target_cone
+scr_heli_protect_pos_time
+scr_heli_protect_radius
+scr_heli_protect_time
+scr_heli_target_recognition
+scr_heli_target_spawnprotection
+scr_heli_targeting_delay
+scr_heli_turretClipSize
+scr_heli_turretReloadTime
+scr_heli_turret_angle_tan
+scr_heli_turret_spinup_delay
+scr_heli_turret_target_cone
+scr_heli_visual_range
+scr_heli_warning_distance
+scr_helicopterTurretMaxAngle
+scr_hostmigrationtest
+scr_incendiaryDamageRadius
+scr_incendiaryfireDamage
+scr_incendiaryfireDamageHardcore
+scr_incendiaryfireDamageTickTime
+scr_incendiaryfireDuration
+scr_incendiaryfxDuration
+scr_killcam
+scr_lightningGunKillcamDecelPercent
+scr_lightningGunKillcamOffset
+scr_lightningGunKillcamTime
+scr_mapsize
+scr_max_rank
+scr_max_simLocks
+scr_maxinventory_scorestreaks
+scr_min_prestige
+scr_minimap_height
+scr_missileDudDeleteDelay
+scr_mod_enable_devblock
+scr_motd
+scr_no_checkpoints
+scr_numLives
+scr_oldschool
+scr_playerInvulTimeScale
+scr_player_allowrevive
+scr_player_sprinttime
+scr_proximityChainBoltSpeed
+scr_proximityChainDebug
+scr_proximityChainGracePeriod
+scr_proximityGrenadeActivationTime
+scr_proximityGrenadeDOTDamageAmount
+scr_proximityGrenadeDOTDamageAmountHardcore
+scr_proximityGrenadeDOTDamageInstances
+scr_proximityGrenadeDOTDamageTime
+scr_proximityGrenadeDetectionRadius
+scr_proximityGrenadeDuration
+scr_proximityGrenadeGracePeriod
+scr_proximityGrenadeProtectedTime
+scr_rampagebonusscale
+scr_rankXpCap
+scr_requiredMapAspectRatio
+scr_satchel_detonation_delay
+scr_scorestreaks
+scr_scorestreaks_maxstacking
+scr_selecting_location
+scr_showperksonspawn
+scr_sideBetTimer
+scr_sitrepscan1_enable
+scr_sitrepscan1_setdesat
+scr_sitrepscan1_setfalloff
+scr_sitrepscan1_setlinewidth
+scr_sitrepscan1_setoutline
+scr_sitrepscan1_setradius
+scr_sitrepscan1_setsolid
+scr_sitrepscan2_enable
+scr_sitrepscan2_setdesat
+scr_sitrepscan2_setfalloff
+scr_sitrepscan2_setlinewidth
+scr_sitrepscan2_setoutline
+scr_sitrepscan2_setradius
+scr_sitrepscan2_setsolid
+scr_skip_devblock
+scr_spawn_enemyavoiddist
+scr_spawn_enemyavoidweight
+scr_spawn_force_unified
+scr_tdm_friendlyFireDelayTime
+scr_tdm_killstreak_allowcounteruav
+scr_tdm_killstreak_allowradar
+scr_tdm_killstreak_allowradardirection
+scr_tdm_score_aircraft_destruction_assist_25
+scr_tdm_score_aircraft_destruction_assist_50
+scr_tdm_score_aircraft_destruction_assist_75
+scr_tdm_score_aircraft_flare_assist
+scr_tdm_score_aitank_kill
+scr_tdm_score_annihilator_kill
+scr_tdm_score_annihilator_multikill
+scr_tdm_score_annihilator_multikill_2
+scr_tdm_score_annihilator_stolen
+scr_tdm_score_armblades_kill
+scr_tdm_score_armblades_multikill
+scr_tdm_score_armblades_multikill_2
+scr_tdm_score_armblades_stolen
+scr_tdm_score_assist_25
+scr_tdm_score_assist_50
+scr_tdm_score_assist_75
+scr_tdm_score_assist_concussion
+scr_tdm_score_assist_emp
+scr_tdm_score_assist_flash
+scr_tdm_score_assist_proximity
+scr_tdm_score_assisted_suicide
+scr_tdm_score_backstabber_kill
+scr_tdm_score_ball_capture_assist
+scr_tdm_score_ball_capture_carry
+scr_tdm_score_ball_capture_throw
+scr_tdm_score_ball_intercept
+scr_tdm_score_bomb_detonated
+scr_tdm_score_bounce_hatchet_kill
+scr_tdm_score_bowlauncher_kill
+scr_tdm_score_bowlauncher_multikill
+scr_tdm_score_bowlauncher_multikill_2
+scr_tdm_score_bowlauncher_stolen
+scr_tdm_score_c4_multikill
+scr_tdm_score_capture_enemy_crate
+scr_tdm_score_clean_assist_collect
+scr_tdm_score_clean_enemy_collect
+scr_tdm_score_clean_enemy_deposit
+scr_tdm_score_clean_friendly_collect
+scr_tdm_score_clean_kill_enemy_carrying_tacos
+scr_tdm_score_clean_multi_deny_tacos
+scr_tdm_score_clean_multi_deposit_big
+scr_tdm_score_clean_multi_deposit_normal
+scr_tdm_score_clean_own_collect
+scr_tdm_score_cleanse_kill
+scr_tdm_score_clear_2_attackers
+scr_tdm_score_combat_efficiency_bonus_1
+scr_tdm_score_combat_efficiency_bonus_2
+scr_tdm_score_combat_efficiency_bonus_3
+scr_tdm_score_combat_robot_kill
+scr_tdm_score_comeback_from_deathstreak
+scr_tdm_score_completed_match
+scr_tdm_score_counter_uav_assist
+scr_tdm_score_dart_kill
+scr_tdm_score_death
+scr_tdm_score_defend_flag_carrier
+scr_tdm_score_defend_hq_last_man_alive
+scr_tdm_score_defused_bomb
+scr_tdm_score_defused_bomb_last_man_alive
+scr_tdm_score_destroyed_aitank
+scr_tdm_score_destroyed_bouncingbetty
+scr_tdm_score_destroyed_c4
+scr_tdm_score_destroyed_claymore
+scr_tdm_score_destroyed_combat_robot
+scr_tdm_score_destroyed_counter_uav
+scr_tdm_score_destroyed_dart
+scr_tdm_score_destroyed_drone_strike
+scr_tdm_score_destroyed_emp
+scr_tdm_score_destroyed_fireflyhive
+scr_tdm_score_destroyed_helicopter_agr_drop
+scr_tdm_score_destroyed_helicopter_comlink
+scr_tdm_score_destroyed_helicopter_giunit_drop
+scr_tdm_score_destroyed_helicopter_supply_drop
+scr_tdm_score_destroyed_heliopter_giunit_drop
+scr_tdm_score_destroyed_hover_rcxd
+scr_tdm_score_destroyed_microwave_turret
+scr_tdm_score_destroyed_motion_sensor
+scr_tdm_score_destroyed_plane_mortar
+scr_tdm_score_destroyed_proxy
+scr_tdm_score_destroyed_raps_deployship
+scr_tdm_score_destroyed_remote_missile
+scr_tdm_score_destroyed_rolling_thunder_all_drones
+scr_tdm_score_destroyed_rolling_thunder_drone
+scr_tdm_score_destroyed_satellite
+scr_tdm_score_destroyed_sentinel
+scr_tdm_score_destroyed_sentry_gun
+scr_tdm_score_destroyed_shield
+scr_tdm_score_destroyed_siegebot
+scr_tdm_score_destroyed_siegebot_assist
+scr_tdm_score_destroyed_tac_insert
+scr_tdm_score_destroyed_trophy_system
+scr_tdm_score_destroyed_uav
+scr_tdm_score_destroyed_vtol_mothership
+scr_tdm_score_disabled_robot
+scr_tdm_score_disarm_hacked_care_package
+scr_tdm_score_dom_point_neutral_b_secured
+scr_tdm_score_dom_point_neutral_secured
+scr_tdm_score_dom_point_neutralized_neutralizing
+scr_tdm_score_dom_point_secured
+scr_tdm_score_dom_point_secured_neutralizing
+scr_tdm_score_downed_player
+scr_tdm_score_drone_strike_kill
+scr_tdm_score_electrified
+scr_tdm_score_eliminate_oic
+scr_tdm_score_elimination_and_last_player_alive
+scr_tdm_score_emp_assist
+scr_tdm_score_end_enemy_armblades_attack
+scr_tdm_score_end_enemy_gravity_spike_attack
+scr_tdm_score_end_enemy_psychosis
+scr_tdm_score_end_enemy_specialist_weapon
+scr_tdm_score_escort_robot_disable
+scr_tdm_score_escort_robot_disable_assist_25
+scr_tdm_score_escort_robot_disable_assist_50
+scr_tdm_score_escort_robot_disable_near_goal
+scr_tdm_score_escort_robot_escort
+scr_tdm_score_escort_robot_escort_goal
+scr_tdm_score_escort_robot_reboot
+scr_tdm_score_final_kill_elimination
+scr_tdm_score_first_kill
+scr_tdm_score_flag_capture
+scr_tdm_score_flag_carrier_kill_return_close
+scr_tdm_score_flag_grab
+scr_tdm_score_flag_return
+scr_tdm_score_flamethrower_kill
+scr_tdm_score_flamethrower_multikill
+scr_tdm_score_flamethrower_multikill_2
+scr_tdm_score_flamethrower_stolen
+scr_tdm_score_flashback_kill
+scr_tdm_score_focus_earn_multiscorestreak
+scr_tdm_score_focus_earn_scorestreak
+scr_tdm_score_frag_multikill
+scr_tdm_score_gelgun_kill
+scr_tdm_score_gelgun_multikill
+scr_tdm_score_gelgun_multikill_2
+scr_tdm_score_gelgun_stolen
+scr_tdm_score_gravityspikes_kill
+scr_tdm_score_gravityspikes_multikill
+scr_tdm_score_gravityspikes_multikill_2
+scr_tdm_score_gravityspikes_stolen
+scr_tdm_score_hack_3_agrs
+scr_tdm_score_hacked
+scr_tdm_score_hacked_ai_tank
+scr_tdm_score_hacked_autoturret
+scr_tdm_score_hacked_combat_robot
+scr_tdm_score_hacked_counteruav
+scr_tdm_score_hacked_dart
+scr_tdm_score_hacked_emp
+scr_tdm_score_hacked_helicopter_comlink
+scr_tdm_score_hacked_killstreak_protection
+scr_tdm_score_hacked_microwaveturret
+scr_tdm_score_hacked_mothership
+scr_tdm_score_hacked_raps
+scr_tdm_score_hacked_rcbomb
+scr_tdm_score_hacked_satellite
+scr_tdm_score_hacked_sentinel
+scr_tdm_score_hacked_supply_drop
+scr_tdm_score_hacked_uav
+scr_tdm_score_hacker_drone_hacked
+scr_tdm_score_hacker_drone_killed
+scr_tdm_score_hardpoint_kill
+scr_tdm_score_hatchet_kill
+scr_tdm_score_headshot
+scr_tdm_score_heatwave_kill
+scr_tdm_score_helicopter_comlink_kill
+scr_tdm_score_hover_rcxd_kill
+scr_tdm_score_hpm_suppress
+scr_tdm_score_hq_destroyed
+scr_tdm_score_hq_secure
+scr_tdm_score_humiliation_gun
+scr_tdm_score_kill
+scr_tdm_score_kill_ball_carrier
+scr_tdm_score_kill_confirmed
+scr_tdm_score_kill_confirmed_multi
+scr_tdm_score_kill_denied
+scr_tdm_score_kill_enemies_one_bullet
+scr_tdm_score_kill_enemy_after_death
+scr_tdm_score_kill_enemy_grenade_throwback
+scr_tdm_score_kill_enemy_injuring_teammate
+scr_tdm_score_kill_enemy_one_bullet
+scr_tdm_score_kill_enemy_that_heatwaved_you
+scr_tdm_score_kill_enemy_that_is_in_air
+scr_tdm_score_kill_enemy_that_is_using_optic_camo
+scr_tdm_score_kill_enemy_that_is_wallrunning
+scr_tdm_score_kill_enemy_that_pulsed_you
+scr_tdm_score_kill_enemy_that_used_resurrect
+scr_tdm_score_kill_enemy_when_injured
+scr_tdm_score_kill_enemy_while_both_in_air
+scr_tdm_score_kill_enemy_while_capping_dom
+scr_tdm_score_kill_enemy_while_capping_hq
+scr_tdm_score_kill_enemy_while_carrying_ball
+scr_tdm_score_kill_enemy_while_flashbanged
+scr_tdm_score_kill_enemy_while_in_air
+scr_tdm_score_kill_enemy_while_sliding
+scr_tdm_score_kill_enemy_while_stunned
+scr_tdm_score_kill_enemy_while_using_psychosis
+scr_tdm_score_kill_enemy_while_wallrunning
+scr_tdm_score_kill_enemy_who_has_flashbacked
+scr_tdm_score_kill_enemy_who_has_full_power
+scr_tdm_score_kill_enemy_who_has_high_score
+scr_tdm_score_kill_enemy_who_has_powerarmor
+scr_tdm_score_kill_enemy_who_is_speedbursting
+scr_tdm_score_kill_enemy_who_is_using_focus
+scr_tdm_score_kill_enemy_who_killed_teammate
+scr_tdm_score_kill_enemy_with_care_package_crush
+scr_tdm_score_kill_enemy_with_fists
+scr_tdm_score_kill_enemy_with_gunbutt
+scr_tdm_score_kill_enemy_with_hacked_care_package
+scr_tdm_score_kill_enemy_with_more_ammo_oic
+scr_tdm_score_kill_enemy_with_siegebot_crush
+scr_tdm_score_kill_enemy_with_their_hero_ability
+scr_tdm_score_kill_enemy_with_their_hero_weapon
+scr_tdm_score_kill_enemy_with_their_weapon
+scr_tdm_score_kill_flag_carrier
+scr_tdm_score_kill_gun
+scr_tdm_score_kill_hacker
+scr_tdm_score_kill_hacker_then_hack
+scr_tdm_score_kill_in_3_seconds_gun
+scr_tdm_score_kill_sd
+scr_tdm_score_kill_underwater_enemy_explosive
+scr_tdm_score_kill_x2_score_shrp
+scr_tdm_score_killed_annihilator_enemy
+scr_tdm_score_killed_armblades_enemy
+scr_tdm_score_killed_attacker
+scr_tdm_score_killed_bomb_defuser
+scr_tdm_score_killed_bomb_planter
+scr_tdm_score_killed_bowlauncher_enemy
+scr_tdm_score_killed_clone_enemy
+scr_tdm_score_killed_defender
+scr_tdm_score_killed_dog
+scr_tdm_score_killed_dog_assist
+scr_tdm_score_killed_enemy_while_carrying_flag
+scr_tdm_score_killed_flamethrower_enemy
+scr_tdm_score_killed_gelgun_enemy
+scr_tdm_score_killed_gravityspikes_enemy
+scr_tdm_score_killed_lightninggun_enemy
+scr_tdm_score_killed_minigun_enemy
+scr_tdm_score_killed_pineapple_enemy
+scr_tdm_score_killed_raps
+scr_tdm_score_killed_raps_assist
+scr_tdm_score_killstreak_10
+scr_tdm_score_killstreak_11
+scr_tdm_score_killstreak_12
+scr_tdm_score_killstreak_13
+scr_tdm_score_killstreak_14
+scr_tdm_score_killstreak_15
+scr_tdm_score_killstreak_16
+scr_tdm_score_killstreak_17
+scr_tdm_score_killstreak_18
+scr_tdm_score_killstreak_19
+scr_tdm_score_killstreak_2
+scr_tdm_score_killstreak_20
+scr_tdm_score_killstreak_21
+scr_tdm_score_killstreak_22
+scr_tdm_score_killstreak_23
+scr_tdm_score_killstreak_24
+scr_tdm_score_killstreak_25
+scr_tdm_score_killstreak_26
+scr_tdm_score_killstreak_27
+scr_tdm_score_killstreak_28
+scr_tdm_score_killstreak_29
+scr_tdm_score_killstreak_3
+scr_tdm_score_killstreak_30
+scr_tdm_score_killstreak_4
+scr_tdm_score_killstreak_5
+scr_tdm_score_killstreak_6
+scr_tdm_score_killstreak_7
+scr_tdm_score_killstreak_8
+scr_tdm_score_killstreak_9
+scr_tdm_score_killstreak_more_than_30
+scr_tdm_score_knife_with_ammo_oic
+scr_tdm_score_koth_secure
+scr_tdm_score_lightninggun_kill
+scr_tdm_score_lightninggun_multikill
+scr_tdm_score_lightninggun_multikill_2
+scr_tdm_score_lightninggun_stolen
+scr_tdm_score_longshot_kill
+scr_tdm_score_melee_kill
+scr_tdm_score_melee_leader_gun
+scr_tdm_score_microwave_turret_assist
+scr_tdm_score_microwave_turret_kill
+scr_tdm_score_minigun_kill
+scr_tdm_score_minigun_multikill
+scr_tdm_score_minigun_multikill_2
+scr_tdm_score_minigun_stolen
+scr_tdm_score_most_points_shrp
+scr_tdm_score_mothership_assist_kill
+scr_tdm_score_multikill_2
+scr_tdm_score_multikill_3
+scr_tdm_score_multikill_4
+scr_tdm_score_multikill_5
+scr_tdm_score_multikill_6
+scr_tdm_score_multikill_7
+scr_tdm_score_multikill_8
+scr_tdm_score_multikill_more_than_8
+scr_tdm_score_optic_camo_capture_objective
+scr_tdm_score_optic_camo_kill
+scr_tdm_score_pineapple_kill
+scr_tdm_score_pineapple_multikill
+scr_tdm_score_pineapple_multikill_2
+scr_tdm_score_pineapple_stolen
+scr_tdm_score_plane_mortar_kill
+scr_tdm_score_planted_bomb
+scr_tdm_score_power_armor_kill
+scr_tdm_score_quickly_secure_point
+scr_tdm_score_raps_kill
+scr_tdm_score_reboot_robot
+scr_tdm_score_remote_missile_kill
+scr_tdm_score_rescue_flag_carrier
+scr_tdm_score_resurrect_kill
+scr_tdm_score_retrieve_own_tags
+scr_tdm_score_revenge_kill
+scr_tdm_score_satellite_assist
+scr_tdm_score_sentinel_kill
+scr_tdm_score_sentry_gun_kill
+scr_tdm_score_share_care_package
+scr_tdm_score_shield_assist
+scr_tdm_score_shield_blocked_damage
+scr_tdm_score_shield_blocked_damage_reduced
+scr_tdm_score_siegebot_killstreak_5
+scr_tdm_score_speed_burst_kill
+scr_tdm_score_stick_explosive_kill
+scr_tdm_score_stop_enemy_killstreak
+scr_tdm_score_suicide
+scr_tdm_score_survivor
+scr_tdm_score_team_kill
+scr_tdm_score_teammate_kill_confirmed
+scr_tdm_score_thief_shutdown_enemy
+scr_tdm_score_traversal_kill
+scr_tdm_score_trophy_defense
+scr_tdm_score_uav_assist
+scr_tdm_score_uninterrupted_obit_feed_kills
+scr_tdm_score_vision_pulse_kill
+scr_tdm_score_vtol_mothership_kill
+scr_tdm_score_wager_melee_kill
+scr_tdm_score_won_match
+scr_tdm_score_x2_score_shrp
+scr_tdm_weapon_allowbetty
+scr_tdm_weapon_allowflash
+scr_tdm_weapon_allowfrag
+scr_tdm_weapon_allowrpgs
+scr_tdm_weapon_allowsatchel
+scr_tdm_weapon_allowsmoke
+scr_team_fftype
+scr_team_teamkillerplaylistbanpenalty
+scr_team_teamkillerplaylistbanquantum
+scr_teambalance
+scr_timeplayedcap
+scr_use_digital_blood_enabled
+scr_veh_alive_cleanuptimemax
+scr_veh_alive_cleanuptimemin
+scr_veh_cleanupabandoned
+scr_veh_cleanupdebugprint
+scr_veh_cleanupdrifted
+scr_veh_cleanupmaxspeedmph
+scr_veh_cleanupmindistancefeet
+scr_veh_cleanuptime_dmgfactor_deadtread
+scr_veh_cleanuptime_dmgfactor_max
+scr_veh_cleanuptime_dmgfactor_min
+scr_veh_cleanuptime_dmgfraction_curve_begin
+scr_veh_cleanuptime_dmgfraction_curve_end
+scr_veh_dead_cleanuptimemax
+scr_veh_dead_cleanuptimemin
+scr_veh_disableoverturndamage
+scr_veh_disablerespawn
+scr_veh_disappear_maxpreventdistancefeet
+scr_veh_disappear_maxpreventvisibilityfeet
+scr_veh_disappear_maxwaittime
+scr_veh_driversarehidden
+scr_veh_driversareinvulnerable
+scr_veh_explode_on_cleanup
+scr_veh_explosion_doradiusdamage
+scr_veh_explosion_husk_forcepointvariance
+scr_veh_explosion_husk_horzvelocityvariance
+scr_veh_explosion_husk_vertvelocitymax
+scr_veh_explosion_husk_vertvelocitymin
+scr_veh_explosion_maxdamage
+scr_veh_explosion_mindamage
+scr_veh_explosion_radius
+scr_veh_explosion_spawnfx
+scr_veh_health_jeep
+scr_veh_health_tank
+scr_veh_ondeath_createhusk
+scr_veh_ondeath_usevehicleashusk
+scr_veh_respawnafterhuskcleanup
+scr_veh_respawntimemax
+scr_veh_respawntimemin
+scr_veh_respawnwait_iterationwaitseconds
+scr_veh_respawnwait_maxiterations
+scr_veh_waittillstoppedandmindist_maxtime
+scr_veh_waittillstoppedandmindist_maxtimeenabledistfeet
+scr_vehicle_damage_scalar
+scr_vialsAwardedScale
+scr_wagerBet
+scr_wagerPool
+scr_wagerSideBet
+scr_wager_firstPayout
+scr_wager_firstPlayer
+scr_wager_secondPayout
+scr_wager_secondPlayer
+scr_wager_thirdPayout
+scr_wager_thirdPlayer
+scr_weapon_allowbetty
+scr_weapon_allowc4
+scr_weapon_allowflash
+scr_weapon_allowfrags
+scr_weapon_allowmines
+scr_weapon_allowrpgs
+scr_weapon_allowsatchel
+scr_weapon_allowsmoke
+scr_weaponobject_coneangle
+scr_weaponobject_debug
+scr_weaponobject_graceperiod
+scr_weaponobject_mindist
+scr_weaponobject_radius
+scr_writeConfigStrings
+scr_writeconfigstrings
+scr_xpscale
+scr_xpscaleCP
+scr_xpscaleMP
+scr_xpscaleZM
+scr_xpscaleZMPromo
+scr_xpscalecp
+scr_xpscalemp
+scr_xpscalezm
+scr_zclassic_friendlyFireDelayTime
+scr_zclassic_grenadeLauncherDudTime
+scr_zclassic_killstreakDelayTime
+scr_zclassic_score_alive_at_round_end_1
+scr_zclassic_score_alive_at_round_end_10
+scr_zclassic_score_alive_at_round_end_11
+scr_zclassic_score_alive_at_round_end_12
+scr_zclassic_score_alive_at_round_end_13
+scr_zclassic_score_alive_at_round_end_14
+scr_zclassic_score_alive_at_round_end_15
+scr_zclassic_score_alive_at_round_end_16
+scr_zclassic_score_alive_at_round_end_17
+scr_zclassic_score_alive_at_round_end_18
+scr_zclassic_score_alive_at_round_end_19
+scr_zclassic_score_alive_at_round_end_2
+scr_zclassic_score_alive_at_round_end_20
+scr_zclassic_score_alive_at_round_end_3
+scr_zclassic_score_alive_at_round_end_4
+scr_zclassic_score_alive_at_round_end_5
+scr_zclassic_score_alive_at_round_end_6
+scr_zclassic_score_alive_at_round_end_7
+scr_zclassic_score_alive_at_round_end_8
+scr_zclassic_score_alive_at_round_end_9
+scr_zclassic_score_headshot
+scr_zclassic_score_kill
+scr_zclassic_score_kill_margwa
+scr_zclassic_score_kill_meatball
+scr_zclassic_score_kill_mechz
+scr_zclassic_score_kill_parasite
+scr_zclassic_score_kill_raz
+scr_zclassic_score_kill_sentinel
+scr_zclassic_score_kill_spider
+scr_zclassic_score_kill_thrasher
+scr_zclassic_score_main_EE_quest
+scr_zclassic_score_main_EE_quest_castle
+scr_zclassic_score_main_EE_quest_factory
+scr_zclassic_score_main_EE_quest_genesis
+scr_zclassic_score_main_EE_quest_island
+scr_zclassic_score_main_EE_quest_stalingrad
+scr_zclassic_score_main_EE_quest_stalingrad_dragon
+scr_zclassic_score_main_ee_quest_all
+scr_zclassic_score_main_quest
+scr_zclassic_score_melee_kill
+scr_zclassic_score_melee_kill_meatball
+scr_zclassic_score_melee_kill_parasite
+scr_zclassic_score_open_door
+scr_zclassic_score_revive_an_ally
+scr_zclassic_score_solo_challenge_stalingrad
+scr_zclassic_score_team_challenge_stalingrad
+scr_zclassic_thrownGrenadeDudTime
+scr_zm_enable_bots
+scr_zm_use_code_enemy_selection
+searchSessionDedicatedGeoMin
+searchSessionDedicatedMaxPing
+searchSessionGeo1Weight
+searchSessionGeo2Weight
+searchSessionGeo3Weight
+searchSessionGeo4Weight
+searchSessionGeoMin
+searchSessionIsEmpty
+searchSessionMapPackFlags
+searchSessionNextTaskDelay
+searchSessionSkillWeight
+season_pass_incentive_id
+season_pass_incentive_max
+secondScreenClient
+selectedFriendIndex
+selectedFriendName
+selectedPlayerXuid
+sensitivity
+serverbrowser_show
+serverinfo
+sessionSearchMaxAttempts
+sessionTaskFailDebug
+session_nonblocking
+set_gametype
+setliveevent
+settings_allowGibbing
+settings_defaultSubtitles
+setviewpos
+shardEdgeSize
+shardShatterSizeLimitScale
+shardSplitDir
+shardSplitDir2
+shatterFxMaxDist
+shatterFxMinEdgeLength
+shieldBlastDamageProtection_120
+shieldBlastDamageProtection_180
+shieldBlastDamageProtection_30
+shieldBlastDamageProtection_60
+shieldDeployShakeDuration
+shieldDeployShakeScale
+shieldImpactBulletShakeDuration
+shieldImpactBulletShakeScale
+shieldImpactExplosionHighShakeDuration
+shieldImpactExplosionHighShakeScale
+shieldImpactExplosionLowShakeDuration
+shieldImpactExplosionLowShakeScale
+shieldImpactExplosionThreshold
+shieldImpactMissileShakeDuration
+shieldImpactMissileShakeScale
+shieldPlayerBulletProtectionDegrees
+shortversion
+shoutcastHighlightedClient
+shoutcastSelectedClient
+showMapErrors
+showVisionSetDebugInfo
+show_reticle_during_swimming
+showdrop
+showevents
+showpackets
+skill_onboardingAdjustOnExit
+skill_onboardingEnabled
+skill_onboardingEnter
+skill_onboardingExit
+skill_onboardingGames
+skill_onboardingThreshold
+skill_scoreBeta
+skill_scoreRange
+skill_teamBeta
+skill_teamRange
+skipChunkCheck
+skip_contract_rewards
+skipto
+skipto_complete
+skipto_jump
+slam_air_accel
+slam_air_downward_angle
+slam_air_enabled
+slam_air_frictionMax
+slam_air_frictionMin
+slam_air_maxUpwardsVelocity
+slam_air_speed
+slam_air_upBoostAccel
+slam_air_view_delta
+slam_blur_amount
+slam_blur_enabled
+slam_blur_radius_inner
+slam_blur_radius_outer
+slam_blur_time_in
+slam_blur_time_out
+slam_clearance_check_dist
+slam_clearance_check_radius
+slam_debug
+slam_enabled
+slam_player_trace_offset
+slam_time_in_air_timeout_ms
+slam_time_ms
+slam_wallrun_enabled
+slide_allowEarlyMoveTime
+slide_allow_hold_for_prone
+slide_allow_shooting
+slide_angle1
+slide_angle2
+slide_blur_amount
+slide_blur_enabled
+slide_blur_radius_inner
+slide_blur_radius_outer
+slide_blur_time_in
+slide_blur_time_out
+slide_cameraAlignmentEaseMode
+slide_cameraClamp
+slide_cameraPitchOffset
+slide_cameraPitchRate
+slide_cameraRotateTimeMs
+slide_clearance_check_dist
+slide_clearance_check_radius
+slide_deadzoneTweek
+slide_debug
+slide_delayTime
+slide_downhillFriction_amount
+slide_enable
+slide_enable_tweak_left_right
+slide_fallDamageReduction
+slide_forceBaseSlide
+slide_frictionScale
+slide_friction_amount
+slide_friction_duration_ms
+slide_hold_change_stance_time_air_ms
+slide_hold_change_stance_time_ms
+slide_jetFxDuration
+slide_lensInTransRate
+slide_lensOutTransRate
+slide_maxTime
+slide_maxTimeBase
+slide_maxTimeReduced
+slide_min_continue_velocity
+slide_min_required_airVelocity
+slide_min_required_velocity
+slide_min_sprint_time_ms
+slide_outAllowSprint
+slide_outShouldScaleSpeed
+slide_outSpeedScale
+slide_player_trace_offset
+slide_required_airAngle
+slide_speed
+slide_speedBase
+slide_speedReduced
+slide_subsequentSlideScale
+slide_subsequentSlideTime
+slide_tap_button_to_slide
+slide_to_sprint_friction_time_scale
+slide_under_geo_trace_dist
+slide_under_geo_trace_radius
+slide_uphillFriction_amount
+slide_viewMovementEnabled
+slide_view_angles
+slide_view_anglesTransitionTime
+slide_view_bounceAngles
+slide_view_bounceAnglesPeriod
+slide_view_slide_height
+sm_enableViewmodel
+sm_fastSunShadow
+sm_lightScore_eyeProjectDist
+sm_lightScore_spotProjectFrac
+sm_showFXShadowmap
+sm_showLightShadowmap
+sm_showLightShadowmapScale
+sm_showSpotAxis
+sm_showSunOverlay
+sm_showSunOverlayScaleBias
+sm_showTris
+sm_showViewmodelShadowmap
+sm_spotPolygonOffsetBias
+sm_spotPolygonOffsetScale
+sm_spotShadowLargeRadiusScale
+sm_strictCull
+sm_sunAlwaysCastsShadow
+sm_sunPolygonOffsetBias
+sm_sunPolygonOffsetScale
+smpDraw2D
+smpGlass
+smpScanForCrosshairEntity
+smpUpdatePlayerNames
+snaps
+snd_assert_on_animation_prime
+snd_assert_on_duck_stop
+snd_assert_on_enqueue
+snd_assert_on_play
+snd_assert_on_stop
+snd_autoSim
+snd_autosim_window
+snd_boat_current_rpm
+snd_boat_engine_off
+snd_boat_lerp_rpm
+snd_boat_pitch_high_max
+snd_boat_pitch_high_min
+snd_boat_pitch_idle_max
+snd_boat_pitch_idle_min
+snd_boat_pitch_low_max
+snd_boat_pitch_low_min
+snd_boat_pitch_med_max
+snd_boat_pitch_med_min
+snd_boat_rpm_high_fin_end
+snd_boat_rpm_high_start
+snd_boat_rpm_idle_end
+snd_boat_rpm_idle_fout_start
+snd_boat_rpm_low_end
+snd_boat_rpm_low_fin_end
+snd_boat_rpm_low_fout_start
+snd_boat_rpm_low_start
+snd_boat_rpm_med_end
+snd_boat_rpm_med_fin_end
+snd_boat_rpm_med_fout_start
+snd_boat_rpm_med_start
+snd_boat_rpm_scalar
+snd_boat_using_lerp_rpm
+snd_boat_water_fast_min
+snd_boat_water_idle_max
+snd_boat_water_pitch_max
+snd_boat_water_slow_max
+snd_boat_water_slow_min
+snd_debug_alias_filter
+snd_debug_context_type
+snd_debug_context_value
+snd_debug_duck
+snd_disable_ducks
+snd_disable_play_once
+snd_dlpf_attenuation
+snd_dlpf_max_distance
+snd_dlpf_min_distance
+snd_dopplerRate
+snd_dopplerScale
+snd_draw3D
+snd_dry_scale
+snd_dsp_futz
+snd_dsp_meters
+snd_earlyverb_force
+snd_earlyverb_scale
+snd_enable_pitch
+snd_farverb_force
+snd_farverb_scale
+snd_flux_separation
+snd_force_pfutz
+snd_futz_distance_ratio
+snd_futz_force
+snd_gfutz_override
+snd_global_pitch
+snd_isbig_distance
+snd_jetgun_loop_start
+snd_jetgun_pitch_end
+snd_jetgun_pitch_start
+snd_levelFadeTime
+snd_losOcclusion
+snd_master_override
+snd_max_ram_voice
+snd_max_stream_voice
+snd_minigun_loop_start
+snd_minigun_pitch_end
+snd_minigun_pitch_start
+snd_music_stress
+snd_mute_alias_substring
+snd_nearfar_max
+snd_nearfar_min
+snd_nearverb_force
+snd_nearverb_scale
+snd_occlusion_attenuation
+snd_occlusion_rate
+snd_pitch_timescale
+snd_playing_priority_boost
+snd_reverb_override
+snd_reverb_prefader
+snd_skip_muted_sounds
+snd_solo_alias_substring
+snd_solo_loaded
+snd_solo_snapshot_group
+snd_solo_streams
+snd_speakerConfiguration
+snd_start_alias
+snd_start_alias_distance
+snd_stop_alias
+snd_stress
+snd_throttle_reduce_vol
+snd_throttle_time_held_down
+snd_timescale_filter
+snd_vo_implementation_mode
+snd_voice_duck_override
+snd_wet_scale
+spawnPingPerkFadeTime
+spawnsystem_allow_culling
+spawnsystem_allow_non_team_spawns
+spawnsystem_badspawn_aggression_delay
+spawnsystem_badspawn_damage_delay
+spawnsystem_badspawn_force_record
+spawnsystem_convert_spawns_to_structs
+spawnsystem_danger_time
+spawnsystem_debug
+spawnsystem_debug_archive
+spawnsystem_debug_best_points
+spawnsystem_debug_current_player
+spawnsystem_debug_explored
+spawnsystem_debug_influencer_pulse
+spawnsystem_debug_influencer_types
+spawnsystem_debug_influencers
+spawnsystem_debug_list
+spawnsystem_debug_liveedit
+spawnsystem_debug_player
+spawnsystem_debug_point_weights
+spawnsystem_debug_points
+spawnsystem_debug_reduced_logging
+spawnsystem_debug_showclients
+spawnsystem_debug_sideswitched
+spawnsystem_debug_team
+spawnsystem_debug_visibility
+spawnsystem_debug_visibility_time
+spawnsystem_demo_enable_parsing
+spawnsystem_demo_max_written
+spawnsystem_influencer_sight_line
+spawnsystem_influencer_sight_line_min_length
+spawnsystem_influencer_sight_line_push_through
+spawnsystem_influencer_sight_line_update_interval
+spawnsystem_old_vis_mask
+spawnsystem_pause_weight_update
+spawnsystem_player_explored_radius
+spawnsystem_score_cull_min_points
+spawnsystem_score_cull_percent
+spawnsystem_score_cull_time_max
+spawnsystem_score_cull_time_min
+spawnsystem_sight_check_dual_point
+spawnsystem_sight_check_dual_point_radius
+spawnsystem_sight_check_max_distance
+spawnsystem_sight_check_max_distance_ai
+spawnsystem_sight_check_sentient_ai
+spawnsystem_sight_check_sentient_players
+spawnsystem_sight_height_offset
+spawnsystem_sight_use_player_current_view_height
+spawnsystem_use_code_point_enabled
+spawnsystem_user_selects_spawn
+speedburst_blur_amount
+speedburst_blur_enabled
+speedburst_blur_radius_inner
+speedburst_blur_radius_outer
+speedburst_blur_time_in
+speedburst_blur_time_out
+splitscreen
+splitscreen_controller
+splitscreen_horizontal
+splitscreen_playerCount
+spmode
+sprintLeap_enabled
+sprintLeap_forwardVelocityScale
+sprintLeap_groundTraceDist
+sprintLeap_height
+sprintLeap_minSprintTimeMs
+sprintLeap_minVolumeTimeMs
+sprintLeap_traceForwardIncrament
+sprintLeap_traceForwardMax
+sprint_allowRechamber
+sprint_allowReload
+sprint_allowRestore
+sprint_capSpeedEnabled
+sprint_controlScheme
+sprint_focalLength
+sprint_fx_enabled
+sprint_lensEnabled
+sprint_lensInTransRate
+sprint_lensOutTransRate
+sprint_maxTime
+sprint_minTime
+sprint_minVelocity
+sprint_minVelocitySwimming
+sprint_rampIn
+sprint_recoveryDelay
+sprint_recoveryExtraDelay
+sprint_recoveryTime
+sprint_rollDeg
+sprint_rollEnabled
+sprint_rollTransTime
+sprint_rumble_enabled
+sprint_shake_duration
+sprint_shake_enabled
+sprint_shake_scale
+sprint_stopOnWeaponRest
+sprint_weaponScalarEnabled
+sprintleap_check_dist
+st_LODDistScale
+st_forceLOD
+standardPrimaryAttachmentCount
+standardSecondaryAttachmentCount
+stat_version
+statsCheckXuidBeforeStatsUpload
+statsErrorBackup
+statsErrorNormal
+statsErrorOtherPlayer
+statsErrorStable
+statsLocationFatal
+statsVersionCP
+statsVersionFR
+statsVersionMP
+statsVersionZM
+stats_version_check
+status
+steamLobby_frameEnable
+steamLobby_frameFailInterval
+steamLobby_frameInterval
+steamLobby_frameKeepAliveInterval
+steamP2P_Enable
+steamWorkshop_Enable
+stopspeed
+storage_auto_reset
+storage_backoff
+storage_maxfailures
+storage_offline
+storeMapPackMaskToStats
+store_item_viewed_timer
+streamMBPerSecond
+survey_chance
+survey_count
+sv_FFCheckSums
+sv_FFNames
+sv_FakeRemoteClient
+sv_SnapshotPeek
+sv_allowAnonymous
+sv_allowDownload
+sv_antilagAnim
+sv_archiveClientsPositions
+sv_assistWorkers
+sv_authenticating
+sv_bitfieldTracking
+sv_botThinkType
+sv_botsPressAttackBtn
+sv_bullet_range
+sv_capture_ping_data
+sv_cheats
+sv_clientArchive
+sv_clientFpsLimit
+sv_clientFrameRateFix
+sv_clientSideBullets
+sv_clientSideVehicles
+sv_clientUpdateDistance
+sv_clientside
+sv_connectTimeout
+sv_connectionLogProbability
+sv_connectionLogSamplesPerSecond
+sv_connecttimeout
+sv_debugAntiLagRewind
+sv_debugConstantConfigStrings
+sv_debugMessageKey
+sv_debugPacketContents
+sv_debugPacketContentsForClientThisFrame
+sv_debugPacketContentsQuick
+sv_debugPlayerstate
+sv_debugRate
+sv_debugReliableCmds
+sv_detailedScriptErrors
+sv_disableClientConsole
+sv_dwlsgerror
+sv_dynsnaps
+sv_earlyEndSnapshots
+sv_endGameIfISuck
+sv_endmatch
+sv_error_on_baseline_failure
+sv_expensive_bullet_time
+sv_fakeServerLoad
+sv_fakeServerLoadRand
+sv_floodProtect
+sv_forceUpdateInterval
+sv_forcelicensetype
+sv_forceunranked
+sv_fx_blockMinDist
+sv_generateConstBaselines
+sv_greedylock
+sv_hitFXFrustumCutoff
+sv_hostname
+sv_ignorePing
+sv_iwdNames
+sv_iwds
+sv_jqprof_continuous
+sv_jqprof_enabled
+sv_jqprof_frequency
+sv_jqprof_profileCheckpointFrames
+sv_jqprof_threshold
+sv_keywords
+sv_kickBanTime
+sv_leaderboardwriteInterval
+sv_loadMyChanges
+sv_mapRotation
+sv_mapRotationCurrent
+sv_mapSwitch
+sv_mapSwitchPerloadFrontendReserveMB
+sv_mapSwitchPerloadFrontendReservePagesPerFrame
+sv_mapSwitchPerloadFrontendStreamerFrames
+sv_mapSwitchPreloadFrontend
+sv_mapSwitch_rat
+sv_mapcrc
+sv_mapname
+sv_maprotationcurrent
+sv_mapswitch
+sv_maxHappyPingTime
+sv_maxPhysExplosionSpheres
+sv_maxRate
+sv_maxclients
+sv_maxping
+sv_momentumPercent
+sv_network_fps
+sv_nextmap
+sv_noname
+sv_onlineHostSnapshotRateThrottled
+sv_packet_info
+sv_padPackets
+sv_paused
+sv_penetrationCount
+sv_playlistFetchInterval
+sv_potm_debug
+sv_printMessageSize
+sv_privateClients
+sv_privateClientsForClients
+sv_privatePassword
+sv_privateclients
+sv_pure
+sv_rateBoosting
+sv_rateBoostingAllowUnackDeltas
+sv_rateBoostingDebugForceSuspend
+sv_rateBoostingMaxUploadUsage
+sv_rateBoostingMinUploadScale
+sv_rateBoostingRecoverTime
+sv_rateBoostingSuspendBadFramesCPU
+sv_rateBoostingSuspendBadFramesCPUThreshold
+sv_rateBoostingSuspendBadFramesCPUTimeout
+sv_rateBoostingSuspendedMaxUploadUsage
+sv_reconnectlimit
+sv_referencedFFCheckSums
+sv_referencedFFNames
+sv_referencedIwdNames
+sv_referencedIwds
+sv_restrictedTempEnts
+sv_running
+sv_saveGameSkipto
+sv_sendCmdAngles
+sv_serverLogClientPings
+sv_showAverageBPS
+sv_showCommands
+sv_showHuffmanData
+sv_showPingSpam
+sv_skipto
+sv_snapshot_skip_count
+sv_timeout
+sv_useAnimCulling
+sv_useMapPreloading
+sv_userCmdLimiter
+sv_vac
+sv_voice
+sv_voiceQuality
+sv_writeConfigStrings
+sv_wwwBaseURL
+sv_wwwDlDisconnected
+sv_wwwDownload
+sv_zlib_threshold
+sv_zombietime
+sys_threadWatchdogTimeoutLive
+systemUiActive
+systeminfo
+systemlink
+tacticalWalkDirection
+take
+teamOpsEnabled
+teamOpsKillsCountTrigger
+teamOpsName
+teamOpsPreanounceTime
+teamOpsStartDelay
+teamsplitter_verbose
+tell
+tempCPOnline
+tempbanclient
+tempbanuser
+terriblePing
+testMissingContentPacks
+test_levels_selection
+tgraph_debugClearancePointId
+tgraph_debugDrawPointNavFace
+tgraph_debugDrawPoints
+tgraph_debugShowStats
+tgraph_debugTargetPointId
+tgraph_debugVisMapDrawNonVisible
+tgraph_debugVisMapPointId
+throwback_enabled
+tickerStandardWidth
+tickerWidescreenWidth
+ticker_menu_context
+timeUntilDropRange
+timescale
+tm_currentErrorPage
+tm_failsThreshold
+tm_logTimeLimit
+tm_pendingeThreshold
+tm_startedThreshold
+tm_succeedsThreshold
+tm_taskManagerDebug
+tm_taskTrackerOn
+tm_typeToDisplay
+totalCoverage_blockFriendlyMinimap
+totalCoverage_debug
+totalCoverage_enemy_minimap
+totalCoverage_friendly_minimap
+totalCoverage_higherGroundTest
+totalCoverage_offsetToCoverage
+totalCoverage_smokeInTime
+totalCoverage_smokeOutTime
+totalSampleClientTrack
+totalSampleRateBlackBox
+totalSampleRateQoS
+totalSampleRateSurvey
+total_paintjobs
+tquery_drawQuery
+tquery_drawQueryDuration
+tracer_debugDraw
+tracer_explosiveColor1
+tracer_explosiveColor2
+tracer_explosiveColor3
+tracer_explosiveColor4
+tracer_explosiveColor5
+tracer_explosiveOverride
+tracer_explosiveWidth
+tracer_firstPersonMaxWidth
+tracer_stoppingPowerColor1
+tracer_stoppingPowerColor2
+tracer_stoppingPowerColor3
+tracer_stoppingPowerColor4
+tracer_stoppingPowerColor5
+tracer_stoppingPowerColor6
+tracer_stoppingPowerOverride
+tracer_stoppingPowerWidth
+tracer_thermalWidthMult
+traverse_mode
+trm_adsDisablesAutoComplete
+trm_alignViewToSurfaceTime
+trm_autoCompleteJumpTimeMs
+trm_autocomplete_require_jump
+trm_checkRadius
+trm_checkRange
+trm_checkRangeVault
+trm_clearanceTraceZEpsilon
+trm_clearanceWidthAdd
+trm_deadZone
+trm_debug
+trm_doublejumpPreventReengageTime
+trm_doublejump_out_frac_on_high_forward_100
+trm_doublejump_out_frac_on_high_forward_140
+trm_doublejump_out_frac_on_low_forward
+trm_doublejump_out_frac_on_low_left
+trm_doublejump_out_frac_on_low_right
+trm_doublejump_out_frac_on_med_forward
+trm_doublejump_out_frac_on_med_left
+trm_doublejump_out_frac_on_med_right
+trm_doublejump_out_frac_over_high_forward_100
+trm_doublejump_out_frac_over_high_forward_140
+trm_doublejump_out_frac_over_high_forward_75
+trm_doublejump_out_frac_over_low_forward
+trm_doublejump_out_frac_over_low_forward_vault
+trm_doublejump_out_frac_over_low_left
+trm_doublejump_out_frac_over_low_right
+trm_doublejump_out_frac_step
+trm_enable
+trm_enableDoubleJumpOut
+trm_enabled
+trm_entitiesBlockForwardTrace
+trm_fastmantle_scalar
+trm_highPitchDegrees
+trm_highYawDegrees
+trm_initMinForwardMove
+trm_initMinSideMove
+trm_input
+trm_inputRange
+trm_inputRangeBack
+trm_inputRangeSide
+trm_ledgeAngleOffset
+trm_ledgeCapsuleRadius
+trm_ledgeHeight_onHigh
+trm_ledgeHeight_onLow
+trm_ledgeHeight_onMed
+trm_ledgeHeight_overHigh
+trm_ledgeHeight_overLow
+trm_ledgeHeight_overMed
+trm_ledgeHeight_step
+trm_maxBackMantleHeight
+trm_maxHurdleDistance
+trm_maxSideMantleHeight
+trm_maxVerticalityRatio
+trm_minFacingRatio
+trm_minLedgeHeight
+trm_movefrac_on_high_forward_100
+trm_movefrac_on_high_forward_140
+trm_movefrac_on_low_forward
+trm_movefrac_on_low_left
+trm_movefrac_on_low_right
+trm_movefrac_on_med_forward
+trm_movefrac_on_med_left
+trm_movefrac_on_med_right
+trm_movefrac_over_high_forward_100
+trm_movefrac_over_high_forward_140
+trm_movefrac_over_high_forward_75
+trm_movefrac_over_low_forward
+trm_movefrac_over_low_forward_vault
+trm_movefrac_over_low_left
+trm_movefrac_over_low_right
+trm_movefrac_step
+trm_pitchRecenterTime
+trm_safeHurdleZ
+trm_stepDistance
+trm_step_contact_frac
+trm_timescale_on_high_forward_100
+trm_timescale_on_high_forward_140
+trm_timescale_on_low_forward
+trm_timescale_on_low_left
+trm_timescale_on_low_right
+trm_timescale_on_med_forward
+trm_timescale_on_med_left
+trm_timescale_on_med_right
+trm_timescale_over_high_forward_100
+trm_timescale_over_high_forward_140
+trm_timescale_over_high_forward_75
+trm_timescale_over_low_forward
+trm_timescale_over_low_forward_vault
+trm_timescale_over_low_left
+trm_timescale_over_low_right
+trm_timescale_step
+trm_viewCenterStart
+trm_viewCenterTimeMs
+trm_weaponRaisedelayMs
+tu10_ClearWeapNextHeldInputOnSwitchWeaponCmd
+tu10_cleanupRagdollsOnExit
+tu10_enableCyclicalDailyChallenges
+tu10_enableHighestAvailableDLCEntitlementCheck
+tu10_metPlayerClearOnUserSignedOut
+tu10_mpSwitchSpecialistWeaponExploitFix
+tu10_validationFatal
+tu11_AllowIgnoreDisabledWeaponCyclingInActionSlotUsageAllowed
+tu11_IgnoreItemsWithPLevel100InIsItemLockedForChallenge
+tu11_cleanupRagdollsOnDemoJump
+tu11_clearMpVehicleWaterMaterial
+tu11_dontUpdateWeaponPosFracWhenLinked
+tu11_enableClassicMode
+tu11_enableVehicleMode
+tu11_fixForMultishotRechamberWeaponSwitchIssue
+tu11_lootCryptoAutoRetry
+tu11_matchmakingPriorityDOA
+tu11_matchmakingPriorityDOAIgnoreTime
+tu11_matchmakingPriorityMP
+tu11_matchmakingPriorityMPIgnoreTime
+tu11_maxQuadCacheAlloc
+tu11_mpNewCodCasterKeyline
+tu11_mpReconstructTrailsForStationaryEntities
+tu11_programaticallyColoredGameFX
+tu11_uploadStreamFailureFlag
+tu11_useLootXPDueStat
+tu12_delayFFOTD
+tu12_mpMaintainMissileSpeed
+tu12_switchToWeaponImmediateFix
+tu12_zmHideLegsWithViewmodel
+tu13_recordContentAvailable
+tu14_skipPrimaryGroupCheck
+tu16_SLFreeStringFix
+tu16_physicsPushOutThreshold
+tu19_orbis_presence_localizations
+tu1_aiPathableMaterials
+tu1_build
+tu1_pickupParentlessGrenade
+tu1_queuedEventInterval
+tu1_saveGameAiProximityCheck
+tu1_vehicleCollisionCacheSetup
+tu1_zombiePaintJobsEnabled
+tu2_catchMissingRbEndFrame
+tu2_cscGetDStatCP
+tu2_disableChallengesForLockedItemsInArena
+tu2_forceConnectionStateTransitionSpinnerOn
+tu2_logLootToKVS
+tu3_lobby_dropRejoiningClients
+tu3_onlineSavegameErrorFatal
+tu4_burnDuplicates
+tu4_enableBonusCryptokeysHint
+tu4_enableCodPoints
+tu4_enableMeleeWeaponFlourish
+tu4_firstValidCurrencyID
+tu4_newSysInfo
+tu4_newSysInfoUpdateRate
+tu4_partyPrivacyLuaCheck
+tu4_partyPrivacyUseGlobal
+tu4_refetchBalanceOnUpdate
+tu4_skipStatStatusCache
+tu4_storageClearTargetQueue
+tu4_storageControllerSwapProtection
+tu4_zmChangePlayerStandOnSentients
+tu5_defaultMaxHeroAttachmentsToZero
+tu5_dwNetFatalErrors
+tu5_enableVialsOwed
+tu5_gadgetThiefSupport
+tu5_live_friends_signedin_fetch
+tu5_partyStatusGetInterval
+tu5_recordXuidMismatch
+tu5_vialsOwedCheckDelay
+tu5_zmChangeOffhandGearWeaponChange
+tu5_zmChangeSlamUseWalkable
+tu5_zmEnableClipOnlyWeaponFlourish
+tu5_zmPathDistanceCheckTolarance
+tu6_doublePistolSpreadAmmo
+tu6_mpMeleeAttachmentObitIcon
+tu6_mpReconstructTrailForOtherPlayers
+tu6_mpReconstructTrailForTriboltCrossbow
+tu6_mpStackFirePitchChange
+tu6_player_shallowWaterHeight
+tu7_enableBundles
+tu7_mpDoNotSetBallisticAnglesWhenLinked
+tu7_mpNoVehicleNeutralTeamTargetHighlight
+tu7_mpUseImprovedMissileStickAngles
+tu7_mpUseNewBounceMissileMayStopFleshLogic
+tu7_zmInAirDisabledTimeoutTime
+tu8_ai_enableBTInterruptPriority
+tu8_animTimeResetInterval
+tu8_enableDurableProductsExchange
+tu8_mpChallengesGroupPrereqFix
+tu8_mpLootWeaponPurchasedCheckEnabled
+tu8_mtx_enabled
+tu8_platformSessionOrbisValidateNpEventResult
+tu8_trmRestrictionLevel
+tu8_yySlideExploitFix
+tu9_backupBadDecompress
+tu9_backupBadSpace
+tu9_canSplitInProgressUnbalancedTeams
+tu9_entryExitImpactSurfaceNormalFix
+tu9_fileshareCommunityIncludeEmptyDescriptors
+tu9_highestAvailableDLC
+tu9_hostLaunchCheckMinPlayer
+tu9_hostLaunchCheckUnbalancedTeams
+tu9_hostPrivateSessions
+tu9_jitterModExploitFix
+tu9_skipPerlocalClientAllocation
+tu9_ui_zmLobbyEEEnabled
+tu9_yySlideExploitFix
+tu9_zmDisableMeleeChargeJump
+turretPlayerAvoidScale
+turret_placement_debug
+turret_placement_feet_offset
+turret_placement_feet_trace_dist_z
+turret_placement_trace_dist
+turret_placement_trace_dist_wallmount
+turret_placement_trace_dist_zm
+turret_placement_trace_maxs
+turret_placement_trace_min_normal
+turret_placement_trace_mins
+turret_placement_trace_pitch
+turret_placement_trace_radius_canon_safety
+turretplacement_traceOffset
+turretplacement_useTraceOffset
+twitch_app_version
+twitch_audio_volume
+twitch_client_id
+twitch_mixpanel_token
+twitch_platform_name
+twitch_player_name
+twitch_stats_update_interval
+typeWriterCod7LetterFXTime
+ufo
+ui_DSPPromotionInterval
+ui_SPReminderPopupInterval
+ui_abortKeyboardOnUIChange
+ui_allowDisplayContinue
+ui_allow_classchange
+ui_allow_controlschange
+ui_allow_teamchange
+ui_allowvote
+ui_autoContinue
+ui_autoControlledPlayer
+ui_badWordMaxTaskWaits
+ui_badWordSeverity
+ui_bigFont
+ui_blocksaves
+ui_blurAmount
+ui_blurDarkenAmount
+ui_blurTime
+ui_borderLowLightScale
+ui_buildLocation
+ui_buildSize
+ui_busyBlockIngameMenu
+ui_checksum_enabled
+ui_cinematicsTimestamp
+ui_codexindex_unlocked
+ui_combatCurrScrollBarPos
+ui_creditSkipTo
+ui_creditsScrollScale
+ui_currFocusList
+ui_currFocusStates
+ui_currMenuNameList
+ui_currentNetMap
+ui_custom_name
+ui_customerServiceURL
+ui_damage_widget_hide_delay
+ui_deadquote
+ui_dedicated
+ui_demoname
+ui_detailedMM
+ui_disablePSControlWidgets
+ui_disable_blur
+ui_disable_lan
+ui_display_aar
+ui_doa_unlocked
+ui_drawBuildNumber
+ui_drawCrosshair
+ui_drawSpinnerAfterMovie
+ui_dropdownListMax
+ui_dropdownMax
+ui_emblemDisableGroups
+ui_enableAllHeroes
+ui_enableConnectionMetricGraphs
+ui_enableDSPPromotion
+ui_enableSPReminderPopup
+ui_enableZMHDFeaturedCard
+ui_enabled
+ui_errorMessage
+ui_errorMessageDebug
+ui_errorTitle
+ui_errorUndefLocals
+ui_error_callstack_ship
+ui_error_report
+ui_error_report_delay
+ui_execdemo
+ui_execdemo_beta
+ui_execdemo_cp
+ui_execdemo_e3
+ui_execdemo_gamescom
+ui_execdemo_gamescom_host
+ui_extraBigFont
+ui_fakeCurrentMap
+ui_forceQueue
+ui_framesBetweenButtonPromptTraces
+ui_framesBetweenObjectiveLOSTraces
+ui_freeCursorAcceleration
+ui_freeCursorParallax
+ui_freeCursorSpeed_Focus
+ui_freeCursorSpeed_NoFocus
+ui_friendlyfire
+ui_friendsListOpen
+ui_fxFontFalloff
+ui_fxFontGlowSize
+ui_fxFontOutlineSize
+ui_fxFontShadowOffset
+ui_fxFontShadowSize
+ui_fxFontTweaks
+ui_gametype
+ui_generic_status_bar
+ui_guncycle
+ui_heatMapColor
+ui_heatMapColorForPlayer
+ui_heroExtracamResolution
+ui_hideLeaderboards
+ui_hideMiniLeaderboards
+ui_hostname
+ui_hud_hardcore
+ui_hud_minimap_hide
+ui_hud_obituaries
+ui_hud_showobjicons
+ui_hud_visible
+ui_inGameStoreVisible
+ui_isDLCPopupEnabled
+ui_keepLoadingScreenUntilAllPlayersConnected
+ui_keyboard_dvar_edit
+ui_keyboardtitle
+ui_levelEra
+ui_level_sv
+ui_liveEventViewerOpen
+ui_lobbyDebugAgreeCountLoc
+ui_lobbyDebugAgreementLoc
+ui_lobbyDebugBaseX
+ui_lobbyDebugBaseY
+ui_lobbyDebugClients
+ui_lobbyDebugDWSessionLoc
+ui_lobbyDebugExtraInfoLoc
+ui_lobbyDebugGameClientSessionLoc
+ui_lobbyDebugGameHostSessionLoc
+ui_lobbyDebugJoinLoc
+ui_lobbyDebugLobbyTasksLoc
+ui_lobbyDebugMsgLoc
+ui_lobbyDebugOverlay
+ui_lobbyDebugPlatformSessionLoc
+ui_lobbyDebugPrivateClientSessionLoc
+ui_lobbyDebugPrivateHostSessionLoc
+ui_lobbyDebugResCountLoc
+ui_lobbyDebugReservationLoc
+ui_lobbyDebugSessionSQJ
+ui_lobbyDebugVis
+ui_lobbyDebugVoice
+ui_lobbyDebugVoiceClientLoc
+ui_lobbyDebugVoiceHostLoc
+ui_lobbypopup
+ui_mapname
+ui_menuLvlNotify
+ui_motd
+ui_mousePitch
+ui_mpTheaterEnabled
+ui_mpWagerMatchEnabled
+ui_netSource
+ui_newStartMenu
+ui_numTacticalWidgets
+ui_options_open
+ui_paintshopEditDarkening
+ui_playLogoMovie
+ui_playerListOpen
+ui_playerNemesisColor
+ui_playerSquadColor
+ui_playlistPopulationRefreshTime
+ui_readingSaveDevice
+ui_safearea
+ui_saveMessageMinTime
+ui_scorelimit
+ui_scrollSpeed
+ui_sessionModeLocation
+ui_showFocus
+ui_showGameModeHistory
+ui_showList
+ui_showNewestLeaderboards
+ui_showSessionMode
+ui_showmap
+ui_singlemission
+ui_smallFont
+ui_smp_hud_models
+ui_snapToNearestPixel
+ui_splitscreen
+ui_storeButtonPressed
+ui_supportURL
+ui_ten_classes
+ui_textPaddingOverride
+ui_text_endreason
+ui_timelimit
+ui_timescale
+ui_totalDLCReleased
+ui_tu11_splitscreen_scoreboard_snap_check
+ui_useloadingmovie
+ui_useoutromovie
+ui_usingFreeCursor
+ui_weakpointIndicatorMedium
+ui_weakpointIndicatorNear
+ui_weapon_tiers
+ui_zm_gamemodegroup
+ui_zm_mapstartlocation
+uiscript_debug
+unbanuser
+unbind
+unbind2
+unbindall
+unbindall2
+unifiedLens_enabled
+unifiedLens_minFocalLength
+unifiedLens_minVelocityThreshold
+unifiedLens_scaleFinal
+unifiedLens_scaleInitial
+unifiedLens_transTimeIn
+unifiedLens_transTimeOut
+unsubscriptionCooloffTimer
+upload_bps_dedicated
+upload_bps_demosystem
+upload_bps_perplayer
+useClassSets
+useFakeEmblems
+useFastFile
+useForceEliteCmds
+useLargeRadius
+useMapPreloading
+usePaintshopData
+useRadius
+useSvMapPreloading
+useWalkPathnodesMode
+vc_LUT
+vc_SNAP
+vehControlMode
+vehGunnerSplashDamage
+vehHelicopterAlwaysFaceCamera
+vehHelicopterAlwaysFaceCameraRate
+vehHelicopterHeadSwayDontSwayTheTurret
+vehHelicopterJitterJerkyness
+vehLocationalVehicleSeatEntry
+vehLockTurretToPlayerView
+vehNPCThrottleMultiplier
+vehPlaneFakeLiftForce
+vehPlaneGravityForce
+vehPlaneInvertPitch
+vehPlaneJetControls
+vehPlaneLiftForce
+vehPlaneLowSpeed
+vehPlanePitchAccel
+vehPlaneRollAccel
+vehPlaneRollDeadZone
+vehPlaneYawFromRollScale
+vehPlaneYawSpeed
+vehRecenterDelay
+vehanim_debug
+vehanim_enable
+vehicleMouseExtraTurnSpeed
+vehicle_collision_prediction_crash_time
+vehicle_collision_prediction_time
+vehicle_damage_max_shielding
+vehicle_damage_zone_front
+vehicle_damage_zone_rear
+vehicle_damage_zone_side
+vehicle_damage_zone_under
+vehicle_destructible_damage_bouncing_betty
+vehicle_destructible_damage_bouncing_betty_radius
+vehicle_destructible_damage_grenade
+vehicle_destructible_damage_grenade_radius
+vehicle_destructible_damage_projectile_radius
+vehicle_destructible_damage_satchel_charge
+vehicle_destructible_damage_satchel_charge_radius
+vehicle_destructible_damage_sticky_grenade
+vehicle_destructible_damage_sticky_grenade_radius
+vehicle_infinite_boost
+vehicle_perk_boost_duration_seconds
+vehicle_piece_damagesfx_threshold
+vehicle_push_during_mantle
+vehicle_riding
+vehicle_selfCollision
+vehicle_sounds_cutoff
+vehicle_spline_arrows
+vehicle_strafe_control_dead_zone
+vehicle_switch_seat_delay
+vehicle_useRadius
+version
+vid_xpos
+vid_ypos
+viewpos
+vm_sendNotifyAndCallbackOnSpawn
+voiceDegrade
+voice_debug
+voice_enabled
+vote
+waitForInitial
+waitForStreamer
+waitOnStatsTimeout
+walkMove_avoidanceDot
+walkMove_avoidanceEnabled
+walkMove_avoidanceMinSpeedScale
+walkMove_avoidanceProbeDistance
+walkMove_avoidanceSpeedDifferentialThreshold
+wallRun_avoidanceEnabled
+wallRun_avoidanceMinMaintainSpeed
+wallRun_avoidanceMinSpeedScale
+wallRun_avoidanceProbeDistance
+wallRun_beginFallOnDamage
+wallRun_cameraAlignmentEaseMode
+wallRun_cameraAutoCurveAngleFactor
+wallRun_cameraAutoCurveEnabled
+wallRun_cameraAutoCurveTimeMs
+wallRun_cameraAutoCurveTraceDistance
+wallRun_cameraClamp
+wallRun_cameraInputDeadTimeMs
+wallRun_cameraRollSpeed
+wallRun_cameraRotateTimeMs
+wallRun_cameraYaw
+wallRun_cameraYawOffset
+wallRun_cameraYawRate
+wallRun_combatEnable
+wallRun_debug
+wallRun_downStepVelocity
+wallRun_enabled
+wallRun_exitMoveDampening
+wallRun_facingMaxPitch
+wallRun_facingMinSin
+wallRun_fallGroundPitchMax
+wallRun_fallGroundPitchMin
+wallRun_fallStageTimeMs
+wallRun_fallingRollScalar
+wallRun_firingInStateDelay
+wallRun_frictionScale
+wallRun_handTraceEnable
+wallRun_initialAnimDelayMs
+wallRun_initialCameraInputDeadTimeMs
+wallRun_jumpHeight
+wallRun_jumpVelocity
+wallRun_maxHeight
+wallRun_maxTimeMs
+wallRun_minForwardMove
+wallRun_minHeightOffGround
+wallRun_minJumpHeight
+wallRun_minJumpHeightEnable
+wallRun_minMaintainSpeed
+wallRun_minTriggerSpeed
+wallRun_minVelocityAlignment
+wallRun_minZVel
+wallRun_moveMode
+wallRun_normalFacingRatio
+wallRun_obtuseSlopeTolerance
+wallRun_peakTest
+wallRun_peakTest_zm
+wallRun_pitchTimeMs
+wallRun_rollDeg
+wallRun_rollInTimeMs
+wallRun_rollOutTimeMs
+wallRun_sameSurfaceDelayPeriodMs
+wallRun_sameSurfaceWallrun
+wallRun_sightTraceDistance
+wallRun_speedScale
+wallRun_speedScaleADS
+wallRun_sweepTraceDistance
+wallRun_sweepTraceEnable
+wallRun_traceDistance
+wallRun_traceMode
+wallRun_tracePitch
+wallRun_universalRollEnable
+wallRun_viewmodelAnimEnable
+wallRun_weaponBobFrequency
+wallmount_turret_placement_trace_maxs
+wallmount_turret_placement_trace_mins
+wallrun_additiveWalkAnimScale
+wallrun_additiveWalkAnimScaleADS
+wallrun_avoidanceDot
+wallrun_enabled
+wallrun_jumpLateralLimit
+wallrun_peakTestMinVelocity
+wallrun_slopeQuotient
+war_a
+war_b
+war_c
+war_d
+war_e
+waterbrush_entity
+waypointAlphaFractionUnderMinimap
+waypointCombatAlpha
+waypointDebugDraw
+waypointDistFade
+waypointDistScaleRangeMax
+waypointDistScaleRangeMin
+waypointDistScaleSmallest
+waypointForceDrawDistance
+waypointIconHeight
+waypointIconWidth
+waypointMaxDrawDist
+waypointOffscreenCornerRadius
+waypointOffscreenDistanceThresholdAlpha
+waypointOffscreenPadBottom
+waypointOffscreenPadLeft
+waypointOffscreenPadRight
+waypointOffscreenPadTop
+waypointOffscreenPointerDistance
+waypointOffscreenPointerHeight
+waypointOffscreenPointerWidth
+waypointOffscreenRoundedCorners
+waypointOffscreenScaleLength
+waypointOffscreenScaleSmallest
+waypointPlayerOffsetCrouch
+waypointPlayerOffsetProne
+waypointPlayerOffsetRevive
+waypointPlayerOffsetStand
+waypointSplitscreenScale
+waypointTimeFade
+waypointTweakY
+waypointVerticalSeparation
+weaponCamoLodDist
+weaponClanTagLodDist
+weaponClanTagShieldLodDist
+weaponEmblemLodDist
+weaponEmblemShieldLodDist
+weapon_contract_incentive_id
+weapon_contract_max
+weapon_contract_target_value
+weaponrest_check_radius
+weaponrest_check_range
+weaponrest_debug
+weaponrest_enabled
+weaponrest_removepitch
+weaponrest_updatemsec
+webm_encAllowCamera
+weekly_contract_blackjack_contract_reward_count
+weekly_contract_cryptokey_reward_count
+welcome_shown
+wideScreen
+wiiuGame
+wiiuIkEnabled
+wind_debug_display
+wind_global_hi_altitude
+wind_global_low_altitude
+wind_global_low_strength_percent
+wind_global_vector
+wind_grass_gust_distance
+wind_grass_gust_radius
+wind_grass_gust_speed
+wind_grass_gust_strength
+wind_grass_gustinterval
+wind_grass_scale
+wind_grass_tension
+wind_leaf_scale
+winvoice_loopback
+winvoice_mic_mute
+winvoice_mic_reclevel
+winvoice_mic_scaler
+winvoice_save_voice
+winvoice_voice_level
+xPGroupMask
+xPGroups
+xanim_debug
+xanim_debugNotetracks
+xanim_monitorEnt
+xanim_monitorFilter
+xblive_clanListChanged
+xblive_clanmatch
+xblive_loggedin
+xblive_mappacks
+xblive_matchEndingSoon
+xblive_privatematch
+xblive_rankedmatch
+xblive_theater
+xblive_wagermatch
+xenonGame
+xenon_maxVoicePacketsPerSec
+xenon_maxVoicePacketsPerSecForServer
+xuid
+yawAccelerationTime
+yawDecelerationThreshold
+zero_idle_movement
+zero_stats_check
+zm_private_rankedmatch
+zm_rand_loc
+zm_rand_mode
+zm_vials_3_id
+zm_vials_6_id
+zm_vials_9_id
+zm_wasp_open_spawning
+zombie_cheat
+zombie_debug
+zombie_devgui
+zombie_kill_timer
+zombie_kills
+zombiemode_debug_zombie_count
\ No newline at end of file
diff --git a/installer/game/localappdata/T7x/data/scripts/mp/bots/_bot.gsc b/installer/game/localappdata/T7x/data/scripts/mp/bots/_bot.gsc
new file mode 100644
index 00000000..7f793a68
Binary files /dev/null and b/installer/game/localappdata/T7x/data/scripts/mp/bots/_bot.gsc differ
diff --git a/installer/game/localappdata/T7x/data/scripts/mp/bots/_bot.gsc_raw b/installer/game/localappdata/T7x/data/scripts/mp/bots/_bot.gsc_raw
new file mode 100644
index 00000000..8206b454
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/scripts/mp/bots/_bot.gsc_raw
@@ -0,0 +1,1125 @@
+#using scripts\codescripts\struct;
+
+#using scripts\shared\array_shared;
+#using scripts\shared\callbacks_shared;
+#using scripts\shared\killstreaks_shared;
+#using scripts\shared\math_shared;
+#using scripts\shared\rank_shared;
+#using scripts\shared\system_shared;
+#using scripts\shared\util_shared;
+#using scripts\shared\weapons_shared;
+
+#using scripts\shared\weapons\_weapons;
+
+#using scripts\shared\bots\_bot;
+#using scripts\shared\bots\_bot_combat;
+#using scripts\shared\bots\bot_buttons;
+#using scripts\shared\bots\bot_traversals;
+
+#using scripts\mp\bots\_bot_ball;
+#using scripts\mp\bots\_bot_clean;
+#using scripts\mp\bots\_bot_combat;
+#using scripts\mp\bots\_bot_conf;
+#using scripts\mp\bots\_bot_ctf;
+#using scripts\mp\bots\_bot_dem;
+#using scripts\mp\bots\_bot_dom;
+#using scripts\mp\bots\_bot_escort;
+#using scripts\mp\bots\_bot_hq;
+#using scripts\mp\bots\_bot_koth;
+#using scripts\mp\bots\_bot_loadout;
+#using scripts\mp\bots\_bot_sd;
+
+#using scripts\mp\killstreaks\_ai_tank;
+#using scripts\mp\killstreaks\_airsupport;
+#using scripts\mp\killstreaks\_combat_robot;
+#using scripts\mp\killstreaks\_counteruav;
+#using scripts\mp\killstreaks\_dart;
+#using scripts\mp\killstreaks\_dogs;
+#using scripts\mp\killstreaks\_drone_strike;
+#using scripts\mp\killstreaks\_emp;
+#using scripts\mp\killstreaks\_flak_drone;
+#using scripts\mp\killstreaks\_helicopter;
+#using scripts\mp\killstreaks\_helicopter_gunner;
+#using scripts\mp\killstreaks\_killstreak_bundles;
+#using scripts\mp\killstreaks\_killstreak_detect;
+#using scripts\mp\killstreaks\_killstreak_hacking;
+#using scripts\mp\killstreaks\_killstreakrules;
+#using scripts\mp\killstreaks\_killstreaks;
+#using scripts\mp\killstreaks\_microwave_turret;
+#using scripts\mp\killstreaks\_planemortar;
+#using scripts\mp\killstreaks\_qrdrone;
+#using scripts\mp\killstreaks\_raps;
+#using scripts\mp\killstreaks\_rcbomb;
+#using scripts\mp\killstreaks\_remote_weapons;
+#using scripts\mp\killstreaks\_remotemissile;
+#using scripts\mp\killstreaks\_satellite;
+#using scripts\mp\killstreaks\_sentinel;
+#using scripts\mp\killstreaks\_supplydrop;
+#using scripts\mp\killstreaks\_turret;
+#using scripts\mp\killstreaks\_uav;
+
+#using scripts\mp\teams\_teams;
+#using scripts\mp\_util;
+
+#insert scripts\shared\shared.gsh;
+#insert scripts\mp\bots\_bot.gsh;
+
+#define MAX_LOCAL_PLAYERS 10
+#define MAX_ONLINE_PLAYERS 18
+#define MAX_ONLINE_PLAYERS_PER_TEAM 6
+
+#define RESPAWN_DELAY 0.1
+#define RESPAWN_INTERVAL 0.1
+
+#namespace bot;
+
+#precache("eventstring", "mpl_killstreak_cruisemissile");
+#precache("eventstring", "mpl_killstreak_raps");
+
+REGISTER_SYSTEM("bot_mp", &__init__, undefined)
+
+function __init__()
+{
+ callback::on_start_gametype(&init);
+
+ level.getBotSettings = &get_bot_settings;
+
+ level.onBotConnect = &on_bot_connect;
+ level.onBotSpawned = &on_bot_spawned;
+ level.onBotKilled = &on_bot_killed;
+
+ level.botIdle = &bot_idle;
+
+ level.botThreatLost = &bot_combat::chase_threat;
+
+ level.botPreCombat = &bot_combat::mp_pre_combat;
+ level.botCombat = &bot_combat::combat_think;
+ level.botPostCombat = &bot_combat::mp_post_combat;
+
+ level.botIgnoreThreat = &bot_combat::bot_ignore_threat;
+
+ level.enemyEmpActive = &emp::enemyEmpActive;
+
+/*
+/#
+ level.botDevguiCmd = &bot_devgui_cmd;
+ level thread system_devgui_gadget_think();
+#/
+*/
+ setDvar("bot_enableWallrun", 1);
+}
+
+function init()
+{
+ level endon("game_ended");
+
+ level.botSoak = is_bot_soak();
+ if (!init_bot_gametype())
+ {
+ return;
+ }
+
+ wait_for_host();
+
+ level thread populate_bots();
+}
+
+// Init Utils
+//========================================
+
+function is_bot_soak()
+{
+ return getDvarInt("sv_botsoak", 0);
+}
+
+function wait_for_host()
+{
+ level endon("game_ended");
+
+ host = util::getHostPlayerForBots();
+
+ while (!isdefined(host))
+ {
+ wait(0.25);
+ host = util::getHostPlayerForBots();
+ }
+}
+
+function get_host_team()
+{
+ host = util::getHostPlayerForBots();
+
+ if (!isdefined(host) || host.team == "spectator")
+ {
+ return "allies";
+ }
+
+ return host.team;
+}
+
+function is_bot_comp_stomp()
+{
+ return false;
+}
+
+// Bot Events
+//========================================
+
+function on_bot_connect()
+{
+ self endon("disconnect");
+ level endon("game_ended");
+
+ if (IS_TRUE(level.disableClassSelection))
+ {
+ self set_rank();
+
+ // Doesn't work if we don't do it in this order
+ self bot_loadout::pick_hero_gadget();
+ self bot_loadout::pick_killstreaks();
+
+ return;
+ }
+
+ if (!IS_TRUE(self.pers["bot_loadout"]))
+ {
+ self set_rank();
+
+ // Doesn't work if we don't do it in this order
+ self bot_loadout::build_classes();
+ self bot_loadout::pick_hero_gadget();
+ self bot_loadout::pick_killstreaks();
+
+ self.pers["bot_loadout"] = true;
+ }
+
+ self bot_loadout::pick_classes();
+ self choose_class();
+}
+
+function on_bot_spawned()
+{
+ self.bot.goalTag = undefined;
+/*
+/#
+ weapon = undefined;
+
+ if (getDvarInt("scr_botsHasPlayerWeapon") != 0)
+ {
+ player = util::getHostPlayer();
+ weapon = player getCurrentWeapon();
+ }
+
+ if (getDvarString("devgui_bot_weapon", "") != "")
+ {
+ weapon = getWeapon(getDvarString("devgui_bot_weapon"));
+ }
+
+ if (isdefined(weapon) && level.weaponNone != weapon)
+ {
+ self weapons::detach_all_weapons();
+ self takeAllWeapons();
+ self giveWeapon(weapon);
+ self switchToWeapon(weapon);
+ self setSpawnWeapon(weapon);
+
+ self teams::set_player_model(self.team, weapon);
+ }
+#/
+*/
+}
+
+function on_bot_killed()
+{
+ self endon("disconnect");
+ level endon("game_ended");
+ self endon("spawned");
+ self waittill("death_delay_finished");
+
+ wait RESPAWN_DELAY;
+
+ if (self choose_class() && level.playerForceRespawn)
+ {
+ return;
+ }
+
+ self thread respawn();
+}
+
+function respawn()
+{
+ self endon("spawned");
+ self endon("disconnect");
+ level endon("game_ended");
+
+ while (1)
+ {
+ self bot::tap_use_button();
+
+ wait RESPAWN_INTERVAL;
+ }
+}
+
+function bot_idle()
+{
+ if (self do_supplydrop())
+ {
+ return;
+ }
+
+ // TODO: Look for an enemy radar blip
+ // TODO: Get points on navmesh and feed into the spawn system to see if an enemy is likely to spawn there
+ self bot::navmesh_wander();
+ self bot::sprint_to_goal();
+}
+
+// Crate maxs: 23.1482
+#define CRATE_GOAL_RADIUS 39
+#define CRATE_USE_RADIUS 62 // Wild guess on usable radius
+
+function do_supplydrop(maxRange = 1400) // A little under minimap width
+{
+ crates = getEntArray("care_package", "script_noteworthy");
+
+ maxRangeSq = maxRange * maxRange;
+
+ useRadiusSq = CRATE_USE_RADIUS * CRATE_USE_RADIUS;
+
+ closestCrate = undefined;
+ closestCrateDistSq = undefined;
+
+ foreach(crate in crates)
+ {
+ if (!crate isOnGround())
+ {
+ continue;
+ }
+
+ crateDistSq = distance2DSquared(self.origin, crate.origin);
+
+ if (crateDistSq > maxRangeSq)
+ {
+ continue;
+ }
+
+ inUse = isdefined(crate.useEnt) && IS_TRUE(crate.useEnt.inUse);
+
+ if (crateDistSq <= useRadiusSq)
+ {
+ if (inUse && !self useButtonPressed())
+ {
+ continue;
+ }
+
+ self bot::press_use_button();
+ return true;
+ }
+
+ if (!self has_minimap() && !self botSightTracePassed(crate))
+ {
+ continue;
+ }
+
+ if (!isdefined(closestCrate) || crateDistSq < closestCrateDistSq)
+ {
+ closestCrate = crate;
+ closestCrateDistSq = crateDistSq;
+ }
+ }
+
+ if (isdefined(closestCrate))
+ {
+ randomAngle = (0, randomInt(360), 0);
+ randomVec = AnglesToForward(randomAngle);
+
+ point = closestCrate.origin + randomVec * CRATE_GOAL_RADIUS;
+
+ if (self botSetGoal(point))
+ {
+ self thread watch_crate(closestCrate);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+function watch_crate(crate)
+{
+ self endon("death");
+ self endon("bot_goal_reached");
+ level endon("game_ended");
+
+ while (isdefined(crate) && !self bot_combat::has_threat())
+ {
+ wait level.botSettings.thinkInterval;
+ }
+
+ self botSetGoal(self.origin);
+}
+
+// Bot Team Population
+//========================================
+
+function populate_bots()
+{
+ level endon("game_ended");
+
+ if (level.teambased)
+ {
+ maxAllies = getDvarInt("bot_maxAllies", 0);
+ maxAxis = getDvarInt("bot_maxAxis", 0);
+
+ level thread monitor_bot_team_population(maxAllies, maxAxis);
+ }
+ else
+ {
+ maxFree = getDvarInt("bot_maxFree", 0);
+
+ level thread monitor_bot_population(maxFree);
+ }
+}
+
+function monitor_bot_team_population(maxAllies, maxAxis)
+{
+ level endon("game_ended");
+
+ if (!maxAllies && !maxAxis)
+ {
+ return;
+ }
+
+ fill_balanced_teams(maxAllies, maxAxis);
+
+ while (1)
+ {
+ wait 3;
+
+ // TODO: Get a player count that includes 'CON_CONNECTING' players
+ allies = getPlayers("allies");
+ axis = getPlayers("axis");
+
+ if (allies.size > maxAllies &&
+ remove_best_bot(allies))
+ {
+ continue;
+ }
+
+ if (axis.size > maxAxis &&
+ remove_best_bot(axis))
+ {
+ continue;
+ }
+
+ if (allies.size < maxAllies || axis.size < maxAxis)
+ {
+ add_balanced_bot(allies, maxAllies, axis, maxAxis);
+ }
+ }
+}
+
+function fill_balanced_teams(maxAllies, maxAxis)
+{
+ allies = getPlayers("allies");
+ axis = getPlayers("axis");
+
+ while ((allies.size < maxAllies || axis.size < maxAxis) &&
+ add_balanced_bot(allies, maxAllies, axis, maxAxis))
+ {
+ WAIT_SERVER_FRAME;
+
+ allies = getPlayers("allies");
+ axis = getPlayers("axis");
+ }
+}
+
+function add_balanced_bot(allies, maxAllies, axis, maxAxis)
+{
+ bot = undefined;
+
+ if (allies.size < maxAllies &&
+ (allies.size <= axis.size || axis.size >= maxAxis))
+ {
+ bot = add_bot("allies");
+ }
+ else if (axis.size < maxAxis)
+ {
+ bot = add_bot("axis");
+ }
+
+ return isdefined(bot);
+}
+
+function monitor_bot_population(maxFree)
+{
+ level endon("game_ended");
+
+ if (!maxFree)
+ {
+ return;
+ }
+
+ // Initial Fill
+ players = getPlayers();
+ while (players.size < maxFree)
+ {
+ add_bot();
+ WAIT_SERVER_FRAME;
+ players = getPlayers();
+ }
+
+ while (1)
+ {
+ wait 3;
+
+ // TODO: Get a player count that includes 'CON_CONNECTING' players
+ players = getPlayers();
+
+ if (players.size < maxFree)
+ {
+ add_bot();
+ }
+ else if (players.size > maxFree)
+ {
+ remove_best_bot(players);
+ }
+ }
+}
+
+function remove_best_bot(players)
+{
+ bots = filter_bots(players);
+
+ if (!bots.size)
+ {
+ return false;
+ }
+
+ // Prefer non-combat bots
+ bestBots = [];
+
+ foreach(bot in bots)
+ {
+ // Don't kick bots in the process of connecting
+ if (bot.sessionstate == "spectator")
+ {
+ continue;
+ }
+
+ if (bot.sessionstate == "dead" || !bot bot_combat::has_threat())
+ {
+ bestBots[bestBots.size] = bot;
+ }
+ }
+
+ if (bestBots.size)
+ {
+ remove_bot(bestBots[randomInt(bestBots.size)]);
+ }
+ else
+ {
+ remove_bot(bots[randomInt(bots.size)]);
+ }
+
+ return true;
+}
+
+// Bot Loadouts
+//========================================
+
+function choose_class()
+{
+ if (IS_TRUE(level.disableClassSelection))
+ {
+ return false;
+ }
+
+ currClass = self bot_loadout::get_current_class();
+
+ if (!isdefined(currClass) || randomInt(100) < VAL(level.botSettings.changeClassWeight, 0))
+ {
+ classIndex = randomInt(self.loadoutClasses.size);
+ className = self.loadoutClasses[classIndex].name;
+ }
+
+ if (!isdefined(className) || className == currClass)
+ {
+ return false;
+ }
+
+ self notify("menuresponse", MENU_CHANGE_CLASS, className);
+
+ return true;
+}
+
+// Killstreaks
+//========================================
+
+function use_killstreak()
+{
+ if (!level.loadoutKillstreaksEnabled ||
+ self emp::enemyEmpActive())
+ {
+ return;
+ }
+
+ weapons = self getWeaponsList();
+ inventoryWeapon = self getInventoryWeapon();
+
+ foreach(weapon in weapons)
+ {
+ killstreak = killstreaks::get_killstreak_for_weapon(weapon);
+
+ if (!isdefined(killstreak))
+ {
+ continue;
+ }
+
+ if (weapon != inventoryWeapon && !self getWeaponAmmoClip(weapon))
+ {
+ continue;
+ }
+
+ if (self killstreakrules::isKillstreakAllowed(killstreak, self.team))
+ {
+ useWeapon = weapon;
+ break;
+ }
+ }
+
+ if (!isdefined(useWeapon))
+ {
+ return;
+ }
+
+ killstreak_ref = killstreaks::get_menu_name(killstreak);
+
+ switch (killstreak_ref)
+ {
+ case "killstreak_uav":
+ case "killstreak_counteruav":
+ case "killstreak_satellite":
+ case "killstreak_helicopter_player_gunner":
+ case "killstreak_raps":
+ case "killstreak_sentinel":
+ {
+ self switchToWeapon(useWeapon);
+ break;
+ }
+ case "killstreak_ai_tank_drop":
+ {
+ self use_supply_drop(weapon);
+ break;
+ }
+ case "killstreak_remote_missile":
+ {
+ self switchToWeapon(weapon);
+ self waittill("weapon_change_complete");
+ wait 1.5;
+ self bot::press_attack_button();
+ return;
+ }
+ }
+}
+
+function get_closest_enemy(origin, on_radar)
+{
+ enemies = self get_enemies(on_radar);
+ enemies = arraysort(enemies, origin);
+
+ if (enemies.size)
+ return enemies[0];
+
+ return undefined;
+}
+
+function use_supply_drop(weapon)
+{
+ if (weapon == "inventory_supplydrop_mp" || weapon == "supplydrop_mp")
+ {
+ if (gettime() - self.spawntime > 5000)
+ return;
+ }
+
+ yaw = (0, self.angles[1], 0);
+ dir = anglestoforward(yaw);
+ dir = vectornormalize(dir);
+ drop_point = self.origin + vectorscale(dir, 384);
+ end = drop_point + vectorscale((0, 0, 1), 2048.0);
+
+ if (!sighttracepassed(drop_point, end, 0, undefined))
+ return;
+
+ if (!sighttracepassed(self.origin, end, 0, undefined))
+ return;
+
+ end = drop_point - vectorscale((0, 0, 1), 32.0);
+
+ if (bullettracepassed(drop_point, end, 0, undefined))
+ return;
+
+ self addgoal(self.origin, 24, 4, "killstreak");
+
+ if (weapon == "missile_drone_mp" || weapon == "inventory_missile_drone_mp")
+ self lookat(drop_point + vectorscale((0, 0, 1), 384.0));
+ else
+ self lookat(drop_point);
+
+ wait 0.5;
+
+ if (self getCurrentWeapon() != weapon)
+ {
+ self thread weapon_switch_failsafe();
+ self switchToWeapon(weapon);
+
+ self waittill("weapon_change_complete");
+ }
+
+ use_item(weapon);
+ self switchToWeapon(self.lastnonkillstreakweapon);
+ self clearlookat();
+ self cancelgoal("killstreak");
+}
+
+function use_item(weapon)
+{
+ self bot::press_attack_button();
+ wait 0.5;
+
+ for (i = 0; i < 10; i++)
+ {
+ if (self getCurrentWeapon() == weapon || self getCurrentWeapon() == "none")
+ self bot::press_attack_button();
+ else
+ return;
+
+ wait 0.5;
+ }
+}
+
+function killstreak_location(num, weapon)
+{
+ enemies = get_enemies();
+
+ if (!enemies.size)
+ return;
+
+ if (!self switchToWeapon(weapon))
+ return;
+
+ self waittill("weapon_change");
+
+ self util::freeze_player_controls(true);
+ wait_time = 1;
+
+ while (!isdefined(self.selectinglocation) || self.selectinglocation == 0)
+ {
+ wait 0.05;
+ wait_time -= 0.05;
+
+ if (wait_time <= 0)
+ {
+ self util::freeze_player_controls(false);
+ self switchToWeapon(self.lastnonkillstreakweapon);
+ return;
+ }
+ }
+
+ wait 2;
+
+ for (i = 0; i < num; i++)
+ {
+ enemies = get_enemies();
+
+ if (enemies.size)
+ {
+ enemy = randomInt(enemies);
+ self notify("confirm_location", enemy.origin, 0);
+ }
+
+ wait 0.25;
+ }
+
+ self util::freeze_player_controls(false);
+}
+
+function weapon_switch_failsafe()
+{
+ self endon("death");
+ self endon("disconnect");
+ self endon("weapon_change_complete");
+ wait 10;
+ self notify("weapon_change_complete");
+}
+
+function has_radar()
+{
+ if (level.teambased)
+ {
+ return (uav::HasUAV(self.team) || satellite::HasSatellite(self.team));
+ }
+
+ return (uav::HasUAV(self.entnum) || satellite::HasSatellite(self.entnum));
+}
+
+function has_minimap()
+{
+ if (self IsEmpJammed())
+ {
+ return false;
+ }
+
+ if (IS_TRUE(level.hardcoreMode))
+ {
+ return self has_radar();
+ }
+
+ return true;
+}
+
+function get_enemies(on_radar)
+{
+ if (!isdefined(on_radar))
+ {
+ on_radar = false;
+ }
+
+ enemies = self GetEnemies();
+
+/*
+/#
+ for (i = 0; i < enemies.size; i++)
+ {
+ if (isplayer(enemies[i]) && enemies[i] isInMoveMode("ufo", "noclip"))
+ {
+ arrayRemoveIndex(enemies, i);
+ i--;
+ }
+ }
+#/
+*/
+
+ if (on_radar && !self has_radar())
+ {
+ for (i = 0; i < enemies.size; i++)
+ {
+ if (!isdefined(enemies[i].lastFireTime))
+ {
+ arrayRemoveIndex(enemies, i);
+ i--;
+ }
+ else if (GetTime() - enemies[i].lastFireTime > 2000)
+ {
+ arrayRemoveIndex(enemies, i);
+ i--;
+ }
+ }
+ }
+
+ return enemies;
+}
+
+function set_rank()
+{
+ players = getPlayers();
+
+ ranks = [];
+ bot_ranks = [];
+ human_ranks = [];
+
+ for (i = 0; i < players.size; i++)
+ {
+ if (players[i] == self)
+ continue;
+
+ if (isdefined(players[i].pers["rank"]))
+ {
+ if (players[i] util::is_bot())
+ {
+ bot_ranks[bot_ranks.size] = players[i].pers["rank"];
+ }
+ else
+ {
+ human_ranks[human_ranks.size] = players[i].pers["rank"];
+ }
+ }
+ }
+
+ if (!human_ranks.size)
+ human_ranks[human_ranks.size] = 10;
+
+ human_avg = math::array_average(human_ranks);
+
+ while (bot_ranks.size + human_ranks.size < 5)
+ {
+ // add some random ranks for better random number distribution
+ r = human_avg + randomIntRange(-5, 5);
+ rank = math::clamp(r, 0, level.maxRank);
+ human_ranks[human_ranks.size] = rank;
+ }
+
+ ranks = arrayCombine(human_ranks, bot_ranks, true, false);
+
+ avg = math::array_average(ranks);
+ s = math::array_std_deviation(ranks, avg);
+
+ rank = Int(math::random_normal_distribution(avg, s, 0, level.maxRank));
+
+ while (!isdefined(self.pers["codpoints"]))
+ {
+ wait 0.1;
+ }
+
+ self.pers["rank"] = rank;
+ self.pers["rankxp"] = rank::getRankInfoMinXP(rank);
+
+ self setRank(rank);
+ self rank::syncXPStat();
+}
+
+function init_bot_gametype()
+{
+ switch (level.gameType)
+ {
+ case "ball":
+ bot_ball::init();
+ return true;
+ case "conf":
+ bot_conf::init();
+ return true;
+ case "ctf":
+ bot_ctf::init();
+ return true;
+ case "dem":
+ bot_dem::init();
+ return true;
+ case "dm":
+ return true;
+ case "dom":
+ bot_dom::init();
+ return true;
+ case "escort":
+ bot_escort::init();
+ return true;
+// case "infect":
+// return true;
+ case "gun":
+ return true;
+ case "koth":
+ bot_koth::init();
+ return true;
+ case "sd":
+ bot_sd::init();
+ return true;
+ case "clean":
+ bot_clean::init();
+ return true;
+ case "tdm":
+ return true;
+ case "sas":
+ return true;
+ case "prop":
+ return true;
+ case "sniperonly":
+ return true;
+ }
+
+ return false;
+}
+
+function get_bot_settings()
+{
+ switch (getDvarInt("bot_difficulty", 1))
+ {
+ case 0:
+ bundleName = "bot_mp_easy";
+ break;
+
+ case 1:
+ bundleName = "bot_mp_normal";
+ break;
+ case 2:
+ bundleName = "bot_mp_hard";
+ break;
+ case 3:
+ default:
+ bundleName = "bot_mp_veteran";
+ break;
+ }
+
+ return struct::get_script_bundle("botsettings", bundleName);
+}
+
+function friend_goal_in_radius(goal_name, origin, radius)
+{
+ return 0;
+}
+
+function friend_in_radius(goal_name, origin, radius)
+{
+ return false;
+}
+
+function get_friends()
+{
+ return[];
+}
+
+function bot_vehicle_weapon_ammo(weaponName)
+{
+ return false;
+}
+
+function navmesh_points_visible(origin, point)
+{
+ return false;
+}
+
+function dive_to_prone(exit_stance)
+{
+
+}
+
+/*
+/#
+
+// Devgui
+//========================================
+
+function bot_devgui_cmd(cmd)
+{
+ cmdTokens = strtok(cmd, " ");
+
+ if (cmdTokens.size == 0)
+ {
+ return false;
+ }
+
+ host = util::getHostPlayerForBots();
+ team = get_host_team();
+
+ switch (cmdTokens[0])
+ {
+ case "spawn_enemy":
+ team = util::getotherteam(team);
+ case "spawn_friendly":
+ count = 1;
+ if (cmdTokens.size > 1)
+ {
+ count = int(cmdTokens[1]);
+ }
+ for (i = 0; i < count; i++)
+ {
+ add_bot(team);
+ }
+ return true;
+ case "remove_enemy":
+ team = util::getotherteam(team);
+ case "remove_friendly":
+ remove_bots(undefined, team);
+ return true;
+ case "fixed_spawn_enemy":
+ team = util::getotherteam(team);
+ case "fixed_spawn_friendly":
+ bot = add_bot_at_eye_trace(team);
+ if (isdefined(bot))
+ {
+ bot thread fixed_spawn_override();
+ }
+ return true;
+
+ case "player_weapon":
+ players = getPlayers();
+ foreach(player in players)
+ {
+ if (!player util::is_bot())
+ {
+ continue;
+ }
+
+ weapon = host getCurrentWeapon();
+
+ player weapons::detach_all_weapons();
+ player takeAllWeapons();
+ player giveWeapon(weapon);
+ player switchToWeapon(weapon);
+ player setSpawnWeapon(weapon);
+
+ player teams::set_player_model(player.team, weapon);
+ }
+ return true;
+ }
+
+ return false;
+}
+
+function system_devgui_gadget_think()
+{
+ setDvar("devgui_bot_gadget", "");
+
+ for (;; )
+ {
+ wait(1);
+
+ gadget = getDvarString("devgui_bot_gadget");
+
+ if (gadget.size == 0)
+ {
+ bot_turn_on_gadget(getWeapon(gadget));
+ setDvar("devgui_bot_gadget", "");
+ }
+ }
+}
+
+function bot_turn_on_gadget(gadget)
+{
+ players = getPlayers();
+
+ foreach(player in players)
+ {
+ if (!player util::is_bot())
+ {
+ continue;
+ }
+
+ host = util::getHostPlayer();
+ weapon = host getCurrentWeapon();
+
+ if (!isdefined(weapon) || weapon == level.weaponNone || weapon == level.weaponNull)
+ {
+ weapon = getWeapon("smg_standard");
+ }
+
+ player weapons::detach_all_weapons();
+ player takeAllWeapons();
+ player giveWeapon(weapon);
+ player switchToWeapon(weapon);
+ player setSpawnWeapon(weapon);
+
+ player teams::set_player_model(player.team, weapon);
+
+ player giveWeapon(gadget);
+ slot = player gadgetGetSlot(gadget);
+ player gadgetPowerSet(slot, 100.0);
+ player botPressButtonForGadget(gadget);
+ }
+}
+
+function fixed_spawn_override()
+{
+ self endon("disconnect");
+
+ spawnOrigin = self.origin;
+ spawnAngles = self.angles;
+
+ while (1)
+ {
+ self waittill("spawned_player");
+
+ self setOrigin(spawnOrigin);
+ self setPlayerAngles(spawnAngles);
+ }
+}
+
+#/
+*/
diff --git a/installer/game/localappdata/T7x/data/scripts/mp/bots/_bot_loadout.gsc b/installer/game/localappdata/T7x/data/scripts/mp/bots/_bot_loadout.gsc
new file mode 100644
index 00000000..1dce3345
Binary files /dev/null and b/installer/game/localappdata/T7x/data/scripts/mp/bots/_bot_loadout.gsc differ
diff --git a/installer/game/localappdata/T7x/data/scripts/mp/bots/_bot_loadout.gsc_raw b/installer/game/localappdata/T7x/data/scripts/mp/bots/_bot_loadout.gsc_raw
new file mode 100644
index 00000000..3b48b7f1
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/scripts/mp/bots/_bot_loadout.gsc_raw
@@ -0,0 +1,854 @@
+#using scripts\shared\array_shared;
+#using scripts\shared\rank_shared;
+
+#insert scripts\shared\shared.gsh;
+#insert scripts\shared\statstable_shared.gsh;
+
+#using scripts\mp\killstreaks\_killstreaks;
+
+#using scripts\mp\bots\_bot;
+
+#define BOT_ALLOCATION_MAX 100
+#define BOT_ALLOCATION_UNLOCK_MAX 3
+#define BOT_RANK_ALL_OPTIONS_AVAILABLE 20
+#define BOT_RANK_OPTIONS_MULTIPLIER 4
+
+#namespace bot_loadout;
+
+// Item Whitelist
+//========================================
+
+function in_whitelist( itemName )
+{
+ if ( !isdefined( itemName ) )
+ return false;
+
+ switch( itemName )
+ {
+ // Secondaries
+ case "WEAPON_KNIFE_LOADOUT":
+ case "WEAPON_PISTOL_STANDARD":
+ case "WEAPON_PISTOL_BURST":
+ case "WEAPON_PISTOL_FULLAUTO":
+ case "WEAPON_LAUNCHER_STANDARD":
+ case "WEAPON_LAUNCHER_LOCKONLY":
+
+ // Primaries
+ case "WEAPON_SMG_STANDARD":
+ case "WEAPON_SMG_BURST":
+ case "WEAPON_SMG_FASTFIRE":
+ case "WEAPON_SMG_LONGRANGE":
+ case "WEAPON_SMG_VERSATILE":
+ case "WEAPON_SMG_CAPACITY":
+ case "WEAPON_AR_STANDARD":
+ case "WEAPON_AR_ACCURATE":
+ case "WEAPON_AR_CQB":
+ case "WEAPON_AR_DAMAGE":
+ case "WEAPON_AR_FASTBURST":
+ case "WEAPON_AR_LONGBURST":
+ case "WEAPON_AR_MARKSMAN":
+ case "WEAPON_LMG_CQB":
+ case "WEAPON_LMG_HEAVY":
+ case "WEAPON_LMG_LIGHT":
+ case "WEAPON_LMG_SLOWFIRE":
+ case "WEAPON_SNIPER_FASTBOLT":
+ case "WEAPON_SNIPER_FASTSEMI":
+ case "WEAPON_SNIPER_POWERBOLT":
+ case "WEAPON_SNIPER_CHARGESHOT":
+ case "WEAPON_SHOTGUN_FULLAUTO":
+ case "WEAPON_SHOTGUN_PRECISION":
+ case "WEAPON_SHOTGUN_PUMP":
+ case "WEAPON_SHOTGUN_SEMIAUTO":
+
+ // Lethals
+ case "WEAPON_FRAGGRENADE":
+ case "WEAPON_HATCHET":
+ case "WEAPON_STICKY_GRENADE":
+ case "WEAPON_SATCHEL_CHARGE":
+ case "WEAPON_BOUNCINGBETTY":
+ case "WEAPON_INCENDIARY_GRENADE":
+
+ // Tacticals
+ case "WEAPON_WILLY_PETE":
+ case "WEAPON_STUN_GRENADE":
+ case "WEAPON_EMPGRENADE":
+ case "WEAPON_FLASHBANG":
+ case "WEAPON_PROXIMITY_GRENADE":
+ case "WEAPON_PDA_HACK":
+ case "WEAPON_TROPHY_SYSTEM":
+
+ // Killstreaks
+ //case "KILLSTREAK_RCBOMB":
+ case "KILLSTREAK_RECON":
+ case "KILLSTREAK_COUNTER_UAV":
+ //case "KILLSTREAK_SUPPLY_DROP":
+ //case "KILLSTREAK_MICROWAVE_TURRET":
+ case "KILLSTREAK_REMOTE_MISSILE":
+ //case "KILLSTREAK_PLANEMORTAR":
+ //case "KILLSTREAK_AUTO_TURRET":
+ case "KILLSTREAK_AI_TANK_DROP":
+ //case "KILLSTREAK_HELICOPTER_COMLINK":
+ case "KILLSTREAK_SATELLITE":
+ //case "KILLSTREAK_EMP":
+ //case "KILLSTREAK_HELICOPTER_GUNNER":
+ case "KILLSTREAK_RAPS":
+ //case "KILLSTREAK_DRONE_STRIKE":
+ //case "KILLSTREAK_DART":
+ case "KILLSTREAK_SENTINEL":
+
+ // TU Something Weapons
+ case "WEAPON_MELEE_KNUCKLES":
+ case "WEAPON_MELEE_BUTTERFLY":
+ case "WEAPON_MELEE_WRENCH":
+
+ // TU 6 Weapons
+ case "WEAPON_PISTOL_SHOTGUN":
+ case "WEAPON_AR_GARAND":
+ case "WEAPON_SPECIAL_CROSSBOW":
+ case "WEAPON_MELEE_CROWBAR":
+ case "WEAPON_MELEE_SWORD":
+ case "WEAPON_MELEE_BOXING":
+ case "WEAPON_SMG_AK74U":
+ case "WEAPON_SMG_MP40":
+ case "WEAPON_SMG_RECHAMBER":
+ case "WEAPON_SMG_NAILGUN":
+ case "WEAPON_AR_AN94":
+ case "WEAPON_AR_FAMAS":
+ case "WEAPON_SMG_MSMC":
+ case "WEAPON_LMG_INFINITE":
+ case "WEAPON_AR_PULSE":
+ case "WEAPON_AR_M16":
+ case "WEAPON_SMG_PPSH":
+ case "WEAPON_LAUNCHER_EX41":
+ case "WEAPON_SHOTGUN_OLYMPIA":
+ case "WEAPON_SNIPER_QUICKSCOPE":
+ case "WEAPON_SNIPER_DOUBLE":
+ case "WEAPON_SMG_STEN":
+ case "WEAPON_AR_GALIL":
+ case "WEAPON_LMG_RPK":
+ case "WEAPON_AR_M14":
+ case "WEAPON_SHOTGUN_ENERGY":
+ case "WEAPON_SPECIAL_CROSSBOW_DW":
+ case "WEAPON_AR_PEACEKEEPER":
+ case "WEAPON_MELEE_CHAINSAW":
+ case "WEAPON_SPECIAL_KNIFE_BALLISTIC":
+ case "WEAPON_MELEE_CRESCENT":
+ case "WEAPON_SPECIAL_DISCGUN":
+ return true;
+ }
+
+ return false;
+}
+
+// Classes
+//========================================
+
+function build_classes()
+{
+ primaryWeapons = self get_available_items( undefined, "primary" );
+ secondaryWeapons = self get_available_items( undefined, "secondary" );
+ lethals = self get_available_items( undefined, "primarygadget" );
+ tacticals = self get_available_items( undefined, "secondarygadget" );
+ if ( IS_TRUE( level.perksEnabled ) )
+ {
+ specialties1 = self get_available_items( undefined, "specialty1" );
+ specialties2 = self get_available_items( undefined, "specialty2" );
+ specialties3 = self get_available_items( undefined, "specialty3" );
+ }
+
+ foreach( className, classValue in level.classMap )
+ {
+ if ( !isSubstr( className, "custom" ) )
+ {
+ continue;
+ }
+
+ classIndex = int( className[className.size-1] );
+
+ pickedItems = [];
+
+ pick_item( pickedItems, primaryWeapons );
+
+ if ( RandomInt( 100 ) < 95 ) // 5% chance to be a boxer for Scronce
+ {
+ pick_item( pickedItems, secondaryWeapons );
+ }
+
+ // Shuffle these selections around a bit so the classes don't all look the same when the allocation is low
+ otherItems = Array ( lethals, tacticals, specialties1, specialties2, specialties3 );
+ otherItems = array::randomize( otherItems );
+
+ for ( i = 0; i < otherItems.size; i ++ )
+ {
+ pick_item( pickedItems, otherItems[i] );
+ }
+
+ // Add items up to the max allocation
+ for ( i = 0; i < pickedItems.size && i < level.maxAllocation; i++ )
+ {
+ self BotClassAddItem( classIndex, pickedItems[i] );
+ }
+
+ // TODO: Pick primary/secondary attachments, extra perks, extra lethal, extra tactical, overkill
+/*
+ primaryWeapon = self GetLoadoutWeapon( classIndex, "primary" );
+
+ if ( primaryWeapon != level.weaponNone && primaryWeapon.supportedAttachments.size )
+ {
+ attachment = array::random( primaryWeapon.supportedAttachments );
+ self BotClassAddAttachment( classIndex, primaryWeapon, attachment, "primary" );
+ }
+
+ secondaryWeapon = self GetLoadoutWeapon( classIndex, "secondary" );
+
+ if ( secondaryWeapon != level.weaponNone && secondaryWeapon.supportedAttachments.size )
+ {
+ attachment = array::random( secondaryWeapon.supportedAttachments );
+ self BotClassAddAttachment( classIndex, secondaryWeapon, attachment, "secondary" );
+ }
+*/
+ }
+}
+
+function pick_item( &pickedItems, items )
+{
+ if ( !isdefined( items ) || items.size <= 0 )
+ {
+ return;
+ }
+
+ pickedItems[pickedItems.size] = array::random( items );
+}
+
+function pick_classes()
+{
+ self.loadoutClasses = [];
+ self.launcherClassCount = 0;
+
+ foreach( className, classValue in level.classMap )
+ {
+ if ( isSubstr( className, "custom" ) )
+ {
+ if ( level.disableCAC )
+ {
+ continue;
+ }
+
+ classIndex = int( className[className.size-1] );
+ }
+ else
+ {
+ // Things bots could use better in the default classes:
+ // C4, Trophy System, Lock on only launcher
+ classIndex = level.classToClassNum[ classValue ];
+ }
+
+ primary = self GetLoadoutWeapon( classIndex, "primary" );
+ secondary = self GetLoadoutWeapon( classIndex, "secondary" );
+
+ botClass = SpawnStruct();
+ botClass.name = className;
+ botClass.index = classIndex;
+ botClass.value = classValue;
+ botClass.primary = primary;
+ botClass.secondary = secondary;
+
+ if ( botClass.secondary.isRocketLauncher )
+ {
+ self.launcherClassCount++;
+ }
+
+ self.loadoutClasses[ self.loadoutClasses.size ] = botClass;
+ }
+}
+
+function get_current_class()
+{
+ currValue = self.pers["class"];
+ if ( !isdefined( currValue ) )
+ {
+ return undefined;
+ }
+
+ foreach( botClass in self.loadoutClasses )
+ {
+ if ( botClass.value == currValue )
+ {
+ return botClass;
+ }
+ }
+
+ return undefined;
+}
+
+// Specialists
+//========================================
+
+function pick_hero_gadget()
+{
+ if ( RandomInt( 2 ) < 1 || !self pick_hero_ability() )
+ {
+ self pick_hero_weapon();
+ }
+}
+
+function pick_hero_weapon()
+{
+ heroWeaponRef = self GetHeroWeaponName();
+
+ if ( IsItemRestricted( heroWeaponRef ) )
+ {
+ return false;
+ }
+
+ heroWeaponName = self get_item_name( heroWeaponRef );
+ self BotClassAddItem( 0, heroWeaponName );
+
+ return true;
+}
+
+function pick_hero_ability()
+{
+ heroAbilityRef = self GetHeroAbilityName();
+
+ if ( IsItemRestricted( heroAbilityRef ) )
+ {
+ return false;
+ }
+
+ heroAbilityName = self get_item_name( heroAbilityRef );
+ self BotClassAddItem( 0, heroAbilityName );
+
+ return true;
+}
+
+// Killstreaks
+//========================================
+
+function pick_killstreaks()
+{
+ killstreaks = array::randomize( self get_available_items( "killstreak" ) );
+
+ for( i = 0; i < 3 && i < killstreaks.size; i++ )
+ {
+ self BotClassAddItem( 0, killstreaks[i] );
+ }
+}
+
+
+// Get Items
+//========================================
+
+function get_available_items( filterGroup, filterSlot )
+{
+ // Get unlocked and unrestricted items
+ items = [];
+
+ for( i = 0; i < STATS_TABLE_MAX_ITEMS; i++ )
+ {
+ row = tableLookupRowNum( level.statsTableID, STATS_TABLE_COL_NUMBERING, i );
+
+ if ( row < 0 )
+ {
+ continue;
+ }
+
+ name = tableLookupColumnForRow( level.statsTableID, row, STATS_TABLE_COL_NAME );
+
+ if ( name == "" || !in_whitelist( name ) )
+ {
+ continue;
+ }
+
+ allocation = Int( tableLookupColumnForRow( level.statsTableID, row, STATS_TABLE_COL_ALLOCATION ) );
+
+ if ( allocation < 0 )
+ {
+ continue;
+ }
+
+ ref = tableLookupColumnForRow( level.statsTableId, row, STATS_TABLE_COL_REFERENCE );
+
+ if ( IsItemRestricted( ref ) )
+ {
+ continue;
+ }
+
+ number = Int( tableLookupColumnForRow( level.statsTableID, row, STATS_TABLE_COL_NUMBERING ) );
+/*
+ if ( SessionModeIsPrivate() && self IsItemLocked( number ) )
+ {
+ continue;
+ }
+*/
+ if ( isdefined( filterGroup ) )
+ {
+ group = tableLookupColumnForRow( level.statsTableID, row, STATS_TABLE_COL_GROUP );
+
+ if ( group != filterGroup )
+ {
+ continue;
+ }
+ }
+
+ if ( isdefined( filterSlot ) )
+ {
+ slot = tableLookupColumnForRow( level.statsTableID, row, STATS_TABLE_COL_SLOT );
+
+ if ( slot != filterSlot )
+ {
+ continue;
+ }
+ }
+
+ items[items.size] = name;
+ }
+
+ return items;
+}
+
+function get_item_name( itemReference )
+{
+ for( i = 0; i < STATS_TABLE_MAX_ITEMS; i++ )
+ {
+ row = tableLookupRowNum( level.statsTableID, STATS_TABLE_COL_NUMBERING, i );
+
+ if ( row < 0 )
+ {
+ continue;
+ }
+
+ reference = tableLookupColumnForRow( level.statsTableID, row, STATS_TABLE_COL_REFERENCE );
+
+ if ( reference != itemReference )
+ {
+ continue;
+ }
+
+ name = tableLookupColumnForRow( level.statsTableID, row, STATS_TABLE_COL_NAME );
+
+ return name;
+ }
+
+ return undefined;
+}
+
+// Not in use
+
+function init()
+{
+ level endon( "game_ended" );
+
+ level.bot_banned_killstreaks = Array ( "KILLSTREAK_RCBOMB",
+ "KILLSTREAK_QRDRONE",
+ /* "KILLSTREAK_REMOTE_MISSILE",*/
+ "KILLSTREAK_REMOTE_MORTAR",
+ "KILLSTREAK_HELICOPTER_GUNNER" );
+ for ( ;; )
+ {
+ level waittill( "connected", player );
+
+ if ( !player IsTestClient() )
+ {
+ continue;
+ }
+
+ player thread on_bot_connect();
+ }
+}
+
+function on_bot_connect()
+{
+ self endon( "disconnect" );
+
+ if ( isdefined( self.pers[ "bot_loadout" ] ) )
+ {
+ return;
+ }
+
+ wait( 0.10 );
+
+ if ( self GetEntityNumber() % 2 == 0 )
+ {
+ WAIT_SERVER_FRAME;
+ }
+
+ self bot::set_rank();
+
+ self BotSetRandomCharacterCustomization();
+
+
+ max_allocation = BOT_ALLOCATION_MAX;
+/*
+ if ( SessionModeIsPrivate() )
+ {
+ for ( i = 1; i <= BOT_ALLOCATION_UNLOCK_MAX; i++ )
+ {
+ if ( self IsItemLocked( rank::GetItemIndex( "feature_allocation_slot_" + i ) ) )
+ {
+ max_allocation--;
+ }
+ }
+ }
+*/
+ self construct_loadout( max_allocation );
+ self.pers[ "bot_loadout" ] = true;
+}
+
+function construct_loadout( allocation_max )
+{
+/* if ( SessionModeIsPrivate() && self IsItemLocked( rank::GetItemIndex( "feature_cac" ) ) )
+ {
+ // cac still locked
+ return;
+ }
+*/
+ pixbeginevent( "bot_construct_loadout" );
+
+ item_list = build_item_list();
+
+// item_list["primary"] = [];
+// item_list["primary"][0] = "WEAPON_RIOTSHIELD";
+
+ construct_class( 0, item_list, allocation_max );
+ construct_class( 1, item_list, allocation_max );
+ construct_class( 2, item_list, allocation_max );
+ construct_class( 3, item_list, allocation_max );
+ construct_class( 4, item_list, allocation_max );
+
+ killstreaks = item_list["killstreak1"];
+
+ if ( isdefined( item_list["killstreak2"] ) )
+ {
+ killstreaks = ArrayCombine( killstreaks, item_list["killstreak2"], true, false );
+ }
+
+ if ( isdefined( item_list["killstreak3"] ) )
+ {
+ killstreaks = ArrayCombine( killstreaks, item_list["killstreak3"], true, false );
+ }
+
+ if ( isdefined( killstreaks ) && killstreaks.size )
+ {
+ choose_weapon( 0, killstreaks );
+ choose_weapon( 0, killstreaks );
+ choose_weapon( 0, killstreaks );
+ }
+
+ self.claimed_items = undefined;
+ pixendevent();
+}
+
+function construct_class( constructclass, items, allocation_max )
+{
+ allocation = 0;
+
+ claimed_count = build_claimed_list( items );
+ self.claimed_items = [];
+
+ // primary
+ weapon = choose_weapon( constructclass, items["primary"] );
+ claimed_count["primary"]++;
+ allocation++;
+
+ // secondary
+ weapon = choose_weapon( constructclass, items["secondary"] );
+ choose_weapon_option( constructclass, "camo", 1 );
+}
+
+function make_choice( chance, claimed, max_claim )
+{
+ return ( claimed < max_claim && RandomInt( 100 ) < chance );
+}
+
+function chose_action( action1, chance1, action2, chance2, action3, chance3, action4, chance4 )
+{
+ chance1 = Int( chance1 / 10 );
+ chance2 = Int( chance2 / 10 );
+ chance3 = Int( chance3 / 10 );
+ chance4 = Int( chance4 / 10 );
+
+ actions = [];
+
+ for( i = 0; i < chance1; i++ )
+ {
+ actions[ actions.size ] = action1;
+ }
+
+ for( i = 0; i < chance2; i++ )
+ {
+ actions[ actions.size ] = action2;
+ }
+
+ for( i = 0; i < chance3; i++ )
+ {
+ actions[ actions.size ] = action3;
+ }
+
+ for( i = 0; i < chance4; i++ )
+ {
+ actions[ actions.size ] = action4;
+ }
+
+ return array::random( actions );
+}
+
+function item_is_claimed( item )
+{
+ foreach( claim in self.claimed_items )
+ {
+ if ( claim == item )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+function choose_weapon( weaponclass, items )
+{
+ if ( !isdefined( items ) || !items.size )
+ {
+ return undefined;
+ }
+
+ start = RandomInt( items.size );
+
+ for( i = 0; i < items.size; i++ )
+ {
+ weapon = items[ start ];
+
+ if ( !item_is_claimed( weapon ) )
+ {
+ break;
+ }
+
+ start = ( start + 1 ) % items.size;
+ }
+
+ self.claimed_items[ self.claimed_items.size ] = weapon;
+
+ self BotClassAddItem( weaponclass, weapon );
+ return weapon;
+}
+
+function build_weapon_options_list( optionType )
+{
+ level.botWeaponOptionsId[optionType] = [];
+ level.botWeaponOptionsProb[optionType] = [];
+
+ csv_filename = "gamedata/weapons/common/attachmentTable.csv";
+ prob = 0;
+ for ( row = 0 ; row < 255 ; row++ )
+ {
+ if ( tableLookupColumnForRow( csv_filename, row, ATTACHMENT_TABLE_COL_TYPE ) == optionType )
+ {
+ index = level.botWeaponOptionsId[optionType].size;
+ level.botWeaponOptionsId[optionType][index] = Int( tableLookupColumnForRow( csv_filename, row, ATTACHMENT_TABLE_COL_NUMBERING ) );
+ prob += Int( tableLookupColumnForRow( csv_filename, row, ATTACHMENT_TABLE_COL_BOT_PROB ) );
+ level.botWeaponOptionsProb[optionType][index] = prob;
+ }
+ }
+}
+
+function choose_weapon_option( weaponclass, optionType, primary )
+{
+ if ( !isdefined( level.botWeaponOptionsId ) )
+ {
+ level.botWeaponOptionsId = [];
+ level.botWeaponOptionsProb = [];
+
+ build_weapon_options_list( "camo" );
+ build_weapon_options_list( "reticle" );
+ }
+
+ // weapon options cannot be set in local matches
+ if ( !level.onlineGame && !level.systemLink )
+ return;
+
+ // Increase the range of the probability to reduce the chances of picking the option when the bot's level is less than BOT_RANK_ALL_OPTIONS_AVAILABLE
+ // (in system link all options are available)
+ numOptions = level.botWeaponOptionsProb[optionType].size;
+ maxProb = level.botWeaponOptionsProb[optionType][numOptions-1];
+ if ( !level.systemLink && self.pers[ "rank" ] < BOT_RANK_ALL_OPTIONS_AVAILABLE )
+ maxProb += BOT_RANK_OPTIONS_MULTIPLIER * maxProb * ( ( BOT_RANK_ALL_OPTIONS_AVAILABLE - self.pers[ "rank" ] ) / BOT_RANK_ALL_OPTIONS_AVAILABLE );
+
+ rnd = RandomInt( Int( maxProb ) );
+ for (i=0 ; i rnd )
+ {
+ self BotClassSetWeaponOption( weaponclass, primary, optionType, level.botWeaponOptionsId[optionType][i] );
+ break;
+ }
+ }
+}
+
+function choose_primary_attachments( weaponclass, weapon, allocation, allocation_max )
+{
+ attachments = weapon.supportedAttachments;
+ remaining = allocation_max - allocation;
+
+ if ( !attachments.size || !remaining )
+ {
+ return 0;
+ }
+
+ attachment_action = chose_action( "3_attachments", 25, "2_attachments", 65, "1_attachments", 10, "none", 5 );
+
+ if ( remaining >= 4 && attachment_action == "3_attachments" )
+ {
+ a1 = array::random( attachments );
+ self BotClassAddAttachment( weaponclass, weapon, a1, "primaryattachment1" );
+ count = 1;
+
+ attachments = GetWeaponAttachments( weapon, a1 );
+
+ if ( attachments.size )
+ {
+ a2 = array::random( attachments );
+ self BotClassAddAttachment( weaponclass, weapon, a2, "primaryattachment2" );
+ count++;
+
+ attachments = GetWeaponAttachments( weapon, a1, a2 );
+
+ if ( attachments.size )
+ {
+ a3 = array::random( attachments );
+ self BotClassAddItem( weaponclass, "BONUSCARD_PRIMARY_GUNFIGHTER" );
+ self BotClassAddAttachment( weaponclass, weapon, a3, "primaryattachment3" );
+ return 4;
+ }
+ }
+
+ return count;
+ }
+ else if ( remaining >= 2 && attachment_action == "2_attachments" )
+ {
+ a1 = array::random( attachments );
+ self BotClassAddAttachment( weaponclass, weapon, a1, "primaryattachment1" );
+
+ attachments = GetWeaponAttachments( weapon, a1 );
+
+ if ( attachments.size )
+ {
+ a2 = array::random( attachments );
+ self BotClassAddAttachment( weaponclass, weapon, a2, "primaryattachment2" );
+ return 2;
+ }
+
+ return 1;
+ }
+ else if ( remaining >= 1 && attachment_action == "1_attachments" )
+ {
+ a = array::random( attachments );
+ self BotClassAddAttachment( weaponclass, weapon, a, "primaryattachment1" );
+ return 1;
+ }
+
+ return 0;
+}
+
+function choose_secondary_attachments( weaponclass, weapon, allocation, allocation_max )
+{
+ attachments = weapon.supportedAttachments ;
+ remaining = allocation_max - allocation;
+
+ if ( !attachments.size || !remaining )
+ {
+ return 0;
+ }
+
+ attachment_action = chose_action( "2_attachments", 10, "1_attachments", 40, "none", 50, "none", 0 );
+
+ if ( remaining >= 3 && attachment_action == "2_attachments" )
+ {
+ a1 = array::random( attachments );
+ self BotClassAddAttachment( weaponclass, weapon, a1, "secondaryattachment1" );
+
+ attachments = GetWeaponAttachments( weapon, a1 );
+
+ if ( attachments.size )
+ {
+ a2 = array::random( attachments );
+ self BotClassAddItem( weaponclass, "BONUSCARD_SECONDARY_GUNFIGHTER" );
+ self BotClassAddAttachment( weaponclass, weapon, a2, "secondaryattachment2" );
+ return 3;
+ }
+
+ return 1;
+ }
+ else if ( remaining >= 1 && attachment_action == "1_attachments" )
+ {
+ a = array::random( attachments );
+ self BotClassAddAttachment( weaponclass, weapon, a, "secondaryattachment1" );
+ return 1;
+ }
+
+ return 0;
+}
+
+function build_item_list()
+{
+ items = [];
+
+ for( i = 0; i < STATS_TABLE_MAX_ITEMS; i++ )
+ {
+ row = tableLookupRowNum( level.statsTableID, STATS_TABLE_COL_NUMBERING, i );
+
+ if ( row > -1 )
+ {
+ slot = tableLookupColumnForRow( level.statsTableID, row, STATS_TABLE_COL_SLOT );
+
+ if ( slot == "" )
+ {
+ continue;
+ }
+
+ number = Int( tableLookupColumnForRow( level.statsTableID, row, STATS_TABLE_COL_NUMBERING ) );
+/*
+ if ( SessionModeIsPrivate() && self IsItemLocked( number ) )
+ {
+ continue;
+ }
+*/
+ allocation = Int( tableLookupColumnForRow( level.statsTableID, row, STATS_TABLE_COL_ALLOCATION ) );
+
+ if ( allocation < 0 )
+ {
+ continue;
+ }
+
+ name = tableLookupColumnForRow( level.statsTableID, row, STATS_TABLE_COL_NAME );
+/*
+ if ( item_is_banned( slot, name ) )
+ {
+ continue;
+ }
+*/
+ if ( !isdefined( items[slot] ) )
+ {
+ items[slot] = [];
+ }
+
+ items[ slot ][ items[slot].size ] = name;
+ }
+ }
+
+ return items;
+}
+
+
+function build_claimed_list( items )
+{
+ claimed = [];
+ keys = GetArrayKeys( items );
+
+ foreach( key in keys )
+ {
+ claimed[ key ] = 0;
+ }
+
+ return claimed;
+}
\ No newline at end of file
diff --git a/installer/game/localappdata/T7x/data/scripts/mp/gametypes/_globallogic_player.gsc b/installer/game/localappdata/T7x/data/scripts/mp/gametypes/_globallogic_player.gsc
new file mode 100644
index 00000000..b0673052
Binary files /dev/null and b/installer/game/localappdata/T7x/data/scripts/mp/gametypes/_globallogic_player.gsc differ
diff --git a/installer/game/localappdata/T7x/data/scripts/mp/gametypes/_globallogic_player.gsc_raw b/installer/game/localappdata/T7x/data/scripts/mp/gametypes/_globallogic_player.gsc_raw
new file mode 100644
index 00000000..6b8e3a86
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/scripts/mp/gametypes/_globallogic_player.gsc_raw
@@ -0,0 +1,4524 @@
+#using scripts\shared\abilities\_ability_player;
+#using scripts\shared\abilities\_ability_power;
+#using scripts\shared\abilities\_ability_util;
+#using scripts\shared\callbacks_shared;
+#using scripts\shared\challenges_shared;
+#using scripts\shared\clientfield_shared;
+#using scripts\shared\damagefeedback_shared;
+#using scripts\shared\demo_shared;
+#using scripts\shared\flag_shared;
+#using scripts\shared\hostmigration_shared;
+#using scripts\shared\hud_message_shared;
+#using scripts\shared\hud_util_shared;
+#using scripts\shared\killstreaks_shared;
+#using scripts\shared\math_shared;
+#using scripts\shared\medals_shared;
+#using scripts\shared\persistence_shared;
+#using scripts\shared\player_shared;
+#using scripts\shared\rank_shared;
+#using scripts\shared\scoreevents_shared;
+#using scripts\shared\tweakables_shared;
+#using scripts\shared\util_shared;
+#using scripts\shared\weapons_shared;
+#using scripts\shared\weapons\_weapon_utils;
+#using scripts\shared\weapons\_weapons;
+#using scripts\shared\ai\systems\gib;
+
+#using scripts\mp\gametypes\_battlechatter;
+#using scripts\mp\gametypes\_deathicons;
+#using scripts\mp\gametypes\_globallogic;
+#using scripts\mp\gametypes\_globallogic_audio;
+#using scripts\mp\gametypes\_globallogic_score;
+#using scripts\mp\gametypes\_globallogic_spawn;
+#using scripts\mp\gametypes\_globallogic_ui;
+#using scripts\mp\gametypes\_globallogic_utils;
+#using scripts\mp\gametypes\_globallogic_vehicle;
+#using scripts\mp\gametypes\_hostmigration;
+#using scripts\mp\gametypes\_hud_message;
+#using scripts\mp\gametypes\_killcam;
+#using scripts\mp\gametypes\_loadout;
+#using scripts\mp\gametypes\_spawning;
+#using scripts\mp\gametypes\_spawnlogic;
+#using scripts\mp\gametypes\_spectating;
+#using scripts\mp\gametypes\_weapons;
+
+#using scripts\mp\_armor;
+#using scripts\mp\_behavior_tracker;
+#using scripts\shared\_burnplayer;
+#using scripts\mp\_challenges;
+#using scripts\mp\_contracts;
+#using scripts\mp\_gamerep;
+#using scripts\mp\_laststand;
+#using scripts\mp\_teamops;
+#using scripts\mp\_util;
+#using scripts\mp\_vehicle;
+#using scripts\mp\killstreaks\_killstreaks;
+#using scripts\mp\teams\_teams;
+
+#namespace globallogic_player;
+
+function on_joined_team()
+{
+ // for cod caster update the top scorers
+ if ( !level.rankedMatch && !level.teambased )
+ {
+ level thread update_ffa_top_scorers();
+ }
+}
+
+function freezePlayerForRoundEnd()
+{
+ self util::clearLowerMessage();
+
+ self closeInGameMenu();
+
+ self util::freeze_player_controls( true );
+
+ if( !SessionModeIsZombiesGame() )
+ {
+ currentWeapon = self GetCurrentWeapon();
+ if ( killstreaks::is_killstreak_weapon( currentWeapon ) && !currentWeapon.isCarriedKillstreak )
+ self takeWeapon( currentWeapon );
+ }
+
+ //self util::_disableWeapon();
+}
+
+function ArrayToString( inputArray )
+{
+ targetString = "";
+ for (i=0; i < inputArray.size; i++)
+ {
+ targetString += inputArray[i];
+ if (i != inputArray.size-1)
+ targetString += ",";
+ }
+ return targetString;
+}
+
+
+function recordEndGameComScoreEventForPlayer( player, result )
+{
+ lpselfnum = player getEntityNumber();
+ lpXuid = player getxuid(true);
+ bbPrint( "global_leave", "name %s client %s xuid %s", player.name, lpselfnum, lpXuid );
+
+ weeklyAContractId = 0;
+ weeklyAContractTarget = 0;
+ weeklyAContractCurrent = 0;
+ weeklyAContractCompleted = 0;
+
+ weeklyBContractId = 0;
+ weeklyBContractTarget = 0;
+ weeklyBContractCurrent = 0;
+ weeklyBContractCompleted = 0;
+
+ dailyContractId = 0;
+ dailyContractTarget = 0;
+ dailyContractCurrent = 0;
+ dailyContractCompleted = 0;
+
+ specialContractId = 0;
+ specialContractTarget = 0;
+ specialContractCurent = 0;
+ specialContractCompleted = 0;
+
+ if ( player util::is_bot() )
+ {
+ currXP = 0;
+ prevXP = 0;
+ }
+ else
+ {
+ currXP = player rank::getRankXpStat();
+ prevXP = player.pers["rankxp"];
+
+ if ( globallogic_score::canUpdateWeaponContractStats( player ) )
+ {
+ specialContractId = 1; // this is a one-off contract. Use any non-zero value to indicate that it is populated.
+ specialContractTarget = GetDvarInt( "weapon_contract_target_value", 100 );
+ specialContractCurent = player GetDStat( "weaponContractData", "currentValue" );
+ if ( (isdefined(player GetDStat( "weaponContractData", "completeTimestamp" ))?player GetDStat( "weaponContractData", "completeTimestamp" ):0) != 0 )
+ {
+ specialContractCompleted = 1;
+ }
+ }
+
+ if ( player contracts::can_process_contracts() )
+ {
+ contractId = player contracts::get_contract_stat( 0, "index" );
+ if ( player contracts::is_contract_active( contractId ) )
+ {
+ weeklyAContractId = contractId;
+ weeklyAContractTarget = player.pers[ "contracts" ][ weeklyAContractId ].target_value;
+ weeklyAContractCurrent = player contracts::get_contract_stat( 0, "progress" );
+ weeklyAContractCompleted = player contracts::get_contract_stat( 0, "award_given" );
+ }
+
+ contractId = player contracts::get_contract_stat( 1, "index" );
+ if ( player contracts::is_contract_active( contractId ) )
+ {
+ weeklyBContractId = contractId;
+ weeklyBContractTarget = player.pers["contracts" ][ weeklyBContractId ].target_value;
+ weeklyBContractCurrent = player contracts::get_contract_stat( 1, "progress" );
+ weeklyBContractCompleted = player contracts::get_contract_stat( 1, "award_given" );
+ }
+
+ contractId = player contracts::get_contract_stat( 2, "index" );
+ if ( player contracts::is_contract_active( contractId ) )
+ {
+ dailyContractId = contractId;
+ dailyContractTarget = player.pers[ "contracts" ][ dailyContractId ].target_value;
+ dailyContractCurrent = player contracts::get_contract_stat( 2, "progress" );
+ dailyContractCompleted = player contracts::get_contract_stat( 2, "award_given" );
+ }
+ }
+ }
+
+ if ( !isdefined( prevXP ) )
+ {
+ // most likely the player never fully connected in the first place
+ // it is possible to specify a default value for prevXP,
+ // however, the call to RecordComScoreEvent() will SRE as most of player.pers[] is missing
+ return;
+ }
+
+ resultStr = result;
+ if ( isDefined(player.team) && result == player.team )
+ resultStr ="win";
+ else if ( result == "allies" || result == "axis" )
+ resultStr = "lose";
+
+ xpEarned = currXP - prevXP;
+
+ perkStr = ArrayToString( player GetPerks() );
+
+ primaryWeaponName = "";
+ primaryWeaponAttachStr="";
+ secondaryWeaponName = "";
+ secondaryWeaponAttachStr="";
+ grenadePrimaryName = "";
+ grenadeSecondaryName = "";
+
+
+
+ if (isdefined( player.primaryLoadoutWeapon ))
+ {
+ primaryWeaponName = player.primaryLoadoutWeapon.name;
+ primaryWeaponAttachStr = ArrayToString( GetArrayKeys(player.primaryLoadoutWeapon.attachments) );
+ }
+ if (isdefined( player.secondaryLoadoutWeapon ))
+ {
+ secondaryWeaponName = player.secondaryLoadoutWeapon.name;
+ secondaryWeaponAttachStr = ArrayToString( GetArrayKeys(player.secondaryLoadoutWeapon.attachments) );
+ }
+
+ if (isdefined( player.grenadeTypePrimary ))
+ grenadePrimaryName = player.grenadeTypePrimary.name;
+ if (isdefined( player.grenadeTypeSecondary ))
+ grenadeSecondaryName = player.grenadeTypeSecondary.name;
+
+ killStreakStr = ArrayToString( player.killstreak );
+
+ gameLength = game["timepassed"] / 1000;
+ timePlayed = player globallogic::getTotalTimePlayed( gameLength );
+
+ totalKills = 0;
+ totalHits = 0;
+ totalDeaths = 0;
+ totalWins = 0;
+ totalXP = 0;
+
+ if ( level.gametype != "fr" )
+ {
+ totalKills = player GetDStat( "playerstatslist", "kills", "statValue" );
+ totalHits = player GetDStat( "playerstatslist", "hits", "statValue" );
+ totalDeaths = player GetDStat( "playerstatslist", "deaths", "statValue" );
+ totalWins = player GetDStat( "playerstatslist", "wins", "statValue" );
+ totalXP = player GetDStat( "playerstatslist", "rankxp", "statValue" );
+ }
+
+ killCount = 0;
+ hitCount = 0;
+
+ if( level.mpCustomMatch )
+ {
+ killCount = player.kills;
+ hitCount = player.shotshit;
+ }
+ else
+ {
+ if ( isdefined( player.startKills ) )
+ killCount = totalKills - player.startKills;
+
+ if ( isdefined( player.startHits ) )
+ hitCount = totalHits - player.startHits;
+ }
+
+ bestScore = "0";
+ if ( isdefined( player.pers["lastHighestScore"] ) && player.score > player.pers["lastHighestScore"] )
+ bestScore = "1";
+
+ bestKills = "0";
+ if ( isdefined( player.pers["lastHighestKills"] ) && killCount > player.pers["lastHighestKills"] )
+ bestKills = "1";
+
+ totalMatchShots = 0;
+ if ( isdefined( player.totalMatchShots) )
+ totalMatchShots = player.totalMatchShots;
+
+ deaths = player.deaths;
+ if (deaths == 0)
+ deaths = 1;
+ kdRatio = player.kills*1000/deaths;
+ bestKDRatio = "0";
+ if ( isdefined( player.pers["lastHighestKDRatio"] ) && kdRatio > player.pers["lastHighestKDRatio"] )
+ bestKDRatio = "1";
+
+ showcaseWeapon = player GetPlayerShowcaseWeapon();
+
+ RecordComScoreEvent( "end_match",
+ "match_id", getDemoFileID(),
+ "game_variant", "mp",
+ "game_mode", level.gametype,
+ "private_match", SessionModeIsPrivate(),
+ "esports_flag", level.leagueMatch,
+ "ranked_play_flag", level.arenaMatch,
+ "league_team_id", player getLeagueTeamID(),
+ "game_map", GetDvarString( "mapname" ),
+ "player_xuid", player getxuid(true),
+ "player_ip", player getipaddress(),
+ "match_kills", killCount,
+ "match_deaths", player.deaths,
+ "match_xp", xpEarned,
+ "match_score", player.score,
+ "match_streak", player.pers["best_kill_streak"],
+ "match_captures", player.pers["captures"],
+ "match_defends", player.pers["defends"],
+ "match_headshots", player.pers["headshots"],
+ "match_longshots", player.pers["longshots"],
+ "match_objtime", player.pers["objtime"],
+ "match_plants", player.pers["plants"],
+ "match_defuses", player.pers["defuses"],
+ "match_throws", player.pers["throws"],
+ "match_carries", player.pers["carries"],
+ "match_returns", player.pers["returns"],
+ "prestige_max", player.pers["plevel"],
+ "level_max", player.pers["rank"],
+ "match_result", resultStr,
+ "match_duration", timePlayed,
+ "match_shots", totalMatchShots,
+ "match_hits", hitCount,
+ "player_gender", player GetPlayerGenderType( CurrentSessionMode() ),
+ "specialist_kills", player.heroweaponKillCount,
+ "specialist_used", player GetMpDialogName(),
+ "season_pass_owned", player HasSeasonPass(0),
+ "loadout_perks", perkStr,
+ "loadout_lethal", grenadePrimaryName,
+ "loadout_tactical", grenadeSecondaryName,
+ "loadout_scorestreaks", killStreakStr,
+ "loadout_primary_weapon", primaryWeaponName,
+ "loadout_secondary_weapon", secondaryWeaponName,
+ "dlc_owned", player GetDLCAvailable(),
+ "loadout_primary_attachments", primaryWeaponAttachStr,
+ "loadout_secondary_attachments",secondaryWeaponAttachStr,
+ "best_score", bestScore,
+ "best_kills", bestKills,
+ "best_kd", bestKDRatio,
+ "total_kills", totalKills,
+ "total_deaths", totalDeaths,
+ "total_wins", totalWins,
+ "total_xp", totalXP,
+ "daily_contract_id", dailyContractId,
+ "daily_contract_target", dailyContractTarget,
+ "daily_contract_current", dailyContractCurrent,
+ "daily_contract_completed", dailyContractCompleted,
+ "weeklyA_contract_id", weeklyAContractId,
+ "weeklyA_contract_target", weeklyAContractTarget,
+ "weeklyA_contract_current", weeklyAContractCurrent,
+ "weeklyA_contract_completed", weeklyAContractCompleted,
+ "weeklyB_contract_id", weeklyBContractId,
+ "weeklyB_contract_target", weeklyBContractTarget,
+ "weeklyB_contract_current", weeklyBContractCurrent,
+ "weeklyB_contract_completed", weeklyBContractCompleted,
+ "special_contract_id ", specialContractId,
+ "special_contract_target", specialContractTarget,
+ "special_contract_curent", specialContractCurent,
+ "special_contract_completed", specialContractCompleted,
+ "specialist_power", player.heroabilityname,
+ "specialist_head", player GetCharacterHelmetModel(),
+ "specialist_body", player GetCharacterBodyModel(),
+ "specialist_taunt", player GetPlayerSelectedTauntName( 0 ),
+ "specialist_goodgame", player GetPlayerSelectedGestureName( 0 ),
+ "specialist_threaten", player GetPlayerSelectedGestureName( 1 ),
+ "specialist_boast", player GetPlayerSelectedGestureName( 2 ),
+ "specialist_showcase", showcaseWeapon.weapon.name
+ );
+}
+
+function player_monitor_travel_dist()
+{
+ self endon ( "death" );
+ self endon ( "disconnect" );
+ waitTime = 1;
+ minimumMoveDistance = 16;
+
+ //Ignore data immediatly after spawn
+ wait 4;
+
+ prevpos = self.origin;
+ positionPTM = self.origin;
+ while( 1 )
+ {
+ wait waitTime;
+
+ if (self util::isUsingRemote())
+ {
+ self waittill ("stopped_using_remote");
+ prevpos = self.origin;
+ positionPTM = self.origin;
+ continue;
+ }
+
+ distance = distance( self.origin, prevpos );
+ self.pers["total_distance_travelled"] += distance;
+ self.pers["movement_Update_Count"]++;
+ prevpos = self.origin;
+
+ if ((self.pers["movement_Update_Count"] % 5) == 0)
+ {
+ distanceMoving = distance(self.origin, positionPTM);
+ positionPTM = self.origin;
+ if ( distanceMoving > minimumMoveDistance )
+ {
+ self.pers["num_speeds_when_moving_entries"]++;
+ self.pers["total_speeds_when_moving"] += ( distanceMoving / waitTime );
+ self.pers["time_played_moving"] += waitTime;
+ }
+ }
+
+
+ }
+}
+
+function record_special_move_data_for_life( killer )
+{
+ // safe to assume fields on self exist?
+ if( !isDefined( self.lastSwimmingStartTime) || !isDefined( self.lastWallRunStartTime) || !isDefined( self.lastSlideStartTime) || !isDefined( self.lastDoubleJumpStartTime) ||
+ !isDefined( self.timeSpentSwimmingInLife) || !isDefined( self.timeSpentWallRunningInLife) || !isDefined( self.numberOfDoubleJumpsInLife) || !isDefined( self.numberOfSlidesInLife) )
+ {
+ /#
+ println( "record_special_move_data_for_life - fields on self not defined!");
+ #/
+ return;
+ }
+
+ if( isDefined(killer) )
+ {
+ if( !isDefined( killer.lastSwimmingStartTime) || !isDefined( killer.lastWallRunStartTime) || !isDefined( killer.lastSlideStartTime) || !isDefined( killer.lastDoubleJumpStartTime) )
+ {
+ /#
+ println( "record_special_move_data_for_life - fields one killer not defined!");
+ #/
+ return;
+ }
+ matchRecordLogSpecialMoveDataForLife( self, self.lastSwimmingStartTime, self.lastWallRunStartTime, self.lastSlideStartTime, self.lastDoubleJumpStartTime,
+ self.timeSpentSwimmingInLife, self.timeSpentWallRunningInLife, self.numberOfDoubleJumpsInLife, self.numberOfSlidesInLife,
+ killer, killer.lastSwimmingStartTime, killer.lastWallRunStartTime, killer.lastSlideStartTime, killer.lastDoubleJumpStartTime );
+ }
+ else
+ {
+ matchRecordLogSpecialMoveDataForLife( self, self.lastSwimmingStartTime, self.lastWallRunStartTime, self.lastSlideStartTime, self.lastDoubleJumpStartTime,
+ self.timeSpentSwimmingInLife, self.timeSpentWallRunningInLife, self.numberOfDoubleJumpsInLife, self.numberOfSlidesInLife );
+ }
+
+}
+
+function player_monitor_wall_run()
+{
+ self endon ( "disconnect" );
+
+ // make sure no other stray threads running on this dude
+ self notify("stop_player_monitor_wall_run");
+ self endon("stop_player_monitor_wall_run");
+
+ self.lastWallRunStartTime = 0;
+ self.timeSpentWallRunningInLife = 0;
+ while ( true )
+ {
+ notification = self util::waittill_any_return( "wallrun_begin", "death", "disconnect", "stop_player_monitor_wall_run" );
+ if( notification == "death" )
+ break; // end thread
+
+ self.lastWallRunStartTime = getTime();
+
+ notification = self util::waittill_any_return( "wallrun_end", "death", "disconnect", "stop_player_monitor_wall_run" );
+
+ self.timeSpentWallRunningInLife += (getTime() - self.lastWallRunStartTime);
+
+ if( notification == "death" )
+ break; // end thread
+
+ }
+}
+
+function player_monitor_swimming()
+{
+ self endon ( "disconnect" );
+
+ // make sure no other stray threads running on this dude
+ self notify("stop_player_monitor_swimming");
+ self endon("stop_player_monitor_swimming");
+
+ self.lastSwimmingStartTime = 0;
+ self.timeSpentSwimmingInLife = 0;
+ while ( true )
+ {
+ notification = self util::waittill_any_return( "swimming_begin", "death", "disconnect", "stop_player_monitor_swimming" );
+ if( notification == "death" )
+ break; // end thread
+
+ self.lastSwimmingStartTime = getTime();
+
+ notification = self util::waittill_any_return( "swimming_end", "death", "disconnect", "stop_player_monitor_swimming" );
+
+ self.timeSpentSwimmingInLife += (getTime() - self.lastSwimmingStartTime);
+
+ if( notification == "death" )
+ break; // end thread
+
+ }
+}
+
+function player_monitor_slide()
+{
+ self endon ( "disconnect" );
+
+ // make sure no other stray threads running on this dude
+ self notify("stop_player_monitor_slide");
+ self endon("stop_player_monitor_slide");
+
+ self.lastSlideStartTime = 0;
+ self.numberOfSlidesInLife = 0;
+ while ( true )
+ {
+ notification = self util::waittill_any_return( "slide_begin", "death", "disconnect", "stop_player_monitor_slide" );
+ if( notification == "death" )
+ break; // end thread
+
+ self.lastSlideStartTime = getTime();
+ self.numberOfSlidesInLife++;
+
+ notification = self util::waittill_any_return( "slide_end", "death", "disconnect", "stop_player_monitor_slide" );
+
+ if( notification == "death" )
+ break; // end thread
+ }
+}
+
+function player_monitor_doublejump()
+{
+ self endon ( "disconnect" );
+
+ // make sure no other stray threads running on this dude
+ self notify("stop_player_monitor_doublejump");
+ self endon("stop_player_monitor_doublejump");
+
+ self.lastDoubleJumpStartTime = 0;
+ self.numberOfDoubleJumpsInLife = 0;
+ while ( true )
+ {
+ notification = self util::waittill_any_return( "doublejump_begin", "death", "disconnect", "stop_player_monitor_doublejump" );
+ if( notification == "death" )
+ break; // end thread
+
+ self.lastDoubleJumpStartTime = getTime();
+ self.numberOfDoubleJumpsInLife++;
+
+ notification = self util::waittill_any_return( "doublejump_end", "death", "disconnect", "stop_player_monitor_doublejump" );
+
+ if( notification == "death" )
+ break; // end thread
+ }
+}
+
+
+function player_monitor_inactivity()
+{
+ self endon ( "disconnect" );
+
+ self notify( "player_monitor_inactivity" );
+ self endon( "player_monitor_inactivity" );
+
+ wait 10;
+
+ while( true )
+ {
+ if ( isdefined( self ) )
+ {
+ if ( self isRemoteControlling() || self util::isUsingRemote() )
+ {
+ self ResetInactivityTimer();
+ }
+ }
+ wait 5;
+ }
+}
+
+function Callback_PlayerConnect()
+{
+ thread notifyConnecting();
+
+ self.statusicon = "hud_status_connecting";
+ self waittill( "begin" );
+
+ if( isdefined( level.reset_clientdvars ) )
+ self [[level.reset_clientdvars]]();
+
+ waittillframeend;
+ self.statusicon = "";
+
+ self.guid = self getXuid();
+
+ self.killstreak = [];
+
+ self.leaderDialogQueue = [];
+ self.killstreakDialogQueue = [];
+
+ profilelog_begintiming( 4, "ship" );
+
+ level notify( "connected", self );
+ callback::callback( #"on_player_connect" );
+
+ if ( self IsHost() )
+ self thread globallogic::listenForGameEnd();
+
+ // only print that we connected if we haven't connected in a previous round
+ if( !level.splitscreen && !isdefined( self.pers["score"] ) )
+ {
+ iPrintLn(&"MP_CONNECTED", self);
+ }
+
+ if( !isdefined( self.pers["score"] ) )
+ {
+ self thread persistence::adjust_recent_stats();
+ self persistence::set_after_action_report_stat( "valid", 0 );
+ if ( GameModeIsMode( 3 ) && !( self IsHost() ) )
+ self persistence::set_after_action_report_stat( "wagerMatchFailed", 1 );
+ else
+ self persistence::set_after_action_report_stat( "wagerMatchFailed", 0 );
+ }
+
+ // track match and hosting stats once per match
+ if( ( level.rankedMatch || level.wagerMatch || level.leagueMatch ) && !isdefined( self.pers["matchesPlayedStatsTracked"] ) )
+ {
+ gameMode = util::GetCurrentGameMode();
+ self globallogic::IncrementMatchCompletionStat( gameMode, "played", "started" );
+
+ if ( !isdefined( self.pers["matchesHostedStatsTracked"] ) && self IsLocalToHost() )
+ {
+ self globallogic::IncrementMatchCompletionStat( gameMode, "hosted", "started" );
+ self.pers["matchesHostedStatsTracked"] = true;
+ }
+
+ self.pers["matchesPlayedStatsTracked"] = true;
+ self thread persistence::upload_stats_soon();
+ }
+
+ self gamerep::gameRepPlayerConnected();
+
+ lpselfnum = self getEntityNumber();
+ lpGuid = self getXuid();
+ lpXuid = self getxuid(true);
+
+ if (self util::is_bot())
+ {
+ lpGuid = "bot0";
+ }
+
+ logPrint("J;" + lpGuid + ";" + lpselfnum + ";" + self.name + "\n");
+ bbPrint( "global_joins", "name %s client %s xuid %s", self.name, lpselfnum, lpXuid );
+
+ // needed for cross-referencing into player breadcrumb buffer
+ // will get out of sync with self.clientId with disconnects/connects
+ recordPlayerStats( self, "codeClientNum", lpselfnum);
+
+ if( !SessionModeIsZombiesGame() ) // it will be set after intro screen is faded out for zombie
+ {
+ self setClientUIVisibilityFlag( "hud_visible", 1 );
+ self setClientUIVisibilityFlag( "weapon_hud_visible", 1 );
+ }
+
+ self SetClientPlayerSprintTime( level.playerSprintTime );
+ self SetClientNumLives( level.numLives );
+
+ //makeDvarServerInfo( "cg_drawTalk", 1 );
+
+ if ( level.hardcoreMode )
+ {
+ self SetClientDrawTalk( 3 );
+ }
+
+ if( SessionModeIsZombiesGame() )
+ {
+ // initial zombies stats
+ self [[level.player_stats_init]]();
+ }
+ else
+ {
+
+ self globallogic_score::initPersStat( "score" );
+ if ( level.resetPlayerScoreEveryRound )
+ {
+ self.pers["score"] = 0;
+ }
+ self.score = self.pers["score"];
+
+ self globallogic_score::initPersStat( "pointstowin" );
+ if ( level.scoreRoundWinBased )
+ {
+ self.pers["pointstowin"] = 0;
+ }
+ self.pointstowin = self.pers["pointstowin"];
+
+ self globallogic_score::initPersStat( "momentum", false );
+ self.momentum = self globallogic_score::getPersStat( "momentum" );
+
+ self globallogic_score::initPersStat( "suicides" );
+ self.suicides = self globallogic_score::getPersStat( "suicides" );
+
+ self globallogic_score::initPersStat( "headshots" );
+ self.headshots = self globallogic_score::getPersStat( "headshots" );
+
+ self globallogic_score::initPersStat( "challenges" );
+ self.challenges = self globallogic_score::getPersStat( "challenges" );
+
+ self globallogic_score::initPersStat( "kills" );
+ self.kills = self globallogic_score::getPersStat( "kills" );
+
+ self globallogic_score::initPersStat( "deaths" );
+ self.deaths = self globallogic_score::getPersStat( "deaths" );
+
+ self globallogic_score::initPersStat( "assists" );
+ self.assists = self globallogic_score::getPersStat( "assists" );
+
+ self globallogic_score::initPersStat( "defends", false );
+ self.defends = self globallogic_score::getPersStat( "defends" );
+
+ self globallogic_score::initPersStat( "offends", false );
+ self.offends = self globallogic_score::getPersStat( "offends" );
+
+ self globallogic_score::initPersStat( "plants", false );
+ self.plants = self globallogic_score::getPersStat( "plants" );
+
+ self globallogic_score::initPersStat( "defuses", false );
+ self.defuses = self globallogic_score::getPersStat( "defuses" );
+
+ self globallogic_score::initPersStat( "returns", false );
+ self.returns = self globallogic_score::getPersStat( "returns" );
+
+ self globallogic_score::initPersStat( "captures", false );
+ self.captures = self globallogic_score::getPersStat( "captures" );
+
+ self globallogic_score::initPersStat( "objtime", false );
+ self.objtime = self globallogic_score::getPersStat( "objtime" );
+
+ self globallogic_score::initPersStat( "carries", false );
+ self.carries = self globallogic_score::getPersStat( "carries" );
+
+ self globallogic_score::initPersStat( "throws", false );
+ self.throws = self globallogic_score::getPersStat( "throws" );
+
+ self globallogic_score::initPersStat( "destructions", false );
+ self.destructions = self globallogic_score::getPersStat( "destructions" );
+
+ self globallogic_score::initPersStat( "disables", false );
+ self.disables = self globallogic_score::getPersStat( "disables" );
+
+ self globallogic_score::initPersStat( "escorts", false );
+ self.escorts = self globallogic_score::getPersStat( "escorts" );
+
+ self globallogic_score::initPersStat( "infects", false );
+ self.infects = self globallogic_score::getPersStat( "infects" );
+
+ self globallogic_score::initPersStat( "sbtimeplayed", false );
+ self.sbtimeplayed = self globallogic_score::getPersStat( "sbtimeplayed" );
+
+ self globallogic_score::initPersStat( "backstabs", false );
+ self.backstabs = self globallogic_score::getPersStat( "backstabs" );
+
+ self globallogic_score::initPersStat( "longshots", false );
+ self.longshots = self globallogic_score::getPersStat( "longshots" );
+
+ self globallogic_score::initPersStat( "survived", false );
+ self.survived = self globallogic_score::getPersStat( "survived" );
+
+ self globallogic_score::initPersStat( "stabs", false );
+ self.stabs = self globallogic_score::getPersStat( "stabs" );
+
+ self globallogic_score::initPersStat( "tomahawks", false );
+ self.tomahawks = self globallogic_score::getPersStat( "tomahawks" );
+
+ self globallogic_score::initPersStat( "humiliated", false );
+ self.humiliated = self globallogic_score::getPersStat( "humiliated" );
+
+ self globallogic_score::initPersStat( "x2score", false );
+ self.x2score = self globallogic_score::getPersStat( "x2score" );
+
+ self globallogic_score::initPersStat( "agrkills", false );
+ self.x2score = self globallogic_score::getPersStat( "agrkills" );
+
+ self globallogic_score::initPersStat( "hacks", false );
+ self.x2score = self globallogic_score::getPersStat( "hacks" );
+
+ self globallogic_score::initPersStat( "killsconfirmed", false );
+ self.killsconfirmed = self globallogic_score::getPersStat( "killsconfirmed" );
+
+ self globallogic_score::initPersStat( "killsdenied", false );
+ self.killsdenied = self globallogic_score::getPersStat( "killsdenied" );
+
+ self globallogic_score::initPersStat( "rescues", false );
+ self.rescues = self globallogic_score::getPersStat( "rescues" );
+
+ self globallogic_score::initPersStat( "shotsfired", false );
+ self.shotsfired = self globallogic_score::getPersStat( "shotsfired" );
+
+ self globallogic_score::initPersStat( "shotshit", false );
+ self.shotshit = self globallogic_score::getPersStat( "shotshit" );
+
+ self globallogic_score::initPersStat( "shotsmissed", false );
+ self.shotsmissed = self globallogic_score::getPersStat( "shotsmissed" );
+
+ self globallogic_score::initPersStat( "cleandeposits", false );
+ self.cleandeposits = self globallogic_score::getPersStat( "cleandeposits" );
+
+ self globallogic_score::initPersStat( "cleandenies", false );
+ self.cleandenies = self globallogic_score::getPersStat( "cleandenies" );
+
+ self globallogic_score::initPersStat( "victory", false );
+ self.victory = self globallogic_score::getPersStat( "victory" );
+
+ self globallogic_score::initPersStat( "sessionbans", false );
+ self.sessionbans = self globallogic_score::getPersStat( "sessionbans" );
+ self globallogic_score::initPersStat( "gametypeban", false );
+ self globallogic_score::initPersStat( "time_played_total", false );
+ self globallogic_score::initPersStat( "time_played_alive", false );
+
+ self globallogic_score::initPersStat( "teamkills", false );
+ self globallogic_score::initPersStat( "teamkills_nostats", false );
+
+ // used by match recorder for analyzing play styles
+ self globallogic_score::initPersStat( "kill_distances", false );
+ self globallogic_score::initPersStat( "num_kill_distance_entries", false );
+ self globallogic_score::initPersStat( "time_played_moving", false );
+ self globallogic_score::initPersStat( "total_speeds_when_moving", false );
+ self globallogic_score::initPersStat( "num_speeds_when_moving_entries", false );
+ self globallogic_score::initPersStat( "total_distance_travelled", false );
+ self globallogic_score::initPersStat( "movement_Update_Count", false );
+
+ self.teamKillPunish = false;
+ if ( level.minimumAllowedTeamKills >= 0 && self.pers["teamkills_nostats"] > level.minimumAllowedTeamKills )
+ self thread reduceTeamKillsOverTime();
+
+ self behaviorTracker::Initialize();
+ }
+
+ self.killedPlayersCurrent = [];
+
+ if ( !isdefined( self.pers["totalTimePlayed"] ) )
+ {
+ self setEnterTime( getTime() );
+ self.pers["totalTimePlayed"] = 0;
+ }
+
+ if ( !isdefined( self.pers["totalMatchBonus"] ) )
+ {
+ self.pers["totalMatchBonus"] = 0;
+ }
+
+ if( !isdefined( self.pers["best_kill_streak"] ) )
+ {
+ self.pers["killed_players"] = [];
+ self.pers["killed_by"] = [];
+ self.pers["nemesis_tracking"] = [];
+ self.pers["artillery_kills"] = 0;
+ self.pers["dog_kills"] = 0;
+ self.pers["nemesis_name"] = "";
+ self.pers["nemesis_rank"] = 0;
+ self.pers["nemesis_rankIcon"] = 0;
+ self.pers["nemesis_xp"] = 0;
+ self.pers["nemesis_xuid"] = "";
+ self.pers["killed_players_with_specialist"] = [];
+
+ /*self.killstreakKills["artillery"] = 0;
+ self.killstreakKills["dogs"] = 0;
+ self.killstreaksUsed["radar"] = 0;
+ self.killstreaksUsed["artillery"] = 0;
+ self.killstreaksUsed["dogs"] = 0;*/
+ self.pers["best_kill_streak"] = 0;
+ }
+
+// Adding Music tracking per player CDC
+ if( !isdefined( self.pers["music"] ) )
+ {
+ self.pers["music"] = spawnstruct();
+ self.pers["music"].spawn = false;
+ self.pers["music"].inque = false;
+ self.pers["music"].currentState = "SILENT";
+ self.pers["music"].previousState = "SILENT";
+ self.pers["music"].nextstate = "UNDERSCORE";
+ self.pers["music"].returnState = "UNDERSCORE";
+
+ }
+
+ if ( self.team != "spectator" )
+ {
+ self thread globallogic_audio::set_music_on_player( "spawnPreLoop" );
+ }
+
+ if ( !isdefined( self.pers["cur_kill_streak"] ) )
+ {
+ self.pers["cur_kill_streak"] = 0;
+ }
+
+ if ( !isdefined( self.pers["cur_total_kill_streak"] ) )
+ {
+ self.pers["cur_total_kill_streak"] = 0;
+ self setplayercurrentstreak( 0 );
+ }
+
+ if ( !isdefined( self.pers["totalKillstreakCount"] ) )
+ self.pers["totalKillstreakCount"] = 0;
+
+ //Keep track of how many killstreaks have been earned in the current streak
+ if ( !isdefined( self.pers["killstreaksEarnedThisKillstreak"] ) )
+ self.pers["killstreaksEarnedThisKillstreak"] = 0;
+
+ if ( isdefined( level.usingScoreStreaks ) && level.usingScoreStreaks && !isdefined( self.pers["killstreak_quantity"] ) )
+ self.pers["killstreak_quantity"] = [];
+
+ if ( isdefined( level.usingScoreStreaks ) && level.usingScoreStreaks && !isdefined( self.pers["held_killstreak_ammo_count"] ) )
+ self.pers["held_killstreak_ammo_count"] = [];
+
+ if ( IsDefined( level.usingScoreStreaks ) && level.usingScoreStreaks && !IsDefined( self.pers["held_killstreak_clip_count"] ) )
+ self.pers["held_killstreak_clip_count"] = [];
+
+ if( !isDefined( self.pers["changed_class"] ) )
+ self.pers["changed_class"] = false;
+
+ if( !isDefined( self.pers["lastroundscore"] ) )
+ self.pers["lastroundscore"] = 0;
+
+ self.lastKillTime = 0;
+
+ self.cur_death_streak = 0;
+ self disabledeathstreak();
+ self.death_streak = 0;
+ self.kill_streak = 0;
+ self.gametype_kill_streak = 0;
+ self.spawnQueueIndex = -1;
+ self.deathTime = 0;
+
+ self.aliveTimes = [];
+ for( index = 0; index < level.aliveTimeMaxCount; index++ )
+ {
+ self.aliveTimes[index] = 0;
+ }
+
+ self.aliveTimeCurrentIndex = 0;
+
+ if ( level.onlineGame && !( isdefined( level.freerun ) && level.freerun ) )
+ {
+ self.death_streak = self getDStat( "HighestStats", "death_streak" );
+ self.kill_streak = self getDStat( "HighestStats", "kill_streak" );
+ self.gametype_kill_streak = self persistence::stat_get_with_gametype( "kill_streak" );
+ }
+
+ self.lastGrenadeSuicideTime = -1;
+
+ self.teamkillsThisRound = 0;
+
+ if ( !isdefined( level.livesDoNotReset ) || !level.livesDoNotReset || !isdefined( self.pers["lives"] ) )
+ {
+ self.pers["lives"] = level.numLives;
+ }
+
+ // multi round FFA games in custom game mode should maintain team in-between rounds
+ if ( !level.teamBased )
+ {
+ self.pers["team"] = undefined;
+ }
+
+ self.hasSpawned = false;
+ self.waitingToSpawn = false;
+ self.wantSafeSpawn = false;
+ self.deathCount = 0;
+
+ self.wasAliveAtMatchStart = false;
+
+ level.players[level.players.size] = self;
+
+ if( level.splitscreen )
+ SetDvar( "splitscreen_playerNum", level.players.size );
+ // removed underscore for debug CDC
+ // When joining a game in progress, if the game is at the post game state (scoreboard) the connecting player should spawn into intermission
+ if ( game["state"] == "postgame" )
+ {
+ self.pers["needteam"] = 1;
+ self.pers["team"] = "spectator";
+ self.team = self.sessionteam;
+
+ self setClientUIVisibilityFlag( "hud_visible", 0 );
+
+ self [[level.spawnIntermission]]();
+ self closeInGameMenu();
+ profilelog_endtiming( 4, "gs=" + game["state"] + " zom=" + SessionModeIsZombiesGame() );
+ return;
+ }
+
+ // don't count losses for CTF and S&D and War at each round.
+ if ( ( level.rankedMatch || level.wagerMatch || level.leagueMatch ) && !isdefined( self.pers["lossAlreadyReported"] ) )
+ {
+ if ( level.leagueMatch )
+ {
+ self recordLeaguePreLoser();
+ }
+
+ globallogic_score::updateLossStats( self );
+
+ self.pers["lossAlreadyReported"] = true;
+ }
+ if ((level.rankedMatch || level.leagueMatch) && !isDefined( self.pers["lateJoin"] ) )
+ {
+ if (game["state"] == "playing" && !level.inPrematchPeriod )
+ {
+ self.pers["lateJoin"] = true;
+ }
+ else
+ {
+ self.pers["lateJoin"] = false;
+ }
+ }
+
+ // don't redo winstreak save to pers array for each round of round based games.
+ if ( !isdefined( self.pers["winstreakAlreadyCleared"] ) )
+ {
+ self globallogic_score::backupAndClearWinStreaks();
+ self.pers["winstreakAlreadyCleared"] = true;
+ }
+
+ if( self istestclient() )
+ {
+ self.pers[ "isBot" ] = true;
+ recordPlayerStats( self, "isBot", true);
+ }
+
+ if ( level.rankedMatch || level.leagueMatch )
+ {
+ self persistence::set_after_action_report_stat( "demoFileID", "0" );
+ }
+
+ level endon( "game_ended" );
+
+ if ( isdefined( level.hostMigrationTimer ) )
+ self thread hostmigration::hostMigrationTimerThink();
+
+ if ( isdefined( self.pers["team"] ) )
+ self.team = self.pers["team"];
+
+ if ( isdefined( self.pers["class"] ) )
+ self.curClass = self.pers["class"];
+
+ if ( !isdefined( self.pers["team"] ) || isdefined( self.pers["needteam"] ) )
+ {
+ // Don't set .sessionteam until we've gotten the assigned team from code,
+ // because it overrides the assigned team.
+ self.pers["needteam"] = undefined;
+ self.pers["team"] = "spectator";
+ self.team = "spectator";
+ self.sessionstate = "dead";
+
+ self globallogic_ui::updateObjectiveText();
+
+ [[level.spawnSpectator]]();
+
+ [[level.autoassign]]( false );
+ if ( level.rankedMatch || level.leagueMatch )
+ {
+ self thread globallogic_spawn::kickIfDontSpawn();
+ }
+
+ if ( self.pers["team"] == "spectator" )
+ {
+ self.sessionteam = "spectator";
+ self thread spectate_player_watcher();
+ }
+
+ if ( level.teamBased )
+ {
+ // set team and spectate permissions so the map shows waypoint info on connect
+ self.sessionteam = self.pers["team"];
+ if ( !isAlive( self ) )
+ self.statusicon = "hud_status_dead";
+ self thread spectating::set_permissions();
+ }
+ }
+ else if ( self.pers["team"] == "spectator" )
+ {
+ self SetClientScriptMainMenu( game[ "menu_start_menu" ] );
+ [[level.spawnSpectator]]();
+ self.sessionteam = "spectator";
+ self.sessionstate = "spectator";
+ self thread spectate_player_watcher();
+ }
+ else
+ {
+ self.sessionteam = self.pers["team"];
+ self.sessionstate = "dead";
+
+ self globallogic_ui::updateObjectiveText();
+
+ [[level.spawnSpectator]]();
+
+ if ( globallogic_utils::isValidClass( self.pers["class"] ) || util::IsPropHuntGametype() )
+ {
+ if ( !globallogic_utils::isValidClass( self.pers["class"] ) )
+ {
+ self.pers["class"] = level.defaultClass;
+ self.curClass = level.defaultClass;
+ self SetClientScriptMainMenu( game[ "menu_start_menu" ] );
+ }
+ self thread [[level.spawnClient]]();
+ }
+ else
+ {
+ self globallogic_ui::showMainMenuForTeam();
+ }
+
+ self thread spectating::set_permissions();
+ }
+
+ if ( self.sessionteam != "spectator" )
+ {
+ self thread spawning::onSpawnPlayer(true);
+ }
+
+ if ( level.forceRadar == 1 ) // radar always sweeping
+ {
+ self.pers["hasRadar"] = true;
+ self.hasSpyplane = true;
+
+ if ( level.teambased )
+ {
+ level.activeUAVs[self.team]++;
+ }
+ else
+ {
+ level.activeUAVs[self getEntityNumber()]++;
+ }
+
+ level.activePlayerUAVs[self getEntityNumber()]++;
+ }
+
+ if ( level.forceRadar == 2 ) // radar constant
+ {
+ self setClientUIVisibilityFlag( "g_compassShowEnemies", level.forceRadar );
+ }
+ else
+ {
+ self SetClientUIVisibilityFlag( "g_compassShowEnemies", 0 );
+ }
+
+ profilelog_endtiming( 4, "gs=" + game["state"] + " zom=" + SessionModeIsZombiesGame() );
+
+ if ( isdefined( self.pers["isBot"] ) )
+ return;
+
+ self record_global_mp_stats_for_player_at_match_start();
+
+ //T7 - moved from load_shared to make sure this doesn't get set on CP until level.players is ready
+ num_con = getnumconnectedplayers();
+ num_exp = getnumexpectedplayers();
+ /#println( "all_players_connected(): getnumconnectedplayers=", num_con, "getnumexpectedplayers=", num_exp );#/
+
+ if(num_con == num_exp && (num_exp != 0))
+ {
+ level flag::set( "all_players_connected" );
+ // CODER_MOD: GMJ (08/28/08): Setting dvar for use by code
+ SetDvar( "all_players_are_connected", "1" );
+ }
+
+ globallogic_score::updateWeaponContractStart( self );
+}
+
+function record_global_mp_stats_for_player_at_match_start()
+{
+ // not sure if we even want/need this test
+ // if ( level.onlinegame && !SessionModeIsPrivate() ) ?
+ // if ( level.rankedMatch ) ?
+ //
+ // just copy from mp_stats, and it will do what it's supposed to
+ // (i.e. return something or 0)
+
+ if( isdefined( level.disableStatTracking ) && level.disableStatTracking == true )
+ {
+ return;
+ }
+
+ startKills = self GetDStat( "playerstatslist", "kills", "statValue" );
+ startDeaths = self GetDStat( "playerstatslist", "deaths", "statValue" );
+ startWins = self GetDStat( "playerstatslist", "wins", "statValue" );
+ startLosses = self GetDStat( "playerstatslist", "losses", "statValue" );
+ startHits = self GetDStat( "playerstatslist", "hits", "statValue" );
+ startMisses = self GetDStat( "playerstatslist", "misses", "statValue" );
+ startTimePlayedTotal = self GetDStat( "playerstatslist", "time_played_total", "statValue" );
+ startScore = self GetDStat( "playerstatslist", "score", "statValue" );
+ startPrestige = self GetDStat( "playerstatslist", "plevel", "statValue" );
+ startUnlockPoints = self GetDStat( "unlocks", 0);
+
+ ties = self GetDStat( "playerstatslist", "ties", "statValue" );
+ startGamesPlayed = startWins + startLosses + ties;
+
+ self.startKills = startKills;
+ self.startHits = startHits;
+ self.totalMatchShots = 0;
+
+ // note: xp_start - already exists - written in code - reads RANKXP
+
+ recordPlayerStats( self, "startKills", startKills );
+ recordPlayerStats( self, "startDeaths", startDeaths );
+ recordPlayerStats( self, "startWins", startWins );
+ recordPlayerStats( self, "startLosses", startLosses );
+ recordPlayerStats( self, "startHits", startHits );
+ recordPlayerStats( self, "startMisses", startMisses );
+ recordPlayerStats( self, "startTimePlayedTotal", startTimePlayedTotal );
+ recordPlayerStats( self, "startScore", startScore );
+ recordPlayerStats( self, "startPrestige", startPrestige );
+ recordPlayerStats( self, "startUnlockPoints", startUnlockPoints );
+ recordPlayerStats( self, "startGamesPlayed", startGamesPlayed );
+
+ // temp commenting out; the getdstat calls here fail
+ lootXPBeforeMatch = self GetDStat( "AfterActionReportStats", "lootXPBeforeMatch" );
+ cryptoKeysBeforeMatch = self GetDStat( "AfterActionReportStats", "cryptoKeysBeforeMatch" );
+ recordPlayerStats( self, "lootXPBeforeMatch", lootXPBeforeMatch );
+ recordPlayerStats( self, "cryptoKeysBeforeMatch", cryptoKeysBeforeMatch );
+
+}
+
+function record_global_mp_stats_for_player_at_match_end()
+{
+ if( isdefined( level.disableStatTracking ) && level.disableStatTracking == true )
+ {
+ return;
+ }
+
+ endKills = self GetDStat( "playerstatslist", "kills", "statValue" );
+ endDeaths = self GetDStat( "playerstatslist", "deaths", "statValue" );
+ endWins = self GetDStat( "playerstatslist", "wins", "statValue" );
+ endLosses = self GetDStat( "playerstatslist", "losses", "statValue" );
+ endHits = self GetDStat( "playerstatslist", "hits", "statValue" );
+ endMisses = self GetDStat( "playerstatslist", "misses", "statValue" );
+ endTimePlayedTotal = self GetDStat( "playerstatslist", "time_played_total", "statValue" );
+ endScore = self GetDStat( "playerstatslist", "score", "statValue" );
+ endPrestige = self GetDStat( "playerstatslist", "plevel", "statValue" );
+ endUnlockPoints = self GetDStat( "unlocks", 0);
+
+ ties = self GetDStat( "playerstatslist", "ties", "statValue" );
+ endGamesPlayed = endWins + endLosses + ties;
+
+ // note: xp_end - already exists - written in code - reads RANKXP
+
+ recordPlayerStats( self, "endKills", endKills );
+ recordPlayerStats( self, "endDeaths", endDeaths );
+ recordPlayerStats( self, "endWins", endWins );
+ recordPlayerStats( self, "endLosses", endLosses );
+ recordPlayerStats( self, "endHits", endHits );
+ recordPlayerStats( self, "endMisses", endMisses );
+ recordPlayerStats( self, "endTimePlayedTotal", endTimePlayedTotal );
+ recordPlayerStats( self, "endScore", endScore );
+ recordPlayerStats( self, "endPrestige", endPrestige );
+ recordPlayerStats( self, "endUnlockPoints", endUnlockPoints );
+ recordPlayerStats( self, "endGamesPlayed", endGamesPlayed );
+
+}
+
+function record_misc_player_stats()
+{
+ if( isdefined( level.disableStatTracking ) && level.disableStatTracking == true )
+ {
+ return;
+ }
+
+ // common either for match end or on disconnect
+ recordPlayerStats( self, "UTCEndTimeSeconds", getUTC() );
+ if( isdefined( self.weaponPickupsCount ) )
+ {
+ recordPlayerStats( self, "weaponPickupsCount", self.weaponPickupsCount );
+ }
+ if( isdefined( self.killcamsSkipped) )
+ {
+ recordPlayerStats( self, "totalKillcamsSkipped", self.killcamsSkipped );
+ }
+ if( isdefined( self.matchBonus) )
+ {
+ recordPlayerStats( self, "matchXp", self.matchBonus );
+ }
+ if( isdefined( self.killsdenied ) )
+ {
+ recordPlayerStats( self, "killsDenied", self.killsdenied );
+ }
+ if( isdefined( self.killsconfirmed ) )
+ {
+ recordPlayerStats( self, "killsConfirmed", self.killsconfirmed );
+ }
+ if( self IsSplitscreen() )
+ {
+ recordPlayerStats( self, "isSplitscreen", true );
+ }
+ if( self.objtime )
+ {
+ recordPlayerStats( self, "objectiveTime", self.objtime );
+ }
+ if( self.escorts )
+ {
+ recordPlayerStats( self, "escortTime", self.escorts );
+ }
+}
+
+function spectate_player_watcher()
+{
+ self endon( "disconnect" );
+
+ // Setup the perks hud elem for the spectator if its not yet initalized
+ // We have to do it here, since the perk hudelem is generally initalized only on spawn, and the spectator will not able able to
+ // look at the perk loadout of some player.
+ if ( !level.splitscreen && !level.hardcoreMode && GetDvarint( "scr_showperksonspawn" ) == 1 && game["state"] != "postgame" && !isdefined( self.perkHudelem ) )
+ {
+ if ( level.perksEnabled == 1 )
+ {
+ self hud::showPerks( );
+ }
+ }
+
+ self.watchingActiveClient = true;
+ self.waitingForPlayersText = undefined;
+
+ while ( 1 )
+ {
+ if ( self.pers["team"] != "spectator" || level.gameEnded )
+ {
+ self hud_message::clearShoutcasterWaitingMessage();
+ if ( !( isdefined( level.inPrematchPeriod ) && level.inPrematchPeriod ) )
+ {
+ self FreezeControls( false );
+ }
+ self.watchingActiveClient = false;
+ break;
+ }
+ else
+ {
+ count = 0;
+ for ( i = 0; i < level.players.size; i++ )
+ {
+ if ( level.players[i].team != "spectator" )
+ {
+ count++;
+ break;
+ }
+ }
+
+ if ( count > 0 )
+ {
+ if ( !self.watchingActiveClient )
+ {
+ self hud_message::clearShoutcasterWaitingMessage();
+ self FreezeControls( false );
+
+ // Make sure that the player spawned notify happens when we start watching a player.
+ self LUINotifyEvent( &"player_spawned", 0 );
+ }
+
+ self.watchingActiveClient = true;
+ }
+ else
+ {
+ if ( self.watchingActiveClient )
+ {
+ [[level.onSpawnSpectator]]();
+ self FreezeControls( true );
+ self hud_message::setShoutcasterWaitingMessage();
+ }
+
+ self.watchingActiveClient = false;
+ }
+
+ wait( 0.5 );
+ }
+ }
+}
+
+function Callback_PlayerMigrated()
+{
+/# println( "Player " + self.name + " finished migrating at time " + gettime() ); #/
+
+ if ( isdefined( self.connected ) && self.connected )
+ {
+ self globallogic_ui::updateObjectiveText();
+// self globallogic_ui::updateObjectiveText();
+// self updateMainMenu();
+
+// if ( level.teambased )
+// self updateScores();
+ }
+
+ level.hostMigrationReturnedPlayerCount++;
+ if ( level.hostMigrationReturnedPlayerCount >= level.players.size * 2 / 3 )
+ {
+ /# println( "2/3 of players have finished migrating" ); #/
+ level notify( "hostmigration_enoughplayers" );
+ }
+}
+
+function Callback_PlayerDisconnect()
+{
+ profilelog_begintiming( 5, "ship" );
+
+ if ( game["state"] != "postgame" && !level.gameEnded )
+ {
+ gameLength = game["timepassed"];
+ self globallogic::bbPlayerMatchEnd( gameLength, "MP_PLAYER_DISCONNECT", 0 );
+
+ if( util::isRoundBased() )
+ {
+ recordPlayerStats( self, "playerQuitRoundNumber", game["roundsplayed"] + 1 );
+ }
+
+ if( level.teambased )
+ {
+ ourTeam = self.team; // only expecting: "allies" or "axis"
+ if( ourTeam == "allies" || ourTeam == "axis" )
+ {
+ theirTeam = "";
+ if( ourTeam == "allies" )
+ {
+ theirTeam = "axis";
+ }
+ else if( ourTeam == "axis" )
+ {
+ theirTeam = "allies";
+ }
+ recordPlayerStats( self, "playerQuitTeamScore", getTeamScore( ourTeam ) );
+ recordPlayerStats( self, "playerQuitOpposingTeamScore", getTeamScore( theirTeam ) );
+ }
+ }
+
+ recordEndGameComScoreEventForPlayer( self, "disconnect" );
+
+ }
+
+ self behaviorTracker::Finalize();
+
+ ArrayRemoveValue( level.players, self );
+
+ if ( level.splitscreen )
+ {
+ players = level.players;
+
+ if ( players.size <= 1 )
+ level thread globallogic::forceEnd();
+
+ // passing number of players to menus in splitscreen to display leave or end game option
+ SetDvar( "splitscreen_playerNum", players.size );
+ }
+
+ if ( isdefined( self.score ) && isdefined( self.pers["team"] ) )
+ {
+ /#print( "team: score " + self.pers["team"] + ":" + self.score );#/
+ level.dropTeam += 1;
+ }
+
+ [[level.onPlayerDisconnect]]();
+
+ lpselfnum = self getEntityNumber();
+ lpGuid = self getXuid();
+
+ if (self util::is_bot())
+ {
+ lpGuid = "bot0";
+ }
+
+ logPrint("Q;" + lpGuid + ";" + lpselfnum + ";" + self.name + "\n");
+
+ self record_global_mp_stats_for_player_at_match_end();
+ self record_special_move_data_for_life( undefined );
+
+ self record_misc_player_stats();
+
+ self gamerep::gameRepPlayerDisconnected();
+
+ for ( entry = 0; entry < level.players.size; entry++ )
+ {
+ if ( level.players[entry] == self )
+ {
+ while ( entry < level.players.size-1 )
+ {
+ level.players[entry] = level.players[entry+1];
+ entry++;
+ }
+ level.players[entry] = undefined;
+ break;
+ }
+ }
+ for ( entry = 0; entry < level.players.size; entry++ )
+ {
+ if ( isdefined( level.players[entry].pers["killed_players"][self.name] ) )
+ level.players[entry].pers["killed_players"][self.name] = undefined;
+
+ if ( isdefined( level.players[entry].pers["killed_players_with_specialist"][self.name] ) )
+ level.players[entry].pers["killed_players_with_specialist"][self.name] = undefined;
+
+ if ( isdefined( level.players[entry].killedPlayersCurrent[self.name] ) )
+ level.players[entry].killedPlayersCurrent[self.name] = undefined;
+
+ if ( isdefined( level.players[entry].pers["killed_by"][self.name] ) )
+ level.players[entry].pers["killed_by"][self.name] = undefined;
+
+ if ( isdefined( level.players[entry].pers["nemesis_tracking"][self.name] ) )
+ level.players[entry].pers["nemesis_tracking"][self.name] = undefined;
+
+ // player that disconnected was our nemesis
+ if ( level.players[entry].pers["nemesis_name"] == self.name )
+ {
+ level.players[entry] chooseNextBestNemesis();
+ }
+ }
+
+ if ( level.gameEnded )
+ self globallogic::removeDisconnectedPlayerFromPlacement();
+
+ level thread globallogic::updateTeamStatus();
+ level thread globallogic::updateAllAliveTimes();
+
+ profilelog_endtiming( 5, "gs=" + game["state"] + " zom=" + SessionModeIsZombiesGame() );
+}
+
+function Callback_PlayerMelee( eAttacker, iDamage, weapon, vOrigin, vDir, boneIndex, shieldHit, fromBehind )
+{
+ hit = true;
+
+ if ( level.teamBased && self.team == eAttacker.team )
+ {
+ if ( level.friendlyfire == 0 ) // no one takes damage
+ {
+ hit = false;
+ }
+ }
+
+ self finishMeleeHit( eAttacker, weapon, vOrigin, vDir, boneIndex, shieldHit, hit, fromBehind );
+}
+
+function chooseNextBestNemesis()
+{
+ nemesisArray = self.pers["nemesis_tracking"];
+ nemesisArrayKeys = getArrayKeys( nemesisArray );
+ nemesisAmount = 0;
+ nemesisName = "";
+
+ if ( nemesisArrayKeys.size > 0 )
+ {
+ for ( i = 0; i < nemesisArrayKeys.size; i++ )
+ {
+ nemesisArrayKey = nemesisArrayKeys[i];
+ if ( nemesisArray[nemesisArrayKey] > nemesisAmount )
+ {
+ nemesisName = nemesisArrayKey;
+ nemesisAmount = nemesisArray[nemesisArrayKey];
+ }
+
+ }
+ }
+
+ self.pers["nemesis_name"] = nemesisName;
+
+ if ( nemesisName != "" )
+ {
+ playerIndex = 0;
+ for( ; playerIndex < level.players.size; playerIndex++ )
+ {
+ if ( level.players[playerIndex].name == nemesisName )
+ {
+ nemesisPlayer = level.players[playerIndex];
+ self.pers["nemesis_rank"] = nemesisPlayer.pers["rank"];
+ self.pers["nemesis_rankIcon"] = nemesisPlayer.pers["rankxp"];
+ self.pers["nemesis_xp"] = nemesisPlayer.pers["prestige"];
+ self.pers["nemesis_xuid"] = nemesisPlayer GetXUID();
+ break;
+ }
+ }
+ }
+ else
+ {
+ self.pers["nemesis_xuid"] = "";
+ }
+}
+
+function custom_gamemodes_modified_damage( victim, eAttacker, iDamage, sMeansOfDeath, weapon, eInflictor, sHitLoc )
+{
+ // regular public matches should early out
+ if ( level.onlinegame && !SessionModeIsPrivate() )
+ {
+ return iDamage;
+ }
+
+ if( isdefined( eAttacker) && isdefined( eAttacker.damageModifier ) )
+ {
+ iDamage *= eAttacker.damageModifier;
+ }
+ if ( ( sMeansOfDeath == "MOD_PISTOL_BULLET" ) || ( sMeansOfDeath == "MOD_RIFLE_BULLET" ) )
+ {
+ iDamage = int( iDamage * level.bulletDamageScalar );
+ }
+
+ return iDamage;
+}
+
+function figure_out_attacker( eAttacker )
+{
+ if ( isdefined(eAttacker) )
+ {
+ if( isai(eAttacker) && isdefined( eAttacker.script_owner ) )
+ {
+ team = self.team;
+
+ if ( eAttacker.script_owner.team != team )
+ eAttacker = eAttacker.script_owner;
+ }
+
+ if( eAttacker.classname == "script_vehicle" && isdefined( eAttacker.owner ) )
+ eAttacker = eAttacker.owner;
+ else if( eAttacker.classname == "auto_turret" && isdefined( eAttacker.owner ) )
+ eAttacker = eAttacker.owner;
+ else if( eAttacker.classname == "actor_spawner_bo3_robot_grunt_assault_mp" && isdefined( eAttacker.owner ) )
+ eAttacker = eAttacker.owner;
+ }
+
+ return eAttacker;
+}
+
+function player_damage_figure_out_weapon( weapon, eInflictor )
+{
+ // explosive barrel/car detection
+ if ( weapon == level.weaponNone && isdefined( eInflictor ) )
+ {
+ if ( isdefined( eInflictor.targetname ) && eInflictor.targetname == "explodable_barrel" )
+ {
+ weapon = GetWeapon( "explodable_barrel" );
+ }
+ else if ( isdefined( eInflictor.destructible_type ) && isSubStr( eInflictor.destructible_type, "vehicle_" ) )
+ {
+ weapon = GetWeapon( "destructible_car" );
+ }
+ else if( isdefined( eInflictor.scriptvehicletype ) )
+ {
+ veh_weapon = GetWeapon( eInflictor.scriptvehicletype );
+ if( isdefined( veh_weapon ) )
+ {
+ weapon = veh_weapon;
+ }
+ }
+ }
+
+ if ( isdefined( eInflictor ) && isdefined( eInflictor.script_noteworthy ) )
+ {
+ if ( IsDefined( level.overrideWeaponFunc ) )
+ {
+ weapon = [[level.overrideWeaponFunc]]( weapon, eInflictor.script_noteworthy );
+ }
+ }
+
+ return weapon;
+}
+
+function figure_out_friendly_fire( victim )
+{
+ if ( level.hardcoreMode && level.friendlyfire > 0 && isdefined( victim ) && victim.is_capturing_own_supply_drop === true )
+ {
+ return 2; // FF 2 = reflect; design wants reflect friendly fire whenever a player is capturing their own supply drop
+ }
+
+ if ( killstreaks::is_ricochet_protected( victim ) )
+ {
+ return 2;
+ }
+
+ // note, keep, non-gametype specific friendly fire logic above this line
+
+ if ( isdefined( level.figure_out_gametype_friendly_fire ) )
+ {
+ return [[ level.figure_out_gametype_friendly_fire ]]( victim );
+ }
+
+ return level.friendlyfire;
+}
+
+function isPlayerImmuneToKillstreak( eAttacker, weapon )
+{
+ if ( level.hardcoreMode )
+ return false;
+
+ if ( !isdefined( eAttacker ) )
+ return false;
+
+ if ( self != eAttacker )
+ return false;
+
+ return weapon.doNotDamageOwner;
+}
+
+
+function should_do_player_damage( eAttacker, weapon, sMeansOfDeath, iDFlags )
+{
+ if ( game["state"] == "postgame" )
+ return false;
+
+ if ( self.sessionteam == "spectator" )
+ return false;
+
+ if ( isdefined( self.canDoCombat ) && !self.canDoCombat )
+ return false;
+
+ if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && isdefined( eAttacker.canDoCombat ) && !eAttacker.canDoCombat )
+ return false;
+
+ if ( isdefined( level.hostMigrationTimer ) )
+ return false;
+
+ if ( level.onlyHeadShots )
+ {
+ if ( sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" )
+ return false;
+ }
+
+ // Make all vehicle drivers invulnerable to bullets
+ if ( self vehicle::player_is_occupant_invulnerable( sMeansOfDeath ) )
+ return false;
+
+ if ( weapon.isSupplyDropWeapon && !weapon.isGrenadeWeapon && ( smeansofdeath != "MOD_TRIGGER_HURT" ) )
+ return false;
+
+ if ( self.scene_takedamage === false )
+ return false;
+
+ // prevent spawn kill wall bangs
+ if ( (iDFlags & 8) && self player::is_spawn_protected() )
+ return false;
+
+return true;
+}
+
+function apply_damage_to_armor( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, sHitLoc, friendlyFire, ignore_round_start_friendly_fire )
+{
+ victim = self;
+
+ if ( friendlyFire && !player_damage_does_friendly_fire_damage_victim( ignore_round_start_friendly_fire ) )
+ return iDamage;
+
+ // Handle armor damage
+ if( IsDefined( victim.lightArmorHP ) )
+ {
+ if ( weapon.ignoresLightArmor && sMeansOfDeath != "MOD_MELEE" )
+ {
+ return iDamage;
+ }
+ else if ( weapon.meleeIgnoresLightArmor && sMeansOfDeath == "MOD_MELEE" )
+ {
+ return iDamage;
+ }
+ // anything stuck to the player does health damage
+ else if( IsDefined( eInflictor ) && IsDefined( eInflictor.stuckToPlayer ) && eInflictor.stuckToPlayer == victim )
+ {
+ iDamage = victim.health;
+ }
+ else
+ {
+ // Handle Armor Damage
+ // no armor damage in case of falling, melee, fmj or head shots
+ if ( sMeansOfDeath != "MOD_FALLING"
+ && !weapon_utils::isMeleeMOD( sMeansOfDeath )
+ && !globallogic_utils::isHeadShot( weapon, sHitLoc, sMeansOfDeath, eAttacker )
+ )
+ {
+ victim armor::setLightArmorHP( victim.lightArmorHP - ( iDamage ) );
+
+ iDamage = 0;
+ if ( victim.lightArmorHP <= 0 )
+ {
+ // since the light armor is gone, adjust the damage to be the excess damage that happens after the light armor hp is reduced
+ iDamage = abs( victim.lightArmorHP );
+ armor::unsetLightArmor();
+ }
+ }
+ }
+ }
+
+ return iDamage;
+}
+
+function make_sure_damage_is_not_zero( iDamage )
+{
+ // Make sure at least one point of damage is done & give back 1 health because of this if you have power armor
+ if ( iDamage < 1 )
+ {
+ if( ( self ability_util::gadget_power_armor_on() ) && isDefined( self.maxHealth ) && ( self.health < self.maxHealth ) )
+ {
+ self.health += 1;
+ }
+ iDamage = 1;
+ }
+
+ return int(iDamage);
+}
+
+function modify_player_damage_friendlyfire( iDamage )
+{
+ friendlyfire = [[ level.figure_out_friendly_fire ]]( self );
+
+ // half damage
+ if ( friendlyfire == 2 || friendlyfire == 3 )
+ {
+ iDamage = int(iDamage * .5);
+ }
+
+ return iDamage;
+}
+
+function modify_player_damage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex )
+{
+ if ( isdefined( self.overridePlayerDamage ) )
+ {
+ iDamage = self [[self.overridePlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex );
+ }
+ else if ( isdefined( level.overridePlayerDamage ) )
+ {
+ iDamage = self [[level.overridePlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex );
+ }
+
+ assert(isdefined(iDamage), "You must return a value from a damage override function.");
+
+ if ( isdefined( eAttacker ) )
+ {
+ iDamage = loadout::cac_modified_damage( self, eAttacker, iDamage, sMeansOfDeath, weapon, eInflictor, sHitLoc );
+
+ if( isdefined( eAttacker.pickup_damage_scale ) && eAttacker.pickup_damage_scale_time > GetTime() )
+ {
+ iDamage = iDamage * eAttacker.pickup_damage_scale;
+ }
+ }
+ iDamage = custom_gamemodes_modified_damage( self, eAttacker, iDamage, sMeansOfDeath, weapon, eInflictor, sHitLoc );
+
+ if ( level.onPlayerDamage != &globallogic::blank )
+ {
+ modifiedDamage = [[level.onPlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime );
+
+ if ( isdefined( modifiedDamage ) )
+ {
+ if ( modifiedDamage <= 0 )
+ return;
+
+ iDamage = modifiedDamage;
+ }
+ }
+
+ if ( level.onlyHeadShots )
+ {
+ if ( sMeansOfDeath == "MOD_HEAD_SHOT" )
+ iDamage = 150;
+ }
+
+ if ( weapon.damageAlwaysKillsPlayer )
+ {
+ iDamage = self.maxHealth + 1;
+ }
+
+ if ( sHitLoc == "riotshield" )
+ {
+ if ( iDFlags & 32 )
+ {
+ if ( !(iDFlags & 64) )
+ {
+ iDamage *= 0.0;
+ }
+ }
+ else if ( iDFlags & 128 )
+ {
+ if ( isdefined( eInflictor ) && isdefined( eInflictor.stuckToPlayer ) && eInflictor.stuckToPlayer == self )
+ {
+ //does enough damage to shield carrier to ensure death
+ iDamage = self.maxhealth + 1;
+ }
+ }
+ }
+
+ return int(iDamage);
+}
+
+function modify_player_damage_meansofdeath( eInflictor, eAttacker, sMeansOfDeath, weapon, sHitLoc )
+{
+ if ( globallogic_utils::isHeadShot( weapon, sHitLoc, sMeansOfDeath, eInflictor ) && isPlayer(eAttacker) && !weapon_utils::ismeleemod( sMeansOfDeath ) )
+ {
+ sMeansOfDeath = "MOD_HEAD_SHOT";
+ }
+
+ if ( isdefined( eInflictor ) && isdefined( eInflictor.script_noteworthy ) )
+ {
+ if ( eInflictor.script_noteworthy == "ragdoll_now" )
+ {
+ sMeansOfDeath = "MOD_FALLING";
+ }
+ }
+
+ return sMeansOfDeath;
+}
+
+function player_damage_update_attacker( eInflictor, eAttacker, sMeansOfDeath )
+{
+ if ( isdefined( eInflictor ) && isPlayer( eAttacker ) && eAttacker == eInflictor )
+ {
+ if ( sMeansOfDeath == "MOD_HEAD_SHOT" || sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" )
+ {
+ //if ( isPlayer( eAttacker ) ) already tested for above
+ {
+ eAttacker.hits++;
+ }
+ }
+ }
+
+ if ( isPlayer( eAttacker ) )
+ eAttacker.pers["participation"]++;
+}
+
+function player_is_spawn_protected_from_explosive( eInflictor, weapon, sMeansOfDeath )
+{
+ if ( !self player::is_spawn_protected() )
+ return false;
+
+ // if we are using this as a impact damage only projectile then no protection
+ // we should probably add a bool to the weapon to indicate that it spawn protects
+ if ( weapon.explosionradius == 0 )
+ return false;
+
+ distSqr = ( ( isdefined( eInflictor ) && isdefined( self.lastSpawnPoint ) ) ? DistanceSquared( eInflictor.origin, self.lastSpawnPoint.origin ) : 0 );
+
+ // protect players from spawnkill grenades, tabun and incendiary
+ if ( distSqr < ( (250) * (250) ) )
+ {
+ if ( sMeansOfDeath == "MOD_GRENADE" || sMeansOfDeath == "MOD_GRENADE_SPLASH" )
+ {
+ return true;
+ }
+
+ if ( sMeansOfDeath == "MOD_PROJECTILE" || sMeansOfDeath == "MOD_PROJECTILE_SPLASH" )
+ {
+ return true;
+ }
+
+ if ( sMeansOfDeath == "MOD_EXPLOSIVE" )
+ {
+ return true;
+ }
+ }
+
+ if ( killstreaks::is_killstreak_weapon( weapon ) )
+ {
+ return true;
+ }
+
+ return false;
+}
+
+function player_damage_update_explosive_info( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex )
+{
+ is_explosive_damage = loadout::isExplosiveDamage( sMeansOfDeath );
+
+ if ( is_explosive_damage )
+ {
+ // protect players from spawnkill grenades, tabun, incendiaries, and scorestreaks
+ if ( self player_is_spawn_protected_from_explosive( eInflictor, weapon, sMeansOfDeath ) )
+ {
+ return false;
+ }
+
+ // protect players from their own non-player controlled killstreaks
+ if ( self isPlayerImmuneToKillstreak( eAttacker, weapon ) )
+ {
+ return false;
+ }
+ }
+
+ if ( isdefined( eInflictor ) && ( sMeansOfDeath == "MOD_GAS" || is_explosive_damage ) )
+ {
+ self.explosiveInfo = [];
+ self.explosiveInfo["damageTime"] = getTime();
+ self.explosiveInfo["damageId"] = eInflictor getEntityNumber();
+ self.explosiveInfo["originalOwnerKill"] = false;
+ self.explosiveInfo["bulletPenetrationKill"] = false;
+ self.explosiveInfo["chainKill"] = false;
+ self.explosiveInfo["damageExplosiveKill"] = false;
+ self.explosiveInfo["chainKill"] = false;
+ self.explosiveInfo["cookedKill"] = false;
+ self.explosiveInfo["weapon"] = weapon;
+ self.explosiveInfo["originalowner"] = eInflictor.originalowner;
+
+ isFrag = ( weapon.rootweapon.name == "frag_grenade" );
+
+ if ( isdefined( eAttacker ) && eAttacker != self )
+ {
+ if ( isdefined( eAttacker ) && isdefined( eInflictor.owner ) && (weapon.name == "satchel_charge" || weapon.name == "claymore" || weapon.name == "bouncingbetty") )
+ {
+ self.explosiveInfo["originalOwnerKill"] = (eInflictor.owner == self);
+ self.explosiveInfo["damageExplosiveKill"] = isdefined( eInflictor.wasDamaged );
+ self.explosiveInfo["chainKill"] = isdefined( eInflictor.wasChained );
+ self.explosiveInfo["wasJustPlanted"] = isdefined( eInflictor.wasJustPlanted );
+ self.explosiveInfo["bulletPenetrationKill"] = isdefined( eInflictor.wasDamagedFromBulletPenetration );
+ self.explosiveInfo["cookedKill"] = false;
+ }
+ if ( isdefined( eInflictor ) && isdefined( eInflictor.stuckToPlayer ) && weapon.projExplosionType == "grenade" )
+ {
+ self.explosiveInfo["stuckToPlayer"] = eInflictor.stuckToPlayer;
+ }
+ if ( weapon.doStun )
+ {
+ self.lastStunnedBy = eAttacker;
+ self.lastStunnedTime = self.iDFlagsTime;
+ }
+ if ( isdefined( eAttacker.lastGrenadeSuicideTime ) && eAttacker.lastGrenadeSuicideTime >= gettime() - 50 && isFrag )
+ {
+ self.explosiveInfo["suicideGrenadeKill"] = true;
+ }
+ else
+ {
+ self.explosiveInfo["suicideGrenadeKill"] = false;
+ }
+ }
+
+ if ( isFrag )
+ {
+ self.explosiveInfo["cookedKill"] = isdefined( eInflictor.isCooked );
+ self.explosiveInfo["throwbackKill"] = isdefined( eInflictor.threwBack );
+ }
+
+ if( isdefined( eAttacker ) && isPlayer( eAttacker ) && eAttacker != self )
+ {
+ self globallogic_score::setInflictorStat( eInflictor, eAttacker, weapon );
+ }
+ }
+
+ if( sMeansOfDeath == "MOD_IMPACT" && isdefined( eAttacker ) && isPlayer( eAttacker ) && eAttacker != self )
+ {
+ if ( weapon != level.weaponBallisticKnife )
+ {
+ self globallogic_score::setInflictorStat( eInflictor, eAttacker, weapon );
+ }
+
+ if ( weapon.rootweapon.name == "hatchet" && isdefined( eInflictor ) )
+ {
+ self.explosiveInfo["projectile_bounced"] = isdefined( eInflictor.bounced );
+ }
+ }
+
+ return true;
+}
+
+function player_damage_is_friendly_fire_at_round_start()
+{
+ //check for friendly fire at the begining of the match. apply the damage to the attacker only
+ if( level.friendlyFireDelay && level.friendlyFireDelayTime >= ( ( ( gettime() - level.startTime ) - level.discardTime ) / 1000 ) )
+ {
+ return true;
+ }
+
+ return false;
+}
+
+function player_damage_does_friendly_fire_damage_attacker( eAttacker, ignore_round_start_friendly_fire )
+{
+ if ( !IsAlive( eAttacker ) )
+ return false;
+
+ friendlyfire = [[ level.figure_out_friendly_fire ]]( self );
+
+ if ( friendlyfire == 1 ) // the friendly takes damage
+ {
+ //check for friendly fire at the begining of the match. apply the damage to the attacker only
+ if ( player_damage_is_friendly_fire_at_round_start() && ( ignore_round_start_friendly_fire == false ) )
+ {
+ return true;
+ }
+ }
+
+ if ( friendlyfire == 2 ) // only the attacker takes damage
+ {
+ return true;
+ }
+
+ if ( friendlyfire == 3 ) // both friendly and attacker take damage
+ {
+ return true;
+ }
+
+ return false;
+}
+
+function player_damage_does_friendly_fire_damage_victim( ignore_round_start_friendly_fire )
+{
+ friendlyfire = [[ level.figure_out_friendly_fire ]]( self );
+
+ if ( friendlyfire == 1 ) // the friendly takes damage
+ {
+ //check for friendly fire at the begining of the match. apply the damage to the attacker only
+ if ( player_damage_is_friendly_fire_at_round_start() && ( ignore_round_start_friendly_fire == false ) )
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ if ( friendlyfire == 3 ) // both friendly and attacker take damage
+ {
+ return true;
+ }
+
+ return false;
+}
+
+function player_damage_riotshield_hit( eAttacker, iDamage, sMeansOfDeath, weapon, attackerIsHittingTeammate)
+{
+ if (( sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" ) &&
+ ( !killstreaks::is_killstreak_weapon( weapon )) &&
+ ( !attackerIsHittingTeammate ) )
+ {
+ if ( self.hasRiotShieldEquipped )
+ {
+ if ( isPlayer( eAttacker ))
+ {
+ eAttacker.lastAttackedShieldPlayer = self;
+ eAttacker.lastAttackedShieldTime = getTime();
+ }
+
+ previous_shield_damage = self.shieldDamageBlocked;
+ self.shieldDamageBlocked += iDamage;
+
+ if (( self.shieldDamageBlocked % 400 /*riotshield_damage_score_threshold*/ ) < ( previous_shield_damage % 400 /*riotshield_damage_score_threshold*/ ))
+ {
+ score_event = "shield_blocked_damage";
+
+ if (( self.shieldDamageBlocked > 2000 /*riotshield_damage_score_max*/ ))
+ {
+ score_event = "shield_blocked_damage_reduced";
+ }
+
+ if ( isdefined( level.scoreInfo[ score_event ]["value"] ) )
+ {
+ // need to get the actual riot shield weapon here
+ self AddWeaponStat( level.weaponRiotshield, "score_from_blocked_damage", level.scoreInfo[ score_event ]["value"] );
+ }
+
+ scoreevents::processScoreEvent( score_event, self );
+ }
+ }
+ }
+
+}
+
+function does_player_completely_avoid_damage(iDFlags, sHitLoc, weapon, friendlyFire, attackerIsHittingSelf, sMeansOfDeath )
+{
+ if( iDFlags & 2048 )
+ return true;
+
+ if ( friendlyFire && level.friendlyfire == 0 )
+ return true;
+
+ if ( sHitLoc == "riotshield" )
+ {
+ if ( !(iDFlags & (32|128)) )
+ return true;
+ }
+
+
+ if( weapon.isEmp && sMeansOfDeath == "MOD_GRENADE_SPLASH" )
+ {
+ if( self hasperk("specialty_immuneemp") )
+ return true;
+ }
+
+ if ( isdefined( level.playerAvoidDamageGameMode ) && self [[ level.playerAvoidDamageGameMode ]]( iDFlags, sHitLoc, weapon, friendlyFire, attackerIsHittingSelf, sMeansOfDeath ) )
+ return true;
+
+ return false;
+}
+
+function player_damage_log( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex )
+{
+ pixbeginevent( "PlayerDamage log" );
+
+/#
+ // Do debug print if it's enabled
+ if(GetDvarint( "g_debugDamage"))
+ println("client:" + self getEntityNumber() + " health:" + self.health + " attacker:" + eAttacker.clientid + " inflictor is player:" + isPlayer(eInflictor) + " damage:" + iDamage + " hitLoc:" + sHitLoc);
+#/
+
+ if(self.sessionstate != "dead")
+ {
+ lpselfnum = self getEntityNumber();
+ lpselfname = self.name;
+ lpselfteam = self.team;
+ lpselfGuid = self getXuid();
+
+ if (self util::is_bot())
+ {
+ lpselfGuid = "bot0";
+ }
+
+ lpattackerteam = "";
+ lpattackerorigin = ( 0, 0, 0 );
+
+ if(isPlayer(eAttacker))
+ {
+ lpattacknum = eAttacker getEntityNumber();
+ lpattackGuid = eAttacker getXuid();
+
+ if (eAttacker util::is_bot())
+ {
+ lpattackGuid = "bot0";
+ }
+
+ lpattackname = eAttacker.name;
+ lpattackerteam = eAttacker.team;
+ lpattackerorigin = eAttacker.origin;
+ isusingheropower = 0;
+
+ if ( eAttacker ability_player::is_using_any_gadget() )
+ isusingheropower = 1;
+
+ bbPrint( "mpattacks", "gametime %d attackerspawnid %d attackerweapon %s attackerx %d attackery %d attackerz %d victimspawnid %d victimx %d victimy %d victimz %d damage %d damagetype %s damagelocation %s death %d isusingheropower %d",
+ gettime(), getplayerspawnid( eAttacker ), weapon.name, lpattackerorigin, getplayerspawnid( self ), self.origin, iDamage, sMeansOfDeath, sHitLoc, 0, isusingheropower );
+ }
+ else
+ {
+ lpattacknum = -1;
+ lpattackGuid = "";
+ lpattackname = "";
+ lpattackerteam = "world";
+ bbPrint( "mpattacks", "gametime %d attackerweapon %s victimspawnid %d victimx %d victimy %d victimz %d damage %d damagetype %s damagelocation %s death %d isusingheropower %d",
+ gettime(), weapon.name, getplayerspawnid( self ), self.origin, iDamage, sMeansOfDeath, sHitLoc, 0, 0 );
+ }
+ logPrint("D;" + lpselfGuid + ";" + lpselfnum + ";" + lpselfteam + ";" + lpselfname + ";" + lpattackGuid + ";" + lpattacknum + ";" + lpattackerteam + ";" + lpattackname + ";" + weapon.name + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n");
+ }
+
+ pixendevent(); // "END: PlayerDamage log"
+}
+
+function should_allow_postgame_damage( sMeansOfDeath )
+{
+ if ( sMeansOfDeath == "MOD_TRIGGER_HURT" || sMeansOfDeath == "MOD_CRUSH" )
+ return true;
+
+ return false;
+}
+
+function do_post_game_damage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal )
+{
+ if ( game["state"] != "postgame" )
+ return;
+
+ if ( !should_allow_postgame_damage( sMeansOfDeath ) )
+ return;
+
+ // just pass it along
+ self finishPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, "MOD_POST_GAME", weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal );
+}
+
+function Callback_PlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal )
+{
+ profilelog_begintiming( 6, "ship" );
+
+ do_post_game_damage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal );
+
+ if ( sMeansOfDeath == "MOD_CRUSH" && isdefined( eInflictor ) && ( eInflictor.deal_no_crush_damage === true ) )
+ {
+ return;
+ }
+
+ if ( isdefined( eInflictor ) && eInflictor.killstreakType === "siegebot" )
+ {
+ if ( eInflictor.team === "neutral" )
+ return;
+ }
+
+ self.iDFlags = iDFlags;
+ self.iDFlagsTime = getTime();
+
+ // determine if we should treat owner damage as friendly fire
+ if ( !IsPlayer( eAttacker ) && isdefined( eAttacker ) && eAttacker.owner === self )
+ {
+ treat_self_damage_as_friendly_fire = eAttacker.treat_owner_damage_as_friendly_fire;
+ }
+
+ // determine if we should ignore_round_start_friendly_fire
+ ignore_round_start_friendly_fire = ( isdefined( eInflictor ) && ( sMeansOfDeath == "MOD_CRUSH" ) || sMeansOfDeath == "MOD_HIT_BY_OBJECT" );
+
+ eAttacker = figure_out_attacker( eAttacker );
+
+ // no damage from people who have dropped into laststand
+ if ( IsPlayer( eAttacker ) && ( isdefined( eAttacker.laststand ) && eAttacker.laststand ) )
+ {
+ return;
+ }
+
+ sMeansOfDeath = modify_player_damage_meansofdeath( eInflictor, eAttacker, sMeansOfDeath, weapon, sHitLoc );
+
+ if ( !(self should_do_player_damage( eAttacker, weapon, sMeansOfDeath, iDFlags )) )
+ return;
+
+ player_damage_update_attacker( eInflictor, eAttacker, sMeansOfDeath );
+
+ weapon = player_damage_figure_out_weapon( weapon, eInflictor );
+
+ pixbeginevent( "PlayerDamage flags/tweaks" );
+
+ // Don't do knockback if the damage direction was not specified
+ if( !isdefined( vDir ) )
+ iDFlags |= 4;
+
+ attackerIsHittingTeammate = isPlayer( eAttacker ) && ( self util::IsEnemyPlayer( eAttacker ) == false );
+ attackerIsHittingSelf = IsPlayer( eAttacker ) && (self == eAttacker);
+
+ friendlyFire = ( ( attackerIsHittingSelf && treat_self_damage_as_friendly_fire === true ) // some killstreaks treak owner damage as friendly-fire
+ || ( level.teamBased && !attackerIsHittingSelf && attackerIsHittingTeammate ) ); // teammates are always friendly-fire, but self is handled above
+
+ pixendevent(); // "END: PlayerDamage flags/tweaks"
+
+ iDamage = modify_player_damage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex );
+ if ( friendlyFire )
+ {
+ iDamage = modify_player_damage_friendlyfire( iDamage );
+ }
+
+ if( ( isdefined( self.power_armor_took_damage ) && self.power_armor_took_damage ) )
+ {
+ iDFlags |= 1024;
+ }
+
+ if ( sHitLoc == "riotshield" )
+ {
+ // do we want all of the damage modifiers that get applied for the player to get applied to this damage?
+ // or friendly fire?
+ player_damage_riotshield_hit( eAttacker, iDamage, sMeansOfDeath, weapon, attackerIsHittingTeammate);
+ }
+
+ // check for completely getting out of the damage
+ if ( self does_player_completely_avoid_damage(iDFlags, sHitLoc, weapon, friendlyFire, attackerIsHittingSelf, sMeansOfDeath ) )
+ {
+ return;
+ }
+
+ // do we want this called pre or post damage application?
+ self callback::callback( #"on_player_damage" );
+
+ armor = self armor::getArmor();
+
+ iDamage = apply_damage_to_armor( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, sHitLoc, friendlyFire, ignore_round_start_friendly_fire );
+ iDamage = make_sure_damage_is_not_zero( iDamage );
+
+ armor_damaged = (armor != self armor::getArmor());
+
+ // this must be below the damage modification functions as they use this to determine riotshield hits
+ if ( sHitLoc == "riotshield" )
+ {
+ sHitLoc = "none"; // code ignores any damage to a "shield" bodypart.
+ }
+
+ if ( !player_damage_update_explosive_info( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex ) )
+ return;
+
+ prevHealthRatio = self.health / self.maxhealth;
+
+ if ( friendlyFire )
+ {
+ pixmarker( "BEGIN: PlayerDamage player" ); // profs automatically end when the function returns
+
+ if ( player_damage_does_friendly_fire_damage_victim( ignore_round_start_friendly_fire ) )
+ {
+ self.lastDamageWasFromEnemy = false;
+
+ self finishPlayerDamageWrapper(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal);
+ }
+ else if ( weapon.forceDamageShellshockAndRumble )
+ {
+ self damageShellshockAndRumble( eAttacker, eInflictor, weapon, sMeansOfDeath, iDamage );
+ }
+
+ if ( player_damage_does_friendly_fire_damage_attacker( eAttacker, ignore_round_start_friendly_fire ) )
+ {
+ eAttacker.lastDamageWasFromEnemy = false;
+
+ eAttacker.friendlydamage = true;
+ eAttacker finishPlayerDamageWrapper(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal);
+ eAttacker.friendlydamage = undefined;
+ }
+
+ pixmarker( "END: PlayerDamage player" );
+ }
+ else
+ {
+ behaviorTracker::UpdatePlayerDamage( eAttacker, self, iDamage );
+
+ self.lastAttackWeapon = weapon;
+
+ giveAttackerAndInflictorOwnerAssist( eAttacker, eInflictor, iDamage, sMeansOfDeath, weapon );
+
+ if ( isdefined( eAttacker ) )
+ level.lastLegitimateAttacker = eAttacker;
+
+ if ( ( sMeansOfDeath == "MOD_GRENADE" || sMeansOfDeath == "MOD_GRENADE_SPLASH" ) && isdefined( eInflictor ) && isdefined( eInflictor.isCooked ) )
+ self.wasCooked = getTime();
+ else
+ self.wasCooked = undefined;
+
+ self.lastDamageWasFromEnemy = (isdefined( eAttacker ) && (eAttacker != self));
+
+ if ( self.lastDamageWasFromEnemy )
+ {
+ if ( isplayer( eAttacker ) )
+ {
+ if ( isdefined ( eAttacker.damagedPlayers[ self.clientId ] ) == false )
+ eAttacker.damagedPlayers[ self.clientId ] = spawnstruct();
+
+ eAttacker.damagedPlayers[ self.clientId ].time = getTime();
+ eAttacker.damagedPlayers[ self.clientId ].entity = self;
+ }
+ }
+
+ if( isPlayer( eAttacker ) && isDefined(weapon.gadget_type) && weapon.gadget_type == 14 )
+ {
+ if( isDefined(eAttacker.heroweaponHits) )
+ {
+ eAttacker.heroweaponHits++;
+ }
+ }
+
+ self finishPlayerDamageWrapper(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal);
+ }
+
+ if ( isdefined( eAttacker ) && !attackerIsHittingSelf )
+ {
+ if ( damagefeedback::doDamageFeedback( weapon, eInflictor, iDamage, sMeansOfDeath ) )
+ {
+ // the perk feedback should be shown only if the enemy is damaged and not killed.
+ if ( iDamage > 0 && self.health > 0 )
+ {
+ perkFeedback = doPerkFeedBack( self, weapon, sMeansOfDeath, eInflictor, armor_damaged );
+ }
+
+ eAttacker thread damagefeedback::update( sMeansOfDeath, eInflictor, perkFeedback, weapon, self, psOffsetTime, sHitLoc );
+ }
+ }
+
+ if( !isdefined(eAttacker) || !friendlyFire || ( isdefined( level.hardcoreMode ) && level.hardcoreMode ) )
+ {
+ if ( isdefined( level.customPlayPainSound ) )
+ self [[ level.customPlayPainSound ]]( sMeansOfDeath );
+ else
+ self battlechatter::pain_vox( sMeansOfDeath );
+ }
+
+ self.hasDoneCombat = true;
+
+ if( weapon.isEmp && sMeansOfDeath == "MOD_GRENADE_SPLASH" )
+ {
+ if( !self hasperk("specialty_immuneemp") )
+ {
+ self notify( "emp_grenaded", eAttacker, vPoint );
+ }
+ }
+
+ if ( isdefined( eAttacker ) && eAttacker != self && !friendlyFire )
+ level.useStartSpawns = false;
+
+ player_damage_log( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex );
+
+ profilelog_endtiming( 6, "gs=" + game["state"] + " zom=" + SessionModeIsZombiesGame() );
+}
+
+function resetAttackerList()
+{
+ self.attackers = [];
+ self.attackerData = [];
+ self.attackerDamage = [];
+ self.firstTimeDamaged = 0;
+}
+
+function resetAttackersThisSpawnList()
+{
+ self.attackersThisSpawn = [];
+}
+
+function doPerkFeedBack( player, weapon, sMeansOfDeath, eInflictor, armor_damaged )
+{
+ perkFeedback = undefined;
+ hasTacticalMask = loadout::hasTacticalMask( player );
+ hasFlakJacket = ( player HasPerk( "specialty_flakjacket" ) );
+ isExplosiveDamage = loadout::isExplosiveDamage( sMeansOfDeath );
+ isFlashOrStunDamage = weapon_utils::isFlashOrStunDamage( weapon, sMeansOfDeath );
+
+ if ( isFlashOrStunDamage && hasTacticalMask )
+ {
+ perkFeedback = "tacticalMask";
+ }
+ else if ( player HasPerk( "specialty_fireproof" ) && loadout::isFireDamage( weapon, sMeansOfDeath ) )
+ {
+ perkFeedback = "flakjacket";
+ }
+ else if ( isExplosiveDamage && hasFlakJacket && !weapon.ignoresFlakJacket && ( !isAIKillstreakDamage( weapon, eInflictor ) ) )
+ {
+ perkFeedback = "flakjacket";
+ }
+ else if ( armor_damaged )
+ {
+ perkFeedback = "armor";
+ }
+
+ return perkFeedback;
+}
+
+function isAIKillstreakDamage( weapon, eInflictor )
+{
+ if ( weapon.isAIKillstreakDamage )
+ {
+ if ( weapon.name != "ai_tank_drone_rocket" || isdefined( eInflictor.firedByAI ) )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+function finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal )
+{
+ pixbeginevent("finishPlayerDamageWrapper");
+
+ if( !level.console && iDFlags & 8 && isplayer ( eAttacker ) )
+ {
+ /#
+ println("penetrated:" + self getEntityNumber() + " health:" + self.health + " attacker:" + eAttacker.clientid + " inflictor is player:" + isPlayer(eInflictor) + " damage:" + iDamage + " hitLoc:" + sHitLoc);
+ #/
+ eAttacker AddPlayerStat( "penetration_shots", 1 );
+ }
+
+ if ( GetDvarString( "scr_csmode" ) != "" )
+ self shellShock( "damage_mp", 0.2 );
+
+ if ( isdefined( level.customDamageShellshockAndRumble ) )
+ self [[ level.customDamageShellshockAndRumble ]]( eAttacker, eInflictor, weapon, sMeansOfDeath, iDamage, vPoint );
+ else
+ self damageShellshockAndRumble( eAttacker, eInflictor, weapon, sMeansOfDeath, iDamage );
+
+ self ability_power::power_loss_event_took_damage( eAttacker, eInflictor, weapon, sMeansOfDeath, iDamage );
+
+ if( isPlayer( eAttacker) )
+ {
+ self.lastShotBy = eAttacker.clientid;
+ }
+
+ if ( sMeansOfDeath == "MOD_BURNED" )
+ {
+ self burnplayer::TakingBurnDamage( eAttacker, weapon, sMeansOfDeath );
+ }
+
+ self.gadget_was_active_last_damage = self GadgetIsActive( 0 );
+
+ self finishPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal );
+
+ pixendevent();
+}
+
+function allowedAssistWeapon( weapon )
+{
+ if ( !killstreaks::is_killstreak_weapon( weapon ) )
+ return true;
+
+ if (killstreaks::is_killstreak_weapon_assist_allowed( weapon ) )
+ return true;
+
+ return false;
+}
+
+function PlayerKilled_Killstreaks( attacker, weapon )
+{
+ if( !isdefined( self.switching_teams ) )
+ {
+ // if team killed we reset kill streak, but dont count death and death streak
+ if ( isPlayer( attacker ) && level.teamBased && ( attacker != self ) && ( self.team == attacker.team ) )
+ {
+
+ self.pers["cur_kill_streak"] = 0;
+ self.pers["cur_total_kill_streak"] = 0;
+ self.pers["totalKillstreakCount"] = 0;
+ self.pers["killstreaksEarnedThisKillstreak"] = 0;
+ self setplayercurrentstreak( 0 );
+ }
+ else
+ {
+ self globallogic_score::incPersStat( "deaths", 1, true, true );
+ self.deaths = self globallogic_score::getPersStat( "deaths" );
+ self UpdateStatRatio( "kdratio", "kills", "deaths" );
+
+ if( self.pers["cur_kill_streak"] > self.pers["best_kill_streak"] )
+ self.pers["best_kill_streak"] = self.pers["cur_kill_streak"];
+
+ // need to keep the current killstreak to see if this was a buzzkill later
+ self.pers["kill_streak_before_death"] = self.pers["cur_kill_streak"];
+
+
+ self.pers["cur_kill_streak"] = 0;
+ self.pers["cur_total_kill_streak"] = 0;
+ self.pers["totalKillstreakCount"] = 0;
+ self.pers["killstreaksEarnedThisKillstreak"] = 0;
+ self setplayercurrentstreak( 0 );
+
+ self.cur_death_streak++;
+
+ if ( self.cur_death_streak > self.death_streak )
+ {
+ if ( level.rankedMatch && !level.disableStatTracking )
+ {
+ self setDStat( "HighestStats", "death_streak", self.cur_death_streak );
+ }
+ self.death_streak = self.cur_death_streak;
+ }
+
+ if( self.cur_death_streak >= GetDvarint( "perk_deathStreakCountRequired" ) )
+ {
+ self enabledeathstreak();
+ }
+ }
+ }
+ else
+ {
+ self.pers["totalKillstreakCount"] = 0;
+ self.pers["killstreaksEarnedThisKillstreak"] = 0;
+ }
+
+ if ( !SessionModeIsZombiesGame() && killstreaks::is_killstreak_weapon( weapon ) )
+ {
+ level.globalKillstreaksDeathsFrom++;
+ }
+}
+
+function PlayerKilled_WeaponStats( attacker, weapon, sMeansOfDeath, wasInLastStand, lastWeaponBeforeDroppingIntoLastStand, inflictor )
+{
+ // Don't increment weapon stats for team kills or deaths
+ if ( isPlayer( attacker ) && attacker != self && ( !level.teamBased || ( level.teamBased && self.team != attacker.team ) ) )
+ {
+ attackerWeaponPickedUp = false;
+ if( isdefined( attacker.pickedUpWeapons ) && isdefined( attacker.pickedUpWeapons[weapon] ) )
+ {
+ attackerWeaponPickedUp = true;
+ }
+ self AddWeaponStat( weapon, "deaths", 1, self.class_num, attackerWeaponPickedUp, undefined, self.primaryLoadoutGunSmithVariantIndex, self.secondaryLoadoutGunSmithVariantIndex );
+
+ if ( wasInLastStand && isdefined( lastWeaponBeforeDroppingIntoLastStand ) )
+ victim_weapon = lastWeaponBeforeDroppingIntoLastStand;
+ else
+ victim_weapon = self.lastdroppableweapon;
+
+ if ( isdefined( victim_weapon ) )
+ {
+ victimWeaponPickedUp = false;
+ if( isdefined( self.pickedUpWeapons ) && isdefined( self.pickedUpWeapons[victim_weapon] ) )
+ {
+ victimWeaponPickedUp = true;
+ }
+ self AddWeaponStat( victim_weapon, "deathsDuringUse", 1, self.class_num, victimWeaponPickedUp, undefined, self.primaryLoadoutGunSmithVariantIndex, self.secondaryLoadoutGunSmithVariantIndex );
+ }
+
+
+ recordWeaponStatKills = true;
+ if ( ( attacker.isThief === true ) && isdefined( weapon ) && ( weapon.isHeroWeapon === true ) )
+ {
+ recordWeaponStatKills = false; // Blackjack's Rogue kills are tracked as specialiststats[9].stats.kills_weapon
+ }
+
+ if ( sMeansOfDeath != "MOD_FALLING" && recordWeaponStatKills )
+ {
+ if ( weapon.name == "explosive_bolt" && IsDefined( inflictor ) && IsDefined( inflictor.ownerWeaponAtLaunch ) && inflictor.ownerAdsAtLaunch )
+ {
+ inflictorOwnerWeaponAtLaunchPickedUp = false;
+ if( isdefined( attacker.pickedUpWeapons ) && isdefined( attacker.pickedUpWeapons[inflictor.ownerWeaponAtLaunch] ) )
+ {
+ inflictorOwnerWeaponAtLaunchPickedUp = true; // ever the case?
+ }
+ attacker AddWeaponStat( inflictor.ownerWeaponAtLaunch, "kills", 1, attacker.class_num, inflictorOwnerWeaponAtLaunchPickedUp, true, attacker.primaryLoadoutGunSmithVariantIndex, attacker.secondaryLoadoutGunSmithVariantIndex );
+ }
+ else
+ {
+ if ( isdefined( attacker ) && isdefined( attacker.class_num ) )
+ attacker AddWeaponStat( weapon, "kills", 1, attacker.class_num, attackerWeaponPickedUp, undefined, attacker.primaryLoadoutGunSmithVariantIndex, attacker.secondaryLoadoutGunSmithVariantIndex );
+ }
+ }
+
+ if ( sMeansOfDeath == "MOD_HEAD_SHOT" )
+ {
+ attacker AddWeaponStat( weapon, "headshots", 1, attacker.class_num, attackerWeaponPickedUp, undefined, attacker.primaryLoadoutGunSmithVariantIndex, attacker.secondaryLoadoutGunSmithVariantIndex );
+ }
+
+ if ( sMeansOfDeath == "MOD_PROJECTILE" || ( ( sMeansOfDeath == "MOD_GRENADE" || sMeansOfDeath == "MOD_IMPACT" ) && weapon.rootWeapon.statIndex == level.weaponLauncherEx41.statIndex ) )
+ {
+ attacker AddWeaponStat( weapon, "direct_hit_kills", 1 );
+ }
+
+ victimIsRoulette = ( self.isRoulette === true );
+ if ( self ability_player::gadget_CheckHeroAbilityKill( attacker ) && !victimIsRoulette )
+ {
+ attacker AddWeaponStat( attacker.heroAbility, "kills_while_active", 1 );
+ }
+ }
+}
+
+function PlayerKilled_Obituary( attacker, eInflictor, weapon, sMeansOfDeath )
+{
+ if ( !isplayer( attacker ) || ( self util::IsEnemyPlayer( attacker ) == false ) || ( isdefined ( weapon ) && killstreaks::is_killstreak_weapon( weapon ) ) )
+ {
+ level notify( "reset_obituary_count" );
+ level.lastObituaryPlayerCount = 0;
+ level.lastObituaryPlayer = undefined;
+ }
+ else
+ {
+ if ( isdefined( level.lastObituaryPlayer ) && level.lastObituaryPlayer == attacker )
+ {
+ level.lastObituaryPlayerCount++;
+ }
+ else
+ {
+ level notify( "reset_obituary_count" );
+ level.lastObituaryPlayer = attacker;
+ level.lastObituaryPlayerCount = 1;
+ }
+
+ level thread scoreevents::decrementLastObituaryPlayerCountAfterFade();
+
+ if ( level.lastObituaryPlayerCount >= 4 )
+ {
+ level notify( "reset_obituary_count" );
+ level.lastObituaryPlayerCount = 0;
+ level.lastObituaryPlayer = undefined;
+ self thread scoreevents::uninterruptedObitFeedKills( attacker, weapon );
+ }
+ }
+
+ if ( !isplayer( attacker ) || ( isdefined( weapon ) && !killstreaks::is_killstreak_weapon( weapon ) ) )
+ {
+ behaviorTracker::UpdatePlayerKilled( attacker, self );
+ }
+
+ overrideEntityCamera = killstreaks::should_override_entity_camera_in_demo( attacker, weapon );
+
+ if( isdefined( eInflictor ) && ( eInflictor.archetype === "robot" ) )
+ {
+ if( sMeansOfDeath == "MOD_HIT_BY_OBJECT" )
+ weapon = GetWeapon( "combat_robot_marker" );
+ sMeansOfDeath = "MOD_RIFLE_BULLET";
+ }
+ // send out an obituary message to all clients about the kill
+ if( level.teamBased && isdefined( attacker.pers ) && self.team == attacker.team && sMeansOfDeath == "MOD_GRENADE" && level.friendlyfire == 0 )
+ {
+ obituary(self, self, weapon, sMeansOfDeath);
+ demo::bookmark( "kill", gettime(), self, self, 0, eInflictor, overrideEntityCamera );
+ }
+ else
+ {
+ obituary(self, attacker, weapon, sMeansOfDeath);
+ demo::bookmark( "kill", gettime(), attacker, self, 0, eInflictor, overrideEntityCamera );
+ }
+}
+
+function PlayerKilled_Suicide( eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc )
+{
+ awardAssists = false;
+ self.suicide = false;
+
+ // switching teams
+ if ( isdefined( self.switching_teams ) )
+ {
+
+ if ( !level.teamBased && ( isdefined( level.teams[ self.leaving_team ] ) && isdefined( level.teams[ self.joining_team ] ) && level.teams[ self.leaving_team ] != level.teams[ self.joining_team ] ) )
+ {
+ playerCounts = self teams::count_players();
+ playerCounts[self.leaving_team]--;
+ playerCounts[self.joining_team]++;
+
+ if( (playerCounts[self.joining_team] - playerCounts[self.leaving_team]) > 1 )
+ {
+ scoreevents::processScoreEvent( "suicide", self );
+ self thread rank::giveRankXP( "suicide" );
+ self globallogic_score::incPersStat( "suicides", 1 );
+ self.suicides = self globallogic_score::getPersStat( "suicides" );
+ self.suicide = true;
+ }
+ }
+ }
+ else
+ {
+ scoreevents::processScoreEvent( "suicide", self );
+ self globallogic_score::incPersStat( "suicides", 1 );
+ self.suicides = self globallogic_score::getPersStat( "suicides" );
+
+ if ( sMeansOfDeath == "MOD_SUICIDE" && sHitLoc == "none" && self.throwingGrenade )
+ {
+ self.lastGrenadeSuicideTime = gettime();
+ }
+
+ if ( level.maxSuicidesBeforeKick > 0 && level.maxSuicidesBeforeKick <= self.suicides )
+ {
+ // should change "teamKillKicked" to just kicked for the next game
+ self notify( "teamKillKicked" );
+ self SuicideKick();
+ }
+
+ //Check for player death related battlechatter
+ thread battlechatter::on_player_suicide_or_team_kill( self, "suicide" ); //Play suicide battlechatter
+
+ //check if assist points should be awarded
+ awardAssists = true;
+ self.suicide = true;
+ }
+
+ if( isdefined( self.friendlydamage ) )
+ {
+ self iPrintLn(&"MP_FRIENDLY_FIRE_WILL_NOT");
+ if ( level.teamKillPointLoss )
+ {
+ scoreSub = self [[level.getTeamKillScore]]( eInflictor, attacker, sMeansOfDeath, weapon);
+
+ score = globallogic_score::_getPlayerScore( attacker ) - scoreSub;
+
+ if ( score < 0 )
+ score = 0;
+
+ globallogic_score::_setPlayerScore( attacker, score );
+ }
+ }
+
+ return awardAssists;
+}
+
+function PlayerKilled_TeamKill( eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc )
+{
+ scoreevents::processScoreEvent( "team_kill", attacker );
+
+ self.teamKilled = true;
+
+ if ( !IgnoreTeamKills( weapon, sMeansOfDeath, eInflictor ) )
+ {
+ teamkill_penalty = self [[level.getTeamKillPenalty]]( eInflictor, attacker, sMeansOfDeath, weapon);
+
+ attacker globallogic_score::incPersStat( "teamkills_nostats", teamkill_penalty, false );
+ attacker globallogic_score::incPersStat( "teamkills", 1 ); //save team kills to player stats
+ attacker.teamkillsThisRound++;
+
+ if ( level.teamKillPointLoss )
+ {
+ scoreSub = self [[level.getTeamKillScore]]( eInflictor, attacker, sMeansOfDeath, weapon);
+
+ score = globallogic_score::_getPlayerScore( attacker ) - scoreSub;
+
+ if ( score < 0 )
+ {
+ score = 0;
+ }
+
+ globallogic_score::_setPlayerScore( attacker, score );
+ }
+
+ if ( globallogic_utils::getTimePassed() < 5000 )
+ teamKillDelay = 1;
+ else if ( attacker.pers["teamkills_nostats"] > 1 && globallogic_utils::getTimePassed() < (8000 + (attacker.pers["teamkills_nostats"] * 1000)) )
+ teamKillDelay = 1;
+ else
+ teamKillDelay = attacker TeamKillDelay();
+
+ if ( teamKillDelay > 0 )
+ {
+ attacker.teamKillPunish = true;
+ attacker thread wait_and_suicide(); // can't eject the teamkilling player same frame bc it purges EV_FIRE_WEAPON fx
+
+ if ( attacker ShouldTeamKillKick(teamKillDelay) )
+ {
+ // should change "teamKillKicked" to just kicked for the next game
+ attacker notify( "teamKillKicked" );
+ attacker thread TeamKillKick();
+ }
+
+ attacker thread reduceTeamKillsOverTime();
+ }
+
+ //Play teamkill battlechatter
+ if( isPlayer( attacker ) )
+ thread battlechatter::on_player_suicide_or_team_kill( attacker, "teamkill" );
+ }
+}
+
+function wait_and_suicide() // self == player
+{
+ self endon( "disconnect" );
+ self util::freeze_player_controls( true );
+
+ wait .25;
+
+ self suicide();
+}
+
+function PlayerKilled_AwardAssists( eInflictor, attacker, weapon, lpattackteam )
+{
+ pixbeginevent( "PlayerKilled assists" );
+
+ if ( isdefined( self.attackers ) )
+ {
+ for ( j = 0; j < self.attackers.size; j++ )
+ {
+ player = self.attackers[j];
+
+ if ( !isdefined( player ) )
+ continue;
+
+ if ( player == attacker )
+ continue;
+
+ if ( player.team != lpattackteam )
+ continue;
+
+ damage_done = self.attackerDamage[player.clientId].damage;
+ player thread globallogic_score::processAssist( self, damage_done, self.attackerDamage[player.clientId].weapon );
+ }
+ }
+
+ if ( level.teamBased )
+ {
+ self globallogic_score::processKillstreakAssists( attacker, eInflictor, weapon );
+ }
+
+ if ( isdefined( self.lastAttackedShieldPlayer ) && isdefined( self.lastAttackedShieldTime ) && self.lastAttackedShieldPlayer != attacker )
+ {
+ if ( gettime() - self.lastAttackedShieldTime < 4000 )
+ {
+ self.lastAttackedShieldPlayer thread globallogic_score::processShieldAssist( self );
+ }
+ }
+
+ pixendevent(); //"END: PlayerKilled assists"
+}
+
+function PlayerKilled_Kill( eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc )
+{
+ if( !isdefined( killstreaks::get_killstreak_for_weapon( weapon ) ) || ( isdefined( level.killstreaksGiveGameScore ) && level.killstreaksGiveGameScore ) )
+ globallogic_score::incTotalKills(attacker.team);
+
+ if( GetDvarInt( "teamOpsEnabled" ) == 1 )
+ {
+ if( isdefined( eInflictor ) && ( isdefined( eInflictor.teamops ) && eInflictor.teamops ) )
+ {
+ if( !isdefined( killstreaks::get_killstreak_for_weapon( weapon ) ) || ( isdefined( level.killstreaksGiveGameScore ) && level.killstreaksGiveGameScore ) )
+ globallogic_score::giveTeamScore( "kill", attacker.team, undefined, self );
+ return;
+ }
+ }
+
+ attacker thread globallogic_score::giveKillStats( sMeansOfDeath, weapon, self );
+
+
+ if ( isAlive( attacker ) )
+ {
+ pixbeginevent("killstreak");
+
+ if ( !isdefined( eInflictor ) || !isdefined( eInflictor.requiredDeathCount ) || attacker.deathCount == eInflictor.requiredDeathCount )
+ {
+ shouldGiveKillstreak = killstreaks::should_give_killstreak( weapon );
+ //attacker thread _properks::earnedAKill();
+
+ if ( shouldGiveKillstreak )
+ {
+ attacker killstreaks::add_to_killstreak_count( weapon );
+ }
+
+ attacker.pers["cur_total_kill_streak"]++;
+ attacker setplayercurrentstreak( attacker.pers["cur_total_kill_streak"] );
+
+ //Kills gotten through killstreak weapons should not the players killstreak
+ if ( isdefined( level.killstreaks ) && shouldGiveKillstreak )
+ {
+ attacker.pers["cur_kill_streak"]++;
+
+ if ( attacker.pers["cur_kill_streak"] >= 2 )
+ {
+ if ( attacker.pers["cur_kill_streak"] == 10 )
+ {
+ attacker challenges::killstreakTen();
+ }
+ if ( attacker.pers["cur_kill_streak"] <= 30 )
+ {
+ scoreevents::processScoreEvent( "killstreak_" + attacker.pers["cur_kill_streak"], attacker, self, weapon );
+
+ if ( attacker.pers["cur_kill_streak"] == 30 )
+ {
+ attacker challenges::killstreak_30_noscorestreaks();
+ }
+ }
+ else
+ {
+ scoreevents::processScoreEvent( "killstreak_more_than_30", attacker, self, weapon );
+ }
+ }
+
+ if ( !isdefined( level.usingMomentum ) || !level.usingMomentum )
+ {
+ if( GetDvarInt( "teamOpsEnabled" ) == 0 )
+ attacker thread killstreaks::give_for_streak();
+ }
+ }
+ }
+
+ pixendevent(); // "killstreak"
+ }
+
+ if ( attacker.pers["cur_kill_streak"] > attacker.kill_streak )
+ {
+ if ( level.rankedMatch && !level.disableStatTracking )
+ {
+ attacker setDStat( "HighestStats", "kill_streak", attacker.pers["totalKillstreakCount"] );
+ }
+ attacker.kill_streak = attacker.pers["cur_kill_streak"];
+ }
+
+
+ if ( attacker.pers["cur_kill_streak"] > attacker.gametype_kill_streak )
+ {
+ attacker persistence::stat_set_with_gametype( "kill_streak", attacker.pers["cur_kill_streak"] );
+ attacker.gametype_kill_streak = attacker.pers["cur_kill_streak"];
+ }
+
+ killstreak = killstreaks::get_killstreak_for_weapon( weapon );
+
+ if ( isdefined( killstreak ) )
+ {
+ if ( scoreevents::isRegisteredEvent( killstreak ) )
+ {
+ scoreevents::processScoreEvent( killstreak, attacker, self, weapon );
+ }
+
+ if( isdefined( eInflictor ) && ( killstreak == "dart" || killstreak == "inventory_dart" ) )
+ {
+ eInflictor notify( "veh_collision" );
+ }
+ }
+ else
+ {
+ scoreevents::processScoreEvent( "kill", attacker, self, weapon );
+
+ // if ( sMeansOfDeath == "MOD_HEAD_SHOT" || ( sMeansOfDeath == "MOD_IMPACT" && sHitLoc == "head" ) ) // TODO: add back when applicable LOOT6 weapon is ready
+ if ( sMeansOfDeath == "MOD_HEAD_SHOT" )
+ {
+ scoreevents::processScoreEvent( "headshot", attacker, self, weapon );
+ attacker util::player_contract_event( "headshot" );
+ }
+ else if ( weapon_utils::isMeleeMOD( sMeansOfDeath ) )
+ {
+ scoreevents::processScoreEvent( "melee_kill", attacker, self, weapon );
+ }
+ }
+
+ attacker thread globallogic_score::trackAttackerKill( self.name, self.pers["rank"], self.pers["rankxp"], self.pers["prestige"], self getXuid(), weapon );
+
+ attackerName = attacker.name;
+ self thread globallogic_score::trackAttackeeDeath( attackerName, attacker.pers["rank"], attacker.pers["rankxp"], attacker.pers["prestige"], attacker getXuid() );
+ self thread medals::setLastKilledBy( attacker );
+
+ attacker thread globallogic_score::incKillstreakTracker( weapon );
+
+ // to prevent spectator gain score for team-spectator after throwing a granade and killing someone before he switched
+ if ( level.teamBased && attacker.team != "spectator")
+ {
+ if( !isdefined( killstreak ) || ( isdefined( level.killstreaksGiveGameScore ) && level.killstreaksGiveGameScore ) )
+ globallogic_score::giveTeamScore( "kill", attacker.team, attacker, self );
+ }
+
+ scoreSub = level.deathPointLoss;
+ if ( scoreSub != 0 )
+ {
+ globallogic_score::_setPlayerScore( self, globallogic_score::_getPlayerScore( self ) - scoreSub );
+ }
+
+ level thread playKillBattleChatter( attacker, weapon, self, eInflictor );
+}
+
+function should_allow_postgame_death( sMeansOfDeath )
+{
+ if ( sMeansOfDeath == "MOD_POST_GAME" )
+ return true;
+
+ return false;
+}
+
+function do_post_game_death(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration)
+{
+ if ( !should_allow_postgame_death( sMeansOfDeath ) )
+ return;
+
+ self weapons::detach_carry_object_model();
+
+ self.sessionstate = "dead";
+ self.spectatorclient = -1;
+ self.killcamentity = -1;
+ self.archivetime = 0;
+ self.psoffsettime = 0;
+
+ clone_weapon = weapon;
+
+ // we do not want the weapon death fx to play if this is not a melee weapon and its a melee attack
+ // ideally the mod be passed to the client side and let it decide but this is post ship t7 and this is safest
+ if ( weapon_utils::isMeleeMOD(sMeansOfDeath) && clone_weapon.type != "melee" )
+ {
+ clone_weapon = level.weaponNone;
+ }
+ body = self clonePlayer( deathAnimDuration, clone_weapon, attacker );
+
+ if ( isdefined( body ) )
+ {
+ self createDeadBody( attacker, iDamage, sMeansOfDeath, weapon, sHitLoc, vDir, (0,0,0), deathAnimDuration, eInflictor, body );
+ }
+}
+
+function Callback_PlayerKilled(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, enteredResurrect = false)
+{
+ profilelog_begintiming( 7, "ship" );
+
+ self endon( "spawned" );
+
+
+ if ( game["state"] == "postgame" )
+ {
+ do_post_game_death(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration);
+ return;
+ }
+
+ if ( self.sessionteam == "spectator" )
+ return;
+
+ self notify( "killed_player" );
+ self callback::callback( #"on_player_killed" );
+
+ self needsRevive( false );
+
+ if ( isdefined( self.burning ) && self.burning == true )
+ {
+ self setburn( 0 );
+ }
+
+ self.suicide = false;
+ self.teamKilled = false;
+
+ if ( isdefined( level.takeLivesOnDeath ) && ( level.takeLivesOnDeath == true ) )
+ {
+ if ( self.pers["lives"] )
+ {
+ self.pers["lives"]--;
+ if ( self.pers["lives"] == 0 )
+ {
+ level notify( "player_eliminated" );
+ self notify( "player_eliminated" );
+ }
+ }
+ if ( game[self.team + "_lives"] )
+ {
+ game[self.team + "_lives"]--;
+ if ( game[self.team + "_lives"] == 0 )
+ {
+ level notify( "player_eliminated" );
+ self notify( "player_eliminated" );
+ }
+ }
+ }
+
+ self thread globallogic_audio::flush_leader_dialog_key_on_player( "equipmentDestroyed" );
+ //self thread globallogic_audio::flush_leader_dialog_key_on_player( "equipmentHacked" );
+
+ weapon = updateWeapon( eInflictor, weapon );
+
+ pixbeginevent( "PlayerKilled pre constants" );
+
+ wasInLastStand = false;
+ bledOut = false;
+ deathTimeOffset = 0;
+ lastWeaponBeforeDroppingIntoLastStand = undefined;
+ attackerStance = undefined;
+ self.lastStandThisLife = undefined;
+ self.vAttackerOrigin = undefined;
+
+ // need to get this before changing the sessionstate
+ weapon_at_time_of_death = self GetCurrentWeapon();
+
+ if ( isdefined( self.useLastStandParams ) && enteredResurrect == false )
+ {
+ self.useLastStandParams = undefined;
+
+ assert( isdefined( self.lastStandParams ) );
+ if ( !level.teamBased || ( !isdefined( attacker ) || !isplayer( attacker ) || attacker.team != self.team || attacker == self ) )
+ {
+ eInflictor = self.lastStandParams.eInflictor;
+ attacker = self.lastStandParams.attacker;
+ attackerStance = self.lastStandParams.attackerStance;
+ iDamage = self.lastStandParams.iDamage;
+ sMeansOfDeath = self.lastStandParams.sMeansOfDeath;
+ weapon = self.lastStandParams.sWeapon;
+ vDir = self.lastStandParams.vDir;
+ sHitLoc = self.lastStandParams.sHitLoc;
+ self.vAttackerOrigin = self.lastStandParams.vAttackerOrigin;
+ self.killcam_entity_info_cached = self.lastStandParams.killcam_entity_info_cached;
+ deathTimeOffset = (gettime() - self.lastStandParams.lastStandStartTime) / 1000;
+ bledOut = true;
+ if ( isdefined( self.previousPrimary ) )
+ {
+ wasInLastStand = true;
+ lastWeaponBeforeDroppingIntoLastStand = self.previousPrimary;
+ }
+ }
+ self.lastStandParams = undefined;
+ }
+
+ self StopSounds();
+
+ bestPlayer = undefined;
+ bestPlayerMeansOfDeath = undefined;
+ obituaryMeansOfDeath = undefined;
+ bestPlayerWeapon = undefined;
+ obituaryWeapon = weapon;
+ assistedSuicide = false;
+
+ if ( isdefined( level.gameModeAssistedSuicide ) )
+ {
+ result = self [[ level.gameModeAssistedSuicide ]]( attacker, sMeansOfDeath, weapon );
+ if ( isdefined( result ) )
+ {
+ bestPlayer = result["bestPlayer"];
+ bestPlayerMeansOfDeath = result["bestPlayerMeansOfDeath"];
+ bestPlayerWeapon = result["bestPlayerWeapon"];
+ }
+ }
+
+ if ( (!isdefined( attacker ) || attacker.classname == "trigger_hurt" || attacker.classname == "worldspawn" || ( isdefined( attacker.isMagicBullet ) && attacker.isMagicBullet == true ) || attacker == self ) && isdefined( self.attackers ) && !self IsPlayerUnderwater() )
+ {
+ if ( !isdefined(bestPlayer) )
+ {
+ for ( i = 0; i < self.attackers.size; i++ )
+ {
+ player = self.attackers[i];
+ if ( !isdefined( player ) )
+ continue;
+
+ if (!isdefined( self.attackerDamage[ player.clientId ] ) || ! isdefined( self.attackerDamage[ player.clientId ].damage ) )
+ continue;
+
+ if ( player == self || (level.teamBased && player.team == self.team ) )
+ continue;
+
+ if ( self.attackerDamage[ player.clientId ].lasttimedamaged + 2500 < getTime() )
+ continue;
+
+ if ( !allowedAssistWeapon( self.attackerDamage[ player.clientId ].weapon ) )
+ continue;
+
+ if ( self.attackerDamage[ player.clientId ].damage > 1 && ! isdefined( bestPlayer ) )
+ {
+ bestPlayer = player;
+ bestPlayerMeansOfDeath = self.attackerDamage[ player.clientId ].meansOfDeath;
+ bestPlayerWeapon = self.attackerDamage[ player.clientId ].weapon;
+ }
+ else if ( isdefined( bestPlayer ) && self.attackerDamage[ player.clientId ].damage > self.attackerDamage[ bestPlayer.clientId ].damage )
+ {
+ bestPlayer = player;
+ bestPlayerMeansOfDeath = self.attackerDamage[ player.clientId ].meansOfDeath;
+ bestPlayerWeapon = self.attackerDamage[ player.clientId ].weapon;
+ }
+ }
+ }
+ if ( isdefined ( bestPlayer ) )
+ {
+ scoreevents::processScoreEvent( "assisted_suicide", bestPlayer, self, weapon );
+ self RecordKillModifier("assistedsuicide");
+ assistedSuicide = true;
+ }
+ }
+
+ if ( isdefined ( bestPlayer ) )
+ {
+ attacker = bestPlayer;
+ obituaryMeansOfDeath = bestPlayerMeansOfDeath;
+ obituaryWeapon = bestPlayerWeapon;
+ if ( isdefined( bestPlayerWeapon ) )
+ {
+ weapon = bestPlayerWeapon;
+ }
+ }
+
+ if ( isplayer( attacker ) && isdefined( attacker.damagedPlayers ) )
+ attacker.damagedPlayers[self.clientid] = undefined;
+
+ if ( enteredResurrect == false )
+ {
+ globallogic::DoWeaponSpecificKillEffects(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime);
+ }
+
+ self.deathTime = getTime();
+
+ if ( attacker != self && (!level.teamBased || attacker.team != self.team ))
+ {
+ assert( IsDefined( self.lastspawntime ) );
+ self.aliveTimes[self.aliveTimeCurrentIndex] = self.deathTime - self.lastspawntime;
+ self.aliveTimeCurrentIndex = (self.aliveTimeCurrentIndex + 1) % level.aliveTimeMaxCount;
+ }
+
+ attacker = updateAttacker( attacker, weapon );
+ eInflictor = updateInflictor( eInflictor );
+
+ sMeansOfDeath = self PlayerKilled_UpdateMeansOfDeath( attacker, eInflictor, weapon, sMeansOfDeath, sHitLoc );
+
+ if ( !isdefined( obituaryMeansOfDeath ) )
+ obituaryMeansOfDeath = sMeansOfDeath;
+
+ self.hasRiotShield = false;
+ self.hasRiotShieldEquipped = false;
+
+ self thread updateGlobalBotKilledCounter();
+
+ self PlayerKilled_WeaponStats( attacker, weapon, sMeansOfDeath, wasInLastStand, lastWeaponBeforeDroppingIntoLastStand, eInflictor );
+
+ if ( bledOut == false )
+ {
+ if( GetDvarInt( "teamOpsEnabled" ) == 1 && ( isdefined( eInflictor ) && ( isdefined( eInflictor.teamops ) && eInflictor.teamops ) ) )
+ {
+ self PlayerKilled_Obituary( eInflictor, eInflictor, obituaryWeapon, obituaryMeansOfDeath );
+ }
+ else
+ {
+ self PlayerKilled_Obituary( attacker, eInflictor, obituaryWeapon, obituaryMeansOfDeath );
+ }
+ }
+
+ if ( enteredResurrect == false )
+ {
+// spawnlogic::death_occured(self, attacker);
+
+ self.sessionstate = "dead";
+ self.statusicon = "hud_status_dead";
+ }
+
+ self.pers["weapon"] = undefined;
+
+ self.killedPlayersCurrent = [];
+
+ self.deathCount++;
+
+/#
+ println( "players("+self.clientId+") death count ++: " + self.deathCount );
+#/
+
+ if ( bledout == false )
+ {
+ self PlayerKilled_Killstreaks( attacker, weapon );
+ }
+
+ lpselfnum = self getEntityNumber();
+ lpselfname = self.name;
+ lpattackGuid = "";
+ lpattackname = "";
+ lpselfteam = self.team;
+ lpselfguid = self getXuid();
+
+ if (self util::is_bot())
+ {
+ lpselfGuid = "bot0";
+ }
+
+ lpattackteam = "";
+ lpattackorigin = ( 0, 0, 0 );
+
+ lpattacknum = -1;
+
+ //check if we should award assist points
+ awardAssists = false;
+ wasTeamKill = false;
+ wasSuicide = false;
+
+ pixendevent(); // "PlayerKilled pre constants" );
+
+ scoreevents::processScoreEvent( "death", self, self, weapon );
+ self.pers["resetMomentumOnSpawn"] = level.scoreResetOnDeath;
+
+
+ if( isPlayer( attacker ) )
+ {
+ lpattackGuid = attacker getXuid();
+
+ if (attacker util::is_bot())
+ {
+ lpattackGuid = "bot0";
+ }
+
+ lpattackname = attacker.name;
+ lpattackteam = attacker.team;
+ lpattackorigin = attacker.origin;
+
+ if ( attacker == self || assistedSuicide == true ) // killed himself
+ {
+ doKillcam = false;
+ wasSuicide = true;
+
+ awardAssists = self PlayerKilled_Suicide( eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc );
+ if( assistedSuicide == true )
+ attacker thread globallogic_score::giveKillStats( sMeansOfDeath, weapon, self );
+ }
+ else
+ {
+ pixbeginevent( "PlayerKilled attacker" );
+
+ lpattacknum = attacker getEntityNumber();
+
+ doKillcam = true;
+
+ if ( level.teamBased && self.team == attacker.team && sMeansOfDeath == "MOD_GRENADE" && level.friendlyfire == 0 )
+ {
+ }
+ else if ( level.teamBased && self.team == attacker.team ) // killed by a friendly
+ {
+ wasTeamKill = true;
+
+ self PlayerKilled_TeamKill( eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc );
+ }
+ else
+ {
+ if ( bledOut == false )
+ {
+ self PlayerKilled_Kill( eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc );
+
+ if ( level.teamBased )
+ {
+ //check if assist points should be awarded
+ awardAssists = true;
+ }
+ }
+ }
+
+ pixendevent(); //"PlayerKilled attacker"
+ }
+ }
+ else if ( isdefined( attacker ) && ( attacker.classname == "trigger_hurt" || attacker.classname == "worldspawn" ) )
+ {
+ doKillcam = false;
+
+ lpattacknum = -1;
+ lpattackguid = "";
+ lpattackname = "";
+ lpattackteam = "world";
+
+ scoreevents::processScoreEvent( "suicide", self );
+ self globallogic_score::incPersStat( "suicides", 1 );
+ self.suicides = self globallogic_score::getPersStat( "suicides" );
+
+ self.suicide = true;
+
+ //Check for player death related battlechatter
+ thread battlechatter::on_player_suicide_or_team_kill( self, "suicide" ); //Play suicide battlechatter
+
+ //check if assist points should be awarded
+ awardAssists = true;
+
+ if ( level.maxSuicidesBeforeKick > 0 && level.maxSuicidesBeforeKick <= self.suicides )
+ {
+ // should change "teamKillKicked" to just kicked for the next game
+ self notify( "teamKillKicked" );
+ self SuicideKick();
+ }
+ }
+ else
+ {
+ doKillcam = false;
+
+ lpattacknum = -1;
+ lpattackguid = "";
+ lpattackname = "";
+ lpattackteam = "world";
+
+ wasSuicide = true;
+
+ // we may have a killcam on an world entity like the rocket in cosmodrome
+ if ( isdefined( eInflictor ) && isdefined( eInflictor.killCamEnt ) )
+ {
+ doKillcam = true;
+ lpattacknum = self getEntityNumber();
+ wasSuicide = false;
+ }
+
+ // even if the attacker isn't a player, it might be on a team
+ if ( isdefined( attacker ) && isdefined( attacker.team ) && ( isdefined( level.teams[attacker.team] ) ) )
+ {
+ if ( attacker.team != self.team )
+ {
+ if ( level.teamBased )
+ {
+ if( !isdefined( killstreaks::get_killstreak_for_weapon( weapon ) ) || ( isdefined( level.killstreaksGiveGameScore ) && level.killstreaksGiveGameScore ) )
+ globallogic_score::giveTeamScore( "kill", attacker.team, attacker, self );
+ }
+
+ wasSuicide = false;
+ }
+ }
+
+ //check if assist points should be awarded
+ awardAssists = true;
+ }
+
+ if ( !level.inGracePeriod && enteredResurrect == false )
+ {
+ if ( sMeansOfDeath != "MOD_GRENADE" && sMeansOfDeath != "MOD_GRENADE_SPLASH" && sMeansOfDeath != "MOD_EXPLOSIVE" && sMeansOfDeath != "MOD_EXPLOSIVE_SPLASH" && sMeansOfDeath != "MOD_PROJECTILE_SPLASH" && sMeansOfDeath != "MOD_FALLING" )
+ {
+ if ( weapon.name != "incendiary_fire" )
+ {
+ self weapons::drop_scavenger_for_death( attacker );
+ }
+ }
+
+ if ( should_drop_weapon_on_death( wasTeamkill, wasSuicide, weapon_at_time_of_death, sMeansOfDeath ) )
+ {
+ self weapons::drop_for_death( attacker, weapon, sMeansOfDeath );
+ }
+ }
+
+ //award assist points if needed
+ if( awardAssists )
+ {
+ self PlayerKilled_AwardAssists( eInflictor, attacker, weapon, lpattackteam );
+ }
+
+ pixbeginevent( "PlayerKilled post constants" );
+
+ self.lastAttacker = attacker;
+ self.lastDeathPos = self.origin;
+
+ if ( isdefined( attacker ) && isPlayer( attacker ) && attacker != self && (!level.teambased || attacker.team != self.team) )
+ {
+ attacker notify( "killed_enemy_player", self, weapon );
+ if( isDefined( attacker.gadget_thief_kill_callback ) )
+ {
+ attacker [[attacker.gadget_thief_kill_callback]]( self, weapon );
+ }
+ self thread challenges::playerKilled(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, sHitLoc, attackerStance, bledOut );
+ }
+ else
+ {
+
+ self notify("playerKilledChallengesProcessed");
+ }
+
+ if ( isdefined ( self.attackers ))
+ self.attackers = [];
+
+
+ // minimize repeat checks of things like isPlayer
+ killerHeroPowerActive = 0;
+ killer = undefined;
+ killerLoadoutIndex = -1;
+ killerWasADS = false;
+ killerInVictimFOV = false;
+ victimInKillerFOV = false;
+
+ if( isPlayer( attacker ) )
+ {
+ attacker.lastKillTime = gettime();
+
+ killer = attacker;
+ if ( isdefined( attacker.class_num ) )
+ killerLoadoutIndex = attacker.class_num;
+ killerWasADS = attacker playerADS() >= 1;
+
+ killerInVictimFOV = util::within_fov( self.origin, self.angles, attacker.origin, self.fovcosine );
+ victimInKillerFOV = util::within_fov( attacker.origin, attacker.angles, self.origin, attacker.fovcosine );
+
+ if ( attacker ability_player::is_using_any_gadget() )
+ killerHeroPowerActive = 1;
+
+ if( killstreaks::is_killstreak_weapon( weapon ) )
+ {
+ killstreak = killstreaks::get_killstreak_for_weapon_for_stats( weapon );
+
+ bbPrint( "mpattacks", "gametime %d attackerspawnid %d attackerweapon %s attackerx %d attackery %d attackerz %d victimspawnid %d victimx %d victimy %d victimz %d damage %d damagetype %s damagelocation %s death %d isusingheropower %d killstreak %s",
+ gettime(), getplayerspawnid( attacker ), weapon.name, lpattackorigin, getplayerspawnid( self ), self.origin, iDamage, sMeansOfDeath, sHitLoc, 1, killerHeroPowerActive, killstreak );
+ }
+ else
+ {
+ bbPrint( "mpattacks", "gametime %d attackerspawnid %d attackerweapon %s attackerx %d attackery %d attackerz %d victimspawnid %d victimx %d victimy %d victimz %d damage %d damagetype %s damagelocation %s death %d isusingheropower %d",
+ gettime(), getplayerspawnid( attacker ), weapon.name, lpattackorigin, getplayerspawnid( self ), self.origin, iDamage, sMeansOfDeath, sHitLoc, 1, killerHeroPowerActive );
+ }
+
+ attacker thread weapons::bestweapon_kill( weapon );
+ }
+ else
+ {
+ bbPrint( "mpattacks", "gametime %d attackerweapon %s victimspawnid %d victimx %d victimy %d victimz %d damage %d damagetype %s damagelocation %s death %d isusingheropower %d",
+ gettime(), weapon.name, getplayerspawnid( self ), self.origin, iDamage, sMeansOfDeath, sHitLoc, 1, 0 );
+ }
+
+ victimWeapon = undefined;
+ victimWeaponPickedUp = false;
+ victimKillstreakWeaponIndex = 0;
+ if( isdefined( weapon_at_time_of_death ) )
+ {
+ victimWeapon = weapon_at_time_of_death;
+ if( isdefined( self.pickedUpWeapons ) && isdefined( self.pickedUpWeapons[victimWeapon] ) )
+ {
+ victimWeaponPickedUp = true;
+ }
+
+ if( killstreaks::is_killstreak_weapon( victimWeapon ) )
+ {
+ killstreak = killstreaks::get_killstreak_for_weapon_for_stats( victimWeapon );
+ if( isdefined( level.killstreaks[killstreak].menuname ) )
+ {
+ victimKillstreakWeaponIndex = level.killstreakindices[level.killstreaks[killstreak].menuname];
+ }
+ }
+ }
+ victimWasADS = self playerADS() >= 1;
+ victimHeroPowerActive = self ability_player::is_using_any_gadget();
+
+ killerWeaponPickedUp = false;
+ killerKillstreakWeaponIndex = 0;
+ killerKillstreakEventIndex = 125; // 125 = not a killstreak
+ if( isdefined( weapon ) )
+ {
+ if( isdefined( killer ) && isdefined( killer.pickedUpWeapons ) && isdefined( killer.pickedUpWeapons[weapon] ) )
+ {
+ killerWeaponPickedUp = true;
+ }
+
+ if( killstreaks::is_killstreak_weapon( weapon ) )
+ {
+ killstreak = killstreaks::get_killstreak_for_weapon_for_stats( weapon );
+ if( isdefined( level.killstreaks[killstreak].menuname ) )
+ {
+ killerKillstreakWeaponIndex = level.killstreakindices[level.killstreaks[killstreak].menuname];
+
+ if( isdefined( killer.killstreakEvents ) && isdefined( killer.killstreakEvents[ killerkillstreakweaponindex ] ) )
+ {
+ killerKillstreakEventIndex = killer.killstreakEvents[killerkillstreakweaponindex];
+ }
+ else
+ {
+ killerkillstreakeventindex = 126; // 126 = was a killstreak but no event index
+ }
+ }
+ }
+ }
+
+ //
+ // Log additional stuff in match record on death.
+ // Mostly values we can't easily access in the existing MatchRecordDeath function in code.
+ //
+
+ matchRecordLogAdditionalDeathInfo( self, killer, victimWeapon, weapon,
+ self.class_num, victimWeaponPickedUp, victimWasADS,
+ killerLoadoutIndex, killerWeaponPickedUp, killerWasADS,
+ victimHeroPowerActive, killerHeroPowerActive,
+ victimInKillerFOV, killerInVictimFOV,
+ killerKillstreakWeaponIndex, victimKillstreakWeaponIndex,
+ killerkillstreakeventindex);
+
+
+ self record_special_move_data_for_life( killer );
+
+ self.pickedUpWeapons = []; // reset on each death
+
+
+ logPrint( "K;" + lpselfguid + ";" + lpselfnum + ";" + lpselfteam + ";" + lpselfname + ";" + lpattackguid + ";" + lpattacknum + ";" + lpattackteam + ";" + lpattackname + ";" + weapon.name + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n" );
+ attackerString = "none";
+ if ( isPlayer( attacker ) ) // attacker can be the worldspawn if it's not a player
+ attackerString = attacker getXuid() + "(" + lpattackname + ")";
+ /#print( "d " + sMeansOfDeath + "(" + weapon.name + ") a:" + attackerString + " d:" + iDamage + " l:" + sHitLoc + " @ " + int( self.origin[0] ) + " " + int( self.origin[1] ) + " " + int( self.origin[2] ) );#/
+
+ // for cod caster update the top scorers
+ if ( !level.rankedMatch && !level.teambased )
+ {
+ level thread update_ffa_top_scorers();
+ }
+
+ level thread globallogic::updateTeamStatus();
+ level thread globallogic::updateAliveTimes(self.team);
+
+ if ( isdefined( self.killcam_entity_info_cached ) )
+ {
+ killcam_entity_info = self.killcam_entity_info_cached;
+ self.killcam_entity_info_cached = undefined;
+ }
+ else
+ {
+ killcam_entity_info = killcam::get_killcam_entity_info( attacker, eInflictor, weapon );
+ }
+
+
+ // no killcam if the player is still involved with a killstreak
+ if ( isdefined( self.killstreak_delay_killcam ) )
+ doKillcam = false;
+
+ self weapons::detach_carry_object_model();
+
+ pixendevent(); //"END: PlayerKilled post constants"
+
+ pixbeginevent( "PlayerKilled body and gibbing" );
+ vAttackerOrigin = undefined;
+ if ( isdefined( attacker ) )
+ {
+ vAttackerOrigin = attacker.origin;
+ }
+
+ if ( enteredResurrect == false )
+ {
+ clone_weapon = weapon;
+
+ // we do not want the weapon death fx to play if this is not a melee weapon and its a melee attack
+ // ideally the mod be passed to the client side and let it decide but this is post ship t7 and this is safest
+ if ( weapon_utils::isMeleeMOD(sMeansOfDeath) && clone_weapon.type != "melee" )
+ {
+ clone_weapon = level.weaponNone;
+ }
+ body = self clonePlayer( deathAnimDuration, clone_weapon, attacker );
+
+ if ( isdefined( body ) )
+ {
+ self createDeadBody( attacker, iDamage, sMeansOfDeath, weapon, sHitLoc, vDir, vAttackerOrigin, deathAnimDuration, eInflictor, body );
+
+ if ( isdefined( level.customPlayDeathSound ) )
+ self [[ level.customPlayDeathSound ]]( body, attacker, weapon, sMeansOfDeath );
+ else
+ self battlechatter::play_death_vox( body, attacker, weapon, sMeansOfDeath );
+
+ globallogic::DoWeaponSpecificCorpseEffects(body, eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime);
+ }
+ }
+
+
+ pixendevent();// "END: PlayerKilled body and gibbing"
+
+ if ( enteredResurrect )
+ {
+ thread globallogic_spawn::spawnQueuedClient( self.team, attacker );
+ }
+
+ self.switching_teams = undefined;
+ self.joining_team = undefined;
+ self.leaving_team = undefined;
+
+ if ( bledOut == false ) // handled in PlayerLastStand
+ {
+ self thread [[level.onPlayerKilled]](eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration);
+ }
+
+ if ( isdefined( level.teamopsOnPlayerKilled ) )
+ {
+ self [[level.teamopsOnPlayerKilled]]( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration);
+ }
+
+ for ( iCB = 0; iCB < level.onPlayerKilledExtraUnthreadedCBs.size; iCB++ )
+ {
+ self [[ level.onPlayerKilledExtraUnthreadedCBs[ iCB ] ]](
+ eInflictor,
+ attacker,
+ iDamage,
+ sMeansOfDeath,
+ weapon,
+ vDir,
+ sHitLoc,
+ psOffsetTime,
+ deathAnimDuration );
+ }
+
+ self.wantSafeSpawn = false;
+ perks = [];
+ // perks = globallogic::getPerks( attacker );
+ killstreaks = globallogic::getKillstreaks( attacker );
+
+ if( !isdefined( self.killstreak_delay_killcam ) )
+ {
+ // start the prediction now so the client gets updates while waiting to spawn
+ self thread [[level.spawnPlayerPrediction]]();
+ }
+
+ profilelog_endtiming( 7, "gs=" + game["state"] + " zom=" + SessionModeIsZombiesGame() );
+
+ // record the kill cam values for the final kill cam
+ if ( wasTeamKill == false && assistedSuicide == false && sMeansOfDeath != "MOD_SUICIDE" && !( !isdefined( attacker ) || attacker.classname == "trigger_hurt" || attacker.classname == "worldspawn" || attacker == self || isdefined ( attacker.disableFinalKillcam ) ) )
+ {
+ level thread killcam::record_settings( lpattacknum, self getEntityNumber(), weapon, sMeansOfDeath, self.deathTime, deathTimeOffset, psOffsetTime, killcam_entity_info, perks, killstreaks, attacker );
+ }
+ if ( enteredResurrect )
+ {
+ return;
+ }
+
+ // let the player watch themselves die
+ wait ( 0.25 );
+
+ //check if killed by a sniper
+ weaponClass = util::getWeaponClass( weapon );
+ if( isdefined( weaponClass ) && weaponClass == "weapon_sniper" )
+ {
+ self thread battlechatter::killed_by_sniper( attacker );
+ }
+ else
+ {
+ self thread battlechatter::player_killed( attacker, killstreak );
+ }
+ self.cancelKillcam = false;
+ self thread killcam::cancel_on_use();
+
+ // initial death cam
+ self playerkilled_watch_death(weapon, sMeansOfDeath, deathAnimDuration);
+
+ // killcam
+/#
+ if ( GetDvarint( "scr_forcekillcam" ) != 0 )
+ {
+ doKillcam = true;
+
+ if ( lpattacknum < 0 )
+ lpattacknum = self getEntityNumber();
+ }
+#/
+
+ if ( game["state"] != "playing" )
+ {
+ return;
+ }
+
+ self.respawnTimerStartTime = gettime();
+ keep_deathcam = false;
+ if ( isdefined( self.overridePlayerDeadStatus ) )
+ {
+ keep_deathcam = self [[ self.overridePlayerDeadStatus ]]();
+ }
+
+ if ( !self.cancelKillcam && doKillcam && level.killcam && ( wasTeamKill == false ) )
+ {
+ livesLeft = !(level.numLives && !self.pers["lives"]) && !(level.numTeamLives && !game[self.team+"_lives"]);
+ timeUntilSpawn = globallogic_spawn::TimeUntilSpawn( true );
+ willRespawnImmediately = livesLeft && (timeUntilSpawn <= 0) && !level.playerQueuedRespawn;
+
+ self killcam::killcam( lpattacknum, self getEntityNumber(), killcam_entity_info, weapon, sMeansOfDeath, self.deathTime, deathTimeOffset, psOffsetTime, willRespawnImmediately, globallogic_utils::timeUntilRoundEnd(), perks, killstreaks, attacker, keep_deathcam );
+ }
+ else if( self.cancelKillcam )
+ {
+ // copy of code from wait_skip_killcam_button
+ // because fast button mashers (not hard to do) will "skip" the killcam
+ // before it even starts
+ if( isdefined( self.killcamsSkipped) )
+ {
+ self.killcamsSkipped++;
+ }
+ else
+ {
+ self.killcamsSkipped = 1;
+ }
+ }
+
+ // secondary deathcam for resurrection
+
+ secondary_deathcam = 0.0;
+
+ timeUntilSpawn = globallogic_spawn::TimeUntilSpawn( true );
+ shouldDoSecondDeathCam = timeUntilSpawn > 0;
+
+ if ( shouldDoSecondDeathCam && IsDefined(self.secondaryDeathCamTime) )
+ {
+ secondary_deathcam = self [[self.secondaryDeathCamTime]]();
+ }
+
+ if ( secondary_deathcam > 0.0 && !self.cancelKillcam )
+ {
+ self.spectatorclient = -1;
+ self.killcamentity = -1;
+ self.archivetime = 0;
+ self.psoffsettime = 0;
+ self.spectatekillcam = false;
+ globallogic_utils::waitForTimeOrNotify( secondary_deathcam, "end_death_delay" );
+ self notify ( "death_delay_finished" );
+ }
+
+ // secondary deathcam is complete
+
+ if ( !self.cancelKillcam && doKillcam && level.killcam && keep_deathcam )
+ {
+ self.sessionstate = "dead";
+ self.spectatorclient = -1;
+ self.killcamentity = -1;
+ self.archivetime = 0;
+ self.psoffsettime = 0;
+ self.spectatekillcam = false;
+ }
+
+ if ( game["state"] != "playing" )
+ {
+ self.sessionstate = "dead";
+ self.spectatorclient = -1;
+ self.killcamtargetentity = -1;
+ self.killcamentity = -1;
+ self.archivetime = 0;
+ self.psoffsettime = 0;
+ self.spectatekillcam = false;
+ return;
+ }
+
+ WaitTillKillStreakDone();
+ useRespawnTime = true;
+ if( isDefined( level.hostMigrationTimer ) )
+ {
+ useRespawnTime = false;
+ }
+ hostmigration::waittillHostMigrationCountDown();
+ //if ( isDefined( level.hostMigrationTimer ) )
+ //return;
+
+ // class may be undefined if we have changed teams
+ if ( globallogic_utils::isValidClass( self.curClass ) )
+ {
+ timePassed = undefined;
+
+ if ( isdefined( self.respawnTimerStartTime ) && useRespawnTime )
+ {
+ timePassed = (gettime() - self.respawnTimerStartTime) / 1000;
+ }
+
+ self thread [[level.spawnClient]]( timePassed );
+ self.respawnTimerStartTime = undefined;
+ }
+}
+
+function update_ffa_top_scorers()
+{
+ waittillframeend;
+
+ if ( !level.players.size || level.gameEnded )
+ return;
+
+ placement = [];
+ foreach ( player in level.players )
+ {
+ if ( player.team != "spectator" )
+ placement[placement.size] = player;
+ }
+
+ for ( i = 1; i < placement.size; i++ )
+ {
+ player = placement[i];
+ playerScore = player.pointstowin;
+ for ( j = i - 1; j >= 0 && (playerScore > placement[j].pointstowin || (playerScore == placement[j].pointstowin && player.deaths < placement[j].deaths) || (playerScore == placement[j].pointstowin && player.deaths == placement[j].deaths && player.lastKillTime > placement[j].lastKillTime)); j-- )
+ placement[j + 1] = placement[j];
+ placement[j + 1] = player;
+ }
+
+ ClearTopScorers();
+ for ( i = 0; i < placement.size && i < 3; i++ )
+ {
+ SetTopScorer( i, placement[i], 0, 0, 0, 0, level.weaponNone );
+ }
+}
+
+function playerkilled_watch_death(weapon, sMeansOfDeath, deathAnimDuration)
+{
+ defaultPlayerDeathWatchTime = 1.75;
+ if ( sMeansOfDeath == "MOD_MELEE_ASSASSINATE" || 0 > weapon.deathCamTime )
+ {
+ defaultPlayerDeathWatchTime = (deathAnimDuration * 0.001) + 0.5;
+ }
+ else if ( 0 < weapon.deathCamTime )
+ {
+ defaultPlayerDeathWatchTime = weapon.deathCamTime;
+ }
+
+ if ( isdefined ( level.overridePlayerDeathWatchTimer ) )
+ {
+ defaultPlayerDeathWatchTime = [[level.overridePlayerDeathWatchTimer]]( defaultPlayerDeathWatchTime );
+ }
+
+ globallogic_utils::waitForTimeOrNotify( defaultPlayerDeathWatchTime, "end_death_delay" );
+
+ self notify ( "death_delay_finished" );
+}
+
+function should_drop_weapon_on_death( wasTeamKill, wasSuicide, current_weapon, sMeansOfDeath )
+{
+ // to avoid exploits dont allow weapon drops on suicide or teamkills.
+ if ( wasTeamKill )
+ return false;
+
+ if ( wasSuicide )
+ return false;
+
+ // assuming this means that they are in a death trigger out of bounds and falling
+ if ( sMeansOfDeath == "MOD_TRIGGER_HURT" && !self IsOnGround())
+ return false;
+
+ // dont drop any weapon if they were holding a hero weapon
+ if ( IsDefined(current_weapon) && current_weapon.isHeroWeapon )
+ return false;
+
+ return true;
+}
+
+function updateGlobalBotKilledCounter()
+{
+ if ( isdefined( self.pers["isBot"] ) )
+ {
+ level.globalLarrysKilled++;
+ }
+}
+
+
+function WaitTillKillStreakDone()
+{
+ if( isdefined( self.killstreak_delay_killcam ) )
+ {
+ while( isdefined( self.killstreak_delay_killcam ) )
+ {
+ wait( 0.1 );
+ }
+
+ //Plus a small amount so we can see our dead body
+ wait( 2.0 );
+
+ self killstreaks::reset_killstreak_delay_killcam();
+ }
+}
+
+function SuicideKick()
+{
+ self globallogic_score::incPersStat( "sessionbans", 1 );
+
+ self endon("disconnect");
+ waittillframeend;
+
+ globallogic::gameHistoryPlayerKicked();
+
+ ban( self getentitynumber() );
+ globallogic_audio::leader_dialog( "gamePlayerKicked" );
+}
+
+function TeamKillKick()
+{
+ self globallogic_score::incPersStat( "sessionbans", 1 );
+
+ self endon("disconnect");
+ waittillframeend;
+
+ //for test purposes lets lock them out of certain game type for 2mins
+
+ playlistbanquantum = tweakables::getTweakableValue( "team", "teamkillerplaylistbanquantum" );
+ playlistbanpenalty = tweakables::getTweakableValue( "team", "teamkillerplaylistbanpenalty" );
+ if ( playlistbanquantum > 0 && playlistbanpenalty > 0 )
+ {
+ timeplayedtotal = self GetDStat( "playerstatslist", "time_played_total", "StatValue" );
+ minutesplayed = timeplayedtotal / 60;
+
+ freebees = 2;
+
+ banallowance = int( floor(minutesplayed / playlistbanquantum) ) + freebees;
+
+ if ( self.sessionbans > banallowance )
+ {
+ self SetDStat( "playerstatslist", "gametypeban", "StatValue", timeplayedtotal + (playlistbanpenalty * 60) );
+ }
+ }
+
+ globallogic::gameHistoryPlayerKicked();
+
+ ban( self getentitynumber() );
+ globallogic_audio::leader_dialog( "gamePlayerKicked" );
+}
+
+function TeamKillDelay()
+{
+ teamkills = self.pers["teamkills_nostats"];
+ if ( level.minimumAllowedTeamKills < 0 || teamkills <= level.minimumAllowedTeamKills )
+ return 0;
+
+ exceeded = (teamkills - level.minimumAllowedTeamKills);
+ return level.teamKillSpawnDelay * exceeded;
+}
+
+
+function ShouldTeamKillKick(teamKillDelay)
+{
+ if ( teamKillDelay && ( level.minimumAllowedTeamKills >= 0 ) )
+ {
+ // if its more then 5 seconds into the match and we have a delay then just kick them
+ if ( globallogic_utils::getTimePassed() >= 5000 )
+ {
+ return true;
+ }
+
+ // if its under 5 seconds into the match only kick them if they have killed more then one players so far
+ if ( self.pers["teamkills_nostats"] > 1 )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+function reduceTeamKillsOverTime()
+{
+ timePerOneTeamkillReduction = 20.0;
+ reductionPerSecond = 1.0 / timePerOneTeamkillReduction;
+
+ while(1)
+ {
+ if ( isAlive( self ) )
+ {
+ self.pers["teamkills_nostats"] -= reductionPerSecond;
+ if ( self.pers["teamkills_nostats"] < level.minimumAllowedTeamKills )
+ {
+ self.pers["teamkills_nostats"] = level.minimumAllowedTeamKills;
+ break;
+ }
+ }
+ wait 1;
+ }
+}
+
+
+function IgnoreTeamKills( weapon, sMeansOfDeath, eInflictor )
+{
+ if ( weapon_utils::isMeleeMOD( sMeansOfDeath ) )
+ return false;
+
+ if ( weapon.ignoreTeamKills )
+ return true;
+
+ if ( isdefined( eInflictor ) && eInflictor.ignore_team_kills === true )
+ return true;
+
+ if( isDefined( eInflictor ) && isDefined( eInflictor.destroyedBy ) && isDefined( eInflictor.owner ) && eInflictor.destroyedBy != eInflictor.owner )
+ return true;
+
+ if ( isDefined( eInflictor ) && eInflictor.classname == "worldspawn" )
+ return true;
+
+ return false;
+}
+
+
+function Callback_PlayerLastStand( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
+{
+ laststand::PlayerLastStand( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration );
+}
+
+function damageShellshockAndRumble( eAttacker, eInflictor, weapon, sMeansOfDeath, iDamage )
+{
+ self thread weapons::on_damage( eAttacker, eInflictor, weapon, sMeansOfDeath, iDamage );
+
+ if ( !self util::isUsingRemote() )
+ {
+ self PlayRumbleOnEntity( "damage_heavy" );
+ }
+}
+
+
+function createDeadBody( attacker, iDamage, sMeansOfDeath, weapon, sHitLoc, vDir, vAttackerOrigin, deathAnimDuration, eInflictor, body )
+{
+ if ( sMeansOfDeath == "MOD_HIT_BY_OBJECT" && self GetStance() == "prone" )
+ {
+ self.body = body;
+ if ( !isdefined( self.switching_teams ) )
+ thread deathicons::add( body, self, self.team, 5.0 );
+
+ return;
+ }
+
+ ragdoll_now = false;
+ if( isdefined(self.usingvehicle) && self.usingvehicle && isdefined(self.vehicleposition) && self.vehicleposition == 1 )
+ {
+ ragdoll_now = true;
+ }
+
+ if ( isdefined( level.ragdoll_override ) && self [[level.ragdoll_override]]( iDamage, sMeansOfDeath, weapon, sHitLoc, vDir, vAttackerOrigin, deathAnimDuration, eInflictor, ragdoll_now, body ) )
+ {
+ return;
+ }
+
+ if ( ( ragdoll_now ) || self isOnLadder() || self isMantling() || sMeansOfDeath == "MOD_CRUSH" || sMeansOfDeath == "MOD_HIT_BY_OBJECT" )
+ body startRagDoll();
+
+ if ( !self IsOnGround() && sMeansOfDeath != "MOD_FALLING" )
+ {
+ if ( GetDvarint( "scr_disable_air_death_ragdoll" ) == 0 )
+ {
+ body startRagDoll();
+ }
+ }
+
+ if( sMeansOfDeath == "MOD_MELEE_ASSASSINATE" && !attacker isOnGround() )
+ {
+ body start_death_from_above_ragdoll( vDir );
+ }
+
+ if ( self is_explosive_ragdoll( weapon, eInflictor ) )
+ {
+ body start_explosive_ragdoll( vDir, weapon );
+ }
+
+ thread delayStartRagdoll( body, sHitLoc, vDir, weapon, eInflictor, sMeansOfDeath );
+
+ if ( sMeansOfDeath == "MOD_CRUSH" )
+ {
+ body globallogic_vehicle::vehicleCrush();
+ }
+
+ self.body = body;
+ if ( !isdefined( self.switching_teams ) )
+ thread deathicons::add( body, self, self.team, 5.0 );
+}
+
+function is_explosive_ragdoll( weapon, inflictor )
+{
+ if ( !isdefined( weapon ) )
+ {
+ return false;
+ }
+
+ // destructible explosives
+ if ( weapon.name == "destructible_car" || weapon.name == "explodable_barrel" )
+ {
+ return true;
+ }
+
+ // special explosive weapons
+ if ( weapon.projExplosionType == "grenade" )
+ {
+ if ( isdefined( inflictor ) && isdefined( inflictor.stuckToPlayer ) )
+ {
+ if ( inflictor.stuckToPlayer == self )
+ {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+function start_explosive_ragdoll( dir, weapon )
+{
+ if ( !isdefined( self ) )
+ {
+ return;
+ }
+
+ x = RandomIntRange( 50, 100 );
+ y = RandomIntRange( 50, 100 );
+ z = RandomIntRange( 10, 20 );
+
+ if ( isdefined( weapon ) && (weapon.name == "sticky_grenade" || weapon.name == "explosive_bolt") )
+ {
+ if ( isdefined( dir ) && LengthSquared( dir ) > 0 )
+ {
+ x = dir[0] * x;
+ y = dir[1] * y;
+ }
+ }
+ else
+ {
+ if ( math::cointoss() )
+ {
+ x = x * -1;
+ }
+ if ( math::cointoss() )
+ {
+ y = y * -1;
+ }
+ }
+
+ self StartRagdoll();
+ self LaunchRagdoll( ( x, y, z ) );
+}
+
+function start_death_from_above_ragdoll( dir )
+{
+ if ( !isdefined( self ) )
+ {
+ return;
+ }
+
+ self StartRagdoll();
+ self LaunchRagdoll( ( 0, 0, -100 ) );
+}
+
+
+function notifyConnecting()
+{
+ waittillframeend;
+
+ if( isdefined( self ) )
+ {
+ level notify( "connecting", self );
+ }
+
+ callback::callback( #"on_player_connecting" );
+}
+
+
+function delayStartRagdoll( ent, sHitLoc, vDir, weapon, eInflictor, sMeansOfDeath )
+{
+ if ( isdefined( ent ) )
+ {
+ deathAnim = ent getcorpseanim();
+ if ( animhasnotetrack( deathAnim, "ignore_ragdoll" ) )
+ return;
+ }
+
+ waittillframeend;
+
+ if ( !isdefined( ent ) )
+ return;
+
+ if ( ent isRagDoll() )
+ return;
+
+ deathAnim = ent getcorpseanim();
+
+ startFrac = 0.35;
+
+ if ( animhasnotetrack( deathAnim, "start_ragdoll" ) )
+ {
+ times = getnotetracktimes( deathAnim, "start_ragdoll" );
+ if ( isdefined( times ) )
+ startFrac = times[0];
+ }
+
+ waitTime = startFrac * getanimlength( deathAnim );
+
+ //waitTime -= 0.2; // account for the wait above
+ if( waitTime > 0 )
+ wait( waitTime );
+
+ if ( isdefined( ent ) )
+ {
+ ent startragdoll();
+ }
+}
+
+function trackAttackerDamage( eAttacker, iDamage, sMeansOfDeath, weapon )
+{
+ if( !IsDefined( eAttacker ) )
+ return;
+
+ if ( !IsPlayer( eAttacker ) )
+ return;
+
+ if ( self.attackerData.size == 0 )
+ {
+ self.firstTimeDamaged = getTime();
+ }
+ if ( !isdefined( self.attackerData[eAttacker.clientid] ) )
+ {
+ self.attackerDamage[eAttacker.clientid] = spawnstruct();
+ self.attackerDamage[eAttacker.clientid].damage = iDamage;
+ self.attackerDamage[eAttacker.clientid].meansOfDeath = sMeansOfDeath;
+ self.attackerDamage[eAttacker.clientid].weapon = weapon;
+ self.attackerDamage[eAttacker.clientid].time = getTime();
+
+ self.attackers[ self.attackers.size ] = eAttacker;
+
+ // we keep an array of attackers by their client ID so we can easily tell
+ // if they're already one of the existing attackers in the above if().
+ // we store in this array data that is useful for other things, like challenges
+ self.attackerData[eAttacker.clientid] = false;
+ }
+ else
+ {
+ self.attackerDamage[eAttacker.clientid].damage += iDamage;
+ self.attackerDamage[eAttacker.clientid].meansOfDeath = sMeansOfDeath;
+ self.attackerDamage[eAttacker.clientid].weapon = weapon;
+ if ( !isdefined( self.attackerDamage[eAttacker.clientid].time ) )
+ self.attackerDamage[eAttacker.clientid].time = getTime();
+ }
+
+ if ( IsArray( self.attackersThisSpawn ) )
+ {
+ self.attackersThisSpawn[ eAttacker.clientid ] = eAttacker;
+ }
+
+ self.attackerDamage[eAttacker.clientid].lasttimedamaged = getTime();
+ if ( weapons::is_primary_weapon( weapon ) )
+ self.attackerData[eAttacker.clientid] = true;
+}
+
+function giveAttackerAndInflictorOwnerAssist( eAttacker, eInflictor, iDamage, sMeansOfDeath, weapon )
+{
+ if ( !allowedAssistWeapon( weapon ) )
+ return;
+
+ self trackAttackerDamage( eAttacker, iDamage, sMeansOfDeath, weapon );
+
+ if ( !isdefined( eInflictor ) )
+ return;
+
+ if ( !isdefined( eInflictor.owner ) )
+ return;
+
+ if ( !isdefined( eInflictor.ownerGetsAssist ) )
+ return;
+
+ if ( !eInflictor.ownerGetsAssist )
+ return;
+
+ // if attacker and inflictor owner are the same no additional points
+ // I dont ever know if they are different
+ if ( isdefined( eAttacker ) && eAttacker == eInflictor.owner )
+ return;
+
+ self trackAttackerDamage( eInflictor.owner, iDamage, sMeansOfDeath, weapon );
+}
+
+function PlayerKilled_UpdateMeansOfDeath( attacker, eInflictor, weapon, sMeansOfDeath, sHitLoc )
+{
+ if( globallogic_utils::isHeadShot( weapon, sHitLoc, sMeansOfDeath, eInflictor ) && isPlayer( attacker ) && !weapon_utils::ismeleemod( sMeansOfDeath ) )
+ {
+ return "MOD_HEAD_SHOT";
+ }
+
+ // we do not want the melee icon to show up for dog attacks
+ switch( weapon.name )
+ {
+ case "dog_bite":
+ sMeansOfDeath = "MOD_PISTOL_BULLET";
+ break;
+ case "destructible_car":
+ sMeansOfDeath = "MOD_EXPLOSIVE";
+ break;
+ case "explodable_barrel":
+ sMeansOfDeath = "MOD_EXPLOSIVE";
+ break;
+ }
+
+ return sMeansOfDeath;
+}
+
+function updateAttacker( attacker, weapon )
+{
+ if( isai(attacker) && isdefined( attacker.script_owner ) )
+ {
+ // if the person who called the dogs in switched teams make sure they don't
+ // get penalized for the kill
+ if ( !level.teambased || attacker.script_owner.team != self.team )
+ attacker = attacker.script_owner;
+ }
+
+ if( attacker.classname == "script_vehicle" && isdefined( attacker.owner ) )
+ {
+ attacker notify("killed",self);
+
+ attacker = attacker.owner;
+ }
+
+ if( isai(attacker) )
+ attacker notify("killed",self);
+
+ if ( ( isdefined ( self.capturingLastFlag ) ) && ( self.capturingLastFlag == true ) )
+ {
+ attacker.lastCapKiller = true;
+ }
+
+ if( isdefined( attacker ) && attacker != self && isdefined( weapon ) )
+ {
+ if ( weapon.name == "planemortar" )
+ {
+ if(!isdefined(attacker.planeMortarBda))attacker.planeMortarBda=0;
+ attacker.planeMortarBda++;
+ }
+ else if( weapon.name == "dart" ||
+ weapon.name == "dart_turret" )
+ {
+ if(!isdefined(attacker.dartBda))attacker.dartBda=0;
+ attacker.dartBda++;
+ }
+ else if( weapon.name == "straferun_rockets" || weapon.name == "straferun_gun")
+ {
+ if( isdefined( attacker.strafeRunbda ) )
+ {
+ attacker.strafeRunbda++;
+ }
+ }
+ else if ( weapon.name == "remote_missile_missile" || weapon.name == "remote_missile_bomblet" )
+ {
+ if(!isdefined(attacker.remotemissileBda))attacker.remotemissileBda=0;
+ attacker.remotemissileBda++;
+ }
+ }
+
+ return attacker;
+}
+
+function updateInflictor( eInflictor )
+{
+ if( isdefined( eInflictor ) && eInflictor.classname == "script_vehicle" )
+ {
+ eInflictor notify("killed",self);
+
+ if ( isdefined( eInflictor.bda ) )
+ {
+ eInflictor.bda++;
+ }
+ }
+
+ return eInflictor;
+}
+
+function updateWeapon( eInflictor, weapon )
+{
+ // explosive barrel/car detection
+ if ( weapon == level.weaponNone && isdefined( eInflictor ) )
+ {
+ if ( isdefined( eInflictor.targetname ) && eInflictor.targetname == "explodable_barrel" )
+ weapon = GetWeapon( "explodable_barrel" );
+ else if ( isdefined( eInflictor.destructible_type ) && isSubStr( eInflictor.destructible_type, "vehicle_" ) )
+ weapon = GetWeapon( "destructible_car" );
+ }
+
+ return weapon;
+}
+
+function playKillBattleChatter( attacker, weapon, victim, eInflictor )
+{
+ if( IsPlayer( attacker ) )
+ {
+ if ( !killstreaks::is_killstreak_weapon( weapon ) )
+ {
+ level thread battlechatter::say_kill_battle_chatter( attacker, weapon, victim, eInflictor );
+ }
+ }
+
+ if( isdefined( eInflictor ) )
+ {
+ eInflictor notify( "bhtn_action_notify", "attack_kill" );
+ }
+}
diff --git a/installer/game/localappdata/T7x/data/scripts/mp/gametypes/_serversettings.gsc b/installer/game/localappdata/T7x/data/scripts/mp/gametypes/_serversettings.gsc
new file mode 100644
index 00000000..bf3985aa
Binary files /dev/null and b/installer/game/localappdata/T7x/data/scripts/mp/gametypes/_serversettings.gsc differ
diff --git a/installer/game/localappdata/T7x/data/scripts/mp/gametypes/_serversettings.gsc_raw b/installer/game/localappdata/T7x/data/scripts/mp/gametypes/_serversettings.gsc_raw
new file mode 100644
index 00000000..e420ca3c
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/scripts/mp/gametypes/_serversettings.gsc_raw
@@ -0,0 +1,209 @@
+#using scripts\codescripts\struct;
+
+#using scripts\shared\callbacks_shared;
+#using scripts\shared\system_shared;
+
+#namespace serversettings;
+
+function autoexec __init__sytem__() { system::register("serversettings",&__init__,undefined,undefined); }
+
+function __init__()
+{
+ callback::on_start_gametype( &init );
+}
+
+function init()
+{
+ level.hostname = GetDvarString( "sv_hostname");
+ if(level.hostname == "")
+ level.hostname = "CoDHost";
+ SetDvar("sv_hostname", level.hostname);
+ SetDvar("ui_hostname", level.hostname);
+ //makeDvarServerInfo("ui_hostname", "CoDHost");
+
+ level.motd = GetDvarString( "scr_motd" );
+ if(level.motd == "")
+ level.motd = "";
+ SetDvar("scr_motd", level.motd);
+ SetDvar("ui_motd", level.motd);
+ //makeDvarServerInfo("ui_motd", "");
+
+ level.allowvote = GetDvarString( "g_allowvote" );
+ if(level.allowvote == "")
+ level.allowvote = "1";
+ SetDvar("g_allowvote", level.allowvote);
+ SetDvar("ui_allowvote", level.allowvote);
+ //makeDvarServerInfo("ui_allowvote", "1");
+
+ level.allow_teamchange = "1";
+ SetDvar("ui_allow_teamchange", level.allow_teamchange);
+
+ level.friendlyfire = GetGametypeSetting( "friendlyfiretype" );
+
+ SetDvar("ui_friendlyfire", level.friendlyfire);
+ //makeDvarServerInfo("ui_friendlyfire", "0");
+
+ if(GetDvarString( "scr_mapsize") == "")
+ SetDvar("scr_mapsize", "64");
+ else if(GetDvarfloat( "scr_mapsize") >= 64)
+ SetDvar("scr_mapsize", "64");
+ else if(GetDvarfloat( "scr_mapsize") >= 32)
+ SetDvar("scr_mapsize", "32");
+ else if(GetDvarfloat( "scr_mapsize") >= 16)
+ SetDvar("scr_mapsize", "16");
+ else
+ SetDvar("scr_mapsize", "8");
+ level.mapsize = GetDvarfloat( "scr_mapsize");
+
+ constrain_gametype(GetDvarString( "g_gametype"));
+ constrain_map_size(level.mapsize);
+
+ thread setup_callbacks();
+
+ for(;;)
+ {
+ update();
+ wait 5;
+ }
+}
+
+function update()
+{
+ sv_hostname = GetDvarString( "sv_hostname");
+ if(level.hostname != sv_hostname)
+ {
+ level.hostname = sv_hostname;
+ SetDvar("ui_hostname", level.hostname);
+ }
+
+ scr_motd = GetDvarString( "scr_motd");
+ if(level.motd != scr_motd)
+ {
+ level.motd = scr_motd;
+ SetDvar("ui_motd", level.motd);
+ }
+
+ g_allowvote = GetDvarString( "g_allowvote" );
+ if(level.allowvote != g_allowvote)
+ {
+ level.allowvote = g_allowvote;
+ SetDvar("ui_allowvote", level.allowvote);
+ }
+
+ scr_friendlyfire = GetGametypeSetting( "friendlyfiretype" );
+ if(level.friendlyfire != scr_friendlyfire)
+ {
+ level.friendlyfire = scr_friendlyfire;
+ SetDvar("ui_friendlyfire", level.friendlyfire);
+ }
+}
+
+function constrain_gametype(gametype)
+{
+ entities = getentarray();
+ for(i = 0; i < entities.size; i++)
+ {
+ entity = entities[i];
+
+ if(gametype == "dm")
+ {
+ if(isdefined(entity.script_gametype_dm) && entity.script_gametype_dm != "1")
+ {
+ //iprintln("DELETED(GameType): ", entity.classname);
+ entity delete();
+ }
+ }
+ else if(gametype == "tdm")
+ {
+ if(isdefined(entity.script_gametype_tdm) && entity.script_gametype_tdm != "1")
+ {
+ //iprintln("DELETED(GameType): ", entity.classname);
+ entity delete();
+ }
+ }
+ else if(gametype == "ctf")
+ {
+ if(isdefined(entity.script_gametype_ctf) && entity.script_gametype_ctf != "1")
+ {
+ //iprintln("DELETED(GameType): ", entity.classname);
+ entity delete();
+ }
+ }
+ else if(gametype == "hq")
+ {
+ if(isdefined(entity.script_gametype_hq) && entity.script_gametype_hq != "1")
+ {
+ //iprintln("DELETED(GameType): ", entity.classname);
+ entity delete();
+ }
+ }
+ else if(gametype == "sd")
+ {
+ if(isdefined(entity.script_gametype_sd) && entity.script_gametype_sd != "1")
+ {
+ //iprintln("DELETED(GameType): ", entity.classname);
+ entity delete();
+ }
+ }
+ else if(gametype == "koth")
+ {
+ if(isdefined(entity.script_gametype_koth) && entity.script_gametype_koth != "1")
+ {
+ //iprintln("DELETED(GameType): ", entity.classname);
+ entity delete();
+ }
+ }
+ }
+}
+
+function constrain_map_size(mapsize)
+{
+ entities = getentarray();
+ for(i = 0; i < entities.size; i++)
+ {
+ entity = entities[i];
+
+ if(int(mapsize) == 8)
+ {
+ if(isdefined(entity.script_mapsize_08) && entity.script_mapsize_08 != "1")
+ {
+ //iprintln("DELETED(MapSize): ", entity.classname);
+ entity delete();
+ }
+ }
+ else if(int(mapsize) == 16)
+ {
+ if(isdefined(entity.script_mapsize_16) && entity.script_mapsize_16 != "1")
+ {
+ //iprintln("DELETED(MapSize): ", entity.classname);
+ entity delete();
+ }
+ }
+ else if(int(mapsize) == 32)
+ {
+ if(isdefined(entity.script_mapsize_32) && entity.script_mapsize_32 != "1")
+ {
+ //iprintln("DELETED(MapSize): ", entity.classname);
+ entity delete();
+ }
+ }
+ else if(int(mapsize) == 64)
+ {
+ if(isdefined(entity.script_mapsize_64) && entity.script_mapsize_64 != "1")
+ {
+ //iprintln("DELETED(MapSize): ", entity.classname);
+ entity delete();
+ }
+ }
+ }
+}
+
+function setup_callbacks()
+{
+ level.onForfeit = &default_onForfeit;
+}
+
+function default_onForfeit()
+{
+ level.gameForfeited = false;
+}
\ No newline at end of file
diff --git a/installer/game/localappdata/T7x/data/scripts/mp/teams/_teams.gsc b/installer/game/localappdata/T7x/data/scripts/mp/teams/_teams.gsc
new file mode 100644
index 00000000..bb53019a
Binary files /dev/null and b/installer/game/localappdata/T7x/data/scripts/mp/teams/_teams.gsc differ
diff --git a/installer/game/localappdata/T7x/data/scripts/mp/teams/_teams.gsc_raw b/installer/game/localappdata/T7x/data/scripts/mp/teams/_teams.gsc_raw
new file mode 100644
index 00000000..1260a17b
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/scripts/mp/teams/_teams.gsc_raw
@@ -0,0 +1,670 @@
+#using scripts\codescripts\struct;
+
+#using scripts\shared\callbacks_shared;
+#using scripts\shared\persistence_shared;
+#using scripts\shared\system_shared;
+#using scripts\shared\util_shared;
+
+#insert scripts\shared\shared.gsh;
+
+#using scripts\mp\gametypes\_globallogic_ui;
+#using scripts\mp\gametypes\_spectating;
+
+#using scripts\mp\_util;
+
+#precache( "material", "mpflag_spectator" );
+#precache( "string", "MP_AUTOBALANCE_NOW" );
+
+#namespace teams;
+
+REGISTER_SYSTEM( "teams", &__init__, undefined )
+
+function __init__()
+{
+ callback::on_start_gametype( &init );
+
+ level.getEnemyTeam = &getEnemyTeam;
+ level.use_team_based_logic_for_locking_on = true;
+}
+
+function init()
+{
+ game["strings"]["autobalance"] = &"MP_AUTOBALANCE_NOW";
+
+ if(GetDvarString( "scr_teambalance") == "")
+ SetDvar("scr_teambalance", "0");
+ level.teambalance = GetDvarint( "scr_teambalance");
+ level.teambalancetimer = 0;
+
+ if(GetDvarString( "scr_timeplayedcap") == "")
+ SetDvar("scr_timeplayedcap", "1800");
+ level.timeplayedcap = int(GetDvarint( "scr_timeplayedcap"));
+
+ level.freeplayers = [];
+
+ if( level.teamBased )
+ {
+ level.alliesplayers = [];
+ level.axisplayers = [];
+
+ callback::on_connect( &on_player_connect );
+ callback::on_joined_team( &on_joined_team );
+ callback::on_joined_spectate( &on_joined_spectators );
+ level thread update_team_balance();
+
+ wait .15;
+
+ level thread update_player_times();
+
+ }
+ else
+ {
+ callback::on_connect( &on_free_player_connect );
+
+ wait .15;
+
+ level thread update_player_times();
+
+ }
+}
+
+function on_player_connect()
+{
+ self thread track_played_time();
+}
+
+function on_free_player_connect()
+{
+ self thread track_free_played_time();
+}
+
+function on_joined_team()
+{
+ /#println( "joined team: " + self.pers["team"] );#/
+ self update_time();
+}
+
+function on_joined_spectators()
+{
+ self.pers["teamTime"] = undefined;
+}
+
+function track_played_time()
+{
+ self endon( "disconnect" );
+
+ if ( !isdefined( self.pers["totalTimePlayed"] ) )
+ {
+ self.pers["totalTimePlayed"] = 0;
+ }
+
+ foreach ( team in level.teams )
+ {
+ self.timePlayed[team] = 0;
+ }
+ self.timePlayed["free"] = 0;
+ self.timePlayed["other"] = 0;
+ self.timePlayed["alive"] = 0;
+
+ // dont reset time played in War when going into final fight, this is used for calculating match bonus
+ if ( !isdefined( self.timePlayed["total"] ) || !( (level.gameType == "twar") && (0 < game["roundsplayed"]) && (0 < self.timeplayed["total"]) ) )
+ self.timePlayed["total"] = 0;
+
+ while ( level.inPrematchPeriod )
+ WAIT_SERVER_FRAME;
+
+ for ( ;; )
+ {
+ if ( game["state"] == "playing" )
+ {
+ if ( isdefined( level.teams[self.sessionteam] ) )
+ {
+ self.timePlayed[self.sessionteam]++;
+ self.timePlayed["total"]++;
+
+ if ( level.mpCustomMatch )
+ {
+ self.pers["sbtimeplayed"] = self.timeplayed["total"];
+ self.sbtimeplayed = self.pers["sbtimeplayed"];
+ }
+
+ if ( IsAlive( self ) )
+ self.timePlayed["alive"]++;
+ }
+ else if ( self.sessionteam == "spectator" )
+ {
+ self.timePlayed["other"]++;
+ }
+ }
+
+ wait ( 1.0 );
+ }
+}
+
+
+function update_player_times()
+{
+ const minWait = 10.0;
+ const step = 1.0;
+ varWait = minWait;
+
+ nextToUpdate = 0;
+ for ( ;; )
+ {
+ varWait = varWait - step;
+ nextToUpdate++;
+
+ if ( nextToUpdate >= level.players.size )
+ {
+ nextToUpdate = 0;
+
+ if ( varWait > 0 )
+ {
+ wait ( varWait );
+ }
+
+ varWait = minWait;
+ }
+
+ if ( isdefined( level.players[nextToUpdate] ) )
+ {
+ level.players[nextToUpdate] update_played_time();
+ level.players[nextToUpdate] persistence::check_contract_expirations();
+ }
+
+ wait ( step );
+ }
+}
+
+function update_played_time()
+{
+ pixbeginevent("updatePlayedTime");
+
+ if ( level.rankedMatch || level.leagueMatch )
+ {
+ foreach( team in level.teams )
+ {
+ if ( self.timePlayed[team] )
+ {
+ if ( level.teambased )
+ {
+ self AddPlayerStat( "time_played_"+team, int( min( self.timePlayed[team], level.timeplayedcap ) ) );
+ }
+
+ self AddPlayerStatWithGameType( "time_played_total", int( min( self.timePlayed[team], level.timeplayedcap ) ) );
+ }
+ }
+
+ if ( self.timePlayed["other"] )
+ {
+ self AddPlayerStat( "time_played_other", int( min( self.timePlayed["other"], level.timeplayedcap ) ) );
+ self AddPlayerStatWithGameType( "time_played_total", int( min( self.timePlayed["other"], level.timeplayedcap ) ) );
+ }
+
+ if ( self.timePlayed["alive"] )
+ {
+ timeAlive = int( min( self.timePlayed["alive"], level.timeplayedcap ) );
+ self persistence::increment_contract_times( timeAlive );
+ self AddPlayerStat( "time_played_alive", timeAlive );
+ }
+ }
+
+ if ( level.onlineGame )
+ {
+ timeAlive = int( min( self.timePlayed["alive"], level.timeplayedcap ) );
+ self.pers["time_played_alive"] += timeAlive;
+ }
+
+ pixendevent();
+
+ if ( game["state"] == "postgame" )
+ return;
+
+ foreach( team in level.teams )
+ {
+ self.timePlayed[team] = 0;
+ }
+ self.timePlayed["other"] = 0;
+ self.timePlayed["alive"] = 0;
+}
+
+
+function update_time()
+{
+ if ( game["state"] != "playing" )
+ return;
+
+ self.pers["teamTime"] = getTime();
+}
+
+function update_balance_dvar()
+{
+ for(;;)
+ {
+ teambalance = GetDvarint( "scr_teambalance");
+ if(level.teambalance != teambalance)
+ level.teambalance = GetDvarint( "scr_teambalance");
+
+ timeplayedcap = GetDvarint( "scr_timeplayedcap");
+ if(level.timeplayedcap != timeplayedcap)
+ level.timeplayedcap = int(GetDvarint( "scr_timeplayedcap"));
+
+ wait 1;
+ }
+}
+
+
+function update_team_balance()
+{
+ level thread update_balance_dvar();
+
+ wait .15;
+
+ if ( level.teamBalance && util::isRoundBased() && level.numlives )
+ {
+ if ( isDefined( game["BalanceTeamsNextRound"] ) )
+ iPrintLnbold( &"MP_AUTOBALANCE_NEXT_ROUND" );
+
+ level waittill( "game_ended" );
+ wait 1;
+
+ if ( isDefined( game["BalanceTeamsNextRound"] ) )
+ {
+ level balance_teams();
+ game["BalanceTeamsNextRound"] = undefined;
+ }
+ else if ( !get_team_balance() )
+ {
+ game["BalanceTeamsNextRound"] = true;
+ }
+ }
+ else
+ {
+ level endon ( "game_ended" );
+
+ for ( ;; )
+ {
+ if ( level.teamBalance )
+ {
+ if ( !get_team_balance() )
+ {
+ iPrintLnBold( &"MP_AUTOBALANCE_SECONDS", 15 );
+ wait 15.0;
+
+ if ( !get_team_balance() )
+ level balance_teams();
+ }
+
+ wait 59.0;
+ }
+
+ wait 1.0;
+ }
+ }
+
+}
+
+
+function get_team_balance()
+{
+ level.team["allies"] = 0;
+ level.team["axis"] = 0;
+
+ players = level.players;
+
+ for ( i = 0; i < players.size; i++ )
+ {
+ if ( ( isdefined( players[i].pers["team"] ) ) && ( players[i].pers["team"] == "allies" ) )
+ level.team["allies"]++;
+ else if ( ( isdefined( players[i].pers["team"] ) ) && ( players[i].pers["team"] == "axis" ) )
+ level.team["axis"]++;
+ }
+
+ if ( ( level.team["allies"] > ( level.team["axis"] + level.teamBalance ) ) || ( level.team["axis"] > ( level.team["allies"] + level.teamBalance ) ) )
+ return false;
+ else
+ return true;
+}
+
+
+function balance_teams()
+{
+ iPrintLnBold( game["strings"]["autobalance"] );
+ //Create/Clear the team arrays
+ AlliedPlayers = [];
+ AxisPlayers = [];
+
+ // Populate the team arrays
+ players = level.players;
+
+ for ( i = 0; i < players.size; i++ )
+ {
+ if ( !isdefined( players[i].pers["teamTime"] ) )
+ continue;
+
+ if ( ( isdefined( players[i].pers["team"] ) ) && ( players[i].pers["team"] == "allies" ) )
+ AlliedPlayers[AlliedPlayers.size] = players[i];
+ else if ( ( isdefined( players[i].pers["team"] ) ) && ( players[i].pers["team"] == "axis" ) )
+ AxisPlayers[AxisPlayers.size] = players[i];
+ }
+
+ MostRecent = undefined;
+
+ while ( ( AlliedPlayers.size > ( AxisPlayers.size + 1 ) ) || ( AxisPlayers.size > ( AlliedPlayers.size + 1 ) ) )
+ {
+ if ( AlliedPlayers.size > ( AxisPlayers.size + 1 ) )
+ {
+ // Move the player that's been on the team the shortest ammount of time (highest teamTime value)
+ // Ignore players capturing or carrying objects
+ for ( j = 0; j < AlliedPlayers.size; j++ )
+ {
+
+ if ( !isdefined( MostRecent ) )
+ MostRecent = AlliedPlayers[j];
+ else if ( AlliedPlayers[j].pers["teamTime"] > MostRecent.pers["teamTime"] )
+ MostRecent = AlliedPlayers[j];
+ }
+
+ if ( isdefined( MostRecent ) )
+ MostRecent change( "axis" );
+ else
+ {
+ // Move the player that's been on the team the shortest ammount of time
+ for ( j = 0; j < AlliedPlayers.size; j++ )
+ {
+ if ( !isdefined( MostRecent ) )
+ MostRecent = AlliedPlayers[j];
+ else if ( AlliedPlayers[j].pers["teamTime"] > MostRecent.pers["teamTime"] )
+ MostRecent = AlliedPlayers[j];
+ }
+
+ MostRecent change( "axis" );
+ }
+ }
+ else if ( AxisPlayers.size > ( AlliedPlayers.size + 1 ) )
+ {
+ // Move the player that's been on the team the shortest ammount of time (highest teamTime value)
+ // Ignore players capturing or carrying objects
+ for ( j = 0; j < AxisPlayers.size; j++ )
+ {
+
+ if ( !isdefined( MostRecent ) )
+ MostRecent = AxisPlayers[j];
+ else if ( AxisPlayers[j].pers["teamTime"] > MostRecent.pers["teamTime"] )
+ MostRecent = AxisPlayers[j];
+ }
+
+ if ( isdefined( MostRecent ) )
+ MostRecent change( "allies" );
+ else
+ {
+ // Move the player that's been on the team the shortest ammount of time
+ for ( j = 0; j < AxisPlayers.size; j++ )
+ {
+ if ( !isdefined( MostRecent ) )
+ MostRecent = AxisPlayers[j];
+ else if ( AxisPlayers[j].pers["teamTime"] > MostRecent.pers["teamTime"] )
+ MostRecent = AxisPlayers[j];
+ }
+
+ MostRecent change( "allies" );
+ }
+ }
+
+ MostRecent = undefined;
+ AlliedPlayers = [];
+ AxisPlayers = [];
+
+ players = level.players;
+
+ for ( i = 0; i < players.size; i++ )
+ {
+ if ( ( isdefined( players[i].pers["team"] ) ) && ( players[i].pers["team"] == "allies" ) )
+ AlliedPlayers[AlliedPlayers.size] = players[i];
+ else if ( ( isdefined( players[i].pers["team"] ) ) && ( players[i].pers["team"] == "axis" ) )
+ AxisPlayers[AxisPlayers.size] = players[i];
+ }
+ }
+}
+
+
+function change( team )
+{
+ if (self.sessionstate != "dead")
+ {
+ // Set a flag on the player to they aren't robbed points for dying - the callback will remove the flag
+ self.switching_teams = true;
+ self.switchedTeamsResetGadgets = true;
+ self.joining_team = team;
+ self.leaving_team = self.pers["team"];
+
+ // Suicide the player so they can't hit escape and fail the team balance
+ self suicide();
+ }
+
+ self.pers["team"] = team;
+ self.team = team;
+ self.pers["weapon"] = undefined;
+ self.pers["spawnweapon"] = undefined;
+ self.pers["savedmodel"] = undefined;
+ self.pers["teamTime"] = undefined;
+ self.sessionteam = self.pers["team"];
+
+ self globallogic_ui::updateObjectiveText();
+
+ // update spectator permissions immediately on change of team
+ self spectating::set_permissions();
+
+ self SetClientScriptMainMenu( game[ "menu_start_menu" ] );
+ self openMenu(game[ "menu_start_menu" ]);
+
+ self notify("end_respawn");
+}
+
+function count_players()
+{
+ players = level.players;
+
+ playerCounts = [];
+ foreach( team in level.teams )
+ {
+ playerCounts[team] = 0;
+ }
+
+ foreach( player in level.players )
+ {
+ if( player == self )
+ continue;
+
+ team = player.pers["team"];
+ if( isdefined(team) && isdefined( level.teams[team] ) )
+ playerCounts[team]++;
+ }
+ return playerCounts;
+}
+
+
+function track_free_played_time()
+{
+ self endon( "disconnect" );
+
+ foreach( team in level.teams )
+ {
+ self.timePlayed[team] = 0;
+ }
+
+ self.timePlayed["other"] = 0;
+ self.timePlayed["total"] = 0;
+ self.timePlayed["alive"] = 0;
+
+ for ( ;; )
+ {
+ if ( game["state"] == "playing" )
+ {
+ team = self.pers["team"];
+ if ( isdefined( team ) && isdefined( level.teams[team] ) && self.sessionteam != "spectator" )
+ {
+ self.timePlayed[team]++;
+ self.timePlayed["total"]++;
+ if ( IsAlive( self ) )
+ self.timePlayed["alive"]++;
+ }
+ else
+ {
+ self.timePlayed["other"]++;
+ }
+ }
+
+ wait ( 1.0 );
+ }
+}
+
+function set_player_model( team, weapon )
+{
+ self DetachAll();
+ self SetMoveSpeedScale( 1 );
+ self SetSprintDuration( 4 );
+ self SetSprintCooldown( 0 );
+}
+
+function get_flag_model( teamRef )
+{
+ assert(isdefined(game["flagmodels"]));
+ assert(isdefined(game["flagmodels"][teamRef]));
+ return ( game["flagmodels"][teamRef] );
+}
+
+function get_flag_carry_model( teamRef )
+{
+ assert(isdefined(game["carry_flagmodels"]));
+ assert(isdefined(game["carry_flagmodels"][teamRef]));
+ return ( game["carry_flagmodels"][teamRef] );
+}
+
+function getTeamIndex( team )
+{
+ if( !isdefined( team ) )
+ {
+ return TEAM_FREE;
+ }
+
+ if( team == "free" )
+ {
+ return TEAM_FREE;
+ }
+
+ if( team == "allies" )
+ {
+ return TEAM_ALLIES;
+ }
+
+ if( team == "axis" )
+ {
+ return TEAM_AXIS;
+ }
+
+ return TEAM_FREE;
+}
+
+function getEnemyTeam( player_team )
+{
+ foreach( team in level.teams )
+ {
+ if ( team == player_team )
+ continue;
+
+ if ( team == "spectator" )
+ continue;
+
+ return team;
+ }
+
+ return util::getOtherTeam( player_team );
+}
+
+function GetEnemyPlayers()
+{
+ enemies = [];
+
+ foreach( player in level.players )
+ {
+ if( player.team == "spectator" )
+ {
+ continue;
+ }
+
+ if( ( level.teamBased && player.team != self.team ) || ( !level.teamBased && player != self ) )
+ {
+ ARRAY_ADD( enemies, player );
+ }
+ }
+
+ return enemies;
+}
+
+function GetFriendlyPlayers()
+{
+ friendlies = [];
+
+ foreach( player in level.players )
+ {
+ if( ( player.team == self.team ) && ( player != self ) )
+ {
+ ARRAY_ADD( friendlies, player );
+ }
+ }
+
+ return friendlies;
+}
+
+function WaitUntilTeamChange( player, callback, arg, end_condition1, end_condition2, end_condition3 )
+{
+ if( isdefined( end_condition1 ) )
+ self endon( end_condition1 );
+ if( isdefined( end_condition2 ) )
+ self endon( end_condition2 );
+ if( isdefined( end_condition3 ) )
+ self endon( end_condition3 );
+
+ event = player util::waittill_any( "joined_team", "disconnect", "joined_spectators" );
+
+ if( isdefined( callback ) )
+ {
+ self [[ callback ]]( arg, event );
+ }
+}
+
+
+function WaitUntilTeamChangeSingleTon( player, singletonString, callback, arg, end_condition1, end_condition2, end_condition3 )
+{
+ self notify( singletonString );
+ self endon( singletonString );
+ if( isdefined( end_condition1 ) )
+ self endon( end_condition1 );
+ if( isdefined( end_condition2 ) )
+ self endon( end_condition2 );
+ if( isdefined( end_condition3 ) )
+ self endon( end_condition3 );
+
+ event = player util::waittill_any( "joined_team", "disconnect", "joined_spectators" );
+
+ if( isdefined( callback ) )
+ {
+ self thread [[ callback ]]( arg, event );
+ }
+}
+
+
+function HideToSameTeam()
+{
+ if( level.teambased )
+ {
+ self SetVisibleToAllExceptTeam( self.team );
+ }
+ else
+ {
+ self SetVisibleToAll();
+ self SetInvisibleToPlayer( self.owner );
+ }
+}
+
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/doubleclick_join_server/__init__.lua b/installer/game/localappdata/T7x/data/ui_scripts/doubleclick_join_server/__init__.lua
new file mode 100644
index 00000000..71c4808c
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/doubleclick_join_server/__init__.lua
@@ -0,0 +1,118 @@
+if Engine.GetCurrentMap() ~= "core_frontend" then
+ return
+end
+
+require( "ui.uieditor.widgets.PC.ServerBrowser.ServerBrowserRowInternal" )
+require( "ui.uieditor.widgets.Lobby.Common.FE_FocusBarContainer" )
+
+CoD.ServerBrowserRow = InheritFrom( LUI.UIElement )
+CoD.ServerBrowserRow.new = function ( menu, controller )
+ local self = LUI.UIElement.new()
+ if PreLoadFunc then
+ PreLoadFunc( self, controller )
+ end
+ self:setUseStencil( false )
+ self:setClass( CoD.ServerBrowserRow )
+ self.id = "ServerBrowserRow"
+ self.soundSet = "default"
+ self:setLeftRight( true, false, 0, 700 )
+ self:setTopBottom( true, false, 0, 22 )
+ self:makeFocusable()
+ self:setHandleMouse( true )
+
+ if CoD.isPC then
+ self:registerEventHandler( "leftmousedown", function ()
+ if self:isInFocus() then
+ ServerBrowserCancelRequest( self )
+ JoinServerBrowser( self, self, controller, menu )
+ end
+ end )
+ end
+ self.anyChildUsesUpdateState = true
+
+ local background = LUI.UIImage.new()
+ background:setLeftRight( true, true, 0, 0 )
+ background:setTopBottom( true, true, 0, 0 )
+ background:setRGB( 0.2, 0.2, 0.2 )
+ background:setAlpha( 0.8 )
+ self:addElement( background )
+ self.background = background
+
+ local rowItems = CoD.ServerBrowserRowInternal.new( menu, controller )
+ rowItems:setLeftRight( true, false, 0, 700 )
+ rowItems:setTopBottom( true, false, 0, 22 )
+ rowItems:linkToElementModel( self, nil, false, function ( model )
+ rowItems:setModel( model, controller )
+ end )
+ self:addElement( rowItems )
+ self.rowItems = rowItems
+
+ local FocusBarB = CoD.FE_FocusBarContainer.new( menu, controller )
+ FocusBarB:setLeftRight( true, true, -2, 2 )
+ FocusBarB:setTopBottom( false, true, -1, 3 )
+ FocusBarB:setAlpha( 0 )
+ FocusBarB:setZoom( 1 )
+ self:addElement( FocusBarB )
+ self.FocusBarB = FocusBarB
+
+ local FocusBarT = CoD.FE_FocusBarContainer.new( menu, controller )
+ FocusBarT:setLeftRight( true, true, -2, 2 )
+ FocusBarT:setTopBottom( true, false, -2, 2 )
+ FocusBarT:setAlpha( 0 )
+ FocusBarT:setZoom( 1 )
+ self:addElement( FocusBarT )
+ self.FocusBarT = FocusBarT
+
+ self.clipsPerState = {
+ DefaultState = {
+ DefaultClip = function ()
+ self:setupElementClipCounter( 3 )
+ background:completeAnimation()
+ self.background:setRGB( 0.2, 0.2, 0.2 )
+ self.clipFinished( background, {} )
+ FocusBarB:completeAnimation()
+ self.FocusBarB:setAlpha( 0 )
+ self.clipFinished( FocusBarB, {} )
+ FocusBarT:completeAnimation()
+ self.FocusBarT:setAlpha( 0 )
+ self.clipFinished( FocusBarT, {} )
+ end,
+ Focus = function ()
+ self:setupElementClipCounter( 3 )
+ background:completeAnimation()
+ self.background:setRGB( 0.2, 0.2, 0.2 )
+ self.clipFinished( background, {} )
+ FocusBarB:completeAnimation()
+ self.FocusBarB:setAlpha( 1 )
+ self.clipFinished( FocusBarB, {} )
+ FocusBarT:completeAnimation()
+ self.FocusBarT:setAlpha( 1 )
+ self.clipFinished( FocusBarT, {} )
+ end,
+ Over = function ()
+ self:setupElementClipCounter( 3 )
+ background:completeAnimation()
+ self.background:setRGB( 0.39, 0.39, 0.39 )
+ self.clipFinished( background, {} )
+ FocusBarB:completeAnimation()
+ self.FocusBarB:setAlpha( 0 )
+ self.clipFinished( FocusBarB, {} )
+ FocusBarT:completeAnimation()
+ self.FocusBarT:setAlpha( 0 )
+ self.clipFinished( FocusBarT, {} )
+ end
+ }
+ }
+ LUI.OverrideFunction_CallOriginalSecond( self, "close", function ( element )
+ element.rowItems:close()
+ element.FocusBarB:close()
+ element.FocusBarT:close()
+ element.m_leftMouseDown = nil
+ end )
+
+ if PostLoadFunc then
+ PostLoadFunc( self, controller, menu )
+ end
+
+ return self
+end
\ No newline at end of file
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/__init__.lua b/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/__init__.lua
new file mode 100644
index 00000000..e9e83a69
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/__init__.lua
@@ -0,0 +1,156 @@
+if Engine.GetCurrentMap() ~= "core_frontend" then
+ return
+end
+
+local enableLobbyMapVote = true -- toggle map vote in public lobby
+local enableLargeServerBrowserButton = true -- toggle large server browser button
+
+local utils = require("utils")
+require("datasources_start_menu_tabs")
+require("datasources_change_map_categories")
+require("datasources_gamesettingsflyout_buttons")
+
+CoD.LobbyButtons.MP_PUBLIC_MATCH = {
+ stringRef = "MENU_PLAY_CAPS",
+ action = NavigateToLobby_SelectionList,
+ param = "MPLobbyOnline",
+ customId = "btnPublicMatch",
+}
+
+CoD.LobbyButtons.MP_FIND_MATCH = {
+ stringRef = "MPUI_BASICTRAINING_CAPS",
+ action = OpenFindMatch,
+ customId = "btnFindMatch",
+}
+
+CoD.LobbyButtons.STATS = {
+ stringRef = "STATS",
+ action = function(self, element, controller, param, menu)
+ SetPerControllerTableProperty(controller, "disableGameSettingsOptions", true)
+ OpenPopup(menu, "T7xStatsMenu", controller)
+ end,
+ customId = "btnMPStats"
+}
+
+CoD.LobbyButtons.MP_START_GAME = {
+ stringRef = "MENU_START_GAME_CAPS",
+ action = function(self, element, controller, param, menu)
+ Engine.SetDvar("party_minplayers", 1)
+ Engine.Exec(nil, "launchgame")
+ end,
+ customId = "btnStartGame"
+}
+
+CoD.LobbyButtons.SETTING_UP_BOTS = {
+ stringRef = "MENU_SETUP_BOTS_CAPS",
+ action = function(self, element, controller, param, menu)
+ SetPerControllerTableProperty(controller, "disableGameSettingsOptions", true)
+ OpenPopup(menu, "GameSettings_Bots", controller)
+ end,
+ customId = "btnSettingUpBots"
+}
+
+CoD.LobbyButtons.GameSettingsFlyoutArenas = {
+ stringRef = "MPUI_SETUP_GAME_CAPS",
+ action = function(self, element, controller, param, menu)
+ SetPerControllerTableProperty(controller, "disableGameSettingsOptions", true)
+ OpenPopup(menu, "GameSettingsFlyoutMP", controller)
+ end,
+ customId = "btnGameSettingsFlyoutMP"
+}
+
+CoD.LobbyButtons.GameSettingsFlyoutMP = {
+ stringRef = "MPUI_SETUP_GAME_CAPS",
+ action = function(self, element, controller, param, menu)
+ SetPerControllerTableProperty(controller, "disableGameSettingsOptions", true)
+ OpenPopup(menu, "GameSettingsFlyoutMPCustom", controller)
+ end,
+ customId = "btnGameSettingsFlyoutMPCustom"
+}
+
+CoD.LobbyButtons.SERVER_BROWSER = {
+ stringRef = "MENU_SERVER_BROWSER_CAPS",
+ action = function(self, element, controller, param, menu)
+ SetPerControllerTableProperty(controller, "disableGameSettingsOptions", true)
+ OpenPopup(menu, "LobbyServerBrowserOnline", controller)
+ end,
+ customId = "btnDedicated"
+}
+
+local shouldShowMapVote = enableLobbyMapVote
+local lobbyMapVote = function(lobbyMapVoteIsEnabled)
+ if lobbyMapVoteIsEnabled == true then
+ Engine.Exec(nil, "LobbyStopDemo")
+ end
+end
+
+local addCustomButtons = function(controller, menuId, buttonTable, isLeader)
+ if menuId == LobbyData.UITargets.UI_MPLOBBYMAIN.id then
+ utils.RemoveSpaces(buttonTable)
+ local theaterIndex = utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.THEATER_MP)
+ if theaterIndex ~= nil then
+ utils.AddSpacer(buttonTable, theaterIndex - 1)
+ end
+ end
+
+ if menuId == LobbyData.UITargets.UI_MPLOBBYONLINE.id or menuId == LobbyData.UITargets.UI_ZMLOBBYONLINE.id then
+ utils.AddSmallButton(controller, buttonTable, CoD.LobbyButtons.STATS)
+ end
+
+ if menuId == LobbyData.UITargets.UI_MPLOBBYONLINE.id or menuId == LobbyData.UITargets.UI_ZMLOBBYONLINE.id or menuId == LobbyData.UITargets.UI_MPLOBBYMAIN.id or menuId == LobbyData.UITargets.UI_MPLOBBYLANGAME.id then
+ Engine.Mods_Lists_UpdateUsermaps()
+ end
+
+ if menuId == LobbyData.UITargets.UI_MPLOBBYONLINE.id then
+ shouldShowMapVote = enableLobbyMapVote
+ if enableLargeServerBrowserButton then
+ utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.SERVER_BROWSER, 1)
+ end
+ elseif menuId == LobbyData.UITargets.UI_MPLOBBYONLINEPUBLICGAME.id then
+ utils.RemoveButton(buttonTable, CoD.LobbyButtons.MP_PUBLIC_LOBBY_LEADERBOARD)
+
+ utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.MP_START_GAME, 1)
+ utils.AddSmallButton(controller, buttonTable, CoD.LobbyButtons.GameSettingsFlyoutMP, 2)
+ utils.AddSpacer(buttonTable, utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.GameSettingsFlyoutMP))
+
+ lobbyMapVote(shouldShowMapVote)
+ shouldShowMapVote = false
+ elseif menuId == LobbyData.UITargets.UI_MPLOBBYONLINEARENAGAME.id then
+ utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.MP_START_GAME, 1)
+ utils.AddSmallButton(controller, buttonTable, CoD.LobbyButtons.GameSettingsFlyoutArenas, 2)
+
+ utils.AddSpacer(buttonTable, utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.GameSettingsFlyoutArenas))
+ end
+
+ if menuId == LobbyData.UITargets.UI_ZMLOBBYONLINE.id then
+ utils.RemoveButton(buttonTable, CoD.LobbyButtons.THEATER_ZM)
+ utils.AddLargeButton(controller, buttonTable, CoD.LobbyButtons.THEATER_ZM)
+
+ utils.RemoveSpaces(buttonTable)
+ utils.AddSpacer(buttonTable, utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.SERVER_BROWSER))
+ local bgbIndex = utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.ZM_BUBBLEGUM_BUFFS)
+ if bgbIndex ~= nil then
+ utils.AddSpacer(buttonTable, bgbIndex - 1)
+ end
+ utils.AddSpacer(buttonTable, utils.GetButtonIndex(buttonTable, CoD.LobbyButtons.STATS))
+ end
+end
+
+local oldAddButtonsForTarget = CoD.LobbyMenus.AddButtonsForTarget
+CoD.LobbyMenus.AddButtonsForTarget = function(controller, id)
+ local model = nil
+ if Engine.IsLobbyActive(Enum.LobbyType.LOBBY_TYPE_GAME) then
+ model = Engine.GetModel(DataSources.LobbyRoot.getModel(controller), "gameClient.isHost")
+ else
+ model = Engine.GetModel(DataSources.LobbyRoot.getModel(controller), "privateClient.isHost")
+ end
+ local isLeader = nil
+ if model ~= nil then
+ isLeader = Engine.GetModelValue(model)
+ else
+ isLeader = 1
+ end
+ local result = oldAddButtonsForTarget(controller, id)
+ addCustomButtons(controller, id, result, isLeader)
+ return result
+end
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/datasources_change_map_categories.lua b/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/datasources_change_map_categories.lua
new file mode 100644
index 00000000..468c6bfe
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/datasources_change_map_categories.lua
@@ -0,0 +1,96 @@
+local f0_local0 = function(f1_arg0, f1_arg1)
+ if not CoD.useMouse then
+ return
+ else
+ LUI.OverrideFunction_CallOriginalFirst(f1_arg0, "setState", function(element, controller)
+ if IsSelfInState(f1_arg0, "SelectingMap") then
+ f1_arg0.mapList:setMouseDisabled(false)
+ f1_arg0.mapCategoriesList:setMouseDisabled(true)
+ f1_arg0.m_categorySet = false
+ else
+ f1_arg0.mapList:setMouseDisabled(true)
+ f1_arg0.mapCategoriesList:setMouseDisabled(false)
+ end
+ end)
+ f1_arg0.mapList:setMouseDisabled(true)
+ f1_arg0.mapList:registerEventHandler("leftclick_outside", function(element, event)
+ if IsSelfInState(f1_arg0, "SelectingMap") and f1_arg0.m_categorySet then
+ CoD.PCUtil.SimulateButtonPress(f1_arg1, Enum.LUIButton.LUI_KEY_XBB_PSCIRCLE)
+ end
+ f1_arg0.m_categorySet = true
+ return true
+ end)
+ end
+end
+
+local PostLoadFunc = function(f4_arg0, f4_arg1)
+ f0_local0(f4_arg0, f4_arg1)
+end
+
+local f0_local2 = 10000
+local f0_local3 = 10001
+local f0_local4 = function(f5_arg0)
+ local f5_local0 = CoD.mapsTable[f5_arg0]
+ if CoD.CONTENT_DLC6_INDEX <= f5_local0.dlc_pack or f5_arg0 == "mp_redwood_ice" or f5_arg0 == "mp_veiled_heyday" then
+ return f0_local3
+ elseif f5_local0.dlc_pack > 0 then
+ return f0_local2
+ else
+ return f5_local0.dlc_pack
+ end
+end
+
+DataSources.ChangeMapCategories = DataSourceHelpers.ListSetup("ChangeMapCategories", function(f6_arg0)
+ local f6_local0 = {}
+ local f6_local1 = CoD.GetMapValue(Engine.DvarString(nil, "ui_mapname"), "dlc_pack", CoD.CONTENT_ORIGINAL_MAP_INDEX)
+ local f6_local2 = function(f7_arg0, f7_arg1)
+ return {
+ models = {
+ text = Engine.Localize("MPUI_MAP_CATEGORY_" .. f7_arg0 .. "_CAPS"),
+ buttonText = Engine.Localize("MPUI_MAP_CATEGORY_" .. f7_arg0 .. "_CAPS"),
+ image = "playlist_map",
+ description = Engine.Localize("MPUI_MAP_CATEGORY_" .. f7_arg0 .. "_DESC")
+ },
+ properties = {
+ category = f7_arg1,
+ selectIndex = f6_local1 == f7_arg1
+ }
+ }
+ end
+
+ CoD.mapsTable = Engine.GetGDTMapsTable()
+ local f6_local3 = function(f8_arg0)
+ for f8_local3, f8_local4 in pairs(CoD.mapsTable) do
+ if f8_local4.session_mode == CoD.gameModeEnum and f0_local4(f8_local3) == f8_arg0 and (ShowPurchasableMap(f6_arg0, f8_local3) or Engine.IsMapValid(f8_local3)) then
+ return true
+ end
+ end
+ return false
+ end
+
+ if CoD.isCampaign == true then
+ table.insert(f6_local0, f6_local2("missions", CoD.CONTENT_ORIGINAL_MAP_INDEX))
+ table.insert(f6_local0, f6_local2("dev", CoD.CONTENT_DEV_MAP_INDEX))
+ else
+ table.insert(f6_local0, f6_local2("standard", CoD.CONTENT_ORIGINAL_MAP_INDEX))
+ if not Dvar.ui_execdemo:get() and f6_local3(f0_local2) then
+ table.insert(f6_local0, f6_local2("dlc", f0_local2))
+ end
+ if not Dvar.ui_execdemo:get() and f6_local3(f0_local3) then
+ table.insert(f6_local0, f6_local2("dlc_bonus", f0_local3))
+ end
+ if Mods_Enabled() then --and Engine.Mods_Lists_GetInfoEntries( LuaEnums.USERMAP_BASE_PATH, 0, Engine.Mods_Lists_GetInfoEntriesCount( LuaEnums.USERMAP_BASE_PATH ) ) ~= nil then
+ local f9_local11 = Engine.Mods_Lists_GetInfoEntries(LuaEnums.USERMAP_BASE_PATH, 0,
+ Engine.Mods_Lists_GetInfoEntriesCount(LuaEnums.USERMAP_BASE_PATH))
+ if f9_local11 then
+ for f9_local12 = 0, #f9_local11, 1 do
+ local f9_local17 = f9_local11[f9_local12]
+ if LUI.startswith(f9_local17.internalName, "mp_") then
+ table.insert(f6_local0, f6_local2("mods", CoD.CONTENT_MODS_INDEX))
+ end
+ end
+ end
+ end
+ end
+ return f6_local0
+end, true)
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/datasources_gamesettingsflyout_buttons.lua b/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/datasources_gamesettingsflyout_buttons.lua
new file mode 100644
index 00000000..497efefb
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/datasources_gamesettingsflyout_buttons.lua
@@ -0,0 +1,260 @@
+local f0_local0 = function(f1_arg0, f1_arg1)
+ if not CoD.useMouse then
+ return
+ else
+ f1_arg0.Options:setHandleMouse(true)
+ f1_arg0.Options:registerEventHandler("leftclick_outside", function(element, event)
+ CoD.PCUtil.SimulateButtonPress(event.controller, Enum.LUIButton.LUI_KEY_XBB_PSCIRCLE)
+ return true
+ end)
+ end
+end
+
+local PostLoadFunc = function(f3_arg0, f3_arg1)
+ f0_local0(f3_arg0, f3_arg1)
+ f3_arg0.disableBlur = true
+ f3_arg0.disablePopupOpenCloseAnim = true
+ Engine.SetModelValue(Engine.CreateModel(Engine.GetGlobalModel(), "GameSettingsFlyoutOpen"), true)
+ LUI.OverrideFunction_CallOriginalSecond(f3_arg0, "close", function(element)
+ Engine.SetModelValue(Engine.CreateModel(Engine.GetGlobalModel(), "GameSettingsFlyoutOpen"), false)
+ end)
+ f3_arg0:registerEventHandler("occlusion_change", function(element, event)
+ local f5_local0 = element:getParent()
+ if f5_local0 then
+ local f5_local1 = f5_local0:getFirstChild()
+ while f5_local1 ~= nil do
+ if f5_local1.menuName == "Lobby" then
+ break
+ end
+ f5_local1 = f5_local1:getNextSibling()
+ end
+ if f5_local1 then
+ if event.occluded == true then
+ f5_local1:setAlpha(0)
+ end
+ f5_local1:setAlpha(1)
+ end
+ end
+ element:OcclusionChange(event)
+ end)
+ f3_arg0:subscribeToModel(Engine.CreateModel(Engine.GetGlobalModel(), "lobbyRoot.lobbyNav", true), function(model)
+ local f6_local0 = f3_arg0.occludedBy
+ while f6_local0 do
+ if f6_local0.occludedBy ~= nil then
+ f6_local0 = f6_local0.occludedBy
+ end
+ while f6_local0 and f6_local0.menuName ~= "Lobby" do
+ f6_local0 = GoBack(f6_local0, f3_arg1)
+ end
+ Engine.SendClientScriptNotify(f3_arg1, "menu_change" .. Engine.GetLocalClientNum(f3_arg1), "Main",
+ "closeToMenu")
+ return
+ end
+ GoBack(f3_arg0, f3_arg1)
+ end, false)
+end
+
+DataSources.GameSettingsFlyoutButtonsCustom = DataSourceHelpers.ListSetup("GameSettingsFlyoutButtonsCustom",
+function(f7_arg0)
+ local f7_local0 = {
+ {
+ optionDisplay = "MPUI_CHANGE_MAP_CAPS",
+ customId = "btnChangeMap",
+ action = OpenChangeMap
+ },
+ -- {
+ -- optionDisplay = "MPUI_CHANGE_GAME_MODE_CAPS",
+ -- customId = "btnChangeGameMode",
+ -- action = OpenChangeGameMode
+ -- },
+ {
+ optionDisplay = "MENU_SETUP_BOTS_CAPS",
+ customId = "btnSetupBots",
+ action = OpenBotSettings
+ },
+ {
+ optionDisplay = "MPUI_EDIT_GAME_RULES_CAPS",
+ customId = "btnEditGameRules",
+ action = OpenEditGameRules
+ }
+ }
+ -- if CoD.isPC and IsServerBrowserEnabled() then
+ -- table.insert( f7_local0, {
+ -- optionDisplay = "PLATFORM_SERVER_SETTINGS_CAPS",
+ -- customID = "btnServerSettings",
+ -- action = OpenServerSettings
+ -- } )
+ -- end
+ local f7_local1 = {}
+ for f7_local5, f7_local6 in ipairs(f7_local0) do
+ table.insert(f7_local1, {
+ models = {
+ displayText = Engine.Localize(f7_local6.optionDisplay),
+ customId = f7_local6.customId,
+ disabled = f7_local6.disabled
+ },
+ properties = {
+ title = f7_local6.optionDisplay,
+ desc = f7_local6.desc,
+ action = f7_local6.action,
+ actionParam = f7_local6.actionParam
+ }
+ })
+ end
+ return f7_local1
+end, nil, nil, nil)
+
+LUI.createMenu.GameSettingsFlyoutMPCustom = function(controller)
+ local self = CoD.Menu.NewForUIEditor("GameSettingsFlyoutMPCustom")
+ if PreLoadFunc then
+ PreLoadFunc(self, controller)
+ end
+ self.soundSet = "default"
+ self:setOwner(controller)
+ self:setLeftRight(true, true, 0, 0)
+ self:setTopBottom(true, true, 0, 0)
+ self:playSound("menu_open", controller)
+ self.buttonModel = Engine.CreateModel(Engine.GetModelForController(controller), "GameSettingsFlyoutMP.buttonPrompts")
+ self.anyChildUsesUpdateState = true
+
+ local Options = LUI.UIList.new(self, controller, -2, 0, nil, false, false, 0, 0, false, false)
+ Options:makeFocusable()
+ Options:setLeftRight(true, false, 243.43, 523.43)
+ Options:setTopBottom(true, false, 177.56, 329.56)
+ Options:setYRot(25)
+ Options:setWidgetType(CoD.FE_List1ButtonLarge_PH)
+ Options:setVerticalCount(3)
+ Options:setSpacing(-2)
+ Options:setDataSource("GameSettingsFlyoutButtonsCustom")
+ Options:registerEventHandler("gain_focus", function(element, event)
+ local f9_local0 = nil
+ if element.gainFocus then
+ f9_local0 = element:gainFocus(event)
+ elseif element.super.gainFocus then
+ f9_local0 = element.super:gainFocus(event)
+ end
+ CoD.Menu.UpdateButtonShownState(element, self, controller, Enum.LUIButton.LUI_KEY_XBA_PSCROSS)
+ return f9_local0
+ end)
+ Options:registerEventHandler("lose_focus", function(element, event)
+ local f10_local0 = nil
+ if element.loseFocus then
+ f10_local0 = element:loseFocus(event)
+ elseif element.super.loseFocus then
+ f10_local0 = element.super:loseFocus(event)
+ end
+ return f10_local0
+ end)
+ self:AddButtonCallbackFunction(Options, controller, Enum.LUIButton.LUI_KEY_XBA_PSCROSS, "ENTER",
+ function(element, menu, controller, model)
+ ProcessListAction(self, element, controller)
+ return true
+ end, function(element, menu, controller)
+ CoD.Menu.SetButtonLabel(menu, Enum.LUIButton.LUI_KEY_XBA_PSCROSS, "MENU_SELECT")
+ return true
+ end, false)
+ self:addElement(Options)
+ self.Options = Options
+
+ self:mergeStateConditions({
+ {
+ stateName = "Local",
+ condition = function(menu, element, event)
+ return IsLobbyNetworkModeLAN()
+ end
+ }
+ })
+ self:subscribeToModel(Engine.GetModel(Engine.GetGlobalModel(), "lobbyRoot.lobbyNetworkMode"), function(model)
+ local f14_local0 = self
+ local f14_local1 = {
+ controller = controller,
+ name = "model_validation",
+ modelValue = Engine.GetModelValue(model),
+ modelName = "lobbyRoot.lobbyNetworkMode"
+ }
+ CoD.Menu.UpdateButtonShownState(f14_local0, self, controller, Enum.LUIButton.LUI_KEY_XBY_PSTRIANGLE)
+ end)
+ self:subscribeToModel(Engine.GetModel(Engine.GetGlobalModel(), "lobbyRoot.lobbyNav"), function(model)
+ local f15_local0 = self
+ local f15_local1 = {
+ controller = controller,
+ name = "model_validation",
+ modelValue = Engine.GetModelValue(model),
+ modelName = "lobbyRoot.lobbyNav"
+ }
+ CoD.Menu.UpdateButtonShownState(f15_local0, self, controller, Enum.LUIButton.LUI_KEY_XBY_PSTRIANGLE)
+ end)
+ self:AddButtonCallbackFunction(self, controller, Enum.LUIButton.LUI_KEY_XBB_PSCIRCLE, nil,
+ function(element, menu, controller, model)
+ GoBack(self, controller)
+ ClearMenuSavedState(menu)
+ return true
+ end, function(element, menu, controller)
+ CoD.Menu.SetButtonLabel(menu, Enum.LUIButton.LUI_KEY_XBB_PSCIRCLE, "")
+ return false
+ end, false)
+ self:AddButtonCallbackFunction(self, controller, Enum.LUIButton.LUI_KEY_START, "M",
+ function(element, menu, controller, model)
+ GoBackAndOpenOverlayOnParent(self, "StartMenu_Main", controller)
+ return true
+ end, function(element, menu, controller)
+ CoD.Menu.SetButtonLabel(menu, Enum.LUIButton.LUI_KEY_START, "MENU_MENU")
+ return true
+ end, false)
+ self:AddButtonCallbackFunction(self, controller, Enum.LUIButton.LUI_KEY_XBY_PSTRIANGLE, "S",
+ function(element, menu, controller, model)
+ if not IsLAN() and not IsPlayerAGuest(controller) and IsPlayerAllowedToPlayOnline(controller) then
+ GoBackAndOpenOverlayOnParent(self, "Social_Main", controller)
+ return true
+ else
+
+ end
+ end, function(element, menu, controller)
+ if not IsLAN() and not IsPlayerAGuest(controller) and IsPlayerAllowedToPlayOnline(controller) then
+ CoD.Menu.SetButtonLabel(menu, Enum.LUIButton.LUI_KEY_XBY_PSTRIANGLE, "")
+ return false
+ else
+ return false
+ end
+ end, false)
+ self:AddButtonCallbackFunction(self, controller, Enum.LUIButton.LUI_KEY_LB, nil,
+ function(element, menu, controller, model)
+ SendButtonPressToOccludedMenu(menu, controller, model, Enum.LUIButton.LUI_KEY_LB)
+ return true
+ end, function(element, menu, controller)
+ CoD.Menu.SetButtonLabel(menu, Enum.LUIButton.LUI_KEY_LB, "")
+ return false
+ end, false)
+ self:AddButtonCallbackFunction(self, controller, Enum.LUIButton.LUI_KEY_RB, nil,
+ function(element, menu, controller, model)
+ SendButtonPressToOccludedMenu(menu, controller, model, Enum.LUIButton.LUI_KEY_RB)
+ return true
+ end, function(element, menu, controller)
+ CoD.Menu.SetButtonLabel(menu, Enum.LUIButton.LUI_KEY_RB, "")
+ return false
+ end, false)
+ Options.id = "Options"
+ self:processEvent({
+ name = "menu_loaded",
+ controller = controller
+ })
+ self:processEvent({
+ name = "update_state",
+ menu = self
+ })
+ if not self:restoreState() then
+ self.Options:processEvent({
+ name = "gain_focus",
+ controller = controller
+ })
+ end
+ LUI.OverrideFunction_CallOriginalSecond(self, "close", function(element)
+ element.Options:close()
+ Engine.UnsubscribeAndFreeModel(Engine.GetModel(Engine.GetModelForController(controller),
+ "GameSettingsFlyoutMP.buttonPrompts"))
+ end)
+ if PostLoadFunc then
+ PostLoadFunc(self, controller)
+ end
+ return self
+end
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/datasources_start_menu_tabs.lua b/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/datasources_start_menu_tabs.lua
new file mode 100644
index 00000000..77767260
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/datasources_start_menu_tabs.lua
@@ -0,0 +1,217 @@
+DataSources.StartMenuTabs = ListHelper_SetupDataSource("StartMenuTabs", function(f44_arg0)
+ local f44_local0 = {}
+ table.insert(f44_local0, {
+ models = {
+ tabIcon = CoD.buttonStrings.shoulderl
+ },
+ properties = {
+ m_mouseDisabled = true
+ }
+ })
+ if Engine.IsDemoPlaying() then
+ local f44_local1 = "CoD.StartMenu_GameOptions"
+ if Engine.IsZombiesGame() then
+ f44_local1 = "CoD.StartMenu_GameOptions_ZM"
+ end
+ table.insert(f44_local0, {
+ models = {
+ tabName = Engine.Localize("MENU_THEATER_CAPS"),
+ tabWidget = f44_local1,
+ tabIcon = ""
+ },
+ properties = {
+ tabId = "gameOptions"
+ }
+ })
+ elseif Engine.IsInGame() then
+ if IsGameTypeDOA() and not InSafehouse() then
+ table.insert(f44_local0, {
+ models = {
+ tabName = "DOA",
+ tabWidget = "CoD.StartMenu_GameOptions_DOA",
+ tabIcon = ""
+ },
+ properties = {
+ tabId = "gameOptions"
+ }
+ })
+ elseif CoD.isCampaign then
+ table.insert(f44_local0, {
+ models = {
+ tabName = SessionModeToUnlocalizedSessionModeCaps(Engine.CurrentSessionMode()),
+ tabWidget = "CoD.StartMenu_GameOptions_CP",
+ tabIcon = ""
+ },
+ properties = {
+ tabId = "gameOptions"
+ }
+ })
+ if not Engine.IsCampaignModeZombies() then
+ if CoD.isSafehouse and CoD.isOnlineGame() and not IsInTrainingSim(f44_arg0) and Dvar.ui_safehousebarracks:get() and not IsPlayerAGuest(f44_arg0) then
+ table.insert(f44_local0, {
+ models = {
+ tabName = "CPUI_BARRACKS_CAPS",
+ tabWidget = "CoD.CombatRecordCP_Contents",
+ tabIcon = ""
+ },
+ properties = {
+ tabId = "combatRecord"
+ }
+ })
+ end
+ if HighestMapReachedGreaterThan(f44_arg0, 1) or LUI.DEV ~= nil then
+ table.insert(f44_local0, {
+ models = {
+ tabName = "CPUI_TACTICAL_MODE_CAPS",
+ tabWidget = "CoD.StartMenu_TacticalMode",
+ tabIcon = ""
+ },
+ properties = {
+ tabId = "tacticalMode"
+ }
+ })
+ end
+ if not CoD.isSafehouse and not IsPlayerAGuest(f44_arg0) then
+ table.insert(f44_local0, {
+ models = {
+ tabName = "CPUI_ACCOLADES",
+ tabWidget = "CoD.MissionRecordVault_Challenges",
+ tabIcon = ""
+ },
+ properties = {
+ tabId = "accolades"
+ }
+ })
+ end
+ end
+ elseif Engine.IsZombiesGame() then
+ table.insert(f44_local0, {
+ models = {
+ tabName = SessionModeToUnlocalizedSessionModeCaps(Engine.CurrentSessionMode()),
+ tabWidget = "CoD.StartMenu_GameOptions_ZM",
+ tabIcon = ""
+ },
+ properties = {
+ tabId = "gameOptions"
+ }
+ })
+ else
+ table.insert(f44_local0, {
+ models = {
+ tabName = SessionModeToUnlocalizedSessionModeCaps(Engine.CurrentSessionMode()),
+ tabWidget = "CoD.StartMenu_GameOptions",
+ tabIcon = ""
+ },
+ properties = {
+ tabId = "gameOptions"
+ }
+ })
+ end
+ else
+ if not IsPlayerAGuest(f44_arg0) then
+ table.insert(f44_local0, {
+ models = {
+ tabName = "MENU_TAB_IDENTITY_CAPS",
+ tabWidget = "CoD.StartMenu_Identity",
+ tabIcon = ""
+ },
+ properties = {
+ tabId = "identity",
+ disabled = Dvar.ui_execdemo_gamescom:get()
+ }
+ })
+ end
+ if not IsLobbyNetworkModeLAN() and not Dvar.ui_execdemo:get() and not Engine.IsCampaignModeZombies() and not IsPlayerAGuest(f44_arg0) then
+ table.insert(f44_local0, {
+ models = {
+ tabName = "MENU_TAB_CHALLENGES_CAPS",
+ tabWidget = "CoD.StartMenu_Challenges",
+ tabIcon = ""
+ },
+ properties = {
+ tabId = "challenges"
+ }
+ })
+ local f44_local1 = CoD.isPC
+ if f44_local1 then
+ f44_local1 = false --Mods_IsUsingMods()
+ end
+ table.insert(f44_local0, {
+ models = {
+ tabName = "MENU_TAB_BARRACKS_CAPS",
+ tabWidget = "CoD.StartMenu_Barracks",
+ tabIcon = "",
+ disabled = f44_local1
+ },
+ properties = {
+ tabId = "barracks"
+ }
+ })
+ if CommunityOptionsEnabled() then
+ local f44_local2 = CoD.perController[f44_arg0].openMediaTabAfterClosingGroups
+ CoD.perController[f44_arg0].openMediaTabAfterClosingGroups = false
+ table.insert(f44_local0, {
+ models = {
+ tabName = "MENU_TAB_MEDIA_CAPS",
+ tabWidget = "CoD.StartMenu_Media",
+ tabIcon = ""
+ },
+ properties = {
+ tabId = "media",
+ selectIndex = f44_local2
+ }
+ })
+ end
+ end
+ end
+ if IsGameTypeDOA() and Engine.IsInGame() and not InSafehouse() then
+ local f44_local1 = table.insert
+ local f44_local2 = f44_local0
+ local f44_local3 = {
+ models = {
+ tabName = "MENU_TAB_OPTIONS_CAPS",
+ tabWidget = "CoD.StartMenu_Options_DOA",
+ tabIcon = ""
+ }
+ }
+ local f44_local4 = {
+ tabId = "options"
+ }
+ local f44_local5 = Dvar.ui_execdemo:get()
+ if f44_local5 then
+ f44_local5 = not Engine.IsInGame()
+ end
+ f44_local4.selectIndex = f44_local5
+ f44_local3.properties = f44_local4
+ f44_local1(f44_local2, f44_local3)
+ else
+ local f44_local1 = table.insert
+ local f44_local2 = f44_local0
+ local f44_local3 = {
+ models = {
+ tabName = "MENU_TAB_OPTIONS_CAPS",
+ tabWidget = "CoD.StartMenu_Options",
+ tabIcon = ""
+ }
+ }
+ local f44_local4 = {
+ tabId = "options"
+ }
+ local f44_local5 = Dvar.ui_execdemo_gamescom:get()
+ if f44_local5 then
+ f44_local5 = not Engine.IsInGame()
+ end
+ f44_local4.selectIndex = f44_local5
+ f44_local3.properties = f44_local4
+ f44_local1(f44_local2, f44_local3)
+ end
+ table.insert(f44_local0, {
+ models = {
+ tabIcon = CoD.buttonStrings.shoulderr
+ },
+ properties = {
+ m_mouseDisabled = true
+ }
+ })
+ return f44_local0
+end, true)
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/utils.lua b/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/utils.lua
new file mode 100644
index 00000000..f394e0ae
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/frontend_menus/utils.lua
@@ -0,0 +1,160 @@
+local IsGamescomDemo = function()
+ return Dvar.ui_execdemo_gamescom:get()
+end
+
+local IsBetaDemo = function()
+ return Dvar.ui_execdemo_beta:get()
+end
+
+local SetButtonState = function(button, state)
+ if state == nil then
+ return
+ elseif state == CoD.LobbyButtons.DISABLED then
+ button.disabled = true
+ elseif state == CoD.LobbyButtons.HIDDEN then
+ button.hidden = true
+ end
+end
+
+local RemoveButton = function(buttonTable, button)
+ if not button then
+ return
+ end
+ for id, v in pairs(buttonTable) do
+ if buttonTable[id].optionDisplay == button.stringRef then
+ table.remove(buttonTable, id)
+ end
+ end
+end
+
+local RemoveSpaces = function(buttonTable)
+ for id, v in pairs(buttonTable) do
+ buttonTable[id].isLastButtonInGroup = false
+ end
+end
+
+local GetButtonIndex = function(buttonTable, button)
+ if not button then
+ return nil
+ end
+ for id, v in pairs(buttonTable) do
+ if buttonTable[id].optionDisplay == button.stringRef then
+ return id
+ end
+ end
+end
+
+local AddButton = function(controller, options, button, isLargeButton, index)
+ if button == nil then
+ return
+ end
+
+ button.disabled = false
+ button.hidden = false
+ button.selected = false
+ button.warning = false
+ if button.defaultState ~= nil then
+ if button.defaultState == CoD.LobbyButtons.DISABLED then
+ button.disabled = true
+ elseif button.defaultState == CoD.LobbyButtons.HIDDEN then
+ button.hidden = true
+ end
+ end
+ if button.disabledFunc ~= nil then
+ button.disabled = button.disabledFunc(controller)
+ end
+ if button.visibleFunc ~= nil then
+ button.hidden = not button.visibleFunc(controller)
+ end
+ if IsBetaDemo() then
+ SetButtonState(button, button.demo_beta)
+ elseif IsGamescomDemo() then
+ SetButtonState(button, button.demo_gamescom)
+ end
+ if button.hidden then
+ return
+ end
+ local lobbyNav = LobbyData.GetLobbyNav()
+ if button.selectedFunc ~= nil then
+ button.selected = button.selectedFunc(button.selectedParam)
+ elseif CoD.LobbyMenus.History[lobbyNav] ~= nil then
+ button.selected = CoD.LobbyMenus.History[lobbyNav] == button.customId
+ end
+ if button.newBreadcrumbFunc then
+ local f8_local1 = button.newBreadcrumbFunc
+ if type(f8_local1) == "string" then
+ f8_local1 = LUI.getTableFromPath(f8_local1)
+ end
+ if f8_local1 then
+ button.isBreadcrumbNew = f8_local1(controller)
+ end
+ end
+ if button.warningFunc ~= nil then
+ button.warning = button.warningFunc(controller)
+ end
+ if button.starterPack == CoD.LobbyButtons.STARTERPACK_UPGRADE then
+ button.starterPackUpgrade = true
+ if IsStarterPack() then
+ button.disabled = false
+ end
+ end
+ if index ~= nil then
+ table.insert(options, index, {
+ optionDisplay = button.stringRef,
+ action = button.action,
+ param = button.param,
+ customId = button.customId,
+ isLargeButton = isLargeButton,
+ isLastButtonInGroup = false,
+ disabled = button.disabled,
+ selected = button.selected,
+ isBreadcrumbNew = button.isBreadcrumbNew,
+ warning = button.warning,
+ requiredChunk = button.selectedParam,
+ starterPackUpgrade = button.starterPackUpgrade,
+ unloadMod = button.unloadMod
+ })
+ else
+ table.insert(options, {
+ optionDisplay = button.stringRef,
+ action = button.action,
+ param = button.param,
+ customId = button.customId,
+ isLargeButton = isLargeButton,
+ isLastButtonInGroup = false,
+ disabled = button.disabled,
+ selected = button.selected,
+ isBreadcrumbNew = button.isBreadcrumbNew,
+ warning = button.warning,
+ requiredChunk = button.selectedParam,
+ starterPackUpgrade = button.starterPackUpgrade,
+ unloadMod = button.unloadMod
+ })
+ end
+end
+
+local AddLargeButton = function(controller, options, button, index)
+ AddButton(controller, options, button, true, index)
+end
+
+local AddSmallButton = function(controller, options, button, index)
+ AddButton(controller, options, button, false, index)
+end
+
+local AddSpacer = function(options, index)
+ if index ~= nil then
+ options[index].isLastButtonInGroup = true
+ elseif 0 < #options then
+ options[#options].isLastButtonInGroup = true
+ end
+end
+
+return {
+ AddButton = AddButton,
+ AddLargeButton = AddLargeButton,
+ AddSmallButton = AddSmallButton,
+ AddSpacer = AddSpacer,
+ RemoveButton = RemoveButton,
+ RemoveSpaces = RemoveSpaces,
+ GetButtonIndex = GetButtonIndex
+}
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/graphics_settings/__init__.lua b/installer/game/localappdata/T7x/data/ui_scripts/graphics_settings/__init__.lua
new file mode 100644
index 00000000..1219bea3
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/graphics_settings/__init__.lua
@@ -0,0 +1,148 @@
+DataSources.OptionGraphicsVideo = DataSourceHelpers.ListSetup( "PC.OptionGraphicsVideo", function ( controller )
+ local videoSettings = {}
+ table.insert( videoSettings, {
+ models = {
+ label = "PLATFORM_DISPLAY_MODE",
+ description = "PLATFORM_DISPLAY_MODE_DESC",
+ profileVarName = "r_fullscreen",
+ datasource = "OptionPCGraphicsDisplayMode",
+ widgetType = "dropdown"
+ },
+ properties = CoD.PCUtil.DependantDropdownProperties
+ } )
+ table.insert( videoSettings, {
+ models = {
+ label = "PLATFORM_MONITOR",
+ description = "PLATFORM_MONITOR_DESC",
+ profileVarName = "r_monitor",
+ datasource = "OptionPCGraphicsMonitor",
+ widgetType = "dropdown",
+ disabledFunction = function ()
+ return Engine.GetHardwareProfileValueAsString( "r_fullscreen" ) == "0"
+ end
+ },
+ properties = CoD.PCUtil.DependantDropdownProperties
+ } )
+ table.insert( videoSettings, {
+ models = {
+ label = "PLATFORM_SCREEN_RESOLUTION",
+ description = "PLATFORM_SCREEN_RESOLUTION_DESC",
+ profileVarName = "r_mode",
+ datasource = "OptionPCGraphicsScreenResolution",
+ widgetType = "dropdown",
+ disabledFunction = function ()
+ return Engine.GetHardwareProfileValueAsString( "r_fullscreen" ) == "2"
+ end
+ },
+ properties = CoD.PCUtil.DependantDropdownProperties
+ } )
+ table.insert( videoSettings, {
+ models = {
+ label = "PLATFORM_REFRESH_RATE",
+ description = "PLATFORM_REFRESH_RATE_DESC",
+ profileVarName = "r_refreshRate",
+ datasource = "OptionPCGraphicsRefreshRate",
+ widgetType = "dropdown",
+ disabledFunction = function ()
+ return Engine.GetHardwareProfileValueAsString( "r_fullscreen" ) ~= "1"
+ end
+ },
+ properties = CoD.PCUtil.OptionsGenericDropdownProperties
+ } )
+ table.insert( videoSettings, {
+ models = {
+ label = "PLATFORM_SCENE_RESOLUTION_RATIO",
+ description = "PLATFORM_SCENE_RESOLUTION_RATIO_DESC",
+ profileVarName = "r_sceneResolutionMultiplier",
+ datasource = "OptionPCGraphicsSceneResolution",
+ widgetType = "dropdown"
+ },
+ properties = CoD.PCUtil.DependantDropdownProperties
+ } )
+ table.insert( videoSettings, {
+ models = {
+ label = "PLATFORM_DISPLAY_GAMMA",
+ description = "PLATFORM_DISPLAY_GAMMA_DESC",
+ profileVarName = "r_videoMode",
+ datasource = "OptionPCGraphicsDisplayGamma",
+ widgetType = "dropdown"
+ },
+ properties = CoD.PCUtil.OptionsGenericDropdownProperties
+ } )
+ table.insert( videoSettings, {
+ models = {
+ label = "PLATFORM_BRIGHTNESS",
+ description = "PLATFORM_BRIGHTNESS_DESC",
+ profileVarName = "r_sceneBrightness",
+ profileType = "user",
+ lowValue = -1,
+ highValue = 1,
+ widgetType = "slider"
+ },
+ properties = CoD.PCUtil.OptionsGenericSliderProperties
+ } )
+ table.insert( videoSettings, {
+ models = {
+ label = "PLATFORM_FOV",
+ description = "PLATFORM_FOV_DESC",
+ profileVarName = "cg_fov_default",
+ lowValue = 65,
+ highValue = 120,
+ useIntegerDisplay = 1,
+ widgetType = "slider"
+ },
+ properties = CoD.PCUtil.OptionsGenericSliderProperties
+ } )
+ table.insert( videoSettings, {
+ models = {
+ widgetType = "spacer",
+ height = 32
+ }
+ } )
+ table.insert( videoSettings, {
+ models = {
+ label = "PLATFORM_MAX_FPS",
+ description = "PLATFORM_MAX_FPS_DESC",
+ profileVarName = "com_maxfps",
+ lowValue = 24,
+ highValue = 500,
+ useIntegerDisplay = 1,
+ widgetType = "slider"
+ },
+ properties = CoD.PCUtil.OptionsGenericSliderProperties
+ } )
+ table.insert( videoSettings, {
+ models = {
+ label = "PLATFORM_SYNC_EVERY_FRAME",
+ description = "PLATFORM_VSYNC_DESC",
+ profileVarName = "r_vsync",
+ widgetType = "checkbox"
+ },
+ properties = CoD.PCUtil.OptionsGenericCheckboxProperties
+ } )
+ table.insert( videoSettings, {
+ models = {
+ label = "PLATFORM_DRAW_FPS",
+ description = "PLATFORM_DRAW_FPS_DESC",
+ profileVarName = "com_drawFPS_PC",
+ widgetType = "checkbox"
+ },
+ properties = CoD.PCUtil.OptionsGenericCheckboxProperties
+ } )
+ return videoSettings
+end, true )
+DataSources.OptionGraphicsVideo.getWidgetTypeForItem = function ( list, dataItemModel, row )
+ if dataItemModel then
+ local widgetType = Engine.GetModelValue( Engine.GetModel( dataItemModel, "widgetType" ) )
+ if widgetType == "dropdown" then
+ return CoD.OptionDropdown
+ elseif widgetType == "checkbox" then
+ return CoD.StartMenu_Options_CheckBoxOption
+ elseif widgetType == "slider" then
+ return CoD.StartMenu_Options_SliderBar
+ elseif widgetType == "spacer" then
+ return CoD.VerticalListSpacer
+ end
+ end
+ return nil
+end
\ No newline at end of file
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/lua_fixes/__init__.lua b/installer/game/localappdata/T7x/data/ui_scripts/lua_fixes/__init__.lua
new file mode 100644
index 00000000..e04639b6
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/lua_fixes/__init__.lua
@@ -0,0 +1,4 @@
+
+-- Fix LUI_NULL_FUNCTION messages
+function Engine.PIXBeginEvent() end
+function Engine.PIXEndEvent() end
\ No newline at end of file
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/party/__init__.lua b/installer/game/localappdata/T7x/data/ui_scripts/party/__init__.lua
new file mode 100644
index 00000000..663b0e8d
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/party/__init__.lua
@@ -0,0 +1,30 @@
+local modeInfo = LobbyData:UITargetFromId(Engine.GetLobbyUIScreen())
+local maxClients = modeInfo.maxClients
+
+-- Disable setting party privacy in menu. Auto set to open + max.
+Engine.SetDvar("partyprivacyenabled", 0)
+Engine.SetDvar("tu4_partyprivacyuseglobal", 0)
+Engine.SetDvar("tu4_partyprivacyluacheck", 0)
+
+-- Fix for invisible bots in custom games
+if maxClients >= 1 then
+ Engine.SetDvar("party_maxplayers", maxClients)
+end
+
+if not Engine.IsInGame() then
+ return
+end
+
+-- Removed check for public matches to allow team change in ranked matches
+CoD.IsTeamChangeAllowed = function()
+ if Engine.GetGametypeSetting("allowInGameTeamChange") == 1 then
+ return true
+ else
+ return false
+ end
+end
+
+-- Set com_maxclients InGame so players can join via direct connect (default from lobbydata)
+Engine.SetDvar("com_maxclients", maxClients)
+
+require("datasources_start_menu_game_options")
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/party/datasources_start_menu_game_options.lua b/installer/game/localappdata/T7x/data/ui_scripts/party/datasources_start_menu_game_options.lua
new file mode 100644
index 00000000..ae6eb3bb
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/party/datasources_start_menu_game_options.lua
@@ -0,0 +1,75 @@
+DataSources.StartMenuGameOptions = ListHelper_SetupDataSource("StartMenuGameOptions", function (controller)
+ local options = {}
+ if Engine.IsDemoPlaying() then
+ if not IsDemoRestrictedBasicMode() then
+ table.insert(options, {models = {displayText = Engine.ToUpper(Engine.Localize("MENU_UPLOAD_CLIP", Engine.GetDemoSegmentCount())), action = StartMenuUploadClip, disabledFunction = IsUploadClipButtonDisabled}, properties = {hideHelpItemLabel = true}})
+ end
+ if Engine.IsDemoHighlightReelMode() then
+ table.insert(options, {models = {displayText = Engine.ToUpper(Engine.Localize("MENU_DEMO_CUSTOMIZE_HIGHLIGHT_REEL")), action = StartMenuOpenCustomizeHighlightReel, disabledFunction = IsCustomizeHighlightReelButtonDisabled}})
+ end
+ table.insert(options, {models = {displayText = Engine.ToUpper(Engine.ToUpper(Engine.Localize("MENU_JUMP_TO_START"))), action = StartMenuJumpToStart, disabledFunction = IsJumpToStartButtonDisabled}, properties = {hideHelpItemLabel = true}})
+ local endDemoButtonText = nil
+ if Engine.IsDemoClipPlaying() then
+ endDemoButtonText = Engine.ToUpper(Engine.Localize("MENU_END_CLIP"))
+ else
+ endDemoButtonText = Engine.ToUpper(Engine.Localize("MENU_END_FILM"))
+ end
+ table.insert(options, {models = {displayText = Engine.ToUpper(endDemoButtonText), action = StartMenuEndDemo}})
+ elseif CoD.isCampaign then
+ table.insert(options, {models = {displayText = "MENU_RESUMEGAME_CAPS", action = StartMenuGoBack_ListElement}})
+ local inTrainingSim = CoD.SafeGetModelValue(Engine.GetModelForController(controller), "safehouse.inTrainingSim")
+ if not inTrainingSim then
+ inTrainingSim = 0
+ end
+ if Engine.IsLobbyHost(Enum.LobbyType.LOBBY_TYPE_GAME) then
+ if not CoD.isSafehouse and controller == Engine.GetPrimaryController() then
+ table.insert(options, {models = {displayText = "MENU_RESTART_MISSION_CAPS", action = RestartMission}})
+ if LUI.DEV ~= nil then
+ table.insert(options, {models = {displayText = "MENU_RESTART_CHECKPOINT_CAPS", action = RestartFromCheckpoint}})
+ end
+ end
+ if controller == Engine.GetPrimaryController() then
+ table.insert(options, {models = {displayText = "MENU_CHANGE_DIFFICULTY_CAPS", action = OpenDifficultySelect}})
+ end
+ if CoD.isSafehouse and inTrainingSim == 1 then
+ table.insert(options, {models = {displayText = "MENU_END_TRAINING_SIM", action = EndTrainingSim}})
+ elseif controller == Engine.GetPrimaryController() then
+ if Engine.DvarBool(0, "ui_blocksaves") then
+ table.insert(options, {models = {displayText = "MENU_EXIT_CAPS", action = SaveAndQuitGame}})
+ else
+ table.insert(options, {models = {displayText = "MENU_SAVE_AND_QUIT_CAPS", action = SaveAndQuitGame}})
+ end
+ end
+ elseif CoD.isSafehouse and inTrainingSim == 1 then
+ table.insert(options, {models = {displayText = "MENU_END_TRAINING_SIM", action = EndTrainingSim}})
+ else
+ table.insert(options, {models = {displayText = "MENU_LEAVE_PARTY_AND_EXIT_CAPS", action = QuitGame}})
+ end
+ elseif CoD.isMultiplayer then
+ if Engine.Team(controller, "name") ~= "TEAM_SPECTATOR" and Engine.GetGametypeSetting("disableClassSelection") ~= 1 then
+ table.insert(options, {models = {displayText = "MPUI_CHOOSE_CLASS_BUTTON_CAPS", action = ChooseClass}})
+ end
+ if not Engine.IsVisibilityBitSet(controller, Enum.UIVisibilityBit.BIT_ROUND_END_KILLCAM) and not Engine.IsVisibilityBitSet(controller, Enum.UIVisibilityBit.BIT_FINAL_KILLCAM) and CoD.IsTeamChangeAllowed() then
+ table.insert(options, {models = {displayText = "MPUI_CHANGE_TEAM_BUTTON_CAPS", action = ChooseTeam}})
+ end
+ if controller == 0 then
+ local endGameText = "MENU_QUIT_GAME_CAPS"
+ if Engine.IsLobbyHost(Enum.LobbyType.LOBBY_TYPE_GAME) and not CoD.isOnlineGame() then
+ endGameText = "MENU_END_GAME_CAPS"
+ end
+ table.insert(options, {models = {displayText = endGameText, action = QuitGame_MP}})
+ end
+ elseif CoD.isZombie then
+ table.insert(options, {models = {displayText = "MENU_RESUMEGAME_CAPS", action = StartMenuGoBack_ListElement}})
+ if Engine.IsLobbyHost(Enum.LobbyType.LOBBY_TYPE_GAME) and (not Engine.SessionModeIsMode(CoD.SESSIONMODE_SYSTEMLINK) or Engine.SessionModeIsMode(CoD.SESSIONMODE_OFFLINE)) then
+ table.insert(options, {models = {displayText = "MENU_RESTART_LEVEL_CAPS", action = RestartGame}})
+ end
+ if Engine.IsLobbyHost(Enum.LobbyType.LOBBY_TYPE_GAME) == true then
+ table.insert(options, {models = {displayText = "MENU_END_GAME_CAPS", action = QuitGame_MP}})
+ else
+ table.insert(options, {models = {displayText = "MENU_QUIT_GAME_CAPS", action = QuitGame_MP}})
+ end
+ end
+ table.insert(options, {models = {displayText = "QUIT TO DESKTOP", action = OpenPCQuit}})
+ return options
+end, true)
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/playlist/__init__.lua b/installer/game/localappdata/T7x/data/ui_scripts/playlist/__init__.lua
new file mode 100644
index 00000000..f8080665
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/playlist/__init__.lua
@@ -0,0 +1,34 @@
+if Engine.GetCurrentMap() ~= "core_frontend" then
+ return
+end
+
+if CoD.LobbyMember then
+ local oldLobbyMember = CoD.LobbyMember.new
+ function CoD.LobbyMember.new(menu, controller)
+ local self = oldLobbyMember(menu, controller)
+
+ -- Hide the playlist count text
+ if self.SearchingForPlayer then
+ self.SearchingForPlayer:setAlpha(0)
+ end
+ if self.FEMemberBlurPanelContainer0 then
+ self.FEMemberBlurPanelContainer0:setAlpha(0)
+ end
+
+ return self
+ end
+end
+
+function IsLobbyStatusVisible()
+ return false
+end
+
+Engine.SetDvar("lobbyMigrate_Enabled", 0)
+Engine.SetDvar("lobbyTimerStatusVotingInterval", 11000)
+Engine.SetDvar("lobbyTimerStatusBeginInterval", 10)
+Engine.SetDvar("lobbyTimerStatusStartInterval", 10)
+Engine.SetDvar("lobbyTimerStatusPostGameInterval", 10)
+Engine.SetDvar("lobbyTimerStatusVotingInterval_Arena", 11000)
+
+require("widget_playlist_match_settings_info")
+require("widget_playlist_category_match_settings_info")
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/playlist/widget_playlist_category_match_settings_info.lua b/installer/game/localappdata/T7x/data/ui_scripts/playlist/widget_playlist_category_match_settings_info.lua
new file mode 100644
index 00000000..28c34d25
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/playlist/widget_playlist_category_match_settings_info.lua
@@ -0,0 +1,15 @@
+if not CoD.playlistCategoryMatchSettingsInfo then
+ return
+end
+
+local oldPlaylistCategoryMatchSettingsInfo = CoD.playlistCategoryMatchSettingsInfo.new
+function CoD.playlistCategoryMatchSettingsInfo.new(menu, controller)
+ local self = oldPlaylistCategoryMatchSettingsInfo(menu, controller)
+
+ -- Hide the playlist count text
+ if self.playlistCount then
+ self.playlistCount:setAlpha(0)
+ end
+
+ return self
+end
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/playlist/widget_playlist_match_settings_info.lua b/installer/game/localappdata/T7x/data/ui_scripts/playlist/widget_playlist_match_settings_info.lua
new file mode 100644
index 00000000..9b31390e
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/playlist/widget_playlist_match_settings_info.lua
@@ -0,0 +1,15 @@
+if not CoD.playlistMatchSettingsInfo then
+ return
+end
+
+local oldPlaylistMatchSettingsInfo = CoD.playlistMatchSettingsInfo.new
+function CoD.playlistMatchSettingsInfo.new(menu, controller)
+ local self = oldPlaylistMatchSettingsInfo(menu, controller)
+
+ -- Hide the playlist count text
+ if self.playlistCount then
+ self.playlistCount:setAlpha(0)
+ end
+
+ return self
+end
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/ranked/__init__.lua b/installer/game/localappdata/T7x/data/ui_scripts/ranked/__init__.lua
new file mode 100644
index 00000000..685aa5ca
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/ranked/__init__.lua
@@ -0,0 +1 @@
+require("online_mods_loaded")
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/ranked/online_mods_loaded.lua b/installer/game/localappdata/T7x/data/ui_scripts/ranked/online_mods_loaded.lua
new file mode 100644
index 00000000..2c388b9b
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/ranked/online_mods_loaded.lua
@@ -0,0 +1,23 @@
+if Engine.GetCurrentMap() ~= "core_frontend" then
+ return
+end
+
+function ShouldUnloadMod(arg0)
+ return false
+end
+
+-- Load usermaps mod if custom map selected
+local mustLoadUsermaps = function(element, controller)
+ if CoD.perController[controller].mapCategory == CoD.CONTENT_MODS_INDEX then
+ if not Engine.IsUsingMods() then
+ LuaUtils.Mods_LoadMod("usermaps") -- LuaUtils.Mods_LoadMod(element.loadModName)
+
+ CoD.OverlayUtility.ShowToast("DefaultState", Engine.Localize("MENU_MODS_CAPS"), Engine.Localize("PLATFORM_MODS_LOADED") .. " " .. element.mapName)
+ end
+ end
+end
+
+function MapSelected(element, controller)
+ SetMap(controller, element.mapName, false)
+ mustLoadUsermaps(element, controller)
+end
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/server_browser/__init__.lua b/installer/game/localappdata/T7x/data/ui_scripts/server_browser/__init__.lua
new file mode 100644
index 00000000..49cd0fc8
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/server_browser/__init__.lua
@@ -0,0 +1,378 @@
+if Engine.GetCurrentMap() ~= "core_frontend" then
+ return
+end
+
+function IsServerBrowserEnabled()
+ return true
+end
+
+DataSources.LobbyServer = {
+ prepare = function(controller, list, filter)
+ list.numElementsInList = list.vCount
+ list.controller = controller
+ list.serverBrowserRootModel = Engine.CreateModel(Engine.GetGlobalModel(), "serverBrowser")
+ local serverListCountModel = Engine.GetModel(list.serverBrowserRootModel, "serverListCount")
+ if serverListCountModel then
+ list.serverCount = Engine.GetModelValue(serverListCountModel)
+ else
+ list.serverCount = 0
+ end
+ list.servers = {}
+ local serversModel = Engine.CreateModel(list.serverBrowserRootModel, "servers")
+ for i = 1, list.numElementsInList, 1 do
+ list.servers[i] = {}
+ list.servers[i].root = Engine.CreateModel(serversModel, "server_" .. i)
+ list.servers[i].model = Engine.CreateModel(list.servers[i].root, "model")
+ end
+ list.updateModels = function(controller, list, offset)
+ local serverInfo = Engine.SteamServerBrowser_GetServerInfo(offset)
+ if serverInfo then
+ local SetModelValue = function(model, key, value)
+ local model = Engine.CreateModel(model, key)
+ if model then
+ Engine.SetModelValue(model, value)
+ end
+ end
+
+ local elementIndex = offset % list.numElementsInList + 1
+ local serverModel = list.servers[elementIndex].model
+ SetModelValue(serverModel, "serverIndex", serverInfo.serverIndex)
+ SetModelValue(serverModel, "connectAddr", serverInfo.connectAddr)
+ SetModelValue(serverModel, "ping", serverInfo.ping)
+ SetModelValue(serverModel, "modName", serverInfo.modName)
+ SetModelValue(serverModel, "mapName", serverInfo.map)
+ SetModelValue(serverModel, "desc", serverInfo.desc)
+ -- Change the client count to be the actual player count
+ local clientCount = serverInfo.playerCount - serverInfo.botCount
+ SetModelValue(serverModel, "clientCount", clientCount)
+ SetModelValue(serverModel, "maxClients", serverInfo.maxPlayers)
+ SetModelValue(serverModel, "passwordProtected", serverInfo.password)
+ SetModelValue(serverModel, "secure", serverInfo.secure)
+ SetModelValue(serverModel, "name", serverInfo.name)
+ SetModelValue(serverModel, "gameType", serverInfo.gametype)
+ SetModelValue(serverModel, "dedicated", serverInfo.dedicated)
+ SetModelValue(serverModel, "ranked", serverInfo.ranked)
+ SetModelValue(serverModel, "hardcore", serverInfo.hardcore)
+ SetModelValue(serverModel, "zombies", serverInfo.zombies)
+ -- Add the bot count
+ SetModelValue(serverModel, "botCount", serverInfo.botCount)
+ return serverModel
+ else
+ return nil
+ end
+ end
+
+ if list.serverListUpdateSubscription then
+ list:removeSubscription(list.serverListUpdateSubscription)
+ end
+ local serverListUpdateModel = Engine.CreateModel(list.serverBrowserRootModel, "serverListCount")
+ list.serverListUpdateSubscription = list:subscribeToModel(serverListUpdateModel, function(model)
+ list:updateDataSource(false, false)
+ end, false)
+ if list.serverListSortTypeSubscription then
+ list:removeSubscription(list.serverListSortTypeSubscription)
+ end
+ local serverListSortTypeModel = Engine.CreateModel(list.serverBrowserRootModel, "serverListSortType")
+ list.serverListSortTypeSubscription = list:subscribeToModel(serverListSortTypeModel, function(model)
+ list:updateDataSource(false, false)
+ end, false)
+ end,
+ getCount = function(list)
+ return list.serverCount
+ end,
+ getItem = function(controller, list, index)
+ local offset = index - 1
+ return list.updateModels(controller, list, offset)
+ end,
+ cleanup = function(list)
+ if list.serverBrowserRootModel then
+ Engine.UnsubscribeAndFreeModel(list.serverBrowserRootModel)
+ list.serverBrowserRootModel = nil
+ end
+ end
+}
+
+CoD.ServerBrowserRowInternal.new = function(menu, controller)
+ local self = LUI.UIHorizontalList.new({
+ left = 0,
+ top = 0,
+ right = 0,
+ bottom = 0,
+ leftAnchor = true,
+ topAnchor = true,
+ rightAnchor = true,
+ bottomAnchor = true,
+ spacing = 2
+ })
+ self:setAlignment(LUI.Alignment.Left)
+ if PreLoadFunc then
+ PreLoadFunc(self, controller)
+ end
+ self:setUseStencil(false)
+ self:setClass(CoD.ServerBrowserRowInternal)
+ self.id = "ServerBrowserRowInternal"
+ self.soundSet = "default"
+ self:setLeftRight(true, false, 0, 700)
+ self:setTopBottom(true, false, 0, 22)
+ self:makeFocusable()
+ self.onlyChildrenFocusable = true
+ self.anyChildUsesUpdateState = true
+
+ local passwordFlag = CoD.ServerBrowserFlag.new(menu, controller)
+ passwordFlag:setLeftRight(true, false, 0, 28)
+ passwordFlag:setTopBottom(true, true, 0, 0)
+ passwordFlag.icon:setImage(RegisterImage("uie_t7_icon_serverbrowser_protected"))
+ passwordFlag:linkToElementModel(self, nil, false, function(model)
+ passwordFlag:setModel(model, controller)
+ end)
+ passwordFlag:mergeStateConditions({
+ {
+ stateName = "FlagOn",
+ condition = function(menu, element, event)
+ return IsSelfModelValueTrue(element, controller, "passwordProtected")
+ end
+ }
+ })
+ passwordFlag:linkToElementModel(passwordFlag, "passwordProtected", true, function(model)
+ menu:updateElementState(passwordFlag, {
+ name = "model_validation",
+ menu = menu,
+ modelValue = Engine.GetModelValue(model),
+ modelName = "passwordProtected"
+ })
+ end)
+ self:addElement(passwordFlag)
+ self.passwordFlag = passwordFlag
+
+ local dedicatedFlag = CoD.ServerBrowserFlag.new(menu, controller)
+ dedicatedFlag:setLeftRight(true, false, 30, 58)
+ dedicatedFlag:setTopBottom(true, true, 0, 0)
+ dedicatedFlag.icon:setImage(RegisterImage("uie_t7_icon_serverbrowser_dedicated"))
+ dedicatedFlag:linkToElementModel(self, nil, false, function(model)
+ dedicatedFlag:setModel(model, controller)
+ end)
+ dedicatedFlag:mergeStateConditions({
+ {
+ stateName = "FlagOn",
+ condition = function(menu, element, event)
+ return IsSelfModelValueTrue(element, controller, "dedicated")
+ end
+ }
+ })
+ dedicatedFlag:linkToElementModel(dedicatedFlag, "dedicated", true, function(model)
+ menu:updateElementState(dedicatedFlag, {
+ name = "model_validation",
+ menu = menu,
+ modelValue = Engine.GetModelValue(model),
+ modelName = "dedicated"
+ })
+ end)
+ self:addElement(dedicatedFlag)
+ self.dedicatedFlag = dedicatedFlag
+
+ local rankedFlag = CoD.ServerBrowserFlag.new(menu, controller)
+ rankedFlag:setLeftRight(true, false, 60, 88)
+ rankedFlag:setTopBottom(true, true, 0, 0)
+ rankedFlag.icon:setImage(RegisterImage("uie_t7_icon_serverbrowser_ranked"))
+ rankedFlag:linkToElementModel(self, nil, false, function(model)
+ rankedFlag:setModel(model, controller)
+ end)
+ rankedFlag:mergeStateConditions({
+ {
+ stateName = "FlagOn",
+ condition = function(menu, element, event)
+ return IsSelfModelValueTrue(element, controller, "ranked")
+ end
+ }
+ })
+ rankedFlag:linkToElementModel(rankedFlag, "ranked", true, function(model)
+ menu:updateElementState(rankedFlag, {
+ name = "model_validation",
+ menu = menu,
+ modelValue = Engine.GetModelValue(model),
+ modelName = "ranked"
+ })
+ end)
+ self:addElement(rankedFlag)
+ self.rankedFlag = rankedFlag
+
+ local name = CoD.horizontalScrollingTextBox_18pt.new(menu, controller)
+ name:setLeftRight(true, false, 90, 330)
+ name:setTopBottom(true, false, 2, 20)
+ name.textBox:setTTF("fonts/default.ttf")
+ name.textBox:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_LEFT)
+ name:linkToElementModel(self, "name", true, function(model)
+ local _name = Engine.GetModelValue(model)
+ if _name then
+ name.textBox:setText(Engine.Localize(_name))
+ end
+ end)
+ self:addElement(name)
+ self.name = name
+
+ local spacer = LUI.UIFrame.new(menu, controller, 0, 0, false)
+ spacer:setLeftRight(true, false, 332, 339)
+ spacer:setTopBottom(true, false, 0, 22)
+ spacer:setAlpha(0)
+ self:addElement(spacer)
+ self.spacer = spacer
+
+ local map = CoD.horizontalScrollingTextBox_18pt.new(menu, controller)
+ map:setLeftRight(true, false, 341, 446)
+ map:setTopBottom(true, false, 2, 20)
+ map.textBox:setTTF("fonts/default.ttf")
+ map.textBox:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_LEFT)
+ map:linkToElementModel(self, "mapName", true, function(model)
+ local mapName = Engine.GetModelValue(model)
+ if mapName then
+ map.textBox:setText(MapNameToLocalizedMapName(mapName))
+ end
+ end)
+ self:addElement(map)
+ self.map = map
+
+ local hardcoreFlag = CoD.ServerBrowserFlag.new(menu, controller)
+ hardcoreFlag:setLeftRight(true, false, 448, 470)
+ hardcoreFlag:setTopBottom(true, true, 0, 0)
+ hardcoreFlag.icon:setImage(RegisterImage("uie_t7_icon_serverbrowser_skull"))
+ hardcoreFlag:linkToElementModel(self, nil, false, function(model)
+ hardcoreFlag:setModel(model, controller)
+ end)
+ hardcoreFlag:mergeStateConditions({
+ {
+ stateName = "FlagOn",
+ condition = function(menu, element, event)
+ return IsSelfModelValueTrue(element, controller, "hardcore")
+ end
+ }
+ })
+ hardcoreFlag:linkToElementModel(hardcoreFlag, "hardcore", true, function(model)
+ menu:updateElementState(hardcoreFlag, {
+ name = "model_validation",
+ menu = menu,
+ modelValue = Engine.GetModelValue(model),
+ modelName = "hardcore"
+ })
+ end)
+ self:addElement(hardcoreFlag)
+ self.hardcoreFlag = hardcoreFlag
+
+ local gametype = LUI.UIText.new()
+ gametype:setLeftRight(true, false, 472, 576)
+ gametype:setTopBottom(true, false, 2, 20)
+ gametype:setTTF("fonts/RefrigeratorDeluxe-Regular.ttf")
+ gametype:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_LEFT)
+ gametype:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_TOP)
+ gametype:linkToElementModel(self, "gameType", true, function(model)
+ local gameType = Engine.GetModelValue(model)
+ if gameType then
+ gametype:setText(Engine.Localize(GetGameTypeDisplayString(gameType)))
+ end
+ end)
+ self:addElement(gametype)
+ self.gametype = gametype
+
+ local playerCount = LUI.UIText.new()
+ playerCount:setLeftRight(true, false, 593, 613)
+ playerCount:setTopBottom(true, false, 2, 20)
+ playerCount:setTTF("fonts/RefrigeratorDeluxe-Regular.ttf")
+ playerCount:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_RIGHT)
+ playerCount:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_TOP)
+ playerCount:linkToElementModel(self, "clientCount", true, function(model)
+ local clientCount = Engine.GetModelValue(model)
+ if clientCount then
+ playerCount:setText(Engine.Localize(clientCount))
+ end
+ end)
+ self:addElement(playerCount)
+ self.playerCount = playerCount
+
+ local slash = LUI.UIText.new()
+ slash:setLeftRight(true, false, 615, 624)
+ slash:setTopBottom(true, false, 2, 20)
+ slash:setText(Engine.Localize("/"))
+ slash:setTTF("fonts/RefrigeratorDeluxe-Regular.ttf")
+ slash:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_LEFT)
+ slash:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_TOP)
+ self:addElement(slash)
+ self.slash = slash
+
+ local maxPlayers = LUI.UIText.new()
+ maxPlayers:setLeftRight(true, false, 626, 645)
+ maxPlayers:setTopBottom(true, false, 2, 20)
+ maxPlayers:setTTF("fonts/RefrigeratorDeluxe-Regular.ttf")
+ maxPlayers:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_LEFT)
+ maxPlayers:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_TOP)
+ maxPlayers:linkToElementModel(self, "maxClients", true, function(model)
+ local maxClients = Engine.GetModelValue(model)
+ if maxClients then
+ maxPlayers:setText(Engine.Localize(maxClients))
+ end
+ end)
+ self:addElement(maxPlayers)
+ self.maxPlayers = maxPlayers
+
+ local botCount = LUI.UIText.new()
+ botCount:setLeftRight(true, false, 637, 659)
+ botCount:setTopBottom(true, false, 2, 20)
+ botCount:setTTF("fonts/RefrigeratorDeluxe-Regular.ttf")
+ botCount:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_LEFT)
+ botCount:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_TOP)
+ botCount:linkToElementModel(self, "botCount", true, function(model)
+ local _botCount = Engine.GetModelValue(model)
+ if _botCount then
+ botCount:setText("[" .. Engine.Localize(_botCount) .. "]")
+ end
+ end)
+ botCount:linkToElementModel(self, "zombies", true, function(model)
+ local zombies = Engine.GetModelValue(model)
+ if zombies ~= nil then
+ botCount:setAlpha(zombies and 0 or 1)
+ end
+ end)
+ self:addElement(botCount)
+ self.botCount = botCount
+
+ local ping = LUI.UIText.new()
+ ping:setLeftRight(true, false, 661, 699.37)
+ ping:setTopBottom(true, false, 2, 20)
+ ping:setTTF("fonts/RefrigeratorDeluxe-Regular.ttf")
+ ping:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_CENTER)
+ ping:setAlignment(Enum.LUIAlignment.LUI_ALIGNMENT_TOP)
+ ping:linkToElementModel(self, "ping", true, function(model)
+ local _ping = Engine.GetModelValue(model)
+ if _ping then
+ ping:setText(Engine.Localize(_ping))
+ end
+ end)
+ self:addElement(ping)
+ self.ping = ping
+
+ spacer.id = "spacer"
+ self:registerEventHandler("gain_focus", function(self, event)
+ if self.m_focusable and self.spacer:processEvent(event) then
+ return true
+ else
+ return LUI.UIElement.gainFocus(self, event)
+ end
+ end)
+ LUI.OverrideFunction_CallOriginalSecond(self, "close", function(element)
+ element.passwordFlag:close()
+ element.dedicatedFlag:close()
+ element.rankedFlag:close()
+ element.name:close()
+ element.map:close()
+ element.hardcoreFlag:close()
+ element.gametype:close()
+ element.playerCount:close()
+ element.maxPlayers:close()
+ element.botCount:close()
+ element.ping:close()
+ end)
+
+ if PostLoadFunc then
+ PostLoadFunc(self, controller, menu)
+ end
+
+ return self
+end
diff --git a/installer/game/localappdata/T7x/data/ui_scripts/stats/__init__.lua b/installer/game/localappdata/T7x/data/ui_scripts/stats/__init__.lua
new file mode 100644
index 00000000..78f62b1d
--- /dev/null
+++ b/installer/game/localappdata/T7x/data/ui_scripts/stats/__init__.lua
@@ -0,0 +1,421 @@
+if Engine.GetCurrentMap() ~= "core_frontend" then
+ return
+end
+
+DataSources.MPStatsSettings = DataSourceHelpers.ListSetup("MPStatsSettings", function(controller)
+ local optionsTable = {}
+
+ local updateDvar = function(f1_arg0, f1_arg1, f1_arg2, dvarName, f1_arg4)
+ local oldValue = Engine.DvarInt(nil, dvarName)
+ local newValue = f1_arg1.value
+ UpdateInfoModels(f1_arg1)
+ if oldValue == newValue then
+ return
+ end
+ Engine.SetDvar(dvarName, f1_arg1.value)
+ if dvarName == "cg_unlockall_loot" then
+ Engine.SetDvar("ui_enableAllHeroes", f1_arg1.value)
+ end
+ if dvarName == "all_ee_completed" then
+ Engine.ExecNow(f1_arg0, "statsetbyname darkops_zod_ee " .. f1_arg1.value)
+ Engine.ExecNow(f1_arg0, "statsetbyname darkops_zod_super_ee " .. f1_arg1.value)
+ Engine.ExecNow(f1_arg0, "statsetbyname darkops_factory_ee " .. f1_arg1.value)
+ Engine.ExecNow(f1_arg0, "statsetbyname darkops_factory_super_ee " .. f1_arg1.value)
+ Engine.ExecNow(f1_arg0, "statsetbyname darkops_castle_ee " .. f1_arg1.value)
+ Engine.ExecNow(f1_arg0, "statsetbyname darkops_castle_super_ee " .. f1_arg1.value)
+ Engine.ExecNow(f1_arg0, "statsetbyname darkops_island_ee " .. f1_arg1.value)
+ Engine.ExecNow(f1_arg0, "statsetbyname darkops_island_super_ee " .. f1_arg1.value)
+ Engine.ExecNow(f1_arg0, "statsetbyname darkops_stalingrad_ee " .. f1_arg1.value)
+ Engine.ExecNow(f1_arg0, "statsetbyname darkops_stalingrad_super_ee " .. f1_arg1.value)
+ Engine.ExecNow(f1_arg0, "statsetbyname darkops_genesis_ee " .. f1_arg1.value)
+ Engine.ExecNow(f1_arg0, "statsetbyname DARKOPS_GENESIS_SUPER_EE " .. f1_arg1.value)
+ end
+ end
+
+ table.insert(optionsTable,
+ CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Loot",
+ "Unlocks all Black Market loot.", "MPStatsSettings_unlock_loot",
+ "cg_unlockall_loot", {
+ {
+ option = "MENU_DISABLED",
+ value = 0,
+ default = true
+ },
+ {
+ option = "MENU_ENABLED",
+ value = 1
+ },
+ }, nil, updateDvar))
+ if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
+ table.insert(optionsTable,
+ CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Purchases",
+ "All items that need to be purchased with unlock tokens are unlocked.", "MPStatsSettings_purchase_all",
+ "cg_unlockall_purchases", {
+ {
+ option = "MENU_DISABLED",
+ value = 0,
+ default = true
+ },
+ {
+ option = "MENU_ENABLED",
+ value = 1
+ },
+ }, nil, updateDvar))
+ table.insert(optionsTable,
+ CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Class Slots",
+ "Unlocks all create-a-class slots and sets.", "MPStatsSettings_unlockall_cac_slots",
+ "cg_unlockall_cac_slots", {
+ {
+ option = "MENU_DISABLED",
+ value = 0,
+ default = true
+ },
+ {
+ option = "MENU_ENABLED",
+ value = 1
+ },
+ }, nil, updateDvar))
+ end
+ table.insert(optionsTable,
+ CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock All Attachments",
+ "All attachments on weapons are unlocked.",
+ "MPStatsSettings_unlockall_attachments", "cg_unlockall_attachments", {
+ {
+ option = "MENU_DISABLED",
+ value = 0,
+ default = true
+ },
+ {
+ option = "MENU_ENABLED",
+ value = 1
+ },
+ }, nil, updateDvar))
+ table.insert(optionsTable,
+ CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock all Camos and Reticles",
+ "All camos and reticles on weapons are unlocked.", "MPStatsSettings_unlockall_camos_and_reticles",
+ "cg_unlockall_camos_and_reticles", {
+ {
+ option = "MENU_DISABLED",
+ value = 0,
+ default = true
+ },
+ {
+ option = "MENU_ENABLED",
+ value = 1
+ },
+ }, nil, updateDvar))
+ table.insert(optionsTable,
+ CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock all Calling Cards", "All calling cards are unlocked.",
+ "MPStatsSettings_unlockall_calling_cards", "cg_unlockall_calling_cards", {
+ {
+ option = "MENU_DISABLED",
+ value = 0,
+ default = true
+ },
+ {
+ option = "MENU_ENABLED",
+ value = 1
+ },
+ }, nil, updateDvar))
+ if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
+ table.insert(optionsTable,
+ CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock all Specialists Outfits",
+ "All specialists outfits are unlocked.", "MPStatsSettings_unlockall_specialists_outfits",
+ "cg_unlockall_specialists_outfits", {
+ {
+ option = "MENU_DISABLED",
+ value = 0,
+ default = true
+ },
+ {
+ option = "MENU_ENABLED",
+ value = 1
+ },
+ }, nil, updateDvar))
+ end
+ if Engine.CurrentSessionMode() == Enum.eModes.MODE_ZOMBIES then
+ table.insert(optionsTable,
+ CoD.OptionsUtility.CreateDvarSettings(controller, "Unlock Easter Eggs",
+ "Complete all Easter Egg Achievements.", "MPStatsSettings_complete_ee",
+ "all_ee_completed", {
+ {
+ option = "MENU_DISABLED",
+ value = 0,
+ default = true
+ },
+ {
+ option = "MENU_ENABLED",
+ value = 1
+ },
+ }, nil, updateDvar))
+ end
+
+ local rankLevels = {}
+ local rankObjs = {}
+ local hasDefault = true
+ local currentPrestige = CoD.PrestigeUtility.GetCurrentPLevel(controller, Engine.CurrentSessionMode())
+ local currentRank = CoD.BlackMarketUtility.GetCurrentRank(controller) + 1
+
+ local isMasterPrestige = currentPrestige == 11
+
+ if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
+ if not isMasterPrestige then
+ rankLevels = { 1, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55 }
+ else
+ rankLevels = { 56, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 }
+ end
+ elseif Engine.CurrentSessionMode() == Enum.eModes.MODE_ZOMBIES then
+ if not isMasterPrestige then
+ rankLevels = { 1, 5, 10, 15, 20, 25, 30, 35 }
+ else
+ rankLevels = { 36, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000 }
+ end
+ end
+
+ local maxlevel = math.max(table.unpack(rankLevels))
+ local minlevel = math.min(table.unpack(rankLevels))
+
+ for index, value in ipairs(rankLevels) do
+ table.insert(rankObjs, {
+ name = value <= minlevel and "Min" or value >= maxlevel and "Max" or value,
+ value = value - 1,
+ default = value == currentRank,
+ title = "Rank Level",
+ desc = value ~= currentRank and "" or "Current Rank"
+ })
+ end
+
+ if hasDefault and currentRank ~= minlevel and currentRank < maxlevel and not isMasterPrestige then
+ table.insert(rankObjs, {
+ name = "Current: " ..
+ tostring(currentRank <= minlevel and "Min" or currentRank >= maxlevel and "Max" or currentRank),
+ value = currentRank - 1,
+ default = true,
+ title = "Rank Level",
+ desc = "Do not adjust rank"
+ })
+ end
+
+ local prestigeTable = {}
+ for i = 0, 11 do
+ table.insert(prestigeTable, {
+ name = i == 0 and "None" or i == 11 and "Master" or i,
+ value = i,
+ default = i == currentPrestige,
+ title = "Prestige",
+ desc = ""
+ })
+ end
+
+ local createSettingsDatasource = function(controller, datasourceName, optionsTable, currentValue, loopEdges, action)
+ if currentValue == nil then
+ currentValue = 0
+ end
+ DataSources[datasourceName] = DataSourceHelpers.ListSetup(datasourceName, function(f47_arg0)
+ local f47_local0 = {}
+ for f47_local4, f47_local5 in ipairs(optionsTable) do
+ table.insert(f47_local0, {
+ models = {
+ text = optionsTable[f47_local4].name
+ },
+ properties = {
+ title = optionsTable[f47_local4].title,
+ desc = optionsTable[f47_local4].desc,
+ image = optionsTable[f47_local4].image,
+ value = optionsTable[f47_local4].value,
+ default = optionsTable[f47_local4].default,
+ action = action,
+ selectIndex = optionsTable[f47_local4].value == currentValue,
+ loopEdges = loopEdges,
+ showChangeIndicator = function(f48_arg0, f48_arg1, f48_arg2)
+ return f48_arg0.default ~= true
+ end
+ }
+ })
+ end
+ f47_local0[1].properties.first = true
+ f47_local0[#optionsTable].properties.last = true
+ return f47_local0
+ end, nil, nil, nil)
+ return datasourceName
+ end
+
+ table.insert(optionsTable, {
+ models = {
+ name = "Prestige",
+ desc = "",
+ image = nil,
+ optionsDatasource = createSettingsDatasource(controller, "MPStatsSettings_rank_prestige", prestigeTable,
+ CoD.PrestigeUtility.GetCurrentPLevel(controller, Engine.CurrentSessionMode()), false,
+ function(f1_arg0, f1_arg1, f1_arg2, dvarName, f1_arg4)
+ UpdateInfoModels(f1_arg1)
+ local newPrestige = f1_arg1.value
+ if newPrestige == 11 then
+ Engine.Exec(f1_arg0, "PrestigeStatsMaster " .. tostring(Engine.CurrentSessionMode()))
+ end
+ Engine.ExecNow(f1_arg0, "statsetbyname plevel " .. newPrestige)
+ Engine.ExecNow(f1_arg0, "statsetbyname hasprestiged " .. (newPrestige > 0 and 1 or 0))
+ Engine.Exec(f1_arg0, "uploadstats " .. tostring(Engine.CurrentSessionMode()))
+ end)
+ },
+ properties = {
+ revert = function(f50_arg0)
+ end
+ }
+ })
+
+ table.insert(optionsTable, {
+ models = {
+ name = "Rank Level",
+ desc = "",
+ image = nil,
+ optionsDatasource = createSettingsDatasource(controller, "MPStatsSettings_rank_level", rankObjs,
+ CoD.BlackMarketUtility.GetCurrentRank(controller), false,
+ function(f1_arg0, f1_arg1, f1_arg2, dvarName, f1_arg4)
+ UpdateInfoModels(f1_arg1)
+ local rankTable = nil
+ local rank = f1_arg1.value + 1
+ if currentPrestige <= 10 then
+ if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
+ rankTable = "gamedata/tables/mp/mp_ranktable.csv"
+ elseif Engine.CurrentSessionMode() == Enum.eModes.MODE_ZOMBIES then
+ rankTable = "gamedata/tables/zm/zm_ranktable.csv"
+ end
+ local skipLines = Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER and 3 or 2
+ local maxXp = tonumber(Engine.TableLookupGetColumnValueForRow(rankTable, rank - 2 + skipLines, 7))
+ if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
+ if maxXp ~= nil and rank == maxlevel then
+ maxXp = maxXp + 55600
+ end
+ end
+ if Engine.CurrentSessionMode() == Enum.eModes.MODE_ZOMBIES then
+ if maxXp ~= nil and rank == maxlevel then
+ maxXp = maxXp + 54244
+ end
+ end
+ if maxXp == nil then
+ maxXp = 0
+ end
+ Engine.ExecNow(f1_arg0, "statsetbyname rank " .. rank - 1)
+ Engine.ExecNow(f1_arg0, "statsetbyname rankxp " .. maxXp)
+ Engine.ExecNow(f1_arg0, "statsetbyname paragon_rankxp " .. 0)
+ else
+ if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
+ rankTable = "gamedata/tables/mp/mp_paragonranktable.csv"
+ elseif Engine.CurrentSessionMode() == Enum.eModes.MODE_ZOMBIES then
+ rankTable = "gamedata/tables/zm/zm_paragonranktable.csv"
+ end
+ local skipLines = 2
+ local maxXp = 0
+ if Engine.CurrentSessionMode() == Enum.eModes.MODE_MULTIPLAYER then
+ maxXp = tonumber(Engine.TableLookupGetColumnValueForRow(rankTable, rank - 57 + skipLines, 7))
+ if maxXp ~= nil and rank == maxlevel then
+ maxXp = maxXp + 55600
+ end
+ rank = rank - 55
+ end
+ if Engine.CurrentSessionMode() == Enum.eModes.MODE_ZOMBIES then
+ maxXp = tonumber(Engine.TableLookupGetColumnValueForRow(rankTable, rank - 37 + skipLines, 7))
+ if maxXp ~= nil and rank == maxlevel then
+ maxXp = maxXp + 54244
+ end
+ rank = rank - 35
+ end
+ if maxXp == nil then
+ maxXp = 0
+ end
+ Engine.ExecNow(f1_arg0, "statsetbyname paragon_rank " .. rank - 1)
+ Engine.ExecNow(f1_arg0, "statsetbyname paragon_rankxp " .. maxXp)
+ end
+ Engine.Exec(f1_arg0, "uploadstats " .. tostring(Engine.CurrentSessionMode()))
+
+ currentRank = rank
+ end)
+ },
+ properties = {
+ revert = function(f50_arg0)
+ end
+ }
+ })
+
+ return optionsTable
+end)
+
+if Dvar.cg_unlockall_loot:get() == true then
+ Engine.SetDvar("ui_enableAllHeroes", 1)
+end
+
+LUI.createMenu.T7xStatsMenu = function(controller)
+ local self = CoD.Menu.NewForUIEditor("T7xStatsMenu")
+ if PreLoadFunc then
+ PreLoadFunc(self, controller)
+ end
+ self.soundSet = "ChooseDecal"
+ self:setOwner(controller)
+ self:setLeftRight(true, true, 0, 0)
+ self:setTopBottom(true, true, 0, 0)
+ self:playSound("menu_open", controller)
+ self.buttonModel = Engine.CreateModel(Engine.GetModelForController(controller), "T7xStatsMenu.buttonPrompts")
+ self.anyChildUsesUpdateState = true
+
+ local GameSettingsBackground = CoD.GameSettings_Background.new(self, controller)
+ GameSettingsBackground:setLeftRight(true, true, 0, 0)
+ GameSettingsBackground:setTopBottom(true, true, 0, 0)
+ GameSettingsBackground.MenuFrame.titleLabel:setText(Engine.Localize("STATS SETTINGS"))
+ GameSettingsBackground.MenuFrame.cac3dTitleIntermediary0.FE3dTitleContainer0.MenuTitle.TextBox1.Label0:setText(
+ Engine.Localize("STATS SETTINGS"))
+ GameSettingsBackground.GameSettingsSelectedItemInfo.GameModeInfo:setAlpha(0)
+ GameSettingsBackground.GameSettingsSelectedItemInfo.GameModeName:setAlpha(0)
+ self:addElement(GameSettingsBackground)
+ self.GameSettingsBackground = GameSettingsBackground
+
+ local Options = CoD.Competitive_SettingsList.new(self, controller)
+ Options:setLeftRight(true, false, 26, 741)
+ Options:setTopBottom(true, false, 135, 720)
+ Options.Title.DescTitle:setText(Engine.Localize("Stats"))
+ Options.ButtonList:setVerticalCount(15)
+ Options.ButtonList:setDataSource("MPStatsSettings")
+ self:addElement(Options)
+ self.Options = Options
+
+ self:AddButtonCallbackFunction(self, controller, Enum.LUIButton.LUI_KEY_XBB_PSCIRCLE, nil,
+ function(element, menu, controller, model)
+ GoBack(self, controller)
+ SetPerControllerTableProperty(controller, "disableGameSettingsOptions", nil)
+ return true
+ end, function(element, menu, controller)
+ CoD.Menu.SetButtonLabel(menu, Enum.LUIButton.LUI_KEY_XBB_PSCIRCLE, "MENU_BACK")
+ return true
+ end, false)
+
+ GameSettingsBackground.MenuFrame:setModel(self.buttonModel, controller)
+ Options.id = "Options"
+
+ self:processEvent({
+ name = "menu_loaded",
+ controller = controller
+ })
+ self:processEvent({
+ name = "update_state",
+ menu = self
+ })
+ if not self:restoreState() then
+ self.Options:processEvent({
+ name = "gain_focus",
+ controller = controller
+ })
+ end
+
+ LUI.OverrideFunction_CallOriginalSecond(self, "close", function(element)
+ element.GameSettingsBackground:close()
+ element.Options:close()
+ Engine.UnsubscribeAndFreeModel(Engine.GetModel(Engine.GetModelForController(controller),
+ "T7xStatsMenu.buttonPrompts"))
+ end)
+
+ if PostLoadFunc then
+ PostLoadFunc(self, controller)
+ end
+
+ return self
+end
diff --git a/installer/game/localappdata/T7x/ext.dll b/installer/game/localappdata/T7x/ext.dll
new file mode 100644
index 00000000..839e1fae
Binary files /dev/null and b/installer/game/localappdata/T7x/ext.dll differ
diff --git a/installer/game/localappdata/cache/cache.bin b/installer/game/localappdata/cache/cache.bin
new file mode 100644
index 00000000..e69de29b
diff --git a/installer/game/localappdata/cache/data.bin b/installer/game/localappdata/cache/data.bin
new file mode 100644
index 00000000..e69de29b
diff --git a/installer/game/t7x.exe b/installer/game/t7x.exe
new file mode 100644
index 00000000..981260ca
Binary files /dev/null and b/installer/game/t7x.exe differ
diff --git a/installer/t7x_Installer.nsi b/installer/t7x_Installer.nsi
new file mode 100644
index 00000000..878b09f7
--- /dev/null
+++ b/installer/t7x_Installer.nsi
@@ -0,0 +1,132 @@
+!include "MUI2.nsh"
+!include "WinVer.nsh"
+!include "nsDialogs.nsh"
+
+; Constants
+!define PRODUCT_NAME "t7x"
+!define PRODUCT_DESCRIPTION "Call of Duty Black Ops III Client"
+!define COPYRIGHT "Created by Ahrimdon - Free and Open Source"
+!define PRODUCT_VERSION "1.0.0.0"
+!define SETUP_VERSION "1.0.0.0"
+
+; Attributes
+Name "${PRODUCT_NAME}"
+OutFile "build\t7xInstaller.exe"
+InstallDir "$EXEDIR"
+RequestExecutionLevel user ; Request user-level execution, not admin
+
+; Version Info
+VIProductVersion "${PRODUCT_VERSION}"
+VIAddVersionKey "ProductName" "${PRODUCT_NAME}"
+VIAddVersionKey "ProductVersion" "${PRODUCT_VERSION}"
+VIAddVersionKey "FileDescription" "${PRODUCT_DESCRIPTION}"
+VIAddVersionKey "LegalCopyright" "${COPYRIGHT}"
+VIAddVersionKey "FileVersion" "${SETUP_VERSION}"
+
+; Modern UI Appearance
+!define MUI_ICON "Contrib\Graphics\Icons\icon.ico"
+!define MUI_UNICON "Contrib\Graphics\Icons\icon.ico"
+!define MUI_HEADERIMAGE
+!define MUI_FINISHPAGE_NOAUTOCLOSE
+; !define MUI_FINISHPAGE_RUN "$INSTDIR\t7x.exe"
+!define MUI_FINISHPAGE_TEXT "Setup has finished installing ${PRODUCT_NAME} on your computer.$\nClick Finish to close this wizard.$\n$\nRun the t7x.exe application from within your Call of Duty Black Ops 3 game folder or use the Desktop shortcut."
+
+; Modern UI Settings
+!define MUI_ABORTWARNING
+!define MUI_UNABORTWARNING
+!define MUI_FINISHPAGE_SHOWREADME ""
+!define MUI_FINISHPAGE_SHOWREADME_CHECKED
+!define MUI_FINISHPAGE_SHOWREADME_TEXT "Create Desktop Shortcut"
+!define MUI_FINISHPAGE_SHOWREADME_FUNCTION finishpageaction
+
+; Show details by default
+ShowInstDetails show
+ShowUninstDetails show
+
+; Installer Images
+!define MUI_WELCOMEFINISHPAGE_BITMAP "Contrib\Graphics\Assets\logo-cropped.bmp"
+!define MUI_HEADERIMAGE_BITMAP "Contrib\Graphics\Assets\banner-t7x-title.bmp" ; For installer header
+
+; Uninstaller Images
+!define MUI_UNHEADERIMAGE_BITMAP "Contrib\Graphics\Assets\banner-t7x-title.bmp" ; For uninstaller header
+!define MUI_UNWELCOMEFINISHPAGE_BITMAP "Contrib\Graphics\Assets\logo-cropped.bmp" ; For uninstaller finish page
+
+; Pages
+!insertmacro MUI_PAGE_WELCOME
+; !insertmacro MUI_PAGE_LICENSE "Readme.txt"
+!insertmacro MUI_PAGE_DIRECTORY
+!insertmacro MUI_PAGE_INSTFILES
+!insertmacro MUI_PAGE_FINISH
+
+; Languages
+!insertmacro MUI_LANGUAGE "English"
+
+Function .onInit
+ MessageBox MB_OKCANCEL|MB_ICONINFORMATION "Place the installer in your Call of Duty Black Ops III game folder. Click OK to continue or Cancel to exit." IDOK done
+ Abort
+ done:
+FunctionEnd
+
+; Sections
+Section "Main Application" SecMain
+ SetOutPath $INSTDIR
+ File "game\t7x.exe"
+ File "game\base_game_dir\README.md"
+ File "game\base_game_dir\T7x_CP_Server.bat"
+ File "game\base_game_dir\T7x_MP_Server.bat"
+ File "game\base_game_dir\T7x_ZM_Server.bat"
+ WriteUninstaller "$INSTDIR\Uninstall.exe"
+SectionEnd
+
+Section "Game Directory t7x Files" SecT7xData
+ SetOutPath $INSTDIR\t7x
+ File /r "game\base_game_dir\t7x\*.*"
+SectionEnd
+
+Section "Game Directory zone Files" SecZoneData
+ SetOutPath $INSTDIR\zone
+ File /r "game\base_game_dir\zone\*.*"
+SectionEnd
+
+Section "LocalAppData Files" SecData
+ SetOutPath $LOCALAPPDATA\t7x
+ File /r "game\localappdata\t7x\*.*"
+SectionEnd
+
+Section "LocalAppData Cache Files" SecCache
+ SetOutPath $LOCALAPPDATA\cache
+ File "game\localappdata\cache\cache.bin"
+ File "game\localappdata\cache\data.bin"
+SectionEnd
+
+Function finishpageaction
+ SetOutPath $INSTDIR
+ CreateShortcut "$DESKTOP\${PRODUCT_NAME}.lnk" "$INSTDIR\t7x.exe" "" "$INSTDIR\t7x.exe"
+FunctionEnd
+
+; Uninstaller Sections
+Section "Uninstall"
+ Delete $INSTDIR\t7x.exe
+ Delete "$DESKTOP\${PRODUCT_NAME}.lnk"
+ Delete "$INSTDIR\README.md"
+ Delete "$INSTDIR\T7x_CP_Server.bat"
+ Delete "$INSTDIR\T7x_MP_Server.bat"
+ Delete "$INSTDIR\T7x_ZM_Server.bat"
+
+ Delete "$INSTDIR\zone\server.cfg"
+ Delete "$INSTDIR\zone\server_cp.cfg"
+ Delete "$INSTDIR\zone\server_zm.cfg"
+
+ Delete $LOCALAPPDATA\cache\cache.bin
+ Delete $LOCALAPPDATA\cache\data.bin
+
+ RMDir /r $INSTDIR\t7x
+ RMDir /r $LOCALAPPDATA\t7x
+
+ Delete "$INSTDIR\Uninstall.exe"
+ RMDir $INSTDIR
+SectionEnd
+
+; Create the desktop shortcut based on the checkbox state
+; Function .onInstSuccess
+; FunctionEnd
\ No newline at end of file
diff --git a/installer/tools/Bin/makensis.exe b/installer/tools/Bin/makensis.exe
new file mode 100644
index 00000000..7c6468b9
Binary files /dev/null and b/installer/tools/Bin/makensis.exe differ
diff --git a/installer/tools/Bin/zlib1.dll b/installer/tools/Bin/zlib1.dll
new file mode 100644
index 00000000..afe71c1d
Binary files /dev/null and b/installer/tools/Bin/zlib1.dll differ
diff --git a/installer/tools/Contrib/Language files/English.nlf b/installer/tools/Contrib/Language files/English.nlf
new file mode 100644
index 00000000..4568a1b5
--- /dev/null
+++ b/installer/tools/Contrib/Language files/English.nlf
@@ -0,0 +1,191 @@
+# Header, don't edit
+NLF v6
+# Start editing here
+# Language ID
+1033
+# Font and size - dash (-) means default
+-
+-
+# Codepage - dash (-) means ASCII code page
+-
+# RTL - anything else than RTL means LTR
+-
+# Translation by ..... (any credits should go here)
+# ^Branding
+t7x Installer - Free and Open Source Software
+# ^SetupCaption
+$(^Name) Setup
+# ^UninstallCaption
+$(^Name) Uninstall
+# ^LicenseSubCaption
+: License Agreement
+# ^ComponentsSubCaption
+: Installation Options
+# ^DirSubCaption
+: Installation Folder
+# ^InstallingSubCaption
+: Installing
+# ^CompletedSubCaption
+: Completed
+# ^UnComponentsSubCaption
+: Uninstallation Options
+# ^UnDirSubCaption
+: Uninstallation Folder
+# ^ConfirmSubCaption
+: Confirmation
+# ^UninstallingSubCaption
+: Uninstalling
+# ^UnCompletedSubCaption
+: Completed
+# ^BackBtn
+< &Back
+# ^NextBtn
+&Next >
+# ^AgreeBtn
+I &Agree
+# ^AcceptBtn
+I &accept the terms of the License Agreement
+# ^DontAcceptBtn
+I &do not accept the terms of the License Agreement
+# ^InstallBtn
+&Install
+# ^UninstallBtn
+&Uninstall
+# ^CancelBtn
+Cancel
+# ^CloseBtn
+&Close
+# ^BrowseBtn
+B&rowse...
+# ^ShowDetailsBtn
+Show &details
+# ^ClickNext
+Click Next to continue.
+# ^ClickInstall
+Click Install to start the installation.
+# ^ClickUninstall
+Click Uninstall to start the uninstallation.
+# ^Name
+Name
+# ^Completed
+Completed
+# ^LicenseText
+Please review the license agreement before installing $(^NameDA). If you accept all terms of the agreement, click I Agree.
+# ^LicenseTextCB
+Please review the license agreement before installing $(^NameDA). If you accept all terms of the agreement, click the check box below. $_CLICK
+# ^LicenseTextRB
+Please review the license agreement before installing $(^NameDA). If you accept all terms of the agreement, select the first option below. $_CLICK
+# ^UnLicenseText
+Please review the license agreement before uninstalling $(^NameDA). If you accept all terms of the agreement, click I Agree.
+# ^UnLicenseTextCB
+Please review the license agreement before uninstalling $(^NameDA). If you accept all terms of the agreement, click the check box below. $_CLICK
+# ^UnLicenseTextRB
+Please review the license agreement before uninstalling $(^NameDA). If you accept all terms of the agreement, select the first option below. $_CLICK
+# ^Custom
+Custom
+# ^ComponentsText
+Check the components you want to install and uncheck the components you don't want to install. $_CLICK
+# ^ComponentsSubText1
+Select the type of install:
+# ^ComponentsSubText2_NoInstTypes
+Select components to install:
+# ^ComponentsSubText2
+Or, select the optional components you wish to install:
+# ^UnComponentsText
+Check the components you want to uninstall and uncheck the components you don't want to uninstall. $_CLICK
+# ^UnComponentsSubText1
+Select the type of uninstall:
+# ^UnComponentsSubText2_NoInstTypes
+Select components to uninstall:
+# ^UnComponentsSubText2
+Or, select the optional components you wish to uninstall:
+# ^DirText
+Setup will install $(^NameDA) in the following folder. Enter the path to your Call of Duty Black Ops III game folder, or click Browse and select the game folder. $_CLICK
+# ^DirSubText
+Destination Folder
+# ^DirBrowseText
+Select the folder to install $(^NameDA) in:
+# ^UnDirText
+Setup will uninstall $(^NameDA) from the following folder. To uninstall from a different folder, click Browse and select another folder. $_CLICK
+# ^UnDirSubText
+""
+# ^UnDirBrowseText
+Select the folder to uninstall $(^NameDA) from:
+# ^SpaceAvailable
+"Space available: "
+# ^SpaceRequired
+"Space required: "
+# ^UninstallingText
+$(^NameDA) will be uninstalled from the following folder. $_CLICK
+# ^UninstallingSubText
+Uninstalling from:
+# ^FileError
+Error opening file for writing: \r\n\r\n$0\r\n\r\nClick Abort to stop the installation,\r\nRetry to try again, or\r\nIgnore to skip this file.
+# ^FileError_NoIgnore
+Error opening file for writing: \r\n\r\n$0\r\n\r\nClick Retry to try again, or\r\nCancel to stop the installation.
+# ^CantWrite
+"Can't write: "
+# ^CopyFailed
+Copy failed
+# ^CopyTo
+"Copy to "
+# ^Registering
+"Registering: "
+# ^Unregistering
+"Unregistering: "
+# ^SymbolNotFound
+"Could not find symbol: "
+# ^CouldNotLoad
+"Could not load: "
+# ^CreateFolder
+"Create folder: "
+# ^CreateShortcut
+"Create shortcut: "
+# ^CreatedUninstaller
+"Created uninstaller: "
+# ^Delete
+"Delete file: "
+# ^DeleteOnReboot
+"Delete on reboot: "
+# ^ErrorCreatingShortcut
+"Error creating shortcut: "
+# ^ErrorCreating
+"Error creating: "
+# ^ErrorDecompressing
+Error decompressing data! Corrupted installer?
+# ^ErrorRegistering
+Error registering DLL
+# ^ExecShell
+"ExecShell: "
+# ^Exec
+"Execute: "
+# ^Extract
+"Extract: "
+# ^ErrorWriting
+"Extract: error writing to file "
+# ^InvalidOpcode
+Installer corrupted: invalid opcode
+# ^NoOLE
+"No OLE for: "
+# ^OutputFolder
+"Output folder: "
+# ^RemoveFolder
+"Remove folder: "
+# ^RenameOnReboot
+"Rename on reboot: "
+# ^Rename
+"Rename: "
+# ^Skipped
+"Skipped: "
+# ^CopyDetails
+Copy Details To Clipboard
+# ^LogInstall
+Log install process
+# ^Byte
+B
+# ^Kilo
+ K
+# ^Mega
+ M
+# ^Giga
+ G
diff --git a/installer/tools/Contrib/Language files/English.nsh b/installer/tools/Contrib/Language files/English.nsh
new file mode 100644
index 00000000..eed4c5fc
--- /dev/null
+++ b/installer/tools/Contrib/Language files/English.nsh
@@ -0,0 +1,129 @@
+;Language: English (1033)
+;By Joost Verburg
+
+!insertmacro LANGFILE "English" "English" "English" "English" ; See \Include\LangFile.nsh for a description of these parameters
+
+!ifdef MUI_WELCOMEPAGE
+ ${LangFileString} MUI_TEXT_WELCOME_INFO_TITLE "Welcome to the $(^NameDA) Setup"
+ ${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "Setup will guide you through the installation of the $(^NameDA) Client for Call of Duty Black Ops III.$\r$\n$\r$\nIt is recommended that you close all other applications before installing.$\r$\n$\r$\nYou will not need to restart your computer after installation.$\r$\n$\r$\n$_CLICK"
+!endif
+
+!ifdef MUI_UNWELCOMEPAGE
+ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TITLE "$(^NameDA) Uninstaller"
+ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Setup will guide you through the uninstallation of $(^NameDA).$\r$\n$\r$\nBefore starting the uninstallation, make sure $(^NameDA) is not running.$\r$\n$\r$\n$_CLICK"
+!endif
+
+!ifdef MUI_LICENSEPAGE
+ ${LangFileString} MUI_TEXT_LICENSE_TITLE "License Agreement"
+ ${LangFileString} MUI_TEXT_LICENSE_SUBTITLE "Please review the license terms before installing $(^NameDA)."
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM "If you accept the terms of the agreement, click I Agree to continue. You must accept the agreement to install $(^NameDA)."
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM_CHECKBOX "If you accept the terms of the agreement, click the check box below. You must accept the agreement to install $(^NameDA). $_CLICK"
+ ${LangFileString} MUI_INNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS "If you accept the terms of the agreement, select the first option below. You must accept the agreement to install $(^NameDA). $_CLICK"
+!endif
+
+!ifdef MUI_UNLICENSEPAGE
+ ${LangFileString} MUI_UNTEXT_LICENSE_TITLE "License Agreement"
+ ${LangFileString} MUI_UNTEXT_LICENSE_SUBTITLE "Please review the license terms before uninstalling $(^NameDA)."
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM "If you accept the terms of the agreement, click I Agree to continue. You must accept the agreement to uninstall $(^NameDA)."
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM_CHECKBOX "If you accept the terms of the agreement, click the check box below. You must accept the agreement to uninstall $(^NameDA). $_CLICK"
+ ${LangFileString} MUI_UNINNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS "If you accept the terms of the agreement, select the first option below. You must accept the agreement to uninstall $(^NameDA). $_CLICK"
+!endif
+
+!ifdef MUI_LICENSEPAGE | MUI_UNLICENSEPAGE
+ ${LangFileString} MUI_INNERTEXT_LICENSE_TOP "Press Page Down to see the rest of the agreement."
+!endif
+
+!ifdef MUI_COMPONENTSPAGE
+ ${LangFileString} MUI_TEXT_COMPONENTS_TITLE "Choose Components"
+ ${LangFileString} MUI_TEXT_COMPONENTS_SUBTITLE "Choose which features of $(^NameDA) you want to install."
+!endif
+
+!ifdef MUI_UNCOMPONENTSPAGE
+ ${LangFileString} MUI_UNTEXT_COMPONENTS_TITLE "Choose Components"
+ ${LangFileString} MUI_UNTEXT_COMPONENTS_SUBTITLE "Choose which features of $(^NameDA) you want to uninstall."
+!endif
+
+!ifdef MUI_COMPONENTSPAGE | MUI_UNCOMPONENTSPAGE
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_TITLE "Description"
+ !ifndef NSIS_CONFIG_COMPONENTPAGE_ALTERNATIVE
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO "Position your mouse over a component to see its description."
+ !else
+ ${LangFileString} MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO "Select a component to see its description."
+ !endif
+!endif
+
+!ifdef MUI_DIRECTORYPAGE
+ ${LangFileString} MUI_TEXT_DIRECTORY_TITLE "Choose Game Location"
+ ${LangFileString} MUI_TEXT_DIRECTORY_SUBTITLE "Choose your Call of Duty Black Ops III game folder in which to install $(^NameDA)."
+!endif
+
+!ifdef MUI_UNDIRECTORYPAGE
+ ${LangFileString} MUI_UNTEXT_DIRECTORY_TITLE "Choose Uninstall Location"
+ ${LangFileString} MUI_UNTEXT_DIRECTORY_SUBTITLE "Choose the folder from which to uninstall $(^NameDA)."
+!endif
+
+!ifdef MUI_INSTFILESPAGE
+ ${LangFileString} MUI_TEXT_INSTALLING_TITLE "Installing"
+ ${LangFileString} MUI_TEXT_INSTALLING_SUBTITLE "Please wait while $(^NameDA) is being installed."
+ ${LangFileString} MUI_TEXT_FINISH_TITLE "Installation Complete"
+ ${LangFileString} MUI_TEXT_FINISH_SUBTITLE "Setup was completed successfully."
+ ${LangFileString} MUI_TEXT_ABORT_TITLE "Installation Aborted"
+ ${LangFileString} MUI_TEXT_ABORT_SUBTITLE "Setup was not completed successfully."
+!endif
+
+!ifdef MUI_UNINSTFILESPAGE
+ ${LangFileString} MUI_UNTEXT_UNINSTALLING_TITLE "Uninstalling"
+ ${LangFileString} MUI_UNTEXT_UNINSTALLING_SUBTITLE "Please wait while $(^NameDA) is being uninstalled."
+ ${LangFileString} MUI_UNTEXT_FINISH_TITLE "Uninstallation Complete"
+ ${LangFileString} MUI_UNTEXT_FINISH_SUBTITLE "Uninstall was completed successfully."
+ ${LangFileString} MUI_UNTEXT_ABORT_TITLE "Uninstallation Aborted"
+ ${LangFileString} MUI_UNTEXT_ABORT_SUBTITLE "Uninstall was not completed successfully."
+!endif
+
+!ifdef MUI_FINISHPAGE
+ ${LangFileString} MUI_TEXT_FINISH_INFO_TITLE "Completing $(^NameDA) Setup"
+ ${LangFileString} MUI_TEXT_FINISH_INFO_TEXT "$(^NameDA) has been installed on your computer.$\r$\n$\r$\nClick Finish to close Setup."
+ ${LangFileString} MUI_TEXT_FINISH_INFO_REBOOT "Your computer must be restarted in order to complete the installation of $(^NameDA). Do you want to reboot now?"
+!endif
+
+!ifdef MUI_UNFINISHPAGE
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_TITLE "Completing $(^NameDA) Uninstall"
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_TEXT "$(^NameDA) has been uninstalled from your computer.$\r$\n$\r$\nClick Finish to close Setup."
+ ${LangFileString} MUI_UNTEXT_FINISH_INFO_REBOOT "Your computer must be restarted in order to complete the uninstallation of $(^NameDA). Do you want to reboot now?"
+!endif
+
+!ifdef MUI_FINISHPAGE | MUI_UNFINISHPAGE
+ ${LangFileString} MUI_TEXT_FINISH_REBOOTNOW "Reboot now"
+ ${LangFileString} MUI_TEXT_FINISH_REBOOTLATER "I want to manually reboot later"
+ ${LangFileString} MUI_TEXT_FINISH_RUN "&Run $(^NameDA)"
+ ${LangFileString} MUI_TEXT_FINISH_SHOWREADME "&Show Readme"
+ ${LangFileString} MUI_BUTTONTEXT_FINISH "&Finish"
+!endif
+
+!ifdef MUI_STARTMENUPAGE
+ ${LangFileString} MUI_TEXT_STARTMENU_TITLE "Choose Start Menu Folder"
+ ${LangFileString} MUI_TEXT_STARTMENU_SUBTITLE "Choose a Start Menu folder for the $(^NameDA) shortcuts."
+ ${LangFileString} MUI_INNERTEXT_STARTMENU_TOP "Select the Start Menu folder in which you would like to create the program's shortcuts. You can also enter a name to create a new folder."
+ ${LangFileString} MUI_INNERTEXT_STARTMENU_CHECKBOX "Do not create shortcuts"
+!endif
+
+!ifdef MUI_UNCONFIRMPAGE
+ ${LangFileString} MUI_UNTEXT_CONFIRM_TITLE "Uninstall $(^NameDA)"
+ ${LangFileString} MUI_UNTEXT_CONFIRM_SUBTITLE "Remove $(^NameDA) from your computer."
+!endif
+
+!ifdef MUI_ABORTWARNING
+ ${LangFileString} MUI_TEXT_ABORTWARNING "Are you sure you want to quit $(^Name) Setup?"
+!endif
+
+!ifdef MUI_UNABORTWARNING
+ ${LangFileString} MUI_UNTEXT_ABORTWARNING "Are you sure you want to quit $(^Name) Uninstall?"
+!endif
+
+!ifdef MULTIUSER_INSTALLMODEPAGE
+ ${LangFileString} MULTIUSER_TEXT_INSTALLMODE_TITLE "Choose Users"
+ ${LangFileString} MULTIUSER_TEXT_INSTALLMODE_SUBTITLE "Choose for which users you want to install $(^NameDA)."
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_TOP "Select whether you want to install $(^NameDA) only for yourself or for all users of this computer. $(^ClickNext)"
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_ALLUSERS "Install for anyone using this computer"
+ ${LangFileString} MULTIUSER_INNERTEXT_INSTALLMODE_CURRENTUSER "Install just for me"
+!endif
diff --git a/installer/tools/Contrib/Modern UI 2/Deprecated.nsh b/installer/tools/Contrib/Modern UI 2/Deprecated.nsh
new file mode 100644
index 00000000..85339f2b
--- /dev/null
+++ b/installer/tools/Contrib/Modern UI 2/Deprecated.nsh
@@ -0,0 +1,86 @@
+/*
+
+NSIS Modern User Interface
+Deprecated code - display warnings
+
+*/
+
+
+!macro MUI_LEGACY_MAP_NOSTRETCH NAME R
+ !if "${R}" != ""
+ !ifdef ${NAME}NOSTRETCH
+ !define /IfNDef ${NAME}STRETCH NoStretchNoCropNoAlign
+ !endif
+ !else
+ !insertmacro ${__MACRO__} ${NAME}BITMAP_ 1
+ !insertmacro ${__MACRO__} ${NAME}BITMAP_RTL_ 1
+ !insertmacro ${__MACRO__} ${NAME}UNBITMAP_ 1
+ !insertmacro ${__MACRO__} ${NAME}UNBITMAP_RTL_ 1
+ !endif
+!macroend
+
+
+;--------------------------------
+;InstallOptions
+
+!define INSTALLOPTIONS_ERROR "MUI_INSTALLOPTIONS_* macros are no longer a part of MUI2. Include InstallOptions.nsh and use INSTALLOPTIONS_* macros instead. It is also recommended to upgrade to nsDialogs."
+
+!macro MUI_INSTALLOPTIONS_EXTRACT FILE
+
+ !error "${INSTALLOPTIONS_ERROR}"
+
+!macroend
+
+!macro MUI_INSTALLOPTIONS_EXTRACT_AS FILE FILENAME
+
+ !error "${INSTALLOPTIONS_ERROR}"
+
+!macroend
+
+!macro MUI_INSTALLOPTIONS_DISPLAY FILE
+
+ !error "${INSTALLOPTIONS_ERROR}"
+
+!macroend
+
+!macro MUI_INSTALLOPTIONS_DISPLAY_RETURN FILE
+
+ !error "${INSTALLOPTIONS_ERROR}"
+
+!macroend
+
+!macro MUI_INSTALLOPTIONS_INITDIALOG FILE
+
+ !error "${INSTALLOPTIONS_ERROR}"
+
+!macroend
+
+!macro MUI_INSTALLOPTIONS_SHOW
+
+ !error "${INSTALLOPTIONS_ERROR}"
+
+!macroend
+
+!macro MUI_INSTALLOPTIONS_SHOW_RETURN
+
+ !error "${INSTALLOPTIONS_ERROR}"
+
+!macroend
+
+!macro MUI_INSTALLOPTIONS_READ VAR FILE SECTION KEY
+
+ !error "${INSTALLOPTIONS_ERROR}"
+
+!macroend
+
+!macro MUI_INSTALLOPTIONS_WRITE FILE SECTION KEY VALUE
+
+ !error "${INSTALLOPTIONS_ERROR}"
+
+!macroend
+
+!macro MUI_RESERVEFILE_INSTALLOPTIONS
+
+ !error `MUI_RESERVEFILE_INSTALLOPTIONS is no longer supported as InstallOptions is no longer used by MUI2. Instead, use "ReserveFile /plugin InstallOptions.dll". It is also recommended to upgrade to nsDialogs.`
+
+!macroend
diff --git a/installer/tools/Contrib/Modern UI 2/Interface.nsh b/installer/tools/Contrib/Modern UI 2/Interface.nsh
new file mode 100644
index 00000000..ee858bd0
--- /dev/null
+++ b/installer/tools/Contrib/Modern UI 2/Interface.nsh
@@ -0,0 +1,363 @@
+/*
+
+NSIS Modern User Interface
+Interface code for all pages
+
+*/
+
+;--------------------------------
+;Variables
+
+Var mui.Header.Text
+Var mui.Header.Text.Font
+Var mui.Header.SubText
+Var mui.Header.Background
+Var mui.Header.Image
+
+Var mui.Branding.Text
+Var mui.Branding.Background
+
+Var mui.Line.Standard
+Var mui.Line.FullWindow
+
+Var mui.Button.Next
+Var mui.Button.Cancel
+Var mui.Button.Back
+
+
+;--------------------------------
+;General interface settings
+
+!macro MUI_INTERFACE
+
+ !ifndef MUI_INTERFACE
+
+ !define MUI_INTERFACE
+
+ ;These values are set after the interface settings in the script,
+ ;so the script itself can override all values.
+
+ ;Default interface settings in nsisconf.nsh
+ !ifdef MUI_INSERT_NSISCONF
+ !insertmacro MUI_NSISCONF
+ !endif
+
+ ;Default interface settings
+ !insertmacro MUI_DEFAULT MUI_UI "${NSISDIR}\Contrib\UIs\modern.exe"
+ !insertmacro MUI_DEFAULT MUI_UI_HEADERIMAGE "${NSISDIR}\Contrib\UIs\modern_headerbmp.exe"
+ !insertmacro MUI_DEFAULT MUI_UI_HEADERIMAGE_RIGHT "${NSISDIR}\Contrib\UIs\modern_headerbmpr.exe"
+ !insertmacro MUI_DEFAULT MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico"
+ !insertmacro MUI_DEFAULT MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico"
+ !insertmacro MUI_DEFAULT MUI_BGCOLOR "FFFFFF"
+ !insertmacro MUI_DEFAULT MUI_TEXTCOLOR "000000"
+
+ ;Map *_NOSTRETCH legacy define to the correct *_STRETCH value
+ !verbose push 2
+ !insertmacro MUI_LEGACY_MAP_NOSTRETCH MUI_HEADERIMAGE_ ""
+ !insertmacro MUI_LEGACY_MAP_NOSTRETCH MUI_WELCOMEFINISHPAGE_ ""
+ !insertmacro MUI_LEGACY_MAP_NOSTRETCH MUI_UNWELCOMEFINISHPAGE_ ""
+ !verbose pop
+
+ ;Default header images
+ !ifdef MUI_HEADERIMAGE
+
+ !insertmacro MUI_DEFAULT MUI_HEADERIMAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Header\nsis.bmp"
+ !insertmacro MUI_DEFAULT MUI_HEADERIMAGE_BITMAP_STRETCH "FitControl"
+ !insertmacro MUI_DEFAULT MUI_HEADERIMAGE_BITMAP_RTL_STRETCH ${MUI_HEADERIMAGE_BITMAP_STRETCH}
+
+ !ifndef MUI_HEADERIMAGE_UNBITMAP
+ !define MUI_HEADERIMAGE_UNBITMAP "${MUI_HEADERIMAGE_BITMAP}"
+ !insertmacro MUI_SET MUI_HEADERIMAGE_UNBITMAP_STRETCH ${MUI_HEADERIMAGE_BITMAP_STRETCH}
+ !endif
+
+ !if "${MUI_HEADERIMAGE_BITMAP}" == ""
+ !error "Invalid MUI_HEADERIMAGE_BITMAP"
+ !endif
+ !if "${MUI_HEADERIMAGE_UNBITMAP}" == ""
+ !error "Invalid MUI_HEADERIMAGE_UNBITMAP"
+ !endif
+
+ !ifdef MUI_HEADERIMAGE_BITMAP_RTL
+ !ifndef MUI_HEADERIMAGE_UNBITMAP_RTL
+ !define MUI_HEADERIMAGE_UNBITMAP_RTL "${MUI_HEADERIMAGE_BITMAP_RTL}"
+ !insertmacro MUI_SET MUI_HEADERIMAGE_UNBITMAP_RTL_STRETCH ${MUI_HEADERIMAGE_BITMAP_RTL_STRETCH}
+ !endif
+
+ !if "${MUI_HEADERIMAGE_BITMAP_RTL}" == ""
+ !error "Invalid MUI_HEADERIMAGE_BITMAP_RTL"
+ !endif
+ !if "${MUI_HEADERIMAGE_UNBITMAP_RTL}" == ""
+ !error "Invalid MUI_HEADERIMAGE_UNBITMAP_RTL"
+ !endif
+ !endif
+
+ !insertmacro MUI_DEFAULT MUI_HEADERIMAGE_UNBITMAP_STRETCH ${MUI_HEADERIMAGE_BITMAP_STRETCH}
+ !insertmacro MUI_DEFAULT MUI_HEADERIMAGE_UNBITMAP_RTL_STRETCH ${MUI_HEADERIMAGE_BITMAP_RTL_STRETCH}
+
+ !endif
+
+ ;Default texts
+ !insertmacro MUI_DEFAULT MUI_ABORTWARNING_TEXT "$(MUI_TEXT_ABORTWARNING)"
+ !insertmacro MUI_DEFAULT MUI_UNABORTWARNING_TEXT "$(MUI_UNTEXT_ABORTWARNING)"
+
+ ;Apply settings
+
+ XPStyle On ;XP style setting in manifest resource
+
+ ;Dialog resources
+ ChangeUI all "${MUI_UI}"
+ !ifdef MUI_HEADERIMAGE
+ !ifndef MUI_HEADERIMAGE_RIGHT
+ ChangeUI IDD_INST "${MUI_UI_HEADERIMAGE}"
+ !else
+ ChangeUI IDD_INST "${MUI_UI_HEADERIMAGE_RIGHT}"
+ !endif
+ !endif
+
+ ;Icons
+ Icon "${MUI_ICON}"
+ UninstallIcon "${MUI_UNICON}"
+
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Abort warning message box
+
+!macro MUI_ABORTWARNING
+
+ !ifdef MUI_ABORTWARNING_CANCEL_DEFAULT
+ MessageBox MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2 "${MUI_ABORTWARNING_TEXT}" IDYES mui.Quit
+ !else
+ MessageBox MB_YESNO|MB_ICONEXCLAMATION "${MUI_ABORTWARNING_TEXT}" IDYES mui.Quit
+ !endif
+
+ Abort
+ mui.Quit:
+
+!macroend
+
+!macro MUI_UNABORTWARNING
+
+ !ifdef MUI_UNABORTWARNING_CANCEL_DEFAULT
+ MessageBox MB_YESNO|MB_ICONEXCLAMATION|MB_DEFBUTTON2 "${MUI_UNABORTWARNING_TEXT}" IDYES mui.Quit
+ !else
+ MessageBox MB_YESNO|MB_ICONEXCLAMATION "${MUI_UNABORTWARNING_TEXT}" IDYES mui.Quit
+ !endif
+
+ Abort
+ mui.Quit:
+
+!macroend
+
+
+;--------------------------------
+;Initialization of GUI
+
+!macro MUI_HEADERIMAGE_INITHELPER_LOADIMAGEWITHMACRO MACRO
+
+ !ifdef MUI_HEADERIMAGE_RIGHT
+ !ifndef MUI_OPTIMIZE_ALWAYSLTR ; Undocumented
+ ${if} $(^RTL) == 1
+ !insertmacro ${MACRO} $mui.Header.Image "${PATH}" Left Leak
+ ${Else}
+ !insertmacro ${MACRO} $mui.Header.Image "${PATH}" Right Leak
+ ${EndIf}
+ !else
+ !insertmacro ${MACRO} $mui.Header.Image "${PATH}" Right Leak
+ !endif
+ !else
+ !insertmacro ${MACRO} $mui.Header.Image "${PATH}" Auto Leak
+ !endif
+
+!macroend
+!macro MUI_HEADERIMAGE_INITHELPER_LOADIMAGE UN RTL IMGRESID PATH
+
+ GetDlgItem $mui.Header.Image $HWNDPARENT ${IMGRESID} ; This variable is not used by every mode but we have to reference it to avoid a compiler warning.
+
+ !if "${MUI_HEADERIMAGE_${UN}BITMAP${RTL}_STRETCH}" == "NoStretchNoCropNoAlign"
+
+ SetBrandingImage /IMGID=${IMGRESID} "${PATH}"
+
+ !else if "${MUI_HEADERIMAGE_${UN}BITMAP${RTL}_STRETCH}" == "NoStretchNoCrop"
+
+ !insertmacro MUI_HEADERIMAGE_INITHELPER_LOADIMAGEWITHMACRO \
+ MUI_LOADANDXALIGNIMAGE
+
+ !else if "${MUI_HEADERIMAGE_${UN}BITMAP${RTL}_STRETCH}" == "AspectFitHeight"
+
+ !insertmacro MUI_HEADERIMAGE_INITHELPER_LOADIMAGEWITHMACRO \
+ MUI_LOADANDASPECTSTRETCHIMAGETOCONTROLHEIGHT
+
+ !else
+
+ !if "${MUI_HEADERIMAGE_${UN}BITMAP${RTL}_STRETCH}" != "FitControl"
+ !warning 'MUI_HEADERIMAGE_${UN}BITMAP${RTL}_STRETCH set to unknown value, defaulting to FitControl'
+ !endif
+ SetBrandingImage /IMGID=${IMGRESID} /RESIZETOFIT "${PATH}"
+
+ !endif
+
+!macroend
+
+!macro MUI_HEADERIMAGE_INIT UN IMGRESID
+
+ ;Load and display header image
+
+ !ifdef MUI_HEADERIMAGE
+
+ InitPluginsDir
+
+ !ifdef MUI_HEADERIMAGE_${UN}BITMAP_RTL
+ ${if} $(^RTL) == 1
+
+ File "/oname=$PLUGINSDIR\modern-header.bmp" "${MUI_HEADERIMAGE_${UN}BITMAP_RTL}"
+ !pragma verifyloadimage "${MUI_HEADERIMAGE_${UN}BITMAP_RTL}"
+ !insertmacro MUI_HEADERIMAGE_INITHELPER_LOADIMAGE "${UN}" "_RTL" ${IMGRESID} "$PLUGINSDIR\modern-header.bmp"
+
+ ${else}
+ !endif
+
+ File "/oname=$PLUGINSDIR\modern-header.bmp" "${MUI_HEADERIMAGE_${UN}BITMAP}"
+ !pragma verifyloadimage "${MUI_HEADERIMAGE_${UN}BITMAP}"
+ !insertmacro MUI_HEADERIMAGE_INITHELPER_LOADIMAGE "${UN}" "" ${IMGRESID} "$PLUGINSDIR\modern-header.bmp"
+
+ !ifdef MUI_HEADERIMAGE_${UN}BITMAP_RTL
+ ${endif}
+ !endif
+
+ !endif
+
+!macroend
+
+!macro MUI_GUIINIT_OUTERDIALOG UNINSTALLER
+
+ ;Initialize outer dialog (fonts & colors)
+
+ ;Header
+ GetDlgItem $mui.Header.Text $HWNDPARENT 1037
+ CreateFont $mui.Header.Text.Font "$(^Font)" "$(^FontSize)" "700"
+ SendMessage $mui.Header.Text ${WM_SETFONT} $mui.Header.Text.Font 0
+
+ GetDlgItem $mui.Header.SubText $HWNDPARENT 1038
+
+ !ifndef MUI_HEADER_TRANSPARENT_TEXT
+ SetCtlColors $mui.Header.Text "${MUI_TEXTCOLOR}" "${MUI_BGCOLOR}"
+ SetCtlColors $mui.Header.SubText "${MUI_TEXTCOLOR}" "${MUI_BGCOLOR}"
+ !else
+ SetCtlColors $mui.Header.Text "${MUI_TEXTCOLOR}" "transparent"
+ SetCtlColors $mui.Header.SubText "${MUI_TEXTCOLOR}" "transparent"
+ !endif
+
+ ;Header image
+ !insertmacro MUI_HEADERIMAGE_INIT "${UNINSTALLER}" 1046
+
+ ;Header background
+ GetDlgItem $mui.Header.Background $HWNDPARENT 1034
+ SetCtlColors $mui.Header.Background "" "${MUI_BGCOLOR}"
+
+ ;Header icon image background
+ !ifndef MUI_HEADERIMAGE
+ GetDlgItem $mui.Header.Image $HWNDPARENT 1039
+ SetCtlColors $mui.Header.Image "" "${MUI_BGCOLOR}"
+ !endif
+
+ ;Branding text
+ GetDlgItem $mui.Branding.Background $HWNDPARENT 1028
+ SetCtlColors $mui.Branding.Background /BRANDING
+ GetDlgItem $mui.Branding.Text $HWNDPARENT 1256
+ SetCtlColors $mui.Branding.Text /BRANDING
+ SendMessage $mui.Branding.Text ${WM_SETTEXT} 0 "STR:$(^Branding) "
+
+ ;Lines
+ GetDlgItem $mui.Line.Standard $HWNDPARENT 1035
+ GetDlgItem $mui.Line.FullWindow $HWNDPARENT 1045
+
+ ;Buttons
+ GetDlgItem $mui.Button.Next $HWNDPARENT 1
+ GetDlgItem $mui.Button.Cancel $HWNDPARENT 2
+ GetDlgItem $mui.Button.Back $HWNDPARENT 3
+
+!macroend
+
+
+;--------------------------------
+;Interface functions
+
+!macro MUI_FUNCTION_GUIINIT
+
+ Function .onGUIInit
+
+ !insertmacro MUI_GUIINIT_OUTERDIALOG ""
+
+ !ifdef MUI_PAGE_FUNCTION_GUIINIT
+ Call "${MUI_PAGE_FUNCTION_GUIINIT}"
+ !endif
+
+ !ifdef MUI_CUSTOMFUNCTION_GUIINIT
+ Call "${MUI_CUSTOMFUNCTION_GUIINIT}"
+ !endif
+
+ FunctionEnd
+
+!macroend
+
+!macro MUI_UNFUNCTION_GUIINIT
+
+ Function un.onGUIInit
+
+ !insertmacro MUI_GUIINIT_OUTERDIALOG UN
+
+ !ifdef MUI_UNPAGE_FUNCTION_GUIINIT
+ Call "${MUI_UNPAGE_FUNCTION_GUIINIT}"
+ !endif
+
+ !ifdef MUI_CUSTOMFUNCTION_UNGUIINIT
+ Call "${MUI_CUSTOMFUNCTION_UNGUIINIT}"
+ !endif
+
+ FunctionEnd
+
+!macroend
+
+!macro MUI_FUNCTION_ABORTWARNING
+
+ Function .onUserAbort
+
+ !ifdef MUI_PAGE_FUNCTION_ABORTWARNING
+ Call ${MUI_PAGE_FUNCTION_ABORTWARNING}
+ !endif
+
+ !ifdef MUI_ABORTWARNING
+ !insertmacro MUI_ABORTWARNING
+ !endif
+
+ !ifdef MUI_CUSTOMFUNCTION_ABORT
+ Call "${MUI_CUSTOMFUNCTION_ABORT}"
+ !endif
+
+ FunctionEnd
+
+!macroend
+
+!macro MUI_FUNCTION_UNABORTWARNING
+
+ Function un.onUserAbort
+
+ !ifdef MUI_UNPAGE_FUNCTION_ABORTWARNING
+ Call ${MUI_UNPAGE_FUNCTION_ABORTWARNING}
+ !endif
+
+ !ifdef MUI_UNABORTWARNING
+ !insertmacro MUI_UNABORTWARNING
+ !endif
+
+ !ifdef MUI_CUSTOMFUNCTION_UNABORT
+ Call "${MUI_CUSTOMFUNCTION_UNABORT}"
+ !endif
+
+ FunctionEnd
+
+!macroend
diff --git a/installer/tools/Contrib/Modern UI 2/Localization.nsh b/installer/tools/Contrib/Modern UI 2/Localization.nsh
new file mode 100644
index 00000000..1f02b187
--- /dev/null
+++ b/installer/tools/Contrib/Modern UI 2/Localization.nsh
@@ -0,0 +1,198 @@
+/*
+
+NSIS Modern User Interface
+Localization
+
+*/
+
+;--------------------------------
+;Variables
+
+!macro MUI_LANGDLL_VARIABLES
+
+ !ifdef MUI_LANGDLL_REGISTRY_ROOT & MUI_LANGDLL_REGISTRY_KEY & MUI_LANGDLL_REGISTRY_VALUENAME
+ !ifndef MUI_LANGDLL_REGISTRY_VARIABLES
+ !define MUI_LANGDLL_REGISTRY_VARIABLES
+
+ ;/GLOBAL because the macros are included in a function
+ Var /GLOBAL mui.LangDLL.RegistryLanguage
+
+ !endif
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Include language files
+
+!macro MUI_LANGUAGEEX LangDir NLFID
+
+ !verbose push ${MUI_VERBOSE}
+
+ !ifndef MUI_PAGE_UNINSTALLER_PREFIX
+ !ifndef MUI_DISABLE_INSERT_LANGUAGE_AFTER_PAGES_WARNING ; Define this to avoid the warning if you only have custom pages
+ !warning "MUI_LANGUAGE[EX] should be inserted after the MUI_[UN]PAGE_* macros"
+ !endif
+ !endif
+
+ !insertmacro MUI_INSERT
+
+ ;Include a language
+ LoadLanguageFile "${LangDir}\${NLFID}.nlf"
+
+ ;Include MUI language file
+ !insertmacro LANGFILE_INCLUDE_WITHDEFAULT \
+ "${LangDir}\${NLFID}.nsh" "${NSISDIR}\Contrib\Language files\English.nsh"
+
+ ;Add language to list of languages for selection dialog
+ !define /ifndef MUI_LANGDLL_LANGUAGES ""
+ !define /redef MUI_LANGDLL_LANGUAGES \
+ `"${LANGFILE_${NLFID}_LANGDLL}" "${LANG_${NLFID}}" ${MUI_LANGDLL_LANGUAGES}`
+ !define /ifndef MUI_LANGDLL_LANGUAGES_CP ""
+ !define /redef MUI_LANGDLL_LANGUAGES_CP \
+ `"${LANGFILE_${NLFID}_LANGDLL}" "${LANG_${NLFID}}" "${LANG_${NLFID}_CP}" ${MUI_LANGDLL_LANGUAGES_CP}`
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_LANGUAGE NLFID
+
+ !verbose push ${MUI_VERBOSE}
+
+ !insertmacro MUI_LANGUAGEEX "${NSISDIR}\Contrib\Language files" "${NLFID}"
+
+ !verbose pop
+
+!macroend
+
+
+;--------------------------------
+;Language selection
+
+!macro MUI_LANGDLL_DISPLAY
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !ifndef MUI_LANGDLL_LANGUAGES
+ !warning "MUI_LANGDLL_DISPLAY should only be used after inserting the MUI_LANGUAGE macro(s)"
+ !endif
+
+ !insertmacro MUI_LANGDLL_VARIABLES
+
+ !insertmacro MUI_DEFAULT MUI_LANGDLL_WINDOWTITLE "Installer Language"
+ !insertmacro MUI_DEFAULT MUI_LANGDLL_INFO "Please select a language."
+
+ !ifdef MUI_LANGDLL_REGISTRY_VARIABLES
+
+ ReadRegStr $mui.LangDLL.RegistryLanguage "${MUI_LANGDLL_REGISTRY_ROOT}" "${MUI_LANGDLL_REGISTRY_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}"
+
+ ${if} $mui.LangDLL.RegistryLanguage != ""
+ ;Set default language to registry language
+ StrCpy $LANGUAGE $mui.LangDLL.RegistryLanguage
+ ${endif}
+
+ !endif
+
+ !ifdef NSIS_CONFIG_SILENT_SUPPORT
+ ${unless} ${Silent}
+ !endif
+
+ !ifndef MUI_LANGDLL_ALWAYSSHOW
+ !ifdef MUI_LANGDLL_REGISTRY_VARIABLES
+ ${if} $mui.LangDLL.RegistryLanguage == ""
+ !endif
+ !endif
+
+ ;Show language selection dialog
+ !ifdef MUI_LANGDLL_ALLLANGUAGES
+ LangDLL::LangDialog "${MUI_LANGDLL_WINDOWTITLE}" "${MUI_LANGDLL_INFO}" A ${MUI_LANGDLL_LANGUAGES} ""
+ !else
+ LangDLL::LangDialog "${MUI_LANGDLL_WINDOWTITLE}" "${MUI_LANGDLL_INFO}" AC ${MUI_LANGDLL_LANGUAGES_CP} ""
+ !endif
+
+ Pop $LANGUAGE
+ ${if} $LANGUAGE == "cancel"
+ Abort
+ ${endif}
+
+ !ifndef MUI_LANGDLL_ALWAYSSHOW
+ !ifdef MUI_LANGDLL_REGISTRY_VARIABLES
+ ${endif}
+ !endif
+ !endif
+
+
+ !ifdef NSIS_CONFIG_SILENT_SUPPORT
+ ${endif}
+ !endif
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_LANGDLL_SAVELANGUAGE
+
+ ;Save language in registry
+
+ !ifndef MUI_PAGE_UNINSTALLER
+
+ IfAbort mui.langdllsavelanguage_abort
+
+ !ifdef MUI_LANGDLL_REGISTRY_ROOT & MUI_LANGDLL_REGISTRY_KEY & MUI_LANGDLL_REGISTRY_VALUENAME
+ WriteRegStr "${MUI_LANGDLL_REGISTRY_ROOT}" "${MUI_LANGDLL_REGISTRY_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}" $LANGUAGE
+ !endif
+
+ mui.langdllsavelanguage_abort:
+
+ !endif
+
+!macroend
+
+!macro MUI_UNGETLANGUAGE
+
+ ;Get language from registry in uninstaller
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_LANGDLL_VARIABLES
+
+ !ifdef MUI_LANGDLL_REGISTRY_ROOT & MUI_LANGDLL_REGISTRY_KEY & MUI_LANGDLL_REGISTRY_VALUENAME
+
+ ReadRegStr $mui.LangDLL.RegistryLanguage "${MUI_LANGDLL_REGISTRY_ROOT}" "${MUI_LANGDLL_REGISTRY_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}"
+
+ ${if} $mui.LangDLL.RegistryLanguage = ""
+
+ !endif
+
+ !insertmacro MUI_LANGDLL_DISPLAY
+
+ !ifdef MUI_LANGDLL_REGISTRY_ROOT & MUI_LANGDLL_REGISTRY_KEY & MUI_LANGDLL_REGISTRY_VALUENAME
+
+ ${else}
+ StrCpy $LANGUAGE $mui.LangDLL.RegistryLanguage
+ ${endif}
+
+ !endif
+
+ !verbose pop
+
+!macroend
+
+
+;--------------------------------
+;Rerserve LangDLL file
+
+!macro MUI_RESERVEFILE_LANGDLL
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ ReserveFile /plugin LangDLL.dll
+
+ !verbose pop
+
+!macroend
diff --git a/installer/tools/Contrib/Modern UI 2/MUI2.nsh b/installer/tools/Contrib/Modern UI 2/MUI2.nsh
new file mode 100644
index 00000000..94cea269
--- /dev/null
+++ b/installer/tools/Contrib/Modern UI 2/MUI2.nsh
@@ -0,0 +1,117 @@
+/*
+
+NSIS Modern User Interface - Version 2.1
+Copyright 2002-2023 Joost Verburg
+Contributors: Amir Szekely, Anders Kjersem
+
+*/
+
+!ifndef MUI_INCLUDED
+!verbose push 3
+!define MUI_INCLUDED
+!define MUI_SYSVERSION "2.1"
+!verbose pop
+!echo "NSIS Modern User Interface version ${MUI_SYSVERSION} - Copyright 2002-2023 Joost Verburg"
+
+;--------------------------------
+!verbose push 3
+!define /IfNDef MUI_VERBOSE 3
+!verbose ${MUI_VERBOSE}
+
+!addincludedir "${NSISDIR}\Contrib\Modern UI 2"
+
+;--------------------------------
+;Header files required by MUI
+
+!include WinMessages.nsh
+!include LogicLib.nsh
+!include nsDialogs.nsh
+!include LangFile.nsh
+
+
+;--------------------------------
+;Macros for compile-time defines
+
+!macro MUI_DEFAULT SYMBOL CONTENT
+
+ ;Define symbol if not yet defined
+ ;For setting default values
+
+ !ifndef "${SYMBOL}"
+ !define "${SYMBOL}" "${CONTENT}"
+ !endif
+
+!macroend
+
+!macro MUI_SET SYMBOL CONTENT
+
+ ;Define symbol and undefine if necessary
+
+ !insertmacro MUI_UNSET "${SYMBOL}"
+ !define "${SYMBOL}" "${CONTENT}"
+
+!macroend
+
+!macro MUI_UNSET SYMBOL
+
+ ;Undefine symbol if defined
+
+ !ifdef "${SYMBOL}"
+ !undef "${SYMBOL}"
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;MUI interface
+
+!include "Deprecated.nsh"
+!include "Interface.nsh"
+!include "Localization.nsh"
+!include "Pages.nsh"
+
+
+;--------------------------------
+;Pages
+
+!include "Pages\Components.nsh"
+!include "Pages\Directory.nsh"
+!include "Pages\Finish.nsh"
+!include "Pages\InstallFiles.nsh"
+!include "Pages\License.nsh"
+!include "Pages\StartMenu.nsh"
+!include "Pages\UninstallConfirm.nsh"
+!include "Pages\Welcome.nsh"
+
+
+;--------------------------------
+;Insert MUI code in script
+
+!macro MUI_INSERT
+
+ !ifndef MUI_INSERT
+ !define MUI_INSERT
+
+ ;This macro is included when the first language file is included,
+ ;after the pages.
+
+ ;Interface settings
+ !insertmacro MUI_INTERFACE
+
+ ;Interface functions - Installer
+ !insertmacro MUI_FUNCTION_GUIINIT
+ !insertmacro MUI_FUNCTION_ABORTWARNING
+
+ ;Interface functions - Uninstaller
+ !ifdef MUI_UNINSTALLER
+ !insertmacro MUI_UNFUNCTION_GUIINIT
+ !insertmacro MUI_FUNCTION_UNABORTWARNING
+ !endif
+
+ !endif
+
+!macroend
+
+!verbose pop
+!endif ;~ MUI_INCLUDED
diff --git a/installer/tools/Contrib/Modern UI 2/Pages.nsh b/installer/tools/Contrib/Modern UI 2/Pages.nsh
new file mode 100644
index 00000000..7a3c3778
--- /dev/null
+++ b/installer/tools/Contrib/Modern UI 2/Pages.nsh
@@ -0,0 +1,324 @@
+/*
+
+NSIS Modern User Interface
+Support code for all pages
+
+*/
+
+;--------------------------------
+;Page initialization
+
+!macro MUI_PAGE_INIT
+
+ !ifdef MUI_INSERT
+ !warning "MUI_PAGE_* inserted after MUI_LANGUAGE"
+ !endif
+
+ ;Include interface settings if necessary
+ !insertmacro MUI_INTERFACE
+
+ ;Define settings for installer page
+ !insertmacro MUI_UNSET MUI_PAGE_UNINSTALLER
+ !insertmacro MUI_UNSET MUI_PAGE_UNINSTALLER_PREFIX
+ !insertmacro MUI_UNSET MUI_PAGE_UNINSTALLER_FUNCPREFIX
+
+ !insertmacro MUI_SET MUI_PAGE_UNINSTALLER_PREFIX ""
+ !insertmacro MUI_SET MUI_PAGE_UNINSTALLER_FUNCPREFIX ""
+
+ ;Generate unique ID
+ !insertmacro MUI_UNSET MUI_UNIQUEID
+ !define MUI_UNIQUEID ${__LINE__}
+
+!macroend
+
+!macro MUI_UNPAGE_INIT
+
+ !ifdef MUI_INSERT
+ !warning "MUI_UNPAGE_* inserted after MUI_LANGUAGE"
+ !endif
+
+ ;Include interface settings
+ !insertmacro MUI_INTERFACE
+
+ ;Define prefixes for uninstaller page
+ !insertmacro MUI_SET MUI_UNINSTALLER ""
+
+ !insertmacro MUI_SET MUI_PAGE_UNINSTALLER ""
+ !insertmacro MUI_SET MUI_PAGE_UNINSTALLER_PREFIX "UN"
+ !insertmacro MUI_SET MUI_PAGE_UNINSTALLER_FUNCPREFIX "un."
+
+ ;Generate unique ID
+ !insertmacro MUI_UNSET MUI_UNIQUEID
+ !define MUI_UNIQUEID ${__LINE__}
+
+!macroend
+
+
+;--------------------------------
+;Header text for standard MUI page
+
+!macro MUI_HEADER_TEXT_PAGE TEXT SUBTEXT
+
+ !ifdef MUI_PAGE_HEADER_TEXT & MUI_PAGE_HEADER_SUBTEXT
+ !insertmacro MUI_HEADER_TEXT "${MUI_PAGE_HEADER_TEXT}" "${MUI_PAGE_HEADER_SUBTEXT}"
+ !else ifdef MUI_PAGE_HEADER_TEXT
+ !insertmacro MUI_HEADER_TEXT "${MUI_PAGE_HEADER_TEXT}" "${SUBTEXT}"
+ !else ifdef MUI_PAGE_HEADER_SUBTEXT
+ !insertmacro MUI_HEADER_TEXT "${TEXT}" "${MUI_PAGE_HEADER_SUBTEXT}"
+ !else
+ !insertmacro MUI_HEADER_TEXT "${TEXT}" "${SUBTEXT}"
+ !endif
+
+ !insertmacro MUI_UNSET MUI_PAGE_HEADER_TEXT
+ !insertmacro MUI_UNSET MUI_PAGE_HEADER_SUBTEXT
+
+!macroend
+
+
+;--------------------------------
+;Header text for custom page
+
+!macro MUI_HEADER_TEXT TEXT SUBTEXT ;Called from script
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !ifdef MUI_HEADER_TRANSPARENT_TEXT
+ LockWindow on
+ !endif
+
+ SendMessage $mui.Header.Text ${WM_SETTEXT} 0 "STR:${TEXT}"
+ SendMessage $mui.Header.SubText ${WM_SETTEXT} 0 "STR:${SUBTEXT}"
+
+ !ifdef MUI_HEADER_TRANSPARENT_TEXT
+ LockWindow off
+ !endif
+
+ !verbose pop
+
+!macroend
+
+
+;--------------------------------
+;Custom page functions
+
+!macro MUI_PAGE_FUNCTION_CUSTOM TYPE
+
+ !ifdef MUI_PAGE_CUSTOMFUNCTION_${TYPE}
+ Call "${MUI_PAGE_CUSTOMFUNCTION_${TYPE}}"
+ !undef MUI_PAGE_CUSTOMFUNCTION_${TYPE}
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Support for full window pages (like welcome/finish page)
+
+!macro MUI_PAGE_FUNCTION_FULLWINDOW
+
+ !ifndef MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_FULLWINDOW
+ !define MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_FULLWINDOW
+
+ Function ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}muiPageLoadFullWindow
+
+ LockWindow on
+
+ ;The branding text needs to be hidden because the full windows page
+ ;overlaps with it.
+ ShowWindow $mui.Branding.Background ${SW_HIDE}
+ ShowWindow $mui.Branding.Text ${SW_HIDE}
+
+ ;The texts need to be hidden because otherwise they may show through
+ ;the page above when the Alt key is pressed.
+ ShowWindow $mui.Header.Text ${SW_HIDE}
+ ShowWindow $mui.Header.SubText ${SW_HIDE}
+ ShowWindow $mui.Header.Image ${SW_HIDE}
+
+ ;Show line below full width of page
+ ShowWindow $mui.Line.Standard ${SW_HIDE}
+ ShowWindow $mui.Line.FullWindow ${SW_NORMAL}
+
+ LockWindow off
+
+ FunctionEnd
+
+ Function ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}muiPageUnloadFullWindow
+
+ ;Set everything back to normal again
+
+ LockWindow on
+
+ ShowWindow $mui.Branding.Background ${SW_NORMAL}
+ ShowWindow $mui.Branding.Text ${SW_NORMAL}
+
+ ShowWindow $mui.Header.Text ${SW_NORMAL}
+ ShowWindow $mui.Header.SubText ${SW_NORMAL}
+ ShowWindow $mui.Header.Image ${SW_NORMAL}
+
+ ShowWindow $mui.Line.Standard ${SW_NORMAL}
+ ShowWindow $mui.Line.FullWindow ${SW_HIDE}
+
+ LockWindow off
+
+ FunctionEnd
+
+ !endif
+
+!macroend
+
+!macro MUI_INTERNAL_FULLWINDOW_LOADWIZARDIMAGE _un _hwndImg _ImgPath _RetImgHandle
+
+ !ifdef MUI_${_un}WELCOMEFINISHPAGE_BITMAP_NOSTRETCH
+ !insertmacro MUI_DEFAULT MUI_${_un}WELCOMEFINISHPAGE_BITMAP_STRETCH NoStretchNoCropNoAlign ; Legacy compatibility
+ !endif
+ !insertmacro MUI_DEFAULT MUI_${_un}WELCOMEFINISHPAGE_BITMAP_STRETCH FitControl
+
+ !if "${MUI_${_un}WELCOMEFINISHPAGE_BITMAP_STRETCH}" == "NoStretchNoCropNoAlign"
+
+ ${NSD_SetImage} ${_hwndImg} "${_ImgPath}" "${_RetImgHandle}"
+
+ !else if "${MUI_${_un}WELCOMEFINISHPAGE_BITMAP_STRETCH}" == "NoStretchNoCrop"
+
+ !insertmacro MUI_LOADANDXALIGNIMAGE ${_hwndImg} "${_ImgPath}" Auto "${_RetImgHandle}"
+
+ !else if "${MUI_${_un}WELCOMEFINISHPAGE_BITMAP_STRETCH}" == "AspectFitHeight"
+
+ !insertmacro MUI_LOADANDASPECTSTRETCHIMAGETOCONTROLHEIGHT ${_hwndImg} "${_ImgPath}" Auto "${_RetImgHandle}"
+
+ !else
+
+ !if "${MUI_${_un}WELCOMEFINISHPAGE_BITMAP_STRETCH}" != "FitControl"
+ !warning 'MUI_${_un}WELCOMEFINISHPAGE_BITMAP_STRETCH set to unknown value, defaulting to FitControl'
+ !endif
+ ${NSD_SetStretchedImage} ${_hwndImg} "${_ImgPath}" "${_RetImgHandle}"
+
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Helper macros
+
+!include Util.nsh
+
+!macro MUI_INTERNAL_LOADANDSIZEIMAGE _macro _hwndImg _ImgPath _XAlign _RetImgHandle
+ !if "${_XAlign}" == "Auto"
+ ${if} $(^RTL) == 1
+ Push "*${_ImgPath}"
+ ${Else}
+ Push "${_ImgPath}"
+ ${EndIf}
+ !else if "${_XAlign}" == "Right"
+ Push "*${_ImgPath}"
+ !else
+ Push "${_ImgPath}"
+ !endif
+ Push "${_hwndImg}"
+ ${CallArtificialFunction} ${_macro}
+ !if "${_RetImgHandle}" == "Leak"
+ !insertmacro _LOGICLIB_TEMP
+ Pop $_LOGICLIB_TEMP
+ !else if "${_RetImgHandle}" != "Stack"
+ Pop ${_RetImgHandle}
+ !endif
+!macroend
+
+!macro MUI_LOADANDXALIGNIMAGE _hwndImg _ImgPath _XAlign _RetImgHandle
+!insertmacro MUI_INTERNAL_LOADANDSIZEIMAGE \
+ MUI_INTERNAL_LOADANDXALIGNIMAGE "${_hwndImg}" "${_ImgPath}" "${_XAlign}" "${_RetImgHandle}"
+!macroend
+!macro MUI_INTERNAL_LOADANDXALIGNIMAGE
+ System::Store "S"
+ System::Call 'USER32::GetWindowRect(psr0,@r1)'
+ System::Call 'USER32::MapWindowPoints(p0,p$hwndparent,pr1,i2)' ; Note: Assuming control is not in inner dialog
+ System::Call '*$1(i.r5,i.r6,i.r7,i.r8)'
+ IntOp $7 $7 - $5
+ IntOp $8 $8 - $6
+
+ Pop $1
+ StrCpy $3 $1 1
+ ${If} $3 == "*" ; Move control to the right?
+ StrCpy $1 $1 "" 1
+ ${Endif}
+ System::Call 'USER32::LoadImage(p0,tr1,i${IMAGE_BITMAP},i0,i0,i${LR_LOADFROMFILE})p.r2'
+ SendMessage $0 ${STM_SETIMAGE} ${IMAGE_BITMAP} $2 $1
+ Push $2 ; Return value
+ System::Call 'GDI32::DeleteObject(pr1)' ; Note: Assuming the previous image (if any) was a bitmap
+ System::Call 'USER32::GetClientRect(pr0,@r1)'
+ System::Call '*$1(i,i,i.r1,i.r2)'
+
+ ${If} $3 == "*"
+ ${AndIf} $1 < $7 ; ImgW < CtlW
+ IntOp $3 $7 - $1
+ IntOp $5 $5 + $3
+ System::Call 'USER32::SetWindowPos(pr0,p0,ir5,ir6,i,i,i0x15)'
+ ${EndIf}
+
+ System::Store "L"
+!macroend
+
+!macro MUI_LOADANDASPECTSTRETCHIMAGETOCONTROLHEIGHT _hwndImg _ImgPath _XAlign _RetImgHandle
+!insertmacro MUI_INTERNAL_LOADANDSIZEIMAGE \
+ MUI_INTERNAL_LOADANDASPECTSTRETCHIMAGETOCONTROLHEIGHT "${_hwndImg}" "${_ImgPath}" "${_XAlign}" "${_RetImgHandle}"
+!macroend
+!macro MUI_INTERNAL_LOADANDASPECTSTRETCHIMAGETOCONTROLHEIGHT
+ System::Store "S"
+ System::Call 'USER32::GetWindowRect(psr0,@r1)'
+ System::Call 'USER32::MapWindowPoints(p0,p$hwndparent,pr1,i2)' ; Note: Assuming control is not in inner dialog
+ System::Call '*$1(i.r5,i.r6,i.r7,i.r8)'
+ IntOp $7 $7 - $5
+ IntOp $8 $8 - $6
+
+ Pop $1
+ StrCpy $3 $1 1
+ ${If} $3 == "*" ; Move control to the right?
+ StrCpy $1 $1 "" 1
+ ${Endif}
+ System::Call 'USER32::LoadImage(p0,tr1,i${IMAGE_BITMAP},i0,i0,i${LR_LOADFROMFILE})p.r2'
+ SendMessage $0 ${STM_SETIMAGE} ${IMAGE_BITMAP} $2 $1
+ Push $2 ; Return value
+ System::Call 'GDI32::DeleteObject(pr1)' ; Note: Assuming the previous image (if any) was a bitmap
+ System::Call 'USER32::GetClientRect(pr0,@r1)'
+ System::Call '*$1(i,i,i.r1,i.r2)'
+
+ IntOp $R7 $7 * 10000
+ IntOp $R8 $8 * 10000
+ IntOp $R1 $1 * 10000
+ IntOp $R2 $2 * 10000
+ IntOp $R3 $R1 / $2
+ StrCpy $R4 10000
+ ${If} $R1 > $R2
+ StrCpy $R3 10000
+ IntOp $R4 $R2 / $1
+ ${EndIf}
+
+ ${DoWhile} $R2 > $R8 ; ImgH > CtlH
+ IntOp $R1 $R1 - $R3
+ IntOp $R2 $R2 - $R4
+ ${Loop}
+ ${DoWhile} $R2 < $R8 ; ImgH < CtlH
+ IntOp $R1 $R1 + $R3
+ IntOp $R2 $R2 + $R4
+ ${Loop}
+ IntOp $1 $R1 / 10000
+ IntOp $2 $R2 / 10000
+
+ ${If} $1 < $7
+ ${AndIf} $3 == "*"
+ IntOp $R3 $7 - $1
+ IntOp $5 $5 + $R3
+ ${EndIf}
+
+ ${DoWhile} $2 > $8 ; Non-aspect-maintained stretch to make it a pixel perfect match
+ IntOp $2 $2 - 1
+ IntOp $1 $1 - 1
+ ${IfThen} $3 == "*" ${|} IntOp $5 $5 + 1 ${|}
+ ${Loop}
+
+ System::Call 'USER32::SetWindowPos(pr0,p0,ir5,ir6,ir1,ir2,i0x14)'
+ System::Store "L"
+!macroend
+
+
diff --git a/installer/tools/Contrib/Modern UI 2/Pages/Components.nsh b/installer/tools/Contrib/Modern UI 2/Pages/Components.nsh
new file mode 100644
index 00000000..5003e5ef
--- /dev/null
+++ b/installer/tools/Contrib/Modern UI 2/Pages/Components.nsh
@@ -0,0 +1,242 @@
+/*
+
+NSIS Modern User Interface
+Components page
+
+*/
+
+;--------------------------------
+;Page interface settings and variables
+
+!macro MUI_COMPONENTSPAGE_INTERFACE
+
+ !ifndef MUI_COMPONENTSPAGE_INTERFACE
+ !define MUI_COMPONENTSPAGE_INTERFACE
+ Var mui.ComponentsPage
+
+ Var mui.ComponentsPage.Text
+ Var mui.ComponentsPage.InstTypesText
+ Var mui.ComponentsPage.ComponentsText
+
+ Var mui.ComponentsPage.InstTypes
+ Var mui.ComponentsPage.Components
+
+ Var mui.ComponentsPage.DescriptionTitle
+ Var mui.ComponentsPage.DescriptionText.Info
+ Var mui.ComponentsPage.DescriptionText
+
+ Var mui.ComponentsPage.SpaceRequired
+
+ !insertmacro MUI_DEFAULT MUI_COMPONENTSPAGE_CHECKBITMAP "${NSISDIR}\Contrib\Graphics\Checks\modern.bmp"
+
+ !insertmacro MUI_DEFAULT MUI_UI_COMPONENTSPAGE_SMALLDESC "${NSISDIR}\Contrib\UIs\modern_smalldesc.exe"
+ !insertmacro MUI_DEFAULT MUI_UI_COMPONENTSPAGE_NODESC "${NSISDIR}\Contrib\UIs\modern_nodesc.exe"
+
+ ;Apply settings
+
+ !ifdef MUI_COMPONENTSPAGE_SMALLDESC
+ ChangeUI IDD_SELCOM "${MUI_UI_COMPONENTSPAGE_SMALLDESC}"
+ !else ifdef MUI_COMPONENTSPAGE_NODESC
+ ChangeUI IDD_SELCOM "${MUI_UI_COMPONENTSPAGE_NODESC}"
+ !endif
+
+ CheckBitmap "${MUI_COMPONENTSPAGE_CHECKBITMAP}"
+
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Page declaration
+
+!macro MUI_PAGEDECLARATION_COMPONENTS
+
+ !insertmacro MUI_SET MUI_${MUI_PAGE_UNINSTALLER_PREFIX}COMPONENTSPAGE ""
+ !insertmacro MUI_COMPONENTSPAGE_INTERFACE
+
+ !insertmacro MUI_DEFAULT MUI_COMPONENTSPAGE_TEXT_TOP ""
+ !insertmacro MUI_DEFAULT MUI_COMPONENTSPAGE_TEXT_COMPLIST ""
+ !insertmacro MUI_DEFAULT MUI_COMPONENTSPAGE_TEXT_INSTTYPE ""
+ !insertmacro MUI_DEFAULT MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_TITLE "$(MUI_INNERTEXT_COMPONENTS_DESCRIPTION_TITLE)"
+ !insertmacro MUI_DEFAULT MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_INFO "$(MUI_INNERTEXT_COMPONENTS_DESCRIPTION_INFO)"
+
+ PageEx ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}components
+
+ PageCallbacks ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.ComponentsPre_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.ComponentsShow_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.ComponentsLeave_${MUI_UNIQUEID}
+
+ Caption " "
+
+ ComponentText "${MUI_COMPONENTSPAGE_TEXT_TOP}" "${MUI_COMPONENTSPAGE_TEXT_INSTTYPE}" "${MUI_COMPONENTSPAGE_TEXT_COMPLIST}"
+
+ PageExEnd
+
+ !insertmacro MUI_FUNCTION_COMPONENTSPAGE ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.ComponentsPre_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.ComponentsShow_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.ComponentsLeave_${MUI_UNIQUEID}
+
+ !undef MUI_COMPONENTSPAGE_TEXT_TOP
+ !undef MUI_COMPONENTSPAGE_TEXT_COMPLIST
+ !undef MUI_COMPONENTSPAGE_TEXT_INSTTYPE
+ !insertmacro MUI_UNSET MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_TITLE
+ !insertmacro MUI_UNSET MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_INFO
+
+!macroend
+
+!macro MUI_PAGE_COMPONENTS
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_PAGE_INIT
+ !insertmacro MUI_PAGEDECLARATION_COMPONENTS
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_UNPAGE_COMPONENTS
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_UNPAGE_INIT
+ !insertmacro MUI_PAGEDECLARATION_COMPONENTS
+
+ !verbose pop
+
+!macroend
+
+
+;--------------------------------
+;Page functions
+
+!macro MUI_FUNCTION_COMPONENTSPAGE PRE SHOW LEAVE
+
+ Function "${PRE}"
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM PRE
+ !insertmacro MUI_HEADER_TEXT_PAGE $(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_COMPONENTS_TITLE) $(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_COMPONENTS_SUBTITLE)
+ FunctionEnd
+
+ Function "${SHOW}"
+
+ ;Get control handles
+ FindWindow $mui.ComponentsPage "#32770" "" $HWNDPARENT
+ GetDlgItem $mui.ComponentsPage.Text $mui.ComponentsPage 1006
+ GetDlgItem $mui.ComponentsPage.InstTypesText $mui.ComponentsPage 1021
+ GetDlgItem $mui.ComponentsPage.ComponentsText $mui.ComponentsPage 1022
+ GetDlgItem $mui.ComponentsPage.InstTypes $mui.ComponentsPage 1017
+ GetDlgItem $mui.ComponentsPage.Components $mui.ComponentsPage 1032
+ GetDlgItem $mui.ComponentsPage.DescriptionTitle $mui.ComponentsPage 1042
+ GetDlgItem $mui.ComponentsPage.DescriptionText $mui.ComponentsPage 1043
+ GetDlgItem $mui.ComponentsPage.SpaceRequired $mui.ComponentsPage 1023
+
+ ;Default text in description textbox
+ SendMessage $mui.ComponentsPage.DescriptionTitle ${WM_SETTEXT} 0 "STR:${MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_TITLE}"
+ EnableWindow $mui.ComponentsPage.DescriptionText 0
+ SendMessage $mui.ComponentsPage.DescriptionText ${WM_SETTEXT} 0 "STR:${MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_INFO}"
+
+ StrCpy $mui.ComponentsPage.DescriptionText.Info "${MUI_COMPONENTSPAGE_TEXT_DESCRIPTION_INFO}" ;Text for current components page
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM SHOW
+
+ FunctionEnd
+
+ Function "${LEAVE}"
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM LEAVE
+
+ FunctionEnd
+
+!macroend
+
+
+;--------------------------------
+;Script functions for components descriptions
+
+!macro MUI_DESCRIPTION_BEGIN
+
+ ${if} $0 == -1
+ ;No mouse hover over component in list
+ SendMessage $mui.ComponentsPage.DescriptionText ${WM_SETTEXT} 0 "STR:"
+ EnableWindow $mui.ComponentsPage.DescriptionText 0
+ SendMessage $mui.ComponentsPage.DescriptionText ${WM_SETTEXT} 0 "STR:$mui.ComponentsPage.DescriptionText.Info"
+
+!macroend
+
+!macro MUI_DESCRIPTION_TEXT VAR TEXT
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ ${elseif} $0 == ${VAR}
+ SendMessage $mui.ComponentsPage.DescriptionText ${WM_SETTEXT} 0 "STR:"
+ EnableWindow $mui.ComponentsPage.DescriptionText 1
+ SendMessage $mui.ComponentsPage.DescriptionText ${WM_SETTEXT} 0 "STR:${TEXT}"
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_DESCRIPTION_END
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ ${endif}
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_FUNCTION_DESCRIPTION_BEGIN
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ Function .onMouseOverSection
+ !insertmacro MUI_DESCRIPTION_BEGIN
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_FUNCTION_DESCRIPTION_END
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_DESCRIPTION_END
+ !ifdef MUI_CUSTOMFUNCTION_ONMOUSEOVERSECTION
+ Call "${MUI_CUSTOMFUNCTION_ONMOUSEOVERSECTION}"
+ !endif
+ FunctionEnd
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_UNFUNCTION_DESCRIPTION_BEGIN
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ Function un.onMouseOverSection
+ !insertmacro MUI_DESCRIPTION_BEGIN
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_UNFUNCTION_DESCRIPTION_END
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_DESCRIPTION_END
+ !ifdef MUI_CUSTOMFUNCTION_UNONMOUSEOVERSECTION
+ Call "${MUI_CUSTOMFUNCTION_UNONMOUSEOVERSECTION}"
+ !endif
+ FunctionEnd
+
+ !verbose pop
+
+!macroend
diff --git a/installer/tools/Contrib/Modern UI 2/Pages/Directory.nsh b/installer/tools/Contrib/Modern UI 2/Pages/Directory.nsh
new file mode 100644
index 00000000..62093571
--- /dev/null
+++ b/installer/tools/Contrib/Modern UI 2/Pages/Directory.nsh
@@ -0,0 +1,126 @@
+/*
+
+NSIS Modern User Interface
+Directory page
+
+*/
+
+;--------------------------------
+;Page interface settings and variables
+
+!macro MUI_DIRECTORYPAGE_INTERFACE
+
+ !ifndef MUI_DIRECTORYPAGE_INTERFACE
+ !define MUI_DIRECTORYPAGE_INTERFACE
+ Var mui.DirectoryPage
+
+ Var mui.DirectoryPage.Text
+
+ Var mui.DirectoryPage.DirectoryBox
+ Var mui.DirectoryPage.Directory
+ Var mui.DirectoryPage.BrowseButton
+
+ Var mui.DirectoryPage.SpaceRequired
+ Var mui.DirectoryPage.SpaceAvailable
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Page declaration
+
+!macro MUI_PAGEDECLARATION_DIRECTORY
+
+ !insertmacro MUI_SET MUI_${MUI_PAGE_UNINSTALLER_PREFIX}DIRECTORYPAGE ""
+ !insertmacro MUI_DIRECTORYPAGE_INTERFACE
+
+ !insertmacro MUI_DEFAULT MUI_DIRECTORYPAGE_TEXT_TOP ""
+ !insertmacro MUI_DEFAULT MUI_DIRECTORYPAGE_TEXT_DESTINATION ""
+
+ PageEx ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}directory
+
+ PageCallbacks ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.DirectoryPre_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.DirectoryShow_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.DirectoryLeave_${MUI_UNIQUEID}
+
+ Caption " "
+
+ DirText "${MUI_DIRECTORYPAGE_TEXT_TOP}" "${MUI_DIRECTORYPAGE_TEXT_DESTINATION}"
+
+ !ifdef MUI_DIRECTORYPAGE_VARIABLE
+ DirVar "${MUI_DIRECTORYPAGE_VARIABLE}"
+ !endif
+
+ !ifdef MUI_DIRECTORYPAGE_VERIFYONLEAVE
+ DirVerify leave
+ !endif
+
+ PageExEnd
+
+ !insertmacro MUI_FUNCTION_DIRECTORYPAGE ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.DirectoryPre_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.DirectoryShow_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.DirectoryLeave_${MUI_UNIQUEID}
+
+ !undef MUI_DIRECTORYPAGE_TEXT_TOP
+ !undef MUI_DIRECTORYPAGE_TEXT_DESTINATION
+ !insertmacro MUI_UNSET MUI_DIRECTORYPAGE_VARIABLE
+ !insertmacro MUI_UNSET MUI_DIRECTORYPAGE_VERIFYONLEAVE
+
+!macroend
+
+!macro MUI_PAGE_DIRECTORY
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_PAGE_INIT
+ !insertmacro MUI_PAGEDECLARATION_DIRECTORY
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_UNPAGE_DIRECTORY
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_UNPAGE_INIT
+ !insertmacro MUI_PAGEDECLARATION_DIRECTORY
+
+ !verbose pop
+
+!macroend
+
+
+;--------------------------------
+;Page functions
+
+!macro MUI_FUNCTION_DIRECTORYPAGE PRE SHOW LEAVE
+
+ Function "${PRE}"
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM PRE
+ !insertmacro MUI_HEADER_TEXT_PAGE $(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_DIRECTORY_TITLE) $(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_DIRECTORY_SUBTITLE)
+ FunctionEnd
+
+ Function "${SHOW}"
+
+ ;Get control handles
+ FindWindow $mui.DirectoryPage "#32770" "" $HWNDPARENT
+ GetDlgItem $mui.DirectoryPage.Text $mui.DirectoryPage 1006
+ GetDlgItem $mui.DirectoryPage.DirectoryBox $mui.DirectoryPage 1020
+ GetDlgItem $mui.DirectoryPage.Directory $mui.DirectoryPage 1019
+ GetDlgItem $mui.DirectoryPage.BrowseButton $mui.DirectoryPage 1001
+ GetDlgItem $mui.DirectoryPage.SpaceRequired $mui.DirectoryPage 1023
+ GetDlgItem $mui.DirectoryPage.SpaceAvailable $mui.DirectoryPage 1024
+
+ !ifdef MUI_DIRECTORYPAGE_BGCOLOR
+ !insertmacro MUI_DEFAULT MUI_DIRECTORYPAGE_TEXTCOLOR ""
+ SetCtlColors $mui.DirectoryPage.Directory "${MUI_DIRECTORYPAGE_TEXTCOLOR}" "${MUI_DIRECTORYPAGE_BGCOLOR}"
+ !endif
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM SHOW
+ FunctionEnd
+
+ Function "${LEAVE}"
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM LEAVE
+ FunctionEnd
+
+!macroend
diff --git a/installer/tools/Contrib/Modern UI 2/Pages/Finish.nsh b/installer/tools/Contrib/Modern UI 2/Pages/Finish.nsh
new file mode 100644
index 00000000..493c1e06
--- /dev/null
+++ b/installer/tools/Contrib/Modern UI 2/Pages/Finish.nsh
@@ -0,0 +1,510 @@
+ /*
+
+NSIS Modern User Interface
+Finish page (implemented using nsDialogs)
+
+*/
+
+;--------------------------------
+;Page interface settings and variables
+
+!macro MUI_FINISHPAGE_INTERFACE
+
+ !ifndef MUI_FINISHPAGE_INTERFACE
+ !define MUI_FINISHPAGE_INTERFACE
+ Var mui.FinishPage
+
+ Var mui.FinishPage.Image
+ Var mui.FinishPage.Image.Bitmap
+
+ Var mui.FinishPage.Title
+ Var mui.FinishPage.Title.Font
+
+ Var mui.FinishPage.Text
+ !endif
+
+ !ifndef MUI_FINISHPAGE_NOREBOOTSUPPORT
+ !ifndef MUI_FINISHPAGE_RETURNVALUE_VARIABLES
+ !define MUI_FINISHPAGE_RETURNVALUE_VARIABLES
+ Var mui.FinishPage.ReturnValue
+ !endif
+ !else ifdef MUI_FINISHPAGE_RUN | MUI_FINISHPAGE_SHOWREADME
+ !ifndef MUI_FINISHPAGE_RETURNVALUE_VARIABLES
+ !define MUI_FINISHPAGE_RETURNVALUE_VARIABLES
+ Var mui.FinishPage.ReturnValue
+ !endif
+ !endif
+
+ !ifdef MUI_FINISHPAGE_CANCEL_ENABLED
+ !ifndef MUI_FINISHPAGE_CANCEL_ENABLED_VARIABLES
+ !define MUI_FINISHPAGE_CANCEL_ENABLED_VARIABLES
+ Var mui.FinishPage.DisableAbortWarning
+ !endif
+ !endif
+
+ !ifdef MUI_FINISHPAGE_RUN
+ !ifndef MUI_FINISHPAGE_RUN_VARIABLES
+ !define MUI_FINISHPAGE_RUN_VARIABLES
+ Var mui.FinishPage.Run
+ !endif
+ !endif
+
+ !ifdef MUI_FINISHPAGE_SHOWREADME
+ !ifndef MUI_FINISHPAGE_SHOWREADME_VARIABLES
+ !define MUI_FINISHPAGE_SHOWREADME_VARIABLES
+ Var mui.FinishPage.ShowReadme
+ !endif
+ !endif
+
+ !ifdef MUI_FINISHPAGE_LINK
+ !ifndef MUI_FINISHPAGE_LINK_VARIABLES
+ !define MUI_FINISHPAGE_LINK_VARIABLES
+ Var mui.FinishPage.Link
+ !endif
+ !endif
+
+ !ifndef MUI_FINISHPAGE_NOREBOOTSUPPORT
+ !ifndef MUI_FINISHPAGE_REBOOT_VARIABLES
+ !define MUI_FINISHPAGE_REBOOT_VARIABLES
+ Var mui.FinishPage.RebootNow
+ Var mui.FinishPage.RebootLater
+ !endif
+ !endif
+
+ !insertmacro MUI_DEFAULT MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\win.bmp"
+ !if "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP}" == ""
+ !error "Invalid MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP"
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Interface initialization
+
+!macro MUI_FINISHPAGE_GUIINIT
+
+ !ifndef MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_GUINIT
+ !define MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_GUINIT
+
+ Function ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.FinishPage.GUIInit
+
+ InitPluginsDir
+ File "/oname=$PLUGINSDIR\modern-wizard.bmp" "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP}"
+ !pragma verifyloadimage "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP}"
+
+ !ifdef MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_GUIINIT
+ Call "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_GUIINIT}"
+ !endif
+
+ !ifndef MUI_${MUI_PAGE_UNINSTALLER_PREFIX}FINISHPAGE_NOAUTOCLOSE
+ SetAutoClose true
+ !endif
+
+ FunctionEnd
+
+ !insertmacro MUI_SET MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_GUIINIT ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.FinishPage.GUIInit
+
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Abort warning
+
+!macro MUI_FINISHPAGE_ABORTWARNING
+
+ !ifdef MUI_FINISHPAGE_CANCEL_ENABLED
+
+ !ifndef MUI_${MUI_PAGE_UNINSTALLER_PREFIX}FINISHPAGE_ABORTWARNING
+ !define MUI_${MUI_PAGE_UNINSTALLER_PREFIX}FINISHPAGE_ABORTWARNING
+
+ Function ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.FinishPage.AbortWarning
+
+ ${if} $mui.FinishPage.DisableAbortWarning == "1"
+ Quit
+ ${endif}
+
+ !ifdef MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_ABORTWARNING
+ Call ${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_ABORTWARNING}
+ !endif
+
+ FunctionEnd
+
+ !insertmacro MUI_SET MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_ABORTWARNING ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.FinishPage.AbortWarning
+
+ !endif
+
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Page declaration
+
+!macro MUI_PAGEDECLARATION_FINISH
+
+ !insertmacro MUI_SET MUI_${MUI_PAGE_UNINSTALLER_PREFIX}FINISHPAGE ""
+ !insertmacro MUI_FINISHPAGE_INTERFACE
+
+ !insertmacro MUI_FINISHPAGE_GUIINIT
+ !insertmacro MUI_FINISHPAGE_ABORTWARNING
+
+ !insertmacro MUI_DEFAULT MUI_FINISHPAGE_TITLE "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_FINISH_INFO_TITLE)"
+ !insertmacro MUI_DEFAULT MUI_FINISHPAGE_TEXT "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_FINISH_INFO_TEXT)"
+ !insertmacro MUI_DEFAULT MUI_FINISHPAGE_BUTTON "$(MUI_BUTTONTEXT_FINISH)"
+ !insertmacro MUI_DEFAULT MUI_FINISHPAGE_TEXT_REBOOT "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_FINISH_INFO_REBOOT)"
+ !insertmacro MUI_DEFAULT MUI_FINISHPAGE_TEXT_REBOOTNOW "$(MUI_TEXT_FINISH_REBOOTNOW)"
+ !insertmacro MUI_DEFAULT MUI_FINISHPAGE_TEXT_REBOOTLATER "$(MUI_TEXT_FINISH_REBOOTLATER)"
+ !insertmacro MUI_DEFAULT MUI_FINISHPAGE_RUN_TEXT "$(MUI_TEXT_FINISH_RUN)"
+ !insertmacro MUI_DEFAULT MUI_FINISHPAGE_SHOWREADME_TEXT "$(MUI_TEXT_FINISH_SHOWREADME)"
+ !insertmacro MUI_DEFAULT MUI_FINISHPAGE_LINK_COLOR "000080"
+
+ !insertmacro MUI_PAGE_FUNCTION_FULLWINDOW
+
+ PageEx ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}custom
+
+ PageCallbacks ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.FinishPage.Pre_${MUI_UNIQUEID} \
+ ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.FinishPage.Leave_${MUI_UNIQUEID}
+
+ Caption " "
+
+ PageExEnd
+
+ !insertmacro MUI_FUNCTION_FINISHPAGE ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.FinishPage.Pre_${MUI_UNIQUEID} \
+ ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.FinishPage.Leave_${MUI_UNIQUEID} \
+ ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.FinishPage.Link_${MUI_UNIQUEID}
+
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_TITLE
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_TITLE_3LINES
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_TEXT
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_TEXT_LARGE
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_BUTTON
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_CANCEL_ENABLED
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_TEXT_REBOOT
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_TEXT_REBOOTNOW
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_TEXT_REBOOTLATER
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_REBOOTLATER_DEFAULT
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_RUN
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_RUN_TEXT
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_RUN_PARAMETERS
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_RUN_NOTCHECKED
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_RUN_FUNCTION
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_SHOWREADME
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_SHOWREADME_TEXT
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_SHOWREADME_FUNCTION
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_LINK
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_LINK_LOCATION
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_LINK_COLOR
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_NOREBOOTSUPPORT
+
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_ABORTWARNINGCHECK
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_CURFIELD_TOP
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_CURFIELD_BOTTOM
+
+!macroend
+
+!macro MUI_PAGE_FINISH
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_PAGE_INIT
+ !insertmacro MUI_PAGEDECLARATION_FINISH
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_UNPAGE_FINISH
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_UNPAGE_INIT
+ !insertmacro MUI_PAGEDECLARATION_FINISH
+
+ !verbose pop
+
+!macroend
+
+
+;--------------------------------
+;Page functions
+
+!macro MUI_FUNCTION_FINISHPAGE PRE LEAVE LINK
+
+ !ifdef MUI_FINISHPAGE_LINK
+
+ Function "${LINK}"
+
+ ExecShell open "${MUI_FINISHPAGE_LINK_LOCATION}"
+
+ FunctionEnd
+
+ !endif
+
+ Function "${PRE}"
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM PRE
+
+ ;Set text on Next button
+ SendMessage $mui.Button.Next ${WM_SETTEXT} 0 "STR:${MUI_FINISHPAGE_BUTTON}"
+
+ ;Enable cancel button if set in script
+ !ifdef MUI_FINISHPAGE_CANCEL_ENABLED
+ EnableWindow $mui.Button.Cancel 1
+ !endif
+
+ ;Create dialog
+ nsDialogs::Create 1044
+ Pop $mui.FinishPage
+ nsDialogs::SetRTL $(^RTL)
+ SetCtlColors $mui.FinishPage "" "${MUI_BGCOLOR}"
+
+ ;Image control
+ ${NSD_CreateBitmap} 0u 0u 109u 193u ""
+ Pop $mui.FinishPage.Image
+ !insertmacro MUI_INTERNAL_FULLWINDOW_LOADWIZARDIMAGE "${MUI_PAGE_UNINSTALLER_PREFIX}" $mui.FinishPage.Image $PLUGINSDIR\modern-wizard.bmp $mui.FinishPage.Image.Bitmap
+
+ ;Positiong of controls
+
+ ;Title
+ !ifndef MUI_FINISHPAGE_TITLE_3LINES
+ !define MUI_FINISHPAGE_TITLE_HEIGHT 28
+ !else
+ !define MUI_FINISHPAGE_TITLE_HEIGHT 38
+ !endif
+
+ ;Text
+ ;17 = 10 (top margin) + 7 (distance between texts)
+ !define /math MUI_FINISHPAGE_TEXT_TOP 17 + ${MUI_FINISHPAGE_TITLE_HEIGHT}
+
+ ;Height if space required for radio buttons or check boxes
+ !ifndef MUI_FINISHPAGE_TEXT_LARGE
+ !define MUI_FINISHPAGE_TEXT_HEIGHT_BUTTONS 40
+ !else
+ !define MUI_FINISHPAGE_TEXT_HEIGHT_BUTTONS 60
+ !endif
+
+ !define /math MUI_FINISHPAGE_TEXT_BOTTOM_BUTTONS ${MUI_FINISHPAGE_TEXT_TOP} + ${MUI_FINISHPAGE_TEXT_HEIGHT_BUTTONS}
+
+ ;Positioning of radio buttons to ask for a reboot
+ !ifndef MUI_FINISHPAGE_NOREBOOTSUPPORT
+ !define /math MUI_FINISHPAGE_REBOOTNOW_TOP ${MUI_FINISHPAGE_TEXT_BOTTOM_BUTTONS} + 5 ;Distance between text and options
+ ;25 = 10 (height of first radio button) + 15 (distance between buttons)
+ !define /math MUI_FINISHPAGE_REBOOTLATER_TOP ${MUI_FINISHPAGE_REBOOTNOW_TOP} + 25
+ !endif
+
+ ;Positioning of checkboxes
+ !ifdef MUI_FINISHPAGE_RUN
+ !define /math MUI_FINISHPAGE_RUN_TOP ${MUI_FINISHPAGE_TEXT_BOTTOM_BUTTONS} + 5 ;Distance between text and options
+ !endif
+ !ifdef MUI_FINISHPAGE_SHOWREADME
+ !ifdef MUI_FINISHPAGE_RUN
+ ;25 = 10 (height of run checkbox) + 10 (distance between checkboxes)
+ !define /math MUI_FINISHPAGE_SHOWREADME_TOP ${MUI_FINISHPAGE_RUN_TOP} + 20
+ !else
+ !define /math MUI_FINISHPAGE_SHOWREADME_TOP ${MUI_FINISHPAGE_TEXT_BOTTOM_BUTTONS} + 5 ;Distance between text and options
+ !endif
+ !endif
+
+ !ifndef MUI_FINISHPAGE_RUN & MUI_FINISHPAGE_SHOWREADME
+ ;Height if full space is available for text and link
+ !ifndef MUI_FINISHPAGE_LINK
+ !define MUI_FINISHPAGE_TEXT_HEIGHT 130
+ !else
+ !define MUI_FINISHPAGE_TEXT_HEIGHT 120
+ !endif
+ !endif
+
+ !ifndef MUI_FINISHPAGE_NOREBOOTSUPPORT
+
+ ${if} ${RebootFlag}
+
+ ;Title text
+ ${NSD_CreateLabel} 120u 10u 195u ${MUI_FINISHPAGE_TITLE_HEIGHT}u "${MUI_FINISHPAGE_TITLE}"
+ Pop $mui.FinishPage.Title
+ SetCtlColors $mui.FinishPage.Title "${MUI_TEXTCOLOR}" "${MUI_BGCOLOR}"
+ CreateFont $mui.FinishPage.Title.Font "$(^Font)" "12" "700"
+ SendMessage $mui.FinishPage.Title ${WM_SETFONT} $mui.FinishPage.Title.Font 0
+
+ ;Finish text
+ ${NSD_CreateLabel} 120u ${MUI_FINISHPAGE_TEXT_TOP}u 195u ${MUI_FINISHPAGE_TEXT_HEIGHT_BUTTONS}u "${MUI_FINISHPAGE_TEXT_REBOOT}"
+ Pop $mui.FinishPage.Text
+ SetCtlColors $mui.FinishPage.Text "${MUI_TEXTCOLOR}" "${MUI_BGCOLOR}"
+
+ ;Radio buttons for reboot page
+ ${NSD_CreateRadioButton} 120u ${MUI_FINISHPAGE_REBOOTNOW_TOP}u 195u 10u "${MUI_FINISHPAGE_TEXT_REBOOTNOW}"
+ Pop $mui.FinishPage.RebootNow
+ SetCtlColors $mui.FinishPage.RebootNow "${MUI_TEXTCOLOR}" "${MUI_BGCOLOR}"
+ ${NSD_CreateRadioButton} 120u ${MUI_FINISHPAGE_REBOOTLATER_TOP}u 195u 10u "${MUI_FINISHPAGE_TEXT_REBOOTLATER}"
+ Pop $mui.FinishPage.RebootLater
+ SetCtlColors $mui.FinishPage.RebootLater "${MUI_TEXTCOLOR}" "${MUI_BGCOLOR}"
+ !ifndef MUI_FINISHPAGE_REBOOTLATER_DEFAULT
+ SendMessage $mui.FinishPage.RebootNow ${BM_SETCHECK} ${BST_CHECKED} 0
+ !else
+ SendMessage $mui.FinishPage.RebootLater ${BM_SETCHECK} ${BST_CHECKED} 0
+ !endif
+ ${NSD_SetFocus} $mui.FinishPage.RebootNow
+
+ ${else}
+
+ !endif
+
+ ;Title text
+ ${NSD_CreateLabel} 120u 10u 195u ${MUI_FINISHPAGE_TITLE_HEIGHT}u "${MUI_FINISHPAGE_TITLE}"
+ Pop $mui.FinishPage.Title
+ SetCtlColors $mui.FinishPage.Title "${MUI_TEXTCOLOR}" "${MUI_BGCOLOR}"
+ CreateFont $mui.FinishPage.Title.Font "$(^Font)" "12" "700"
+ SendMessage $mui.FinishPage.Title ${WM_SETFONT} $mui.FinishPage.Title.Font 0
+
+ ;Finish text
+ !ifndef MUI_FINISHPAGE_RUN & MUI_FINISHPAGE_SHOWREADME
+ ${NSD_CreateLabel} 120u ${MUI_FINISHPAGE_TEXT_TOP}u 195u ${MUI_FINISHPAGE_TEXT_HEIGHT}u "${MUI_FINISHPAGE_TEXT}"
+ !else
+ ${NSD_CreateLabel} 120u ${MUI_FINISHPAGE_TEXT_TOP}u 195u ${MUI_FINISHPAGE_TEXT_HEIGHT_BUTTONS}u "${MUI_FINISHPAGE_TEXT}"
+ !endif
+ Pop $mui.FinishPage.Text
+ SetCtlColors $mui.FinishPage.Text "${MUI_TEXTCOLOR}" "${MUI_BGCOLOR}"
+
+ ;Checkboxes
+ !ifdef MUI_FINISHPAGE_RUN
+ ${NSD_CreateCheckbox} 120u ${MUI_FINISHPAGE_RUN_TOP}u 195u 10u "${MUI_FINISHPAGE_RUN_TEXT}"
+ Pop $mui.FinishPage.Run
+ SetCtlColors $mui.FinishPage.Run "${MUI_TEXTCOLOR}" "${MUI_BGCOLOR}"
+ !ifndef MUI_FINISHPAGE_RUN_NOTCHECKED
+ SendMessage $mui.FinishPage.Run ${BM_SETCHECK} ${BST_CHECKED} 0
+ !endif
+ ${NSD_SetFocus} $mui.FinishPage.Run
+ !endif
+ !ifdef MUI_FINISHPAGE_SHOWREADME
+ ${NSD_CreateCheckbox} 120u ${MUI_FINISHPAGE_SHOWREADME_TOP}u 195u 10u "${MUI_FINISHPAGE_SHOWREADME_TEXT}"
+ Pop $mui.FinishPage.ShowReadme
+ SetCtlColors $mui.FinishPage.ShowReadme "${MUI_TEXTCOLOR}" "${MUI_BGCOLOR}"
+ !ifndef MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
+ SendMessage $mui.FinishPage.ShowReadme ${BM_SETCHECK} ${BST_CHECKED} 0
+ !endif
+ !ifndef MUI_FINISHPAGE_RUN
+ ${NSD_SetFocus} $mui.FinishPage.ShowReadme
+ !endif
+ !endif
+
+ ;Link
+ !ifdef MUI_FINISHPAGE_LINK
+ ${NSD_CreateLink} 120u 175u 195u 10u "${MUI_FINISHPAGE_LINK}"
+ Pop $mui.FinishPage.Link
+ SetCtlColors $mui.FinishPage.Link "${MUI_FINISHPAGE_LINK_COLOR}" "${MUI_BGCOLOR}"
+ ${NSD_OnClick} $mui.FinishPage.Link "${LINK}"
+ !endif
+
+ !ifndef MUI_FINISHPAGE_NOREBOOTSUPPORT
+ ${endif}
+ !endif
+
+ !ifdef MUI_FINISHPAGE_CANCEL_ENABLED
+ StrCpy $mui.FinishPage.DisableAbortWarning "1"
+ !endif
+
+ !ifndef MUI_FORCECLASSICCONTROLS
+ ${If} ${IsHighContrastModeActive}
+ !endif
+ ; SetCtlColors does not change the check/radio text color (bug #443)
+ !ifndef MUI_FINISHPAGE_NOREBOOTSUPPORT
+ System::Call 'UXTHEME::SetWindowTheme(p$mui.FinishPage.RebootNow,w" ",w" ")'
+ System::Call 'UXTHEME::SetWindowTheme(p$mui.FinishPage.RebootLater,w" ",w" ")'
+ !endif
+ !ifdef MUI_FINISHPAGE_RUN
+ System::Call 'UXTHEME::SetWindowTheme(p$mui.FinishPage.Run,w" ",w" ")'
+ !endif
+ !ifdef MUI_FINISHPAGE_SHOWREADME
+ System::Call 'UXTHEME::SetWindowTheme(p$mui.FinishPage.ShowReadme,w" ",w" ")'
+ !endif
+ !ifndef MUI_FORCECLASSICCONTROLS
+ ${EndIf}
+ !endif
+
+ ;Show page
+ Call ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}muiPageLoadFullWindow
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM SHOW
+ nsDialogs::Show
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM DESTROYED
+ Call ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}muiPageUnloadFullWindow
+
+ !ifdef MUI_FINISHPAGE_CANCEL_ENABLED
+ StrCpy $mui.FinishPage.DisableAbortWarning ""
+ !endif
+
+ ;Delete image from memory
+ ${NSD_FreeImage} $mui.FinishPage.Image.Bitmap
+
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_TITLE_HEIGHT
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_TEXT_TOP
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_TEXT_HEIGHT
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_TEXT_HEIGHT_BUTTONS
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_TEXT_BOTTOM_BUTTONS
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_REBOOTNOW_TOP
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_REBOOTLATER_TOP
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_RUN_TOP
+ !insertmacro MUI_UNSET MUI_FINISHPAGE_SHOWREADME_TOP
+
+ FunctionEnd
+
+ Function "${LEAVE}"
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM LEAVE
+
+ !ifndef MUI_FINISHPAGE_NOREBOOTSUPPORT
+
+ ;Check whether the user has chosen to reboot the computer
+ ${if} ${RebootFlag}
+ SendMessage $mui.FinishPage.RebootNow ${BM_GETCHECK} 0 0 $mui.FinishPage.ReturnValue
+ ${if} $mui.FinishPage.ReturnValue = ${BST_CHECKED}
+ Reboot
+ ${else}
+ Return
+ ${endif}
+ ${endif}
+
+ !endif
+
+ ;Run functions depending on checkbox state
+
+ !ifdef MUI_FINISHPAGE_RUN
+
+ SendMessage $mui.FinishPage.Run ${BM_GETCHECK} 0 0 $mui.FinishPage.ReturnValue
+
+ ${if} $mui.FinishPage.ReturnValue = ${BST_CHECKED}
+ !ifndef MUI_FINISHPAGE_RUN_FUNCTION
+ !ifndef MUI_FINISHPAGE_RUN_PARAMETERS
+ Exec "$\"${MUI_FINISHPAGE_RUN}$\""
+ !else
+ Exec "$\"${MUI_FINISHPAGE_RUN}$\" ${MUI_FINISHPAGE_RUN_PARAMETERS}"
+ !endif
+ !else
+ Call "${MUI_FINISHPAGE_RUN_FUNCTION}"
+ !endif
+ ${endif}
+
+ !endif
+
+ !ifdef MUI_FINISHPAGE_SHOWREADME
+
+ SendMessage $mui.FinishPage.ShowReadme ${BM_GETCHECK} 0 0 $mui.FinishPage.ReturnValue
+
+ ${if} $mui.FinishPage.ReturnValue = ${BST_CHECKED}
+ !ifndef MUI_FINISHPAGE_SHOWREADME_FUNCTION
+ ExecShell open "${MUI_FINISHPAGE_SHOWREADME}"
+ !else
+ Call "${MUI_FINISHPAGE_SHOWREADME_FUNCTION}"
+ !endif
+ ${endif}
+
+ !endif
+
+ FunctionEnd
+
+!macroend
diff --git a/installer/tools/Contrib/Modern UI 2/Pages/InstallFiles.nsh b/installer/tools/Contrib/Modern UI 2/Pages/InstallFiles.nsh
new file mode 100644
index 00000000..868ae17c
--- /dev/null
+++ b/installer/tools/Contrib/Modern UI 2/Pages/InstallFiles.nsh
@@ -0,0 +1,149 @@
+/*
+
+NSIS Modern User Interface
+InstallFiles page
+
+*/
+
+;--------------------------------
+;Page interface settings and variables
+
+!macro MUI_INSTFILESPAGE_INTERFACE
+
+ !ifndef MUI_INSTFILESYPAGE_INTERFACE
+ !define MUI_INSTFILESYPAGE_INTERFACE
+
+ !insertmacro MUI_DEFAULT MUI_INSTFILESPAGE_COLORS "/windows"
+ !insertmacro MUI_DEFAULT MUI_INSTFILESPAGE_PROGRESSBAR "smooth"
+
+ Var mui.InstFilesPage
+
+ Var mui.InstFilesPage.Text
+ Var mui.InstFilesPage.ProgressBar
+ Var mui.InstFilesPage.ShowLogButton
+ Var mui.InstFilesPage.Log
+
+ ;Apply settings
+ InstallColors ${MUI_INSTFILESPAGE_COLORS}
+ InstProgressFlags ${MUI_INSTFILESPAGE_PROGRESSBAR}
+ SubCaption 4 " "
+ UninstallSubCaption 2 " "
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Page declaration
+
+!macro MUI_PAGEDECLARATION_INSTFILES
+
+ !insertmacro MUI_SET MUI_${MUI_PAGE_UNINSTALLER_PREFIX}INSTFILESPAGE ""
+ !insertmacro MUI_INSTFILESPAGE_INTERFACE
+
+ PageEx ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}instfiles
+
+ PageCallbacks ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.InstFilesPre_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.InstFilesShow_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.InstFilesLeave_${MUI_UNIQUEID}
+
+ Caption " "
+
+ PageExEnd
+
+ !insertmacro MUI_FUNCTION_INSTFILESPAGE ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.InstFilesPre_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.InstFilesShow_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.InstFilesLeave_${MUI_UNIQUEID}
+
+ !insertmacro MUI_UNSET MUI_INSTFILESPAGE_FINISHHEADER_TEXT
+ !insertmacro MUI_UNSET MUI_INSTFILESPAGE_FINISHHEADER_SUBTEXT
+ !insertmacro MUI_UNSET MUI_INSTFILESPAGE_ABORTWARNING_TEXT
+ !insertmacro MUI_UNSET MUI_INSTFILESPAGE_ABORTWARNING_SUBTEXT
+
+!macroend
+
+!macro MUI_PAGE_INSTFILES
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_PAGE_INIT
+ !insertmacro MUI_PAGEDECLARATION_INSTFILES
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_UNPAGE_INSTFILES
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_UNPAGE_INIT
+ !insertmacro MUI_PAGEDECLARATION_INSTFILES
+
+ !verbose pop
+
+!macroend
+
+
+;--------------------------------
+;Page functions
+
+!macro MUI_FUNCTION_INSTFILESPAGE PRE SHOW LEAVE
+
+ Function "${PRE}"
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM PRE
+ !insertmacro MUI_HEADER_TEXT_PAGE $(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_${MUI_PAGE_UNINSTALLER_PREFIX}INSTALLING_TITLE) $(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_${MUI_PAGE_UNINSTALLER_PREFIX}INSTALLING_SUBTITLE)
+
+ FunctionEnd
+
+ Function "${SHOW}"
+
+ ;Get controls handles
+ FindWindow $mui.InstFilesPage "#32770" "" $HWNDPARENT
+ GetDlgItem $mui.InstFilesPage.Text $mui.InstFilesPage 1006
+ GetDlgItem $mui.InstFilesPage.ProgressBar $mui.InstFilesPage 1004
+ GetDlgItem $mui.InstFilesPage.ShowLogButton $mui.InstFilesPage 1027
+ GetDlgItem $mui.InstFilesPage.Log $mui.InstFilesPage 1016
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM SHOW
+
+ FunctionEnd
+
+ Function "${LEAVE}"
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM LEAVE
+
+ ;Set text on completed page header
+
+ IfAbort mui.endheader_abort
+
+ !ifdef MUI_INSTFILESPAGE_FINISHHEADER_TEXT & MUI_INSTFILESPAGE_FINISHHEADER_SUBTEXT
+ !insertmacro MUI_HEADER_TEXT "${MUI_INSTFILESPAGE_FINISHHEADER_TEXT}" "${MUI_INSTFILESPAGE_FINISHHEADER_SUBTEXT}"
+ !else ifdef MUI_INSTFILESPAGE_FINISHHEADER_TEXT
+ !insertmacro MUI_HEADER_TEXT "${MUI_INSTFILESPAGE_FINISHHEADER_TEXT}" "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_FINISH_SUBTITLE)"
+ !else ifdef MUI_INSTFILESPAGE_FINISHHEADER_SUBTEXT
+ !insertmacro MUI_HEADER_TEXT "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_FINISH_TITLE)" "${MUI_INSTFILESPAGE_FINISHHEADER_SUBTEXT}"
+ !else
+ !insertmacro MUI_HEADER_TEXT "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_FINISH_TITLE)" "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_FINISH_SUBTITLE)"
+ !endif
+
+ Goto mui.endheader_done
+
+ mui.endheader_abort:
+
+ !ifdef MUI_INSTFILESPAGE_ABORTHEADER_TEXT & MUI_INSTFILESPAGE_ABORTHEADER_SUBTEXT
+ !insertmacro MUI_HEADER_TEXT "${MUI_INSTFILESPAGE_ABORTHEADER_TEXT}" "${MUI_INSTFILESPAGE_ABORTHEADER_SUBTEXT}"
+ !else ifdef MUI_INSTFILESPAGE_ABORTHEADER_TEXT
+ !insertmacro MUI_HEADER_TEXT "${MUI_INSTFILESPAGE_ABORTHEADER_TEXT}" "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_ABORT_SUBTITLE)"
+ !else ifdef MUI_INSTFILESPAGE_ABORTHEADER_SUBTEXT
+ !insertmacro MUI_HEADER_TEXT "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_ABORT_TITLE)" "${MUI_INSTFILESPAGE_ABORTHEADER_SUBTEXT}"
+ !else
+ !insertmacro MUI_HEADER_TEXT "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_ABORT_TITLE)" "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_ABORT_SUBTITLE)"
+ !endif
+
+ mui.endheader_done:
+
+ !insertmacro MUI_LANGDLL_SAVELANGUAGE
+
+ FunctionEnd
+
+!macroend
diff --git a/installer/tools/Contrib/Modern UI 2/Pages/License.nsh b/installer/tools/Contrib/Modern UI 2/Pages/License.nsh
new file mode 100644
index 00000000..a74214a0
--- /dev/null
+++ b/installer/tools/Contrib/Modern UI 2/Pages/License.nsh
@@ -0,0 +1,143 @@
+/*
+
+NSIS Modern User Interface
+License page
+
+*/
+
+;--------------------------------
+;Page interface settings and variables
+
+!macro MUI_LICENSEPAGE_INTERFACE
+
+ !ifndef MUI_LICENSEPAGE_INTERFACE
+ !define MUI_LICENSEPAGE_INTERFACE
+ Var mui.LicensePage
+
+ Var mui.Licensepage.TopText
+ Var mui.Licensepage.Text
+ Var mui.Licensepage.LicenseText
+
+ !insertmacro MUI_DEFAULT MUI_LICENSEPAGE_BGCOLOR "/windows"
+
+ ;Apply settings
+ LicenseBkColor "${MUI_LICENSEPAGE_BGCOLOR}"
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Page declaration
+
+!macro MUI_PAGEDECLARATION_LICENSE LICENSEDATA
+
+ !insertmacro MUI_SET MUI_${MUI_PAGE_UNINSTALLER_PREFIX}LICENSEPAGE ""
+ !insertmacro MUI_LICENSEPAGE_INTERFACE
+
+ !insertmacro MUI_DEFAULT MUI_LICENSEPAGE_TEXT_TOP "$(MUI_INNERTEXT_LICENSE_TOP)"
+ !insertmacro MUI_DEFAULT MUI_LICENSEPAGE_BUTTON ""
+ !insertmacro MUI_DEFAULT MUI_LICENSEPAGE_CHECKBOX_TEXT ""
+ !insertmacro MUI_DEFAULT MUI_LICENSEPAGE_RADIOBUTTONS_TEXT_ACCEPT ""
+ !insertmacro MUI_DEFAULT MUI_LICENSEPAGE_RADIOBUTTONS_TEXT_DECLINE ""
+
+ PageEx ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}license
+
+ PageCallbacks ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.LicensePre_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.LicenseShow_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.LicenseLeave_${MUI_UNIQUEID}
+
+ Caption " "
+
+ LicenseData "${LICENSEDATA}"
+
+ !ifndef MUI_LICENSEPAGE_TEXT_BOTTOM
+ !ifndef MUI_LICENSEPAGE_CHECKBOX & MUI_LICENSEPAGE_RADIOBUTTONS
+ LicenseText "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}INNERTEXT_LICENSE_BOTTOM)" "${MUI_LICENSEPAGE_BUTTON}"
+ !else ifdef MUI_LICENSEPAGE_CHECKBOX
+ LicenseText "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}INNERTEXT_LICENSE_BOTTOM_CHECKBOX)" "${MUI_LICENSEPAGE_BUTTON}"
+ !else
+ LicenseText "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}INNERTEXT_LICENSE_BOTTOM_RADIOBUTTONS)" "${MUI_LICENSEPAGE_BUTTON}"
+ !endif
+ !else
+ LicenseText "${MUI_LICENSEPAGE_TEXT_BOTTOM}" "${MUI_LICENSEPAGE_BUTTON}"
+ !endif
+
+ !ifdef MUI_LICENSEPAGE_CHECKBOX
+ LicenseForceSelection checkbox "${MUI_LICENSEPAGE_CHECKBOX_TEXT}"
+ !else ifdef MUI_LICENSEPAGE_RADIOBUTTONS
+ LicenseForceSelection radiobuttons "${MUI_LICENSEPAGE_RADIOBUTTONS_TEXT_ACCEPT}" "${MUI_LICENSEPAGE_RADIOBUTTONS_TEXT_DECLINE}"
+ !endif
+
+ PageExEnd
+
+ !insertmacro MUI_FUNCTION_LICENSEPAGE ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.LicensePre_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.LicenseShow_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.LicenseLeave_${MUI_UNIQUEID}
+
+ !insertmacro MUI_UNSET MUI_LICENSEPAGE_TEXT_TOP
+ !insertmacro MUI_UNSET MUI_LICENSEPAGE_TEXT_BOTTOM
+ !insertmacro MUI_UNSET MUI_LICENSEPAGE_BUTTON
+ !insertmacro MUI_UNSET MUI_LICENSEPAGE_CHECKBOX
+ !insertmacro MUI_UNSET MUI_LICENSEPAGE_CHECKBOX_TEXT
+ !insertmacro MUI_UNSET MUI_LICENSEPAGE_RADIOBUTTONS
+ !insertmacro MUI_UNSET MUI_LICENSEPAGE_CHECKBOX_TEXT_ACCEPT
+ !insertmacro MUI_UNSET MUI_LICENSEPAGE_CHECKBOX_TEXT_DECLINE
+
+!macroend
+
+!macro MUI_PAGE_LICENSE LICENSEDATA
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_PAGE_INIT
+ !insertmacro MUI_PAGEDECLARATION_LICENSE "${LICENSEDATA}"
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_UNPAGE_LICENSE LICENSEDATA
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_UNPAGE_INIT
+ !insertmacro MUI_PAGEDECLARATION_LICENSE "${LICENSEDATA}"
+
+ !verbose pop
+
+!macroend
+
+
+;--------------------------------
+;Page functions
+
+!macro MUI_FUNCTION_LICENSEPAGE PRE SHOW LEAVE
+
+ Function "${PRE}"
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM PRE
+ !insertmacro MUI_HEADER_TEXT_PAGE $(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_LICENSE_TITLE) $(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_LICENSE_SUBTITLE)
+
+ FunctionEnd
+
+ Function "${SHOW}"
+
+ ;Get control handles
+ FindWindow $mui.LicensePage "#32770" "" $HWNDPARENT
+ GetDlgItem $mui.LicensePage.TopText $mui.LicensePage 1040
+ GetDlgItem $mui.LicensePage.Text $mui.LicensePage 1006
+ GetDlgItem $mui.LicensePage.LicenseText $mui.LicensePage 1000
+
+ ;Top text
+ SendMessage $mui.LicensePage.TopText ${WM_SETTEXT} 0 "STR:${MUI_LICENSEPAGE_TEXT_TOP}"
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM SHOW
+
+ FunctionEnd
+
+ Function "${LEAVE}"
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM LEAVE
+
+ FunctionEnd
+
+!macroend
diff --git a/installer/tools/Contrib/Modern UI 2/Pages/StartMenu.nsh b/installer/tools/Contrib/Modern UI 2/Pages/StartMenu.nsh
new file mode 100644
index 00000000..71c41bb6
--- /dev/null
+++ b/installer/tools/Contrib/Modern UI 2/Pages/StartMenu.nsh
@@ -0,0 +1,236 @@
+/*
+
+NSIS Modern User Interface
+Start Menu folder page
+
+*/
+
+;--------------------------------
+;Page interface settings and variables
+
+!macro MUI_STARTMENUPAGE_INTERFACE
+
+ !ifndef MUI_STARTMENUPAGE_INTERFACE
+ !define MUI_STARTMENUPAGE_INTERFACE
+ Var mui.StartMenuPage
+ Var mui.StartMenuPage.Location
+ Var mui.StartMenuPage.FolderList
+
+ Var mui.StartMenuPage.Temp
+ !endif
+
+ !ifdef MUI_STARTMENUPAGE_REGISTRY_ROOT & MUI_STARTMENUPAGE_REGISTRY_KEY & MUI_STARTMENUPAGE_REGISTRY_VALUENAME
+ !ifndef MUI_STARTMENUPAGE_REGISTRY_VARIABLES
+ !define MUI_STARTMENUPAGE_REGISTRY_VARIABLES
+ Var mui.StartMenuPage.RegistryLocation
+ !endif
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Page declaration
+
+!macro MUI_PAGEDECLARATION_STARTMENU ID VAR
+
+ !insertmacro MUI_SET MUI_${MUI_PAGE_UNINSTALLER_PREFIX}STARTMENUPAGE ""
+ !insertmacro MUI_STARTMENUPAGE_INTERFACE
+
+ !insertmacro MUI_DEFAULT MUI_STARTMENUPAGE_DEFAULTFOLDER "$(^Name)"
+ !insertmacro MUI_DEFAULT MUI_STARTMENUPAGE_TEXT_TOP "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}INNERTEXT_STARTMENU_TOP)"
+ !insertmacro MUI_DEFAULT MUI_STARTMENUPAGE_TEXT_CHECKBOX "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}INNERTEXT_STARTMENU_CHECKBOX)"
+
+ !define MUI_STARTMENUPAGE_VARIABLE "${VAR}"
+ !define "MUI_STARTMENUPAGE_${ID}_VARIABLE" "${MUI_STARTMENUPAGE_VARIABLE}"
+ !define "MUI_STARTMENUPAGE_${ID}_DEFAULTFOLDER" "${MUI_STARTMENUPAGE_DEFAULTFOLDER}"
+ !ifdef MUI_STARTMENUPAGE_REGISTRY_ROOT
+ !define "MUI_STARTMENUPAGE_${ID}_REGISTRY_ROOT" "${MUI_STARTMENUPAGE_REGISTRY_ROOT}"
+ !endif
+ !ifdef MUI_STARTMENUPAGE_REGISTRY_KEY
+ !define "MUI_STARTMENUPAGE_${ID}_REGISTRY_KEY" "${MUI_STARTMENUPAGE_REGISTRY_KEY}"
+ !endif
+ !ifdef MUI_STARTMENUPAGE_REGISTRY_VALUENAME
+ !define "MUI_STARTMENUPAGE_${ID}_REGISTRY_VALUENAME" "${MUI_STARTMENUPAGE_REGISTRY_VALUENAME}"
+ !endif
+
+ PageEx ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}custom
+
+ PageCallbacks ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.StartmenuPre_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.StartmenuLeave_${MUI_UNIQUEID}
+
+ Caption " "
+
+ PageExEnd
+
+ !insertmacro MUI_FUNCTION_STARTMENUPAGE ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.StartmenuPre_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.StartmenuLeave_${MUI_UNIQUEID}
+
+ !undef MUI_STARTMENUPAGE_VARIABLE
+ !undef MUI_STARTMENUPAGE_TEXT_TOP
+ !undef MUI_STARTMENUPAGE_TEXT_CHECKBOX
+ !undef MUI_STARTMENUPAGE_DEFAULTFOLDER
+ !insertmacro MUI_UNSET MUI_STARTMENUPAGE_NODISABLE
+ !insertmacro MUI_UNSET MUI_STARTMENUPAGE_REGISTRY_ROOT
+ !insertmacro MUI_UNSET MUI_STARTMENUPAGE_REGISTRY_KEY
+ !insertmacro MUI_UNSET MUI_STARTMENUPAGE_REGISTRY_VALUENAME
+
+!macroend
+
+!macro MUI_PAGE_STARTMENU ID VAR
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_PAGE_INIT
+ !insertmacro MUI_PAGEDECLARATION_STARTMENU "${ID}" "${VAR}"
+
+ !verbose pop
+
+!macroend
+
+;--------------------------------
+;Page functions
+
+!macro MUI_FUNCTION_STARTMENUPAGE PRE LEAVE
+
+ Function "${PRE}"
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM PRE
+
+ !ifdef MUI_STARTMENUPAGE_REGISTRY_ROOT & MUI_STARTMENUPAGE_REGISTRY_KEY & MUI_STARTMENUPAGE_REGISTRY_VALUENAME
+
+ ;Get Start Menu location from registry
+
+ ${if} "${MUI_STARTMENUPAGE_VARIABLE}" == ""
+
+ ReadRegStr $mui.StartMenuPage.RegistryLocation "${MUI_STARTMENUPAGE_REGISTRY_ROOT}" "${MUI_STARTMENUPAGE_REGISTRY_KEY}" "${MUI_STARTMENUPAGE_REGISTRY_VALUENAME}"
+ ${if} $mui.StartMenuPage.RegistryLocation != ""
+ StrCpy "${MUI_STARTMENUPAGE_VARIABLE}" $mui.StartMenuPage.RegistryLocation
+ ${endif}
+
+ ClearErrors
+
+ ${endif}
+
+ !endif
+
+ !insertmacro MUI_HEADER_TEXT_PAGE $(MUI_TEXT_STARTMENU_TITLE) $(MUI_TEXT_STARTMENU_SUBTITLE)
+
+ ${if} $(^RTL) == "0"
+ !ifndef MUI_STARTMENUPAGE_NODISABLE
+ StartMenu::Init /noicon /autoadd /text "${MUI_STARTMENUPAGE_TEXT_TOP}" /lastused "${MUI_STARTMENUPAGE_VARIABLE}" /checknoshortcuts "${MUI_STARTMENUPAGE_TEXT_CHECKBOX}" "${MUI_STARTMENUPAGE_DEFAULTFOLDER}"
+ !else
+ StartMenu::Init /noicon /autoadd /text "${MUI_STARTMENUPAGE_TEXT_TOP}" /lastused "${MUI_STARTMENUPAGE_VARIABLE}" "${MUI_STARTMENUPAGE_DEFAULTFOLDER}"
+ !endif
+ ${else}
+ !ifndef MUI_STARTMENUPAGE_NODISABLE
+ StartMenu::Init /rtl /noicon /autoadd /text "${MUI_STARTMENUPAGE_TEXT_TOP}" /lastused "${MUI_STARTMENUPAGE_VARIABLE}" /checknoshortcuts "${MUI_STARTMENUPAGE_TEXT_CHECKBOX}" "${MUI_STARTMENUPAGE_DEFAULTFOLDER}"
+ !else
+ StartMenu::Init /rtl /noicon /autoadd /text "${MUI_STARTMENUPAGE_TEXT_TOP}" /lastused "${MUI_STARTMENUPAGE_VARIABLE}" "${MUI_STARTMENUPAGE_DEFAULTFOLDER}"
+ !endif
+ ${endif}
+
+ Pop $mui.StartMenuPage
+
+ ;Get control handles
+ GetDlgItem $mui.StartMenuPage.Location $mui.StartMenuPage 1002
+ GetDlgItem $mui.StartMenuPage.FolderList $mui.StartMenuPage 1004
+
+ !ifdef MUI_STARTMENUPAGE_BGCOLOR
+ !insertmacro MUI_DEFAULT MUI_STARTMENUPAGE_TEXTCOLOR ""
+ SetCtlColors $mui.StartMenuPage.Location "${MUI_STARTMENUPAGE_TEXTCOLOR}" "${MUI_STARTMENUPAGE_BGCOLOR}"
+ SetCtlColors $mui.StartMenuMenu.FolderList "${MUI_STARTMENUPAGE_TEXTCOLOR}" "${MUI_STARTMENUPAGE_BGCOLOR}"
+ !endif
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM SHOW
+ StartMenu::Show
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM DESTROYED
+
+ Pop $mui.StartMenuPage.Temp
+ ${if} $mui.StartMenuPage.Temp == "success"
+ Pop "${MUI_STARTMENUPAGE_VARIABLE}"
+ ${endif}
+
+ FunctionEnd
+
+ Function "${LEAVE}"
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM LEAVE
+
+ FunctionEnd
+
+!macroend
+
+
+;--------------------------------
+;Script macros to get Start Menu folder
+
+!macro MUI_STARTMENU_GETFOLDER ID VAR
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ ;Get Start Menu folder from registry
+ ;Can be called from the script in the uninstaller
+
+ !ifdef MUI_STARTMENUPAGE_${ID}_REGISTRY_ROOT & MUI_STARTMENUPAGE_${ID}_REGISTRY_KEY & MUI_STARTMENUPAGE_${ID}_REGISTRY_VALUENAME
+
+ ReadRegStr $mui.StartMenuPage.RegistryLocation "${MUI_STARTMENUPAGE_${ID}_REGISTRY_ROOT}" "${MUI_STARTMENUPAGE_${ID}_REGISTRY_KEY}" "${MUI_STARTMENUPAGE_${ID}_REGISTRY_VALUENAME}"
+
+ ${if} $mui.StartMenuPage.RegistryLocation != ""
+ StrCpy "${VAR}" $mui.StartMenuPage.RegistryLocation
+ ${else}
+ StrCpy "${VAR}" "${MUI_STARTMENUPAGE_${ID}_DEFAULTFOLDER}"
+ ${endif}
+
+ !else
+
+ StrCpy "${VAR}" "${MUI_STARTMENUPAGE_${ID}_DEFAULTFOLDER}"
+
+ !endif
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_STARTMENU_WRITE_BEGIN ID
+
+ ;The code in the script to write the shortcuts should be put between the
+ ;MUI_STARTMENU_WRITE_BEGIN and MUI_STARTMENU_WRITE_END macros
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !define MUI_STARTMENUPAGE_CURRENT_ID "${ID}"
+
+ StrCpy $mui.StartMenuPage.Temp "${MUI_STARTMENUPAGE_${MUI_STARTMENUPAGE_CURRENT_ID}_VARIABLE}" 1
+
+ ;If the folder start with >, the user has chosen not to create a shortcut
+ ${if} $mui.StartMenuPage.Temp != ">"
+
+ ${if} "${MUI_STARTMENUPAGE_${MUI_STARTMENUPAGE_CURRENT_ID}_VARIABLE}" == ""
+ ;Get folder from registry if the variable doesn't contain anything
+ !insertmacro MUI_STARTMENU_GETFOLDER "${MUI_STARTMENUPAGE_CURRENT_ID}" "${MUI_STARTMENUPAGE_${MUI_STARTMENUPAGE_CURRENT_ID}_VARIABLE}"
+ ${endif}
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_STARTMENU_WRITE_END
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !ifdef MUI_STARTMENUPAGE_${MUI_STARTMENUPAGE_CURRENT_ID}_REGISTRY_ROOT & MUI_STARTMENUPAGE_${MUI_STARTMENUPAGE_CURRENT_ID}_REGISTRY_KEY & MUI_STARTMENUPAGE_${MUI_STARTMENUPAGE_CURRENT_ID}_REGISTRY_VALUENAME
+ ;Write folder to registry
+ WriteRegStr "${MUI_STARTMENUPAGE_${MUI_STARTMENUPAGE_CURRENT_ID}_REGISTRY_ROOT}" "${MUI_STARTMENUPAGE_${MUI_STARTMENUPAGE_CURRENT_ID}_REGISTRY_KEY}" "${MUI_STARTMENUPAGE_${MUI_STARTMENUPAGE_CURRENT_ID}_REGISTRY_VALUENAME}" "${MUI_STARTMENUPAGE_${MUI_STARTMENUPAGE_CURRENT_ID}_VARIABLE}"
+ !endif
+
+ ${endif}
+
+ !undef MUI_STARTMENUPAGE_CURRENT_ID
+
+ !verbose pop
+
+!macroend
+
diff --git a/installer/tools/Contrib/Modern UI 2/Pages/UninstallConfirm.nsh b/installer/tools/Contrib/Modern UI 2/Pages/UninstallConfirm.nsh
new file mode 100644
index 00000000..1ebe927d
--- /dev/null
+++ b/installer/tools/Contrib/Modern UI 2/Pages/UninstallConfirm.nsh
@@ -0,0 +1,100 @@
+/*
+
+NSIS Modern User Interface
+Uninstall confirmation page
+
+*/
+
+;--------------------------------
+;Page interface settings and variables
+
+!macro MUI_UNCONFIRMPAGE_INTERFACE
+
+ !ifndef MUI_UNCONFIRMPAGE_INTERFACE
+ !define MUI_UNCONFIRMPAGE_INTERFACE
+ Var mui.UnConfirmPage
+
+ Var mui.UnConfirmPage.Text
+ Var mui.UnConfirmPage.DirectoryText
+ Var mui.UnConfirmPage.Directory
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Page declaration
+
+!macro MUI_PAGEDECLARATION_CONFIRM
+
+ !insertmacro MUI_SET MUI_UNCONFIRMPAGE ""
+ !insertmacro MUI_UNCONFIRMPAGE_INTERFACE
+
+ !insertmacro MUI_DEFAULT MUI_UNCONFIRMPAGE_TEXT_TOP ""
+ !insertmacro MUI_DEFAULT MUI_UNCONFIRMPAGE_TEXT_LOCATION ""
+
+ PageEx un.uninstConfirm
+
+ PageCallbacks un.mui.ConfirmPre_${MUI_UNIQUEID} un.mui.ConfirmShow_${MUI_UNIQUEID} un.mui.ConfirmLeave_${MUI_UNIQUEID}
+
+ Caption " "
+
+ UninstallText "${MUI_UNCONFIRMPAGE_TEXT_TOP}" "${MUI_UNCONFIRMPAGE_TEXT_LOCATION}"
+
+ !ifdef MUI_UNCONFIRMPAGE_VARIABLE
+ DirVar "${MUI_UNCONFIRMPAGE_VARIABLE}"
+ !endif
+
+ PageExEnd
+
+ !insertmacro MUI_UNFUNCTION_CONFIRMPAGE un.mui.ConfirmPre_${MUI_UNIQUEID} un.mui.ConfirmShow_${MUI_UNIQUEID} un.mui.ConfirmLeave_${MUI_UNIQUEID}
+
+ !insertmacro MUI_UNSET MUI_UNCONFIRMPAGE_TEXT_TOP
+ !insertmacro MUI_UNSET MUI_UNCONFIRMPAGE_TEXT_LOCATION
+
+!macroend
+
+!macro MUI_UNPAGE_CONFIRM
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_UNPAGE_INIT
+ !insertmacro MUI_PAGEDECLARATION_CONFIRM
+
+ !verbose pop
+
+!macroend
+
+
+;--------------------------------
+;Page functions
+
+!macro MUI_UNFUNCTION_CONFIRMPAGE PRE SHOW LEAVE
+
+ Function "${PRE}"
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM PRE
+ !insertmacro MUI_HEADER_TEXT_PAGE $(MUI_UNTEXT_CONFIRM_TITLE) $(MUI_UNTEXT_CONFIRM_SUBTITLE)
+
+ FunctionEnd
+
+ Function "${SHOW}"
+
+ ;Get controls handles
+ FindWindow $mui.UnConfirmPage "#32770" "" $HWNDPARENT
+ GetDlgItem $mui.UnConfirmPage.Text $mui.UnConfirmPage 1006
+ GetDlgItem $mui.UnConfirmPage.DirectoryText $mui.UnConfirmPage 1029
+ GetDlgItem $mui.UnConfirmPage.Directory $mui.UnConfirmPage 1000
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM SHOW
+
+ FunctionEnd
+
+ Function "${LEAVE}"
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM LEAVE
+
+ FunctionEnd
+
+!macroend
diff --git a/installer/tools/Contrib/Modern UI 2/Pages/Welcome.nsh b/installer/tools/Contrib/Modern UI 2/Pages/Welcome.nsh
new file mode 100644
index 00000000..0839b949
--- /dev/null
+++ b/installer/tools/Contrib/Modern UI 2/Pages/Welcome.nsh
@@ -0,0 +1,181 @@
+/*
+
+NSIS Modern User Interface
+Welcome page (implemented using nsDialogs)
+
+*/
+
+;--------------------------------
+;Page interface settings and variables
+
+!macro MUI_WELCOMEPAGE_INTERFACE
+
+ !ifndef MUI_WELCOMEPAGE_INTERFACE
+ !define MUI_WELCOMEPAGE_INTERFACE
+ Var mui.WelcomePage
+
+ Var mui.WelcomePage.Image
+ Var mui.WelcomePage.Image.Bitmap
+
+ Var mui.WelcomePage.Title
+ Var mui.WelcomePage.Title.Font
+
+ Var mui.WelcomePage.Text
+ !endif
+
+ !insertmacro MUI_DEFAULT MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP "${NSISDIR}\Contrib\Graphics\Wizard\win.bmp"
+ !if "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP}" == ""
+ !error "Invalid MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP"
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Interface initialization
+
+!macro MUI_WELCOMEPAGE_GUIINIT
+
+ !ifndef MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEWELCOMEPAGE_GUINIT
+ !define MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEWELCOMEPAGE_GUINIT
+
+ Function ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.WelcomePage.GUIInit
+
+ InitPluginsDir
+ File "/oname=$PLUGINSDIR\modern-wizard.bmp" "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP}"
+ !pragma verifyloadimage "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEFINISHPAGE_BITMAP}"
+
+ !ifdef MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_GUIINIT
+ Call "${MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_GUIINIT}"
+ !endif
+
+ FunctionEnd
+
+ !insertmacro MUI_SET MUI_${MUI_PAGE_UNINSTALLER_PREFIX}PAGE_FUNCTION_GUIINIT ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.WelcomePage.GUIInit
+
+ !endif
+
+!macroend
+
+
+;--------------------------------
+;Page declaration
+
+!macro MUI_PAGEDECLARATION_WELCOME
+
+ !insertmacro MUI_SET MUI_${MUI_PAGE_UNINSTALLER_PREFIX}WELCOMEPAGE ""
+ !insertmacro MUI_WELCOMEPAGE_INTERFACE
+
+ !insertmacro MUI_WELCOMEPAGE_GUIINIT
+
+ !insertmacro MUI_DEFAULT MUI_WELCOMEPAGE_TITLE "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_WELCOME_INFO_TITLE)"
+ !insertmacro MUI_DEFAULT MUI_WELCOMEPAGE_TEXT "$(MUI_${MUI_PAGE_UNINSTALLER_PREFIX}TEXT_WELCOME_INFO_TEXT)"
+
+ !insertmacro MUI_PAGE_FUNCTION_FULLWINDOW
+
+ PageEx ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}custom
+
+ PageCallbacks ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.WelcomePre_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.WelcomeLeave_${MUI_UNIQUEID}
+
+ PageExEnd
+
+ !insertmacro MUI_FUNCTION_WELCOMEPAGE ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.WelcomePre_${MUI_UNIQUEID} ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}mui.WelcomeLeave_${MUI_UNIQUEID}
+
+ !insertmacro MUI_UNSET MUI_WELCOMEPAGE_TITLE
+ !insertmacro MUI_UNSET MUI_WELCOMEPAGE_TITLE_3LINES
+ !insertmacro MUI_UNSET MUI_WELCOMEPAGE_TEXT
+
+!macroend
+
+!macro MUI_PAGE_WELCOME
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_PAGE_INIT
+ !insertmacro MUI_PAGEDECLARATION_WELCOME
+
+ !verbose pop
+
+!macroend
+
+!macro MUI_UNPAGE_WELCOME
+
+ !verbose push
+ !verbose ${MUI_VERBOSE}
+
+ !insertmacro MUI_UNPAGE_INIT
+ !insertmacro MUI_PAGEDECLARATION_WELCOME
+
+ !verbose pop
+
+!macroend
+
+
+;--------------------------------
+;Page functions
+
+!macro MUI_FUNCTION_WELCOMEPAGE PRE LEAVE
+
+ Function "${PRE}"
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM PRE
+
+ ;Create dialog
+ nsDialogs::Create 1044
+ Pop $mui.WelcomePage
+ nsDialogs::SetRTL $(^RTL)
+ SetCtlColors $mui.WelcomePage "" "${MUI_BGCOLOR}"
+
+ ;Image control
+ ${NSD_CreateBitmap} 0u 0u 109u 193u ""
+ Pop $mui.WelcomePage.Image
+ !insertmacro MUI_INTERNAL_FULLWINDOW_LOADWIZARDIMAGE "${MUI_PAGE_UNINSTALLER_PREFIX}" $mui.WelcomePage.Image $PLUGINSDIR\modern-wizard.bmp $mui.WelcomePage.Image.Bitmap
+
+ ;Positiong of controls
+
+ ;Title
+ !ifndef MUI_WELCOMEPAGE_TITLE_3LINES
+ !define MUI_WELCOMEPAGE_TITLE_HEIGHT 28
+ !else
+ !define MUI_WELCOMEPAGE_TITLE_HEIGHT 38
+ !endif
+
+ ;Text
+ ;17 = 10 (top margin) + 7 (distance between texts)
+ !define /math MUI_WELCOMEPAGE_TEXT_TOP 17 + ${MUI_WELCOMEPAGE_TITLE_HEIGHT}
+
+ ;Title
+ ${NSD_CreateLabel} 120u 10u 195u ${MUI_WELCOMEPAGE_TITLE_HEIGHT}u "${MUI_WELCOMEPAGE_TITLE}"
+ Pop $mui.WelcomePage.Title
+ SetCtlColors $mui.WelcomePage.Title "${MUI_TEXTCOLOR}" "${MUI_BGCOLOR}"
+ CreateFont $mui.WelcomePage.Title.Font "$(^Font)" "12" "700"
+ SendMessage $mui.WelcomePage.Title ${WM_SETFONT} $mui.WelcomePage.Title.Font 0
+
+ ;Welcome text
+ ${NSD_CreateLabel} 120u ${MUI_WELCOMEPAGE_TEXT_TOP}u 195u 130u "${MUI_WELCOMEPAGE_TEXT}"
+ Pop $mui.WelcomePage.Text
+ SetCtlColors $mui.WelcomePage.Text "${MUI_TEXTCOLOR}" "${MUI_BGCOLOR}"
+
+ ;Show page
+ Call ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}muiPageLoadFullWindow
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM SHOW
+ nsDialogs::Show
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM DESTROYED
+ Call ${MUI_PAGE_UNINSTALLER_FUNCPREFIX}muiPageUnloadFullWindow
+
+ ;Delete image from memory
+ ${NSD_FreeImage} $mui.WelcomePage.Image.Bitmap
+
+ !insertmacro MUI_UNSET MUI_WELCOMEPAGE_TITLE_HEIGHT
+ !insertmacro MUI_UNSET MUI_WELCOMEPAGE_TEXT_TOP
+
+ FunctionEnd
+
+ Function "${LEAVE}"
+
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM LEAVE
+
+ FunctionEnd
+
+!macroend
diff --git a/installer/tools/Contrib/UIs/modern.exe b/installer/tools/Contrib/UIs/modern.exe
new file mode 100644
index 00000000..45db1de6
Binary files /dev/null and b/installer/tools/Contrib/UIs/modern.exe differ
diff --git a/installer/tools/Contrib/UIs/modern_headerbmp.exe b/installer/tools/Contrib/UIs/modern_headerbmp.exe
new file mode 100644
index 00000000..7ccc53bf
Binary files /dev/null and b/installer/tools/Contrib/UIs/modern_headerbmp.exe differ
diff --git a/installer/tools/Include/Colors.nsh b/installer/tools/Include/Colors.nsh
new file mode 100644
index 00000000..64ca3a1e
--- /dev/null
+++ b/installer/tools/Include/Colors.nsh
@@ -0,0 +1,75 @@
+!ifndef COLORS_NSH
+!define COLORS_NSH
+
+!verbose push
+!verbose 3
+
+# Squad
+# Rob Segal
+# Joel
+# Yathosho
+
+
+# Predefined HTML Hex colors
+!define WHITE "FFFFFF"
+!define BLACK "000000"
+!define YELLOW "FFFF00"
+!define RED "FF0000"
+!define GREEN "00FF00"
+!define BLUE "0000FF"
+!define MAGENTA "FF00FF"
+!define CYAN "00FFFF"
+
+# Function to convert red , green and blue integer values to HTML Hex format
+!define RGB '!insertmacro rgb2hex'
+
+# Function to convert red, green and blue integer values to Hexadecimal (0xRRGGBB) format
+!define HEX '!insertmacro rgb2hex2'
+
+# Function to get the r value from a RGB number
+!define GetRvalue '!insertmacro redvalue'
+
+# Function to get the g value from a RGB number
+!define GetGvalue '!insertmacro greenvalue'
+
+# Function to get the b value from a RGB number
+!define GetBvalue '!insertmacro bluevalue'
+
+# Function to get the r value from a Hex number
+!define GetRvalueX '!insertmacro bluevalue'
+
+# Function to get the g value from a Hex number
+!define GetGvalueX '!insertmacro greenvalue'
+
+# Function to get the r value from a HEX number
+!define GetBvalueX '!insertmacro redvalue'
+
+!macro rgb2hex output R G B
+IntFmt "${output}" "%02X" "${R}"
+IntFmt "${output}" "${output}%02X" "${G}"
+IntFmt "${output}" "${output}%02X" "${B}"
+!macroend
+
+!macro rgb2hex2 output R G B
+IntFmt "${output}" "%02X" "${B}"
+IntFmt "${output}" "${output}%02X" "${G}"
+IntFmt "${output}" "${output}%02X" "${R}"
+!macroend
+
+!macro redvalue output hexval
+StrCpy ${output} ${hexval} 2 0
+IntFmt "${output}" "%02i" "0x${output}"
+!macroend
+
+!macro greenvalue output hexval
+StrCpy ${output} ${hexval} 2 2
+IntFmt "${output}" "%02i" "0x${output}"
+!macroend
+
+!macro bluevalue output hexval
+StrCpy ${output} ${hexval} 2 4
+IntFmt "${output}" "%02i" "0x${output}"
+!macroend
+
+!verbose pop
+!endif
\ No newline at end of file
diff --git a/installer/tools/Include/FileFunc.nsh b/installer/tools/Include/FileFunc.nsh
new file mode 100644
index 00000000..f993da4e
--- /dev/null
+++ b/installer/tools/Include/FileFunc.nsh
@@ -0,0 +1,2012 @@
+/*
+_____________________________________________________________________________
+
+ File Functions Header v3.4
+_____________________________________________________________________________
+
+ 2006 Shengalts Aleksander aka Instructor (Shengalts@mail.ru)
+
+ See documentation for more information about the following functions.
+
+ Usage in script:
+ 1. !include "FileFunc.nsh"
+ 2. [Section|Function]
+ ${FileFunction} "Param1" "Param2" "..." $var
+ [SectionEnd|FunctionEnd]
+
+
+ FileFunction=[Locate|GetSize|DriveSpace|GetDrives|GetTime|GetFileAttributes|
+ GetFileVersion|GetExeName|GetExePath|GetParameters|GetOptions|
+ GetOptionsS|GetRoot|GetParent|GetFileName|GetBaseName|GetFileExt|
+ BannerTrimPath|DirState|RefreshShellIcons]
+
+_____________________________________________________________________________
+
+ Thanks to:
+_____________________________________________________________________________
+
+GetSize
+ KiCHiK (Function "FindFiles")
+DriveSpace
+ sunjammer (Function "CheckSpaceFree")
+GetDrives
+ deguix (Based on his idea of Function "DetectDrives")
+GetTime
+ Takhir (Script "StatTest") and deguix (Function "FileModifiedDate")
+GetFileVersion
+ KiCHiK (Based on his example for command "GetDLLVersion")
+GetParameters
+ sunjammer (Based on his Function "GetParameters")
+GetRoot
+ KiCHiK (Based on his Function "GetRoot")
+GetParent
+ sunjammer (Based on his Function "GetParent")
+GetFileName
+ KiCHiK (Based on his Function "GetFileName")
+GetBaseName
+ comperio (Based on his idea of Function "GetBaseName")
+GetFileExt
+ opher (author)
+RefreshShellIcons
+ jerome tremblay (author)
+*/
+
+
+;_____________________________________________________________________________
+;
+; Macros
+;_____________________________________________________________________________
+;
+; Change log window verbosity (default: 3=no script)
+;
+; Example:
+; !include "FileFunc.nsh"
+; !insertmacro Locate
+; ${FILEFUNC_VERBOSE} 4 # all verbosity
+; !insertmacro VersionCompare
+; ${FILEFUNC_VERBOSE} 3 # no script
+
+!ifndef FILEFUNC_INCLUDED
+
+!verbose push 3
+!define /IfNDef _FILEFUNC_VERBOSE 3
+!verbose ${_FILEFUNC_VERBOSE}
+!define FILEFUNC_VERBOSE `!insertmacro FILEFUNC_VERBOSE`
+
+!define FILEFUNC_INCLUDED
+
+!include Util.nsh
+
+
+!macro FILEFUNC_VERBOSE _VERBOSE
+ !verbose push 3
+ !define /ReDef _FILEFUNC_VERBOSE ${_VERBOSE}
+ !verbose pop
+!macroend
+
+!macro LocateCall _PATH _OPTIONS _FUNC
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push $0
+ Push `${_PATH}`
+ Push `${_OPTIONS}`
+ GetFunctionAddress $0 `${_FUNC}`
+ Push `$0`
+ ${CallArtificialFunction} Locate_
+ Pop $0
+ !verbose pop
+!macroend
+
+!macro GetSizeCall _PATH _OPTIONS _RESULT1 _RESULT2 _RESULT3
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push `${_PATH}`
+ Push `${_OPTIONS}`
+ ${CallArtificialFunction} GetSize_
+ Pop ${_RESULT1}
+ Pop ${_RESULT2}
+ Pop ${_RESULT3}
+ !verbose pop
+!macroend
+
+!macro DriveSpaceCall _DRIVE _OPTIONS _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push `${_DRIVE}`
+ Push `${_OPTIONS}`
+ ${CallArtificialFunction} DriveSpace_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro GetDrivesCall _DRV _FUNC
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push $0
+ Push `${_DRV}`
+ GetFunctionAddress $0 `${_FUNC}`
+ Push `$0`
+ ${CallArtificialFunction} GetDrives_
+ Pop $0
+ !verbose pop
+!macroend
+
+!macro GetTimeCall _FILE _OPTION _RESULT1 _RESULT2 _RESULT3 _RESULT4 _RESULT5 _RESULT6 _RESULT7
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push `${_FILE}`
+ Push `${_OPTION}`
+ ${CallArtificialFunction} GetTime_
+ Pop ${_RESULT1}
+ Pop ${_RESULT2}
+ Pop ${_RESULT3}
+ Pop ${_RESULT4}
+ Pop ${_RESULT5}
+ Pop ${_RESULT6}
+ Pop ${_RESULT7}
+ !verbose pop
+!macroend
+
+!macro GetFileAttributesCall _PATH _ATTR _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push `${_PATH}`
+ Push `${_ATTR}`
+ ${CallArtificialFunction} GetFileAttributes_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro GetFileVersionCall _FILE _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push `${_FILE}`
+ ${CallArtificialFunction} GetFileVersion_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro GetExeNameCall _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ ${CallArtificialFunction} GetExeName_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro GetExePathCall _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ ${CallArtificialFunction} GetExePath_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro GetParametersCall _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ ${CallArtificialFunction} GetParameters_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro GetOptionsCall _PARAMETERS _OPTION _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push `${_PARAMETERS}`
+ Push `${_OPTION}`
+ ${CallArtificialFunction} GetOptions_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro GetOptionsSCall _PARAMETERS _OPTION _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push `${_PARAMETERS}`
+ Push `${_OPTION}`
+ ${CallArtificialFunction} GetOptionsS_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro GetRootCall _FULLPATH _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push `${_FULLPATH}`
+ ${CallArtificialFunction} GetRoot_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro GetParentCall _PATHSTRING _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push `${_PATHSTRING}`
+ ${CallArtificialFunction} GetParent_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro GetFileNameCall _PATHSTRING _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push `${_PATHSTRING}`
+ ${CallArtificialFunction} GetFileName_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro GetBaseNameCall _FILESTRING _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push `${_FILESTRING}`
+ ${CallArtificialFunction} GetBaseName_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro GetFileExtCall _FILESTRING _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push `${_FILESTRING}`
+ ${CallArtificialFunction} GetFileExt_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro BannerTrimPathCall _PATH _LENGHT _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push `${_PATH}`
+ Push `${_LENGHT}`
+ ${CallArtificialFunction} BannerTrimPath_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro DirStateCall _PATH _RESULT
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ Push `${_PATH}`
+ ${CallArtificialFunction} DirState_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro RefreshShellIconsCall
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+ ${CallArtificialFunction} RefreshShellIcons_
+ !verbose pop
+!macroend
+
+!define Locate `!insertmacro LocateCall`
+!define un.Locate `!insertmacro LocateCall`
+
+!macro Locate
+!macroend
+
+!macro un.Locate
+!macroend
+
+!macro Locate_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Exch $2
+ Exch
+ Exch $1
+ Exch
+ Exch 2
+ Exch $0
+ Exch 2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $8
+ Push $9
+ Push $R6
+ Push $R7
+ Push $R8
+ Push $R9
+ ClearErrors
+
+ StrCpy $3 ''
+ StrCpy $4 ''
+ StrCpy $5 ''
+ StrCpy $6 ''
+ StrCpy $7 ''
+ StrCpy $8 0
+ StrCpy $R7 ''
+
+ StrCpy $R9 $0 1 -1
+ StrCmp $R9 '\' 0 +3
+ StrCpy $0 $0 -1
+ goto -3
+ IfFileExists '$0\*.*' 0 FileFunc_Locate_error
+
+ FileFunc_Locate_option:
+ StrCpy $R9 $1 1
+ StrCpy $1 $1 '' 1
+ StrCmp $R9 ' ' -2
+ StrCmp $R9 '' FileFunc_Locate_sizeset
+ StrCmp $R9 '/' 0 -4
+ StrCpy $9 -1
+ IntOp $9 $9 + 1
+ StrCpy $R9 $1 1 $9
+ StrCmp $R9 '' +2
+ StrCmp $R9 '/' 0 -3
+ StrCpy $R8 $1 $9
+ StrCpy $R8 $R8 '' 2
+ StrCpy $R9 $R8 '' -1
+ StrCmp $R9 ' ' 0 +3
+ StrCpy $R8 $R8 -1
+ goto -3
+ StrCpy $R9 $1 2
+ StrCpy $1 $1 '' $9
+
+ StrCmp $R9 'L=' 0 FileFunc_Locate_mask
+ StrCpy $3 $R8
+ StrCmp $3 '' +6
+ StrCmp $3 'FD' +5
+ StrCmp $3 'F' +4
+ StrCmp $3 'D' +3
+ StrCmp $3 'DE' +2
+ StrCmp $3 'FDE' 0 FileFunc_Locate_error
+ goto FileFunc_Locate_option
+
+ FileFunc_Locate_mask:
+ StrCmp $R9 'M=' 0 FileFunc_Locate_size
+ StrCpy $4 $R8
+ goto FileFunc_Locate_option
+
+ FileFunc_Locate_size:
+ StrCmp $R9 'S=' 0 FileFunc_Locate_gotosubdir
+ StrCpy $6 $R8
+ goto FileFunc_Locate_option
+
+ FileFunc_Locate_gotosubdir:
+ StrCmp $R9 'G=' 0 FileFunc_Locate_banner
+ StrCpy $7 $R8
+ StrCmp $7 '' +3
+ StrCmp $7 '1' +2
+ StrCmp $7 '0' 0 FileFunc_Locate_error
+ goto FileFunc_Locate_option
+
+ FileFunc_Locate_banner:
+ StrCmp $R9 'B=' 0 FileFunc_Locate_error
+ StrCpy $R7 $R8
+ StrCmp $R7 '' +3
+ StrCmp $R7 '1' +2
+ StrCmp $R7 '0' 0 FileFunc_Locate_error
+ goto FileFunc_Locate_option
+
+ FileFunc_Locate_sizeset:
+ StrCmp $6 '' FileFunc_Locate_default
+ StrCpy $9 0
+ StrCpy $R9 $6 1 $9
+ StrCmp $R9 '' +4
+ StrCmp $R9 ':' +3
+ IntOp $9 $9 + 1
+ goto -4
+ StrCpy $5 $6 $9
+ IntOp $9 $9 + 1
+ StrCpy $1 $6 1 -1
+ StrCpy $6 $6 -1 $9
+ StrCmp $5 '' +2
+ IntOp $5 $5 + 0
+ StrCmp $6 '' +2
+ IntOp $6 $6 + 0
+
+ StrCmp $1 'B' 0 +3
+ StrCpy $1 1
+ goto FileFunc_Locate_default
+ StrCmp $1 'K' 0 +3
+ StrCpy $1 1024
+ goto FileFunc_Locate_default
+ StrCmp $1 'M' 0 +3
+ StrCpy $1 1048576
+ goto FileFunc_Locate_default
+ StrCmp $1 'G' 0 FileFunc_Locate_error
+ StrCpy $1 1073741824
+
+ FileFunc_Locate_default:
+ StrCmp $3 '' 0 +2
+ StrCpy $3 'FD'
+ StrCmp $4 '' 0 +2
+ StrCpy $4 '*.*'
+ StrCmp $7 '' 0 +2
+ StrCpy $7 '1'
+ StrCmp $R7 '' 0 +2
+ StrCpy $R7 '0'
+ StrCpy $7 'G$7B$R7'
+
+ StrCpy $8 1
+ Push $0
+ SetDetailsPrint textonly
+
+ FileFunc_Locate_nextdir:
+ IntOp $8 $8 - 1
+ Pop $R8
+
+ StrCpy $9 $7 2 2
+ StrCmp $9 'B0' +3
+ GetLabelAddress $9 FileFunc_Locate_findfirst
+ goto call
+ DetailPrint 'Search in: $R8'
+
+ FileFunc_Locate_findfirst:
+ FindFirst $0 $R7 '$R8\$4'
+ IfErrors FileFunc_Locate_subdir
+ StrCmp $R7 '.' 0 FileFunc_Locate_dir
+ FindNext $0 $R7
+ StrCmp $R7 '..' 0 FileFunc_Locate_dir
+ FindNext $0 $R7
+ IfErrors 0 FileFunc_Locate_dir
+ FindClose $0
+ goto FileFunc_Locate_subdir
+
+ FileFunc_Locate_dir:
+ IfFileExists '$R8\$R7\*.*' 0 FileFunc_Locate_file
+ StrCpy $R6 ''
+ StrCmp $3 'DE' +4
+ StrCmp $3 'FDE' +3
+ StrCmp $3 'FD' FileFunc_Locate_precall
+ StrCmp $3 'F' FileFunc_Locate_findnext FileFunc_Locate_precall
+ FindFirst $9 $R9 '$R8\$R7\*.*'
+ StrCmp $R9 '.' 0 +4
+ FindNext $9 $R9
+ StrCmp $R9 '..' 0 +2
+ FindNext $9 $R9
+ FindClose $9
+ IfErrors FileFunc_Locate_precall FileFunc_Locate_findnext
+
+ FileFunc_Locate_file:
+ StrCmp $3 'FDE' +3
+ StrCmp $3 'FD' +2
+ StrCmp $3 'F' 0 FileFunc_Locate_findnext
+ StrCpy $R6 0
+ StrCmp $5$6 '' FileFunc_Locate_precall
+ FileOpen $9 '$R8\$R7' r
+ IfErrors +3
+ FileSeek $9 0 END $R6
+ FileClose $9
+ System::Int64Op $R6 / $1
+ Pop $R6
+ StrCmp $5 '' +2
+ IntCmp $R6 $5 0 FileFunc_Locate_findnext
+ StrCmp $6 '' +2
+ IntCmp $R6 $6 0 0 FileFunc_Locate_findnext
+
+ FileFunc_Locate_precall:
+ StrCpy $9 0
+ StrCpy $R9 '$R8\$R7'
+
+ call:
+ Push $0
+ Push $1
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $8
+ Push $9
+ Push $R7
+ Push $R8
+ StrCmp $9 0 +4
+ StrCpy $R6 ''
+ StrCpy $R7 ''
+ StrCpy $R9 ''
+ Call $2
+ Pop $R9
+ Pop $R8
+ Pop $R7
+ Pop $9
+ Pop $8
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+
+ IfErrors 0 +3
+ FindClose $0
+ goto FileFunc_Locate_error
+ StrCmp $R9 'StopLocate' 0 +3
+ FindClose $0
+ goto FileFunc_Locate_clearstack
+ goto $9
+
+ FileFunc_Locate_findnext:
+ FindNext $0 $R7
+ IfErrors 0 FileFunc_Locate_dir
+ FindClose $0
+
+ FileFunc_Locate_subdir:
+ StrCpy $9 $7 2
+ StrCmp $9 'G0' FileFunc_Locate_end
+ FindFirst $0 $R7 '$R8\*.*'
+ StrCmp $R7 '.' 0 FileFunc_Locate_pushdir
+ FindNext $0 $R7
+ StrCmp $R7 '..' 0 FileFunc_Locate_pushdir
+ FindNext $0 $R7
+ IfErrors 0 FileFunc_Locate_pushdir
+ FindClose $0
+ StrCmp $8 0 FileFunc_Locate_end FileFunc_Locate_nextdir
+
+ FileFunc_Locate_pushdir:
+ IfFileExists '$R8\$R7\*.*' 0 +3
+ Push '$R8\$R7'
+ IntOp $8 $8 + 1
+ FindNext $0 $R7
+ IfErrors 0 FileFunc_Locate_pushdir
+ FindClose $0
+ StrCmp $8 0 FileFunc_Locate_end FileFunc_Locate_nextdir
+
+ FileFunc_Locate_error:
+ SetErrors
+
+ FileFunc_Locate_clearstack:
+ StrCmp $8 0 FileFunc_Locate_end
+ IntOp $8 $8 - 1
+ Pop $R8
+ goto FileFunc_Locate_clearstack
+
+ FileFunc_Locate_end:
+ SetDetailsPrint both
+ Pop $R9
+ Pop $R8
+ Pop $R7
+ Pop $R6
+ Pop $9
+ Pop $8
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+
+ !verbose pop
+!macroend
+
+!define GetSize `!insertmacro GetSizeCall`
+!define un.GetSize `!insertmacro GetSizeCall`
+
+!macro GetSize
+!macroend
+
+!macro un.GetSize
+!macroend
+
+!macro GetSize_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $8
+ Push $9
+ Push $R3
+ Push $R4
+ Push $R5
+ Push $R6
+ Push $R7
+ Push $R8
+ Push $R9
+ ClearErrors
+
+ StrCpy $R9 $0 1 -1
+ StrCmp $R9 '\' 0 +3
+ StrCpy $0 $0 -1
+ goto -3
+ IfFileExists '$0\*.*' 0 FileFunc_GetSize_error
+
+ StrCpy $3 ''
+ StrCpy $4 ''
+ StrCpy $5 ''
+ StrCpy $6 ''
+ StrCpy $8 0
+ StrCpy $R3 ''
+ StrCpy $R4 ''
+ StrCpy $R5 ''
+
+ FileFunc_GetSize_option:
+ StrCpy $R9 $1 1
+ StrCpy $1 $1 '' 1
+ StrCmp $R9 ' ' -2
+ StrCmp $R9 '' FileFunc_GetSize_sizeset
+ StrCmp $R9 '/' 0 -4
+
+ StrCpy $9 -1
+ IntOp $9 $9 + 1
+ StrCpy $R9 $1 1 $9
+ StrCmp $R9 '' +2
+ StrCmp $R9 '/' 0 -3
+ StrCpy $8 $1 $9
+ StrCpy $8 $8 '' 2
+ StrCpy $R9 $8 '' -1
+ StrCmp $R9 ' ' 0 +3
+ StrCpy $8 $8 -1
+ goto -3
+ StrCpy $R9 $1 2
+ StrCpy $1 $1 '' $9
+
+ StrCmp $R9 'M=' 0 FileFunc_GetSize_size
+ StrCpy $4 $8
+ goto FileFunc_GetSize_option
+
+ FileFunc_GetSize_size:
+ StrCmp $R9 'S=' 0 FileFunc_GetSize_gotosubdir
+ StrCpy $6 $8
+ goto FileFunc_GetSize_option
+
+ FileFunc_GetSize_gotosubdir:
+ StrCmp $R9 'G=' 0 FileFunc_GetSize_error
+ StrCpy $7 $8
+ StrCmp $7 '' +3
+ StrCmp $7 '1' +2
+ StrCmp $7 '0' 0 FileFunc_GetSize_error
+ goto FileFunc_GetSize_option
+
+ FileFunc_GetSize_sizeset:
+ StrCmp $6 '' FileFunc_GetSize_default
+ StrCpy $9 0
+ StrCpy $R9 $6 1 $9
+ StrCmp $R9 '' +4
+ StrCmp $R9 ':' +3
+ IntOp $9 $9 + 1
+ goto -4
+ StrCpy $5 $6 $9
+ IntOp $9 $9 + 1
+ StrCpy $1 $6 1 -1
+ StrCpy $6 $6 -1 $9
+ StrCmp $5 '' +2
+ IntOp $5 $5 + 0
+ StrCmp $6 '' +2
+ IntOp $6 $6 + 0
+
+ StrCmp $1 'B' 0 +4
+ StrCpy $1 1
+ StrCpy $2 bytes
+ goto FileFunc_GetSize_default
+ StrCmp $1 'K' 0 +4
+ StrCpy $1 1024
+ StrCpy $2 Kb
+ goto FileFunc_GetSize_default
+ StrCmp $1 'M' 0 +4
+ StrCpy $1 1048576
+ StrCpy $2 Mb
+ goto FileFunc_GetSize_default
+ StrCmp $1 'G' 0 FileFunc_GetSize_error
+ StrCpy $1 1073741824
+ StrCpy $2 Gb
+
+ FileFunc_GetSize_default:
+ StrCmp $4 '' 0 +2
+ StrCpy $4 '*.*'
+ StrCmp $7 '' 0 +2
+ StrCpy $7 '1'
+
+ StrCpy $8 1
+ Push $0
+ SetDetailsPrint textonly
+
+ FileFunc_GetSize_nextdir:
+ IntOp $8 $8 - 1
+ Pop $R8
+ FindFirst $0 $R7 '$R8\$4'
+ IfErrors FileFunc_GetSize_show
+ StrCmp $R7 '.' 0 FileFunc_GetSize_dir
+ FindNext $0 $R7
+ StrCmp $R7 '..' 0 FileFunc_GetSize_dir
+ FindNext $0 $R7
+ IfErrors 0 FileFunc_GetSize_dir
+ FindClose $0
+ goto FileFunc_GetSize_show
+
+ FileFunc_GetSize_dir:
+ IfFileExists '$R8\$R7\*.*' 0 FileFunc_GetSize_file
+ IntOp $R5 $R5 + 1
+ goto FileFunc_GetSize_findnext
+
+ FileFunc_GetSize_file:
+ StrCpy $R6 0
+ StrCmp $5$6 '' 0 +3
+ IntOp $R4 $R4 + 1
+ goto FileFunc_GetSize_findnext
+ FileOpen $9 '$R8\$R7' r
+ IfErrors +3
+ FileSeek $9 0 END $R6
+ FileClose $9
+ StrCmp $5 '' +2
+ IntCmp $R6 $5 0 FileFunc_GetSize_findnext
+ StrCmp $6 '' +2
+ IntCmp $R6 $6 0 0 FileFunc_GetSize_findnext
+ IntOp $R4 $R4 + 1
+ System::Int64Op $R3 + $R6
+ Pop $R3
+
+ FileFunc_GetSize_findnext:
+ FindNext $0 $R7
+ IfErrors 0 FileFunc_GetSize_dir
+ FindClose $0
+
+ FileFunc_GetSize_show:
+ StrCmp $5$6 '' FileFunc_GetSize_nosize
+ System::Int64Op $R3 / $1
+ Pop $9
+ DetailPrint 'Size:$9 $2 Files:$R4 Folders:$R5'
+ goto FileFunc_GetSize_subdir
+ FileFunc_GetSize_nosize:
+ DetailPrint 'Files:$R4 Folders:$R5'
+
+ FileFunc_GetSize_subdir:
+ StrCmp $7 0 FileFunc_GetSize_preend
+ FindFirst $0 $R7 '$R8\*.*'
+ StrCmp $R7 '.' 0 FileFunc_GetSize_pushdir
+ FindNext $0 $R7
+ StrCmp $R7 '..' 0 FileFunc_GetSize_pushdir
+ FindNext $0 $R7
+ IfErrors 0 FileFunc_GetSize_pushdir
+ FindClose $0
+ StrCmp $8 0 FileFunc_GetSize_preend FileFunc_GetSize_nextdir
+
+ FileFunc_GetSize_pushdir:
+ IfFileExists '$R8\$R7\*.*' 0 +3
+ Push '$R8\$R7'
+ IntOp $8 $8 + 1
+ FindNext $0 $R7
+ IfErrors 0 FileFunc_GetSize_pushdir
+ FindClose $0
+ StrCmp $8 0 FileFunc_GetSize_preend FileFunc_GetSize_nextdir
+
+ FileFunc_GetSize_preend:
+ StrCmp $R3 '' FileFunc_GetSize_nosizeend
+ System::Int64Op $R3 / $1
+ Pop $R3
+ FileFunc_GetSize_nosizeend:
+ StrCpy $2 $R4
+ StrCpy $1 $R5
+ StrCpy $0 $R3
+ goto FileFunc_GetSize_end
+
+ FileFunc_GetSize_error:
+ SetErrors
+ StrCpy $0 ''
+ StrCpy $1 ''
+ StrCpy $2 ''
+
+ FileFunc_GetSize_end:
+ SetDetailsPrint both
+ Pop $R9
+ Pop $R8
+ Pop $R7
+ Pop $R6
+ Pop $R5
+ Pop $R4
+ Pop $R3
+ Pop $9
+ Pop $8
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Exch $2
+ Exch
+ Exch $1
+ Exch 2
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define DriveSpace `!insertmacro DriveSpaceCall`
+!define un.DriveSpace `!insertmacro DriveSpaceCall`
+
+!macro DriveSpace
+!macroend
+
+!macro un.DriveSpace
+!macroend
+
+!macro DriveSpace_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ ClearErrors
+
+ StrCpy $2 $0 1 -1
+ StrCmp $2 '\' 0 +3
+ StrCpy $0 $0 -1
+ goto -3
+ IfFileExists '$0\NUL' 0 FileFunc_DriveSpace_error
+
+ StrCpy $5 ''
+ StrCpy $6 ''
+
+ FileFunc_DriveSpace_option:
+ StrCpy $2 $1 1
+ StrCpy $1 $1 '' 1
+ StrCmp $2 ' ' -2
+ StrCmp $2 '' FileFunc_DriveSpace_default
+ StrCmp $2 '/' 0 -4
+ StrCpy $3 -1
+ IntOp $3 $3 + 1
+ StrCpy $2 $1 1 $3
+ StrCmp $2 '' +2
+ StrCmp $2 '/' 0 -3
+ StrCpy $4 $1 $3
+ StrCpy $4 $4 '' 2
+ StrCpy $2 $4 1 -1
+ StrCmp $2 ' ' 0 +3
+ StrCpy $4 $4 -1
+ goto -3
+ StrCpy $2 $1 2
+ StrCpy $1 $1 '' $3
+
+ StrCmp $2 'D=' 0 FileFunc_DriveSpace_unit
+ StrCpy $5 $4
+ StrCmp $5 '' +4
+ StrCmp $5 'T' +3
+ StrCmp $5 'O' +2
+ StrCmp $5 'F' 0 FileFunc_DriveSpace_error
+ goto FileFunc_DriveSpace_option
+
+ FileFunc_DriveSpace_unit:
+ StrCmp $2 'S=' 0 FileFunc_DriveSpace_error
+ StrCpy $6 $4
+ goto FileFunc_DriveSpace_option
+
+ FileFunc_DriveSpace_default:
+ StrCmp $5 '' 0 +2
+ StrCpy $5 'T'
+ StrCmp $6 '' 0 +3
+ StrCpy $6 '1'
+ goto FileFunc_DriveSpace_getspace
+
+ StrCmp $6 'B' 0 +3
+ StrCpy $6 1
+ goto FileFunc_DriveSpace_getspace
+ StrCmp $6 'K' 0 +3
+ StrCpy $6 1024
+ goto FileFunc_DriveSpace_getspace
+ StrCmp $6 'M' 0 +3
+ StrCpy $6 1048576
+ goto FileFunc_DriveSpace_getspace
+ StrCmp $6 'G' 0 FileFunc_DriveSpace_error
+ StrCpy $6 1073741824
+
+ FileFunc_DriveSpace_getspace:
+ System::Call 'kernel32::GetDiskFreeSpaceEx(t, *l, *l, *l)i(r0,.r2,.r3,.)'
+
+ StrCmp $5 T 0 +3
+ StrCpy $0 $3
+ goto FileFunc_DriveSpace_getsize
+ StrCmp $5 O 0 +4
+ System::Int64Op $3 - $2
+ Pop $0
+ goto FileFunc_DriveSpace_getsize
+ StrCmp $5 F 0 +2
+ StrCpy $0 $2
+
+ FileFunc_DriveSpace_getsize:
+ System::Int64Op $0 / $6
+ Pop $0
+ goto FileFunc_DriveSpace_end
+
+ FileFunc_DriveSpace_error:
+ SetErrors
+ StrCpy $0 ''
+
+ FileFunc_DriveSpace_end:
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define GetDrives `!insertmacro GetDrivesCall`
+!define un.GetDrives `!insertmacro GetDrivesCall`
+
+!macro GetDrives
+!macroend
+
+!macro un.GetDrives
+!macroend
+
+!macro GetDrives_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $8
+ Push $9
+
+ System::StrAlloc 1024
+ Pop $2
+ System::Call 'kernel32::GetLogicalDriveStrings(i,i) i(1024, r2)'
+
+ StrCmp $0 ALL FileFunc_GetDrives_drivestring
+ StrCmp $0 '' 0 FileFunc_GetDrives_typeset
+ StrCpy $0 ALL
+ goto FileFunc_GetDrives_drivestring
+
+ FileFunc_GetDrives_typeset:
+ StrCpy $6 -1
+ IntOp $6 $6 + 1
+ StrCpy $8 $0 1 $6
+ StrCmp $8$0 '' FileFunc_GetDrives_enumex
+ StrCmp $8 '' +2
+ StrCmp $8 '+' 0 -4
+ StrCpy $8 $0 $6
+ IntOp $6 $6 + 1
+ StrCpy $0 $0 '' $6
+
+ StrCmp $8 'FDD' 0 +3
+ StrCpy $6 2
+ goto FileFunc_GetDrives_drivestring
+ StrCmp $8 'HDD' 0 +3
+ StrCpy $6 3
+ goto FileFunc_GetDrives_drivestring
+ StrCmp $8 'NET' 0 +3
+ StrCpy $6 4
+ goto FileFunc_GetDrives_drivestring
+ StrCmp $8 'CDROM' 0 +3
+ StrCpy $6 5
+ goto FileFunc_GetDrives_drivestring
+ StrCmp $8 'RAM' 0 FileFunc_GetDrives_typeset
+ StrCpy $6 6
+
+ FileFunc_GetDrives_drivestring:
+ StrCpy $3 $2
+
+ FileFunc_GetDrives_enumok:
+ System::Call 'kernel32::lstrlen(t) i(i r3) .r4'
+ StrCmp $4$0 '0ALL' FileFunc_GetDrives_enumex
+ StrCmp $4 0 FileFunc_GetDrives_typeset
+ System::Call 'kernel32::GetDriveType(t) i(i r3) .r5'
+
+ StrCmp $0 ALL +2
+ StrCmp $5 $6 FileFunc_GetDrives_letter FileFunc_GetDrives_enumnext
+ StrCmp $5 2 0 +3
+ StrCpy $8 FDD
+ goto FileFunc_GetDrives_letter
+ StrCmp $5 3 0 +3
+ StrCpy $8 HDD
+ goto FileFunc_GetDrives_letter
+ StrCmp $5 4 0 +3
+ StrCpy $8 NET
+ goto FileFunc_GetDrives_letter
+ StrCmp $5 5 0 +3
+ StrCpy $8 CDROM
+ goto FileFunc_GetDrives_letter
+ StrCmp $5 6 0 FileFunc_GetDrives_enumex
+ StrCpy $8 RAM
+
+ FileFunc_GetDrives_letter:
+ System::Call '*$3(&t1024 .r9)'
+
+ Push $0
+ Push $1
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $8
+ Call $1
+ Pop $9
+ Pop $8
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+ StrCmp $9 'StopGetDrives' FileFunc_GetDrives_enumex
+
+ FileFunc_GetDrives_enumnext:
+ IntOp $4 $4 * ${NSIS_CHAR_SIZE}
+ IntOp $3 $3 + $4
+ IntOp $3 $3 + ${NSIS_CHAR_SIZE}
+ goto FileFunc_GetDrives_enumok
+
+ FileFunc_GetDrives_enumex:
+ System::Free $2
+
+ Pop $9
+ Pop $8
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+
+ !verbose pop
+!macroend
+
+!define GetTime `!insertmacro GetTimeCall`
+!define un.GetTime `!insertmacro GetTimeCall`
+
+!macro GetTime
+!macroend
+
+!macro un.GetTime
+!macroend
+
+!macro GetTime_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ ClearErrors
+
+ StrCmp $1 'L' FileFunc_GetTime_gettime
+ StrCmp $1 'A' FileFunc_GetTime_getfile
+ StrCmp $1 'C' FileFunc_GetTime_getfile
+ StrCmp $1 'M' FileFunc_GetTime_getfile
+ StrCmp $1 'LS' FileFunc_GetTime_gettime
+ StrCmp $1 'AS' FileFunc_GetTime_getfile
+ StrCmp $1 'CS' FileFunc_GetTime_getfile
+ StrCmp $1 'MS' FileFunc_GetTime_getfile
+ goto FileFunc_GetTime_error
+
+ FileFunc_GetTime_getfile:
+ IfFileExists $0 0 FileFunc_GetTime_error
+ System::Call '*(i,l,l,l,i,i,i,i,&t260,&t14) p .r6'
+ System::Call 'kernel32::FindFirstFile(t,p)p(r0,r6) .r2'
+ System::Call 'kernel32::FindClose(i)i(r2)'
+
+ FileFunc_GetTime_gettime:
+ System::Call '*(&i2,&i2,&i2,&i2,&i2,&i2,&i2,&i2) p .r7'
+ StrCmp $1 'L' 0 FileFunc_GetTime_systemtime
+ System::Call 'kernel32::GetLocalTime(p)i(r7)'
+ goto FileFunc_GetTime_convert
+ FileFunc_GetTime_systemtime:
+ StrCmp $1 'LS' 0 FileFunc_GetTime_filetime
+ System::Call 'kernel32::GetSystemTime(p)i(r7)'
+ goto FileFunc_GetTime_convert
+
+ FileFunc_GetTime_filetime:
+ System::Call '*$6(i,l,l,l,i,i,i,i,&t260,&t14)p(,.r4,.r3,.r2)'
+ System::Free $6
+ StrCmp $1 'A' 0 +3
+ StrCpy $2 $3
+ goto FileFunc_GetTime_tolocal
+ StrCmp $1 'C' 0 +3
+ StrCpy $2 $4
+ goto FileFunc_GetTime_tolocal
+ StrCmp $1 'M' FileFunc_GetTime_tolocal
+
+ StrCmp $1 'AS' FileFunc_GetTime_tosystem
+ StrCmp $1 'CS' 0 +3
+ StrCpy $3 $4
+ goto FileFunc_GetTime_tosystem
+ StrCmp $1 'MS' 0 +3
+ StrCpy $3 $2
+ goto FileFunc_GetTime_tosystem
+
+ FileFunc_GetTime_tolocal:
+ System::Call 'kernel32::FileTimeToLocalFileTime(*l,*l)i(r2,.r3)'
+ FileFunc_GetTime_tosystem:
+ System::Call 'kernel32::FileTimeToSystemTime(*l,i)i(r3,r7)'
+
+ FileFunc_GetTime_convert:
+ System::Call '*$7(&i2.r5,&i2.r6,&i2.r4,&i2.r0,&i2.r3,&i2.r2,&i2.r1,&i2)'
+ System::Free $7
+
+ IntFmt $6 "%.2u" $6 ; Month
+ IntFmt $0 "%.2u" $0 ; Day
+ IntFmt $3 "%.2u" $3 ; Hour
+ IntFmt $2 "%.2u" $2 ; Minute
+ IntFmt $1 "%.2u" $1 ; Second
+
+ StrCmp $4 0 0 +3
+ StrCpy $4 Sunday
+ goto FileFunc_GetTime_end
+ StrCmp $4 1 0 +3
+ StrCpy $4 Monday
+ goto FileFunc_GetTime_end
+ StrCmp $4 2 0 +3
+ StrCpy $4 Tuesday
+ goto FileFunc_GetTime_end
+ StrCmp $4 3 0 +3
+ StrCpy $4 Wednesday
+ goto FileFunc_GetTime_end
+ StrCmp $4 4 0 +3
+ StrCpy $4 Thursday
+ goto FileFunc_GetTime_end
+ StrCmp $4 5 0 +3
+ StrCpy $4 Friday
+ goto FileFunc_GetTime_end
+ StrCmp $4 6 0 FileFunc_GetTime_error
+ StrCpy $4 Saturday
+ goto FileFunc_GetTime_end
+
+ FileFunc_GetTime_error:
+ SetErrors
+ StrCpy $0 ''
+ StrCpy $1 ''
+ StrCpy $2 ''
+ StrCpy $3 ''
+ StrCpy $4 ''
+ StrCpy $5 ''
+ StrCpy $6 ''
+
+ FileFunc_GetTime_end:
+ Pop $7
+ Exch $6
+ Exch
+ Exch $5
+ Exch 2
+ Exch $4
+ Exch 3
+ Exch $3
+ Exch 4
+ Exch $2
+ Exch 5
+ Exch $1
+ Exch 6
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define GetFileAttributes `!insertmacro GetFileAttributesCall`
+!define un.GetFileAttributes `!insertmacro GetFileAttributesCall`
+
+!macro GetFileAttributes
+!macroend
+
+!macro un.GetFileAttributes
+!macroend
+
+!macro GetFileAttributes_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+
+ System::Call 'kernel32::GetFileAttributes(t r0)i .r2'
+ StrCmp $2 -1 FileFunc_GetFileAttributes_error
+ StrCpy $3 ''
+
+ IntOp $0 $2 & 0x4000
+ IntCmp $0 0 +2
+ StrCpy $3 'ENCRYPTED|'
+
+ IntOp $0 $2 & 0x2000
+ IntCmp $0 0 +2
+ StrCpy $3 'NOT_CONTENT_INDEXED|$3'
+
+ IntOp $0 $2 & 0x1000
+ IntCmp $0 0 +2
+ StrCpy $3 'OFFLINE|$3'
+
+ IntOp $0 $2 & 0x0800
+ IntCmp $0 0 +2
+ StrCpy $3 'COMPRESSED|$3'
+
+ IntOp $0 $2 & 0x0400
+ IntCmp $0 0 +2
+ StrCpy $3 'REPARSE_POINT|$3'
+
+ IntOp $0 $2 & 0x0200
+ IntCmp $0 0 +2
+ StrCpy $3 'SPARSE_FILE|$3'
+
+ IntOp $0 $2 & 0x0100
+ IntCmp $0 0 +2
+ StrCpy $3 'TEMPORARY|$3'
+
+ IntOp $0 $2 & 0x0080
+ IntCmp $0 0 +2
+ StrCpy $3 'NORMAL|$3'
+
+ IntOp $0 $2 & 0x0040
+ IntCmp $0 0 +2
+ StrCpy $3 'DEVICE|$3'
+
+ IntOp $0 $2 & 0x0020
+ IntCmp $0 0 +2
+ StrCpy $3 'ARCHIVE|$3'
+
+ IntOp $0 $2 & 0x0010
+ IntCmp $0 0 +2
+ StrCpy $3 'DIRECTORY|$3'
+
+ IntOp $0 $2 & 0x0004
+ IntCmp $0 0 +2
+ StrCpy $3 'SYSTEM|$3'
+
+ IntOp $0 $2 & 0x0002
+ IntCmp $0 0 +2
+ StrCpy $3 'HIDDEN|$3'
+
+ IntOp $0 $2 & 0x0001
+ IntCmp $0 0 +2
+ StrCpy $3 'READONLY|$3'
+
+ StrCpy $0 $3 -1
+ StrCmp $1 '' FileFunc_GetFileAttributes_end
+ StrCmp $1 'ALL' FileFunc_GetFileAttributes_end
+
+ FileFunc_GetFileAttributes_attrcmp:
+ StrCpy $5 0
+ IntOp $5 $5 + 1
+ StrCpy $4 $1 1 $5
+ StrCmp $4 '' +2
+ StrCmp $4 '|' 0 -3
+ StrCpy $2 $1 $5
+ IntOp $5 $5 + 1
+ StrCpy $1 $1 '' $5
+ StrLen $3 $2
+ StrCpy $5 -1
+ IntOp $5 $5 + 1
+ StrCpy $4 $0 $3 $5
+ StrCmp $4 '' FileFunc_GetFileAttributes_notfound
+ StrCmp $4 $2 0 -3
+ StrCmp $1 '' 0 FileFunc_GetFileAttributes_attrcmp
+ StrCpy $0 1
+ goto FileFunc_GetFileAttributes_end
+
+ FileFunc_GetFileAttributes_notfound:
+ StrCpy $0 0
+ goto FileFunc_GetFileAttributes_end
+
+ FileFunc_GetFileAttributes_error:
+ SetErrors
+ StrCpy $0 ''
+
+ FileFunc_GetFileAttributes_end:
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define GetFileVersion `!insertmacro GetFileVersionCall`
+!define un.GetFileVersion `!insertmacro GetFileVersionCall`
+
+!macro GetFileVersion
+!macroend
+
+!macro un.GetFileVersion
+!macroend
+
+!macro GetFileVersion_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Exch $0
+ Push $1
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ ClearErrors
+
+ GetDllVersion '$0' $1 $2
+ IfErrors FileFunc_GetFileVersion_error
+ IntOp $3 $1 >> 16
+ IntOp $3 $3 & 0x0000FFFF
+ IntOp $4 $1 & 0x0000FFFF
+ IntOp $5 $2 >> 16
+ IntOp $5 $5 & 0x0000FFFF
+ IntOp $6 $2 & 0x0000FFFF
+ StrCpy $0 '$3.$4.$5.$6'
+ goto FileFunc_GetFileVersion_end
+
+ FileFunc_GetFileVersion_error:
+ SetErrors
+ StrCpy $0 ''
+
+ FileFunc_GetFileVersion_end:
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define GetExeName `!insertmacro GetExeNameCall`
+!define un.GetExeName `!insertmacro GetExeNameCall`
+
+!macro GetExeName
+!macroend
+
+!macro un.GetExeName
+!macroend
+
+!macro GetExeName_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Push $0
+ Push $1
+ Push $2
+ System::Call 'kernel32::GetModuleFileName(p 0, t.r0, i ${NSIS_MAX_STRLEN})'
+ System::Call 'kernel32::GetLongPathName(t r0, t.r1, i ${NSIS_MAX_STRLEN})i.r2'
+ StrCmp $2 error +2
+ StrCpy $0 $1
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define GetExePath `!insertmacro GetExePathCall`
+!define un.GetExePath `!insertmacro GetExePathCall`
+
+!macro GetExePath
+!macroend
+
+!macro un.GetExePath
+!macroend
+
+!macro GetExePath_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Push $0
+ Push $1
+ Push $2
+ StrCpy $0 $EXEDIR
+ System::Call 'kernel32::GetLongPathName(t r0, t.r1, i ${NSIS_MAX_STRLEN})i.r2'
+ StrCmp $2 error +2
+ StrCpy $0 $1
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define GetParameters `!insertmacro GetParametersCall`
+!define un.GetParameters `!insertmacro GetParametersCall`
+
+!macro GetParameters
+!macroend
+
+!macro un.GetParameters
+!macroend
+
+!macro GetParameters_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ ;cmdline-check
+ StrCmp $CMDLINE "" 0 +3
+ Push ""
+ Return
+
+ ;vars
+ Push $0 ;tmp
+ Push $1 ;length
+ Push $2 ;parameter offset
+ Push $3 ;separator
+
+ ;length/offset
+ StrLen $1 $CMDLINE
+ StrCpy $2 2 ;start with third character
+
+ ;separator
+ StrCpy $3 $CMDLINE 1 ;first character
+ StrCmp $3 '"' +2
+ StrCpy $3 ' '
+
+ FileFunc_GetParameters_token: ;finding second separator
+ IntCmp $2 $1 FileFunc_GetParameters_strip 0 FileFunc_GetParameters_strip
+ StrCpy $0 $CMDLINE 1 $2
+ IntOp $2 $2 + 1
+ StrCmp $3 $0 0 FileFunc_GetParameters_token
+
+ FileFunc_GetParameters_strip: ;strip white space
+ IntCmp $2 $1 FileFunc_GetParameters_copy 0 FileFunc_GetParameters_copy
+ StrCpy $0 $CMDLINE 1 $2
+ StrCmp $0 ' ' 0 FileFunc_GetParameters_copy
+ IntOp $2 $2 + 1
+ Goto FileFunc_GetParameters_strip
+
+ FileFunc_GetParameters_copy:
+ StrCpy $0 $CMDLINE "" $2
+
+ ;strip white spaces from end
+ FileFunc_GetParameters_rstrip:
+ StrCpy $1 $0 1 -1
+ StrCmp $1 ' ' 0 FileFunc_GetParameters_done
+ StrCpy $0 $0 -1
+ Goto FileFunc_GetParameters_rstrip
+
+ FileFunc_GetParameters_done:
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!macro GetOptionsBody _FILEFUNC_S
+
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ ClearErrors
+
+ StrCpy $2 $1 '' 1
+ StrCpy $1 $1 1
+ StrLen $3 $2
+ StrCpy $7 0
+
+ FileFunc_GetOptions${_FILEFUNC_S}_begin:
+ StrCpy $4 -1
+ StrCpy $6 ''
+
+ FileFunc_GetOptions${_FILEFUNC_S}_quote:
+ IntOp $4 $4 + 1
+ StrCpy $5 $0 1 $4
+ StrCmp${_FILEFUNC_S} $5$7 '0' FileFunc_GetOptions${_FILEFUNC_S}_notfound
+ StrCmp${_FILEFUNC_S} $5 '' FileFunc_GetOptions${_FILEFUNC_S}_trimright
+ StrCmp${_FILEFUNC_S} $5 '"' 0 +7
+ StrCmp${_FILEFUNC_S} $6 '' 0 +3
+ StrCpy $6 '"'
+ goto FileFunc_GetOptions${_FILEFUNC_S}_quote
+ StrCmp${_FILEFUNC_S} $6 '"' 0 +3
+ StrCpy $6 ''
+ goto FileFunc_GetOptions${_FILEFUNC_S}_quote
+ StrCmp${_FILEFUNC_S} $5 `'` 0 +7
+ StrCmp${_FILEFUNC_S} $6 `` 0 +3
+ StrCpy $6 `'`
+ goto FileFunc_GetOptions${_FILEFUNC_S}_quote
+ StrCmp${_FILEFUNC_S} $6 `'` 0 +3
+ StrCpy $6 ``
+ goto FileFunc_GetOptions${_FILEFUNC_S}_quote
+ StrCmp${_FILEFUNC_S} $5 '`' 0 +7
+ StrCmp${_FILEFUNC_S} $6 '' 0 +3
+ StrCpy $6 '`'
+ goto FileFunc_GetOptions${_FILEFUNC_S}_quote
+ StrCmp${_FILEFUNC_S} $6 '`' 0 +3
+ StrCpy $6 ''
+ goto FileFunc_GetOptions${_FILEFUNC_S}_quote
+ StrCmp${_FILEFUNC_S} $6 '"' FileFunc_GetOptions${_FILEFUNC_S}_quote
+ StrCmp${_FILEFUNC_S} $6 `'` FileFunc_GetOptions${_FILEFUNC_S}_quote
+ StrCmp${_FILEFUNC_S} $6 '`' FileFunc_GetOptions${_FILEFUNC_S}_quote
+ StrCmp${_FILEFUNC_S} $5 $1 0 FileFunc_GetOptions${_FILEFUNC_S}_quote
+ StrCmp${_FILEFUNC_S} $7 0 FileFunc_GetOptions${_FILEFUNC_S}_trimleft FileFunc_GetOptions${_FILEFUNC_S}_trimright
+
+ FileFunc_GetOptions${_FILEFUNC_S}_trimleft:
+ IntOp $4 $4 + 1
+ StrCpy $5 $0 $3 $4
+ StrCmp${_FILEFUNC_S} $5 '' FileFunc_GetOptions${_FILEFUNC_S}_notfound
+ StrCmp${_FILEFUNC_S} $5 $2 0 FileFunc_GetOptions${_FILEFUNC_S}_quote
+ IntOp $4 $4 + $3
+ StrCpy $0 $0 '' $4
+ StrCpy $4 $0 1
+ StrCmp${_FILEFUNC_S} $4 ' ' 0 +3
+ StrCpy $0 $0 '' 1
+ goto -3
+ StrCpy $7 1
+ goto FileFunc_GetOptions${_FILEFUNC_S}_begin
+
+ FileFunc_GetOptions${_FILEFUNC_S}_trimright:
+ StrCpy $0 $0 $4
+ StrCpy $4 $0 1 -1
+ StrCmp${_FILEFUNC_S} $4 ' ' 0 +3
+ StrCpy $0 $0 -1
+ goto -3
+ StrCpy $3 $0 1
+ StrCpy $4 $0 1 -1
+ StrCmp${_FILEFUNC_S} $3 $4 0 FileFunc_GetOptions${_FILEFUNC_S}_end
+ StrCmp${_FILEFUNC_S} $3 '"' +3
+ StrCmp${_FILEFUNC_S} $3 `'` +2
+ StrCmp${_FILEFUNC_S} $3 '`' 0 FileFunc_GetOptions${_FILEFUNC_S}_end
+ StrCpy $0 $0 -1 1
+ goto FileFunc_GetOptions${_FILEFUNC_S}_end
+
+ FileFunc_GetOptions${_FILEFUNC_S}_notfound:
+ SetErrors
+ StrCpy $0 ''
+
+ FileFunc_GetOptions${_FILEFUNC_S}_end:
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+
+!macroend
+
+!define GetOptions `!insertmacro GetOptionsCall`
+!define un.GetOptions `!insertmacro GetOptionsCall`
+
+!macro GetOptions
+!macroend
+
+!macro un.GetOptions
+!macroend
+
+!macro GetOptions_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ !insertmacro GetOptionsBody ''
+
+ !verbose pop
+!macroend
+
+!define GetOptionsS `!insertmacro GetOptionsSCall`
+!define un.GetOptionsS `!insertmacro GetOptionsSCall`
+
+!macro GetOptionsS
+!macroend
+
+!macro un.GetOptionsS
+!macroend
+
+!macro GetOptionsS_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ !insertmacro GetOptionsBody 'S'
+
+ !verbose pop
+!macroend
+
+!define GetRoot `!insertmacro GetRootCall`
+!define un.GetRoot `!insertmacro GetRootCall`
+
+!macro GetRoot
+!macroend
+
+!macro un.GetRoot
+!macroend
+
+!macro GetRoot_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Exch $0
+ Push $1
+ Push $2
+ Push $3
+
+ StrCpy $1 $0 2
+ StrCmp $1 '\\' FileFunc_GetRoot_UNC
+ StrCpy $2 $1 1 1
+ StrCmp $2 ':' 0 FileFunc_GetRoot_empty
+ StrCpy $0 $1
+ goto FileFunc_GetRoot_end
+
+ FileFunc_GetRoot_UNC:
+ StrCpy $2 1
+ StrCpy $3 ''
+
+ FileFunc_GetRoot_loop:
+ IntOp $2 $2 + 1
+ StrCpy $1 $0 1 $2
+ StrCmp $1$3 '' FileFunc_GetRoot_empty
+ StrCmp $1 '' +5
+ StrCmp $1 '\' 0 FileFunc_GetRoot_loop
+ StrCmp $3 '1' +3
+ StrCpy $3 '1'
+ goto FileFunc_GetRoot_loop
+ StrCpy $0 $0 $2
+ StrCpy $2 $0 1 -1
+ StrCmp $2 '\' 0 FileFunc_GetRoot_end
+
+ FileFunc_GetRoot_empty:
+ StrCpy $0 ''
+
+ FileFunc_GetRoot_end:
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define GetParent `!insertmacro GetParentCall`
+!define un.GetParent `!insertmacro GetParentCall`
+
+!macro GetParent
+!macroend
+
+!macro un.GetParent
+!macroend
+
+!macro GetParent_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Exch $0
+ Push $1
+ Push $2
+
+ StrCpy $2 $0 1 -1
+ StrCmp $2 '\' 0 +3
+ StrCpy $0 $0 -1
+ goto -3
+
+ StrCpy $1 0
+ IntOp $1 $1 - 1
+ StrCpy $2 $0 1 $1
+ StrCmp $2 '\' +2
+ StrCmp $2 '' 0 -3
+ StrCpy $0 $0 $1
+
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define GetFileName `!insertmacro GetFileNameCall`
+!define un.GetFileName `!insertmacro GetFileNameCall`
+
+!macro GetFileName
+!macroend
+
+!macro un.GetFileName
+!macroend
+
+!macro GetFileName_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Exch $0
+ Push $1
+ Push $2
+
+ StrCpy $2 $0 1 -1
+ StrCmp $2 '\' 0 +3
+ StrCpy $0 $0 -1
+ goto -3
+
+ StrCpy $1 0
+ IntOp $1 $1 - 1
+ StrCpy $2 $0 1 $1
+ StrCmp $2 '' FileFunc_GetFileName_end
+ StrCmp $2 '\' 0 -3
+ IntOp $1 $1 + 1
+ StrCpy $0 $0 '' $1
+
+ FileFunc_GetFileName_end:
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define GetBaseName `!insertmacro GetBaseNameCall`
+!define un.GetBaseName `!insertmacro GetBaseNameCall`
+
+!macro GetBaseName
+!macroend
+
+!macro un.GetBaseName
+!macroend
+
+!macro GetBaseName_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Exch $0
+ Push $1
+ Push $2
+ Push $3
+
+ StrCpy $1 0
+ StrCpy $3 ''
+
+ FileFunc_GetBaseName_loop:
+ IntOp $1 $1 - 1
+ StrCpy $2 $0 1 $1
+ StrCmp $2 '' FileFunc_GetBaseName_trimpath
+ StrCmp $2 '\' FileFunc_GetBaseName_trimpath
+ StrCmp $3 'noext' FileFunc_GetBaseName_loop
+ StrCmp $2 '.' 0 FileFunc_GetBaseName_loop
+ StrCpy $0 $0 $1
+ StrCpy $3 'noext'
+ StrCpy $1 0
+ goto FileFunc_GetBaseName_loop
+
+ FileFunc_GetBaseName_trimpath:
+ StrCmp $1 -1 FileFunc_GetBaseName_empty
+ IntOp $1 $1 + 1
+ StrCpy $0 $0 '' $1
+ goto FileFunc_GetBaseName_end
+
+ FileFunc_GetBaseName_empty:
+ StrCpy $0 ''
+
+ FileFunc_GetBaseName_end:
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define GetFileExt `!insertmacro GetFileExtCall`
+!define un.GetFileExt `!insertmacro GetFileExtCall`
+
+!macro GetFileExt
+!macroend
+
+!macro un.GetFileExt
+!macroend
+
+!macro GetFileExt_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Exch $0
+ Push $1
+ Push $2
+
+ StrCpy $1 0
+
+ FileFunc_GetFileExt_loop:
+ IntOp $1 $1 - 1
+ StrCpy $2 $0 1 $1
+ StrCmp $2 '' FileFunc_GetFileExt_empty
+ StrCmp $2 '\' FileFunc_GetFileExt_empty
+ StrCmp $2 '.' 0 FileFunc_GetFileExt_loop
+
+ StrCmp $1 -1 FileFunc_GetFileExt_empty
+ IntOp $1 $1 + 1
+ StrCpy $0 $0 '' $1
+ goto FileFunc_GetFileExt_end
+
+ FileFunc_GetFileExt_empty:
+ StrCpy $0 ''
+
+ FileFunc_GetFileExt_end:
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define BannerTrimPath `!insertmacro BannerTrimPathCall`
+!define un.BannerTrimPath `!insertmacro BannerTrimPathCall`
+
+!macro BannerTrimPath
+!macroend
+
+!macro un.BannerTrimPath
+!macroend
+
+!macro BannerTrimPath_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $2
+ Push $3
+ Push $4
+
+ StrCpy $3 $1 1 -1
+ IntOp $1 $1 + 0
+ StrLen $2 $0
+ IntCmp $2 $1 FileFunc_BannerTrimPath_end FileFunc_BannerTrimPath_end
+ IntOp $1 $1 - 3
+ IntCmp $1 0 FileFunc_BannerTrimPath_empty FileFunc_BannerTrimPath_empty
+ StrCmp $3 'A' FileFunc_BannerTrimPath_A-trim
+ StrCmp $3 'B' FileFunc_BannerTrimPath_B-trim
+ StrCmp $3 'C' FileFunc_BannerTrimPath_C-trim
+ StrCmp $3 'D' FileFunc_BannerTrimPath_D-trim
+
+ FileFunc_BannerTrimPath_A-trim:
+ StrCpy $3 $0 1 1
+ StrCpy $2 0
+ StrCmp $3 ':' 0 +2
+ IntOp $2 $2 + 2
+
+ FileFunc_BannerTrimPath_loopleft:
+ IntOp $2 $2 + 1
+ StrCpy $3 $0 1 $2
+ StrCmp $2 $1 FileFunc_BannerTrimPath_C-trim
+ StrCmp $3 '\' 0 FileFunc_BannerTrimPath_loopleft
+ StrCpy $3 $0 $2
+ IntOp $2 $2 - $1
+ IntCmp $2 0 FileFunc_BannerTrimPath_B-trim 0 FileFunc_BannerTrimPath_B-trim
+
+ FileFunc_BannerTrimPath_loopright:
+ IntOp $2 $2 + 1
+ StrCpy $4 $0 1 $2
+ StrCmp $2 0 FileFunc_BannerTrimPath_B-trim
+ StrCmp $4 '\' 0 FileFunc_BannerTrimPath_loopright
+ StrCpy $4 $0 '' $2
+ StrCpy $0 '$3\...$4'
+ goto FileFunc_BannerTrimPath_end
+
+ FileFunc_BannerTrimPath_B-trim:
+ StrCpy $2 $1
+ IntOp $2 $2 - 1
+ StrCmp $2 -1 FileFunc_BannerTrimPath_C-trim
+ StrCpy $3 $0 1 $2
+ StrCmp $3 '\' 0 -3
+ StrCpy $0 $0 $2
+ StrCpy $0 '$0\...'
+ goto FileFunc_BannerTrimPath_end
+
+ FileFunc_BannerTrimPath_C-trim:
+ StrCpy $0 $0 $1
+ StrCpy $0 '$0...'
+ goto FileFunc_BannerTrimPath_end
+
+ FileFunc_BannerTrimPath_D-trim:
+ StrCpy $3 -1
+ IntOp $3 $3 - 1
+ StrCmp $3 -$2 FileFunc_BannerTrimPath_C-trim
+ StrCpy $4 $0 1 $3
+ StrCmp $4 '\' 0 -3
+ StrCpy $4 $0 '' $3
+ IntOp $3 $1 + $3
+ IntCmp $3 2 FileFunc_BannerTrimPath_C-trim FileFunc_BannerTrimPath_C-trim
+ StrCpy $0 $0 $3
+ StrCpy $0 '$0...$4'
+ goto FileFunc_BannerTrimPath_end
+
+ FileFunc_BannerTrimPath_empty:
+ StrCpy $0 ''
+
+ FileFunc_BannerTrimPath_end:
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define DirState `!insertmacro DirStateCall`
+!define un.DirState `!insertmacro DirStateCall`
+
+!macro DirState
+!macroend
+
+!macro un.DirState
+!macroend
+
+!macro DirState_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ Exch $0
+ Push $1
+ ClearErrors
+
+ FindFirst $1 $0 '$0\*.*'
+ IfErrors 0 +3
+ StrCpy $0 -1
+ goto FileFunc_DirState_end
+ StrCmp $0 '.' 0 +4
+ FindNext $1 $0
+ StrCmp $0 '..' 0 +2
+ FindNext $1 $0
+ FindClose $1
+ IfErrors 0 +3
+ StrCpy $0 0
+ goto FileFunc_DirState_end
+ StrCpy $0 1
+
+ FileFunc_DirState_end:
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define RefreshShellIcons `!insertmacro RefreshShellIconsCall`
+!define un.RefreshShellIcons `!insertmacro RefreshShellIconsCall`
+
+!macro RefreshShellIcons
+!macroend
+
+!macro un.RefreshShellIcons
+!macroend
+
+!macro RefreshShellIcons_
+ !verbose push
+ !verbose ${_FILEFUNC_VERBOSE}
+
+ System::Call 'shell32::SHChangeNotify(i 0x08000000, i 0, i 0, i 0)'
+
+ !verbose pop
+!macroend
+
+!verbose pop
+!endif
diff --git a/installer/tools/Include/InstallOptions.nsh b/installer/tools/Include/InstallOptions.nsh
new file mode 100644
index 00000000..04cd5b94
--- /dev/null
+++ b/installer/tools/Include/InstallOptions.nsh
@@ -0,0 +1,244 @@
+/*
+
+InstallOptions.nsh
+Macros and conversion functions for InstallOptions
+
+*/
+
+!ifndef ___NSIS__INSTALL_OPTIONS__NSH___
+!define ___NSIS__INSTALL_OPTIONS__NSH___
+
+!include LogicLib.nsh
+
+!macro INSTALLOPTIONS_FUNCTION_READ_CONVERT
+ !insertmacro INSTALLOPTIONS_FUNCTION_IO2NSIS ""
+!macroend
+
+!macro INSTALLOPTIONS_UNFUNCTION_READ_CONVERT
+ !insertmacro INSTALLOPTIONS_FUNCTION_IO2NSIS un.
+!macroend
+
+!macro INSTALLOPTIONS_FUNCTION_WRITE_CONVERT
+ !insertmacro INSTALLOPTIONS_FUNCTION_NSIS2IO ""
+!macroend
+
+!macro INSTALLOPTIONS_UNFUNCTION_WRITE_CONVERT
+ !insertmacro INSTALLOPTIONS_FUNCTION_NSIS2IO un.
+!macroend
+
+!macro INSTALLOPTIONS_FUNCTION_NSIS2IO UNINSTALLER_FUNCPREFIX
+
+ ; Convert an NSIS string to a form suitable for use by InstallOptions
+ ; Usage:
+ ; Push
+ ; Call Nsis2Io
+ ; Pop
+
+ Function ${UNINSTALLER_FUNCPREFIX}Nsis2Io
+
+ Exch $0 ; The source
+ Push $1 ; The output
+ Push $2 ; Temporary char
+ Push $3 ; Length
+ Push $4 ; Loop index
+ StrCpy $1 "" ; Initialise the output
+
+ StrLen $3 $0
+ IntOp $3 $3 - 1
+
+ ${For} $4 0 $3
+ StrCpy $2 $0 1 $4
+ ${If} $2 == '\'
+ StrCpy $2 '\\'
+ ${ElseIf} $2 == '$\r'
+ StrCpy $2 '\r'
+ ${ElseIf} $2 == '$\n'
+ StrCpy $2 '\n'
+ ${ElseIf} $2 == '$\t'
+ StrCpy $2 '\t'
+ ${EndIf}
+ StrCpy $1 $1$2
+ ${Next}
+
+ StrCpy $0 $1
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+
+ FunctionEnd
+
+!macroend
+
+!macro INSTALLOPTIONS_FUNCTION_IO2NSIS UNINSTALLER_FUNCPREFIX
+
+ ; Convert an InstallOptions string to a form suitable for use by NSIS
+ ; Usage:
+ ; Push
+ ; Call Io2Nsis
+ ; Pop
+
+ Function ${UNINSTALLER_FUNCPREFIX}Io2Nsis
+
+ Exch $0 ; The source
+ Push $1 ; The output
+ Push $2 ; Temporary char
+ Push $3 ; Length
+ Push $4 ; Loop index
+ StrCpy $1 "" ; Initialise the output
+
+ StrLen $3 $0
+ IntOp $3 $3 - 1
+
+ ${For} $4 0 $3
+ StrCpy $2 $0 2 $4
+ ${If} $2 == '\\'
+ StrCpy $2 '\'
+ IntOp $4 $4 + 1
+ ${ElseIf} $2 == '\r'
+ StrCpy $2 '$\r'
+ IntOp $4 $4 + 1
+ ${ElseIf} $2 == '\n'
+ StrCpy $2 '$\n'
+ IntOp $4 $4 + 1
+ ${ElseIf} $2 == '\t'
+ StrCpy $2 '$\t'
+ IntOp $4 $4 + 1
+ ${EndIf}
+ StrCpy $2 $2 1
+ StrCpy $1 $1$2
+ ${Next}
+
+ StrCpy $0 $1
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+
+ FunctionEnd
+
+!macroend
+
+!macro INSTALLOPTIONS_EXTRACT FILE
+
+ InitPluginsDir
+ File "/oname=$PLUGINSDIR\${FILE}" "${FILE}"
+!ifdef NSIS_UNICODE
+ InstallOptions::make_unicode "$PLUGINSDIR\${FILE}"
+!endif
+ !insertmacro INSTALLOPTIONS_WRITE "${FILE}" "Settings" "RTL" "$(^RTL)"
+
+!macroend
+
+!macro INSTALLOPTIONS_EXTRACT_AS FILE FILENAME
+
+ InitPluginsDir
+ File "/oname=$PLUGINSDIR\${FILENAME}" "${FILE}"
+!ifdef NSIS_UNICODE
+ InstallOptions::make_unicode "$PLUGINSDIR\${FILENAME}"
+!endif
+ !insertmacro INSTALLOPTIONS_WRITE "${FILENAME}" "Settings" "RTL" "$(^RTL)"
+
+!macroend
+
+!macro INSTALLOPTIONS_DISPLAY FILE
+
+ Push $0
+
+ InstallOptions::dialog "$PLUGINSDIR\${FILE}"
+ Pop $0
+
+ Pop $0
+
+!macroend
+
+!macro INSTALLOPTIONS_DISPLAY_RETURN FILE
+
+ InstallOptions::dialog "$PLUGINSDIR\${FILE}"
+
+!macroend
+
+!macro INSTALLOPTIONS_INITDIALOG FILE
+
+ InstallOptions::initDialog "$PLUGINSDIR\${FILE}"
+
+!macroend
+
+!macro INSTALLOPTIONS_SHOW
+
+ Push $0
+
+ InstallOptions::show
+ Pop $0
+
+ Pop $0
+
+!macroend
+
+!macro INSTALLOPTIONS_SHOW_RETURN
+
+ InstallOptions::show
+
+!macroend
+
+!macro INSTALLOPTIONS_READ VAR FILE SECTION KEY
+
+ ReadIniStr ${VAR} "$PLUGINSDIR\${FILE}" "${SECTION}" "${KEY}"
+
+!macroend
+
+!macro INSTALLOPTIONS_WRITE FILE SECTION KEY VALUE
+
+ WriteIniStr "$PLUGINSDIR\${FILE}" "${SECTION}" "${KEY}" "${VALUE}"
+
+!macroend
+
+!macro INSTALLOPTIONS_READ_CONVERT VAR FILE SECTION KEY
+
+ ReadIniStr ${VAR} "$PLUGINSDIR\${FILE}" "${SECTION}" "${KEY}"
+ Push ${VAR}
+ Call Io2Nsis
+ Pop ${VAR}
+
+!macroend
+
+!macro INSTALLOPTIONS_READ_UNCONVERT VAR FILE SECTION KEY
+
+ ReadIniStr ${VAR} "$PLUGINSDIR\${FILE}" "${SECTION}" "${KEY}"
+ Push ${VAR}
+ Call un.Io2Nsis
+ Pop ${VAR}
+
+!macroend
+
+!macro INSTALLOPTIONS_WRITE_CONVERT FILE SECTION KEY VALUE
+
+ Push $0
+ StrCpy $0 "${VALUE}"
+ Push $0
+ Call Nsis2Io
+ Pop $0
+
+ WriteIniStr "$PLUGINSDIR\${FILE}" "${SECTION}" "${KEY}" $0
+
+ Pop $0
+
+!macroend
+
+!macro INSTALLOPTIONS_WRITE_UNCONVERT FILE SECTION KEY VALUE
+
+ Push $0
+ StrCpy $0 "${VALUE}"
+ Push $0
+ Call un.Nsis2Io
+ Pop $0
+
+ WriteIniStr "$PLUGINSDIR\${FILE}" "${SECTION}" "${KEY}" $0
+
+ Pop $0
+
+!macroend
+
+!endif # ___NSIS__INSTALL_OPTIONS__NSH___
diff --git a/installer/tools/Include/Integration.nsh b/installer/tools/Include/Integration.nsh
new file mode 100644
index 00000000..f25c3123
--- /dev/null
+++ b/installer/tools/Include/Integration.nsh
@@ -0,0 +1,44 @@
+!verbose push 3
+!ifndef INTEGRATION_INCLUDED
+!define INTEGRATION_INCLUDED 1
+
+!include "Util.nsh"
+
+
+!define NotifyShell_AssocChanged `System::Call 'SHELL32::SHChangeNotify(i0x8000000,i0,p0,p0)'` ; Notify the shell with SHCNE_ASSOCCHANGED
+
+
+!define UnpinShortcut "!insertmacro UnpinShortcut "
+!macro UnpinShortcut lnkpath
+Push "${lnkpath}"
+${CallArtificialFunction} UnpinShortcut_Implementation
+!macroend
+!macro UnpinShortcut_Implementation
+!include "LogicLib.nsh"
+!include "Win\COM.nsh"
+Exch $0
+Push $1
+!insertmacro ComHlpr_CreateInProcInstance ${CLSID_StartMenuPin} ${IID_IStartMenuPinnedList} r1 ""
+${If} $1 P<> 0
+ System::Call 'SHELL32::SHCreateItemFromParsingName(wr0,p0,g"${IID_IShellItem}",*p0r0)'
+ ${If} $0 P<> 0
+ ${IStartMenuPinnedList::RemoveFromList} $1 '(r0)'
+ ${IUnknown::Release} $0 ""
+ ${EndIf}
+ ${IUnknown::Release} $1 ""
+!ifdef NSIS_IX86 | NSIS_AMD64
+${Else}
+ !insertmacro ComHlpr_CreateInProcInstance ${CLSID_StartMenuPin} "{ec35e37a-6579-4f3c-93cd-6e62c4ef7636}" r1 ""
+ ${If} $1 P<> 0
+ ExecShellWait /INVOKEIDLIST "unpin" $0 ; WinXP
+ ${IUnknown::Release} $1 ""
+ ${EndIf}
+!endif
+${EndIf}
+Pop $1
+Pop $0
+!macroend
+
+
+!endif #!INCLUDED
+!verbose pop
diff --git a/installer/tools/Include/LangFile.nsh b/installer/tools/Include/LangFile.nsh
new file mode 100644
index 00000000..767028b0
--- /dev/null
+++ b/installer/tools/Include/LangFile.nsh
@@ -0,0 +1,191 @@
+/*
+
+LangFile.nsh
+
+Header file to create language files that can be
+included with a single command.
+
+Copyright 2008-2023 Joost Verburg, Anders Kjersem
+
+* Either LANGFILE_INCLUDE or LANGFILE_INCLUDE_WITHDEFAULT
+ can be called from the script to include a language file.
+
+ - LANGFILE_INCLUDE takes the language file name as parameter.
+ - LANGFILE_INCLUDE_WITHDEFAULT takes as additional second
+ parameter, the default language file to load missing strings from.
+
+* Language strings in the language file have the format:
+ ${LangFileString} LANGSTRING_NAME "Text"
+
+* There are two types of language header files:
+
+ - NSIS multi-lang support; these must start with the LANGFILE macro and
+ provide strings for features like MUI and MultiUser. If you are adding
+ support for a new language to NSIS you should make a copy of English.nsh
+ and translate this .nsh along with the .nlf.
+ - Custom installer strings; these must start with the LANGFILE_EXT macro and
+ contain translated versions of
+ custom strings used in a particular installer.
+ This is useful if you want to put the translations for each language in
+ their own separate file.
+
+* Example:
+
+ ; Setup.nsi
+ !include "MUI.nsh"
+ !insertmacro MUI_PAGE_INSTFILES
+ !insertmacro MUI_LANGUAGE "Danish"
+ !insertmacro LANGFILE_INCLUDE "DanishExtra.nsh"
+ !insertmacro MUI_LANGUAGE "Swedish"
+ !insertmacro LANGFILE_INCLUDE "SwedishExtra.nsh"
+ Section
+ MessageBox MB_OK "$(myCustomString)"
+ SectionEnd
+
+ ; SwedishExtra.nsh
+ !insertmacro LANGFILE_EXT Swedish
+ ${LangFileString} myCustomString "Bork bork"
+
+*/
+
+!ifndef LANGFILE_INCLUDED
+!define LANGFILE_INCLUDED
+
+!macro LANGFILE_INCLUDE FILENAME
+
+ ;Called from script: include a language file
+
+ !ifdef LangFileString
+ !undef LangFileString
+ !endif
+
+ !define LangFileString "!insertmacro LANGFILE_SETSTRING"
+
+ !define LANGFILE_SETNAMES
+ !include "${FILENAME}"
+ !undef LANGFILE_SETNAMES
+
+ ;Create language strings
+ !define /redef LangFileString "!insertmacro LANGFILE_LANGSTRING"
+ !include "${FILENAME}"
+
+!macroend
+
+!macro LANGFILE_INCLUDE_WITHDEFAULT FILENAME FILENAME_DEFAULT
+
+ ;Called from script: include a language file
+ ;Obtains missing strings from a default file
+
+ !ifdef LangFileString
+ !undef LangFileString
+ !endif
+
+ !define LangFileString "!insertmacro LANGFILE_SETSTRING"
+
+ !define LANGFILE_SETNAMES
+ !include "${FILENAME}"
+ !undef LANGFILE_SETNAMES
+
+ ;Include default language for missing strings
+ !define LANGFILE_PRIV_INCLUDEISFALLBACK "${FILENAME_DEFAULT}"
+ !include "${FILENAME_DEFAULT}"
+ !undef LANGFILE_PRIV_INCLUDEISFALLBACK
+
+ ;Create language strings
+ !define /redef LangFileString "!insertmacro LANGFILE_LANGSTRING"
+ !include "${FILENAME_DEFAULT}"
+
+!macroend
+
+!macro LANGFILE NLFID ENGNAME NATIVENAME NATIVEASCIINAME
+
+ ;Start of standard NSIS language file
+
+ ; NLFID: Must match the name of the .nlf file
+ ; ENGNAME: English name of language, "=" if it is the same as NLFID
+ ; NATIVENAME: Native name of language. (In Unicode)
+ ; NATIVEASCIINAME: Native name of language using only ASCII, "=" if it is the same as NATIVENAME
+
+ ; Example: LANGFILE "Swedish" = "Svenska" = (This is the same as LANGFILE "Swedish" "Swedish" "Svenska" "Svenska")
+ ; For more examples, see French.nsh, Greek.nsh and PortugueseBR.nsh
+
+ !ifdef LANGFILE_SETNAMES
+
+ !ifdef LANGFILE_IDNAME
+ !undef LANGFILE_IDNAME
+ !endif
+
+ !define LANGFILE_IDNAME "${NLFID}"
+
+ ; ModernUI or the .nsi can change LANGFILE_LANGDLL_FMT if desired
+ !ifndef LANGFILE_LANGDLL_FMT
+ !ifndef NSIS_UNICODE
+ !define LANGFILE_LANGDLL_FMT "%ENGNAME% / %NATIVEASCIINAME%"
+ !endif
+ !define /ifndef LANGFILE_LANGDLL_FMT "%NATIVENAME%"
+ !endif
+
+ !ifndef "LANGFILE_${NLFID}_NAME"
+ !if "${ENGNAME}" == "="
+ !define /redef ENGNAME "${NLFID}"
+ !endif
+ !if "${NATIVEASCIINAME}" == "="
+ !define /redef NATIVEASCIINAME "${NATIVENAME}"
+ !endif
+
+ !define "LANGFILE_${NLFID}_ENGLISHNAME" "${ENGNAME}"
+ !ifdef NSIS_UNICODE
+ !define "LANGFILE_${NLFID}_NAME" "${NATIVENAME}"
+ !else
+ !define "LANGFILE_${NLFID}_NAME" "${NATIVEASCIINAME}"
+ !endif
+
+ !searchreplace LANGFILE_${NLFID}_LANGDLL "${LANGFILE_LANGDLL_FMT}" %NATIVEASCIINAME% "${NATIVEASCIINAME}"
+ !searchreplace LANGFILE_${NLFID}_LANGDLL "${LANGFILE_${NLFID}_LANGDLL}" %NATIVENAME% "${NATIVENAME}"
+ !searchreplace LANGFILE_${NLFID}_LANGDLL "${LANGFILE_${NLFID}_LANGDLL}" %ENGNAME% "${ENGNAME}"
+
+ !endif
+
+ !endif
+
+!macroend
+
+!macro LANGFILE_EXT IDNAME
+
+ ;Start of installer language file
+
+ !ifdef LANGFILE_SETNAMES
+
+ !ifdef LANGFILE_IDNAME
+ !undef LANGFILE_IDNAME
+ !endif
+
+ !define LANGFILE_IDNAME "${IDNAME}"
+
+ !endif
+
+!macroend
+
+!macro LANGFILE_SETSTRING NAME VALUE
+
+ ;Set define with translated string
+
+ !ifndef ${NAME}
+ !define "${NAME}" "${VALUE}"
+ !ifdef LANGFILE_PRIV_INCLUDEISFALLBACK
+ !warning 'LangString "${NAME}" for language ${LANGFILE_IDNAME} is missing, using fallback from "${LANGFILE_PRIV_INCLUDEISFALLBACK}"'
+ !endif
+ !endif
+
+!macroend
+
+!macro LANGFILE_LANGSTRING NAME DUMMY
+
+ ;Create a language string from a define and undefine
+
+ LangString "${NAME}" "${LANG_${LANGFILE_IDNAME}}" "${${NAME}}"
+ !undef "${NAME}"
+
+!macroend
+
+!endif
diff --git a/installer/tools/Include/Library.nsh b/installer/tools/Include/Library.nsh
new file mode 100644
index 00000000..ff3ee337
--- /dev/null
+++ b/installer/tools/Include/Library.nsh
@@ -0,0 +1,885 @@
+#
+# Library.nsh
+#
+# A system for the installation and uninstallation of dynamic
+# link libraries (DLL) and type libraries (TLB). Using this
+# system you can handle the complete setup with one single
+# line of code:
+#
+# * File copying
+# * File copying on reboot
+# * Version checks
+# * Registration and unregistration
+# * Registration and unregistration on reboot
+# * Shared DLL counting
+# * Windows File Protection checks
+#
+# For more information, read appendix B in the documentation.
+#
+
+!verbose push
+!verbose 3
+
+!ifndef LIB_INCLUDED
+
+!define LIB_INCLUDED
+
+!ifndef SHCNE_ASSOCCHANGED
+ !define SHCNE_ASSOCCHANGED 0x08000000
+!endif
+!ifndef SHCNF_IDLIST
+ !define SHCNF_IDLIST 0x0000
+!endif
+
+!define REGTOOL_VERSION v3
+!define REGTOOL_KEY NSIS.Library.RegTool.${REGTOOL_VERSION}
+
+!include LogicLib.nsh
+!include x64.nsh
+
+### GetParent macro, don't pass $1 or $2 as INPUT or OUTPUT
+!macro __InstallLib_Helper_GetParent INPUT OUTPUT
+
+ # Copied from FileFunc.nsh
+
+ StrCpy ${OUTPUT} ${INPUT}
+
+ Push $1
+ Push $2
+
+ StrCpy $2 ${OUTPUT} 1 -1
+ StrCmp $2 '\' 0 +3
+ StrCpy ${OUTPUT} ${OUTPUT} -1
+ goto -3
+
+ StrCpy $1 0
+ IntOp $1 $1 - 1
+ StrCpy $2 ${OUTPUT} 1 $1
+ StrCmp $2 '\' +2
+ StrCmp $2 '' 0 -3
+ StrCpy ${OUTPUT} ${OUTPUT} $1
+
+ Pop $2
+ Pop $1
+
+!macroend
+
+### Initialize session id (GUID)
+!macro __InstallLib_Helper_InitSession
+
+ !ifndef __InstallLib_SessionGUID_Defined
+
+ !define __InstallLib_SessionGUID_Defined
+
+ Var /GLOBAL __INSTALLLLIB_SESSIONGUID
+
+ !endif
+
+ !define __InstallLib_Helper_InitSession_Label "Library_${__FILE__}${__LINE__}"
+
+ StrCmp $__INSTALLLLIB_SESSIONGUID '' 0 "${__InstallLib_Helper_InitSession_Label}"
+
+ System::Call 'ole32::CoCreateGuid(g .s)'
+ Pop $__INSTALLLLIB_SESSIONGUID
+
+ "${__InstallLib_Helper_InitSession_Label}:"
+
+ !undef __InstallLib_Helper_InitSession_Label
+
+!macroend
+
+### Add a RegTool entry to register after reboot
+!macro __InstallLib_Helper_AddRegToolEntry mode filename tempdir
+
+ Push $R0
+ Push $R1
+ Push $R2
+ Push $R3
+
+ ;------------------------
+ ;Copy the parameters
+
+ Push "${filename}"
+ Push "${tempdir}"
+
+ Pop $R2 ; temporary directory
+ Pop $R1 ; file name to register
+
+ ;------------------------
+ ;Initialize session id
+
+ !insertmacro __InstallLib_Helper_InitSession
+
+ ;------------------------
+ ;Advance counter
+
+ StrCpy $R0 0
+ ReadRegDWORD $R0 HKLM "Software\${REGTOOL_KEY}\$__INSTALLLLIB_SESSIONGUID" "count"
+ IntOp $R0 $R0 + 1
+ WriteRegDWORD HKLM "Software\${REGTOOL_KEY}\$__INSTALLLLIB_SESSIONGUID" "count" "$R0"
+
+ ;------------------------
+ ;Setup RegTool
+
+ !if ! /FileExists "${NSISDIR}\Bin\RegTool-${NSIS_CPU}.bin"
+ !error "Missing RegTool for ${NSIS_CPU}!"
+ !endif
+
+ ReadRegStr $R3 HKLM "Software\Microsoft\Windows\CurrentVersion\RunOnce" "${REGTOOL_KEY}"
+ StrCpy $R3 $R3 -4 1
+ IfFileExists $R3 +3
+
+ File /oname=$R2\${REGTOOL_KEY}.$__INSTALLLLIB_SESSIONGUID.exe "${NSISDIR}\Bin\RegTool-${NSIS_CPU}.bin"
+ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\RunOnce" \
+ "${REGTOOL_KEY}" '"$R2\${REGTOOL_KEY}.$__INSTALLLLIB_SESSIONGUID.exe" /S'
+
+ ;------------------------
+ ;Add RegTool entry
+
+ WriteRegStr HKLM "Software\${REGTOOL_KEY}\$__INSTALLLLIB_SESSIONGUID" "$R0.file" "$R1"
+ WriteRegStr HKLM "Software\${REGTOOL_KEY}\$__INSTALLLLIB_SESSIONGUID" "$R0.mode" "${mode}"
+
+ Pop $R3
+ Pop $R2
+ Pop $R1
+ Pop $R0
+
+!macroend
+
+!macro __InstallLib_Helper_CmpPackedVer64 oldhi oldlo newhi newlo jeq jle jgt
+
+ IntCmpU ${oldhi} ${newhi} "0" "${jle}" "${jgt}"
+ IntCmpU ${oldlo} ${newlo} "${jeq}" "${jle}" "${jgt}"
+
+!macroend
+
+### Get library version
+!macro __InstallLib_Helper_GetVersion TYPE FILE
+
+ !if "${TYPE}" == "D"
+ !getdllversion /NoErrors /Packed "${FILE}" LIBRARY_VERSION_
+ !else if "${TYPE}" == "T"
+ !gettlbversion /NoErrors /Packed "${FILE}" LIBRARY_VERSION_
+ !endif
+
+ ; Emulate the old LibraryLocal defines
+ !ifndef LIBRARY_VERSION_HIGH
+ !define LIBRARY_VERSION_FILENOTFOUND
+ !else if "${LIBRARY_VERSION_HIGH}" == ""
+ !define LIBRARY_VERSION_NONE
+ !undef LIBRARY_VERSION_HIGH
+ !undef LIBRARY_VERSION_LOW
+ !endif
+
+!macroend
+
+### Install library
+!macro InstallLib libtype shared install localfile destfile tempbasedir
+
+ !verbose push
+ !verbose 3
+
+ Push $R0
+ Push $R1
+ Push $R2
+ Push $R3
+ Push $R4
+ Push $R5
+
+ ;------------------------
+ ;Define
+
+ !define INSTALLLIB_UNIQUE "${__FILE__}${__LINE__}"
+
+ !define INSTALLLIB_LIBTYPE_${libtype}
+ !define INSTALLLIB_LIBTYPE_SET INSTALLLIB_LIBTYPE_${libtype}
+ !define INSTALLLIB_SHARED_${shared}
+ !define INSTALLLIB_SHARED_SET INSTALLLIB_SHARED_${shared}
+ !define INSTALLLIB_INSTALL_${install}
+ !define INSTALLLIB_INSTALL_SET INSTALLLIB_INSTALL_${install}
+
+ ;------------------------
+ ;Validate
+
+ !ifndef INSTALLLIB_LIBTYPE_DLL & INSTALLLIB_LIBTYPE_REGDLL & INSTALLLIB_LIBTYPE_TLB & \
+ INSTALLLIB_LIBTYPE_REGDLLTLB & INSTALLLIB_LIBTYPE_REGEXE
+ !error "InstallLib: Incorrect setting for parameter: libtype"
+ !endif
+
+ !ifndef INSTALLLIB_INSTALL_REBOOT_PROTECTED & INSTALLLIB_INSTALL_REBOOT_NOTPROTECTED & \
+ INSTALLLIB_INSTALL_NOREBOOT_PROTECTED & INSTALLLIB_INSTALL_NOREBOOT_NOTPROTECTED
+ !error "InstallLib: Incorrect setting for parameter: install"
+ !endif
+
+ ;------------------------
+ ;x64 settings
+
+ !ifdef LIBRARY_X64
+
+ ${DisableX64FSRedirection}
+
+ !endif
+
+ ;------------------------
+ ;Copy the parameters used on run-time to a variable
+ ;This allows the usage of variables as parameter
+
+ StrCpy $R4 "${destfile}"
+ StrCpy $R5 "${tempbasedir}"
+
+ ;------------------------
+ ;Shared library count
+
+ !ifndef INSTALLLIB_SHARED_NOTSHARED
+
+ StrCmp ${shared} "" 0 "installlib.noshareddllincrease_${INSTALLLIB_UNIQUE}"
+
+ !ifdef LIBRARY_X64
+
+ SetRegView 64
+
+ !endif
+
+ ReadRegDword $R0 HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R4
+ ClearErrors
+ IntOp $R0 $R0 + 1
+ WriteRegDWORD HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R4 $R0
+
+ !ifdef LIBRARY_X64
+
+ SetRegView lastused
+
+ !endif
+
+ "installlib.noshareddllincrease_${INSTALLLIB_UNIQUE}:"
+
+ !endif
+
+ ;------------------------
+ ;Check Windows File Protection
+
+ !ifdef INSTALLLIB_INSTALL_REBOOT_PROTECTED | INSTALLLIB_INSTALL_NOREBOOT_PROTECTED
+
+ !define LIBRARY_DEFINE_DONE_LABEL
+
+ System::Call "sfc::SfcIsFileProtected(i 0, w R4) i.R0"
+
+ StrCmp $R0 "error" "installlib.notprotected_${INSTALLLIB_UNIQUE}"
+ StrCmp $R0 "0" "installlib.notprotected_${INSTALLLIB_UNIQUE}"
+
+ Goto "installlib.done_${INSTALLLIB_UNIQUE}"
+
+ "installlib.notprotected_${INSTALLLIB_UNIQUE}:"
+
+ !endif
+
+ ;------------------------
+ ;Check file
+
+ IfFileExists $R4 0 "installlib.copy_${INSTALLLIB_UNIQUE}"
+
+ ;------------------------
+ ;Get version information
+
+ !ifndef LIBRARY_IGNORE_VERSION
+
+ !insertmacro __InstallLib_Helper_GetVersion D "${LOCALFILE}"
+
+ !ifdef LIBRARY_VERSION_FILENOTFOUND
+ !error "InstallLib: The library ${LOCALFILE} could not be found."
+ !endif
+
+ !ifndef LIBRARY_VERSION_NONE
+
+ !define LIBRARY_DEFINE_UPGRADE_LABEL
+ !define LIBRARY_DEFINE_REGISTER_LABEL
+
+ StrCpy $R0 ${LIBRARY_VERSION_HIGH}
+ StrCpy $R1 ${LIBRARY_VERSION_LOW}
+
+ GetDLLVersion $R4 $R2 $R3
+
+ !undef LIBRARY_VERSION_HIGH
+ !undef LIBRARY_VERSION_LOW
+
+ !ifndef INSTALLLIB_LIBTYPE_TLB & INSTALLLIB_LIBTYPE_REGDLLTLB
+
+ !ifdef LIBRARY_INSTALL_EQUAL_VERSION
+ !insertmacro __InstallLib_Helper_CmpPackedVer64 $R0 $R1 $R2 $R3 "installlib.upgrade_${INSTALLLIB_UNIQUE}" \
+ "installlib.register_${INSTALLLIB_UNIQUE}" "installlib.upgrade_${INSTALLLIB_UNIQUE}"
+ !else
+ !insertmacro __InstallLib_Helper_CmpPackedVer64 $R0 $R1 $R2 $R3 "installlib.register_${INSTALLLIB_UNIQUE}" \
+ "installlib.register_${INSTALLLIB_UNIQUE}" "installlib.upgrade_${INSTALLLIB_UNIQUE}"
+ !endif
+
+ !else
+
+ !insertmacro __InstallLib_Helper_GetVersion T "${LOCALFILE}"
+
+ !ifdef LIBRARY_VERSION_FILENOTFOUND
+ !error "InstallLib: The library ${LOCALFILE} could not be found."
+ !endif
+
+ !ifndef LIBRARY_VERSION_NONE
+
+ !insertmacro __InstallLib_Helper_CmpPackedVer64 $R0 $R1 $R2 $R3 0 \
+ "installlib.register_${INSTALLLIB_UNIQUE}" "installlib.upgrade_${INSTALLLIB_UNIQUE}"
+
+ !else
+
+ !ifdef LIBRARY_INSTALL_EQUAL_VERSION
+ !insertmacro __InstallLib_Helper_CmpPackedVer64 $R0 $R1 $R2 $R3 "installlib.upgrade_${INSTALLLIB_UNIQUE}" \
+ "installlib.register_${INSTALLLIB_UNIQUE}" "installlib.upgrade_${INSTALLLIB_UNIQUE}"
+ !else
+ !insertmacro __InstallLib_Helper_CmpPackedVer64 $R0 $R1 $R2 $R3 "installlib.register_${INSTALLLIB_UNIQUE}" \
+ "installlib.register_${INSTALLLIB_UNIQUE}" "installlib.upgrade_${INSTALLLIB_UNIQUE}"
+ !endif
+
+ !endif
+
+ !endif
+
+ !else
+
+ !undef LIBRARY_VERSION_NONE
+
+ !ifdef INSTALLLIB_LIBTYPE_TLB | INSTALLLIB_LIBTYPE_REGDLLTLB
+
+ !insertmacro __InstallLib_Helper_GetVersion T "${LOCALFILE}"
+
+ !endif
+
+ !endif
+
+ !ifdef INSTALLLIB_LIBTYPE_TLB | INSTALLLIB_LIBTYPE_REGDLLTLB
+
+ !ifndef LIBRARY_VERSION_NONE
+
+ !ifndef LIBRARY_DEFINE_UPGRADE_LABEL
+
+ !define LIBRARY_DEFINE_UPGRADE_LABEL
+
+ !endif
+
+ !ifndef LIBRARY_DEFINE_REGISTER_LABEL
+
+ !define LIBRARY_DEFINE_REGISTER_LABEL
+
+ !endif
+
+ StrCpy $R0 ${LIBRARY_VERSION_HIGH}
+ StrCpy $R1 ${LIBRARY_VERSION_LOW}
+
+ TypeLib::GetLibVersion $R4
+ Pop $R3
+ Pop $R2
+
+ !ifdef LIBRARY_INSTALL_EQUAL_VERSION
+ !insertmacro __InstallLib_Helper_CmpPackedVer64 $R0 $R1 $R2 $R3 "installlib.upgrade_${INSTALLLIB_UNIQUE}" \
+ "installlib.register_${INSTALLLIB_UNIQUE}" "installlib.upgrade_${INSTALLLIB_UNIQUE}"
+ !else
+ !insertmacro __InstallLib_Helper_CmpPackedVer64 $R0 $R1 $R2 $R3 "installlib.register_${INSTALLLIB_UNIQUE}" \
+ "installlib.register_${INSTALLLIB_UNIQUE}" "installlib.upgrade_${INSTALLLIB_UNIQUE}"
+ !endif
+
+ !undef LIBRARY_VERSION_HIGH
+ !undef LIBRARY_VERSION_LOW
+
+ !else
+
+ !undef LIBRARY_VERSION_NONE
+
+ !endif
+
+ !endif
+
+ !endif ;~LIBRARY_IGNORE_VERSION
+
+ ;------------------------
+ ;Upgrade
+
+ !ifdef LIBRARY_DEFINE_UPGRADE_LABEL
+
+ !undef LIBRARY_DEFINE_UPGRADE_LABEL
+
+ "installlib.upgrade_${INSTALLLIB_UNIQUE}:"
+
+ !endif
+
+ ;------------------------
+ ;Copy
+
+ !ifdef INSTALLLIB_INSTALL_NOREBOOT_PROTECTED | INSTALLLIB_INSTALL_NOREBOOT_NOTPROTECTED
+
+ "installlib.copy_${INSTALLLIB_UNIQUE}:"
+
+ StrCpy $R0 $R4
+ Call ":installlib.file_${INSTALLLIB_UNIQUE}"
+
+ !else
+
+ !ifndef LIBRARY_DEFINE_REGISTER_LABEL
+
+ !define LIBRARY_DEFINE_REGISTER_LABEL
+
+ !endif
+
+ !ifndef LIBRARY_DEFINE_DONE_LABEL
+
+ !define LIBRARY_DEFINE_DONE_LABEL
+
+ !endif
+
+ ClearErrors
+
+ StrCpy $R0 $R4
+ Call ":installlib.file_${INSTALLLIB_UNIQUE}"
+
+ IfErrors 0 "installlib.register_${INSTALLLIB_UNIQUE}"
+
+ SetOverwrite lastused
+
+ ;------------------------
+ ;Copy on reboot
+
+ GetTempFileName $R0 $R5
+ Call ":installlib.file_${INSTALLLIB_UNIQUE}"
+ Rename /REBOOTOK $R0 $R4
+
+ ;------------------------
+ ;Register on reboot
+
+ Call ":installlib.regonreboot_${INSTALLLIB_UNIQUE}"
+
+ Goto "installlib.done_${INSTALLLIB_UNIQUE}"
+
+ "installlib.copy_${INSTALLLIB_UNIQUE}:"
+ StrCpy $R0 $R4
+ Call ":installlib.file_${INSTALLLIB_UNIQUE}"
+
+ !endif
+
+ ;------------------------
+ ;Register
+
+ !ifdef LIBRARY_DEFINE_REGISTER_LABEL
+
+ !undef LIBRARY_DEFINE_REGISTER_LABEL
+
+ "installlib.register_${INSTALLLIB_UNIQUE}:"
+
+ !endif
+
+ !ifdef INSTALLLIB_LIBTYPE_REGDLL | INSTALLLIB_LIBTYPE_TLB | INSTALLLIB_LIBTYPE_REGDLLTLB | INSTALLLIB_LIBTYPE_REGEXE
+
+ !ifdef INSTALLLIB_INSTALL_REBOOT_PROTECTED | INSTALLLIB_INSTALL_REBOOT_NOTPROTECTED
+
+ IfRebootFlag 0 "installlib.regnoreboot_${INSTALLLIB_UNIQUE}"
+
+ Call ":installlib.regonreboot_${INSTALLLIB_UNIQUE}"
+
+ Goto "installlib.registerfinish_${INSTALLLIB_UNIQUE}"
+
+ "installlib.regnoreboot_${INSTALLLIB_UNIQUE}:"
+
+ !endif
+
+ !ifdef INSTALLLIB_LIBTYPE_TLB | INSTALLLIB_LIBTYPE_REGDLLTLB
+
+ TypeLib::Register $R4
+
+ !endif
+
+ !ifdef INSTALLLIB_LIBTYPE_REGDLL | INSTALLLIB_LIBTYPE_REGDLLTLB
+
+ !ifndef LIBRARY_X64
+
+ RegDll $R4
+
+ !else
+
+ ExecWait '"$SYSDIR\regsvr32.exe" /s "$R4"'
+
+ !endif
+
+ !endif
+
+ !ifdef INSTALLLIB_LIBTYPE_REGEXE
+
+ ExecWait '"$R4" /regserver'
+
+ !endif
+
+ !ifdef INSTALLLIB_INSTALL_REBOOT_PROTECTED | INSTALLLIB_INSTALL_REBOOT_NOTPROTECTED
+
+ "installlib.registerfinish_${INSTALLLIB_UNIQUE}:"
+
+ !endif
+
+ !endif
+
+ !ifdef LIBRARY_SHELL_EXTENSION
+
+ System::Call 'Shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_IDLIST}, i 0, i 0)'
+
+ !endif
+
+ !ifdef LIBRARY_COM
+
+ System::Call 'Ole32::CoFreeUnusedLibraries()'
+
+ !endif
+
+ ;------------------------
+ ;Done
+
+ !ifdef LIBRARY_DEFINE_DONE_LABEL
+
+ !undef LIBRARY_DEFINE_DONE_LABEL
+
+ "installlib.done_${INSTALLLIB_UNIQUE}:"
+
+ !endif
+
+ Pop $R5
+ Pop $R4
+ Pop $R3
+ Pop $R2
+ Pop $R1
+ Pop $R0
+
+ ;------------------------
+ ;End
+
+ Goto "installlib.end_${INSTALLLIB_UNIQUE}"
+
+ ;------------------------
+ ;Extract
+
+ !ifdef INSTALLLIB_INSTALL_REBOOT_PROTECTED | INSTALLLIB_INSTALL_REBOOT_NOTPROTECTED
+
+ SetOverwrite try
+
+ !else
+
+ SetOverwrite on
+
+ !endif
+
+ "installlib.file_${INSTALLLIB_UNIQUE}:"
+ SetFileAttributes $R0 FILE_ATTRIBUTE_NORMAL
+ ClearErrors
+ File /oname=$R0 "${LOCALFILE}"
+ Return
+
+ SetOverwrite lastused
+
+ ;------------------------
+ ;Register on reboot
+
+ !ifdef INSTALLLIB_INSTALL_REBOOT_PROTECTED | INSTALLLIB_INSTALL_REBOOT_NOTPROTECTED
+
+ "installlib.regonreboot_${INSTALLLIB_UNIQUE}:"
+
+ !ifdef INSTALLLIB_LIBTYPE_REGDLL | INSTALLLIB_LIBTYPE_REGDLLTLB
+ !ifndef LIBRARY_X64
+ !insertmacro __InstallLib_Helper_AddRegToolEntry 'D' "$R4" "$R5"
+ !else
+ !insertmacro __InstallLib_Helper_AddRegToolEntry 'DX' "$R4" "$R5"
+ !endif
+ !endif
+
+ !ifdef INSTALLLIB_LIBTYPE_TLB | INSTALLLIB_LIBTYPE_REGDLLTLB
+ !insertmacro __InstallLib_Helper_AddRegToolEntry 'T' "$R4" "$R5"
+ !endif
+
+ !ifdef INSTALLLIB_LIBTYPE_REGEXE
+ !insertmacro __InstallLib_Helper_AddRegToolEntry 'E' "$R4" "$R5"
+ !endif
+
+ Return
+
+ !endif
+
+ ;------------------------
+ ;End label
+
+ "installlib.end_${INSTALLLIB_UNIQUE}:"
+
+ !ifdef LIBRARY_X64
+
+ ${EnableX64FSRedirection}
+
+ !endif
+
+ ;------------------------
+ ;Undefine
+
+ !undef INSTALLLIB_UNIQUE
+
+ !undef ${INSTALLLIB_LIBTYPE_SET}
+ !undef INSTALLLIB_LIBTYPE_SET
+ !undef ${INSTALLLIB_SHARED_SET}
+ !undef INSTALLLIB_SHARED_SET
+ !undef ${INSTALLLIB_INSTALL_SET}
+ !undef INSTALLLIB_INSTALL_SET
+
+ !verbose pop
+
+!macroend
+
+### Uninstall library
+!macro UnInstallLib libtype shared uninstall file
+
+ !verbose push
+ !verbose 3
+
+ Push $R0
+ Push $R1
+
+ ;------------------------
+ ;Define
+
+ !define UNINSTALLLIB_UNIQUE "${__FILE__}${__LINE__}"
+
+ !define UNINSTALLLIB_LIBTYPE_${libtype}
+ !define UNINSTALLLIB_LIBTYPE_SET UNINSTALLLIB_LIBTYPE_${libtype}
+ !define UNINSTALLLIB_SHARED_${shared}
+ !define UNINSTALLLIB_SHARED_SET UNINSTALLLIB_SHARED_${shared}
+ !define UNINSTALLLIB_UNINSTALL_${uninstall}
+ !define UNINSTALLLIB_UNINSTALL_SET UNINSTALLLIB_UNINSTALL_${uninstall}
+
+ ;------------------------
+ ;Validate
+
+ !ifndef UNINSTALLLIB_LIBTYPE_DLL & UNINSTALLLIB_LIBTYPE_REGDLL & UNINSTALLLIB_LIBTYPE_TLB & \
+ UNINSTALLLIB_LIBTYPE_REGDLLTLB & UNINSTALLLIB_LIBTYPE_REGEXE
+ !error "UnInstallLib: Incorrect setting for parameter: libtype"
+ !endif
+
+ !ifndef UNINSTALLLIB_SHARED_NOTSHARED & UNINSTALLLIB_SHARED_SHARED
+ !error "UnInstallLib: Incorrect setting for parameter: shared"
+ !endif
+
+ !ifndef UNINSTALLLIB_UNINSTALL_NOREMOVE & UNINSTALLLIB_UNINSTALL_REBOOT_PROTECTED & \
+ UNINSTALLLIB_UNINSTALL_REBOOT_NOTPROTECTED & UNINSTALLLIB_UNINSTALL_NOREBOOT_PROTECTED & \
+ UNINSTALLLIB_UNINSTALL_NOREBOOT_NOTPROTECTED
+ !error "UnInstallLib: Incorrect setting for parameter: uninstall"
+ !endif
+
+ ;------------------------
+ ;x64 settings
+
+ !ifdef LIBRARY_X64
+
+ ${DisableX64FSRedirection}
+
+ !endif
+
+ ;------------------------
+ ;Copy the parameters used on run-time to a variable
+ ;This allows the usage of variables as parameter
+
+ StrCpy $R1 "${file}"
+
+ ;------------------------
+ ;Shared library count
+
+ !ifdef UNINSTALLLIB_SHARED_SHARED
+
+ !define UNINSTALLLIB_DONE_LABEL
+
+ !ifdef LIBRARY_X64
+
+ SetRegView 64
+
+ !endif
+
+ ReadRegDword $R0 HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1
+ StrCmp $R0 "" "uninstalllib.shareddlldone_${UNINSTALLLIB_UNIQUE}"
+
+ IntOp $R0 $R0 - 1
+ IntCmp $R0 0 "uninstalllib.shareddllremove_${UNINSTALLLIB_UNIQUE}" \
+ "uninstalllib.shareddllremove_${UNINSTALLLIB_UNIQUE}" "uninstalllib.shareddllinuse_${UNINSTALLLIB_UNIQUE}"
+
+ "uninstalllib.shareddllremove_${UNINSTALLLIB_UNIQUE}:"
+ DeleteRegValue HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1
+ !ifndef UNINSTALLLIB_SHARED_SHAREDNOREMOVE
+ Goto "uninstalllib.shareddlldone_${UNINSTALLLIB_UNIQUE}"
+ !endif
+
+ "uninstalllib.shareddllinuse_${UNINSTALLLIB_UNIQUE}:"
+ WriteRegDWORD HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1 $R0
+
+ !ifdef LIBRARY_X64
+
+ SetRegView lastused
+
+ !endif
+
+ Goto "uninstalllib.done_${UNINSTALLLIB_UNIQUE}"
+
+ "uninstalllib.shareddlldone_${UNINSTALLLIB_UNIQUE}:"
+
+ !ifdef LIBRARY_X64
+
+ SetRegView lastused
+
+ !endif
+
+ !endif
+
+ ;------------------------
+ ;Remove
+
+ !ifndef UNINSTALLLIB_UNINSTALL_NOREMOVE
+
+ ;------------------------
+ ;Check Windows File Protection
+
+ !ifdef UNINSTALLLIB_UNINSTALL_REBOOT_PROTECTED | UNINSTALLLIB_UNINSTALL_NOREBOOT_PROTECTED
+
+ !ifndef UNINSTALLLIB_DONE_LABEL
+
+ !define UNINSTALLLIB_DONE_LABEL
+
+ !endif
+
+ System::Call "sfc::SfcIsFileProtected(i 0, w $R1) i.R0"
+
+ StrCmp $R0 "error" "uninstalllib.notprotected_${UNINSTALLLIB_UNIQUE}"
+ StrCmp $R0 "0" "uninstalllib.notprotected_${UNINSTALLLIB_UNIQUE}"
+
+ Goto "uninstalllib.done_${UNINSTALLLIB_UNIQUE}"
+
+ "uninstalllib.notprotected_${UNINSTALLLIB_UNIQUE}:"
+
+ !endif
+
+ ;------------------------
+ ;Unregister
+
+ !ifdef UNINSTALLLIB_LIBTYPE_REGDLL | UNINSTALLLIB_LIBTYPE_REGDLLTLB
+
+ !ifndef LIBRARY_X64
+
+ UnRegDLL $R1
+
+ !else
+
+ ExecWait '"$SYSDIR\regsvr32.exe" /s /u "$R1"'
+
+ !endif
+
+ !endif
+
+ !ifdef UNINSTALLLIB_LIBTYPE_REGEXE
+
+ ExecWait '"$R1" /unregserver'
+
+ !endif
+
+ !ifdef UNINSTALLLIB_LIBTYPE_TLB | UNINSTALLLIB_LIBTYPE_REGDLLTLB
+
+ TypeLib::UnRegister $R1
+
+ !endif
+
+ !ifdef LIBRARY_SHELL_EXTENSION
+
+ System::Call 'Shell32::SHChangeNotify(i ${SHCNE_ASSOCCHANGED}, i ${SHCNF_IDLIST}, i 0, i 0)'
+
+ !endif
+
+ !ifdef LIBRARY_COM
+
+ System::Call 'Ole32::CoFreeUnusedLibraries()'
+
+ !endif
+
+ ;------------------------
+ ;Delete
+
+ Delete $R1
+
+ !ifdef UNINSTALLLIB_UNINSTALL_REBOOT_PROTECTED | UNINSTALLLIB_UNINSTALL_REBOOT_NOTPROTECTED
+
+ ${If} ${FileExists} $R1
+ # File is in use, can't just delete.
+ # Move file to another location before using Delete /REBOOTOK. This way, if
+ # the user installs a new version of the DLL, it won't be deleted after
+ # reboot. See bug #1097642 for more information on this.
+
+ # Try moving to $TEMP.
+ GetTempFileName $R0
+ Delete $R0
+ Rename $R1 $R0
+
+ ${If} ${FileExists} $R1
+ # Still here, delete temporary file, in case the file was copied
+ # and not deleted. This happens when moving from network drives,
+ # for example.
+ Delete $R0
+
+ # Try moving to directory containing the file.
+ !insertmacro __InstallLib_Helper_GetParent $R1 $R0
+ GetTempFileName $R0 $R0
+ Delete $R0
+ Rename $R1 $R0
+
+ ${If} ${FileExists} $R1
+ # Still here, delete temporary file.
+ Delete $R0
+
+ # Give up moving, simply Delete /REBOOTOK the file.
+ StrCpy $R0 $R1
+ ${EndIf}
+ ${EndIf}
+
+ # Delete the moved file.
+ Delete /REBOOTOK $R0
+ ${EndIf}
+
+ !endif
+
+ !endif
+
+ ;------------------------
+ ;Done
+
+ !ifdef UNINSTALLLIB_DONE_LABEL
+
+ !undef UNINSTALLLIB_DONE_LABEL
+
+ "uninstalllib.done_${UNINSTALLLIB_UNIQUE}:"
+
+ !endif
+
+ !ifdef LIBRARY_X64
+
+ ${EnableX64FSRedirection}
+
+ !endif
+
+ Pop $R1
+ Pop $R0
+
+ ;------------------------
+ ;Undefine
+
+ !undef UNINSTALLLIB_UNIQUE
+
+ !undef ${UNINSTALLLIB_LIBTYPE_SET}
+ !undef UNINSTALLLIB_LIBTYPE_SET
+ !undef ${UNINSTALLLIB_SHARED_SET}
+ !undef UNINSTALLLIB_SHARED_SET
+ !undef ${UNINSTALLLIB_UNINSTALL_SET}
+ !undef UNINSTALLLIB_UNINSTALL_SET
+
+ !verbose pop
+
+!macroend
+
+!endif
+
+!verbose pop
diff --git a/installer/tools/Include/LogicLib.nsh b/installer/tools/Include/LogicLib.nsh
new file mode 100644
index 00000000..c338852d
--- /dev/null
+++ b/installer/tools/Include/LogicLib.nsh
@@ -0,0 +1,899 @@
+; NSIS LOGIC LIBRARY - LogicLib.nsh
+; Version 2.6 - 08/12/2007
+; By dselkirk@hotmail.com
+; and eccles@users.sf.net
+; with IfNot support added by Message
+;
+; Questions/Comments -
+; See http://forums.winamp.com/showthread.php?s=&postid=1116241
+;
+; Description:
+; Provides the use of various logic statements within NSIS.
+;
+; Usage:
+; The following "statements" are available:
+; If|IfNot|Unless..{ElseIf|ElseIfNot|ElseUnless}..[Else]..EndIf|EndUnless
+; - Conditionally executes a block of statements, depending on the value
+; of an expression. IfNot and Unless are equivalent and
+; interchangeable, as are ElseIfNot and ElseUnless.
+; AndIf|AndIfNot|AndUnless|OrIf|OrIfNot|OrUnless
+; - Adds any number of extra conditions to If, IfNot, Unless, ElseIf,
+; ElseIfNot and ElseUnless statements.
+; IfThen|IfNotThen..|..|
+; - Conditionally executes an inline statement, depending on the value
+; of an expression.
+; IfCmd..||..|
+; - Conditionally executes an inline statement, depending on a true
+; value of the provided NSIS function.
+; Select..{Case[2|3|4|5]}..[CaseElse|Default]..EndSelect
+; - Executes one of several blocks of statements, depending on the value
+; of an expression.
+; Switch..{Case|CaseElse|Default}..EndSwitch
+; - Jumps to one of several labels, depending on the value of an
+; expression.
+; Do[While|Until]..{ExitDo|Continue|Break}..Loop[While|Until]
+; - Repeats a block of statements until stopped, or depending on the
+; value of an expression.
+; While..{ExitWhile|Continue|Break}..EndWhile
+; - An alias for DoWhile..Loop (for backwards-compatibility)
+; For[Each]..{ExitFor|Continue|Break}..Next
+; - Repeats a block of statements varying the value of a variable.
+;
+; The following "expressions" are available:
+; Standard (built-in) string tests (which are case-insensitive):
+; a == b; a != b
+; Additional case-insensitive string tests (using System.dll):
+; a S< b; a S>= b; a S> b; a S<= b
+; Case-sensitive string tests:
+; a S== b; a S!= b
+; Standard (built-in) signed integer tests:
+; a = b; a <> b; a < b; a >= b; a > b; a <= b; a & b
+; Standard (built-in) unsigned integer tests:
+; a U< b; a U>= b; a U> b; a U<= b
+; 64-bit integer tests (using System.dll):
+; a L= b; a L<> b; a L< b; a L>= b; a L> b; a L<= b
+; ptrdiff_t integer tests
+; a P= b; a P<> b; a P< b; a P>= b; a P> b; a P<= b
+; size_t integer tests
+; a Z= b; a Z<> b; a Z< b; a Z>= b; a Z> b; a Z<= b
+; Built-in NSIS flag tests:
+; ${Abort}; ${Errors}; ${RebootFlag}; ${Silent}; ${RtlLanguage};
+; ${ShellVarContextAll}
+; Built-in NSIS other tests:
+; ${FileExists} a
+; Any conditional NSIS instruction test:
+; ${Cmd} a
+; Section flag tests:
+; ${SectionIsSelected} a; ${SectionIsSectionGroup} a;
+; ${SectionIsSectionGroupEnd} a; ${SectionIsBold} a;
+; ${SectionIsReadOnly} a; ${SectionIsExpanded} a;
+; ${SectionIsPartiallySelected} a
+; Additional tests:
+; HK RegKeyIsEmpty SubKey
+;
+; Examples:
+; See LogicLib.nsi in the Examples folder for lots of example usage.
+
+!verbose push
+!verbose 3
+!ifndef LOGICLIB_VERBOSITY
+ !define LOGICLIB_VERBOSITY 3
+!endif
+!define _LOGICLIB_VERBOSITY ${LOGICLIB_VERBOSITY}
+!undef LOGICLIB_VERBOSITY
+!verbose ${_LOGICLIB_VERBOSITY}
+
+!ifndef LOGICLIB
+ !define LOGICLIB
+ !define | "'"
+ !define || "' '"
+ !define LOGICLIB_COUNTER 0
+
+ !include Sections.nsh
+
+ !macro _LOGICLIB_TEMP
+ !ifndef _LOGICLIB_TEMP
+ !define _LOGICLIB_TEMP
+ Var /GLOBAL _LOGICLIB_TEMP ; Temporary variable to aid the more elaborate logic tests
+ !endif
+ !macroend
+
+ !macro LogicLib_JumpToBranch _Jump _Skip
+ !if `${_Jump}${_Skip}` != ``
+ StrCmp "" "" `${_Jump}` ${_Skip}
+ !endif
+ !macroend
+
+ !macro _IncreaseCounter
+ !define /redef /math LOGICLIB_COUNTER `${LOGICLIB_COUNTER}` + 1
+ !macroend
+
+ !macro _PushLogic
+ !insertmacro _PushScope Logic _LogicLib_Label_${LOGICLIB_COUNTER}
+ !insertmacro _IncreaseCounter
+ !macroend
+
+ !macro _PopLogic
+ !insertmacro _PopScope Logic
+ !macroend
+
+ !macro _PushScope Type label
+ !ifdef _${Type} ; If we already have a statement
+ !define _Cur${Type} ${_${Type}}
+ !undef _${Type}
+ !define _${Type} ${label}
+ !define ${_${Type}}Prev${Type} ${_Cur${Type}} ; Save the current logic
+ !undef _Cur${Type}
+ !else
+ !define _${Type} ${label} ; Initialise for first statement
+ !endif
+ !macroend
+
+ !macro _PopScope Type
+ !ifndef _${Type}
+ !error "Cannot use _Pop${Type} without a preceding _Push${Type}"
+ !endif
+ !ifdef ${_${Type}}Prev${Type} ; If a previous statement was active then restore it
+ !define _Cur${Type} ${_${Type}}
+ !undef _${Type}
+ !define _${Type} ${${_Cur${Type}}Prev${Type}}
+ !undef ${_Cur${Type}}Prev${Type}
+ !undef _Cur${Type}
+ !else
+ !undef _${Type}
+ !endif
+ !macroend
+
+ !macro _LogicLib_AlwaysTrue _a _b _t _f
+ !insertmacro LogicLib_JumpToBranch `${_t}` `${_f}`
+ !macroend
+ !macro _LogicLib_AlwaysFalse _a _b _t _f
+ !insertmacro LogicLib_JumpToBranch `${_f}` `${_t}`
+ !macroend
+
+ ; String tests
+ !macro _== _a _b _t _f
+ StrCmp `${_a}` `${_b}` `${_t}` `${_f}`
+ !macroend
+
+ !macro _!= _a _b _t _f
+ !insertmacro _== `${_a}` `${_b}` `${_f}` `${_t}`
+ !macroend
+
+ ; Case-sensitive string tests
+ !macro _S== _a _b _t _f
+ StrCmpS `${_a}` `${_b}` `${_t}` `${_f}`
+ !macroend
+
+ !macro _S!= _a _b _t _f
+ !insertmacro _S== `${_a}` `${_b}` `${_f}` `${_t}`
+ !macroend
+
+ ; Extra string tests (cannot do these case-sensitively - I tried and lstrcmp still ignored the case)
+ !macro _StrCmpI _a _b _e _l _m
+ !insertmacro _LOGICLIB_TEMP
+ System::Call `kernel32::lstrcmpi(ts, ts) i.s` `${_a}` `${_b}`
+ Pop $_LOGICLIB_TEMP
+ IntCmp $_LOGICLIB_TEMP 0 `${_e}` `${_l}` `${_m}`
+ !macroend
+
+ !macro _S< _a _b _t _f
+ !insertmacro _StrCmpI `${_a}` `${_b}` `${_f}` `${_t}` `${_f}`
+ !macroend
+
+ !macro _S>= _a _b _t _f
+ !insertmacro _S< `${_a}` `${_b}` `${_f}` `${_t}`
+ !macroend
+
+ !macro _S> _a _b _t _f
+ !insertmacro _StrCmpI `${_a}` `${_b}` `${_f}` `${_f}` `${_t}`
+ !macroend
+
+ !macro _S<= _a _b _t _f
+ !insertmacro _S> `${_a}` `${_b}` `${_f}` `${_t}`
+ !macroend
+
+ ; Integer tests
+ !macro _= _a _b _t _f
+ IntCmp `${_a}` `${_b}` `${_t}` `${_f}` `${_f}`
+ !macroend
+
+ !macro _<> _a _b _t _f
+ !insertmacro _= `${_a}` `${_b}` `${_f}` `${_t}`
+ !macroend
+
+ !macro _< _a _b _t _f
+ IntCmp `${_a}` `${_b}` `${_f}` `${_t}` `${_f}`
+ !macroend
+
+ !macro _>= _a _b _t _f
+ !insertmacro _< `${_a}` `${_b}` `${_f}` `${_t}`
+ !macroend
+
+ !macro _> _a _b _t _f
+ IntCmp `${_a}` `${_b}` `${_f}` `${_f}` `${_t}`
+ !macroend
+
+ !macro _<= _a _b _t _f
+ !insertmacro _> `${_a}` `${_b}` `${_f}` `${_t}`
+ !macroend
+
+ !macro _& _a _b _t _f
+ !insertmacro _LOGICLIB_TEMP
+ IntOp $_LOGICLIB_TEMP `${_a}` & `${_b}`
+ !insertmacro _<> $_LOGICLIB_TEMP 0 `${_t}` `${_f}`
+ !macroend
+
+ ; Unsigned integer tests (NB: no need for extra equality tests)
+ !macro _U< _a _b _t _f
+ IntCmpU `${_a}` `${_b}` `${_f}` `${_t}` `${_f}`
+ !macroend
+
+ !macro _U>= _a _b _t _f
+ !insertmacro _U< `${_a}` `${_b}` `${_f}` `${_t}`
+ !macroend
+
+ !macro _U> _a _b _t _f
+ IntCmpU `${_a}` `${_b}` `${_f}` `${_f}` `${_t}`
+ !macroend
+
+ !macro _U<= _a _b _t _f
+ !insertmacro _U> `${_a}` `${_b}` `${_f}` `${_t}`
+ !macroend
+
+ ; Int64 tests
+ !macro _Int64Cmp _a _o _b _t _f
+ !insertmacro _LOGICLIB_TEMP
+ System::Int64Op `${_a}` `${_o}` `${_b}`
+ Pop $_LOGICLIB_TEMP
+ !insertmacro _= $_LOGICLIB_TEMP 0 `${_f}` `${_t}`
+ !macroend
+
+ !macro _L= _a _b _t _f
+ !insertmacro _Int64Cmp `${_a}` = `${_b}` `${_t}` `${_f}`
+ !macroend
+
+ !macro _L<> _a _b _t _f
+ !insertmacro _L= `${_a}` `${_b}` `${_f}` `${_t}`
+ !macroend
+
+ !macro _L< _a _b _t _f
+ !insertmacro _Int64Cmp `${_a}` < `${_b}` `${_t}` `${_f}`
+ !macroend
+
+ !macro _L>= _a _b _t _f
+ !insertmacro _L< `${_a}` `${_b}` `${_f}` `${_t}`
+ !macroend
+
+ !macro _L> _a _b _t _f
+ !insertmacro _Int64Cmp `${_a}` > `${_b}` `${_t}` `${_f}`
+ !macroend
+
+ !macro _L<= _a _b _t _f
+ !insertmacro _L> `${_a}` `${_b}` `${_f}` `${_t}`
+ !macroend
+
+ ; ptrdiff_t & size_t tests
+ !macro LogicLib_PtrDiffTest _o _a _b _t _f
+ !if "${NSIS_PTR_SIZE}" <= 4
+ !insertmacro _${_o} `${_a}` `${_b}` `${_t}` `${_f}`
+ !else
+ !insertmacro _L${_o} `${_a}` `${_b}` `${_t}` `${_f}`
+ !endif
+ !macroend
+ !macro _P= _a _b _t _f
+ !insertmacro LogicLib_PtrDiffTest = `${_a}` `${_b}` `${_t}` `${_f}`
+ !macroend
+ !macro _P<> _a _b _t _f
+ !insertmacro LogicLib_PtrDiffTest <> `${_a}` `${_b}` `${_t}` `${_f}`
+ !macroend
+ !macro _P< _a _b _t _f
+ !insertmacro LogicLib_PtrDiffTest < `${_a}` `${_b}` `${_t}` `${_f}`
+ !macroend
+ !macro _P>= _a _b _t _f
+ !insertmacro LogicLib_PtrDiffTest >= `${_a}` `${_b}` `${_t}` `${_f}`
+ !macroend
+ !macro _P> _a _b _t _f
+ !insertmacro LogicLib_PtrDiffTest > `${_a}` `${_b}` `${_t}` `${_f}`
+ !macroend
+ !macro _P<= _a _b _t _f
+ !insertmacro LogicLib_PtrDiffTest <= `${_a}` `${_b}` `${_t}` `${_f}`
+ !macroend
+ !include Util.nsh
+ !macro _Z= _a _b _t _f
+ !insertmacro LogicLib_PtrDiffTest = `${_a}` `${_b}` `${_t}` `${_f}`
+ !macroend
+ !macro _Z<> _a _b _t _f
+ !insertmacro LogicLib_PtrDiffTest <> `${_a}` `${_b}` `${_t}` `${_f}`
+ !macroend
+ !macro _Z< _a _b _t _f
+ !insertmacro IntPtrCmpU `${_a}` `${_b}` `${_f}` `${_t}` `${_f}`
+ !macroend
+ !macro _Z>= _a _b _t _f
+ !insertmacro IntPtrCmpU `${_a}` `${_b}` `${_t}` `${_f}` `${_t}`
+ !macroend
+ !macro _Z> _a _b _t _f
+ !insertmacro IntPtrCmpU `${_a}` `${_b}` `${_f}` `${_f}` `${_t}`
+ !macroend
+ !macro _Z<= _a _b _t _f
+ !insertmacro IntPtrCmpU `${_a}` `${_b}` `${_t}` `${_t}` `${_f}`
+ !macroend
+
+ ; Flag tests
+ !macro _Abort _a _b _t _f
+ IfAbort `${_t}` `${_f}`
+ !macroend
+ !define Abort `"" Abort ""`
+
+ !macro _Errors _a _b _t _f
+ IfErrors `${_t}` `${_f}`
+ !macroend
+ !define Errors `"" Errors ""`
+
+ !macro _FileExists _a _b _t _f
+ IfFileExists `${_b}` `${_t}` `${_f}`
+ !macroend
+ !define FileExists `"" FileExists`
+
+ !macro _RebootFlag _a _b _t _f
+ IfRebootFlag `${_t}` `${_f}`
+ !macroend
+ !define RebootFlag `"" RebootFlag ""`
+
+ !macro _Silent _a _b _t _f
+ IfSilent `${_t}` `${_f}`
+ !macroend
+ !define Silent `"" Silent ""`
+
+ !macro _ShellVarContextAll _a _b _t _f
+ IfShellVarContextAll `${_t}` `${_f}`
+ !macroend
+ !define ShellVarContextAll `"" ShellVarContextAll ""`
+
+ !macro _RtlLanguage _a _b _t _f
+ IfRtlLanguage `${_t}` `${_f}`
+ !macroend
+ !define RtlLanguage `"" RtlLanguage ""`
+
+ !macro _AltRegView _a _b _t _f
+ IfAltRegView `${_t}` `${_f}`
+ !macroend
+ !define AltRegView `"" AltRegView ""`
+
+ !macro _RegKeyIsEmpty _a _b _t _f
+ !insertmacro _LOGICLIB_TEMP
+ ClearErrors
+ EnumRegValue $_LOGICLIB_TEMP ${_a} `${_b}` ""
+ !if `${_f}` != ``
+ IfErrors "" `${_f}` ; Skip calls to EnumRegKey and _== if possible
+ !else
+ IfErrors +3
+ StrCpy $_LOGICLIB_TEMP "1" ; The default value is also named "", make sure we don't mistake it as empty
+ Goto +2
+ !endif
+ EnumRegKey $_LOGICLIB_TEMP ${_a} `${_b}` ""
+ !insertmacro _== $_LOGICLIB_TEMP "" `${_t}` `${_f}`
+ !macroend
+ !define RegKeyIsEmpty `RegKeyIsEmpty`
+
+ ; "Any instruction" test
+ !macro _Cmd _a _b _t _f
+ !define _t=${_t}
+ !ifdef _t= ; If no true label then make one
+ !define __t _LogicLib_Label_${LOGICLIB_COUNTER}
+ !insertmacro _IncreaseCounter
+ !else
+ !define __t ${_t}
+ !endif
+ ${_b} ${__t}
+ !define _f=${_f}
+ !ifndef _f= ; If a false label then go there
+ Goto ${_f}
+ !endif
+ !undef _f=${_f}
+ !ifdef _t= ; If we made our own true label then place it
+ ${__t}:
+ !endif
+ !undef __t
+ !undef _t=${_t}
+ !macroend
+ !define Cmd `"" Cmd`
+
+ ; Section flag test
+ !macro _SectionFlagIsSet _a _b _t _f
+ !insertmacro _LOGICLIB_TEMP
+ SectionGetFlags `${_b}` $_LOGICLIB_TEMP
+ IntOp $_LOGICLIB_TEMP $_LOGICLIB_TEMP & `${_a}`
+ !insertmacro _= $_LOGICLIB_TEMP `${_a}` `${_t}` `${_f}`
+ !macroend
+ !define SectionIsSelected `${SF_SELECTED} SectionFlagIsSet`
+ !define SectionIsSubSection `${SF_SUBSEC} SectionFlagIsSet`
+ !define SectionIsSubSectionEnd `${SF_SUBSECEND} SectionFlagIsSet`
+ !define SectionIsSectionGroup `${SF_SECGRP} SectionFlagIsSet`
+ !define SectionIsSectionGroupEnd `${SF_SECGRPEND} SectionFlagIsSet`
+ !define SectionIsBold `${SF_BOLD} SectionFlagIsSet`
+ !define SectionIsReadOnly `${SF_RO} SectionFlagIsSet`
+ !define SectionIsExpanded `${SF_EXPAND} SectionFlagIsSet`
+ !define SectionIsPartiallySelected `${SF_PSELECTED} SectionFlagIsSet`
+
+ !define IfCmd `!insertmacro _IfThen "" Cmd ${|}`
+
+ !macro _If _c _a _o _b
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !insertmacro _PushLogic
+ !define ${_Logic}If
+ !define ${_Logic}Else _LogicLib_ElseLabel_${LOGICLIB_COUNTER} ; Get a label for the Else
+ !insertmacro _IncreaseCounter
+ !define _c=${_c}
+ !ifdef _c=true ; If is true
+ !insertmacro _${_o} `${_a}` `${_b}` "" ${${_Logic}Else}
+ !else ; If condition is false
+ !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}Else} ""
+ !endif
+ !undef _c=${_c}
+ !verbose pop
+ !macroend
+ !define If `!insertmacro _If true`
+ !define Unless `!insertmacro _If false`
+ !define IfNot `!insertmacro _If false`
+
+ !macro _And _c _a _o _b
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !ifndef _Logic | ${_Logic}If
+ !error "Cannot use And without a preceding If or IfNot/Unless"
+ !endif
+ !ifndef ${_Logic}Else
+ !error "Cannot use And following an Else"
+ !endif
+ !define _c=${_c}
+ !ifdef _c=true ; If is true
+ !insertmacro _${_o} `${_a}` `${_b}` "" ${${_Logic}Else}
+ !else ; If condition is false
+ !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}Else} ""
+ !endif
+ !undef _c=${_c}
+ !verbose pop
+ !macroend
+ !define AndIf `!insertmacro _And true`
+ !define AndUnless `!insertmacro _And false`
+ !define AndIfNot `!insertmacro _And false`
+
+ !macro _Or _c _a _o _b
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !ifndef _Logic | ${_Logic}If
+ !error "Cannot use Or without a preceding If or IfNot/Unless"
+ !endif
+ !ifndef ${_Logic}Else
+ !error "Cannot use Or following an Else"
+ !endif
+ !define _label _LogicLib_Label_${LOGICLIB_COUNTER} ; Skip this test as we already
+ !insertmacro _IncreaseCounter
+ Goto ${_label} ; have a successful result
+ ${${_Logic}Else}: ; Place the Else label
+ !undef ${_Logic}Else ; and remove it
+ !define ${_Logic}Else _LogicLib_ElseLabel_${LOGICLIB_COUNTER} ; Get a label for the next Else and perform the new If
+ !insertmacro _IncreaseCounter
+ !define _c=${_c}
+ !ifdef _c=true ; If is true
+ !insertmacro _${_o} `${_a}` `${_b}` "" ${${_Logic}Else}
+ !else ; If condition is false
+ !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}Else} ""
+ !endif
+ !undef _c=${_c}
+ ${_label}:
+ !undef _label
+ !verbose pop
+ !macroend
+ !define OrIf `!insertmacro _Or true`
+ !define OrUnless `!insertmacro _Or false`
+ !define OrIfNot `!insertmacro _Or false`
+
+ !macro _Else
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !ifndef _Logic | ${_Logic}If
+ !error "Cannot use Else without a preceding If or IfNot/Unless"
+ !endif
+ !ifndef ${_Logic}Else
+ !error "Cannot use Else following an Else"
+ !endif
+ !ifndef ${_Logic}EndIf ; First Else for this If?
+ !define ${_Logic}EndIf _LogicLib_EndIfLabel_${LOGICLIB_COUNTER} ; Get a label for the EndIf
+ !insertmacro _IncreaseCounter
+ !endif
+ Goto ${${_Logic}EndIf} ; Go to the EndIf
+ ${${_Logic}Else}: ; Place the Else label
+ !undef ${_Logic}Else ; and remove it
+ !verbose pop
+ !macroend
+ !define Else `!insertmacro _Else`
+
+ !macro _ElseIf _c _a _o _b
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ ${Else} ; Perform the Else
+ !define ${_Logic}Else _LogicLib_ElseLabel_${LOGICLIB_COUNTER} ; Get a label for the next Else and perform the new If
+ !insertmacro _IncreaseCounter
+ !define _c=${_c}
+ !ifdef _c=true ; If is true
+ !insertmacro _${_o} `${_a}` `${_b}` "" ${${_Logic}Else}
+ !else ; If condition is false
+ !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}Else} ""
+ !endif
+ !undef _c=${_c}
+ !verbose pop
+ !macroend
+ !define ElseIf `!insertmacro _ElseIf true`
+ !define ElseUnless `!insertmacro _ElseIf false`
+ !define ElseIfNot `!insertmacro _ElseIf false`
+
+ !macro _EndIf _n
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !ifndef _Logic | ${_Logic}If
+ !error "Cannot use End${_n} without a preceding If or IfNot/Unless"
+ !endif
+ !ifdef ${_Logic}Else
+ ${${_Logic}Else}: ; Place the Else label
+ !undef ${_Logic}Else ; and remove it
+ !endif
+ !ifdef ${_Logic}EndIf
+ ${${_Logic}EndIf}: ; Place the EndIf
+ !undef ${_Logic}EndIf ; and remove it
+ !endif
+ !undef ${_Logic}If
+ !insertmacro _PopLogic
+ !verbose pop
+ !macroend
+ !define EndIf `!insertmacro _EndIf If`
+ !define EndUnless `!insertmacro _EndIf Unless`
+
+ !macro _IfThen _a _o _b _t
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ ${If} `${_a}` `${_o}` `${_b}`
+ ${_t}
+ ${EndIf}
+ !verbose pop
+ !macroend
+ !define IfThen `!insertmacro _IfThen`
+
+ !macro _IfNotThen _a _o _b _t
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ ${IfNot} `${_a}` `${_o}` `${_b}`
+ ${_t}
+ ${EndIf}
+ !verbose pop
+ !macroend
+ !define IfNotThen `!insertmacro _IfNotThen`
+
+ !macro _ForEach _v _f _t _o _s
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ StrCpy "${_v}" "${_f}" ; Assign the initial value
+ Goto +2 ; Skip the loop expression for the first iteration
+ !define _DoLoopExpression `IntOp "${_v}" "${_v}" "${_o}" "${_s}"` ; Define the loop expression
+ !define _o=${_o}
+ !ifdef _o=+ ; Check the loop expression operator
+ !define __o > ; to determine the correct loop condition
+ !else ifdef _o=-
+ !define __o <
+ !else
+ !error "Unsupported ForEach step operator (must be + or -)"
+ !endif
+ !undef _o=${_o}
+ !insertmacro _Do For false `${_v}` `${__o}` `${_t}` ; Let Do do the rest
+ !undef __o
+ !verbose pop
+ !macroend
+ !define ForEach `!insertmacro _ForEach`
+
+ !macro _For _v _f _t
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ ${ForEach} `${_v}` `${_f}` `${_t}` + 1 ; Pass on to ForEach
+ !verbose pop
+ !macroend
+ !define For `!insertmacro _For`
+
+ !define ExitFor `!insertmacro _Goto ExitFor For`
+
+ !define Next `!insertmacro _Loop For Next "" "" "" ""`
+
+ !define While `!insertmacro _Do While true`
+
+ !define ExitWhile `!insertmacro _Goto ExitWhile While`
+
+ !define EndWhile `!insertmacro _Loop While EndWhile "" "" "" ""`
+
+ !macro _Do _n _c _a _o _b
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !insertmacro _PushLogic
+ !define ${_Logic}${_n} _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the start of the loop
+ !insertmacro _IncreaseCounter
+ ${${_Logic}${_n}}:
+ !insertmacro _PushScope Exit${_n} _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the end of the loop
+ !insertmacro _IncreaseCounter
+ !insertmacro _PushScope Break ${_Exit${_n}} ; Break goes to the end of the loop
+ !ifdef _DoLoopExpression
+ ${_DoLoopExpression} ; Special extra parameter for inserting code
+ !undef _DoLoopExpression ; between the Continue label and the loop condition
+ !endif
+ !define _c=${_c}
+ !ifdef _c= ; No starting condition
+ !insertmacro _PushScope Continue _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for Continue at the end of the loop
+ !insertmacro _IncreaseCounter
+ !else
+ !insertmacro _PushScope Continue ${${_Logic}${_n}} ; Continue goes to the start of the loop
+ !ifdef _c=true ; If is true
+ !insertmacro _${_o} `${_a}` `${_b}` "" ${_Exit${_n}}
+ !else ; If condition is false
+ !insertmacro _${_o} `${_a}` `${_b}` ${_Exit${_n}} ""
+ !endif
+ !endif
+ !undef _c=${_c}
+ !define ${_Logic}Condition ${_c} ; Remember the condition used
+ !verbose pop
+ !macroend
+ !define Do `!insertmacro _Do Do "" "" "" ""`
+ !define DoWhile `!insertmacro _Do Do true`
+ !define DoUntil `!insertmacro _Do Do false`
+
+ !macro _Goto _n _s
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !ifndef _${_n}
+ !error "Cannot use ${_n} without a preceding ${_s}"
+ !endif
+ Goto ${_${_n}}
+ !verbose pop
+ !macroend
+ !define ExitDo `!insertmacro _Goto ExitDo Do`
+
+ !macro _Loop _n _e _c _a _o _b
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !ifndef _Logic | ${_Logic}${_n}
+ !error "Cannot use ${_e} without a preceding ${_n}"
+ !endif
+ !define _c=${${_Logic}Condition}
+ !ifdef _c= ; If Do had no condition place the Continue label
+ ${_Continue}:
+ !endif
+ !undef _c=${${_Logic}Condition}
+ !define _c=${_c}
+ !ifdef _c= ; No ending condition
+ Goto ${${_Logic}${_n}}
+ !else ifdef _c=true ; If condition is true
+ !insertmacro _${_o} `${_a}` `${_b}` ${${_Logic}${_n}} ${_Exit${_n}}
+ !else ; If condition is false
+ !insertmacro _${_o} `${_a}` `${_b}` ${_Exit${_n}} ${${_Logic}${_n}}
+ !endif
+ !undef _c=${_c}
+ Goto ${_Continue} ; Just to ensure it is referenced at least once
+ Goto ${_Exit${_n}} ; Just to ensure it is referenced at least once
+ ${_Exit${_n}}: ; Place the loop exit point
+ !undef ${_Logic}Condition
+ !insertmacro _PopScope Continue
+ !insertmacro _PopScope Break
+ !insertmacro _PopScope Exit${_n}
+ !undef ${_Logic}${_n}
+ !insertmacro _PopLogic
+ !verbose pop
+ !macroend
+ !define Loop `!insertmacro _Loop Do Loop "" "" "" ""`
+ !define LoopWhile `!insertmacro _Loop Do LoopWhile true`
+ !define LoopUntil `!insertmacro _Loop Do LoopUntil false`
+
+ !define Continue `!insertmacro _Goto Continue "For or Do or While"`
+ !define Break `!insertmacro _Goto Break "For or Do or While"`
+
+ !macro _Select _a
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !insertmacro _PushLogic
+ !define ${_Logic}Select `${_a}` ; Remember the left hand side of the comparison
+ !verbose pop
+ !macroend
+ !define Select `!insertmacro _Select`
+
+ !macro _Select_CaseElse
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !ifndef _Logic | ${_Logic}Select
+ !error "Cannot use Case without a preceding Select"
+ !endif
+ !ifdef ${_Logic}EndSelect ; This is set only after the first case
+ !ifndef ${_Logic}Else
+ !error "Cannot use Case following a CaseElse"
+ !endif
+ Goto ${${_Logic}EndSelect} ; Go to EndSelect (Ends the previous Case)
+ !define /IfNDef _LogicLib_EndSelectLabelUsed_${_Logic}
+ ${${_Logic}Else}: ; Place the Else label
+ !undef ${_Logic}Else ; and remove it
+ !else
+ !define ${_Logic}EndSelect _LogicLib_EndSelectLabel_${LOGICLIB_COUNTER} ; Get a label for the EndSelect
+ !insertmacro _IncreaseCounter
+ !endif
+ !verbose pop
+ !macroend
+ !define CaseElse `!insertmacro _CaseElse`
+ !define Case_Else `!insertmacro _CaseElse` ; Compatibility with 2.2 and earlier
+ !define Default `!insertmacro _CaseElse` ; For the C-minded
+
+ !macro _Select_Case _a
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ ${CaseElse} ; Perform the CaseElse
+ !define ${_Logic}Else _LogicLib_NextSelectCaseLabel_${LOGICLIB_COUNTER} ; Get a label for the next Else and perform the new Case
+ !insertmacro _IncreaseCounter
+ !insertmacro _== `${${_Logic}Select}` `${_a}` "" ${${_Logic}Else}
+ !verbose pop
+ !macroend
+ !define Case `!insertmacro _Case`
+
+ !macro _Case2 _a _b
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ ${CaseElse} ; Perform the CaseElse
+ !define ${_Logic}Else _LogicLib_NextSelectCaseLabel_${LOGICLIB_COUNTER} ; Get a label for the next Else and perform the new Case
+ !insertmacro _IncreaseCounter
+ !insertmacro _== `${${_Logic}Select}` `${_a}` +2 ""
+ !insertmacro _== `${${_Logic}Select}` `${_b}` "" ${${_Logic}Else}
+ !verbose pop
+ !macroend
+ !define Case2 `!insertmacro _Case2`
+
+ !macro _Case3 _a _b _c
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ ${CaseElse} ; Perform the CaseElse
+ !define ${_Logic}Else _LogicLib_NextSelectCaseLabel_${LOGICLIB_COUNTER} ; Get a label for the next Else and perform the new Case
+ !insertmacro _IncreaseCounter
+ !insertmacro _== `${${_Logic}Select}` `${_a}` +3 ""
+ !insertmacro _== `${${_Logic}Select}` `${_b}` +2 ""
+ !insertmacro _== `${${_Logic}Select}` `${_c}` "" ${${_Logic}Else}
+ !verbose pop
+ !macroend
+ !define Case3 `!insertmacro _Case3`
+
+ !macro _Case4 _a _b _c _d
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ ${CaseElse} ; Perform the CaseElse
+ !define ${_Logic}Else _LogicLib_NextSelectCaseLabel_${LOGICLIB_COUNTER} ; Get a label for the next Else and perform the new Case
+ !insertmacro _IncreaseCounter
+ !insertmacro _== `${${_Logic}Select}` `${_a}` +4 ""
+ !insertmacro _== `${${_Logic}Select}` `${_b}` +3 ""
+ !insertmacro _== `${${_Logic}Select}` `${_c}` +2 ""
+ !insertmacro _== `${${_Logic}Select}` `${_d}` "" ${${_Logic}Else}
+ !verbose pop
+ !macroend
+ !define Case4 `!insertmacro _Case4`
+
+ !macro _Case5 _a _b _c _d _e
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ ${CaseElse} ; Perform the CaseElse
+ !define ${_Logic}Else _LogicLib_NextSelectCaseLabel_${LOGICLIB_COUNTER} ; Get a label for the next Else and perform the new Case
+ !insertmacro _IncreaseCounter
+ !insertmacro _== `${${_Logic}Select}` `${_a}` +5 ""
+ !insertmacro _== `${${_Logic}Select}` `${_b}` +4 ""
+ !insertmacro _== `${${_Logic}Select}` `${_c}` +3 ""
+ !insertmacro _== `${${_Logic}Select}` `${_d}` +2 ""
+ !insertmacro _== `${${_Logic}Select}` `${_e}` "" ${${_Logic}Else}
+ !verbose pop
+ !macroend
+ !define Case5 `!insertmacro _Case5`
+
+ !macro _EndSelect
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !ifndef _Logic | ${_Logic}Select
+ !error "Cannot use EndSelect without a preceding Select"
+ !endif
+ !ifdef ${_Logic}Else
+ ${${_Logic}Else}: ; Place the Else label
+ !undef ${_Logic}Else ; and remove it
+ !endif
+ !ifdef ${_Logic}EndSelect ; This won't be set if there weren't any cases
+ !ifdef _LogicLib_EndSelectLabelUsed_${_Logic} ; There is no jump to ${${_Logic}EndSelect}: if there is only one Case
+ ${${_Logic}EndSelect}: ; Place the EndSelect
+ !undef _LogicLib_EndSelectLabelUsed_${_Logic}
+ !endif
+ !undef ${_Logic}EndSelect ; and remove it
+ !endif
+ !undef ${_Logic}Select
+ !insertmacro _PopLogic
+ !verbose pop
+ !macroend
+ !define EndSelect `!insertmacro _EndSelect`
+
+ !macro _Switch _a
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !insertmacro _PushLogic
+ !insertmacro _PushScope Switch ${_Logic} ; Keep a separate stack for switch data
+ !insertmacro _PushScope Break _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for beyond the end of the switch
+ !insertmacro _IncreaseCounter
+ !define ${_Switch}Var `${_a}` ; Remember the left hand side of the comparison
+ !tempfile ${_Switch}Tmp ; Create a temporary file
+ !if "${NSIS_CHAR_SIZE}" > 1
+ !appendfile /CHARSET=UTF8SIG "${${_Switch}Tmp}" "" ; Make sure the file uses Unicode
+ !endif
+ !define ${_Logic}Switch _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the end of the switch
+ !insertmacro _IncreaseCounter
+ Goto ${${_Logic}Switch} ; and go there
+ !verbose pop
+ !macroend
+ !define Switch `!insertmacro _Switch`
+
+ !macro _Case _a
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !ifdef _Logic & ${_Logic}Select ; Check for an active Select
+ !insertmacro _Select_Case `${_a}`
+ !else ifndef _Switch ; If not then check for an active Switch
+ !error "Cannot use Case without a preceding Select or Switch"
+ !else
+ !define _label _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for this case,
+ !insertmacro _IncreaseCounter
+ ${_label}: ; place it and add it's check to the temp file
+ !appendfile "${${_Switch}Tmp}" `!insertmacro _== $\`${${_Switch}Var}$\` $\`${_a}$\` ${_label} ""$\n`
+ !undef _label
+ !endif
+ !verbose pop
+ !macroend
+
+ !macro _CaseElse
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !ifdef _Logic & ${_Logic}Select ; Check for an active Select
+ !insertmacro _Select_CaseElse
+ !else ifndef _Switch ; If not then check for an active Switch
+ !error "Cannot use Case without a preceding Select or Switch"
+ !else ifdef ${_Switch}Else ; Already had a default case?
+ !error "Cannot use CaseElse following a CaseElse"
+ !else
+ !define ${_Switch}Else _LogicLib_Label_${LOGICLIB_COUNTER} ; Get a label for the default case,
+ !insertmacro _IncreaseCounter
+ ${${_Switch}Else}: ; and place it
+ !endif
+ !verbose pop
+ !macroend
+
+ !macro _EndSwitch
+ !verbose push
+ !verbose ${LOGICLIB_VERBOSITY}
+ !ifndef _Logic | ${_Logic}Switch
+ !error "Cannot use EndSwitch without a preceding Switch"
+ !endif
+ Goto ${_Break} ; Skip the jump table
+ ${${_Logic}Switch}: ; Place the end of the switch
+ !undef ${_Logic}Switch
+ !include "${${_Switch}Tmp}" ; Include the jump table
+ !delfile "${${_Switch}Tmp}" ; and clear it up
+ !ifdef ${_Switch}Else ; Was there a default case?
+ Goto ${${_Switch}Else} ; then go there if all else fails
+ !undef ${_Switch}Else
+ !endif
+ !undef ${_Switch}Tmp
+ !undef ${_Switch}Var
+ ${_Break}: ; Place the break label
+ !insertmacro _PopScope Break
+ !insertmacro _PopScope Switch
+ !insertmacro _PopLogic
+ !verbose pop
+ !macroend
+ !define EndSwitch `!insertmacro _EndSwitch`
+
+!endif ; LOGICLIB
+!verbose 3
+!define LOGICLIB_VERBOSITY ${_LOGICLIB_VERBOSITY}
+!undef _LOGICLIB_VERBOSITY
+!verbose pop
diff --git a/installer/tools/Include/MUI.nsh b/installer/tools/Include/MUI.nsh
new file mode 100644
index 00000000..c2b2a71c
--- /dev/null
+++ b/installer/tools/Include/MUI.nsh
@@ -0,0 +1 @@
+!include "${NSISDIR}\Contrib\Modern UI\System.nsh"
\ No newline at end of file
diff --git a/installer/tools/Include/MUI2.nsh b/installer/tools/Include/MUI2.nsh
new file mode 100644
index 00000000..0e76adbf
--- /dev/null
+++ b/installer/tools/Include/MUI2.nsh
@@ -0,0 +1 @@
+!include "${NSISDIR}\Contrib\Modern UI 2\MUI2.nsh"
\ No newline at end of file
diff --git a/installer/tools/Include/Memento.nsh b/installer/tools/Include/Memento.nsh
new file mode 100644
index 00000000..3381c85c
--- /dev/null
+++ b/installer/tools/Include/Memento.nsh
@@ -0,0 +1,553 @@
+!verbose push
+!verbose 3
+
+!include LogicLib.nsh
+!include Sections.nsh
+
+!ifndef ___MEMENTO_NSH___
+!define ___MEMENTO_NSH___
+
+#####################################
+### Memento ###
+#####################################
+
+/*
+
+Memento is a set of macros that allow installers to remember user selection
+across separate runs of the installer. Currently, it can remember the state
+of sections and mark new sections as bold. In the future, it'll integrate
+InstallOptions and maybe even the Modern UI.
+
+A usage example can be found in `Examples\Memento.nsi`.
+
+*/
+
+#####################################
+### Usage Instructions ###
+#####################################
+
+/*
+
+1. Declare usage of Memento by including Memento.nsh at the top of the script.
+
+ !include Memento.nsh
+
+2. Define MEMENTO_REGISTRY_ROOT and MEMENTO_REGISTRY_KEY with the a registry key
+ where sections' state should be saved.
+
+ !define MEMENTO_REGISTRY_ROOT HKLM
+ !define MEMENTO_REGISTRY_KEY \
+ Software\Microsoft\Windows\CurrentVersion\Uninstall\MyProgram
+
+3. Replace Section with ${MementoSection} and SectionEnd with ${MementoSectionEnd}
+ for sections that whose state should be remembered by Memento.
+
+ For sections that should be unselected by default, use ${MementoSection}'s
+ brother - ${MementoUnselectedSection}.
+
+ Sections that don't already have an identifier must be assigned one.
+
+ Section identifiers must stay the same across different versions of the
+ installer or their state will be forgotten.
+
+4. Use ${MementoSectionDone} after the last ${MementoSection}.
+
+5. Add a call to ${MementoSectionRestore} to .onInit to restore the state
+ of all sections from the registry.
+
+ Function .onInit
+
+ ${MementoSectionRestore}
+
+ FunctionEnd
+
+6. Add a call to ${MementoSectionSave} to .onInstSuccess to save the state
+ of all sections to the registry.
+
+ Function .onInstSuccess
+
+ ${MementoSectionSave}
+
+ FunctionEnd
+
+7. Tattoo the location of the chosen registry key on your arm.
+
+*/
+
+#####################################
+### User API ###
+#####################################
+
+;
+; ${MementoSection}
+;
+; Defines a section whose state is remembered by Memento.
+;
+; Usage is similar to Section.
+;
+; ${MementoSection} "name" "some_id"
+;
+
+!define MementoSection "!insertmacro MementoSection"
+
+;
+; ${MementoSectionEnd}
+;
+; Ends a section previously opened using ${MementoSection}.
+;
+; Usage is similar to SectionEnd.
+;
+; ${MementoSection} "name" "some_id"
+; # some code...
+; ${MementoSectionEnd}
+;
+
+;
+; ${MementoUnselectedSection}
+;
+; Defines a section whose state is remembered by Memento and is
+; unselected by default.
+;
+; Usage is similar to Section with the /o switch.
+;
+; ${MementoUnselectedSection} "name" "some_id"
+;
+
+!define MementoUnselectedSection "!insertmacro MementoUnselectedSection"
+
+;
+; ${MementoSectionEnd}
+;
+; Ends a section previously opened using ${MementoSection}.
+;
+; Usage is similar to SectionEnd.
+;
+; ${MementoSection} "name" "some_id"
+; # some code...
+; ${MementoSectionEnd}
+;
+
+!define MementoSectionEnd "!insertmacro MementoSectionEnd"
+
+;
+; ${MementoSectionDone}
+;
+; Used after all ${MementoSection} have been set.
+;
+; ${MementoSection} "name1" "some_id1"
+; # some code...
+; ${MementoSectionEnd}
+;
+; ${MementoSection} "name2" "some_id2"
+; # some code...
+; ${MementoSectionEnd}
+;
+; ${MementoSection} "name3" "some_id3"
+; # some code...
+; ${MementoSectionEnd}
+;
+; ${MementoSectionDone}
+;
+
+!define MementoSectionDone "!insertmacro MementoSectionDone"
+
+;
+; ${MementoSectionRestore}
+;
+; Restores the state of all Memento sections from the registry.
+;
+; Commonly used in .onInit.
+;
+; Function .onInit
+;
+; ${MementoSectionRestore}
+;
+; FunctionEnd
+;
+
+!define MementoSectionRestore "!insertmacro MementoSectionRestore"
+
+;
+; ${MementoSectionSave}
+;
+; Saves the state of all Memento sections to the registry.
+;
+; Commonly used in .onInstSuccess.
+;
+; Function .onInstSuccess
+;
+; ${MementoSectionSave}
+;
+; FunctionEnd
+;
+
+!define MementoSectionSave "!insertmacro MementoSectionSave"
+
+;
+; MementoSection
+;
+; Replaceable macros that allow custom storage methods to be used.
+;
+
+!ifmacrondef MementoSectionReadInt
+!define __MementoSectionStdRegReadWrite
+
+!macro MementoSectionReadInt outvar name
+ReadRegDWord ${outvar} ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `MementoSection${name}`
+!macroend
+
+!macro MementoSectionWriteInt name val
+WriteRegDWord ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `MementoSection${name}` `${val}`
+!macroend
+
+!macro MementoSectionReadMarker outvar name
+ReadRegStr ${outvar} ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `MementoSection${name}`
+!macroend
+
+!macro MementoSectionWriteMarker name
+WriteRegStr ${MEMENTO_REGISTRY_ROOT} `${MEMENTO_REGISTRY_KEY}` `MementoSection${name}` ``
+!macroend
+
+!endif
+
+#####################################
+### Internal Defines ###
+#####################################
+
+!define __MementoSectionIndex 1
+
+#####################################
+### Internal Macros ###
+#####################################
+
+!macro __MementoCheckSettings
+
+ !ifdef __MementoSectionStdRegReadWrite
+ !ifndef MEMENTO_REGISTRY_ROOT | MEMENTO_REGISTRY_KEY
+
+ !error "MEMENTO_REGISTRY_ROOT and MEMENTO_REGISTRY_KEY must be defined before using any of Memento's macros"
+
+ !endif
+ !endif
+
+!macroend
+
+!macro __MementoSection flags name id
+
+ !insertmacro __MementoCheckSettings
+
+ !ifndef __MementoSectionIndex
+
+ !error "MementoSectionDone already used!"
+
+ !endif
+
+ !define __MementoSectionLastSectionId `${id}`
+
+ !verbose pop
+
+ Section ${flags} `${name}` `${id}`
+
+ !verbose push
+ !verbose 3
+
+!macroend
+
+#####################################
+### User Macros ###
+#####################################
+
+!macro MementoSection name id
+
+ !verbose push
+ !verbose 3
+
+ !insertmacro __MementoSection "" `${name}` `${id}`
+
+ !verbose pop
+
+!macroend
+
+!macro MementoUnselectedSection name id
+
+ !verbose push
+ !verbose 3
+
+ !insertmacro __MementoSection /o `${name}` `${id}`
+
+ !define __MementoSectionUnselected
+
+ !verbose pop
+
+!macroend
+
+!macro MementoSectionEnd
+
+ SectionEnd
+
+ !verbose push
+ !verbose 3
+
+ !insertmacro __MementoCheckSettings
+
+ !ifndef __MementoSectionIndex
+
+ !error "MementoSectionDone already used!"
+
+ !endif
+
+ !define /MATH __MementoSectionIndexNext \
+ ${__MementoSectionIndex} + 1
+
+ Function __MementoSectionMarkNew${__MementoSectionIndex}
+
+ ClearErrors
+ !insertmacro MementoSectionReadInt $0 `_${__MementoSectionLastSectionId}`
+
+ ${If} ${Errors}
+
+ !insertmacro SetSectionFlag `${${__MementoSectionLastSectionId}}` ${SF_BOLD}
+
+ ${EndIf}
+
+ GetFunctionAddress $0 __MementoSectionMarkNew${__MementoSectionIndexNext}
+ Goto $0
+
+ FunctionEnd
+
+ Function __MementoSectionRestoreStatus${__MementoSectionIndex}
+
+ ClearErrors
+ !insertmacro MementoSectionReadInt $0 `_${__MementoSectionLastSectionId}`
+
+ !ifndef __MementoSectionUnselected
+
+ ${If} ${Errors}
+ ${OrIf} $0 != 0
+
+ !insertmacro SelectSection `${${__MementoSectionLastSectionId}}`
+
+ ${Else}
+
+ !insertmacro UnselectSection `${${__MementoSectionLastSectionId}}`
+
+ ${EndIf}
+
+ !else
+
+ !undef __MementoSectionUnselected
+
+ ${If} ${Errors}
+ ${OrIf} $0 == 0
+
+ !insertmacro UnselectSection `${${__MementoSectionLastSectionId}}`
+
+ ${Else}
+
+ !insertmacro SelectSection `${${__MementoSectionLastSectionId}}`
+
+ ${EndIf}
+
+ !endif
+
+ GetFunctionAddress $0 __MementoSectionRestoreStatus${__MementoSectionIndexNext}
+ Goto $0
+
+ FunctionEnd
+
+ Function __MementoSectionSaveStatus${__MementoSectionIndex}
+
+ ${If} ${SectionIsSelected} `${${__MementoSectionLastSectionId}}`
+
+ !insertmacro MementoSectionWriteInt `_${__MementoSectionLastSectionId}` 1
+
+ ${Else}
+
+ !insertmacro MementoSectionWriteInt `_${__MementoSectionLastSectionId}` 0
+
+ ${EndIf}
+
+ GetFunctionAddress $0 __MementoSectionSaveStatus${__MementoSectionIndexNext}
+ Goto $0
+
+ FunctionEnd
+
+ !undef __MementoSectionIndex
+ !define __MementoSectionIndex ${__MementoSectionIndexNext}
+ !undef __MementoSectionIndexNext
+
+ !undef __MementoSectionLastSectionId
+
+ !verbose pop
+
+!macroend
+
+!macro MementoSectionDone
+
+ !verbose push
+ !verbose 3
+
+ !insertmacro __MementoCheckSettings
+
+ Function __MementoSectionMarkNew${__MementoSectionIndex}
+ FunctionEnd
+
+ Function __MementoSectionRestoreStatus${__MementoSectionIndex}
+ FunctionEnd
+
+ Function __MementoSectionSaveStatus${__MementoSectionIndex}
+ FunctionEnd
+
+ !undef __MementoSectionIndex
+
+ !verbose pop
+
+!macroend
+
+!macro MementoSectionRestore
+
+ !verbose push
+ !verbose 3
+
+ !insertmacro __MementoCheckSettings
+
+ Push $0
+ Push $1
+ Push $2
+ Push $3
+
+ # check for first usage
+
+ ClearErrors
+ !insertmacro MementoSectionReadMarker $0 `Used`
+
+ ${If} ${Errors}
+
+ # use script defaults on first run
+ Goto done
+
+ ${EndIf}
+
+ # mark new components in bold
+
+ Call __MementoSectionMarkNew1
+
+ # mark section groups in bold
+
+ StrCpy $0 0
+ StrCpy $1 ""
+ StrCpy $2 ""
+ StrCpy $3 ""
+
+ loop:
+
+ ClearErrors
+
+ ${If} ${SectionIsBold} $0
+
+ ${If} $1 != ""
+
+ !insertmacro SetSectionFlag $1 ${SF_BOLD}
+
+ ${EndIf}
+
+ ${If} $2 != ""
+
+ !insertmacro SetSectionFlag $2 ${SF_BOLD}
+
+ ${EndIf}
+
+ ${If} $3 != ""
+
+ !insertmacro SetSectionFlag $3 ${SF_BOLD}
+
+ ${EndIf}
+
+ ${ElseIf} ${Errors}
+
+ Goto loop_end
+
+ ${EndIf}
+
+ ${If} ${SectionIsSectionGroup} $0
+
+ ${If} $1 == ""
+
+ StrCpy $1 $0
+
+ ${ElseIf} $2 == ""
+
+ StrCpy $2 $0
+
+ ${ElseIf} $3 == ""
+
+ StrCpy $3 $0
+
+ ${EndIf}
+
+ ${EndIf}
+
+ ${If} ${SectionIsSectionGroupEnd} $0
+
+ ${If} $3 != ""
+
+ StrCpy $3 ""
+
+ ${ElseIf} $2 != ""
+
+ StrCpy $2 ""
+
+ ${ElseIf} $1 != ""
+
+ StrCpy $1 ""
+
+ ${EndIf}
+
+ ${EndIf}
+
+ IntOp $0 $0 + 1
+
+ Goto loop
+ loop_end:
+
+ # restore sections' status
+
+ Call __MementoSectionRestoreStatus1
+
+ # all done
+
+ done:
+
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+
+ !verbose pop
+
+!macroend
+
+!macro MementoSectionSave
+
+ !verbose push
+ !verbose 3
+
+ !insertmacro __MementoCheckSettings
+
+ Push $0
+
+ !insertmacro MementoSectionWriteMarker `Used`
+
+ Call __MementoSectionSaveStatus1
+
+ Pop $0
+
+ !verbose pop
+
+!macroend
+
+
+
+!endif # ___MEMENTO_NSH___
+
+!verbose pop
diff --git a/installer/tools/Include/MultiUser.nsh b/installer/tools/Include/MultiUser.nsh
new file mode 100644
index 00000000..7c59c730
--- /dev/null
+++ b/installer/tools/Include/MultiUser.nsh
@@ -0,0 +1,505 @@
+/*
+
+MultiUser.nsh
+
+Installer configuration for multi-user Windows environments
+
+Copyright 2008-2023 Joost Verburg
+
+*/
+
+!ifndef MULTIUSER_INCLUDED
+!define MULTIUSER_INCLUDED 20210216
+!verbose push 3
+
+;Standard NSIS header files
+
+!ifdef MULTIUSER_MUI
+ !include MUI2.nsh
+!endif
+!include LogicLib.nsh
+!include WinVer.nsh
+!include FileFunc.nsh
+
+!if ${NSIS_PTR_SIZE} > 4
+!define /IfNDef MULTIUSER_MINWIN 0x501
+!else
+!define /IfNDef MULTIUSER_MINWIN 0x400
+!endif
+
+;Variables
+
+Var MultiUser.Privileges
+Var MultiUser.InstallMode
+
+;Command line installation mode setting
+
+!ifdef MULTIUSER_INSTALLMODE_COMMANDLINE
+ !include StrFunc.nsh
+ ${Using:StrFunc} StrStr
+ !ifndef MULTIUSER_NOUNINSTALL
+ ${Using:StrFunc} UnStrStr
+ !endif
+
+ Var MultiUser.Parameters
+ Var MultiUser.Result
+!endif
+
+;Installation folder stored in registry
+
+!ifdef MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY & MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME
+ Var MultiUser.InstDir
+!endif
+
+!ifdef MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY & MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME
+ Var MultiUser.DefaultKeyValue
+!endif
+
+;Windows Vista UAC setting
+
+!if "${MULTIUSER_EXECUTIONLEVEL}" == Admin
+ RequestExecutionLevel admin
+ !define MULTIUSER_EXECUTIONLEVEL_ALLUSERS
+!else if "${MULTIUSER_EXECUTIONLEVEL}" == Power
+ RequestExecutionLevel admin
+ !define MULTIUSER_EXECUTIONLEVEL_ALLUSERS
+!else if "${MULTIUSER_EXECUTIONLEVEL}" == Highest
+ RequestExecutionLevel highest
+ !define MULTIUSER_EXECUTIONLEVEL_ALLUSERS
+!else
+ RequestExecutionLevel user
+ !ifndef MULTIUSER_EXECUTIONLEVEL
+ !warning "MULTIUSER_EXECUTIONLEVEL not set!"
+ !endif
+!endif
+
+/*
+
+Install modes
+
+*/
+
+!macro MULTIUSER_INSTALLMODE_ALLUSERS UNINSTALLER_PREFIX UNINSTALLER_FUNCPREFIX
+
+ ;Install mode initialization - per-machine
+
+ ${ifnot} ${IsNT}
+ ${orif} $MultiUser.Privileges == "Admin"
+ ${orif} $MultiUser.Privileges == "Power"
+
+ StrCpy $MultiUser.InstallMode AllUsers
+
+ SetShellVarContext all
+
+ !if "${UNINSTALLER_PREFIX}" != UN
+ ;Set default installation location for installer
+ !ifdef MULTIUSER_INSTALLMODE_INSTDIR
+ !ifdef MULTIUSER_USE_PROGRAMFILES64
+ StrCpy $INSTDIR "$PROGRAMFILES64\${MULTIUSER_INSTALLMODE_INSTDIR}"
+ !else
+ StrCpy $INSTDIR "$PROGRAMFILES\${MULTIUSER_INSTALLMODE_INSTDIR}"
+ !endif
+ !endif
+ !endif
+
+ !ifdef MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY & MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME
+
+ ReadRegStr $MultiUser.InstDir HKLM "${MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME}"
+
+ ${if} $MultiUser.InstDir != ""
+ StrCpy $INSTDIR $MultiUser.InstDir
+ ${endif}
+
+ !endif
+
+ !ifdef MULTIUSER_INSTALLMODE_${UNINSTALLER_PREFIX}FUNCTION
+ Call "${MULTIUSER_INSTALLMODE_${UNINSTALLER_PREFIX}FUNCTION}"
+ !endif
+
+ ${endif}
+
+!macroend
+
+!macro MULTIUSER_INSTALLMODE_CURRENTUSER UNINSTALLER_PREFIX UNINSTALLER_FUNCPREFIX
+
+ ;Install mode initialization - per-user
+
+ !if ${MULTIUSER_MINWIN} < 0x500
+ ${if} ${IsNT}
+ !endif
+
+ StrCpy $MultiUser.InstallMode CurrentUser
+ SetShellVarContext current
+
+ !if "${UNINSTALLER_PREFIX}" != UN
+ ;Set default installation location for installer
+ !ifdef MULTIUSER_INSTALLMODE_INSTDIR
+ !if ${MULTIUSER_MINWIN} < 0x490
+ ${if} ${AtLeastWin2000}
+ !endif
+ GetKnownFolderPath $INSTDIR {5CD7AEE2-2219-4A67-B85D-6C9CE15660CB} ; FOLDERID_UserProgramFiles
+ StrCmp $INSTDIR "" 0 +2
+ StrCpy $INSTDIR "$LocalAppData\Programs" ; Fallback directory
+ StrCpy $INSTDIR "$INSTDIR\${MULTIUSER_INSTALLMODE_INSTDIR}"
+ !if ${MULTIUSER_MINWIN} < 0x490
+ ${else}
+ StrCpy $INSTDIR "$PROGRAMFILES\${MULTIUSER_INSTALLMODE_INSTDIR}"
+ ${endif}
+ !endif
+ !endif
+ !endif
+
+ !ifdef MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY & MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME
+ ReadRegStr $MultiUser.InstDir HKCU "${MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_INSTDIR_REGISTRY_VALUENAME}"
+ ${if} $MultiUser.InstDir != ""
+ StrCpy $INSTDIR $MultiUser.InstDir
+ ${endif}
+ !endif
+
+ !ifdef MULTIUSER_INSTALLMODE_${UNINSTALLER_PREFIX}FUNCTION
+ Call "${MULTIUSER_INSTALLMODE_${UNINSTALLER_PREFIX}FUNCTION}"
+ !endif
+
+ !if ${MULTIUSER_MINWIN} < 0x500
+ ${endif}
+ !endif
+
+!macroend
+
+Function MultiUser.InstallMode.AllUsers
+ !insertmacro MULTIUSER_INSTALLMODE_ALLUSERS "" ""
+FunctionEnd
+
+Function MultiUser.InstallMode.CurrentUser
+ !insertmacro MULTIUSER_INSTALLMODE_CURRENTUSER "" ""
+FunctionEnd
+
+!ifndef MULTIUSER_NOUNINSTALL
+
+Function un.MultiUser.InstallMode.AllUsers
+ !insertmacro MULTIUSER_INSTALLMODE_ALLUSERS UN .un
+FunctionEnd
+
+Function un.MultiUser.InstallMode.CurrentUser
+ !insertmacro MULTIUSER_INSTALLMODE_CURRENTUSER UN .un
+FunctionEnd
+
+!endif
+
+/*
+
+Installer/uninstaller initialization
+
+*/
+
+!macro MULTIUSER_INIT_QUIT UNINSTALLER_FUNCPREFIX
+
+ !ifdef MULTIUSER_INIT_${UNINSTALLER_FUNCPREFIX}FUNCTIONQUIT
+ Call "${MULTIUSER_INIT_${UNINSTALLER_FUNCPREFIX}FUNCTIONQUIT}"
+ !else
+ Quit
+ !endif
+
+!macroend
+
+!macro MULTIUSER_INIT_TEXTS UNINSTALLER_PREFIX
+
+ !if "${UNINSTALLER_PREFIX}" == ""
+ !define /ReDef MULTIUSER_TMPSTR_CAPTION "$(^SetupCaption)"
+ !else
+ !define /ReDef MULTIUSER_TMPSTR_CAPTION "$(^Name)"
+ !endif
+
+ !define /IfNDef MULTIUSER_INIT_TEXT_ADMINREQUIRED "${MULTIUSER_TMPSTR_CAPTION} requires administrator privileges."
+ !define /IfNDef MULTIUSER_INIT_TEXT_POWERREQUIRED "${MULTIUSER_TMPSTR_CAPTION} requires at least Power User privileges."
+ !define /IfNDef MULTIUSER_INIT_TEXT_ALLUSERSNOTPOSSIBLE "Your user account does not have sufficient privileges to install $(^Name) for all users of this computer."
+
+ !undef MULTIUSER_TMPSTR_CAPTION
+
+!macroend
+
+!macro MULTIUSER_INIT_CHECKS UNINSTALLER_PREFIX UNINSTALLER_FUNCPREFIX
+
+ ;Installer initialization - check privileges and set install mode
+
+ !insertmacro MULTIUSER_INIT_TEXTS "${UNINSTALLER_PREFIX}"
+
+ UserInfo::GetAccountType
+ Pop $MultiUser.Privileges
+
+ !if ${MULTIUSER_MINWIN} < 0x500
+ ${if} ${IsNT}
+ !endif
+
+ ;Check privileges
+
+ !if "${MULTIUSER_EXECUTIONLEVEL}" == Admin
+
+ ${if} $MultiUser.Privileges != "Admin"
+ MessageBox MB_OK|MB_ICONSTOP "${MULTIUSER_INIT_TEXT_ADMINREQUIRED}"
+ !insertmacro MULTIUSER_INIT_QUIT "${UNINSTALLER_FUNCPREFIX}"
+ ${endif}
+
+ !else if "${MULTIUSER_EXECUTIONLEVEL}" == Power
+
+ ${if} $MultiUser.Privileges != "Power"
+ ${andif} $MultiUser.Privileges != "Admin"
+ ${if} ${AtMostWinXP}
+ MessageBox MB_OK|MB_ICONSTOP "${MULTIUSER_INIT_TEXT_POWERREQUIRED}"
+ ${else}
+ MessageBox MB_OK|MB_ICONSTOP "${MULTIUSER_INIT_TEXT_ADMINREQUIRED}"
+ ${endif}
+ !insertmacro MULTIUSER_INIT_QUIT "${UNINSTALLER_FUNCPREFIX}"
+ ${endif}
+
+ !endif
+
+ !ifdef MULTIUSER_EXECUTIONLEVEL_ALLUSERS
+
+ ;Default to per-machine installation if possible
+
+ ${if} $MultiUser.Privileges == "Admin"
+ ${orif} $MultiUser.Privileges == "Power"
+ !ifndef MULTIUSER_INSTALLMODE_DEFAULT_CURRENTUSER
+ Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.AllUsers
+ !else
+ Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
+ !endif
+
+ !ifdef MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY & MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME
+
+ ;Set installation mode to setting from a previous installation
+
+ !ifndef MULTIUSER_INSTALLMODE_DEFAULT_CURRENTUSER
+ ReadRegStr $MultiUser.DefaultKeyValue HKLM "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME}"
+ ${if} $MultiUser.DefaultKeyValue == ""
+ ReadRegStr $MultiUser.DefaultKeyValue HKCU "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME}"
+ ${if} $MultiUser.DefaultKeyValue != ""
+ Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
+ ${endif}
+ ${endif}
+ !else
+ ReadRegStr $MultiUser.DefaultKeyValue HKCU "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME}"
+ ${if} $MultiUser.DefaultKeyValue == ""
+ ReadRegStr $MultiUser.DefaultKeyValue HKLM "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_KEY}" "${MULTIUSER_INSTALLMODE_DEFAULT_REGISTRY_VALUENAME}"
+ ${if} $MultiUser.DefaultKeyValue != ""
+ Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.AllUsers
+ ${endif}
+ ${endif}
+ !endif
+
+ !endif
+
+ ${else}
+ Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
+ ${endif}
+
+ !else
+
+ Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
+
+ !endif
+
+ !ifdef MULTIUSER_INSTALLMODE_COMMANDLINE
+
+ ;Check for install mode setting on command line
+
+ ${${UNINSTALLER_FUNCPREFIX}GetParameters} $MultiUser.Parameters
+
+ ${${UNINSTALLER_PREFIX}StrStr} $MultiUser.Result $MultiUser.Parameters "/CurrentUser"
+
+ ${if} $MultiUser.Result != ""
+ Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.CurrentUser
+ ${endif}
+
+ ${${UNINSTALLER_PREFIX}StrStr} $MultiUser.Result $MultiUser.Parameters "/AllUsers"
+
+ ${if} $MultiUser.Result != ""
+ ${if} $MultiUser.Privileges == "Admin"
+ ${orif} $MultiUser.Privileges == "Power"
+ Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.AllUsers
+ ${else}
+ MessageBox MB_OK|MB_ICONSTOP "${MULTIUSER_INIT_TEXT_ALLUSERSNOTPOSSIBLE}"
+ !insertmacro MULTIUSER_INIT_QUIT "${UNINSTALLER_FUNCPREFIX}"
+ ${endif}
+ ${endif}
+
+ !endif
+
+ !if ${MULTIUSER_MINWIN} < 0x500
+ ${else}
+
+ ;Not running Windows NT, per-user installation not supported
+ Call ${UNINSTALLER_FUNCPREFIX}MultiUser.InstallMode.AllUsers
+
+ ${endif}
+ !endif
+
+!macroend
+
+!macro MULTIUSER_INIT
+ !verbose push 3
+ !ifdef __UNINSTALL__
+ !insertmacro MULTIUSER_UNINIT
+ !else
+ !insertmacro MULTIUSER_INIT_CHECKS "" ""
+ !endif
+ !verbose pop
+!macroend
+
+!ifndef MULTIUSER_NOUNINSTALL
+!macro MULTIUSER_UNINIT
+ !verbose push 3
+ !insertmacro MULTIUSER_INIT_CHECKS Un un.
+ !verbose pop
+!macroend
+!endif
+
+/*
+
+Mode selection page
+
+*/
+
+!macro MULTIUSER_PAGE_FUNCTION_CUSTOM TYPE
+ !ifmacrodef MUI_PAGE_FUNCTION_CUSTOM
+ !insertmacro MUI_PAGE_FUNCTION_CUSTOM "${TYPE}"
+ !endif
+ !ifdef MULTIUSER_PAGE_CUSTOMFUNCTION_${TYPE}
+ Call "${MULTIUSER_PAGE_CUSTOMFUNCTION_${TYPE}}"
+ !undef MULTIUSER_PAGE_CUSTOMFUNCTION_${TYPE}
+ !endif
+!macroend
+
+!macro MULTIUSER_INSTALLMODEPAGE_INTERFACE
+
+ !ifndef MULTIUSER_INSTALLMODEPAGE_INTERFACE
+ !define MULTIUSER_INSTALLMODEPAGE_INTERFACE
+ Var MultiUser.InstallModePage
+
+ Var MultiUser.InstallModePage.Text
+
+ Var MultiUser.InstallModePage.AllUsers
+ Var MultiUser.InstallModePage.CurrentUser
+
+ !endif
+
+!macroend
+
+!macro MULTIUSER_PAGEDECLARATION_INSTALLMODE UNPREFIX UNIQUEID
+
+ !define /ReDef MULTIUSER_${UNPREFIX}INSTALLMODEPAGE "" ; Unlock strings in the language file(s)
+ !insertmacro MULTIUSER_INSTALLMODEPAGE_INTERFACE
+
+ !define /IfNDef MULTIUSER_INSTALLMODEPAGE_TEXT_TOP "$(MULTIUSER_INNERTEXT_INSTALLMODE_TOP)"
+ !define /IfNDef MULTIUSER_INSTALLMODEPAGE_TEXT_ALLUSERS "$(MULTIUSER_INNERTEXT_INSTALLMODE_ALLUSERS)"
+ !define /IfNDef MULTIUSER_INSTALLMODEPAGE_TEXT_CURRENTUSER "$(MULTIUSER_INNERTEXT_INSTALLMODE_CURRENTUSER)"
+
+ PageEx custom
+
+ PageCallbacks MultiUser.InstallModePre_${UNIQUEID} MultiUser.InstallModeLeave_${UNIQUEID}
+
+ !define /IfNDef MULTIUSER_INSTALLMODEPAGE_CAPTION " "
+ Caption "${MULTIUSER_INSTALLMODEPAGE_CAPTION}"
+
+ PageExEnd
+
+ !insertmacro MULTIUSER_FUNCTION_INSTALLMODEPAGE MultiUser.InstallModePre_${UNIQUEID} MultiUser.InstallModeLeave_${UNIQUEID}
+
+ !undef MULTIUSER_INSTALLMODEPAGE_TEXT_TOP
+ !undef MULTIUSER_INSTALLMODEPAGE_TEXT_ALLUSERS
+ !undef MULTIUSER_INSTALLMODEPAGE_TEXT_CURRENTUSER
+
+!macroend
+
+!macro MULTIUSER_PAGE_INSTALLMODE
+
+ !verbose push 3
+
+ !ifndef MULTIUSER_EXECUTIONLEVEL_ALLUSERS
+ !error "A mixed-mode installation requires MULTIUSER_EXECUTIONLEVEL to be set to Admin, Power or Highest."
+ !endif
+
+ !ifmacrodef MUI_PAGE_INIT
+ !insertmacro MUI_PAGE_INIT
+ !endif
+ !insertmacro MULTIUSER_PAGEDECLARATION_INSTALLMODE "" ${__COUNTER__}
+
+ !verbose pop
+
+!macroend
+
+!macro MULTIUSER_FUNCTION_INSTALLMODEPAGE PRE LEAVE
+
+ !include nsDialogs.nsh
+
+ Function "${PRE}"
+
+ !if ${MULTIUSER_MINWIN} < 0x500
+ ${ifnot} ${IsNT}
+ Abort
+ ${endif}
+ !endif
+
+ ${if} $MultiUser.Privileges != "Power"
+ ${andif} $MultiUser.Privileges != "Admin"
+ Abort
+ ${endif}
+
+ !insertmacro MULTIUSER_PAGE_FUNCTION_CUSTOM PRE
+ !ifmacrodef MUI_HEADER_TEXT_PAGE
+ !insertmacro MUI_HEADER_TEXT_PAGE $(MULTIUSER_TEXT_INSTALLMODE_TITLE) $(MULTIUSER_TEXT_INSTALLMODE_SUBTITLE)
+ !endif
+
+ nsDialogs::Create 1018
+ Pop $MultiUser.InstallModePage
+
+ ${NSD_CreateLabel} 0 2u 100% 42u "${MULTIUSER_INSTALLMODEPAGE_TEXT_TOP}"
+ Pop $MultiUser.InstallModePage.Text
+
+ ${NSD_CreateRadioButton} 15u 50u -15u 10u "${MULTIUSER_INSTALLMODEPAGE_TEXT_ALLUSERS}"
+ Pop $MultiUser.InstallModePage.AllUsers
+
+ !ifdef MULTIUSER_INSTALLMODEPAGE_SHOWUSERNAME
+ !ifdef NOSYSTEMCALLS
+ ReadEnvStr $0 USERNAME
+ !else
+ System::Call 'ADVAPI32::GetUserName(t""r0,*i${NSIS_MAX_STRLEN})'
+ !endif
+ StrCmp $0 "" +2
+ StrCpy $0 " ($0)"
+ ${NSD_CreateRadioButton} 15u 70u -15u 10u "${MULTIUSER_INSTALLMODEPAGE_TEXT_CURRENTUSER}$0"
+ !else
+ ${NSD_CreateRadioButton} 15u 70u -15u 10u "${MULTIUSER_INSTALLMODEPAGE_TEXT_CURRENTUSER}"
+ !endif
+ Pop $MultiUser.InstallModePage.CurrentUser
+
+ ${if} $MultiUser.InstallMode == "AllUsers"
+ SendMessage $MultiUser.InstallModePage.AllUsers ${BM_SETCHECK} ${BST_CHECKED} 0
+ ${else}
+ SendMessage $MultiUser.InstallModePage.CurrentUser ${BM_SETCHECK} ${BST_CHECKED} 0
+ ${endif}
+
+ !insertmacro MULTIUSER_PAGE_FUNCTION_CUSTOM SHOW
+ nsDialogs::Show
+ !insertmacro MULTIUSER_PAGE_FUNCTION_CUSTOM DESTROYED
+
+ FunctionEnd
+
+ Function "${LEAVE}"
+ SendMessage $MultiUser.InstallModePage.AllUsers ${BM_GETCHECK} 0 0 $0
+
+ ${if} $0 = ${BST_CHECKED}
+ Call MultiUser.InstallMode.AllUsers
+ ${else}
+ Call MultiUser.InstallMode.CurrentUser
+ ${endif}
+
+ !insertmacro MULTIUSER_PAGE_FUNCTION_CUSTOM LEAVE
+ FunctionEnd
+
+!macroend
+
+
+!verbose pop
+!endif
diff --git a/installer/tools/Include/Sections.nsh b/installer/tools/Include/Sections.nsh
new file mode 100644
index 00000000..7ae9f682
--- /dev/null
+++ b/installer/tools/Include/Sections.nsh
@@ -0,0 +1,310 @@
+; Sections.nsh
+;
+; Defines and macros for section control
+;
+; Include in your script using:
+; !include "Sections.nsh"
+
+;--------------------------------
+
+!ifndef SECTIONS_INCLUDED
+
+!define SECTIONS_INCLUDED
+
+;--------------------------------
+
+; Generic section defines
+
+# section or section group is selected
+!define SF_SELECTED 1
+# section group
+!define SF_SECGRP 2
+!define SF_SUBSEC 2 # deprecated
+# section group end marker
+!define SF_SECGRPEND 4
+!define SF_SUBSECEND 4 # deprecated
+# bold text (Section !blah)
+!define SF_BOLD 8
+# read only (SectionIn RO)
+!define SF_RO 16
+# expanded section group (SectionGroup /e blah)
+!define SF_EXPAND 32
+# section group is partially selected
+!define SF_PSELECTED 64 # internal
+# internal
+!define SF_TOGGLED 128 # internal
+!define SF_NAMECHG 256 # internal
+
+# mask to toggle off the selected flag
+!define SECTION_OFF 0xFFFFFFFE
+
+;--------------------------------
+
+; Select / unselect / reserve section
+
+!macro SelectSection SECTION
+
+ Push $0
+ Push $1
+ StrCpy $1 "${SECTION}"
+ SectionGetFlags $1 $0
+ IntOp $0 $0 | ${SF_SELECTED}
+ SectionSetFlags $1 $0
+ Pop $1
+ Pop $0
+
+!macroend
+
+!macro UnselectSection SECTION
+
+ Push $0
+ Push $1
+ StrCpy $1 "${SECTION}"
+ SectionGetFlags $1 $0
+ IntOp $0 $0 & ${SECTION_OFF}
+ SectionSetFlags $1 $0
+ Pop $1
+ Pop $0
+
+!macroend
+
+; If section selected, will unselect, if unselected, will select
+
+!macro ReverseSection SECTION
+
+ Push $0
+ Push $1
+ StrCpy $1 "${SECTION}"
+ SectionGetFlags $1 $0
+ IntOp $0 $0 ^ ${SF_SELECTED}
+ SectionSetFlags $1 $0
+ Pop $1
+ Pop $0
+
+!macroend
+
+;--------------------------------
+
+; Macros for mutually exclusive section selection
+; Written by Tim Gallagher
+;
+; See one-section.nsi for an example of usage
+
+; Starts the Radio Button Block
+; You should pass a variable that keeps the selected section
+; as the first parameter for this macro. This variable should
+; be initialized to the default section's index.
+;
+; As this macro uses $R0 and $R1 you can't use those two as the
+; variable which will keep the selected section.
+
+!macro StartRadioButtons var
+
+ !define StartRadioButtons_Var "${var}"
+
+ Push $R0
+
+ SectionGetFlags "${StartRadioButtons_Var}" $R0
+ IntOp $R0 $R0 & ${SECTION_OFF}
+ SectionSetFlags "${StartRadioButtons_Var}" $R0
+
+ Push $R1
+
+ StrCpy $R1 "${StartRadioButtons_Var}"
+
+!macroend
+
+; A radio button
+
+!macro RadioButton SECTION_NAME
+
+ SectionGetFlags ${SECTION_NAME} $R0
+ IntOp $R0 $R0 & ${SF_SELECTED}
+ IntCmp $R0 ${SF_SELECTED} 0 +2 +2
+ StrCpy "${StartRadioButtons_Var}" ${SECTION_NAME}
+
+!macroend
+
+; Ends the radio button block
+
+!macro EndRadioButtons
+
+ StrCmp $R1 "${StartRadioButtons_Var}" 0 +4 ; selection hasn't changed
+ SectionGetFlags "${StartRadioButtons_Var}" $R0
+ IntOp $R0 $R0 | ${SF_SELECTED}
+ SectionSetFlags "${StartRadioButtons_Var}" $R0
+
+ Pop $R1
+ Pop $R0
+
+ !undef StartRadioButtons_Var
+
+!macroend
+
+;--------------------------------
+
+; These are two macros you can use to set a Section in an InstType
+; or clear it from an InstType.
+;
+; Written by Robert Kehl
+;
+; For details, see https://nsis.sourceforge.io/wiki/SetSectionInInstType%2C_ClearSectionInInstType
+;
+; Use the defines below for the WANTED_INSTTYPE parameter.
+
+!define INSTTYPE_1 1
+!define INSTTYPE_2 2
+!define INSTTYPE_3 4
+!define INSTTYPE_4 8
+!define INSTTYPE_5 16
+!define INSTTYPE_6 32
+!define INSTTYPE_7 64
+!define INSTTYPE_8 128
+!define INSTTYPE_9 256
+!define INSTTYPE_10 512
+!define INSTTYPE_11 1024
+!define INSTTYPE_12 2048
+!define INSTTYPE_13 4096
+!define INSTTYPE_14 8192
+!define INSTTYPE_15 16384
+!define INSTTYPE_16 32768
+!define INSTTYPE_17 65536
+!define INSTTYPE_18 131072
+!define INSTTYPE_19 262144
+!define INSTTYPE_20 524288
+!define INSTTYPE_21 1048576
+!define INSTTYPE_22 2097152
+!define INSTTYPE_23 4194304
+!define INSTTYPE_24 8388608
+!define INSTTYPE_25 16777216
+!define INSTTYPE_26 33554432
+!define INSTTYPE_27 67108864
+!define INSTTYPE_28 134217728
+!define INSTTYPE_29 268435456
+!define INSTTYPE_30 536870912
+!define INSTTYPE_31 1073741824
+!define INSTTYPE_32 2147483648
+
+!macro SetSectionInInstType SECTION_NAME WANTED_INSTTYPE
+
+ Push $0
+ Push $1
+ StrCpy $1 "${SECTION_NAME}"
+ SectionGetInstTypes $1 $0
+ IntOp $0 $0 | ${WANTED_INSTTYPE}
+ SectionSetInstTypes $1 $0
+ Pop $1
+ Pop $0
+
+!macroend
+
+!macro ClearSectionInInstType SECTION_NAME WANTED_INSTTYPE
+
+ Push $0
+ Push $1
+ Push $2
+ StrCpy $2 "${SECTION_NAME}"
+ SectionGetInstTypes $2 $0
+ StrCpy $1 ${WANTED_INSTTYPE}
+ IntOp $1 $1 ~
+ IntOp $0 $0 & $1
+ SectionSetInstTypes $2 $0
+ Pop $2
+ Pop $1
+ Pop $0
+
+!macroend
+
+;--------------------------------
+
+; Set / clear / check bits in a section's flags
+; Written by derekrprice
+
+; Set one or more bits in a sections's flags
+
+!macro SetSectionFlag SECTION BITS
+
+ Push $R0
+ Push $R1
+ StrCpy $R1 "${SECTION}"
+ SectionGetFlags $R1 $R0
+ IntOp $R0 $R0 | "${BITS}"
+ SectionSetFlags $R1 $R0
+ Pop $R1
+ Pop $R0
+
+!macroend
+
+; Clear one or more bits in section's flags
+
+!macro ClearSectionFlag SECTION BITS
+
+ Push $R0
+ Push $R1
+ Push $R2
+ StrCpy $R2 "${SECTION}"
+ SectionGetFlags $R2 $R0
+ IntOp $R1 "${BITS}" ~
+ IntOp $R0 $R0 & $R1
+ SectionSetFlags $R2 $R0
+ Pop $R2
+ Pop $R1
+ Pop $R0
+
+!macroend
+
+; Check if one or more bits in section's flags are set
+; If they are, jump to JUMPIFSET
+; If not, jump to JUMPIFNOTSET
+
+!macro SectionFlagIsSet SECTION BITS JUMPIFSET JUMPIFNOTSET
+ Push $R0
+ SectionGetFlags "${SECTION}" $R0
+ IntOp $R0 $R0 & "${BITS}"
+ IntCmp $R0 "${BITS}" +3
+ Pop $R0
+ StrCmp "" "${JUMPIFNOTSET}" +3 "${JUMPIFNOTSET}"
+ Pop $R0
+ Goto "${JUMPIFSET}"
+!macroend
+
+;--------------------------------
+
+; Removes a section by unselecting and hiding it
+
+!macro RemoveSection SECTION
+
+ Push $R0
+ Push $R1
+ StrCpy $R1 `${SECTION}`
+ SectionGetFlags $R1 $R0
+ IntOp $R0 $R0 & ${SECTION_OFF}
+ SectionSetFlags $R1 $R0
+ SectionSetText $R1 ``
+ Pop $R1
+ Pop $R0
+
+!macroend
+
+; Undoes the RemoveSection action
+
+!macro UnremoveSection SECTION SECTION_TEXT
+
+ Push $R0
+ Push $R1
+ Push $R2
+ StrCpy $R1 `${SECTION}`
+ StrCpy $R2 `${SECTION_TEXT}`
+ SectionGetFlags $R1 $R0
+ IntOp $R0 $R0 | ${SF_SELECTED}
+ SectionSetFlags $R1 $R0
+ SectionSetText $R1 $R2
+ Pop $R2
+ Pop $R1
+ Pop $R0
+
+!macroend
+
+;--------------------------------
+
+!endif
\ No newline at end of file
diff --git a/installer/tools/Include/StrFunc.nsh b/installer/tools/Include/StrFunc.nsh
new file mode 100644
index 00000000..b0448c0c
--- /dev/null
+++ b/installer/tools/Include/StrFunc.nsh
@@ -0,0 +1,1627 @@
+/*
+o-----------------------------------------------------------------------------o
+|String Functions Header File 1.10 |
+(-----------------------------------------------------------------------------)
+| By deguix / A Header file for NSIS 2.01 |
+| -------------------------------|
+| |
+| This header file contains NSIS functions for string manipulation. |
+| ---------|
+| !include "StrFunc.nsh" / Example |
+| ${Using:StrFunc} StrRep -----------|
+| |
+| Section |
+| ${StrRep} $0 "Hello world!" "world" "everyone" |
+| MessageBox mb_ok $0 |
+| SectionEnd |
+| |
+o-----------------------------------------------------------------------------o
+*/
+
+!verbose push 3
+!define /IfNDef STRFUNC_VERBOSITY 3
+!define /IfNDef _STRFUNC_VERBOSITY ${STRFUNC_VERBOSITY}
+!define /IfNDef _STRFUNC_CREDITVERBOSITY ${STRFUNC_VERBOSITY}
+!undef STRFUNC_VERBOSITY
+!verbose ${_STRFUNC_VERBOSITY}
+
+!include LogicLib.nsh
+
+!ifndef STRFUNC
+
+ !define /IfNDef FALSE 0
+ !define /IfNDef TRUE 1
+
+ ;Header File Identification
+
+ !define STRFUNC `String Functions Header File`
+ ;define STRFUNC_SHORT `StrFunc`
+ !define STRFUNC_CREDITS `2004 Diego Pedroso`
+
+ ;Header File Version
+
+ !define STRFUNC_VERMAJ 1
+ !define STRFUNC_VERMED 10
+ ;!define STRFUNC_VERMIN 0
+ ;!define STRFUNC_VERBLD 0
+
+ !define STRFUNC_VER `${STRFUNC_VERMAJ}.${STRFUNC_VERMED}`
+
+ ;Header File Init Message Prefix and Postfix
+
+ !define STRFUNC_INITMSGPRE `----------------------------------------------------------------------$\r$\n`
+ !define STRFUNC_INITMSGPOST `$\r$\n----------------------------------------------------------------------$\r$\n`
+
+ ;Header File Init Message
+
+ !verbose push ${_STRFUNC_CREDITVERBOSITY}
+ !echo `${STRFUNC_INITMSGPRE}NSIS ${STRFUNC} ${STRFUNC_VER} - Copyright ${STRFUNC_CREDITS}${STRFUNC_INITMSGPOST}`
+ !verbose pop
+
+ ;Header File Function Macros
+
+ !ifdef STRFUNC_USECALLARTIFICIALFUNCTION
+ !include Util.nsh
+ !endif
+
+ !define "Using:StrFunc" `!insertmacro STRFUNC_USING `
+ !macro STRFUNC_USING Name
+ !if "${STRFUNC_VERBOSITY}" > 4
+ !verbose push 4
+ !endif
+ !ifndef ${Name}_INCLUDED
+ !ifndef STRFUNC_USECALLARTIFICIALFUNCTION
+ ${${Name}} ; Invoke !insertmacro STRFUNC_MAKEFUNC
+ !endif
+ !endif
+ !if "${STRFUNC_VERBOSITY}" > 4
+ !verbose pop
+ !endif
+ !macroend
+
+ !macro STRFUNC_FUNCLIST_INSERT Name
+ !ifdef StrFunc_List
+ !define /ReDef StrFunc_List `${StrFunc_List}|${Name}`
+ !else
+ !define StrFunc_List `${Name}`
+ !endif
+ !macroend
+
+ !macro STRFUNC_DEFFUNC Name List TypeList
+ !insertmacro STRFUNC_FUNCLIST_INSERT ${Name}
+ !define `${Name}_List` `${List}`
+ !define `${Name}_TypeList` `${TypeList}`
+ !ifdef STRFUNC_USECALLARTIFICIALFUNCTION
+ !define `${Name}` `!insertmacro STRFUNC_CALL_${Name} "" `
+ !define `Un${Name}` `!insertmacro STRFUNC_CALL_${Name} Un `
+ !else
+ !define `${Name}` `!insertmacro STRFUNC_MAKEFUNC ${Name} "" #`
+ !define `Un${Name}` `!insertmacro STRFUNC_MAKEFUNC ${Name} Un #`
+ !endif
+ !macroend
+
+ !macro STRFUNC_MAKEFUNC basename un
+ !ifndef __GLOBAL__
+ !error "You forgot ${U+24}{Using:StrFunc} ${un}${basename}"
+ !endif
+ !insertmacro STRFUNC_MAKEFUNC_${basename}
+ !macroend
+
+ !macro STRFUNC_BEGINFUNC basename un credits
+ !verbose push ${_STRFUNC_CREDITVERBOSITY}
+ !echo `${U+24}{${un}${basename}} - Copyright ${credits}`
+ !verbose pop
+ !define /IfNDef ${un}${basename}_INCLUDED
+ !ifndef STRFUNC_USECALLARTIFICIALFUNCTION
+ !define /ReDef ${un}${basename} `!insertmacro STRFUNC_CALL_${basename} "${un}" `
+ !if "${un}" != ""
+ Function un.${basename}
+ !else
+ Function ${basename}
+ !endif
+ !endif
+ !macroend
+ !macro STRFUNC_ENDFUNC
+ !ifndef STRFUNC_USECALLARTIFICIALFUNCTION
+ FunctionEnd
+ !endif
+ !macroend
+
+ !macro STRFUNC_CALL basename un
+ !ifdef STRFUNC_USECALLARTIFICIALFUNCTION
+ ${CallArtificialFunction} STRFUNC_MAKEFUNC_${basename}
+ !else
+ !if "${un}" != ""
+ Call un.${basename}
+ !else
+ Call ${basename}
+ !endif
+ !endif
+ !macroend
+
+
+ ############################################################################
+ # StrCase
+ !insertmacro STRFUNC_DEFFUNC StrCase `ResultVar|String|Type` `Output|Text|Option U L T S <>`
+
+ !macro STRFUNC_CALL_StrCase un ResultVar String Type
+ !verbose push ${STRFUNC_VERBOSITY}
+ !echo `${U+24}{${un}StrCase} "${ResultVar}" "${String}" "${Type}"`
+ !verbose 2
+ Push `${String}`
+ Push `${Type}`
+ !insertmacro STRFUNC_CALL StrCase "${un}"
+ Pop ${ResultVar}
+ !verbose pop
+ !macroend
+
+ !macro STRFUNC_MAKEFUNC_StrCase
+ !insertmacro STRFUNC_BEGINFUNC ${basename} `${un}` `2004 Diego Pedroso - Based on functions by Dave Laundon`
+ /*After this point:
+ ------------------------------------------
+ $0 = String (input)
+ $1 = Type (input)
+ $2 = StrLength (temp)
+ $3 = StartChar (temp)
+ $4 = EndChar (temp)
+ $5 = ResultStr (temp)
+ $6 = CurrentChar (temp)
+ $7 = LastChar (temp)
+ $8 = Temp (temp)*/
+
+ ;Get input from user
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $8
+
+ ;Initialize variables
+ StrCpy $2 ""
+ StrCpy $3 ""
+ StrCpy $4 ""
+ StrCpy $5 ""
+ StrCpy $6 ""
+ StrCpy $7 ""
+ StrCpy $8 ""
+
+ ;Upper and lower cases are simple to use
+ ${If} $1 == "U"
+
+ ;Upper Case System:
+ ;------------------
+ ; Convert all characters to upper case.
+
+ System::Call "User32::CharUpper(t r0 r5)i"
+ Goto StrCase_End
+ ${ElseIf} $1 == "L"
+
+ ;Lower Case System:
+ ;------------------
+ ; Convert all characters to lower case.
+
+ System::Call "User32::CharLower(t r0 r5)i"
+ Goto StrCase_End
+ ${EndIf}
+
+ ;For the rest of cases:
+ ;Get "String" length
+ StrLen $2 $0
+
+ ;Make a loop until the end of "String"
+ ${For} $3 0 $2
+ ;Add 1 to "EndChar" counter also
+ IntOp $4 $3 + 1
+
+ # Step 1: Detect one character at a time
+
+ ;Remove characters before "StartChar" except when
+ ;"StartChar" is the first character of "String"
+ ${If} $3 <> 0
+ StrCpy $6 $0 `` $3
+ ${EndIf}
+
+ ;Remove characters after "EndChar" except when
+ ;"EndChar" is the last character of "String"
+ ${If} $4 <> $2
+ ${If} $3 = 0
+ StrCpy $6 $0 1
+ ${Else}
+ StrCpy $6 $6 1
+ ${EndIf}
+ ${EndIf}
+
+ # Step 2: Convert to the advanced case user chose:
+
+ ${If} $1 == "T"
+
+ ;Title Case System:
+ ;------------------
+ ; Convert all characters after a non-alphabetic character to upper case.
+ ; Else convert to lower case.
+
+ ;Use "IsCharAlpha" for the job
+ System::Call "*(&t1 r7) p .r8"
+ System::Call "*$8(&i1 .r7)"
+ System::Free $8
+ System::Call "user32::IsCharAlpha(i r7) i .r8"
+
+ ;Verify "IsCharAlpha" result and convert the character
+ ${If} $8 = 0
+ System::Call "User32::CharUpper(t r6 r6)i"
+ ${Else}
+ System::Call "User32::CharLower(t r6 r6)i"
+ ${EndIf}
+ ${ElseIf} $1 == "S"
+
+ ;Sentence Case System:
+ ;------------------
+ ; Convert all characters after a ".", "!" or "?" character to upper case.
+ ; Else convert to lower case. Spaces or tabs after these marks are ignored.
+
+ ;Detect current characters and ignore if necessary
+ ${If} $6 == " "
+ ${OrIf} $6 == "$\t"
+ Goto IgnoreLetter
+ ${EndIf}
+
+ ;Detect last characters and convert
+ ${If} $7 == "."
+ ${OrIf} $7 == "!"
+ ${OrIf} $7 == "?"
+ ${OrIf} $7 == ""
+ System::Call "User32::CharUpper(t r6 r6)i"
+ ${Else}
+ System::Call "User32::CharLower(t r6 r6)i"
+ ${EndIf}
+ ${ElseIf} $1 == "<>"
+
+ ;Switch Case System:
+ ;------------------
+ ; Switch all characters cases to their inverse case.
+
+ ;Use "IsCharUpper" for the job
+ System::Call "*(&t1 r6) p .r8"
+ System::Call "*$8(&i1 .r7)"
+ System::Free $8
+ System::Call "user32::IsCharUpper(i r7) i .r8"
+
+ ;Verify "IsCharUpper" result and convert the character
+ ${If} $8 = 0
+ System::Call "User32::CharUpper(t r6 r6)i"
+ ${Else}
+ System::Call "User32::CharLower(t r6 r6)i"
+ ${EndIf}
+ ${EndIf}
+
+ ;Write the character to "LastChar"
+ StrCpy $7 $6
+
+ IgnoreLetter:
+ ;Add this character to "ResultStr"
+ StrCpy $5 `$5$6`
+ ${Next}
+
+ StrCase_End:
+
+ /*After this point:
+ ------------------------------------------
+ $0 = OutVar (output)*/
+
+ ; Copy "ResultStr" to "OutVar"
+ StrCpy $0 $5
+
+ ;Return output to user
+ Pop $8
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+ !insertmacro STRFUNC_ENDFUNC
+
+ !macroend
+
+ ############################################################################
+ # StrClb
+ !insertmacro STRFUNC_DEFFUNC StrClb `ResultVar|String|Action` `Output|Text|Option > < <>`
+
+ !macro STRFUNC_CALL_StrClb un ResultVar String Action
+ !verbose push ${STRFUNC_VERBOSITY}
+ !echo `${U+24}{${un}StrClb} "${ResultVar}" "${String}" "${Action}"`
+ !verbose 2
+ Push `${String}`
+ Push `${Action}`
+ !insertmacro STRFUNC_CALL StrClb "${un}"
+ Pop ${ResultVar}
+ !verbose pop
+ !macroend
+
+ !macro STRFUNC_MAKEFUNC_StrClb
+ !insertmacro STRFUNC_BEGINFUNC ${basename} `${un}` `2004 Diego Pedroso - Based on functions by Nik Medved`
+
+ /*After this point:
+ ------------------------------------------
+ $0 = String (input)
+ $1 = Action (input)
+ $2 = Lock/Unlock (temp)
+ $3 = Temp (temp)
+ $4 = Temp2 (temp)*/
+
+ ;Get input from user
+
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $2
+ Push $3
+ Push $4
+
+ StrCpy $2 ""
+ StrCpy $3 ""
+ StrCpy $4 ""
+
+ ;Open the clipboard to do the operations the user chose (kichik's fix)
+ System::Call 'user32::OpenClipboard(p $HWNDPARENT)'
+
+ ${If} $1 == ">" ;Set
+
+ ;Step 1: Clear the clipboard
+ System::Call 'user32::EmptyClipboard()'
+
+ ;Step 2: Allocate global heap
+ StrLen $2 $0
+ IntOp $2 $2 + 1
+ !if "${NSIS_CHAR_SIZE}" > 1
+ IntOp $2 $2 * ${NSIS_CHAR_SIZE}
+ !endif
+ System::Call 'kernel32::GlobalAlloc(i 2, i r2) p.r2'
+
+ ;Step 3: Lock the handle
+ System::Call 'kernel32::GlobalLock(p r2) i.r3'
+
+ ;Step 4: Copy the text to locked clipboard buffer
+ System::Call 'kernel32::lstrcpy(p r3, t r0)'
+
+ ;Step 5: Unlock the handle again
+ System::Call 'kernel32::GlobalUnlock(p r2)'
+
+ ;Step 6: Set the information to the clipboard
+ !if "${NSIS_CHAR_SIZE}" > 1
+ System::Call 'user32::SetClipboardData(i 13, p r2)'
+ !else
+ System::Call 'user32::SetClipboardData(i 1, p r2)'
+ !endif
+
+ StrCpy $0 ""
+
+ ${ElseIf} $1 == "<" ;Get
+
+ ;Step 1: Get clipboard data
+ !if "${NSIS_CHAR_SIZE}" > 1
+ System::Call 'user32::GetClipboardData(i 13)p.r2'
+ !else
+ System::Call 'user32::GetClipboardData(i 1)p.r2'
+ !endif
+
+ ;Step 2: Lock and copy data (kichik's fix)
+ System::Call 'kernel32::GlobalLock(p r2) t .r0'
+
+ ;Step 3: Unlock (kichik's fix)
+ System::Call 'kernel32::GlobalUnlock(p r2)'
+
+ ${ElseIf} $1 == "<>" ;Swap
+
+ ;Step 1: Get clipboard data
+ !if "${NSIS_CHAR_SIZE}" > 1
+ System::Call 'user32::GetClipboardData(i 13)p.r2'
+ !else
+ System::Call 'user32::GetClipboardData(i 1)p.r2'
+ !endif
+
+ ;Step 2: Lock and copy data (kichik's fix)
+ System::Call 'kernel32::GlobalLock(p r2) t .r4'
+
+ ;Step 3: Unlock (kichik's fix)
+ System::Call 'kernel32::GlobalUnlock(p r2)'
+
+ ;Step 4: Clear the clipboard
+ System::Call 'user32::EmptyClipboard()'
+
+ ;Step 5: Allocate global heap
+ StrLen $2 $0
+ IntOp $2 $2 + 1
+ !if "${NSIS_CHAR_SIZE}" > 1
+ IntOp $2 $2 * ${NSIS_CHAR_SIZE}
+ !endif
+ System::Call 'kernel32::GlobalAlloc(i 2, i r2) p.r2'
+
+ ;Step 6: Lock the handle
+ System::Call 'kernel32::GlobalLock(p r2) i.r3'
+
+ ;Step 7: Copy the text to locked clipboard buffer
+ System::Call 'kernel32::lstrcpy(p r3, t r0)'
+
+ ;Step 8: Unlock the handle again
+ System::Call 'kernel32::GlobalUnlock(p r2)'
+
+ ;Step 9: Set the information to the clipboard
+ !if "${NSIS_CHAR_SIZE}" > 1
+ System::Call 'user32::SetClipboardData(i 13, p r2)'
+ !else
+ System::Call 'user32::SetClipboardData(i 1, p r2)'
+ !endif
+
+ StrCpy $0 $4
+ ${Else} ;Clear
+
+ ;Step 1: Clear the clipboard
+ System::Call 'user32::EmptyClipboard()'
+
+ StrCpy $0 ""
+ ${EndIf}
+
+ ;Close the clipboard
+ System::Call 'user32::CloseClipboard()'
+
+ /*After this point:
+ ------------------------------------------
+ $0 = OutVar (output)*/
+
+ ;Return result to user
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+ !insertmacro STRFUNC_ENDFUNC
+
+ !macroend
+
+ ############################################################################
+ # StrIOToNSIS
+ !insertmacro STRFUNC_DEFFUNC StrIOToNSIS `ResultVar|String` `Output|Text`
+
+ !macro STRFUNC_CALL_StrIOToNSIS un ResultVar String
+ !verbose push ${STRFUNC_VERBOSITY}
+ !echo `${U+24}{${un}StrIOToNSIS} "${ResultVar}" "${String}"`
+ !verbose 2
+ Push `${String}`
+ !insertmacro STRFUNC_CALL StrIOToNSIS "${un}"
+ Pop ${ResultVar}
+ !verbose pop
+ !macroend
+
+ !macro STRFUNC_MAKEFUNC_StrIOToNSIS
+ !insertmacro STRFUNC_BEGINFUNC ${basename} `${un}` `2004 "bluenet" - Based on functions by Amir Szekely, Joost Verburg, Dave Laundon and Diego Pedroso`
+
+ /*After this point:
+ ------------------------------------------
+ $R0 = String (input/output)
+ $R1 = StartCharPos (temp)
+ $R2 = StrLen (temp)
+ $R3 = TempStr (temp)
+ $R4 = TempRepStr (temp)*/
+
+ ;Get input from user
+ Exch $R0
+ Push $R1
+ Push $R2
+ Push $R3
+ Push $R4
+
+ ;Get "String" length
+ StrLen $R2 $R0
+
+ ;Loop until "String" end is reached
+ ${For} $R1 0 $R2
+ ;Get the next "String" characters
+ StrCpy $R3 $R0 2 $R1
+
+ ;Detect if current character is:
+ ${If} $R3 == "\\" ;Back-slash
+ StrCpy $R4 "\"
+ ${ElseIf} $R3 == "\r" ;Carriage return
+ StrCpy $R4 "$\r"
+ ${ElseIf} $R3 == "\n" ;Line feed
+ StrCpy $R4 "$\n"
+ ${ElseIf} $R3 == "\t" ;Tab
+ StrCpy $R4 "$\t"
+ ${Else} ;Anything else
+ StrCpy $R4 ""
+ ${EndIf}
+
+ ;Detect if "TempRepStr" is not empty
+ ${If} $R4 != ""
+ ;Replace the old characters with the new one
+ StrCpy $R3 $R0 $R1
+ IntOp $R1 $R1 + 2
+ StrCpy $R0 $R0 "" $R1
+ StrCpy $R0 "$R3$R4$R0"
+ IntOp $R2 $R2 - 1 ;Decrease "StrLen"
+ IntOp $R1 $R1 - 2 ;Go back to the next character
+ ${EndIf}
+ ${Next}
+ Pop $R4
+ Pop $R3
+ Pop $R2
+ Pop $R1
+ Exch $R0
+ !insertmacro STRFUNC_ENDFUNC
+ !macroend
+
+ ############################################################################
+ # StrLoc
+ !insertmacro STRFUNC_DEFFUNC StrLoc `ResultVar|String|StrToSearchFor|CounterDirection` `Output|Text|Text|Option > <`
+
+ !macro STRFUNC_CALL_StrLoc un ResultVar String StrToSearchFor OffsetDirection
+ !verbose push ${STRFUNC_VERBOSITY}
+ !echo `${U+24}{${un}StrLoc} "${ResultVar}" "${String}" "${StrToSearchFor}" "${OffsetDirection}"`
+ !verbose 2
+ Push `${String}`
+ Push `${StrToSearchFor}`
+ Push `${OffsetDirection}`
+ !insertmacro STRFUNC_CALL StrLoc "${un}"
+ Pop ${ResultVar}
+ !verbose pop
+ !macroend
+
+ !macro STRFUNC_MAKEFUNC_StrLoc
+ !insertmacro STRFUNC_BEGINFUNC ${basename} `${un}` `2004 Diego Pedroso - Based on functions by Ximon Eighteen`
+
+ /*After this point:
+ ------------------------------------------
+ $R0 = OffsetDirection (input)
+ $R1 = StrToSearch (input)
+ $R2 = String (input)
+ $R3 = StrToSearchLen (temp)
+ $R4 = StrLen (temp)
+ $R5 = StartCharPos (temp)
+ $R6 = TempStr (temp)*/
+
+ ;Get input from user
+ Exch $R0
+ Exch
+ Exch $R1
+ Exch 2
+ Exch $R2
+ Push $R3
+ Push $R4
+ Push $R5
+ Push $R6
+
+ ;Get "String" and "StrToSearch" length
+ StrLen $R3 $R1
+ StrLen $R4 $R2
+ ;Start "StartCharPos" counter
+ StrCpy $R5 0
+
+ ;Loop until "StrToSearch" is found or "String" reaches its end
+ ${Do}
+ ;Remove everything before and after the searched part ("TempStr")
+ StrCpy $R6 $R2 $R3 $R5
+
+ ;Compare "TempStr" with "StrToSearch"
+ ${If} $R6 == $R1
+ ${If} $R0 == `<`
+ IntOp $R6 $R3 + $R5
+ IntOp $R0 $R4 - $R6
+ ${Else}
+ StrCpy $R0 $R5
+ ${EndIf}
+ ${ExitDo}
+ ${EndIf}
+ ;If not "StrToSearch", this could be "String" end
+ ${If} $R5 >= $R4
+ StrCpy $R0 ``
+ ${ExitDo}
+ ${EndIf}
+ ;If not, continue the loop
+ IntOp $R5 $R5 + 1
+ ${Loop}
+
+ ;Return output to user
+ Pop $R6
+ Pop $R5
+ Pop $R4
+ Pop $R3
+ Pop $R2
+ Exch
+ Pop $R1
+ Exch $R0
+ !insertmacro STRFUNC_ENDFUNC
+
+ !macroend
+
+ ############################################################################
+ # StrNSISToIO
+ !insertmacro STRFUNC_DEFFUNC StrNSISToIO `ResultVar|String` `Output|Text`
+
+ !macro STRFUNC_CALL_StrNSISToIO un ResultVar String
+ !verbose push ${STRFUNC_VERBOSITY}
+ !echo `${U+24}{${un}StrNSISToIO} "${ResultVar}" "${String}"`
+ !verbose 2
+ Push `${String}`
+ !insertmacro STRFUNC_CALL StrNSISToIO "${un}"
+ Pop ${ResultVar}
+ !verbose pop
+ !macroend
+
+ !macro STRFUNC_MAKEFUNC_StrNSISToIO
+ !insertmacro STRFUNC_BEGINFUNC ${basename} `${un}` `2004 "bluenet" - Based on functions by Amir Szekely, Joost Verburg, Dave Laundon and Diego Pedroso`
+
+ /*After this point:
+ ------------------------------------------
+ $R0 = String (input/output)
+ $R1 = StartCharPos (temp)
+ $R2 = StrLen (temp)
+ $R3 = TempStr (temp)
+ $R4 = TempRepStr (temp)*/
+
+ ;Get input from user
+ Exch $R0
+ Push $R1
+ Push $R2
+ Push $R3
+ Push $R4
+
+ ;Get "String" length
+ StrLen $R2 $R0
+
+ ;Loop until "String" end is reached
+ ${For} $R1 0 $R2
+ ;Get the next "String" character
+ StrCpy $R3 $R0 1 $R1
+
+ ;Detect if current character is:
+ ${If} $R3 == "$\r" ;Back-slash
+ StrCpy $R4 "\r"
+ ${ElseIf} $R3 == "$\n" ;Carriage return
+ StrCpy $R4 "\n"
+ ${ElseIf} $R3 == "$\t" ;Line feed
+ StrCpy $R4 "\t"
+ ${ElseIf} $R3 == "\" ;Tab
+ StrCpy $R4 "\\"
+ ${Else} ;Anything else
+ StrCpy $R4 ""
+ ${EndIf}
+
+ ;Detect if "TempRepStr" is not empty
+ ${If} $R4 != ""
+ ;Replace the old character with the new ones
+ StrCpy $R3 $R0 $R1
+ IntOp $R1 $R1 + 1
+ StrCpy $R0 $R0 "" $R1
+ StrCpy $R0 "$R3$R4$R0"
+ IntOp $R2 $R2 + 1 ;Increase "StrLen"
+ ${EndIf}
+ ${Next}
+
+ ;Return output to user
+ Pop $R4
+ Pop $R3
+ Pop $R2
+ Pop $R1
+ Exch $R0
+ !insertmacro STRFUNC_ENDFUNC
+ !macroend
+
+ ############################################################################
+ # StrRep
+ !insertmacro STRFUNC_DEFFUNC StrRep `ResultVar|String|StrToReplace|ReplacementString` `Output|Text|Text|Text`
+
+ !macro STRFUNC_CALL_StrRep un ResultVar String StringToReplace ReplacementString
+ !verbose push ${STRFUNC_VERBOSITY}
+ !echo `${U+24}{${un}StrRep} "${ResultVar}" "${String}" "${StringToReplace}" "${ReplacementString}"`
+ !verbose 2
+ Push `${String}`
+ Push `${StringToReplace}`
+ Push `${ReplacementString}`
+ !insertmacro STRFUNC_CALL StrRep "${un}"
+ Pop ${ResultVar}
+ !verbose pop
+ !macroend
+
+ !macro STRFUNC_MAKEFUNC_StrRep
+ !insertmacro STRFUNC_BEGINFUNC ${basename} `${un}` `2004 Diego Pedroso - Based on functions by Hendri Adriaens`
+
+ /*After this point:
+ ------------------------------------------
+ $R0 = ReplacementString (input)
+ $R1 = StrToSearch (input)
+ $R2 = String (input)
+ $R3 = RepStrLen (temp)
+ $R4 = StrToSearchLen (temp)
+ $R5 = StrLen (temp)
+ $R6 = StartCharPos (temp)
+ $R7 = TempStrL (temp)
+ $R8 = TempStrR (temp)*/
+
+ ;Get input from user
+ Exch $R0
+ Exch
+ Exch $R1
+ Exch
+ Exch 2
+ Exch $R2
+ Push $R3
+ Push $R4
+ Push $R5
+ Push $R6
+ Push $R7
+ Push $R8
+
+ ;Return "String" if "StrToSearch" is ""
+ ${IfThen} $R1 == "" ${|} Goto Done ${|}
+
+ ;Get "ReplacementString", "String" and "StrToSearch" length
+ StrLen $R3 $R0
+ StrLen $R4 $R1
+ StrLen $R5 $R2
+ ;Start "StartCharPos" counter
+ StrCpy $R6 0
+
+ ;Loop until "StrToSearch" is found or "String" reaches its end
+ ${Do}
+ ;Remove everything before and after the searched part ("TempStrL")
+ StrCpy $R7 $R2 $R4 $R6
+
+ ;Compare "TempStrL" with "StrToSearch"
+ ${If} $R7 == $R1
+ ;Split "String" to replace the string wanted
+ StrCpy $R7 $R2 $R6 ;TempStrL
+
+ ;Calc: "StartCharPos" + "StrToSearchLen" = EndCharPos
+ IntOp $R8 $R6 + $R4
+
+ StrCpy $R8 $R2 "" $R8 ;TempStrR
+
+ ;Insert the new string between the two separated parts of "String"
+ StrCpy $R2 $R7$R0$R8
+ ;Now calculate the new "StrLen" and "StartCharPos"
+ StrLen $R5 $R2
+ IntOp $R6 $R6 + $R3
+ ${Continue}
+ ${EndIf}
+
+ ;If not "StrToSearch", this could be "String" end
+ ${IfThen} $R6 >= $R5 ${|} ${ExitDo} ${|}
+ ;If not, continue the loop
+ IntOp $R6 $R6 + 1
+ ${Loop}
+
+ Done:
+
+ /*After this point:
+ ------------------------------------------
+ $R0 = OutVar (output)*/
+
+ ;Return output to user
+ StrCpy $R0 $R2
+ Pop $R8
+ Pop $R7
+ Pop $R6
+ Pop $R5
+ Pop $R4
+ Pop $R3
+ Pop $R2
+ Pop $R1
+ Exch $R0
+ !insertmacro STRFUNC_ENDFUNC
+
+ !macroend
+
+ ############################################################################
+ # StrSort
+ !insertmacro STRFUNC_DEFFUNC StrSort `ResultVar|String|CenterStr|LeftStr|RightStr|IncludeLeftStr|IncludeCenterStr|IncludeRightStr` `Output|Text|Text|Text|Text|Option 1 0|Option 1 0|Option 1 0`
+
+ !macro STRFUNC_CALL_StrSort un ResultVar String CenterStr LeftStr RightStr IncludeCenterStr IncludeLeftStr IncludeRightStr
+ !verbose push ${STRFUNC_VERBOSITY}
+ !echo `${U+24}{${un}StrSort} "${ResultVar}" "${String}" "${CenterStr}" "${LeftStr}" "${RightStr}" "${IncludeCenterStr}" "${IncludeLeftStr}" "${IncludeRightStr}"`
+ !verbose 2
+ Push `${String}`
+ Push `${CenterStr}`
+ Push `${LeftStr}`
+ Push `${RightStr}`
+ Push `${IncludeCenterStr}`
+ Push `${IncludeLeftStr}`
+ Push `${IncludeRightStr}`
+ !insertmacro STRFUNC_CALL StrSort "${un}"
+ Pop ${ResultVar}
+ !verbose pop
+ !macroend
+
+ !macro STRFUNC_MAKEFUNC_StrSort
+ !insertmacro STRFUNC_BEGINFUNC ${basename} `${un}` `2004 Diego Pedroso - Based on functions by Stuart Welch`
+
+ /*After this point:
+ ------------------------------------------
+ $R0 = String (input)
+ $R1 = LeftStr (input)
+ $R2 = CenterStr (input)
+ $R3 = RightStr (input)
+ $R4 = IncludeLeftStr (input)
+ $R5 = IncludeCenterStr (input)
+ $R6 = IncludeRightStr (input)
+
+ $0 = StrLen (temp)
+ $1 = LeftStrLen (temp)
+ $2 = CenterStrLen (temp)
+ $3 = RightStrLen (temp)
+ $4 = StartPos (temp)
+ $5 = EndPos (temp)
+ $6 = StartCharPos (temp)
+ $7 = EndCharPos (temp)
+ $8 = TempStr (temp)*/
+
+ ;Get input from user
+ Exch $R6
+ Exch
+ Exch $R5
+ Exch
+ Exch 2
+ Exch $R4
+ Exch 2
+ Exch 3
+ Exch $R3
+ Exch 3
+ Exch 4
+ Exch $R2
+ Exch 4
+ Exch 5
+ Exch $R1
+ Exch 5
+ Exch 6
+ Exch $R0
+ Exch 6
+ Push $0
+ Push $1
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $8
+
+ ;Parameter defaults
+ ${IfThen} $R4 == `` ${|} StrCpy $R4 `1` ${|}
+ ${IfThen} $R5 == `` ${|} StrCpy $R5 `1` ${|}
+ ${IfThen} $R6 == `` ${|} StrCpy $R6 `1` ${|}
+
+ ;Get "String", "CenterStr", "LeftStr" and "RightStr" length
+ StrLen $0 $R0
+ StrLen $1 $R1
+ StrLen $2 $R2
+ StrLen $3 $R3
+ ;Start "StartCharPos" counter
+ StrCpy $6 0
+ ;Start "EndCharPos" counter based on "CenterStr" length
+ IntOp $7 $6 + $2
+
+ ;Loop until "CenterStr" is found or "String" reaches its end
+ ${Do}
+ ;Remove everything before and after the searched part ("TempStr")
+ StrCpy $8 $R0 $2 $6
+
+ ;Compare "TempStr" with "CenterStr"
+ ${IfThen} $8 == $R2 ${|} ${ExitDo} ${|}
+ ;If not, this could be "String" end
+ ${IfThen} $7 >= $0 ${|} Goto Done ${|}
+ ;If not, continue the loop
+ IntOp $6 $6 + 1
+ IntOp $7 $7 + 1
+ ${Loop}
+
+ # "CenterStr" was found
+
+ ;Remove "CenterStr" from "String" if the user wants
+ ${If} $R5 = ${FALSE}
+ StrCpy $8 $R0 $6
+ StrCpy $R0 $R0 `` $7
+ StrCpy $R0 $8$R0
+ ${EndIf}
+
+ ;"StartPos" and "EndPos" will record "CenterStr" coordinates for now
+ StrCpy $4 $6
+ StrCpy $5 $7
+ ;"StartCharPos" and "EndCharPos" should be before "CenterStr"
+ IntOp $6 $6 - $1
+ IntOp $7 $6 + $1
+
+ ;Loop until "LeftStr" is found or "String" reaches its start
+ ${Do}
+ ;Remove everything before and after the searched part ("TempStr")
+ StrCpy $8 $R0 $1 $6
+
+ ;If "LeftStr" is empty
+ ${If} $R1 == ``
+ StrCpy $6 0
+ StrCpy $7 0
+ ${ExitDo}
+ ${EndIf}
+
+ ;Compare "TempStr" with "LeftStr"
+ ${IfThen} $8 == $R1 ${|} ${ExitDo} ${|}
+ ;If not, this could be "String" start
+ ${IfThen} $6 <= 0 ${|} ${ExitDo} ${|}
+ ;If not, continue the loop
+ IntOp $6 $6 - 1
+ IntOp $7 $7 - 1
+ ${Loop}
+
+ # "LeftStr" is found or "String" start was reached
+
+ ;Remove "LeftStr" from "String" if the user wants
+ ${If} $R4 = ${FALSE}
+ IntOp $6 $6 + $1
+ ${EndIf}
+
+ ;Record "LeftStr" first character position on "TempStr" (temporarily)
+ StrCpy $8 $6
+
+ ;"StartCharPos" and "EndCharPos" should be after "CenterStr"
+ ${If} $R5 = ${FALSE}
+ StrCpy $6 $4
+ ${Else}
+ IntOp $6 $4 + $2
+ ${EndIf}
+ IntOp $7 $6 + $3
+
+ ;Record "LeftStr" first character position on "StartPos"
+ StrCpy $4 $8
+
+ ;Loop until "RightStr" is found or "String" reaches its end
+ ${Do}
+ ;Remove everything before and after the searched part ("TempStr")
+ StrCpy $8 $R0 $3 $6
+
+ ;If "RightStr" is empty
+ ${If} $R3 == ``
+ StrCpy $6 $0
+ StrCpy $7 $0
+ ${ExitDo}
+ ${EndIf}
+
+ ;Compare "TempStr" with "RightStr"
+ ${IfThen} $8 == $R3 ${|} ${ExitDo} ${|}
+ ;If not, this could be "String" end
+ ${IfThen} $7 >= $0 ${|} ${ExitDo} ${|}
+ ;If not, continue the loop
+ IntOp $6 $6 + 1
+ IntOp $7 $7 + 1
+ ${Loop}
+
+ ;Remove "RightStr" from "String" if the user wants
+ ${If} $R6 = ${FALSE}
+ IntOp $7 $7 - $3
+ ${EndIf}
+
+ ;Record "RightStr" last character position on "StartPos"
+ StrCpy $5 $7
+
+ ;As the positionment is relative...
+ IntOp $5 $5 - $4
+
+ ;Write the string and finish the job
+ StrCpy $R0 $R0 $5 $4
+ Goto +2
+
+ Done:
+ StrCpy $R0 ``
+
+ /*After this point:
+ ------------------------------------------
+ $R0 = OutVar (output)*/
+
+ ;Return output to user
+ Pop $8
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+ Pop $R6
+ Pop $R5
+ Pop $R4
+ Pop $R3
+ Pop $R2
+ Pop $R1
+ Exch $R0
+ !insertmacro STRFUNC_ENDFUNC
+
+ !macroend
+
+ ############################################################################
+ # StrStr
+ !insertmacro STRFUNC_DEFFUNC StrStr `ResultVar|String|StrToSearchFor` `Output|Text|Text`
+
+ !macro STRFUNC_CALL_StrStr un ResultVar String StrToSearchFor
+ !verbose push ${STRFUNC_VERBOSITY}
+ !echo `${U+24}{${un}StrStr} "${ResultVar}" "${String}" "${StrToSearchFor}"`
+ !verbose 2
+ Push `${String}`
+ Push `${StrToSearchFor}`
+ !insertmacro STRFUNC_CALL StrStr "${un}"
+ Pop ${ResultVar}
+ !verbose pop
+ !macroend
+
+ !macro STRFUNC_MAKEFUNC_StrStr
+ !insertmacro STRFUNC_BEGINFUNC ${basename} `${un}` `2004 Diego Pedroso - Based on functions by Ximon Eighteen`
+
+ /*After this point:
+ ------------------------------------------
+ $R0 = StrToSearch (input)
+ $R1 = String (input)
+ $R2 = StrToSearchLen (temp)
+ $R3 = StrLen (temp)
+ $R4 = StartCharPos (temp)
+ $R5 = TempStr (temp)*/
+
+ ;Get input from user
+ Exch $R0
+ Exch
+ Exch $R1
+ Push $R2
+ Push $R3
+ Push $R4
+ Push $R5
+
+ ;Get "String" and "StrToSearch" length
+ StrLen $R2 $R0
+ StrLen $R3 $R1
+ ;Start "StartCharPos" counter
+ StrCpy $R4 0
+
+ ;Loop until "StrToSearch" is found or "String" reaches its end
+ ${Do}
+ ;Remove everything before and after the searched part ("TempStr")
+ StrCpy $R5 $R1 $R2 $R4
+
+ ;Compare "TempStr" with "StrToSearch"
+ ${IfThen} $R5 == $R0 ${|} ${ExitDo} ${|}
+ ;If not "StrToSearch", this could be "String" end
+ ${IfThen} $R4 >= $R3 ${|} ${ExitDo} ${|}
+ ;If not, continue the loop
+ IntOp $R4 $R4 + 1
+ ${Loop}
+
+ /*After this point:
+ ------------------------------------------
+ $R0 = OutVar (output)*/
+
+ ;Remove part before "StrToSearch" on "String" (if there has one)
+ StrCpy $R0 $R1 `` $R4
+
+ ;Return output to user
+ Pop $R5
+ Pop $R4
+ Pop $R3
+ Pop $R2
+ Pop $R1
+ Exch $R0
+ !insertmacro STRFUNC_ENDFUNC
+
+ !macroend
+
+ ############################################################################
+ # StrStrAdv
+ !insertmacro STRFUNC_DEFFUNC StrStrAdv `ResultVar|String|StrToSearchFor|SearchDirection|ResultStrDirection|DisplayStrToSearch|Loops|CaseSensitive` `Output|Text|Text|Option > <|Option > <|Option 1 0|Text|Option 0 1`
+
+ !macro STRFUNC_CALL_StrStrAdv un ResultVar String StrToSearchFor SearchDirection ResultStrDirection DisplayStrToSearch Loops CaseSensitive
+ !verbose push ${STRFUNC_VERBOSITY}
+ !echo `${U+24}{${un}StrStrAdv} "${ResultVar}" "${String}" "${StrToSearchFor}" "${SearchDirection}" "${ResultStrDirection}" "${DisplayStrToSearch}" "${Loops}" "${CaseSensitive}"`
+ !verbose 2
+ Push `${String}`
+ Push `${StrToSearchFor}`
+ Push `${SearchDirection}`
+ Push `${ResultStrDirection}`
+ Push `${DisplayStrToSearch}`
+ Push `${Loops}`
+ Push `${CaseSensitive}`
+ !insertmacro STRFUNC_CALL StrStrAdv "${un}"
+ Pop ${ResultVar}
+ !verbose pop
+ !macroend
+
+ !macro STRFUNC_MAKEFUNC_StrStrAdv
+ !insertmacro STRFUNC_BEGINFUNC ${basename} `${un}` `2003-2004 Diego Pedroso`
+
+ /*After this point:
+ ------------------------------------------
+ $0 = String (input)
+ $1 = StringToSearch (input)
+ $2 = DirectionOfSearch (input)
+ $3 = DirectionOfReturn (input)
+ $4 = ShowStrToSearch (input)
+ $5 = NumLoops (input)
+ $6 = CaseSensitive (input)
+ $7 = StringLength (temp)
+ $8 = StrToSearchLength (temp)
+ $9 = CurrentLoop (temp)
+ $R0 = EndCharPos (temp)
+ $R1 = StartCharPos (temp)
+ $R2 = OutVar (output)
+ $R3 = Temp (temp)*/
+
+ ;Get input from user
+
+ Exch $6
+ Exch
+ Exch $5
+ Exch
+ Exch 2
+ Exch $4
+ Exch 2
+ Exch 3
+ Exch $3
+ Exch 3
+ Exch 4
+ Exch $2
+ Exch 4
+ Exch 5
+ Exch $1
+ Exch 5
+ Exch 6
+ Exch $0
+ Exch 6
+ Push $7
+ Push $8
+ Push $9
+ Push $R3
+ Push $R2
+ Push $R1
+ Push $R0
+
+ ; Clean $R0-$R3 variables
+ StrCpy $R0 ""
+ StrCpy $R1 ""
+ StrCpy $R2 ""
+ StrCpy $R3 ""
+
+ ; Verify if we have the correct values on the variables
+ ${If} $0 == ``
+ SetErrors ;AdvStrStr_StrToSearch not found
+ Goto AdvStrStr_End
+ ${EndIf}
+
+ ${If} $1 == ``
+ SetErrors ;No text to search
+ Goto AdvStrStr_End
+ ${EndIf}
+
+ ${If} $2 != <
+ StrCpy $2 >
+ ${EndIf}
+
+ ${If} $3 != <
+ StrCpy $3 >
+ ${EndIf}
+
+ ${If} $4 <> 0
+ StrCpy $4 1
+ ${EndIf}
+
+ ${If} $5 <= 0
+ StrCpy $5 0
+ ${EndIf}
+
+ ${If} $6 <> 1
+ StrCpy $6 0
+ ${EndIf}
+
+ ; Find "AdvStrStr_String" length
+ StrLen $7 $0
+
+ ; Then find "AdvStrStr_StrToSearch" length
+ StrLen $8 $1
+
+ ; Now set up basic variables
+
+ ${If} $2 == <
+ IntOp $R1 $7 - $8
+ StrCpy $R2 $7
+ ${Else}
+ StrCpy $R1 0
+ StrCpy $R2 $8
+ ${EndIf}
+
+ StrCpy $9 0 ; First loop
+
+ ;Let's begin the search
+
+ ${Do}
+ ; Step 1: If the starting or ending numbers are negative
+ ; or more than AdvStrStr_StringLen, we return
+ ; error
+
+ ${If} $R1 < 0
+ StrCpy $R1 ``
+ StrCpy $R2 ``
+ StrCpy $R3 ``
+ SetErrors ;AdvStrStr_StrToSearch not found
+ Goto AdvStrStr_End
+ ${ElseIf} $R2 > $7
+ StrCpy $R1 ``
+ StrCpy $R2 ``
+ StrCpy $R3 ``
+ SetErrors ;AdvStrStr_StrToSearch not found
+ Goto AdvStrStr_End
+ ${EndIf}
+
+ ; Step 2: Start the search depending on
+ ; AdvStrStr_DirectionOfSearch. Chop down not needed
+ ; characters.
+
+ ${If} $R1 <> 0
+ StrCpy $R3 $0 `` $R1
+ ${EndIf}
+
+ ${If} $R2 <> $7
+ ${If} $R1 = 0
+ StrCpy $R3 $0 $8
+ ${Else}
+ StrCpy $R3 $R3 $8
+ ${EndIf}
+ ${EndIf}
+
+ ; Step 3: Make sure that's the string we want
+
+ ; Case-Sensitive Support <- Use "AdvStrStr_Temp"
+ ; variable because it won't be used anymore
+
+ ${If} $6 == 1
+ System::Call `kernel32::lstrcmp(ts, ts) i.s` `$R3` `$1`
+ Pop $R3
+ ${If} $R3 = 0
+ StrCpy $R3 1 ; Continue
+ ${Else}
+ StrCpy $R3 0 ; Break
+ ${EndIf}
+ ${Else}
+ ${If} $R3 == $1
+ StrCpy $R3 1 ; Continue
+ ${Else}
+ StrCpy $R3 0 ; Break
+ ${EndIf}
+ ${EndIf}
+
+ ; After the comparasion, confirm that it is the
+ ; value we want.
+
+ ${If} $R3 = 1
+
+ ;We found it, return except if the user has set up to
+ ;search for another one:
+ ${If} $9 >= $5
+
+ ;Now, let's see if the user wants
+ ;AdvStrStr_StrToSearch to appear:
+ ${If} $4 == 0
+ ;Return depends on AdvStrStr_DirectionOfReturn
+ ${If} $3 == <
+ ; RTL
+ StrCpy $R0 $0 $R1
+ ${Else}
+ ; LTR
+ StrCpy $R0 $0 `` $R2
+ ${EndIf}
+ ${Break}
+ ${Else}
+ ;Return depends on AdvStrStr_DirectionOfReturn
+ ${If} $3 == <
+ ; RTL
+ StrCpy $R0 $0 $R2
+ ${Else}
+ ; LTR
+ StrCpy $R0 $0 `` $R1
+ ${EndIf}
+ ${Break}
+ ${EndIf}
+ ${Else}
+ ;If the user wants to have more loops, let's do it so!
+ IntOp $9 $9 + 1
+
+ ${If} $2 == <
+ IntOp $R1 $R1 - 1
+ IntOp $R2 $R2 - 1
+ ${Else}
+ IntOp $R1 $R1 + 1
+ IntOp $R2 $R2 + 1
+ ${EndIf}
+ ${EndIf}
+ ${Else}
+ ; Step 4: We didn't find it, so do steps 1 thru 3 again
+
+ ${If} $2 == <
+ IntOp $R1 $R1 - 1
+ IntOp $R2 $R2 - 1
+ ${Else}
+ IntOp $R1 $R1 + 1
+ IntOp $R2 $R2 + 1
+ ${EndIf}
+ ${EndIf}
+ ${Loop}
+
+ AdvStrStr_End:
+
+ ;Add 1 to AdvStrStr_EndCharPos to be supportable
+ ;by "StrCpy"
+
+ IntOp $R2 $R2 - 1
+
+ ;Return output to user
+
+ Exch $R0
+ Exch
+ Pop $R1
+ Exch
+ Pop $R2
+ Exch
+ Pop $R3
+ Exch
+ Pop $9
+ Exch
+ Pop $8
+ Exch
+ Pop $7
+ Exch
+ Pop $6
+ Exch
+ Pop $5
+ Exch
+ Pop $4
+ Exch
+ Pop $3
+ Exch
+ Pop $2
+ Exch
+ Pop $1
+ Exch
+ Pop $0
+
+ !insertmacro STRFUNC_ENDFUNC
+
+ !macroend
+
+ ############################################################################
+ # StrTok
+ !insertmacro STRFUNC_DEFFUNC StrTok `ResultVar|String|Separators|ResultPart|SkipEmptyParts` `Output|Text|Text|Mixed L|Option 1 0`
+
+ !macro STRFUNC_CALL_StrTok un ResultVar String Separators ResultPart SkipEmptyParts
+ !verbose push ${STRFUNC_VERBOSITY}
+ !echo `${U+24}{${un}StrTok} "${ResultVar}" "${String}" "${Separators}" "${ResultPart}" "${SkipEmptyParts}"`
+ !verbose 2
+ Push `${String}`
+ Push `${Separators}`
+ Push `${ResultPart}`
+ Push `${SkipEmptyParts}`
+ !insertmacro STRFUNC_CALL StrTok "${un}"
+ Pop ${ResultVar}
+ !verbose pop
+ !macroend
+
+ !macro STRFUNC_MAKEFUNC_StrTok
+ !insertmacro STRFUNC_BEGINFUNC ${basename} `${un}` `2004 Diego Pedroso - Based on functions by "bigmac666"`
+ /*After this point:
+ ------------------------------------------
+ $0 = SkipEmptyParts (input)
+ $1 = ResultPart (input)
+ $2 = Separators (input)
+ $3 = String (input)
+ $4 = StrToSearchLen (temp)
+ $5 = StrLen (temp)
+ $6 = StartCharPos (temp)
+ $7 = TempStr (temp)
+ $8 = CurrentLoop
+ $9 = CurrentSepChar
+ $R0 = CurrentSepCharNum
+ */
+
+ ;Get input from user
+ Exch $0
+ Exch
+ Exch $1
+ Exch
+ Exch 2
+ Exch $2
+ Exch 2
+ Exch 3
+ Exch $3
+ Exch 3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $8
+ Push $9
+ Push $R0
+
+ ;Parameter defaults
+ ${IfThen} $2 == `` ${|} StrCpy $2 `|` ${|}
+ ${IfThen} $1 == `` ${|} StrCpy $1 `L` ${|}
+ ${IfThen} $0 == `` ${|} StrCpy $0 `0` ${|}
+
+ ;Get "String" and "StrToSearch" length
+ StrLen $4 $2
+ StrLen $5 $3
+ ;Start "StartCharPos" and "ResultPart" counters
+ StrCpy $6 0
+ StrCpy $8 -1
+
+ ;Loop until "ResultPart" is met, "StrToSearch" is found or
+ ;"String" reaches its end
+ ResultPartLoop: ;"CurrentLoop" Loop
+
+ ;Increase "CurrentLoop" counter
+ IntOp $8 $8 + 1
+
+ StrSearchLoop:
+ ${Do} ;"String" Loop
+ ;Remove everything before and after the searched part ("TempStr")
+ StrCpy $7 $3 1 $6
+
+ ;Verify if it's the "String" end
+ ${If} $6 >= $5
+ ;If "CurrentLoop" is what the user wants, remove the part
+ ;after "TempStr" and itself and get out of here
+ ${If} $8 == $1
+ ${OrIf} $1 == `L`
+ StrCpy $3 $3 $6
+ ${Else} ;If not, empty "String" and get out of here
+ StrCpy $3 ``
+ ${EndIf}
+ StrCpy $R0 `End`
+ ${ExitDo}
+ ${EndIf}
+
+ ;Start "CurrentSepCharNum" counter (for "Separators" Loop)
+ StrCpy $R0 0
+
+ ${Do} ;"Separators" Loop
+ ;Use one "Separators" character at a time
+ ${If} $R0 <> 0
+ StrCpy $9 $2 1 $R0
+ ${Else}
+ StrCpy $9 $2 1
+ ${EndIf}
+
+ ;Go to the next "String" char if it's "Separators" end
+ ${IfThen} $R0 >= $4 ${|} ${ExitDo} ${|}
+
+ ;Or, if "TempStr" equals "CurrentSepChar", then...
+ ${If} $7 == $9
+ StrCpy $7 $3 $6
+
+ ;If "String" is empty because this result part doesn't
+ ;contain data, verify if "SkipEmptyParts" is activated,
+ ;so we don't return the output to user yet
+
+ ${If} $7 == ``
+ ${AndIf} $0 = ${TRUE}
+ IntOp $6 $6 + 1
+ StrCpy $3 $3 `` $6
+ StrCpy $6 0
+ Goto StrSearchLoop
+ ${ElseIf} $8 == $1
+ StrCpy $3 $3 $6
+ StrCpy $R0 "End"
+ ${ExitDo}
+ ${EndIf} ;If not, go to the next result part
+ IntOp $6 $6 + 1
+ StrCpy $3 $3 `` $6
+ StrCpy $6 0
+ Goto ResultPartLoop
+ ${EndIf}
+
+ ;Increase "CurrentSepCharNum" counter
+ IntOp $R0 $R0 + 1
+ ${Loop}
+ ${IfThen} $R0 == "End" ${|} ${ExitDo} ${|}
+
+ ;Increase "StartCharPos" counter
+ IntOp $6 $6 + 1
+ ${Loop}
+
+ /*After this point:
+ ------------------------------------------
+ $3 = OutVar (output)*/
+
+ ;Return output to user
+
+ Pop $R0
+ Pop $9
+ Pop $8
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $0
+ Pop $1
+ Pop $2
+ Exch $3
+ !insertmacro STRFUNC_ENDFUNC
+
+ !macroend
+
+ ############################################################################
+ # StrTrimNewLines
+ !insertmacro STRFUNC_DEFFUNC StrTrimNewLines `ResultVar|String` `Output|Text`
+
+ !macro STRFUNC_CALL_StrTrimNewLines un ResultVar String
+ !verbose push ${STRFUNC_VERBOSITY}
+ !echo `${U+24}{${un}StrTrimNewLines} "${ResultVar}" "${String}"`
+ !verbose 2
+ Push `${String}`
+ !insertmacro STRFUNC_CALL StrTrimNewLines "${un}"
+ Pop ${ResultVar}
+ !verbose pop
+ !macroend
+
+ !macro STRFUNC_MAKEFUNC_StrTrimNewLines
+ !insertmacro STRFUNC_BEGINFUNC ${basename} `${un}` `2004 Diego Pedroso - Based on functions by Ximon Eighteen`
+
+ /*After this point:
+ ------------------------------------------
+ $R0 = String (input)
+ $R1 = TrimCounter (temp)
+ $R2 = Temp (temp)*/
+
+ ;Get input from user
+ Exch $R0
+ Push $R1
+ Push $R2
+
+ ;Initialize trim counter
+ StrCpy $R1 0
+
+ loop:
+ ;Subtract to get "String"'s last characters
+ IntOp $R1 $R1 - 1
+
+ ;Verify if they are either $\r or $\n
+ StrCpy $R2 $R0 1 $R1
+ ${If} $R2 == `$\r`
+ ${OrIf} $R2 == `$\n`
+ Goto loop
+ ${EndIf}
+
+ ;Trim characters (if needed)
+ IntOp $R1 $R1 + 1
+ ${If} $R1 < 0
+ StrCpy $R0 $R0 $R1
+ ${EndIf}
+
+ /*After this point:
+ ------------------------------------------
+ $R0 = OutVar (output)*/
+
+ ;Return output to user
+ Pop $R2
+ Pop $R1
+ Exch $R0
+ !insertmacro STRFUNC_ENDFUNC
+
+ !macroend
+
+ ############################################################################
+
+!endif
+!verbose 3
+!define STRFUNC_VERBOSITY ${_STRFUNC_VERBOSITY}
+!undef _STRFUNC_VERBOSITY
+!verbose pop
diff --git a/installer/tools/Include/TextFunc.nsh b/installer/tools/Include/TextFunc.nsh
new file mode 100644
index 00000000..230835b6
--- /dev/null
+++ b/installer/tools/Include/TextFunc.nsh
@@ -0,0 +1,1211 @@
+/*
+_____________________________________________________________________________
+
+ Text Functions Header v2.4
+_____________________________________________________________________________
+
+ 2006 Shengalts Aleksander aka Instructor (Shengalts@mail.ru)
+
+ See documentation for more information about the following functions.
+
+ Usage in script:
+ 1. !include "TextFunc.nsh"
+ 2. [Section|Function]
+ ${TextFunction} "File" "..." $var
+ [SectionEnd|FunctionEnd]
+
+
+ TextFunction=[LineFind|LineRead|FileReadFromEnd|LineSum|FileJoin|
+ TextCompare|TextCompareS|ConfigRead|ConfigReadS|
+ ConfigWrite|ConfigWriteS|FileRecode|TrimNewLines]
+
+_____________________________________________________________________________
+
+ Thanks to:
+_____________________________________________________________________________
+
+LineRead
+ Afrow UK (Based on his idea of Function "ReadFileLine")
+LineSum
+ Afrow UK (Based on his idea of Function "LineCount")
+FileJoin
+ Afrow UK (Based on his idea of Function "JoinFiles")
+ConfigRead
+ vbgunz (His idea)
+ConfigWrite
+ vbgunz (His idea)
+TrimNewLines
+ sunjammer (Based on his Function "TrimNewLines")
+*/
+
+
+;_____________________________________________________________________________
+;
+; Macros
+;_____________________________________________________________________________
+;
+; Change log window verbosity (default: 3=no script)
+;
+; Example:
+; !include "TextFunc.nsh"
+; !insertmacro LineFind
+; ${TEXTFUNC_VERBOSE} 4 # all verbosity
+; !insertmacro LineSum
+; ${TEXTFUNC_VERBOSE} 3 # no script
+
+!ifndef TEXTFUNC_INCLUDED
+
+!verbose push 3
+!define /IfNDef _TEXTFUNC_VERBOSE 3
+!verbose ${_TEXTFUNC_VERBOSE}
+!define TEXTFUNC_VERBOSE `!insertmacro TEXTFUNC_VERBOSE`
+
+!define TEXTFUNC_INCLUDED
+
+!include FileFunc.nsh
+!include Util.nsh
+
+
+!macro TEXTFUNC_VERBOSE _VERBOSE
+ !verbose push 3
+ !define /ReDef _TEXTFUNC_VERBOSE ${_VERBOSE}
+ !verbose pop
+!macroend
+
+!macro LineFindCall _INPUT _OUTPUT _RANGE _FUNC
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+ Push $0
+ Push `${_INPUT}`
+ Push `${_OUTPUT}`
+ Push `${_RANGE}`
+ GetFunctionAddress $0 `${_FUNC}`
+ Push `$0`
+ ${CallArtificialFunction} LineFind_
+ Pop $0
+ !verbose pop
+!macroend
+
+!macro LineReadCall _FILE _NUMBER _RESULT
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+ Push `${_FILE}`
+ Push `${_NUMBER}`
+ ${CallArtificialFunction} LineRead_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro FileReadFromEndCall _FILE _FUNC
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+ Push $0
+ Push `${_FILE}`
+ GetFunctionAddress $0 `${_FUNC}`
+ Push `$0`
+ ${CallArtificialFunction} FileReadFromEnd_
+ Pop $0
+ !verbose pop
+!macroend
+
+!macro LineSumCall _FILE _RESULT
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+ Push `${_FILE}`
+ ${CallArtificialFunction} LineSum_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro FileJoinCall _FILE1 _FILE2 _FILE3
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+ Push `${_FILE1}`
+ Push `${_FILE2}`
+ Push `${_FILE3}`
+ ${CallArtificialFunction} FileJoin_
+ !verbose pop
+!macroend
+
+!macro TextCompareCall _FILE1 _FILE2 _OPTION _FUNC
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+ Push $0
+ Push `${_FILE1}`
+ Push `${_FILE2}`
+ Push `${_OPTION}`
+ GetFunctionAddress $0 `${_FUNC}`
+ Push `$0`
+ ${CallArtificialFunction} TextCompare_
+ Pop $0
+ !verbose pop
+!macroend
+
+!macro TextCompareSCall _FILE1 _FILE2 _OPTION _FUNC
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+ Push $0
+ Push `${_FILE1}`
+ Push `${_FILE2}`
+ Push `${_OPTION}`
+ GetFunctionAddress $0 `${_FUNC}`
+ Push `$0`
+ ${CallArtificialFunction} TextCompareS_
+ Pop $0
+ !verbose pop
+!macroend
+
+!macro ConfigReadCall _FILE _ENTRY _RESULT
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+ Push `${_FILE}`
+ Push `${_ENTRY}`
+ ${CallArtificialFunction} ConfigRead_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro ConfigReadSCall _FILE _ENTRY _RESULT
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+ Push `${_FILE}`
+ Push `${_ENTRY}`
+ ${CallArtificialFunction} ConfigReadS_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro ConfigWriteCall _FILE _ENTRY _VALUE _RESULT
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+ Push `${_FILE}`
+ Push `${_ENTRY}`
+ Push `${_VALUE}`
+ ${CallArtificialFunction} ConfigWrite_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro ConfigWriteSCall _FILE _ENTRY _VALUE _RESULT
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+ Push `${_FILE}`
+ Push `${_ENTRY}`
+ Push `${_VALUE}`
+ ${CallArtificialFunction} ConfigWriteS_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro FileRecodeCall _FILE _FORMAT
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+ Push `${_FILE}`
+ Push `${_FORMAT}`
+ ${CallArtificialFunction} FileRecode_
+ !verbose pop
+!macroend
+
+!macro TrimNewLinesCall _FILE _RESULT
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+ Push `${_FILE}`
+ ${CallArtificialFunction} TrimNewLines_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro _TextFunc_TempFileForFile _FILE _RESULT
+ # XXX replace with GetParent
+ Push `${_FILE}`
+ Exch $0
+ Push $1
+ Push $2
+
+ StrCpy $2 $0 1 -1
+ StrCmp $2 '\' 0 +3
+ StrCpy $0 $0 -1
+ goto -3
+
+ StrCpy $1 0
+ IntOp $1 $1 - 1
+ StrCpy $2 $0 1 $1
+ StrCmp $2 '\' +2
+ StrCmp $2 '' 0 -3
+ StrCpy $0 $0 $1
+
+ Pop $2
+ Pop $1
+ Exch $0
+ Pop ${_RESULT}
+ # XXX
+ StrCmp ${_RESULT} "" 0 +2
+ StrCpy ${_RESULT} $EXEDIR
+ GetTempFileName ${_RESULT} ${_RESULT}
+ StrCmp ${_RESULT} "" 0 +2
+ GetTempFileName ${_RESULT}
+ ClearErrors
+!macroend
+
+!define LineFind `!insertmacro LineFindCall`
+!define un.LineFind `!insertmacro LineFindCall`
+
+!macro LineFind
+!macroend
+
+!macro un.LineFind
+!macroend
+
+!macro LineFind_
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+
+ Exch $3
+ Exch
+ Exch $2
+ Exch
+ Exch 2
+ Exch $1
+ Exch 2
+ Exch 3
+ Exch $0
+ Exch 3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $8
+ Push $9
+ Push $R4
+ Push $R5
+ Push $R6
+ Push $R7
+ Push $R8
+ Push $R9
+ ClearErrors
+
+ IfFileExists '$0' 0 TextFunc_LineFind_error
+ StrCmp $1 '/NUL' TextFunc_LineFind_begin
+ StrCpy $8 0
+ IntOp $8 $8 - 1
+ StrCpy $9 $1 1 $8
+ StrCmp $9 \ +2
+ StrCmp $9 '' +3 -3
+ StrCpy $9 $1 $8
+ IfFileExists '$9\*.*' 0 TextFunc_LineFind_error
+
+ TextFunc_LineFind_begin:
+ StrCpy $4 1
+ StrCpy $5 -1
+ StrCpy $6 0
+ StrCpy $7 0
+ StrCpy $R4 ''
+ StrCpy $R6 ''
+ StrCpy $R7 ''
+ StrCpy $R8 0
+
+ StrCpy $8 $2 1
+ StrCmp $8 '{' 0 TextFunc_LineFind_delspaces
+ StrCpy $2 $2 '' 1
+ StrCpy $8 $2 1 -1
+ StrCmp $8 '}' 0 TextFunc_LineFind_delspaces
+ StrCpy $2 $2 -1
+ StrCpy $R6 TextFunc_LineFind_cut
+
+ TextFunc_LineFind_delspaces:
+ StrCpy $8 $2 1
+ StrCmp $8 ' ' 0 +3
+ StrCpy $2 $2 '' 1
+ goto -3
+ StrCmp $2$7 '0' TextFunc_LineFind_file
+ StrCpy $4 ''
+ StrCpy $5 ''
+ StrCmp $2 '' TextFunc_LineFind_writechk
+
+ TextFunc_LineFind_range:
+ StrCpy $8 0
+ StrCpy $9 $2 1 $8
+ StrCmp $9 '' +5
+ StrCmp $9 ' ' +4
+ StrCmp $9 ':' +3
+ IntOp $8 $8 + 1
+ goto -5
+ StrCpy $5 $2 $8
+ IntOp $5 $5 + 0
+ IntOp $8 $8 + 1
+ StrCpy $2 $2 '' $8
+ StrCmp $4 '' 0 +2
+ StrCpy $4 $5
+ StrCmp $9 ':' TextFunc_LineFind_range
+
+ IntCmp $4 0 0 +2
+ IntCmp $5 -1 TextFunc_LineFind_goto 0 TextFunc_LineFind_growthcmp
+ StrCmp $R7 '' 0 TextFunc_LineFind_minus2plus
+ StrCpy $R7 0
+ FileOpen $8 $0 r
+ FileRead $8 $9
+ IfErrors +3
+ IntOp $R7 $R7 + 1
+ Goto -3
+ FileClose $8
+
+ TextFunc_LineFind_minus2plus:
+ IntCmp $4 0 +5 0 +5
+ IntOp $4 $R7 + $4
+ IntOp $4 $4 + 1
+ IntCmp $4 0 +2 0 +2
+ StrCpy $4 0
+ IntCmp $5 -1 TextFunc_LineFind_goto 0 TextFunc_LineFind_growthcmp
+ IntOp $5 $R7 + $5
+ IntOp $5 $5 + 1
+ TextFunc_LineFind_growthcmp:
+ IntCmp $4 $5 TextFunc_LineFind_goto TextFunc_LineFind_goto
+ StrCpy $5 $4
+ TextFunc_LineFind_goto:
+ goto $7
+
+ TextFunc_LineFind_file:
+ StrCmp $1 '/NUL' TextFunc_LineFind_notemp
+ !insertmacro _TextFunc_TempFileForFile $1 $R4
+ Push $R4
+ FileOpen $R4 $R4 w
+ TextFunc_LineFind_notemp:
+ FileOpen $R5 $0 r
+ IfErrors TextFunc_LineFind_preerror
+
+ TextFunc_LineFind_loop:
+ IntOp $R8 $R8 + 1
+ FileRead $R5 $R9
+ IfErrors TextFunc_LineFind_handleclose
+
+ TextFunc_LineFind_cmp:
+ StrCmp $2$4$5 '' TextFunc_LineFind_writechk
+ IntCmp $4 $R8 TextFunc_LineFind_call 0 TextFunc_LineFind_writechk
+ StrCmp $5 -1 TextFunc_LineFind_call
+ IntCmp $5 $R8 TextFunc_LineFind_call 0 TextFunc_LineFind_call
+
+ GetLabelAddress $7 TextFunc_LineFind_cmp
+ goto TextFunc_LineFind_delspaces
+
+ TextFunc_LineFind_call:
+ StrCpy $7 $R9
+ Push $0
+ Push $1
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $R4
+ Push $R5
+ Push $R6
+ Push $R7
+ Push $R8
+ StrCpy $R6 '$4:$5'
+ StrCmp $R7 '' +3
+ IntOp $R7 $R8 - $R7
+ IntOp $R7 $R7 - 1
+ Call $3
+ Pop $9
+ Pop $R8
+ Pop $R7
+ Pop $R6
+ Pop $R5
+ Pop $R4
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+ IfErrors TextFunc_LineFind_preerror
+ StrCmp $9 'StopLineFind' 0 +3
+ IntOp $6 $6 + 1
+ goto TextFunc_LineFind_handleclose
+ StrCmp $1 '/NUL' TextFunc_LineFind_loop
+ StrCmp $9 'SkipWrite' 0 +3
+ IntOp $6 $6 + 1
+ goto TextFunc_LineFind_loop
+ StrCmp $7 $R9 TextFunc_LineFind_write
+ IntOp $6 $6 + 1
+ goto TextFunc_LineFind_write
+
+ TextFunc_LineFind_writechk:
+ StrCmp $1 '/NUL' TextFunc_LineFind_loop
+ StrCmp $R6 TextFunc_LineFind_cut 0 TextFunc_LineFind_write
+ IntOp $6 $6 + 1
+ goto TextFunc_LineFind_loop
+
+ TextFunc_LineFind_write:
+ FileWrite $R4 $R9
+ goto TextFunc_LineFind_loop
+
+ TextFunc_LineFind_preerror:
+ SetErrors
+
+ TextFunc_LineFind_handleclose:
+ StrCmp $1 '/NUL' +3
+ FileClose $R4
+ Pop $R4
+ FileClose $R5
+ IfErrors TextFunc_LineFind_error
+
+ StrCmp $1 '/NUL' TextFunc_LineFind_end
+ StrCmp $1 '' 0 +2
+ StrCpy $1 $0
+ StrCmp $6 0 0 TextFunc_LineFind_rename
+ FileOpen $7 $0 r
+ FileSeek $7 0 END $8
+ FileClose $7
+ FileOpen $7 $R4 r
+ FileSeek $7 0 END $9
+ FileClose $7
+ IntCmp $8 $9 0 TextFunc_LineFind_rename
+ Delete $R4
+ StrCmp $1 $0 TextFunc_LineFind_end
+ CopyFiles /SILENT $0 $1
+ goto TextFunc_LineFind_end
+
+ TextFunc_LineFind_rename:
+ Delete '$EXEDIR\$1'
+ Rename $R4 '$EXEDIR\$1'
+ IfErrors 0 TextFunc_LineFind_end
+ Delete $1
+ Rename $R4 $1
+ IfErrors 0 TextFunc_LineFind_end
+
+ TextFunc_LineFind_error:
+ SetErrors
+
+ TextFunc_LineFind_end:
+ Pop $R9
+ Pop $R8
+ Pop $R7
+ Pop $R6
+ Pop $R5
+ Pop $R4
+ Pop $9
+ Pop $8
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+
+ !verbose pop
+!macroend
+
+!define LineRead `!insertmacro LineReadCall`
+!define un.LineRead `!insertmacro LineReadCall`
+
+!macro LineRead
+!macroend
+
+!macro un.LineRead
+!macroend
+
+!macro LineRead_
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $2
+ Push $3
+ Push $4
+ ClearErrors
+
+ IfFileExists $0 0 TextFunc_LineRead_error
+ IntOp $1 $1 + 0
+ IntCmp $1 0 TextFunc_LineRead_error 0 TextFunc_LineRead_plus
+ StrCpy $4 0
+ FileOpen $2 $0 r
+ IfErrors TextFunc_LineRead_error
+ FileRead $2 $3
+ IfErrors +3
+ IntOp $4 $4 + 1
+ Goto -3
+ FileClose $2
+ IntOp $1 $4 + $1
+ IntOp $1 $1 + 1
+ IntCmp $1 0 TextFunc_LineRead_error TextFunc_LineRead_error
+
+ TextFunc_LineRead_plus:
+ FileOpen $2 $0 r
+ IfErrors TextFunc_LineRead_error
+ StrCpy $3 0
+ IntOp $3 $3 + 1
+ FileRead $2 $0
+ IfErrors +4
+ StrCmp $3 $1 0 -3
+ FileClose $2
+ goto TextFunc_LineRead_end
+ FileClose $2
+
+ TextFunc_LineRead_error:
+ SetErrors
+ StrCpy $0 ''
+
+ TextFunc_LineRead_end:
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define FileReadFromEnd `!insertmacro FileReadFromEndCall`
+!define un.FileReadFromEnd `!insertmacro FileReadFromEndCall`
+
+!macro FileReadFromEnd
+!macroend
+
+!macro un.FileReadFromEnd
+!macroend
+
+!macro FileReadFromEnd_
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $7
+ Push $8
+ Push $9
+ ClearErrors
+
+ StrCpy $7 -1
+ StrCpy $8 0
+ IfFileExists $0 0 TextFunc_FileReadFromEnd_error
+ FileOpen $0 $0 r
+ IfErrors TextFunc_FileReadFromEnd_error
+ FileRead $0 $9
+ IfErrors +4
+ Push $9
+ IntOp $8 $8 + 1
+ goto -4
+ FileClose $0
+
+ TextFunc_FileReadFromEnd_nextline:
+ StrCmp $8 0 TextFunc_FileReadFromEnd_end
+ Pop $9
+ Push $1
+ Push $7
+ Push $8
+ Call $1
+ Pop $0
+ Pop $8
+ Pop $7
+ Pop $1
+ IntOp $7 $7 - 1
+ IntOp $8 $8 - 1
+ IfErrors TextFunc_FileReadFromEnd_error
+ StrCmp $0 'StopFileReadFromEnd' TextFunc_FileReadFromEnd_clearstack TextFunc_FileReadFromEnd_nextline
+
+ TextFunc_FileReadFromEnd_error:
+ SetErrors
+
+ TextFunc_FileReadFromEnd_clearstack:
+ StrCmp $8 0 TextFunc_FileReadFromEnd_end
+ Pop $9
+ IntOp $8 $8 - 1
+ goto TextFunc_FileReadFromEnd_clearstack
+
+ TextFunc_FileReadFromEnd_end:
+ Pop $9
+ Pop $8
+ Pop $7
+ Pop $1
+ Pop $0
+
+ !verbose pop
+!macroend
+
+!define LineSum `!insertmacro LineSumCall`
+!define un.LineSum `!insertmacro LineSumCall`
+
+!macro LineSum
+!macroend
+
+!macro un.LineSum
+!macroend
+
+!macro LineSum_
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+
+ Exch $0
+ Push $1
+ Push $2
+ ClearErrors
+
+ IfFileExists $0 0 TextFunc_LineSum_error
+ StrCpy $2 0
+ FileOpen $0 $0 r
+ IfErrors TextFunc_LineSum_error
+ FileRead $0 $1
+ IfErrors +3
+ IntOp $2 $2 + 1
+ Goto -3
+ FileClose $0
+ StrCpy $0 $2
+ goto TextFunc_LineSum_end
+
+ TextFunc_LineSum_error:
+ SetErrors
+ StrCpy $0 ''
+
+ TextFunc_LineSum_end:
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define FileJoin `!insertmacro FileJoinCall`
+!define un.FileJoin `!insertmacro FileJoinCall`
+
+!macro FileJoin
+!macroend
+
+!macro un.FileJoin
+!macroend
+
+!macro FileJoin_
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+
+ Exch $2
+ Exch
+ Exch $1
+ Exch
+ Exch 2
+ Exch $0
+ Exch 2
+ Push $3
+ Push $4
+ Push $5
+ ClearErrors
+
+ IfFileExists $0 0 TextFunc_FileJoin_error
+ IfFileExists $1 0 TextFunc_FileJoin_error
+ StrCpy $3 0
+ IntOp $3 $3 - 1
+ StrCpy $4 $2 1 $3
+ StrCmp $4 \ +2
+ StrCmp $4 '' +3 -3
+ StrCpy $4 $2 $3
+ IfFileExists '$4\*.*' 0 TextFunc_FileJoin_error
+
+ StrCmp $2 $0 0 +2
+ StrCpy $2 ''
+ StrCmp $2 '' 0 +3
+ StrCpy $4 $0
+ Goto TextFunc_FileJoin_notemp
+ !insertmacro _TextFunc_TempFileForFile $2 $4
+ CopyFiles /SILENT $0 $4
+ TextFunc_FileJoin_notemp:
+ FileOpen $3 $4 a
+ IfErrors TextFunc_FileJoin_error
+ FileSeek $3 -1 END
+ FileRead $3 $5
+ StrCmp $5 '$\r' +3
+ StrCmp $5 '$\n' +2
+ FileWrite $3 '$\r$\n'
+
+ ;FileWrite $3 '$\r$\n--Divider--$\r$\n'
+
+ FileOpen $0 $1 r
+ IfErrors TextFunc_FileJoin_error
+ FileRead $0 $5
+ IfErrors +3
+ FileWrite $3 $5
+ goto -3
+ FileClose $0
+ FileClose $3
+ StrCmp $2 '' TextFunc_FileJoin_end
+ Delete '$EXEDIR\$2'
+ Rename $4 '$EXEDIR\$2'
+ IfErrors 0 TextFunc_FileJoin_end
+ Delete $2
+ Rename $4 $2
+ IfErrors 0 TextFunc_FileJoin_end
+
+ TextFunc_FileJoin_error:
+ SetErrors
+
+ TextFunc_FileJoin_end:
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+
+ !verbose pop
+!macroend
+
+!macro TextCompareBody _TEXTFUNC_S
+ Exch $3
+ Exch
+ Exch $2
+ Exch
+ Exch 2
+ Exch $1
+ Exch 2
+ Exch 3
+ Exch $0
+ Exch 3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $8
+ Push $9
+ ClearErrors
+
+ IfFileExists $0 0 TextFunc_TextCompare${_TEXTFUNC_S}_error
+ IfFileExists $1 0 TextFunc_TextCompare${_TEXTFUNC_S}_error
+ StrCmp $2 'FastDiff' +5
+ StrCmp $2 'FastEqual' +4
+ StrCmp $2 'SlowDiff' +3
+ StrCmp $2 'SlowEqual' +2
+ goto TextFunc_TextCompare${_TEXTFUNC_S}_error
+
+ FileOpen $4 $0 r
+ IfErrors TextFunc_TextCompare${_TEXTFUNC_S}_error
+ FileOpen $5 $1 r
+ IfErrors TextFunc_TextCompare${_TEXTFUNC_S}_error
+ SetDetailsPrint textonly
+
+ StrCpy $6 0
+ StrCpy $8 0
+
+ TextFunc_TextCompare${_TEXTFUNC_S}_nextline:
+ StrCmp${_TEXTFUNC_S} $4 '' TextFunc_TextCompare${_TEXTFUNC_S}_fast
+ IntOp $8 $8 + 1
+ FileRead $4 $9
+ IfErrors 0 +4
+ FileClose $4
+ StrCpy $4 ''
+ StrCmp${_TEXTFUNC_S} $5 '' TextFunc_TextCompare${_TEXTFUNC_S}_end
+ StrCmp $2 'FastDiff' TextFunc_TextCompare${_TEXTFUNC_S}_fast
+ StrCmp $2 'FastEqual' TextFunc_TextCompare${_TEXTFUNC_S}_fast TextFunc_TextCompare${_TEXTFUNC_S}_slow
+
+ TextFunc_TextCompare${_TEXTFUNC_S}_fast:
+ StrCmp${_TEXTFUNC_S} $5 '' TextFunc_TextCompare${_TEXTFUNC_S}_call
+ IntOp $6 $6 + 1
+ FileRead $5 $7
+ IfErrors 0 +5
+ FileClose $5
+ StrCpy $5 ''
+ StrCmp${_TEXTFUNC_S} $4 '' TextFunc_TextCompare${_TEXTFUNC_S}_end
+ StrCmp $2 'FastDiff' TextFunc_TextCompare${_TEXTFUNC_S}_call TextFunc_TextCompare${_TEXTFUNC_S}_close
+ StrCmp $2 'FastDiff' 0 +2
+ StrCmp${_TEXTFUNC_S} $7 $9 TextFunc_TextCompare${_TEXTFUNC_S}_nextline TextFunc_TextCompare${_TEXTFUNC_S}_call
+ StrCmp${_TEXTFUNC_S} $7 $9 TextFunc_TextCompare${_TEXTFUNC_S}_call TextFunc_TextCompare${_TEXTFUNC_S}_nextline
+
+ TextFunc_TextCompare${_TEXTFUNC_S}_slow:
+ StrCmp${_TEXTFUNC_S} $4 '' TextFunc_TextCompare${_TEXTFUNC_S}_close
+ StrCpy $6 ''
+ DetailPrint '$8. $9'
+ FileSeek $5 0
+
+ TextFunc_TextCompare${_TEXTFUNC_S}_slownext:
+ FileRead $5 $7
+ IfErrors 0 +2
+ StrCmp $2 'SlowDiff' TextFunc_TextCompare${_TEXTFUNC_S}_call TextFunc_TextCompare${_TEXTFUNC_S}_nextline
+ StrCmp $2 'SlowDiff' 0 +2
+ StrCmp${_TEXTFUNC_S} $7 $9 TextFunc_TextCompare${_TEXTFUNC_S}_nextline TextFunc_TextCompare${_TEXTFUNC_S}_slownext
+ IntOp $6 $6 + 1
+ StrCmp${_TEXTFUNC_S} $7 $9 0 TextFunc_TextCompare${_TEXTFUNC_S}_slownext
+
+ TextFunc_TextCompare${_TEXTFUNC_S}_call:
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $8
+ Push $9
+ Call $3
+ Pop $0
+ Pop $9
+ Pop $8
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ StrCmp $0 'StopTextCompare' 0 TextFunc_TextCompare${_TEXTFUNC_S}_nextline
+
+ TextFunc_TextCompare${_TEXTFUNC_S}_close:
+ FileClose $4
+ FileClose $5
+ goto TextFunc_TextCompare${_TEXTFUNC_S}_end
+
+ TextFunc_TextCompare${_TEXTFUNC_S}_error:
+ SetErrors
+
+ TextFunc_TextCompare${_TEXTFUNC_S}_end:
+ SetDetailsPrint both
+ Pop $9
+ Pop $8
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+!macroend
+
+!define TextCompare `!insertmacro TextCompareCall`
+!define un.TextCompare `!insertmacro TextCompareCall`
+
+!macro TextCompare
+!macroend
+
+!macro un.TextCompare
+!macroend
+
+!macro TextCompare_
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+
+ !insertmacro TextCompareBody ''
+
+ !verbose pop
+!macroend
+
+!define TextCompareS `!insertmacro TextCompareSCall`
+!define un.TextCompareS `!insertmacro TextCompareSCall`
+
+!macro TextCompareS
+!macroend
+
+!macro un.TextCompareS
+!macroend
+
+!macro TextCompareS_
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+
+ !insertmacro TextCompareBody 'S'
+
+ !verbose pop
+!macroend
+
+!macro ConfigReadBody _TEXTFUNC_S
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $2
+ Push $3
+ Push $4
+ ClearErrors
+
+ FileOpen $2 $0 r
+ IfErrors TextFunc_ConfigRead${_TEXTFUNC_S}_error
+ StrLen $0 $1
+ StrCmp${_TEXTFUNC_S} $0 0 TextFunc_ConfigRead${_TEXTFUNC_S}_error
+
+ TextFunc_ConfigRead${_TEXTFUNC_S}_readnext:
+ FileRead $2 $3
+ IfErrors TextFunc_ConfigRead${_TEXTFUNC_S}_error
+ StrCpy $4 $3 $0
+ StrCmp${_TEXTFUNC_S} $4 $1 0 TextFunc_ConfigRead${_TEXTFUNC_S}_readnext
+ StrCpy $0 $3 '' $0
+ StrCpy $4 $0 1 -1
+ StrCmp${_TEXTFUNC_S} $4 '$\r' +2
+ StrCmp${_TEXTFUNC_S} $4 '$\n' 0 TextFunc_ConfigRead${_TEXTFUNC_S}_close
+ StrCpy $0 $0 -1
+ goto -4
+
+ TextFunc_ConfigRead${_TEXTFUNC_S}_error:
+ SetErrors
+ StrCpy $0 ''
+
+ TextFunc_ConfigRead${_TEXTFUNC_S}_close:
+ FileClose $2
+
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+!macroend
+
+!define ConfigRead `!insertmacro ConfigReadCall`
+!define un.ConfigRead `!insertmacro ConfigReadCall`
+
+!macro ConfigRead
+!macroend
+
+!macro un.ConfigRead
+!macroend
+
+!macro ConfigRead_
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+
+ !insertmacro ConfigReadBody ''
+
+ !verbose pop
+!macroend
+
+!define ConfigReadS `!insertmacro ConfigReadSCall`
+!define un.ConfigReadS `!insertmacro ConfigReadSCall`
+
+!macro ConfigReadS
+!macroend
+
+!macro un.ConfigReadS
+!macroend
+
+!macro ConfigReadS_
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+
+ !insertmacro ConfigReadBody 'S'
+
+ !verbose pop
+!macroend
+
+!macro ConfigWriteBody _TEXTFUNC_S
+ Exch $2
+ Exch
+ Exch $1
+ Exch
+ Exch 2
+ Exch $0
+ Exch 2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ ClearErrors
+
+ IfFileExists $0 0 TextFunc_ConfigWrite${_TEXTFUNC_S}_error
+ FileOpen $3 $0 a
+ IfErrors TextFunc_ConfigWrite${_TEXTFUNC_S}_error
+
+ StrLen $0 $1
+ StrCmp${_TEXTFUNC_S} $0 0 0 TextFunc_ConfigWrite${_TEXTFUNC_S}_readnext
+ StrCpy $0 ''
+ goto TextFunc_ConfigWrite${_TEXTFUNC_S}_close
+
+ TextFunc_ConfigWrite${_TEXTFUNC_S}_readnext:
+ FileRead $3 $4
+ IfErrors TextFunc_ConfigWrite${_TEXTFUNC_S}_add
+ StrCpy $5 $4 $0
+ StrCmp${_TEXTFUNC_S} $5 $1 0 TextFunc_ConfigWrite${_TEXTFUNC_S}_readnext
+
+ StrCpy $5 0
+ IntOp $5 $5 - 1
+ StrCpy $6 $4 1 $5
+ StrCmp${_TEXTFUNC_S} $6 '$\r' -2
+ StrCmp${_TEXTFUNC_S} $6 '$\n' -3
+ StrCpy $6 $4
+ StrCmp${_TEXTFUNC_S} $5 -1 +3
+ IntOp $5 $5 + 1
+ StrCpy $6 $4 $5
+
+ StrCmp${_TEXTFUNC_S} $2 '' TextFunc_ConfigWrite${_TEXTFUNC_S}_change
+ StrCmp${_TEXTFUNC_S} $6 '$1$2' 0 TextFunc_ConfigWrite${_TEXTFUNC_S}_change
+ StrCpy $0 SAME
+ goto TextFunc_ConfigWrite${_TEXTFUNC_S}_close
+
+ TextFunc_ConfigWrite${_TEXTFUNC_S}_change:
+ FileSeek $3 0 CUR $5
+ StrLen $4 $4
+ IntOp $4 $5 - $4
+ FileSeek $3 0 END $6
+ IntOp $6 $6 - $5
+
+ System::Alloc $6
+ Pop $0
+ FileSeek $3 $5 SET
+ System::Call 'kernel32::ReadFile(p r3, p r0, i $6, t.,)'
+ FileSeek $3 $4 SET
+ StrCmp${_TEXTFUNC_S} $2 '' +2
+ FileWrite $3 '$1$2$\r$\n'
+ System::Call 'kernel32::WriteFile(p r3, p r0, i $6, t.,)'
+ System::Call 'kernel32::SetEndOfFile(p r3)'
+ System::Free $0
+ StrCmp${_TEXTFUNC_S} $2 '' +3
+ StrCpy $0 CHANGED
+ goto TextFunc_ConfigWrite${_TEXTFUNC_S}_close
+ StrCpy $0 DELETED
+ goto TextFunc_ConfigWrite${_TEXTFUNC_S}_close
+
+ TextFunc_ConfigWrite${_TEXTFUNC_S}_add:
+ StrCmp${_TEXTFUNC_S} $2 '' 0 +3
+ StrCpy $0 SAME
+ goto TextFunc_ConfigWrite${_TEXTFUNC_S}_close
+ FileSeek $3 -1 END
+ FileRead $3 $4
+ IfErrors +4
+ StrCmp${_TEXTFUNC_S} $4 '$\r' +3
+ StrCmp${_TEXTFUNC_S} $4 '$\n' +2
+ FileWrite $3 '$\r$\n'
+ FileWrite $3 '$1$2$\r$\n'
+ StrCpy $0 ADDED
+
+ TextFunc_ConfigWrite${_TEXTFUNC_S}_close:
+ FileClose $3
+ goto TextFunc_ConfigWrite${_TEXTFUNC_S}_end
+
+ TextFunc_ConfigWrite${_TEXTFUNC_S}_error:
+ SetErrors
+ StrCpy $0 ''
+
+ TextFunc_ConfigWrite${_TEXTFUNC_S}_end:
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+!macroend
+
+!define ConfigWrite `!insertmacro ConfigWriteCall`
+!define un.ConfigWrite `!insertmacro ConfigWriteCall`
+
+!macro ConfigWrite
+!macroend
+
+!macro un.ConfigWrite
+!macroend
+
+!macro ConfigWrite_
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+
+ !insertmacro ConfigWriteBody ''
+
+ !verbose pop
+!macroend
+
+!define ConfigWriteS `!insertmacro ConfigWriteSCall`
+!define un.ConfigWriteS `!insertmacro ConfigWriteSCall`
+
+!macro ConfigWriteS
+!macroend
+
+!macro un.ConfigWriteS
+!macroend
+
+!macro ConfigWriteS_
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+
+ !insertmacro ConfigWriteBody 'S'
+
+ !verbose pop
+!macroend
+
+!define FileRecode `!insertmacro FileRecodeCall`
+!define un.FileRecode `!insertmacro FileRecodeCall`
+
+!macro FileRecode
+!macroend
+
+!macro un.FileRecode
+!macroend
+
+!macro FileRecode_
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $2
+ Push $3
+ Push $4
+
+ IfFileExists $0 0 TextFunc_FileRecode_error
+ StrCmp $1 OemToChar +2
+ StrCmp $1 CharToOem 0 TextFunc_FileRecode_error
+
+ FileOpen $2 $0 a
+ FileSeek $2 0 END $3
+ System::Alloc $3
+ Pop $4
+ FileSeek $2 0 SET
+ System::Call 'kernel32::ReadFile(p r2, p r4, i $3, t.,)'
+ System::Call 'user32::$1Buff(p r4, p r4, i $3)'
+ FileSeek $2 0 SET
+ System::Call 'kernel32::WriteFile(p r2, p r4, i $3, t.,)'
+ System::Free $4
+ FileClose $2
+ goto TextFunc_FileRecode_end
+
+ TextFunc_FileRecode_error:
+ SetErrors
+
+ TextFunc_FileRecode_end:
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+
+ !verbose pop
+!macroend
+
+!define TrimNewLines `!insertmacro TrimNewLinesCall`
+!define un.TrimNewLines `!insertmacro TrimNewLinesCall`
+
+!macro TrimNewLines
+!macroend
+
+!macro un.TrimNewLines
+!macroend
+
+!macro TrimNewLines_
+ !verbose push
+ !verbose ${_TEXTFUNC_VERBOSE}
+
+ Exch $0
+ Push $1
+ Push $2
+
+ StrCpy $1 0
+ IntOp $1 $1 - 1
+ StrCpy $2 $0 1 $1
+ StrCmp $2 '$\r' -2
+ StrCmp $2 '$\n' -3
+ StrCmp $1 -1 +3
+ IntOp $1 $1 + 1
+ StrCpy $0 $0 $1
+
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!verbose pop
+!endif
diff --git a/installer/tools/Include/UpgradeDLL.nsh b/installer/tools/Include/UpgradeDLL.nsh
new file mode 100644
index 00000000..cfb29471
--- /dev/null
+++ b/installer/tools/Include/UpgradeDLL.nsh
@@ -0,0 +1,207 @@
+/*
+
+NOTE:
+-----
+This macro is provided for backwards compatibility with NSIS 2.0 scripts.
+It's recommended you update your scripts to use the new Library.nsh macros.
+
+
+Macro - Upgrade DLL File
+Written by Joost Verburg
+------------------------
+
+Parameters:
+LOCALFILE Location of the new DLL file (on the compiler system)
+DESTFILE Location of the DLL file that should be upgraded (on the user's system)
+TEMPBASEDIR Directory on the user's system to store a temporary file when the system has
+ to be rebooted.
+ For Win9x/ME support, this should be on the same volume as DESTFILE.
+ The Windows temp directory could be located on any volume, so you cannot use
+ this directory.
+
+Define UPGRADEDLL_NOREGISTER if you want to upgrade a DLL that does not have to be registered.
+
+Notes:
+
+* If you want to support Windows 9x/ME, you can only use short filenames (8.3).
+
+* This macro uses the GetDLLVersionLocal command to retrieve the version of local libraries.
+ This command is only supported when compiling on a Windows system.
+
+------------------------
+
+Example:
+
+!insertmacro UpgradeDLL "dllname.dll" "$SYSDIR\dllname.dll" "$SYSDIR"
+
+*/
+
+!ifndef UPGRADEDLL_INCLUDED
+
+!define UPGRADEDLL_INCLUDED
+
+!macro __UpgradeDLL_Helper_AddRegToolEntry mode filename tempdir
+
+ Push $R0
+ Push $R1
+ Push $R2
+ Push $R3
+
+ ;------------------------
+ ;Copy the parameters
+
+ Push "${filename}"
+ Push "${tempdir}"
+
+ Pop $R2 ; temporary directory
+ Pop $R1 ; file name to register
+
+ ;------------------------
+ ;Advance counter
+
+ StrCpy $R0 0
+ ReadRegDWORD $R0 HKLM "Software\NSIS.Library.RegTool.v3\UpgradeDLLSession" "count"
+ IntOp $R0 $R0 + 1
+ WriteRegDWORD HKLM "Software\NSIS.Library.RegTool.v3\UpgradeDLLSession" "count" "$R0"
+
+ ;------------------------
+ ;Setup RegTool
+
+ !if ! /FileExists "${NSISDIR}\Bin\RegTool-${NSIS_CPU}.bin"
+ !error "Missing RegTool for ${NSIS_CPU}!"
+ !endif
+
+ ReadRegStr $R3 HKLM "Software\Microsoft\Windows\CurrentVersion\RunOnce" "NSIS.Library.RegTool.v3"
+ StrCpy $R3 $R3 -4 1
+ IfFileExists $R3 +3
+
+ File /oname=$R2\NSIS.Library.RegTool.v3.$HWNDPARENT.exe "${NSISDIR}\Bin\RegTool-${NSIS_CPU}.bin"
+ WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\RunOnce" \
+ "NSIS.Library.RegTool.v3" '"$R2\NSIS.Library.RegTool.v3.$HWNDPARENT.exe" /S'
+
+ ;------------------------
+ ;Add RegTool entry
+
+ WriteRegStr HKLM "Software\NSIS.Library.RegTool.v3\UpgradeDLLSession" "$R0.file" "$R1"
+ WriteRegStr HKLM "Software\NSIS.Library.RegTool.v3\UpgradeDLLSession" "$R0.mode" "${mode}"
+
+ Pop $R3
+ Pop $R2
+ Pop $R1
+ Pop $R0
+
+!macroend
+
+!macro UpgradeDLL LOCALFILE DESTFILE TEMPBASEDIR
+
+ Push $R0
+ Push $R1
+ Push $R2
+ Push $R3
+ Push $R4
+ Push $R5
+
+ !define UPGRADEDLL_UNIQUE "${__FILE__}${__LINE__}"
+
+ SetOverwrite try
+
+ ;------------------------
+ ;Copy the macro parameters to a run-time to a variable,
+ ;this allows the usage of variables as parameter
+
+ StrCpy $R4 "${DESTFILE}"
+ StrCpy $R5 "${TEMPBASEDIR}"
+
+ ;------------------------
+ ;Get version information
+
+ IfFileExists $R4 0 "upgradedll.copy_${UPGRADEDLL_UNIQUE}"
+
+ ClearErrors
+ GetDLLVersionLocal "${LOCALFILE}" $R0 $R1
+ GetDLLVersion $R4 $R2 $R3
+ IfErrors "upgradedll.upgrade_${UPGRADEDLL_UNIQUE}"
+
+ IntCmpU $R0 $R2 0 "upgradedll.done_${UPGRADEDLL_UNIQUE}" "upgradedll.upgrade_${UPGRADEDLL_UNIQUE}"
+ IntCmpU $R1 $R3 "upgradedll.done_${UPGRADEDLL_UNIQUE}" "upgradedll.done_${UPGRADEDLL_UNIQUE}" \
+ "upgradedll.upgrade_${UPGRADEDLL_UNIQUE}"
+
+ ;------------------------
+ ;Upgrade
+
+ "upgradedll.upgrade_${UPGRADEDLL_UNIQUE}:"
+ !ifndef UPGRADEDLL_NOREGISTER
+ ;Unregister the DLL
+ UnRegDLL $R4
+ !endif
+
+ ;------------------------
+ ;Copy
+
+ ClearErrors
+ StrCpy $R0 $R4
+ Call ":upgradedll.file_${UPGRADEDLL_UNIQUE}"
+ IfErrors 0 "upgradedll.noreboot_${UPGRADEDLL_UNIQUE}"
+
+ ;------------------------
+ ;Copy on reboot
+
+ GetTempFileName $R0 $R5
+ Call ":upgradedll.file_${UPGRADEDLL_UNIQUE}"
+ Rename /REBOOTOK $R0 $R4
+
+ ;------------------------
+ ;Register on reboot
+
+ !insertmacro __UpgradeDLL_Helper_AddRegToolEntry 'D' $R4 $R5
+
+ Goto "upgradedll.done_${UPGRADEDLL_UNIQUE}"
+
+ ;------------------------
+ ;DLL does not exist
+
+ "upgradedll.copy_${UPGRADEDLL_UNIQUE}:"
+ StrCpy $R0 $R4
+ Call ":upgradedll.file_${UPGRADEDLL_UNIQUE}"
+
+ ;------------------------
+ ;Register
+
+ "upgradedll.noreboot_${UPGRADEDLL_UNIQUE}:"
+ !ifndef UPGRADEDLL_NOREGISTER
+ RegDLL $R4
+ !endif
+
+ ;------------------------
+ ;Done
+
+ "upgradedll.done_${UPGRADEDLL_UNIQUE}:"
+
+ Pop $R5
+ Pop $R4
+ Pop $R3
+ Pop $R2
+ Pop $R1
+ Pop $R0
+
+ ;------------------------
+ ;End
+
+ Goto "upgradedll.end_${UPGRADEDLL_UNIQUE}"
+
+ ;------------------------
+ ;Extract
+
+ "upgradedll.file_${UPGRADEDLL_UNIQUE}:"
+ File /oname=$R0 "${LOCALFILE}"
+ Return
+
+ "upgradedll.end_${UPGRADEDLL_UNIQUE}:"
+
+ SetOverwrite lastused
+
+ !undef UPGRADEDLL_UNIQUE
+
+!macroend
+
+!endif
diff --git a/installer/tools/Include/Util.nsh b/installer/tools/Include/Util.nsh
new file mode 100644
index 00000000..30d03a50
--- /dev/null
+++ b/installer/tools/Include/Util.nsh
@@ -0,0 +1,184 @@
+; ---------------------
+; Util.nsh
+; ---------------------
+;
+; Voodoo macros to make end-user usage easier. This may be documented someday.
+
+!verbose push 3
+!ifndef ___UTIL__NSH___
+!define ___UTIL__NSH___
+
+# CallArtificialFunction, see WinVer.nsh and *Func.nsh for usage examples
+!macro CallArtificialFunctionHelper TYPE NAME
+ !verbose pop
+ Call :.${NAME}${TYPE}
+ !ifndef ${NAME}${TYPE}_DEFINED
+ !verbose push 2
+ Goto ${NAME}${TYPE}_DONE
+ !define ${NAME}${TYPE}_DEFINED
+ !verbose pop
+ .${NAME}${TYPE}:
+ !insertmacro ${NAME}
+ Return
+ ${NAME}${TYPE}_DONE:
+ !endif
+ !verbose push 2
+!macroend
+
+!macro CallArtificialFunction NAME
+ !verbose push 2
+ !ifdef __UNINSTALL__
+ !insertmacro CallArtificialFunctionHelper uninst ${NAME}
+ !else
+ !insertmacro CallArtificialFunctionHelper inst ${NAME}
+ !endif
+ !verbose pop
+!macroend
+!define CallArtificialFunction `!insertmacro CallArtificialFunction`
+
+!macro CallArtificialFunction2 NAME ; Retained for v2.4x..v3.0b0 compatibility
+ ${CallArtificialFunction} ${NAME}
+!macroend
+!define CallArtificialFunction2 `!insertmacro CallArtificialFunction`
+
+
+!define Int32Op '!insertmacro Int32Op '
+!define Int64Op '!insertmacro Int64Op '
+!define IntPtrOp '!insertmacro IntPtrOp '
+!macro Int32Op r a o b
+IntOp `${r}` `${a}` `${o}` ${b}
+!macroend
+!macro Int64Op r a o b
+!echo "Int64Op ${r}=${a}${o}${b}"
+!verbose push 2
+System::Int64Op `${a}` `${o}` ${b}
+Pop ${r}
+!verbose pop
+!macroend
+!macro IntPtrOp r a o b
+IntPtrOp `${r}` `${a}` `${o}` `${b}`
+!macroend
+
+!define Int32Cmp '!insertmacro Int32Cmp '
+!define Int64Cmp '!insertmacro Int64Cmp '
+!define IntPtrCmp '!insertmacro IntPtrCmp '
+!macro Int32Cmp a b jeek jles jgtr
+IntCmp `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}`
+!macroend
+!macro Int64Cmp a b jeek jles jgtr
+!if ${NSIS_PTR_SIZE} <= 4
+!ifmacrondef _LOGICLIB_TEMP
+!include LogicLib.nsh
+!endif
+!echo "Int64Cmp ${a}:${b} =${jeek}, <${jles}, >${jgtr}"
+!verbose push 2
+${IfThen} ${a} L= ${b} ${|} Goto ${jeek} ${|}
+!insertmacro _L< ${a} ${b} `${jles}` `${jgtr}`
+!verbose pop
+!else
+Int64Cmp `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}`
+!endif
+!macroend
+!macro IntPtrCmp a b jeek jles jgtr
+IntPtrCmp `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}`
+!macroend
+
+!define Int32CmpU '!insertmacro Int32CmpU '
+!define Int64CmpU '!insertmacro Int64CmpU '
+!define IntPtrCmpU '!insertmacro IntPtrCmpU '
+!macro Int32CmpU a b jeek jles jgtr
+IntCmpU `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}`
+!macroend
+!macro Int64CmpUHelper
+; This macro performs "$_LOGICLIB_TEMP = a < b ? -1 : a > b ? 1 : 0" but System::Int64Op does not support unsigned operations so we have to perform multiple steps
+!ifmacrondef _LOGICLIB_TEMP
+!include LogicLib.nsh
+!endif
+!insertmacro _LOGICLIB_TEMP
+Exch $2 ; b
+Exch
+Exch $1 ; a
+; if (a == b) return 0;
+; if (a < 0)
+; {
+; if (b >= 0) return 1
+; }
+; else
+; {
+; if (b < 0) return -1
+; }
+; return a < b ? -1 : 1
+System::Int64Op $1 ^ $2 ; Using xor so $_LOGICLIB_TEMP ends up as 0 when they are equal
+Pop $_LOGICLIB_TEMP
+StrCmp $_LOGICLIB_TEMP 0 ret ; NOTE: Must use StrCmp, IntCmp fails on "0x8000000000000001 Z> 1"
+System::Int64Op $1 < 0
+Pop $_LOGICLIB_TEMP
+StrCmp $_LOGICLIB_TEMP 0 checkNegOther
+System::Int64Op $2 < 0 ; System::Int64Op does not support the >= operator so we invert the operation
+Pop $_LOGICLIB_TEMP
+StrCmp $_LOGICLIB_TEMP 0 retPos finalCmp
+retPos:
+StrCpy $_LOGICLIB_TEMP "1"
+Goto ret
+checkNegOther:
+System::Int64Op $2 < 0
+Pop $_LOGICLIB_TEMP
+StrCmp $_LOGICLIB_TEMP 0 finalCmp retNeg
+retNeg:
+StrCpy $_LOGICLIB_TEMP "-1"
+Goto ret
+finalCmp:
+System::Int64Op $1 < $2
+Pop $_LOGICLIB_TEMP
+StrCmp $_LOGICLIB_TEMP 0 retPos retNeg
+ret:
+Pop $1
+Pop $2
+!macroend
+!macro Int64CmpU a b jeek jles jgtr
+!if ${NSIS_PTR_SIZE} <= 4
+!echo "Int64CmpU ${a}:${b} =${jeek}, <${jles}, >${jgtr}"
+!verbose push 2
+Push `${a}`
+Push `${b}`
+!insertmacro CallArtificialFunction Int64CmpUHelper
+IntCmp $_LOGICLIB_TEMP 0 `${jeek}` `${jles}` `${jgtr}`
+!verbose pop
+!else
+Int64CmpU `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}`
+!endif
+!macroend
+!macro IntPtrCmpU a b jeek jles jgtr
+IntPtrCmpU `${a}` `${b}` `${jeek}` `${jles}` `${jgtr}`
+!macroend
+
+
+!define MakeARPInstallDate "!insertmacro MakeARPInstallDate "
+!macro MakeARPInstallDate _outvar
+System::Call 'KERNEL32::GetDateFormat(i0x409,i0,p0,t"yyyyMMdd",t.s,i${NSIS_MAX_STRLEN})'
+Pop ${_outvar}
+!macroend
+
+
+!define /IfNDef SPI_GETHIGHCONTRAST 0x42
+!define /IfNDef HCF_HIGHCONTRASTON 0x01
+!define /IfNDef /math SYSSIZEOF_HIGHCONTRAST 8 + ${NSIS_PTR_SIZE}
+!define IsHighContrastModeActive '"" IsHighContrastModeActive ""'
+!macro _IsHighContrastModeActive _lhs _rhs _t _f
+!ifmacrondef _LOGICLIB_TEMP
+!include LogicLib.nsh
+!endif
+!insertmacro _LOGICLIB_TEMP
+Push $1
+System::Call '*(i${SYSSIZEOF_HIGHCONTRAST},i0,p)p.r1'
+System::Call 'USER32::SystemParametersInfo(i${SPI_GETHIGHCONTRAST},i${SYSSIZEOF_HIGHCONTRAST},pr1,i0)'
+System::Call '*$1(i,i.s)'
+Pop $_LOGICLIB_TEMP
+System::Free $1
+Pop $1
+!insertmacro _& $_LOGICLIB_TEMP ${HCF_HIGHCONTRASTON} `${_t}` `${_f}`
+!macroend
+
+
+!endif # !___UTIL__NSH___
+!verbose pop
diff --git a/installer/tools/Include/VB6RunTime.nsh b/installer/tools/Include/VB6RunTime.nsh
new file mode 100644
index 00000000..7ad2fc29
--- /dev/null
+++ b/installer/tools/Include/VB6RunTime.nsh
@@ -0,0 +1,90 @@
+/*
+
+VB6RunTime.nsh
+
+Setup of Visual Basic 6.0 run-time files, including the Oleaut32.dll security update
+
+Copyright 2008-2023 Joost Verburg
+
+To obtain the run-time files, download and extract
+https://nsis.sourceforge.io/vb6runtime.zip
+
+Script code for installation:
+
+!insertmacro InstallVB6RunTime FOLDER ALREADY_INSTALLED
+
+in which FOLDER is the location of the run-time files and ALREADY_INSTALLED is the
+name of a variable that is empty when the application is installed for the first time
+and non-empty otherwise
+
+Script code for uninstallation:
+
+!insertmacro UnInstallVB6RunTime
+
+Remarks:
+
+* You may have to install additional files for such Visual Basic application to work,
+ such as OCX files for user interface controls.
+
+* Installation of the run-time files requires Administrator or Power User privileges.
+ Use the Multi-User header file to verify whether these privileges are available.
+
+* Add a Modern UI finish page or another check (see IfRebootFlag in the NSIS Users
+ Manual) to allow the user to restart the computer when necessary.
+
+*/
+
+!ifndef VB6_INCLUDED
+!define VB6_INCLUDED
+!verbose push
+!verbose 3
+
+!include Library.nsh
+!include WinVer.nsh
+
+!macro VB6RunTimeInstall FOLDER ALREADY_INSTALLED
+
+ !insertmacro InstallLib REGDLL "${ALREADY_INSTALLED}" REBOOT_PROTECTED "${FOLDER}\msvbvm60.dll" "$SYSDIR\msvbvm60.dll" "$SYSDIR"
+
+ ;The files below will only be installed on Win9x/NT4
+
+ !insertmacro InstallLib REGDLL "${ALREADY_INSTALLED}" REBOOT_PROTECTED "${FOLDER}\olepro32.dll" "$SYSDIR\olepro32.dll" "$SYSDIR"
+ !insertmacro InstallLib REGDLL "${ALREADY_INSTALLED}" REBOOT_PROTECTED "${FOLDER}\comcat.dll" "$SYSDIR\comcat.dll" "$SYSDIR"
+ !insertmacro InstallLib DLL "${ALREADY_INSTALLED}" REBOOT_PROTECTED "${FOLDER}\asycfilt.dll" "$SYSDIR\asycfilt.dll" "$SYSDIR"
+ !insertmacro InstallLib TLB "${ALREADY_INSTALLED}" REBOOT_PROTECTED "${FOLDER}\stdole2.tlb" "$SYSDIR\stdole2.tlb" "$SYSDIR"
+
+ Push $R0
+
+ ${if} ${IsNT}
+ ${if} ${IsWinNT4}
+ ReadRegStr $R0 HKLM "System\CurrentControlSet\Control" "ProductOptions"
+ ${if} $R0 == "Terminal Server"
+ !insertmacro InstallLib REGDLL "${ALREADY_INSTALLED}" REBOOT_NOTPROTECTED "${FOLDER}\NT4TS\oleaut32.dll" "$SYSDIR\oleaut32.dll" "$SYSDIR"
+ ${else}
+ !insertmacro InstallLib REGDLL "${ALREADY_INSTALLED}" REBOOT_NOTPROTECTED "${FOLDER}\NT4\oleaut32.dll" "$SYSDIR\oleaut32.dll" "$SYSDIR"
+ ${endif}
+ ${endif}
+ ${else}
+ ;No Oleaut32.dll with the security update has been released for Windows 9x.
+ ;The NT4 version is used because NT4 and Win9x used to share the same 2.40 version
+ ;and version 2.40.4519.0 is reported to work fine on Win9x.
+ !insertmacro InstallLib REGDLL "${ALREADY_INSTALLED}" REBOOT_NOTPROTECTED "${FOLDER}\NT4\oleaut32.dll" "$SYSDIR\oleaut32.dll" "$SYSDIR"
+ ${endif}
+
+ Pop $R0
+
+!macroend
+
+!macro VB6RunTimeUnInstall
+
+ !insertmacro UnInstallLib REGDLL SHARED NOREMOVE "$SYSDIR\msvbvm60.dll"
+ !insertmacro UnInstallLib REGDLL SHARED NOREMOVE "$SYSDIR\oleaut32.dll"
+ !insertmacro UnInstallLib REGDLL SHARED NOREMOVE "$SYSDIR\olepro32.dll"
+ !insertmacro UnInstallLib REGDLL SHARED NOREMOVE "$SYSDIR\comcat.dll"
+ !insertmacro UnInstallLib DLL SHARED NOREMOVE "$SYSDIR\asycfilt.dll"
+ !insertmacro UnInstallLib TLB SHARED NOREMOVE "$SYSDIR\stdole2.tlb"
+
+!macroend
+
+!verbose pop
+!endif
diff --git a/installer/tools/Include/VPatchLib.nsh b/installer/tools/Include/VPatchLib.nsh
new file mode 100644
index 00000000..1e01bc8c
--- /dev/null
+++ b/installer/tools/Include/VPatchLib.nsh
@@ -0,0 +1,47 @@
+; PatchLib v3.0
+; =============
+;
+; Library with macro for use with VPatch (DLL version) in NSIS 2.0.5+
+; Created by Koen van de Sande
+
+!include LogicLib.nsh
+
+!macro VPatchFile PATCHDATA SOURCEFILE TEMPFILE
+
+ Push $1
+ Push $2
+ Push $3
+ Push $4
+
+ Push ${SOURCEFILE}
+ Push ${TEMPFILE}
+
+ Pop $2 # temp file
+ Pop $3 # source file
+
+ InitPluginsDir
+ GetTempFileName $1 $PLUGINSDIR
+ File /oname=$1 ${PATCHDATA}
+
+ vpatch::vpatchfile $1 $3 $2
+ Pop $4
+ DetailPrint $4
+
+ StrCpy $4 $4 2
+ ${Unless} $4 == "OK"
+ SetErrors
+ ${EndIf}
+
+ ${If} ${FileExists} $2
+ Delete $3
+ Rename /REBOOTOK $2 $3
+ ${EndIf}
+
+ Delete $1
+
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+
+!macroend
diff --git a/installer/tools/Include/Win/COM.nsh b/installer/tools/Include/Win/COM.nsh
new file mode 100644
index 00000000..3b2a0115
--- /dev/null
+++ b/installer/tools/Include/Win/COM.nsh
@@ -0,0 +1,392 @@
+/*
+-------------
+ COM.nsh
+-------------
+
+COM defines and helper macros
+
+; Example usage:
+!include LogicLib.nsh
+!include Win\COM.nsh
+!include Win\Propkey.nsh
+!insertmacro ComHlpr_CreateInProcInstance ${CLSID_ShellLink} ${IID_IShellLink} r0 ""
+${If} $0 P<> 0
+ ${IShellLink::SetPath} $0 '("%COMSPEC%").r1'
+ ${IShellLink::SetArguments} $0 '("/k echo HelloWorld").r2'
+ ${If} $1 = 0
+ ${AndIf} $2 = 0
+ ${IUnknown::QueryInterface} $0 '("${IID_IPropertyStore}",.r1)'
+ ${If} $1 P<> 0
+ System::Call '*${SYSSTRUCT_PROPERTYKEY}(${PKEY_AppUserModel_StartPinOption})p.r2'
+ System::Call '*${SYSSTRUCT_PROPVARIANT}(${VT_UI4},,&i4 ${APPUSERMODEL_STARTPINOPTION_NOPINONINSTALL})p.r3'
+ ${IPropertyStore::SetValue} $1 '($2,$3)'
+
+ ; Reuse the PROPERTYKEY & PROPVARIANT buffers to set another property
+ System::Call '*$2${SYSSTRUCT_PROPERTYKEY}(${PKEY_AppUserModel_ExcludeFromShowInNewInstall})'
+ System::Call '*$3${SYSSTRUCT_PROPVARIANT}(${VT_BOOL},,&i2 ${VARIANT_TRUE})'
+ ${IPropertyStore::SetValue} $1 '($2,$3)'
+
+ System::Free $2
+ System::Free $3
+ ${IPropertyStore::Commit} $1 ""
+ ${IUnknown::Release} $1 ""
+ ${EndIf}
+ ${IUnknown::QueryInterface} $0 '("${IID_IPersistFile}",.r1)'
+ ${If} $1 P<> 0
+ ${IPersistFile::Save} $1 '("$SMPrograms\nsis_test.lnk",1)'
+ ${IUnknown::Release} $1 ""
+ ${EndIf}
+ ${EndIf}
+ ${IUnknown::Release} $0 ""
+${EndIf}
+
+*/
+
+
+!ifndef __WIN_COM__INC
+!define __WIN_COM__INC ${NSIS_CHAR_SIZE}
+!verbose push
+!verbose 3
+
+!define /ifndef STGM_READ 0
+!define /ifndef STGM_WRITE 1
+!define /ifndef STGM_READWRITE 2
+!define /ifndef STGM_SHARE_DENY_NONE 0x00000040
+!define /ifndef STGM_SHARE_DENY_READ 0x00000030
+!define /ifndef STGM_SHARE_DENY_WRITE 0x00000020
+!define /ifndef STGM_SHARE_EXCLUSIVE 0x00000010
+!define /ifndef STGM_PRIORITY 0x00040000
+!define /ifndef STGM_CREATE 0x00001000
+!define /ifndef STGM_CONVERT 0x00020000
+!define /ifndef STGM_FAILIFTHERE 0
+!define /ifndef STGM_DELETEONRELEASE 0x04000000
+
+!define /ifndef CLSCTX_INPROC_SERVER 0x1
+!define /ifndef CLSCTX_INPROC_HANDLER 0x2
+!define /ifndef CLSCTX_LOCAL_SERVER 0x4
+!define /ifndef CLSCTX_REMOTE_SERVER 0x10
+!define /ifndef CLSCTX_ACTIVATE_32_BIT_SERVER 0x40000
+!define /ifndef CLSCTX_ACTIVATE_64_BIT_SERVER 0x80000
+!define /ifndef CLSCTX_ENABLE_CLOAKING 0x100000
+
+!define NSISCOMCALL "!insertmacro NSISCOMCALL "
+!macro NSISCOMCALL vtblidx decl ptr params
+!if ${NSIS_CHAR_SIZE} <> ${__WIN_COM__INC}
+; Warn if QueryInterface() for IID_IShellLink etc will return the wrong interface
+!warning "NSIS_CHAR_SIZE changed, existing defines and macros might not work correctly!"
+!endif
+System::Call `${ptr}->${vtblidx}${decl}${params}`
+!macroend
+!define NSISCOMIFACEDECL "!insertmacro NSISCOMIFACEDECL "
+!macro NSISCOMIFACEDECL iface method vtblidx decl
+!define ${iface}::${method} `${NSISCOMCALL} ${vtblidx} ${decl} `
+!macroend
+
+!macro ComHlpr_CreateInstance clsid iid sysoutvarIFacePtr sysret
+System::Call 'OLE32::CoCreateInstance(g"${clsid}",i0,i23,g"${iid}",*p.${sysoutvarIFacePtr})i${sysret}'
+!macroend
+!macro ComHlpr_CreateInProcInstance clsid iid sysoutvarIFacePtr sysret
+System::Call 'OLE32::CoCreateInstance(g"${clsid}",i0,i${CLSCTX_INPROC_SERVER},g"${iid}",*p.${sysoutvarIFacePtr})i${sysret}'
+!macroend
+
+!macro ComHlpr_SafeRelease _p
+${If} ${_p} P<> 0
+ ${IUnknown::Release} ${_p} ""
+${EndIf}
+!macroend
+!macro ComHlpr_SafeReleaseAndNull _p
+${If} ${_p} P<> 0
+ ${IUnknown::Release} ${_p} ""
+ StrCpy ${_p} 0
+${EndIf}
+!macroend
+
+
+!ifndef IID_IUnknown
+!define IID_IUnknown {00000000-0000-0000-C000-000000000046}
+${NSISCOMIFACEDECL}IUnknown QueryInterface 0 (g,*p)i
+${NSISCOMIFACEDECL}IUnknown AddRef 1 ()i
+${NSISCOMIFACEDECL}IUnknown Release 2 ()i
+!endif
+
+!ifndef IID_IPersist
+!define IID_IPersist {0000010c-0000-0000-C000-000000000046}
+${NSISCOMIFACEDECL}IPersist GetClassID 3 (g)i
+!endif
+
+!ifndef IID_IPersistStream
+!define IID_IPersistStream {00000109-0000-0000-C000-000000000046} ; IPersist>
+${NSISCOMIFACEDECL}IPersistStream IsDirty 4 ()i
+${NSISCOMIFACEDECL}IPersistStream Load 5 (p,i)i
+${NSISCOMIFACEDECL}IPersistStream Save 6 (p,i)i
+${NSISCOMIFACEDECL}IPersistStream GetSizeMax 7 (*l)i
+!endif
+!ifndef IID_IPersistStreamInit
+!define IID_IPersistStreamInit {7FD52380-4E07-101B-AE2D-08002B2EC713} ; IPersist>
+${NSISCOMIFACEDECL}IPersistStreamInit IsDirty 4 ()i
+${NSISCOMIFACEDECL}IPersistStreamInit Load 5 (p,i)i
+${NSISCOMIFACEDECL}IPersistStreamInit Save 6 (p,i)i
+${NSISCOMIFACEDECL}IPersistStreamInit GetSizeMax 7 (*l)i
+${NSISCOMIFACEDECL}IPersistStreamInit InitNew 8 ()i
+!endif
+
+!ifndef IID_IPersistFile
+!define IID_IPersistFile {0000010b-0000-0000-C000-000000000046} ; IPersist>
+${NSISCOMIFACEDECL}IPersistFile IsDirty 4 ()i
+${NSISCOMIFACEDECL}IPersistFile Load 5 (w,i)i
+${NSISCOMIFACEDECL}IPersistFile Save 6 (w,i)i
+${NSISCOMIFACEDECL}IPersistFile SaveCompleted 7 (w)i
+${NSISCOMIFACEDECL}IPersistFile GetCurFile 8 (*w)i
+!endif
+
+!ifndef CLSID_ShellLink
+!define CLSID_ShellLink {00021401-0000-0000-c000-000000000046}
+!endif
+!ifndef IID_IShellLink
+!define IID_IShellLinkA {000214ee-0000-0000-c000-000000000046}
+!define IID_IShellLinkW {000214f9-0000-0000-c000-000000000046}
+!ifdef NSIS_UNICODE
+!define IID_IShellLink ${IID_IShellLinkW}
+!else
+!define IID_IShellLink ${IID_IShellLinkA}
+!endif
+${NSISCOMIFACEDECL}IShellLink GetPath 3 (t,i,p,i)i
+${NSISCOMIFACEDECL}IShellLink GetIDList 4 (*p)i
+${NSISCOMIFACEDECL}IShellLink SetIDList 5 (p)i
+${NSISCOMIFACEDECL}IShellLink GetDescription 6 (t,i)i
+${NSISCOMIFACEDECL}IShellLink SetDescription 7 (t)i
+${NSISCOMIFACEDECL}IShellLink GetWorkingDirectory 8 (t,i)i
+${NSISCOMIFACEDECL}IShellLink SetWorkingDirectory 9 (t)i
+${NSISCOMIFACEDECL}IShellLink GetArguments 10 (t,i)i
+${NSISCOMIFACEDECL}IShellLink SetArguments 11 (t)i
+${NSISCOMIFACEDECL}IShellLink GetHotkey 12 (*i0)i
+${NSISCOMIFACEDECL}IShellLink SetHotkey 13 (&i2)i
+${NSISCOMIFACEDECL}IShellLink GetShowCmd 14 (*i)i
+${NSISCOMIFACEDECL}IShellLink SetShowCmd 15 (i)i
+${NSISCOMIFACEDECL}IShellLink GetIconLocation 16 (t,i,*i)i
+${NSISCOMIFACEDECL}IShellLink SetIconLocation 17 (t,i)i
+${NSISCOMIFACEDECL}IShellLink SetRelativePath 18 (t,i)i
+${NSISCOMIFACEDECL}IShellLink Resolve 19 (p,i)i
+${NSISCOMIFACEDECL}IShellLink SetPath 20 (t)i
+!endif
+
+!ifndef IID_IShellLinkDataList
+!define IID_IShellLinkDataList {45e2b4ae-b1c3-11d0-b92f-00a0c90312e1}
+${NSISCOMIFACEDECL}IShellLinkDataList AddDataBlock 3 (p)i
+${NSISCOMIFACEDECL}IShellLinkDataList CopyDataBlock 4 (i,*p)i
+${NSISCOMIFACEDECL}IShellLinkDataList RemoveDataBlock 5 (i)i
+${NSISCOMIFACEDECL}IShellLinkDataList GetFlags 6 (*i)i
+${NSISCOMIFACEDECL}IShellLinkDataList SetFlags 7 (i)i
+!endif
+!define /ifndef EXP_SZ_LINK_SIG 0xA0000001
+!define /ifndef NT_CONSOLE_PROPS_SIG 0xA0000002
+!define /ifndef NT_FE_CONSOLE_PROPS_SIG 0xA0000004
+!define /ifndef EXP_SPECIAL_FOLDER_SIG 0xA0000005
+!define /ifndef EXP_DARWIN_ID_SIG 0xA0000006
+!define /ifndef EXP_SZ_ICON_SIG 0xA0000007
+!define /ifndef EXP_PROPERTYSTORAGE_SIG 0xA0000009
+;SHELL_LINK_DATA_FLAGS
+!define /ifndef SLDF_HAS_ID_LIST 0x00000001
+!define /ifndef SLDF_HAS_LINK_INFO 0x00000002
+!define /ifndef SLDF_HAS_NAME 0x00000004
+!define /ifndef SLDF_HAS_RELPATH 0x00000008
+!define /ifndef SLDF_HAS_WORKINGDIR 0x00000010
+!define /ifndef SLDF_HAS_ARGS 0x00000020
+!define /ifndef SLDF_HAS_ICONLOCATION 0x00000040
+!define /ifndef SLDF_UNICODE 0x00000080
+!define /ifndef SLDF_FORCE_NO_LINKINFO 0x00000100
+!define /ifndef SLDF_HAS_EXP_SZ 0x00000200
+!define /ifndef SLDF_RUN_IN_SEPARATE 0x00000400
+!define /ifndef SLDF_HAS_LOGO3ID 0x00000800
+!define /ifndef SLDF_HAS_DARWINID 0x00001000
+!define /ifndef SLDF_RUNAS_USER 0x00002000
+!define /ifndef SLDF_HAS_EXP_ICON_SZ 0x00004000
+!define /ifndef SLDF_NO_PIDL_ALIAS 0x00008000
+!define /ifndef SLDF_FORCE_UNCNAME 0x00010000
+!define /ifndef SLDF_RUN_WITH_SHIMLAYER 0x00020000
+!define /ifndef SLDF_FORCE_NO_LINKTRACK 0x00040000 ;[Vista+]
+!define /ifndef SLDF_ENABLE_TARGET_METADATA 0x00080000
+!define /ifndef SLDF_DISABLE_LINK_PATH_TRACKING 0x00100000 ;[Seven+]
+!define /ifndef SLDF_DISABLE_KNOWNFOLDER_RELATIVE_TRACKING 0x00200000
+!define /ifndef SLDF_NO_KF_ALIAS 0x00400000
+!define /ifndef SLDF_ALLOW_LINK_TO_LINK 0x00800000
+!define /ifndef SLDF_UNALIAS_ON_SAVE 0x01000000
+!define /ifndef SLDF_PREFER_ENVIRONMENT_PATH 0x02000000
+!define /ifndef SLDF_KEEP_LOCAL_IDLIST_FOR_UNC_TARGET 0x04000000
+!define /ifndef SLDF_PERSIST_VOLUME_ID_RELATIVE 0x08000000 ;[Eight+]
+
+!ifndef IID_IShellItem
+!define IID_IShellItem {43826d1e-e718-42ee-bc55-a1e261c37bfe}
+${NSISCOMIFACEDECL}IShellItem BindToHandler 3 (p,g,g,*p)i
+${NSISCOMIFACEDECL}IShellItem GetParent 4 (*p)i
+${NSISCOMIFACEDECL}IShellItem GetDisplayName 5 (i,*p)i
+${NSISCOMIFACEDECL}IShellItem GetAttributes 6 (i,*i)i
+${NSISCOMIFACEDECL}IShellItem Compare 7 (p,i,*i)i
+!endif
+
+!ifndef CLSID_StartMenuPin
+!define CLSID_StartMenuPin {a2a9545d-a0c2-42b4-9708-a0b2badd77c8}
+!endif
+!ifndef IID_IStartMenuPinnedList
+!define IID_IStartMenuPinnedList {4CD19ADA-25A5-4A32-B3B7-347BEE5BE36B}
+${NSISCOMIFACEDECL}IStartMenuPinnedList RemoveFromList 3 (p)i
+!endif
+
+!ifndef CLSID_ApplicationDestinations
+!define CLSID_ApplicationDestinations {86c14003-4d6b-4ef3-a7b4-0506663b2e68}
+!endif
+!ifndef IID_IApplicationDestinations
+!define IID_IApplicationDestinations {12337D35-94C6-48A0-BCE7-6A9C69D4D600} ;[Seven+]
+${NSISCOMIFACEDECL}IApplicationDestinations SetAppID 3 (w)i
+${NSISCOMIFACEDECL}IApplicationDestinations RemoveDestination 4 (p)i ; IShellItem or IShellLink
+${NSISCOMIFACEDECL}IApplicationDestinations RemoveAllDestinations 5 ()i
+!endif
+
+!ifndef CLSID_DestinationList
+!define CLSID_DestinationList {77f10cf0-3db5-4966-b520-b7c54fd35ed6}
+!endif
+!ifndef IID_ICustomDestinationList
+!define IID_ICustomDestinationList {6332debf-87b5-4670-90c0-5e57b408a49e} ;[Seven+]
+${NSISCOMIFACEDECL}ICustomDestinationList SetAppID 3 (w)i
+${NSISCOMIFACEDECL}ICustomDestinationList BeginList 4 (*i,g,*p)i ; IObjectArray or IEnumObjects
+${NSISCOMIFACEDECL}ICustomDestinationList AppendCategory 5 (w,p)i ; IObjectArray*
+${NSISCOMIFACEDECL}ICustomDestinationList AppendKnownCategory 6 (i)i
+${NSISCOMIFACEDECL}ICustomDestinationList AddUserTasks 7 (p)i ; IObjectArray*
+${NSISCOMIFACEDECL}ICustomDestinationList CommitList 8 ()i
+${NSISCOMIFACEDECL}ICustomDestinationList GetRemovedDestinations 9 (g,*p)i ; IObjectCollection
+${NSISCOMIFACEDECL}ICustomDestinationList DeleteList 10 (w)i
+${NSISCOMIFACEDECL}ICustomDestinationList AbortList 11 ()i
+!endif
+
+!ifndef CLSID_EnumerableObjectCollection
+!define CLSID_EnumerableObjectCollection {2d3468c1-36a7-43b6-ac24-d3f02fd9607a}
+!endif
+!ifndef IID_IObjectArray
+!define IID_IObjectArray {92CA9DCD-5622-4bba-A805-5E9F541BD8C9}
+${NSISCOMIFACEDECL}IObjectArray GetCount 3 (*i)i
+${NSISCOMIFACEDECL}IObjectArray GetAt 4 (i,g,*p)i
+!endif
+
+!ifndef IID_IObjectCollection
+!define IID_IObjectCollection {5632b1a4-e38a-400a-928a-d4cd63230295} ; IObjectArray>
+${NSISCOMIFACEDECL}IObjectCollection AddObject 5 (p)i ; IUnknown*
+${NSISCOMIFACEDECL}IObjectCollection AddFromArray 6 (p)i ; IObjectArray*
+${NSISCOMIFACEDECL}IObjectCollection RemoveObjectAt 7 (i)i
+${NSISCOMIFACEDECL}IObjectCollection Clear 8 ()i
+!endif
+
+!ifndef IID_IEnumObjects
+!define IID_IEnumObjects {2c1c7e2e-2d0e-4059-831e-1e6f82335c2e}
+${NSISCOMIFACEDECL}IEnumObjects Next 3 (i,g,*p,*i)i
+${NSISCOMIFACEDECL}IEnumObjects Skip 4 (i)i
+${NSISCOMIFACEDECL}IEnumObjects Reset 5 ()i
+${NSISCOMIFACEDECL}IEnumObjects Clone 6 (*p)i
+!endif
+
+!ifndef IID_IEnumUnknown
+!define IID_IEnumUnknown {00000100-0000-0000-C000-000000000046}
+${NSISCOMIFACEDECL}IEnumUnknown Next 3 (i,*p,*i)i
+${NSISCOMIFACEDECL}IEnumUnknown Skip 4 (i)i
+${NSISCOMIFACEDECL}IEnumUnknown Reset 5 ()i
+${NSISCOMIFACEDECL}IEnumUnknown Clone 6 (*p)i
+!endif
+
+!ifndef IID_IPropertyStore
+!define IID_IPropertyStore {886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99}
+${NSISCOMIFACEDECL}IPropertyStore GetCount 3 (*i)i
+${NSISCOMIFACEDECL}IPropertyStore GetAt 4 (i,p)i
+${NSISCOMIFACEDECL}IPropertyStore GetValue 5 (p,p)i
+${NSISCOMIFACEDECL}IPropertyStore SetValue 6 (p,p)i
+${NSISCOMIFACEDECL}IPropertyStore Commit 7 ()i
+!endif
+
+!ifndef IID_IPropertyStorage
+!define IID_IPropertyStorage {00000138-0000-0000-C000-000000000046}
+${NSISCOMIFACEDECL}IPropertyStorage ReadMultiple 3 (i,p,p)i
+${NSISCOMIFACEDECL}IPropertyStorage WriteMultiple 4 (i,p,p,i)i
+${NSISCOMIFACEDECL}IPropertyStorage DeleteMultiple 5 (i,p)i
+${NSISCOMIFACEDECL}IPropertyStorage ReadPropertyNames 6 (p,p)i
+${NSISCOMIFACEDECL}IPropertyStorage WritePropertyNames 7 (i,p,p)i
+${NSISCOMIFACEDECL}IPropertyStorage DeletePropertyNames 8 (i,p)i
+${NSISCOMIFACEDECL}IPropertyStorage Commit 9 (i)i ; Note: Some implementations might return E_NOTIMPL
+${NSISCOMIFACEDECL}IPropertyStorage Revert 10 ()i
+${NSISCOMIFACEDECL}IPropertyStorage Enum 11 (*p)i
+${NSISCOMIFACEDECL}IPropertyStorage SetTimes 12 (p,p,p)i
+${NSISCOMIFACEDECL}IPropertyStorage SetClass 13 (g)i
+${NSISCOMIFACEDECL}IPropertyStorage Stat 14 (p)i
+!endif
+
+!ifndef IID_IPropertySetStorage
+!define IID_IPropertySetStorage {0000013A-0000-0000-C000-000000000046}
+${NSISCOMIFACEDECL}IPropertySetStorage Create 3 (g,g,i,i,*p)i
+${NSISCOMIFACEDECL}IPropertySetStorage Open 4 (g,i,*p)i
+${NSISCOMIFACEDECL}IPropertySetStorage Delete 5 (g)i
+${NSISCOMIFACEDECL}IPropertySetStorage Enum 6 (*p)i
+!endif
+
+!ifndef CLSID_ApplicationAssociationRegistration
+!define CLSID_ApplicationAssociationRegistration {591209c7-767b-42b2-9fba-44ee4615f2c7}
+!endif
+!ifndef IID_IApplicationAssociationRegistration
+!define IID_IApplicationAssociationRegistration {4e530b0a-e611-4c77-a3ac-9031d022281b} ;[Vista+]
+${NSISCOMIFACEDECL}IApplicationAssociationRegistration QueryCurrentDefault 3 (w,i,i,*p)i
+${NSISCOMIFACEDECL}IApplicationAssociationRegistration QueryAppIsDefault 4 (w,i,i,w,*i)i
+${NSISCOMIFACEDECL}IApplicationAssociationRegistration QueryAppIsDefaultAll 5 (i,w,*i)i
+${NSISCOMIFACEDECL}IApplicationAssociationRegistration SetAppAsDefault 6 (w,w,i)i
+${NSISCOMIFACEDECL}IApplicationAssociationRegistration SetAppAsDefaultAll 7 (w)i
+${NSISCOMIFACEDECL}IApplicationAssociationRegistration ClearUserAssociations 8 ()i
+!endif
+!ifndef CLSID_ApplicationAssociationRegistrationUI
+!define CLSID_ApplicationAssociationRegistrationUI {1968106d-f3b5-44cf-890e-116fcb9ecef1}
+!endif
+!ifndef IID_IApplicationAssociationRegistrationUI
+!define IID_IApplicationAssociationRegistrationUI {1f76a169-f994-40ac-8fc8-0959e8874710} ;[Vista+]
+${NSISCOMIFACEDECL}IApplicationAssociationRegistrationUI LaunchAdvancedAssociationUI 3 (w)i
+!endif
+
+!ifndef CLSID_GameExplorer
+!define CLSID_GameExplorer {9A5EA990-3034-4D6F-9128-01F3C61022BC}
+!endif
+!ifndef IID_IGameExplorer
+!define IID_IGameExplorer {E7B2FB72-D728-49B3-A5F2-18EBF5F1349E} ;[Vista+]
+${NSISCOMIFACEDECL}IGameExplorer AddGame 3 (p,p,i,g)i
+${NSISCOMIFACEDECL}IGameExplorer RemoveGame 4 (i,i,i,i)i ; The parameter is a GUID, not REFGUID so the 'g' type cannot be used!
+${NSISCOMIFACEDECL}IGameExplorer UpdateGame 5 (i,i,i,i)i
+${NSISCOMIFACEDECL}IGameExplorer VerifyAccess 6 (p,*i)i
+!endif
+!define /ifndef GIS_NOT_INSTALLED 1
+!define /ifndef GIS_CURRENT_USER 2
+!define /ifndef GIS_ALL_USERS 3
+!ifndef IID_IGameExplorer2
+!define IID_IGameExplorer2 {86874AA7-A1ED-450d-A7EB-B89E20B2FFF3} ;[Seven+]
+${NSISCOMIFACEDECL}IGameExplorer2 InstallGame 3 (w,w,i)i
+${NSISCOMIFACEDECL}IGameExplorer2 UninstallGame 4 (w)i
+${NSISCOMIFACEDECL}IGameExplorer2 CheckAccess 5 (w,*i)i
+!endif
+!ifndef CLSID_GameStatistics
+!define CLSID_GameStatistics {DBC85A2C-C0DC-4961-B6E2-D28B62C11AD4}
+!endif
+!ifndef IID_IGameStatisticsMgr
+!define IID_IGameStatisticsMgr {AFF3EA11-E70E-407d-95DD-35E612C41CE2} ;[Seven+]
+${NSISCOMIFACEDECL}IGameStatisticsMgr GetGameStatistics 3 (w,i,*i,*p)i
+${NSISCOMIFACEDECL}IGameStatisticsMgr RemoveGameStatistics 4 (w)i
+!endif
+
+!ifndef CLSID_InternetShortcut
+!define CLSID_InternetShortcut {FBF23B40-E3F0-101B-8488-00AA003E56F8}
+!endif
+!ifndef IID_IUniformResourceLocator
+!define IID_IUniformResourceLocatorA {FBF23B80-E3F0-101B-8488-00AA003E56F8}
+!define IID_IUniformResourceLocatorW {CABB0DA0-DA57-11CF-9974-0020AFD79762}
+!ifdef NSIS_UNICODE
+!define IID_IUniformResourceLocator ${IID_IUniformResourceLocatorW}
+!else
+!define IID_IUniformResourceLocator ${IID_IUniformResourceLocatorA}
+!endif
+${NSISCOMIFACEDECL}IUniformResourceLocator SetURL 3 (t,i)i
+${NSISCOMIFACEDECL}IUniformResourceLocator GetURL 4 (*p)i
+${NSISCOMIFACEDECL}IUniformResourceLocator InvokeCommand 5 (p)i
+!endif
+
+!verbose pop
+!endif /* __WIN_COM__INC */
diff --git a/installer/tools/Include/Win/Propkey.nsh b/installer/tools/Include/Win/Propkey.nsh
new file mode 100644
index 00000000..6d61d9a7
--- /dev/null
+++ b/installer/tools/Include/Win/Propkey.nsh
@@ -0,0 +1,216 @@
+!ifndef __WIN_PROPKEY__INC
+!define __WIN_PROPKEY__INC
+!verbose push
+!verbose 3
+
+
+/**************************************************
+WTypes.h
+**************************************************/
+;NOTE: This list is incomplete
+!define VT_EMPTY 0
+!define VT_NULL 1
+!define VT_I2 2
+!define VT_I4 3
+!define VT_BSTR 8
+!define VT_BOOL 11
+!define VT_I1 16
+!define VT_UI1 17
+!define VT_UI2 18
+!define VT_UI4 19
+!define VT_I8 20
+!define VT_UI8 21
+!define VT_INT 22
+!define VT_UINT 23
+!define VT_HRESULT 25
+!define VT_PTR 26
+!define VT_SAFEARRAY 27
+!define VT_LPSTR 30 ; SHStrDupA
+!define VT_LPWSTR 31 ; SHStrDupW
+!define VT_FILETIME 64
+!define VT_STREAM 66
+!define VT_CLSID 72 ; Pointer to CoTaskMem allocated GUID
+!define VT_TYPEMASK 0xFFF
+!define VT_VECTOR 0x1000
+!define VT_ARRAY 0x2000
+!define VT_BYREF 0x4000
+
+!define /ifndef VARIANT_TRUE -1
+!define /ifndef VARIANT_FALSE 0
+
+!define SYSSIZEOF_PROPERTYKEY 20
+!define SYSSTRUCT_PROPERTYKEY (&g16,&i4) ;System.dll is buggy when it comes to g and forces us to specify the size
+
+!define STGC_DEFAULT 0
+!define STGC_OVERWRITE 1
+!define STGC_ONLYIFCURRENT 2
+!define STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE 4
+!define STGC_CONSOLIDATE 8
+
+
+/**************************************************
+OAIdl.h
+**************************************************/
+!if "${NSIS_PTR_SIZE}" > 4
+!define SYSSIZEOF_VARIANT 24
+!define SYSSTRUCT_VARIANT (&i2,&i6,&i8,&i8)
+!else
+!define SYSSIZEOF_VARIANT 16
+!define SYSSTRUCT_VARIANT (&i2,&i6,&i8)
+!endif
+
+
+/**************************************************
+PropIdl.h
+**************************************************/
+!if "${NSIS_PTR_SIZE}" > 4
+!define SYSSIZEOF_PROPVARIANT 24
+!define SYSSTRUCT_PROPVARIANT (&i2,&i6,&i8,&i8)
+!else
+!define SYSSIZEOF_PROPVARIANT 16
+!define SYSSTRUCT_PROPVARIANT (&i2,&i6,&i8)
+!endif
+
+!define PRSPEC_LPWSTR 0
+!define PRSPEC_PROPID 1
+!define SYSSTRUCT_PROPSPEC (p,p)
+
+
+/**************************************************
+Propkey.h
+**************************************************/
+!define PKEY_AppUserModel_RelaunchCommand '"{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}",2' ; VT_LPWSTR (SHGetPropertyStoreForWindow)
+!define PKEY_AppUserModel_RelaunchIconResource '"{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}",3' ; VT_LPWSTR (SHGetPropertyStoreForWindow, optional. Path to icon or module, with resource ID or index.)
+!define PKEY_AppUserModel_RelaunchDisplayNameResource '"{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}",4' ; VT_LPWSTR (SHGetPropertyStoreForWindow. @ style indirect resource string or a plain string.)
+!define PKEY_AppUserModel_ID '"{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}",5' ; VT_LPWSTR
+!define PKEY_AppUserModel_IsDestListSeparator '"{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}",6' ; VT_BOOL
+!define PKEY_AppUserModel_ExcludeFromShowInNewInstall '"{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}",8' ; VT_BOOL
+!define PKEY_AppUserModel_PreventPinning '"{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}",9' ; VT_BOOL
+!define PKEY_AppUserModel_IsDualMode '"{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}",11' ; [Eight+] VT_BOOL
+!define APPUSERMODEL_STARTPINOPTION_NOPINONINSTALL 1
+!define APPUSERMODEL_STARTPINOPTION_USERPINNED 2
+!define PKEY_AppUserModel_StartPinOption '"{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}",12' ; [Eight+] VT_UI4
+!define PKEY_AppUserModel_ToastActivatorCLSID '"{9F4C2855-9F79-4B39-A8D0-E1D42DE1D5F3}",26' ; [10FU1507+] VT_CLSID
+!define PKEY_EdgeGesture_DisableTouchWhenFullscreen '"{32CE38B2-2C9A-41B1-9BC5-B3784394AA44}",2' ; [Eight+] VT_BOOL (SHGetPropertyStoreForWindow)
+
+
+/**************************************************
+ShlGuid.h & ShlObj.h
+**************************************************/
+!define FMTID_Intshcut {000214A0-0000-0000-C000-000000000046}
+!define PID_IS_URL 2 ; VT_LPWSTR
+!define PID_IS_HOTKEY 6 ; VT_UI2
+!define PID_IS_ICONINDEX 8 ; VT_I4
+!define PID_IS_ICONFILE 9 ; VT_LPWSTR
+!define PKEY_Intshcut_Url '"${FMTID_Intshcut}",${PID_IS_URL}' ; Undocumented
+!define FMTID_InternetSite {000214A1-0000-0000-C000-000000000046}
+!define PID_INTSITE_LASTVISIT 4 ; VT_FILETIME
+!define PID_INTSITE_VISITCOUNT 6 ; VT_UI4
+
+
+/**************************************************
+Helper macros
+**************************************************/
+!define V_GetVT '!insertmacro V_GetVT '
+!macro V_GetVT pPV sysdst
+System::Call '*${pPV}(&i2.${sysdst})'
+!macroend
+!define V_SetVT '!insertmacro V_SetVT '
+!macro V_SetVT pPV syssrc
+System::Call '*${pPV}(&i2 ${syssrc})'
+!macroend
+!macro V_GetHelper sysvaltyp pPV sysdst
+System::Call '*${pPV}(l,${sysvaltyp}.${sysdst})'
+!macroend
+!macro V_GenericSetHelper sysvaltyp pPV VT syssrc
+!if "${VT}" != "" ; Setting the VT is optional
+ System::Call '*${pPV}(&i2 ${VT},&i6,${sysvaltyp}${syssrc})'
+!else
+ System::Call '*${pPV}(l,${sysvaltyp}${syssrc})'
+!endif
+!macroend
+!macro V_SpecificSetHelper VT sysvaltyp pPV syssrc
+System::Call '*${pPV}(&i2 ${VT},&i6,${sysvaltyp}${syssrc})'
+!macroend
+!macro Make_V_GetterSetter name sysvaltyp setsep
+!define V_Get${name} '!insertmacro V_GetHelper "${sysvaltyp}" '
+!ifdef VT_${name}
+ !define V_Set${name} '!insertmacro V_SpecificSetHelper ${VT_${name}} "${sysvaltyp}${setsep}" '
+!else
+ !define V_Set${name} '!insertmacro V_GenericSetHelper "${sysvaltyp}${setsep}" '
+!endif
+!macroend
+!insertmacro Make_V_GetterSetter Int8 "&i1" " " ; Generic
+!insertmacro Make_V_GetterSetter Int16 "&i2" " " ; Generic
+!insertmacro Make_V_GetterSetter Int32 "i" "" ; Generic
+!insertmacro Make_V_GetterSetter Int64 "l" "" ; Generic
+!insertmacro Make_V_GetterSetter Pointer "p" "" ; Generic
+!insertmacro Make_V_GetterSetter I4 "i" " "
+!insertmacro Make_V_GetterSetter BOOL "&i2" " "
+!insertmacro Make_V_GetterSetter FILETIME "l" ""
+
+!macro VariantInit pV
+${V_SetVT} ${pV} ${VT_EMPTY}
+!macroend
+!macro VariantClear pV
+System::Call 'OLEAUT32::#9(p${pV})'
+!macroend
+!macro VariantCopy pDstV pSrcV sysretHR
+System::Call 'OLEAUT32::#10(p${pDstV},p${pSrcV})i.${sysretHR}' ; (Frees the destination variant before it copies the source)
+!macroend
+!macro VariantCopyInd pDstV pSrcV sysretHR
+System::Call 'OLEAUT32::#11(p${pDstV},p${pSrcV})i.${sysretHR}' ; (Frees the destination variant before it copies the source)
+!macroend
+!macro VariantChangeType pDstV pSrcV Flags VT sysretHR
+System::Call 'OLEAUT32::#12(p${pDstV},p${pSrcV},i${Flags},i${VT})i.${sysretHR}' ; (Might free the destination on success)
+!macroend
+
+
+!macro PropVariantClear pPV
+System::Call 'OLE32::PropVariantClear(p${pPV})' ; WinNT4.SP0+, Win98+, IE4+
+!macroend
+!macro PropVariantCopy pDstPV pSrcPV sysretHR
+System::Call 'OLE32::PropVariantCopy(p${pDstPV},p${pSrcPV})i.${sysretHR}' ; WinNT4.SP0+, Win98+, IE4+ (Does NOT free the destination before it copies the source)
+!macroend
+!macro PropVariantChangeType pDstPV pSrcPV VT sysretHR
+!ifdef NSIS_ARM | NSIS_ARM32 | NSIS_ARMNT | NSIS_ARM64
+ System::Call 'PROPSYS::PropVariantChangeType(p${pDstPV},p${pSrcPV},i0,i${VT})i.${sysretHR}'
+!else
+ Push "${VT}"
+ Push ${pSrcPV}
+ Push ${pDstPV}
+ !include Util.nsh
+ ${CallArtificialFunction} TryPropVariantChangeType
+ System::Call 'KERNEL32::SetLastError(is${sysretHR})' ; A hack to move the result from the stack to somewhere with System variable syntax
+!endif
+!macroend
+!macro TryPropVariantChangeType
+System::Store S
+System::Call 'PROPSYS::PropVariantChangeType(psr1,psr2,i0,isr3)i.r0' ; Vista+ (Source and destination cannot be the same address)
+StrCmp $0 error "" done
+System::Call 'OLE32::PropVariantChangeType(pr1,pr2,i0,i0,ir3})i.r0' ; 2000+ (Source and destination cannot be the same address)
+!if ${NSIS_PTR_SIZE} < 8
+ StrCmp $0 error "" done
+ !insertmacro VariantChangeType $1 $2 0 $3 r0 ; This is not really correct but there is no PROPVARIANT support on these platforms. Might free the destination!
+!endif
+done:
+Push $0
+System::Store L
+!macroend
+
+
+!macro IPropertyStorage_ReadPropById pPS ID pPV sysoutHR
+System::Call '*(p${PRSPEC_PROPID},p${ID})p.s'
+${IPropertyStorage::ReadMultiple} ${pPS} '(1,pss,p${pPV})${sysoutHR}'
+System::Free
+!macroend
+
+!macro IPropertyStorage_WritePropById pPS ID pPV sysoutHR
+System::Call '*(p${PRSPEC_PROPID},p${ID})p.s'
+${IPropertyStorage::WriteMultiple} ${pPS} '(1,pss,p${pPV},2)${sysoutHR}'
+System::Free
+!macroend
+
+
+!verbose pop
+!endif /* __WIN_PROPKEY__INC */
diff --git a/installer/tools/Include/Win/RestartManager.nsh b/installer/tools/Include/Win/RestartManager.nsh
new file mode 100644
index 00000000..6557b7d4
--- /dev/null
+++ b/installer/tools/Include/Win/RestartManager.nsh
@@ -0,0 +1,117 @@
+!ifndef __WIN_RESTARTMANAGER__INC
+!define __WIN_RESTARTMANAGER__INC 1
+
+/**************************************************
+WinBase.h
+**************************************************/
+!define /IfNDef RESTART_MAX_CMD_LINE 1024
+
+!define /IfNDef RESTART_NO_CRASH 1
+!define /IfNDef RESTART_NO_HANG 2
+!define /IfNDef RESTART_NO_PATCH 4
+!define /IfNDef RESTART_NO_REBOOT 8 ; Do not restart the process when the system is rebooted due to patch installations
+
+!define /IfNDef RECOVERY_DEFAULT_PING_INTERVAL 5000
+!define /IfNDef /math RECOVERY_MAX_PING_INTERVAL 5000 * 60
+
+
+/**************************************************
+RestartManager.h
+**************************************************/
+!define RM_SESSION_KEY_LEN 16
+!define CCH_RM_SESSION_KEY 32
+!define CCH_RM_MAX_APP_NAME 255
+!define CCH_RM_MAX_SVC_NAME 63
+!define RM_INVALID_TS_SESSION -1
+!define RM_INVALID_PROCESS -1
+
+!define RmUnknownApp 0
+!define RmMainWindow 1
+!define RmOtherWindow 2
+!define RmService 3
+!define RmExplorer 4
+!define RmConsole 5
+!define RmCritical 1000 ; Application is critical system process where a reboot is required to restart
+
+!define RmForceShutdown 0x1 ; Force unresponsive applications and services to shut down after the timeout period
+!define RmShutdownOnlyRegistered 0x10 ; Only shutdown apps if all apps registered for restart (RegisterApplicationRestart)
+
+!define RmStatusUnknown 0
+!define RmStatusRunning 1
+!define RmStatusStopped 2 ; Application stopped by Restart Manager
+!define RmStatusStoppedOther 4
+!define RmStatusRestarted 8
+!define RmStatusErrorOnStop 0x10
+!define RmStatusErrorOnRestart 0x20
+!define RmStatusShutdownMasked 0x40
+!define RmStatusRestartMasked 0x80
+
+!define RmRebootReasonNone 0
+!define RmRebootReasonPermissionDenied 1
+!define RmRebootReasonSessionMismatch 2
+!define RmRebootReasonCriticalProcess 4
+!define RmRebootReasonCriticalService 8
+!define RmRebootReasonDetectedSelf 0x10
+
+
+!define SYSSIZEOF_RM_UNIQUE_PROCESS 12
+!define SYSSTRUCT_RM_UNIQUE_PROCESS (i,l)
+
+
+!include LogicLib.nsh
+!include Util.nsh
+
+
+!macro RestartManager_StartSession outvarhandle
+System::Call 'RSTRTMGR::RmStartSession(*i-1s, i0, w)i.s'
+Pop ${outvarhandle}
+${If} ${outvarhandle} <> 0
+${OrIf} ${outvarhandle} == error
+ Pop ${outvarhandle}
+ Push ""
+${EndIf}
+Pop ${outvarhandle}
+!macroend
+
+!macro RestartManager_EndSession handle
+System::Call 'RSTRTMGR::RmEndSession(i${handle})'
+!macroend
+
+!macro RestartManager_RegisterFile handle path
+System::Call 'RSTRTMGR::RmRegisterResources(i${handle},i1,*ws,i0,p0,i0,p0)i.r0' "${path}"
+!macroend
+
+!macro RestartManager_Shutdown handle
+System::Call 'RSTRTMGR::RmShutdown(i${handle}, i${RmForceShutdown}, p0)'
+!macroend
+
+!macro RestartManager_Restart handle
+System::Call 'RSTRTMGR::RmRestart(i${handle}, i0, p0)'
+!macroend
+
+
+!macro RestartManager_ShutdownFile fullpath outvar_errcode
+Push "${fullpath}"
+!insertmacro CallArtificialFunction RestartManager_ShutdownFileImp
+Pop ${outvar_errcode}
+!macroend
+!macro RestartManager_ShutdownFileImp
+Exch $1
+Push $0
+System::Call 'RSTRTMGR::RmStartSession(*i-1s, i0, w)i.r0'
+${If} $0 == error
+ Pop $0
+ StrCpy $0 1150
+${Else}
+ System::Call 'RSTRTMGR::RmRegisterResources(isr1,i1,*wr1,i0,p0,i0,p0)i.r0'
+ ${If} $0 = 0
+ System::Call 'RSTRTMGR::RmShutdown(ir1, i${RmForceShutdown}, p0)i.r0'
+ ${EndIf}
+ System::Call 'RSTRTMGR::RmEndSession(ir1)'
+${EndIf}
+Exch
+Pop $1
+Exch $0
+!macroend
+
+!endif ;~ Include guard
diff --git a/installer/tools/Include/Win/WinDef.nsh b/installer/tools/Include/Win/WinDef.nsh
new file mode 100644
index 00000000..a91d6856
--- /dev/null
+++ b/installer/tools/Include/Win/WinDef.nsh
@@ -0,0 +1,67 @@
+!ifndef __WIN_WINDEF__INC
+!define __WIN_WINDEF__INC
+!verbose push
+!verbose 3
+!ifndef __WIN_NOINC_WINDEF
+
+
+!define /ifndef MAX_PATH 260
+#define NULL 0
+
+
+!macro _Win_MINMAX _intcmp _j1 _j2 _outvar _a _b
+${_intcmp} "${_a}" "${_b}" ${_j1} ${_j1} ${_j2}
+StrCpy ${_outvar} "${_a}"
+goto +2
+StrCpy ${_outvar} "${_b}"
+!macroend
+!ifndef __WIN_MS_NOMINMAX & min & max & min_u & max_u
+!define min "!insertmacro _Win_MINMAX IntCmp +1 +3 "
+!define max "!insertmacro _Win_MINMAX IntCmp +3 +1 "
+!define min_u "!insertmacro _Win_MINMAX IntCmpU +1 +3 "
+!define max_u "!insertmacro _Win_MINMAX IntCmpU +3 +1 "
+!endif
+
+!macro _Win_LOBYTE _outvar _in
+IntOp ${_outvar} "${_in}" & 0xFF
+!macroend
+!define LOBYTE "!insertmacro _Win_LOBYTE "
+
+!macro _Win_HIBYTE _outvar _in
+IntOp ${_outvar} "${_in}" >> 8
+${LOBYTE} ${_outvar} ${_outvar}
+!macroend
+!define HIBYTE "!insertmacro _Win_HIBYTE "
+
+!macro _Win_LOWORD _outvar _in
+IntOp ${_outvar} "${_in}" & 0xFFFF
+!macroend
+!define LOWORD "!insertmacro _Win_LOWORD "
+
+!macro _Win_HIWORD _outvar _in
+IntOp ${_outvar} "${_in}" >>> 16
+!macroend
+!define HIWORD "!insertmacro _Win_HIWORD "
+
+!macro _Win_MAKEWORD _outvar _tmpvar _lo _hi
+${LOBYTE} ${_outvar} "${_hi}"
+${LOBYTE} ${_tmpvar} "${_lo}"
+IntOp ${_outvar} ${_outvar} << 8
+IntOp ${_outvar} ${_outvar} | ${_tmpvar}
+!macroend
+!define MAKEWORD "!insertmacro _Win_MAKEWORD "
+
+!macro _Win_MAKELONG32 _outvar _tmpvar _wlo _whi
+${LOWORD} ${_outvar} "${_wlo}"
+IntOp ${_tmpvar} "${_whi}" << 16
+IntOp ${_outvar} ${_outvar} | ${_tmpvar}
+!macroend
+!define MAKELONG "!insertmacro _Win_MAKELONG32 "
+!define MAKEWPARAM "${MAKELONG}"
+!define MAKELPARAM "${MAKELONG}"
+!define MAKELRESULT "${MAKELONG}"
+
+
+!endif /* __WIN_NOINC_WINDEF */
+!verbose pop
+!endif /* __WIN_WINDEF__INC */
\ No newline at end of file
diff --git a/installer/tools/Include/Win/WinError.nsh b/installer/tools/Include/Win/WinError.nsh
new file mode 100644
index 00000000..16b0ecff
--- /dev/null
+++ b/installer/tools/Include/Win/WinError.nsh
@@ -0,0 +1,155 @@
+!ifndef __WIN_WINERROR__INC
+!define __WIN_WINERROR__INC
+!verbose push
+!verbose 3
+
+!ifndef __WIN_NOINC_WINERROR
+#define NO_ERROR 0
+!define ERROR_SUCCESS 0
+!define ERROR_INVALID_FUNCTION 1
+!define ERROR_FILE_NOT_FOUND 2
+!define ERROR_PATH_NOT_FOUND 3
+!define ERROR_TOO_MANY_OPEN_FILES 4
+!define ERROR_ACCESS_DENIED 5
+!define ERROR_INVALID_HANDLE 6
+!define ERROR_ARENA_TRASHED 7
+!define ERROR_NOT_ENOUGH_MEMORY 8
+!define ERROR_INVALID_BLOCK 9
+!define ERROR_BAD_ENVIRONMENT 10
+!define ERROR_BAD_FORMAT 11
+!define ERROR_INVALID_ACCESS 12
+!define ERROR_INVALID_DATA 13
+!define ERROR_OUTOFMEMORY 14
+!define ERROR_INVALID_DRIVE 15
+!define ERROR_CURRENT_DIRECTORY 16
+!define ERROR_NOT_SAME_DEVICE 17
+!define ERROR_NO_MORE_FILES 18
+!define ERROR_WRITE_PROTECT 19
+!define ERROR_BAD_UNIT 20
+!define ERROR_NOT_READY 21
+!define ERROR_BAD_COMMAND 22
+!define ERROR_CRC 23
+!define ERROR_BAD_LENGTH 24
+!define ERROR_SEEK 25
+!define ERROR_NOT_DOS_DISK 26
+!define ERROR_SECTOR_NOT_FOUND 27
+!define ERROR_OUT_OF_PAPER 28
+!define ERROR_WRITE_FAULT 29
+!define ERROR_READ_FAULT 30
+!define ERROR_GEN_FAILURE 31
+!define ERROR_SHARING_VIOLATION 32
+!define ERROR_LOCK_VIOLATION 33
+!define ERROR_WRONG_DISK 34
+!define ERROR_SHARING_BUFFER_EXCEEDED 36
+!define ERROR_HANDLE_EOF 38
+!define ERROR_HANDLE_DISK_FULL 39
+!define ERROR_NOT_SUPPORTED 50
+!define ERROR_CANNOT_MAKE 82 ; "The directory or file cannot be created"
+!define ERROR_INVALID_PARAMETER 87
+!define ERROR_DISK_FULL 112
+!define ERROR_CALL_NOT_IMPLEMENTED 120 ; "This function is not supported on this system"
+!define ERROR_INSUFFICIENT_BUFFER 122
+!define ERROR_INVALID_NAME 123 ; "The filename, directory name, or volume label syntax is incorrect"
+!define ERROR_MOD_NOT_FOUND 126 ; "The specified module could not be found"
+!define ERROR_BAD_ARGUMENTS 160
+!define ERROR_BAD_PATHNAME 161
+!define ERROR_LOCK_FAILED 167 ; "Unable to lock a region of a file"
+!define ERROR_BUSY 170 ; "The requested resource is in use"
+!define ERROR_ALREADY_EXISTS 183 ; "Cannot create a file when that file already exists"
+!define ERROR_FILENAME_EXCED_RANGE 206 ; "The filename or extension is too long"
+!define ERROR_EXE_MACHINE_TYPE_MISMATCH 216 ; "This version of %1 is not compatible with the version of Windows you're running"
+!define ERROR_IMAGE_SUBSYSTEM_NOT_PRESENT 308
+!define ERROR_DATA_CHECKSUM_ERROR 323
+!define ERROR_ELEVATION_REQUIRED 740
+!define ERROR_SERVICE_DOES_NOT_EXIST 1060
+!define ERROR_NO_MEDIA_IN_DRIVE 1112
+!define ERROR_NO_UNICODE_TRANSLATION 1113
+!define ERROR_DLL_INIT_FAILED 1114
+!define ERROR_SHUTDOWN_IN_PROGRESS 1115
+!define ERROR_OLD_WIN_VERSION 1150 ; "The specified program requires a newer version of Windows"
+!define ERROR_APP_WRONG_OS 1151 ; "The specified program is not a Windows or MS-DOS program"
+!define ERROR_SINGLE_INSTANCE_APP 1152 ; "Cannot start more than one instance of the specified program"
+!define ERROR_RMODE_APP 1153 ; "The specified program was written for an earlier version of Windows"
+!define ERROR_INVALID_DLL 1154
+!define ERROR_NO_ASSOCIATION 1155
+!define ERROR_DDE_FAIL 1156
+!define ERROR_DLL_NOT_FOUND 1157
+!define ERROR_NOT_FOUND 1168 ; "Element not found"
+!define ERROR_NO_MATCH 1169 ; "There was no match for the specified key in the index"
+!define ERROR_NO_VOLUME_ID 1173
+!define ERROR_UNABLE_TO_REMOVE_REPLACED 1175 ; "Unable to remove the file to be replaced"
+!define ERROR_UNABLE_TO_MOVE_REPLACEMENT 1176
+!define ERROR_UNABLE_TO_MOVE_REPLACEMENT_2 1177
+!define ERROR_SHUTDOWN_IS_SCHEDULED 1190
+!define ERROR_SHUTDOWN_USERS_LOGGED_ON 1191 ; "The system shutdown cannot be initiated because there are other users logged on to the computer"
+!define ERROR_NO_NETWORK 1222
+!define ERROR_CANCELLED 1223 ; "The operation was canceled by the user"
+!define ERROR_RETRY 1237
+!define ERROR_SERVICE_NOT_FOUND 1243
+!define ERROR_NOT_AUTHENTICATED 1244
+!define ERROR_UNIDENTIFIED_ERROR 1287
+!define ERROR_PRIVILEGE_NOT_HELD 1314
+!define ERROR_LOGON_FAILURE 1326 ; "The user name or password is incorrect"
+!define ERROR_INTERNAL_ERROR 1359 ; "An internal error occurred"
+!define ERROR_FILE_CORRUPT 1392 ; "The file or directory is corrupted and unreadable"
+!define ERROR_INVALID_WINDOW_HANDLE 1400 ; "Invalid window handle"
+!define ERROR_INVALID_INDEX 1413
+!define ERROR_TIMEOUT 1460
+!define ERROR_SYMLINK_NOT_SUPPORTED 1464
+!define ERROR_XML_PARSE_ERROR 1465
+!define ERROR_RESTART_APPLICATION 1467 ; "This application must be restarted"
+!define ERROR_INSTALL_USEREXIT 1602 ; "User cancelled installation"
+!define ERROR_INSTALL_FAILURE 1603 ; "Fatal error during installation"
+!define ERROR_INSTALL_SUSPEND 1604 ; "Installation suspended, incomplete"
+!define ERROR_UNKNOWN_PRODUCT 1605 ; "This action is only valid for products that are currently installed"
+!define ERROR_BAD_CONFIGURATION 1610
+!define ERROR_INSTALL_SOURCE_ABSENT 1612
+!define ERROR_PRODUCT_UNINSTALLED 1614
+!define ERROR_INSTALL_ALREADY_RUNNING 1618 ; "Another installation is already in progress. Complete that installation before proceeding with this install."
+!define ERROR_INSTALL_PACKAGE_INVALID 1620
+!define ERROR_INSTALL_LOG_FAILURE 1622
+!define ERROR_INSTALL_LANGUAGE_UNSUPPORTED 1623
+!define ERROR_FUNCTION_FAILED 1627
+!define ERROR_DATATYPE_MISMATCH 1629
+!define ERROR_UNSUPPORTED_TYPE 1630
+!define ERROR_INSTALL_TEMP_UNWRITABLE 1632 ; "The Temp folder is on a drive that is full or is inaccessible"
+!define ERROR_INSTALL_PLATFORM_UNSUPPORTED 1633 ; "This installation package is not supported by this processor type. Contact your product vendor."
+!define ERROR_PRODUCT_VERSION 1638 ; "Another version of this product is already installed"
+!define ERROR_SUCCESS_REBOOT_INITIATED 1641 ; "The requested operation completed successfully. The system will be restarted so the changes can take effect."
+!define ERROR_INSTALL_REJECTED 1654 ; "The app that you are trying to run is not supported on this version of Windows"
+!define ERROR_TAG_NOT_FOUND 2012
+!define ERROR_BAD_USERNAME 2202 ; "The user name or group name parameter is invalid"
+!define ERROR_SUCCESS_REBOOT_REQUIRED 3010
+!define ERROR_SUCCESS_RESTART_REQUIRED 3011
+!define ERROR_INSTALL_INVALID_PACKAGE 15602
+!define ERROR_INSTALL_OUT_OF_DISK_SPACE 15604
+!define ERROR_INSTALL_CANCEL 15608 ; "User cancelled the install request"
+!define ERROR_INSTALL_FAILED 15609
+!define ERROR_REMOVE_FAILED 15610
+!define ERROR_NEEDS_REMEDIATION 15612 ; "The application cannot be started. Try reinstalling the application to fix the problem."
+
+!define SEVERITY_SUCCESS 0
+!define SEVERITY_ERROR 1
+!define FACILITY_STORAGE 3
+!define FACILITY_WIN32 7
+!define FACILITY_SECURITY 9
+!define FACILITY_SETUPAPI 15
+!define FACILITY_SXS 23
+!define /IfNDef S_OK 0
+!define /IfNDef S_FALSE 1
+!define E_UNEXPECTED 0x8000FFFF
+!define E_NOTIMPL 0x80004001
+!define E_OUTOFMEMORY 0x8007000E
+!define E_INVALIDARG 0x80070057
+!define E_NOINTERFACE 0x80004002
+!define E_POINTER 0x80004003
+!define E_HANDLE 0x80070006
+!define E_ABORT 0x80004004
+!define E_FAIL 0x80004005
+!define E_ACCESSDENIED 0x80070005
+!define E_PENDING 0x8000000A
+
+!endif /* __WIN_NOINC_WINERROR */
+
+!verbose pop
+!endif /* __WIN_WINERROR__INC */
diff --git a/installer/tools/Include/Win/WinNT.nsh b/installer/tools/Include/Win/WinNT.nsh
new file mode 100644
index 00000000..09e9aaf4
--- /dev/null
+++ b/installer/tools/Include/Win/WinNT.nsh
@@ -0,0 +1,224 @@
+!ifndef __WIN_WINNT__INC
+!define __WIN_WINNT__INC
+!verbose push
+!verbose 3
+!ifndef __WIN_NOINC_WINNT
+
+
+#define MINCHAR 0x80
+#define MAXCHAR 0x7f
+!define MINSHORT 0x8000
+!define MAXSHORT 0x7fff
+!define MINLONG 0x80000000
+!define MAXLONG 0x7fffffff
+!define MAXBYTE 0xff
+!define MAXWORD 0xffff
+!define MAXDWORD 0xffffffff
+
+!ifndef WIN32_NO_STATUS
+!define STATUS_WAIT_0 0x00000000
+!define STATUS_ABANDONED_WAIT_0 0x00000080
+!define STATUS_USER_APC 0x000000C0
+!define STATUS_TIMEOUT 0x00000102
+!define STATUS_PENDING 0x00000103
+!define DBG_EXCEPTION_HANDLED 0x00010001
+!define DBG_CONTINUE 0x00010002
+!define STATUS_SEGMENT_NOTIFICATION 0x40000005
+!define DBG_TERMINATE_THREAD 0x40010003
+!define DBG_TERMINATE_PROCESS 0x40010004
+!define DBG_CONTROL_C 0x40010005
+!define DBG_CONTROL_BREAK 0x40010008
+!define DBG_COMMAND_EXCEPTION 0x40010009
+!define STATUS_GUARD_PAGE_VIOLATION 0x80000001
+!define STATUS_DATATYPE_MISALIGNMENT 0x80000002
+!define STATUS_BREAKPOINT 0x80000003
+!define STATUS_SINGLE_STEP 0x80000004
+!define DBG_EXCEPTION_NOT_HANDLED 0x80010001
+!define STATUS_ACCESS_VIOLATION 0xC0000005
+!define STATUS_IN_PAGE_ERROR 0xC0000006
+!define STATUS_INVALID_HANDLE 0xC0000008
+!define STATUS_NO_MEMORY 0xC0000017
+!define STATUS_ILLEGAL_INSTRUCTION 0xC000001D
+!define STATUS_NONCONTINUABLE_EXCEPTION 0xC0000025
+!define STATUS_INVALID_DISPOSITION 0xC0000026
+!define STATUS_ARRAY_BOUNDS_EXCEEDED 0xC000008C
+!define STATUS_FLOAT_DENORMAL_OPERAND 0xC000008D
+!define STATUS_FLOAT_DIVIDE_BY_ZERO 0xC000008E
+!define STATUS_FLOAT_INEXACT_RESULT 0xC000008F
+!define STATUS_FLOAT_INVALID_OPERATION 0xC0000090
+!define STATUS_FLOAT_OVERFLOW 0xC0000091
+!define STATUS_FLOAT_STACK_CHECK 0xC0000092
+!define STATUS_FLOAT_UNDERFLOW 0xC0000093
+!define STATUS_INTEGER_DIVIDE_BY_ZERO 0xC0000094
+!define STATUS_INTEGER_OVERFLOW 0xC0000095
+!define STATUS_PRIVILEGED_INSTRUCTION 0xC0000096
+!define STATUS_STACK_OVERFLOW 0xC00000FD
+!define STATUS_CONTROL_C_EXIT 0xC000013A
+!define STATUS_FLOAT_MULTIPLE_FAULTS 0xC00002B4
+!define STATUS_FLOAT_MULTIPLE_TRAPS 0xC00002B5
+!define STATUS_REG_NAT_CONSUMPTION 0xC00002C9
+!define STATUS_SXS_EARLY_DEACTIVATION 0xC015000F
+!define STATUS_SXS_INVALID_DEACTIVATION 0xC0150010
+!endif /*WIN32_NO_STATUS*/
+
+#define MAXIMUM_WAIT_OBJECTS 64
+
+!define DELETE 0x00010000
+!define READ_CONTROL 0x00020000
+!define WRITE_DAC 0x00040000
+!define WRITE_OWNER 0x00080000
+!define SYNCHRONIZE 0x00100000
+!define STANDARD_RIGHTS_REQUIRED 0x000F0000
+!define STANDARD_RIGHTS_READ ${READ_CONTROL}
+!define STANDARD_RIGHTS_WRITE ${READ_CONTROL}
+!define STANDARD_RIGHTS_EXECUTE ${READ_CONTROL}
+!define STANDARD_RIGHTS_ALL 0x001F0000
+!define SPECIFIC_RIGHTS_ALL 0x0000FFFF
+!define ACCESS_SYSTEM_SECURITY 0x01000000
+!define MAXIMUM_ALLOWED 0x02000000
+!define GENERIC_READ 0x80000000
+!define GENERIC_WRITE 0x40000000
+!define GENERIC_EXECUTE 0x20000000
+!define GENERIC_ALL 0x10000000
+
+!define SE_PRIVILEGE_ENABLED_BY_DEFAULT 0x00000001
+!define SE_PRIVILEGE_ENABLED 0x00000002
+!define SE_PRIVILEGE_REMOVED 0x00000004
+!define SE_PRIVILEGE_USED_FOR_ACCESS 0x80000000
+
+!define SE_CREATE_TOKEN_NAME "SeCreateTokenPrivilege"
+!define SE_ASSIGNPRIMARYTOKEN_NAME "SeAssignPrimaryTokenPrivilege"
+!define SE_LOCK_MEMORY_NAME "SeLockMemoryPrivilege"
+!define SE_INCREASE_QUOTA_NAME "SeIncreaseQuotaPrivilege"
+!define SE_UNSOLICITED_INPUT_NAME "SeUnsolicitedInputPrivilege"
+!define SE_MACHINE_ACCOUNT_NAME "SeMachineAccountPrivilege"
+!define SE_TCB_NAME "SeTcbPrivilege"
+!define SE_SECURITY_NAME "SeSecurityPrivilege"
+!define SE_TAKE_OWNERSHIP_NAME "SeTakeOwnershipPrivilege"
+!define SE_LOAD_DRIVER_NAME "SeLoadDriverPrivilege"
+!define SE_SYSTEM_PROFILE_NAME "SeSystemProfilePrivilege"
+!define SE_SYSTEMTIME_NAME "SeSystemtimePrivilege"
+!define SE_PROF_SINGLE_PROCESS_NAME "SeProfileSingleProcessPrivilege"
+!define SE_INC_BASE_PRIORITY_NAME "SeIncreaseBasePriorityPrivilege"
+!define SE_CREATE_PAGEFILE_NAME "SeCreatePagefilePrivilege"
+!define SE_CREATE_PERMANENT_NAME "SeCreatePermanentPrivilege"
+!define SE_BACKUP_NAME "SeBackupPrivilege"
+!define SE_RESTORE_NAME "SeRestorePrivilege"
+!define SE_SHUTDOWN_NAME "SeShutdownPrivilege"
+!define SE_DEBUG_NAME "SeDebugPrivilege"
+!define SE_AUDIT_NAME "SeAuditPrivilege"
+!define SE_SYSTEM_ENVIRONMENT_NAME "SeSystemEnvironmentPrivilege"
+!define SE_CHANGE_NOTIFY_NAME "SeChangeNotifyPrivilege"
+!define SE_REMOTE_SHUTDOWN_NAME "SeRemoteShutdownPrivilege"
+!define SE_UNDOCK_NAME "SeUndockPrivilege"
+!define SE_SYNC_AGENT_NAME "SeSyncAgentPrivilege"
+!define SE_ENABLE_DELEGATION_NAME "SeEnableDelegationPrivilege"
+!define SE_MANAGE_VOLUME_NAME "SeManageVolumePrivilege"
+!define SE_IMPERSONATE_NAME "SeImpersonatePrivilege"
+!define SE_CREATE_GLOBAL_NAME "SeCreateGlobalPrivilege"
+
+!define TOKEN_ASSIGN_PRIMARY 0x0001
+!define TOKEN_DUPLICATE 0x0002
+!define TOKEN_IMPERSONATE 0x0004
+!define TOKEN_QUERY 0x0008
+!define TOKEN_QUERY_SOURCE 0x0010
+!define TOKEN_ADJUST_PRIVILEGES 0x0020
+!define TOKEN_ADJUST_GROUPS 0x0040
+!define TOKEN_ADJUST_DEFAULT 0x0080
+!define TOKEN_ADJUST_SESSIONID 0x0100
+!define TOKEN_ALL_ACCESS_P 0xF00FF
+!define /math TOKEN_ALL_ACCESS ${TOKEN_ALL_ACCESS_P} | ${TOKEN_ADJUST_SESSIONID}
+!define /math TOKEN_READ ${STANDARD_RIGHTS_READ} | ${TOKEN_QUERY}
+!define TOKEN_WRITE 0x200E0 ;(STANDARD_RIGHTS_WRITE|TOKEN_ADJUST_PRIVILEGES|TOKEN_ADJUST_GROUPS|TOKEN_ADJUST_DEFAULT)
+!define TOKEN_EXECUTE ${STANDARD_RIGHTS_EXECUTE}
+
+!define PROCESS_TERMINATE 0x0001
+!define PROCESS_CREATE_THREAD 0x0002
+!define PROCESS_SET_SESSIONID 0x0004
+!define PROCESS_VM_OPERATION 0x0008
+!define PROCESS_VM_READ 0x0010
+!define PROCESS_VM_WRITE 0x0020
+!define PROCESS_DUP_HANDLE 0x0040
+!define PROCESS_CREATE_PROCESS 0x0080
+!define PROCESS_SET_QUOTA 0x0100
+!define PROCESS_SET_INFORMATION 0x0200
+!define PROCESS_QUERY_INFORMATION 0x0400
+!define PROCESS_SUSPEND_RESUME 0x0800
+!define PROCESS_ALL_ACCESS 0x1F0FFF ;(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF)
+!define THREAD_TERMINATE 0x0001
+!define THREAD_SUSPEND_RESUME 0x0002
+!define THREAD_GET_CONTEXT 0x0008
+!define THREAD_SET_CONTEXT 0x0010
+!define THREAD_SET_INFORMATION 0x0020
+!define THREAD_QUERY_INFORMATION 0x0040
+!define THREAD_SET_THREAD_TOKEN 0x0080
+!define THREAD_IMPERSONATE 0x0100
+!define THREAD_DIRECT_IMPERSONATION 0x0200
+!define THREAD_ALL_ACCESS 0x1F03FF ;(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x3FF)
+!define JOB_OBJECT_ASSIGN_PROCESS 0x0001
+!define JOB_OBJECT_SET_ATTRIBUTES 0x0002
+!define JOB_OBJECT_QUERY 0x0004
+!define JOB_OBJECT_TERMINATE 0x0008
+!define JOB_OBJECT_SET_SECURITY_ATTRIBUTES 0x0010
+!define JOB_OBJECT_ALL_ACCESS 0x1F001F ;(STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0x1F )
+!define EVENT_MODIFY_STATE 0x0002
+!define EVENT_ALL_ACCESS 0x1F0003 ;(STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x3)
+!define MUTANT_QUERY_STATE 0x0001
+!define MUTANT_ALL_ACCESS 0x1F0001 ;(STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|MUTANT_QUERY_STATE)
+
+!define FILE_SHARE_READ 0x00000001
+!define FILE_SHARE_WRITE 0x00000002
+!define FILE_SHARE_DELETE 0x00000004
+!define FILE_ATTRIBUTE_READONLY 0x00000001
+!define FILE_ATTRIBUTE_HIDDEN 0x00000002
+!define FILE_ATTRIBUTE_SYSTEM 0x00000004
+!define FILE_ATTRIBUTE_DIRECTORY 0x00000010
+!define FILE_ATTRIBUTE_ARCHIVE 0x00000020
+!define FILE_ATTRIBUTE_DEVICE 0x00000040
+!define FILE_ATTRIBUTE_NORMAL 0x00000080
+!define FILE_ATTRIBUTE_TEMPORARY 0x00000100
+!define FILE_ATTRIBUTE_SPARSE_FILE 0x00000200
+!define FILE_ATTRIBUTE_REPARSE_POINT 0x00000400
+!define FILE_ATTRIBUTE_COMPRESSED 0x00000800
+!define FILE_ATTRIBUTE_OFFLINE 0x00001000
+!define FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 0x00002000
+!define FILE_ATTRIBUTE_ENCRYPTED 0x00004000
+
+!define DUPLICATE_CLOSE_SOURCE 0x00000001
+!define DUPLICATE_SAME_ACCESS 0x00000002
+
+!define /ifndef VER_PLATFORM_WIN32s 0
+!define /ifndef VER_PLATFORM_WIN32_WINDOWS 1
+!define /ifndef VER_PLATFORM_WIN32_NT 2
+
+!ifndef REG_SZ & NSIS_WINDOWS__NO_REGTYPES
+!define REG_NONE 0
+!define REG_SZ 1
+!define REG_EXPAND_SZ 2
+!define REG_BINARY 3
+!define REG_DWORD 4
+!define REG_DWORD_LITTLE_ENDIAN 4
+!define REG_DWORD_BIG_ENDIAN 5
+!define REG_LINK 6
+!define REG_MULTI_SZ 7
+!endif
+
+!define PROCESSOR_ARCHITECTURE_UNKNOWN 0xFFFF
+!define PROCESSOR_ARCHITECTURE_INTEL 0 ; x86
+!define PROCESSOR_ARCHITECTURE_ARM 5
+!define PROCESSOR_ARCHITECTURE_IA64 6 ; Itanium
+!define PROCESSOR_ARCHITECTURE_AMD64 9 ; x86-64/x64
+!define PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 10
+!define PROCESSOR_ARCHITECTURE_ARM64 12
+!define PROCESSOR_ARCHITECTURE_ARM32_ON_WIN64 13
+
+!define IMAGE_FILE_MACHINE_UNKNOWN 0
+!define IMAGE_FILE_MACHINE_I386 332 ; x86
+!define IMAGE_FILE_MACHINE_ARMNT 452
+!define IMAGE_FILE_MACHINE_IA64 512 ; Itanium
+!define IMAGE_FILE_MACHINE_AMD64 34404 ; x86-64/x64
+!define IMAGE_FILE_MACHINE_ARM64 43620
+
+!endif /* __WIN_NOINC_WINNT */
+!verbose pop
+!endif /* __WIN_WINNT__INC */
\ No newline at end of file
diff --git a/installer/tools/Include/Win/WinUser.nsh b/installer/tools/Include/Win/WinUser.nsh
new file mode 100644
index 00000000..50a9921c
--- /dev/null
+++ b/installer/tools/Include/Win/WinUser.nsh
@@ -0,0 +1,199 @@
+!ifndef __WIN_WINUSER__INC
+!define __WIN_WINUSER__INC
+!verbose push
+!verbose 3
+!ifndef __WIN_MS_NOUSER & __WIN_NOINC_WINUSER
+
+!ifndef __WIN_MS_NOVIRTUALKEYCODES
+!define VK_LBUTTON 0x01
+!define VK_RBUTTON 0x02
+!define VK_CANCEL 0x03
+!define VK_MBUTTON 0x04 /* NOT contiguous with L & RBUTTON */
+!define VK_XBUTTON1 0x05 /* NOT contiguous with L & RBUTTON */
+!define VK_XBUTTON2 0x06 /* NOT contiguous with L & RBUTTON */
+!define VK_BACK 0x08
+!define VK_TAB 0x09
+!define VK_CLEAR 0x0C
+!define VK_RETURN 0x0D
+!define VK_SHIFT 0x10
+!define VK_CONTROL 0x11
+!define VK_MENU 0x12
+!define VK_PAUSE 0x13
+!define VK_CAPITAL 0x14
+!define VK_ESCAPE 0x1B
+!define VK_CONVERT 0x1C
+!define VK_NONCONVERT 0x1D
+!define VK_ACCEPT 0x1E
+!define VK_MODECHANGE 0x1F
+!define VK_SPACE 0x20
+!define VK_PRIOR 0x21
+!define VK_NEXT 0x22
+!define VK_END 0x23
+!define VK_HOME 0x24
+!define VK_LEFT 0x25
+!define VK_UP 0x26
+!define VK_RIGHT 0x27
+!define VK_DOWN 0x28
+!define VK_SELECT 0x29
+!define VK_PRINT 0x2A
+!define VK_EXECUTE 0x2B
+!define VK_SNAPSHOT 0x2C
+!define VK_INSERT 0x2D
+!define VK_DELETE 0x2E
+!define VK_HELP 0x2F
+; VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39)
+; VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A)
+!define VK_LWIN 0x5B
+!define VK_RWIN 0x5C
+!define VK_APPS 0x5D
+!define VK_SLEEP 0x5F
+!define VK_NUMPAD0 0x60
+!define VK_NUMPAD1 0x61
+!define VK_NUMPAD2 0x62
+!define VK_NUMPAD3 0x63
+!define VK_NUMPAD4 0x64
+!define VK_NUMPAD5 0x65
+!define VK_NUMPAD6 0x66
+!define VK_NUMPAD7 0x67
+!define VK_NUMPAD8 0x68
+!define VK_NUMPAD9 0x69
+!define VK_MULTIPLY 0x6A
+!define VK_ADD 0x6B
+!define VK_SEPARATOR 0x6C
+!define VK_SUBTRACT 0x6D
+!define VK_DECIMAL 0x6E
+!define VK_DIVIDE 0x6F
+!define VK_F1 0x70
+!define VK_F2 0x71
+!define VK_F3 0x72
+!define VK_F4 0x73
+!define VK_F5 0x74
+!define VK_F6 0x75
+!define VK_F7 0x76
+!define VK_F8 0x77
+!define VK_F9 0x78
+!define VK_F10 0x79
+!define VK_F11 0x7A
+!define VK_F12 0x7B
+!define VK_NUMLOCK 0x90
+!define VK_SCROLL 0x91
+!define VK_OEM_NEC_EQUAL 0x92 ; '=' key on numpad
+!define VK_LSHIFT 0xA0
+!define VK_RSHIFT 0xA1
+!define VK_LCONTROL 0xA2
+!define VK_RCONTROL 0xA3
+!define VK_LMENU 0xA4
+!define VK_RMENU 0xA5
+!endif
+
+!ifndef __WIN_MS_NOWINOFFSETS
+!define /ifndef GWL_STYLE -16
+!define /ifndef GWL_EXSTYLE -20
+!define /ifndef GWLP_WNDPROC -4
+!define /ifndef GWLP_HINSTANCE -6
+!define /ifndef GWLP_HWNDPARENT -8
+!define /ifndef GWLP_USERDATA -21
+!define /ifndef GWLP_ID -12
+!define DWLP_MSGRESULT 0
+!define /math DWLP_DLGPROC ${DWLP_MSGRESULT} + ${NSIS_PTR_SIZE} ;DWLP_MSGRESULT + sizeof(LRESULT)
+!define /math DWLP_USER ${DWLP_DLGPROC} + ${NSIS_PTR_SIZE} ;DWLP_DLGPROC + sizeof(DLGPROC)
+!endif
+
+!ifndef __WIN_MS_NONCMESSAGES
+!define HTERROR -2
+!define HTTRANSPARENT -1
+!define HTNOWHERE 0
+!define HTCLIENT 1
+!define HTCAPTION 2
+!define HTSYSMENU 3
+!define HTGROWBOX 4
+!define HTSIZE ${HTGROWBOX}
+!define HTMENU 5
+!define HTHSCROLL 6
+!define HTVSCROLL 7
+!define HTMINBUTTON 8
+!define HTMAXBUTTON 9
+!define HTLEFT 10
+!define HTRIGHT 11
+!define HTTOP 12
+!define HTTOPLEFT 13
+!define HTTOPRIGHT 14
+!define HTBOTTOM 15
+!define HTBOTTOMLEFT 16
+!define HTBOTTOMRIGHT 17
+!define HTBORDER 18
+!define HTREDUCE ${HTMINBUTTON}
+!define HTZOOM ${HTMAXBUTTON}
+!define HTSIZEFIRST ${HTLEFT}
+!define HTSIZELAST ${HTBOTTOMRIGHT}
+!define HTOBJECT 19
+!define HTCLOSE 20
+!define HTHELP 21
+!endif
+
+!ifndef __WIN_MS_NOSYSCOMMANDS
+!define SC_SIZE 0xF000
+!define SC_MOVE 0xF010
+!define SC_MINIMIZE 0xF020
+!define SC_MAXIMIZE 0xF030
+!define SC_NEXTWINDOW 0xF040
+!define SC_PREVWINDOW 0xF050
+!define SC_CLOSE 0xF060
+!define SC_VSCROLL 0xF070
+!define SC_HSCROLL 0xF080
+!define SC_MOUSEMENU 0xF090
+!define SC_KEYMENU 0xF100
+!define SC_ARRANGE 0xF110
+!define SC_RESTORE 0xF120
+!define SC_TASKLIST 0xF130
+!define SC_SCREENSAVE 0xF140
+!define SC_HOTKEY 0xF150
+!define SC_DEFAULT 0xF160
+!define SC_MONITORPOWER 0xF170
+!define SC_CONTEXTHELP 0xF180
+!define SC_SEPARATOR 0xF00F
+!endif
+
+!define /ifndef IDC_ARROW 32512
+!define /ifndef IDC_IBEAM 32513
+!define /ifndef IDC_WAIT 32514
+!define /ifndef IDC_CROSS 32515
+!define /ifndef IDC_UPARROW 32516
+!define /ifndef IDC_SIZE 32640
+!define /ifndef IDC_ICON 32641
+!define /ifndef IDC_SIZENWSE 32642
+!define /ifndef IDC_SIZENESW 32643
+!define /ifndef IDC_SIZEWE 32644
+!define /ifndef IDC_SIZENS 32645
+!define /ifndef IDC_SIZEALL 32646
+!define /ifndef IDC_NO 32648
+!define /ifndef IDC_HAND 32649
+!define /ifndef IDC_APPSTARTING 32650
+!define /ifndef IDC_HELP 32651
+
+!define /ifndef IMAGE_BITMAP 0
+!define /ifndef IMAGE_ICON 1
+!define /ifndef IMAGE_CURSOR 2
+!define /ifndef IMAGE_ENHMETAFILE 3
+
+!define /ifndef LR_DEFAULTCOLOR 0x0000
+!define /ifndef LR_MONOCHROME 0x0001
+!define /ifndef LR_COLOR 0x0002
+!define /ifndef LR_COPYRETURNORG 0x0004
+!define /ifndef LR_COPYDELETEORG 0x0008
+!define /ifndef LR_LOADFROMFILE 0x0010
+!define /ifndef LR_LOADTRANSPARENT 0x0020
+!define /ifndef LR_DEFAULTSIZE 0x0040
+!define /ifndef LR_VGACOLOR 0x0080
+!define /ifndef LR_LOADMAP3DCOLORS 0x1000
+!define /ifndef LR_CREATEDIBSECTION 0x2000
+!define /ifndef LR_COPYFROMRESOURCE 0x4000
+!define /ifndef LR_SHARED 0x8000
+
+!define GA_PARENT 1
+!define GA_ROOT 2
+!define GA_ROOTOWNER 3
+
+!endif /* __WIN_MS_NOUSER & __WIN_NOINC_WINUSER */
+!verbose pop
+!endif /* __WIN_WINUSER__INC */
\ No newline at end of file
diff --git a/installer/tools/Include/WinCore.nsh b/installer/tools/Include/WinCore.nsh
new file mode 100644
index 00000000..2a143147
--- /dev/null
+++ b/installer/tools/Include/WinCore.nsh
@@ -0,0 +1,263 @@
+/*
+
+WinCore.nsh & Win\*.nsh - Collection of common windows defines
+
+!define __WIN_NOINC_xxx to exclude a windows header file
+!define __WIN_MS_xxx to exclude specific things (The original #ifdef xxx checks can be found in the official Microsoft headers)
+
+*/
+
+!ifndef __WIN_WINDOWS__INC
+!define __WIN_WINDOWS__INC
+!verbose push
+!verbose 3
+
+
+
+!include Win\WinDef.nsh
+!include Win\WinError.nsh
+!include Win\WinNT.nsh
+!include Win\WinUser.nsh
+
+!ifndef __WIN_MS_NOWINMESSAGES
+!include WinMessages.nsh
+!endif
+
+
+
+
+
+/**************************************************
+WinBase.h
+**************************************************/
+!ifndef __WIN_NOINC_WINBASE
+!define /ifndef INVALID_HANDLE_VALUE -1
+!define /ifndef INVALID_FILE_SIZE 0xFFFFFFFF
+!define /ifndef INVALID_SET_FILE_POINTER -1
+!define /ifndef INVALID_FILE_ATTRIBUTES -1
+
+!define WAIT_FAILED 0xFFFFFFFF
+!define WAIT_OBJECT_0 0 ;((STATUS_WAIT_0 ) + 0 )
+
+!define WAIT_ABANDONED 0x80 ;((STATUS_ABANDONED_WAIT_0 ) + 0 )
+!define WAIT_ABANDONED_0 0x80 ;((STATUS_ABANDONED_WAIT_0 ) + 0 )
+
+!define DRIVE_UNKNOWN 0
+!define DRIVE_NO_ROOT_DIR 1
+!define DRIVE_REMOVABLE 2
+!define DRIVE_FIXED 3
+!define DRIVE_REMOTE 4
+!define DRIVE_CDROM 5
+!define DRIVE_RAMDISK 6
+
+!define FILE_TYPE_UNKNOWN 0x0000
+!define FILE_TYPE_DISK 0x0001
+!define FILE_TYPE_CHAR 0x0002
+!define FILE_TYPE_PIPE 0x0003
+!define FILE_TYPE_REMOTE 0x8000
+
+!define STD_INPUT_HANDLE -10
+!define STD_OUTPUT_HANDLE -11
+!define STD_ERROR_HANDLE -12
+
+#define IGNORE 0 ; Ignore signal
+!define INFINITE 0xFFFFFFFF ; Infinite timeout
+
+!endif /* __WIN_NOINC_WINBASE */
+
+
+
+
+
+/**************************************************
+WinGDI.h
+**************************************************/
+!ifndef __WIN_MS_NOGDI & __WIN_NOINC_WINGDI
+!define HORZRES 8
+!define VERTRES 10
+!define BITSPIXEL 12
+!define LOGPIXELSX 88
+!define LOGPIXELSY 90
+!define COLORRES 108
+!define VREFRESH 116
+!define DESKTOPVERTRES 117
+!define DESKTOPHORZRES 118
+!endif /* __WIN_MS_NOGDI & __WIN_NOINC_WINGDI */
+
+
+
+
+
+/**************************************************
+WinReg.h
+**************************************************/
+!ifndef __WIN_NOINC_WINREG
+!ifndef __WIN_NOHKEY & HKEY_CLASSES_ROOT & HKEY_CURRENT_USER & HKEY_LOCAL_MACHINE & HKEY_USERS
+!define HKEY_CLASSES_ROOT 0x80000000
+!define HKEY_CURRENT_USER 0x80000001
+!define HKEY_LOCAL_MACHINE 0x80000002
+!define HKEY_USERS 0x80000003
+!define HKEY_PERFORMANCE_DATA 0x80000004
+!define HKEY_PERFORMANCE_TEXT 0x80000050
+!define HKEY_PERFORMANCE_NLSTEXT 0x80000060
+!define HKEY_CURRENT_CONFIG 0x80000005
+!define HKEY_DYN_DATA 0x80000006
+!ifndef __WIN_NOSHORTHKEY & HKCR & HKCU & HKLM
+!define HKCR ${HKEY_CLASSES_ROOT}
+!define HKCU ${HKEY_CURRENT_USER}
+!define HKLM ${HKEY_LOCAL_MACHINE}
+!endif
+!endif
+!endif /* __WIN_NOINC_WINREG */
+
+
+
+
+
+/**************************************************
+WindowsX.h
+**************************************************/
+!ifndef __WIN_NOINC_WINDOWSX
+!ifndef GET_X_LPARAM & GET_Y_LPARAM
+!macro _Win_GET_X_LPARAM _outvar _in
+IntOp ${_outvar} "${_in}" << 16 ;We can't just use LOWORD, we need to keep the sign,
+IntOp ${_outvar} ${_outvar} >> 16 ;so we let NSIS sign extend for us
+!macroend
+!define GET_X_LPARAM "!insertmacro _Win_GET_X_LPARAM "
+!macro _Win_GET_Y_LPARAM _outvar _in
+IntOp ${_outvar} "${_in}" >> 16
+!macroend
+!define GET_Y_LPARAM "!insertmacro _Win_GET_Y_LPARAM "
+!endif
+!endif /* __WIN_NOINC_WINDOWSX */
+
+
+
+
+
+/**************************************************
+ShlObj.h
+**************************************************/
+!ifndef __WIN_NOINC_SHLOBJ
+!ifndef __WIN_NOSHELLFOLDERCSIDL
+!define CSIDL_DESKTOP 0x0000
+!define CSIDL_INTERNET 0x0001 ;Internet Explorer (icon on desktop)
+!define CSIDL_PROGRAMS 0x0002 ;Start Menu\Programs
+!define CSIDL_CONTROLS 0x0003 ;My Computer\Control Panel
+!define CSIDL_PRINTERS 0x0004 ;My Computer\Printers
+!define CSIDL_PERSONAL 0x0005 ;My Documents
+!define CSIDL_FAVORITES 0x0006 ;\Favorites
+!define CSIDL_STARTUP 0x0007 ;Start Menu\Programs\Startup
+!define CSIDL_RECENT 0x0008 ;\Recent
+!define CSIDL_SENDTO 0x0009 ;\SendTo
+!define CSIDL_BITBUCKET 0x000a ;\Recycle Bin
+!define CSIDL_STARTMENU 0x000b ;\Start Menu
+!define CSIDL_MYDOCUMENTS 0x000c ;logical "My Documents" desktop icon
+!define CSIDL_MYMUSIC 0x000d ;"My Music" folder
+!define CSIDL_MYVIDEO 0x000e ;"My Videos" folder
+!define CSIDL_DESKTOPDIRECTORY 0x0010 ;\Desktop
+!define CSIDL_DRIVES 0x0011 ;My Computer
+!define CSIDL_NETWORK 0x0012 ;Network Neighborhood
+!define CSIDL_NETHOOD 0x0013 ;\nethood
+!define CSIDL_FONTS 0x0014 ;windows\fonts
+!define CSIDL_TEMPLATES 0x0015
+!define CSIDL_COMMON_STARTMENU 0x0016 ;All Users\Start Menu
+!define CSIDL_COMMON_PROGRAMS 0x0017 ;All Users\Start Menu\Programs
+!define CSIDL_COMMON_STARTUP 0x0018 ;All Users\Startup
+!define CSIDL_COMMON_DESKTOPDIRECTORY 0x0019 ;All Users\Desktop
+!define CSIDL_APPDATA 0x001a ;\Application Data
+!define CSIDL_PRINTHOOD 0x001b ;\PrintHood
+!define CSIDL_LOCAL_APPDATA 0x001c ;\Local Settings\Application Data (non roaming)
+!define CSIDL_ALTSTARTUP 0x001d ;non localized startup
+!define CSIDL_COMMON_ALTSTARTUP 0x001e ;non localized common startup
+!define CSIDL_COMMON_FAVORITES 0x001f
+!define CSIDL_INTERNET_CACHE 0x0020
+!define CSIDL_COOKIES 0x0021
+!define CSIDL_HISTORY 0x0022
+!define CSIDL_COMMON_APPDATA 0x0023 ;All Users\Application Data
+!define CSIDL_WINDOWS 0x0024 ;GetWindowsDirectory
+!define CSIDL_SYSTEM 0x0025 ;GetSystemDirectory
+!define CSIDL_PROGRAM_FILES 0x0026 ;C:\Program Files
+!define CSIDL_MYPICTURES 0x0027
+!define CSIDL_PROFILE 0x0028 ;USERPROFILE
+!define CSIDL_SYSTEMX86 0x0029 ;x86 system directory on RISC
+!define CSIDL_PROGRAM_FILESX86 0x002a ;x86 C:\Program Files on RISC
+!define CSIDL_PROGRAM_FILES_COMMON 0x002b ;C:\Program Files\Common
+!define CSIDL_PROGRAM_FILES_COMMONX86 0x002c ;x86 Program Files\Common on RISC
+!define CSIDL_COMMON_TEMPLATES 0x002d ;All Users\Templates
+!define CSIDL_COMMON_DOCUMENTS 0x002e ;All Users\Documents
+!define CSIDL_COMMON_ADMINTOOLS 0x002f ;All Users\Start Menu\Programs\Administrative Tools
+!define CSIDL_ADMINTOOLS 0x0030 ;\Start Menu\Programs\Administrative Tools
+!define CSIDL_CONNECTIONS 0x0031 ;Network and Dial-up Connections
+!define CSIDL_COMMON_MUSIC 0x0035 ;All Users\My Music
+!define CSIDL_COMMON_PICTURES 0x0036 ;All Users\My Pictures
+!define CSIDL_COMMON_VIDEO 0x0037 ;All Users\My Video
+!define CSIDL_RESOURCES 0x0038 ;Resource Directory
+!define CSIDL_RESOURCES_LOCALIZED 0x0039 ;Localized Resource Directory
+!define CSIDL_COMMON_OEM_LINKS 0x003a ;Links to All Users OEM specific apps
+!define CSIDL_CDBURN_AREA 0x003b ;USERPROFILE\Local Settings\Application Data\Microsoft\CD Burning
+!define CSIDL_COMPUTERSNEARME 0x003d ;Computers Near Me (computered from Workgroup membership)
+!define CSIDL_FLAG_CREATE 0x8000 ;combine with CSIDL_ value to force folder creation in SHGetFolderPath()
+!define CSIDL_FLAG_DONT_VERIFY 0x4000 ;combine with CSIDL_ value to return an unverified folder path
+!define CSIDL_FLAG_NO_ALIAS 0x1000 ;combine with CSIDL_ value to insure non-alias versions of the pidl
+!define CSIDL_FLAG_PER_USER_INIT 0x0800 ;combine with CSIDL_ value to indicate per-user init (eg. upgrade)
+!define CSIDL_FLAG_MASK 0xFF00
+!endif /* __WIN_NOSHELLFOLDERCSIDL */
+!endif /* __WIN_NOINC_SHLOBJ */
+
+
+
+
+
+/**************************************************
+Shobjidl.h
+**************************************************/
+!ifndef __WIN_NOINC_SHOBJIDL
+; ASSOCIATIONLEVEL
+!define AL_MACHINE 0
+!define AL_EFFECTIVE 1
+!define AL_USER 2
+
+; ASSOCIATIONTYPE
+!define AT_FILEEXTENSION 0
+!define AT_URLPROTOCOL 1
+!define AT_STARTMENUCLIENT 2
+!define AT_MIMETYPE 3
+!endif /* __WIN_NOINC_SHOBJIDL */
+
+
+
+
+
+/**************************************************
+ShlGuid.h
+**************************************************/
+!ifndef __WIN_NOINC_SHLGUID
+!define FOLDERID_Public {DFDF76A2-C82A-4D63-906A-5644AC457385} ; Vista+ Fixed=%SystemDrive%\Users\Public
+!define FOLDERID_Games {CAC52C1A-B53D-4edc-92D7-6B2E8AC19434} ; Vista+ && < 10 (1803) Virtual
+!define FOLDERID_SavedGames {4C5C32FF-BB9D-43b0-B5B4-2D72E54EAAA4} ; Vista+ PerUser=%USERPROFILE%\Saved Games
+!define FOLDERID_GameTasks {054FAE61-4DD8-4787-80B6-090220C4B700} ; Vista+ PerUser=%LOCALAPPDATA%\Microsoft\Windows\GameExplorer
+!define FOLDERID_PublicGameTasks {DEBF2536-E1A8-4c59-B6A2-414586476AEA} ; Vista+ Common=%ALLUSERSPROFILE%\Microsoft\Windows\GameExplorer
+!define FOLDERID_Contacts {56784854-C6CB-462b-8169-88E350ACB882} ; Vista+ PerUser=%USERPROFILE%\Contacts
+!define FOLDERID_Downloads {374DE290-123F-4565-9164-39C4925E467B} ; Vista+ PerUser=%USERPROFILE%\Downloads
+!define FOLDERID_PublicDownloads {3D644C9B-1FB8-4f30-9B45-F670235F79C0} ; Vista+ Common=%PUBLIC%\Downloads
+!define FOLDERID_UserProfiles {0762D272-C50A-4BB0-A382-697DCD729B80} ; Vista+ Fixed=%SystemDrive%\Users
+!define FOLDERID_UserProgramFiles {5CD7AEE2-2219-4A67-B85D-6C9CE15660CB} ; 7+ PerUser=%LOCALAPPDATA%\Programs
+!define FOLDERID_UserProgramFilesCommon {BCBD3057-CA5C-4622-B42D-BC56DB0AE516} ; 7+ PerUser=%LOCALAPPDATA%\Programs\Common
+!define FOLDERID_PublicLibraries {48DAF80B-E6CF-4F4E-B800-0E69D84EE384} ; 7+ Common=%ALLUSERSPROFILE%\Microsoft\Windows\Libraries
+!define FOLDERID_UserPinned {9E3995AB-1F9C-4F13-B827-48B24B6C7174} ; 7+ PerUser=%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned
+!define FOLDERID_ImplicitAppShortcuts {BCB5256F-79F6-4CEE-B725-DC34E402FD46} ; 7+ PerUser=%APPDATA%\Microsoft\Internet Explorer\Quick Launch\User Pinned\ImplicitAppShortcuts
+!define FOLDERID_DeviceMetadataStore {5CE4A5E9-E4EB-479D-B89F-130C02886155} ; 7+ Common=%ALLUSERSPROFILE%\Microsoft\Windows\DeviceMetadataStore
+!define FOLDERID_ApplicationShortcuts {A3918781-E5F2-4890-B3D9-A7E54332328C} ; 8.0+ PerUser=%LOCALAPPDATA%\Microsoft\Windows\Application Shortcuts
+!define FOLDERID_RoamingTiles {00BCFC5A-ED94-4e48-96A1-3F6217F21990} ; 8.0+ PerUser=%LOCALAPPDATA%\Microsoft\Windows\RoamingTiles
+!define FOLDERID_RoamedTileImages {AAA8D5A5-F1D6-4259-BAA8-78E7EF60835E} ; 8.0+ PerUser=%LOCALAPPDATA%\Microsoft\Windows\RoamedTileImages
+!define FOLDERID_PublicUserTiles {0482af6c-08f1-4c34-8c90-e17ec98b1e17} ; 8.0+ Common=%PUBLIC%\AccountPictures
+!define FOLDERID_AccountPictures {008ca0b1-55b4-4c56-b8a8-4de4b299d3be} ; 8.0+ PerUser=%APPDATA%\Microsoft\Windows\AccountPictures
+!define FOLDERID_Screenshots {b7bede81-df94-4682-a7d8-57a52620b86f} ; 8.0+ PerUser=%USERPROFILE%\Pictures\Screenshots
+!define FOLDERID_SkyDrive {A52BBA46-E9E1-435f-B3D9-28DAA648C0F6} ; 8.1+ PerUser=%USERPROFILE%\OneDrive
+!define FOLDERID_AppDataProgramData {559D40A3-A036-40FA-AF61-84CB430A4D34} ; 10 (1709)+ PerUser=%LOCALAPPDATA%\ProgramData
+!endif /* __WIN_NOINC_SHLGUID */
+
+
+!verbose pop
+!endif /* __WIN_WINDOWS__INC */
\ No newline at end of file
diff --git a/installer/tools/Include/WinMessages.nsh b/installer/tools/Include/WinMessages.nsh
new file mode 100644
index 00000000..47d09dcd
--- /dev/null
+++ b/installer/tools/Include/WinMessages.nsh
@@ -0,0 +1,890 @@
+/*
+_____________________________________________________________________________
+
+ List of common Windows Messages
+_____________________________________________________________________________
+
+ 2005 Shengalts Aleksander aka Instructor (Shengalts@mail.ru)
+
+
+Usage example:
+---------------------------------------------------
+Name "Output"
+OutFile "Output.exe"
+
+!include "WinMessages.nsh"
+
+Section
+ FindWindow $0 '#32770' '' $HWNDPARENT
+ GetDlgItem $1 $0 1027
+ SendMessage $1 ${WM_SETTEXT} 0 'STR:MyText'
+SectionEnd
+---------------------------------------------------
+
+
+Prefix Message category
+-------------------------
+SW ShowWindow Commands
+CCM Generic Common Control
+BM Button control
+CB Combo box control
+EM Edit control
+LB List box control
+WM General window
+ABM Application desktop toolbar
+DBT Device
+DM Default push button control
+HDM Header control
+LVM List view control
+SB Status bar window
+SBM Scroll bar control
+STM Static control
+TCM Tab control
+PBM Progress bar
+ACM Animation control
+TBM Track bar
+UDM Up-down control
+HKM Hot key control
+IPM IP address control
+NCM Network address control
+-----------------------------------
+
+NOT included messages (WM_USER + X)
+-----------------------------------
+CBEM Extended combo box control
+CDM Common dialog box
+DL Drag list box
+PGM Pager control
+PSM Property sheet
+RB Rebar control
+TB Toolbar
+TTM Tooltip control
+TVM Tree-view control
+-----------------------------------
+*/
+
+
+!ifndef WINMESSAGES_INCLUDED
+!define WINMESSAGES_INCLUDED
+!verbose push
+!verbose 3
+
+!define _NSIS_DEFAW '!insertmacro _NSIS_DEFAW '
+!macro _NSIS_DEFAW d
+!ifdef NSIS_UNICODE
+!define ${d} "${${d}W}"
+!else
+!define ${d} "${${d}A}"
+!endif
+!macroend
+
+!define HWND_BROADCAST 0xFFFF
+
+#ShowWindow Commands#
+!define SW_HIDE 0
+!define SW_SHOWNORMAL 1
+!define SW_NORMAL 1
+!define SW_SHOWMINIMIZED 2
+!define SW_SHOWMAXIMIZED 3
+!define SW_MAXIMIZE 3
+!define SW_SHOWNOACTIVATE 4
+!define SW_SHOW 5
+!define SW_MINIMIZE 6
+!define SW_SHOWMINNOACTIVE 7
+!define SW_SHOWNA 8
+!define SW_RESTORE 9
+!define SW_SHOWDEFAULT 10
+!define SW_FORCEMINIMIZE 11
+!define SW_MAX 11
+
+#Generic Common Control Messages#
+!define CCM_FIRST 0x2000
+!define /math CCM_SETBKCOLOR ${CCM_FIRST} + 0x1 ; IE4
+!define /math CCM_SETUNICODEFORMAT ${CCM_FIRST} + 0x5
+!define /math CCM_GETUNICODEFORMAT ${CCM_FIRST} + 0x6
+!define /math CCM_SETVERSION ${CCM_FIRST} + 0x7 ; IE5
+!define /math CCM_GETVERSION ${CCM_FIRST} + 0x8
+!define /math CCM_SETWINDOWTHEME ${CCM_FIRST} + 0xB ; WinXP
+!define /math CCM_DPISCALE ${CCM_FIRST} + 0xC
+!define WM_USER 0x400
+
+!define CCS_TOP 1
+!define CCS_BOTTOM 3
+!define CCS_NODIVIDER 64
+!define CCS_LEFT 129
+!define CCS_RIGHT 131
+
+!define I_IMAGENONE -2
+
+#Button Control Messages#
+!define BM_CLICK 0x00F5
+!define BM_GETCHECK 0x00F0
+!define BM_GETIMAGE 0x00F6
+!define BM_GETSTATE 0x00F2
+!define BM_SETCHECK 0x00F1
+!define BM_SETIMAGE 0x00F7
+!define BM_SETSTATE 0x00F3
+!define BM_SETSTYLE 0x00F4
+!define BCM_SETSHIELD 0x160C ; WinVista + ComCtl32 v6
+
+!define BST_UNCHECKED 0
+!define BST_CHECKED 1
+!define BST_INDETERMINATE 2
+!define BST_PUSHED 4
+!define BST_FOCUS 8
+
+#Combo Box Messages#
+!define CB_ADDSTRING 0x0143
+!define CB_DELETESTRING 0x0144
+!define CB_DIR 0x0145
+!define CB_FINDSTRING 0x014C
+!define CB_FINDSTRINGEXACT 0x0158
+!define CB_GETCOUNT 0x0146
+!define CB_GETCURSEL 0x0147
+!define CB_GETDROPPEDCONTROLRECT 0x0152
+!define CB_GETDROPPEDSTATE 0x0157
+!define CB_GETDROPPEDWIDTH 0x015f
+!define CB_GETEDITSEL 0x0140
+!define CB_GETEXTENDEDUI 0x0156
+!define CB_GETHORIZONTALEXTENT 0x015d
+!define CB_GETITEMDATA 0x0150
+!define CB_GETITEMHEIGHT 0x0154
+!define CB_GETLBTEXT 0x0148
+!define CB_GETLBTEXTLEN 0x0149
+!define CB_GETLOCALE 0x015A
+!define CB_GETTOPINDEX 0x015b
+!define CB_INITSTORAGE 0x0161
+!define CB_INSERTSTRING 0x014A
+!define CB_LIMITTEXT 0x0141
+!define CB_MSGMAX 0x015B # 0x0162 0x0163
+!define CB_MULTIPLEADDSTRING 0x0163
+!define CB_RESETCONTENT 0x014B
+!define CB_SELECTSTRING 0x014D
+!define CB_SETCURSEL 0x014E
+!define CB_SETDROPPEDWIDTH 0x0160
+!define CB_SETEDITSEL 0x0142
+!define CB_SETEXTENDEDUI 0x0155
+!define CB_SETHORIZONTALEXTENT 0x015e
+!define CB_SETITEMDATA 0x0151
+!define CB_SETITEMHEIGHT 0x0153
+!define CB_SETLOCALE 0x0159
+!define CB_SETTOPINDEX 0x015c
+!define CB_SHOWDROPDOWN 0x014F
+!define CBM_FIRST 0x1700 ; Vista+
+!define /math CB_SETMINVISIBLE ${CBM_FIRST} + 1
+!define /math CB_GETMINVISIBLE ${CBM_FIRST} + 2
+!define /math CB_SETCUEBANNER ${CBM_FIRST} + 3
+!define /math CB_GETCUEBANNER ${CBM_FIRST} + 4
+
+!define CB_ERR -1
+
+#Edit Control Messages#
+!define EM_CANUNDO 0x00C6
+!define EM_CHARFROMPOS 0x00D7
+!define EM_EMPTYUNDOBUFFER 0x00CD
+!define EM_FMTLINES 0x00C8
+!define EM_GETFIRSTVISIBLELINE 0x00CE
+!define EM_GETHANDLE 0x00BD
+!define EM_GETIMESTATUS 0x00D9
+!define EM_GETLIMITTEXT 0x00D5
+!define EM_GETLINE 0x00C4
+!define EM_GETLINECOUNT 0x00BA
+!define EM_GETMARGINS 0x00D4
+!define EM_GETMODIFY 0x00B8
+!define EM_GETPASSWORDCHAR 0x00D2
+!define EM_GETRECT 0x00B2
+!define EM_GETSEL 0x00B0
+!define EM_GETTHUMB 0x00BE
+!define EM_GETWORDBREAKPROC 0x00D1
+!define EM_LIMITTEXT 0x00C5
+!define EM_LINEFROMCHAR 0x00C9
+!define EM_LINEINDEX 0x00BB
+!define EM_LINELENGTH 0x00C1
+!define EM_LINESCROLL 0x00B6
+!define EM_POSFROMCHAR 0x00D6
+!define EM_REPLACESEL 0x00C2
+!define EM_SCROLL 0x00B5
+!define EM_SCROLLCARET 0x00B7
+!define EM_SETHANDLE 0x00BC
+!define EM_SETIMESTATUS 0x00D8
+!define EM_SETLIMITTEXT 0x00C5 # Same as EM_LIMITTEXT
+!define EM_SETMARGINS 0x00D3
+!define EM_SETMODIFY 0x00B9
+!define EM_SETPASSWORDCHAR 0x00CC
+!define EM_SETREADONLY 0x00CF
+!define EM_SETRECT 0x00B3
+!define EM_SETRECTNP 0x00B4
+!define EM_SETSEL 0x00B1
+!define EM_SETTABSTOPS 0x00CB
+!define EM_SETWORDBREAKPROC 0x00D0
+!define EM_UNDO 0x00C7
+!define ECM_FIRST 0x1500 ; CC6+
+!define /math EM_SETCUEBANNER ${ECM_FIRST} + 1
+
+#RichEdit Messages#
+!define /math EM_EXGETSEL ${WM_USER} + 52
+!define /math EM_EXLIMITTEXT ${WM_USER} + 53
+!define /math EM_EXLINEFROMCHAR ${WM_USER} + 54
+!define /math EM_GETEVENTMASK ${WM_USER} + 59
+!define /math EM_GETOLEINTERFACE ${WM_USER} + 60
+!define /math EM_HIDESELECTION ${WM_USER} + 63
+!define /math EM_SETBKGNDCOLOR ${WM_USER} + 67
+!define /math EM_SETEVENTMASK ${WM_USER} + 69
+!define /math EM_STREAMIN ${WM_USER} + 73
+!define /math EM_STREAMOUT ${WM_USER} + 74
+!define /math EM_GETTEXTRANGE ${WM_USER} + 75
+!define /math EM_SETOPTIONS ${WM_USER} + 77
+!define /math EM_GETOPTIONS ${WM_USER} + 78
+!define /math EM_SETUNDOLIMIT ${WM_USER} + 82 ; v2+
+!define /math EM_AUTOURLDETECT ${WM_USER} + 91
+!define /Math EM_SETTEXTEX ${WM_USER} + 97 ; v3+
+!define /math EM_SETEDITSTYLE ${WM_USER} + 204
+!define /math EM_SETFONTSIZE ${WM_USER} + 223
+
+!define EN_MSGFILTER 0x0700
+!define EN_SELCHANGE 0x0702
+!define EN_LINK 0x070b
+
+!define ENM_NONE 0x00000000
+!define ENM_CHANGE 0x00000001
+!define ENM_UPDATE 0x00000002
+!define ENM_SCROLL 0x00000004
+!define ENM_SCROLLEVENTS 0x00000008
+!define ENM_KEYEVENTS 0x00010000
+!define ENM_MOUSEEVENTS 0x00020000
+!define ENM_SELCHANGE 0x00080000
+!define ENM_LINK 0x04000000 ; v2+
+
+#Listbox Messages#
+!define LB_ADDFILE 0x0196
+!define LB_ADDSTRING 0x0180
+!define LB_DELETESTRING 0x0182
+!define LB_DIR 0x018D
+!define LB_FINDSTRING 0x018F
+!define LB_FINDSTRINGEXACT 0x01A2
+!define LB_GETANCHORINDEX 0x019D
+!define LB_GETCARETINDEX 0x019F
+!define LB_GETCOUNT 0x018B
+!define LB_GETCURSEL 0x0188
+!define LB_GETHORIZONTALEXTENT 0x0193
+!define LB_GETITEMDATA 0x0199
+!define LB_GETITEMHEIGHT 0x01A1
+!define LB_GETITEMRECT 0x0198
+!define LB_GETLOCALE 0x01A6
+!define LB_GETSEL 0x0187
+!define LB_GETSELCOUNT 0x0190
+!define LB_GETSELITEMS 0x0191
+!define LB_GETTEXT 0x0189
+!define LB_GETTEXTLEN 0x018A
+!define LB_GETTOPINDEX 0x018E
+!define LB_INITSTORAGE 0x01A8
+!define LB_INSERTSTRING 0x0181
+!define LB_ITEMFROMPOINT 0x01A9
+!define LB_MSGMAX 0x01A8 # 0x01B0 0x01B1
+!define LB_MULTIPLEADDSTRING 0x01B1
+!define LB_RESETCONTENT 0x0184
+!define LB_SELECTSTRING 0x018C
+!define LB_SELITEMRANGE 0x019B
+!define LB_SELITEMRANGEEX 0x0183
+!define LB_SETANCHORINDEX 0x019C
+!define LB_SETCARETINDEX 0x019E
+!define LB_SETCOLUMNWIDTH 0x0195
+!define LB_SETCOUNT 0x01A7
+!define LB_SETCURSEL 0x0186
+!define LB_SETHORIZONTALEXTENT 0x0194
+!define LB_SETITEMDATA 0x019A
+!define LB_SETITEMHEIGHT 0x01A0
+!define LB_SETLOCALE 0x01A5
+!define LB_SETSEL 0x0185
+!define LB_SETTABSTOPS 0x0192
+!define LB_SETTOPINDEX 0x0197
+
+!define LB_ERR -1
+
+#Window Messages#
+!define WM_ACTIVATE 0x0006
+!define WM_ACTIVATEAPP 0x001C
+!define WM_AFXFIRST 0x0360
+!define WM_AFXLAST 0x037F
+!define WM_APP 0x8000
+!define WM_APPCOMMAND 0x0319
+!define WM_ASKCBFORMATNAME 0x030C
+!define WM_CANCELJOURNAL 0x004B
+!define WM_CANCELMODE 0x001F
+!define WM_CAPTURECHANGED 0x0215
+!define WM_CHANGECBCHAIN 0x030D
+!define WM_CHANGEUISTATE 0x0127
+!define WM_CHAR 0x0102
+!define WM_CHARTOITEM 0x002F
+!define WM_CHILDACTIVATE 0x0022
+!define WM_CLEAR 0x0303
+!define WM_CLOSE 0x0010
+!define WM_COMMAND 0x0111
+!define WM_COMMNOTIFY 0x0044 # no longer supported
+!define WM_COMPACTING 0x0041
+!define WM_COMPAREITEM 0x0039
+!define WM_CONTEXTMENU 0x007B
+!define WM_CONVERTREQUESTEX 0x108
+!define WM_COPY 0x0301
+!define WM_COPYDATA 0x004A
+!define WM_CREATE 0x0001
+!define WM_CTLCOLOR 0x0019
+!define WM_CTLCOLORBTN 0x0135
+!define WM_CTLCOLORDLG 0x0136
+!define WM_CTLCOLOREDIT 0x0133
+!define WM_CTLCOLORLISTBOX 0x0134
+!define WM_CTLCOLORMSGBOX 0x0132
+!define WM_CTLCOLORSCROLLBAR 0x0137
+!define WM_CTLCOLORSTATIC 0x0138
+!define WM_CUT 0x0300
+!define WM_DDE_FIRST 0x3E0
+!define WM_DEADCHAR 0x0103
+!define WM_DELETEITEM 0x002D
+!define WM_DESTROY 0x0002
+!define WM_DESTROYCLIPBOARD 0x0307
+!define WM_DEVICECHANGE 0x0219
+!define WM_DEVMODECHANGE 0x001B
+!define WM_DISPLAYCHANGE 0x007E
+!define WM_DRAWCLIPBOARD 0x0308
+!define WM_DRAWITEM 0x002B
+!define WM_DROPFILES 0x0233
+!define WM_ENABLE 0x000A
+!define WM_ENDSESSION 0x0016
+!define WM_ENTERIDLE 0x0121
+!define WM_ENTERMENULOOP 0x0211
+!define WM_ENTERSIZEMOVE 0x0231
+!define WM_ERASEBKGND 0x0014
+!define WM_EXITMENULOOP 0x0212
+!define WM_EXITSIZEMOVE 0x0232
+!define WM_FONTCHANGE 0x001D
+!define WM_GETDLGCODE 0x0087
+!define WM_GETFONT 0x0031
+!define WM_GETHOTKEY 0x0033
+!define WM_GETICON 0x007F
+!define WM_GETMINMAXINFO 0x0024
+!define WM_GETOBJECT 0x003D
+!define WM_GETTEXT 0x000D
+!define WM_GETTEXTLENGTH 0x000E
+!define WM_HANDHELDFIRST 0x0358
+!define WM_HANDHELDLAST 0x035F
+!define WM_HELP 0x0053
+!define WM_HOTKEY 0x0312
+!define WM_HSCROLL 0x0114
+!define WM_HSCROLLCLIPBOARD 0x030E
+!define WM_ICONERASEBKGND 0x0027
+!define WM_IME_CHAR 0x0286
+!define WM_IME_COMPOSITION 0x010F
+!define WM_IME_COMPOSITIONFULL 0x0284
+!define WM_IME_CONTROL 0x0283
+!define WM_IME_ENDCOMPOSITION 0x010E
+!define WM_IME_KEYDOWN 0x0290
+!define WM_IME_KEYLAST 0x010F
+!define WM_IME_KEYUP 0x0291
+!define WM_IME_NOTIFY 0x0282
+!define WM_IME_REQUEST 0x0288
+!define WM_IME_SELECT 0x0285
+!define WM_IME_SETCONTEXT 0x0281
+!define WM_IME_STARTCOMPOSITION 0x010D
+!define WM_INITDIALOG 0x0110
+!define WM_INITMENU 0x0116
+!define WM_INITMENUPOPUP 0x0117
+!define WM_INPUT 0x00FF
+!define WM_INPUTLANGCHANGE 0x0051
+!define WM_INPUTLANGCHANGEREQUEST 0x0050
+!define WM_KEYDOWN 0x0100
+!define WM_KEYFIRST 0x0100
+!define WM_KEYLAST 0x0108
+!define WM_KEYUP 0x0101
+!define WM_KILLFOCUS 0x0008
+!define WM_LBUTTONDBLCLK 0x0203
+!define WM_LBUTTONDOWN 0x0201
+!define WM_LBUTTONUP 0x0202
+!define WM_MBUTTONDBLCLK 0x0209
+!define WM_MBUTTONDOWN 0x0207
+!define WM_MBUTTONUP 0x0208
+!define WM_MDIACTIVATE 0x0222
+!define WM_MDICASCADE 0x0227
+!define WM_MDICREATE 0x0220
+!define WM_MDIDESTROY 0x0221
+!define WM_MDIGETACTIVE 0x0229
+!define WM_MDIICONARRANGE 0x0228
+!define WM_MDIMAXIMIZE 0x0225
+!define WM_MDINEXT 0x0224
+!define WM_MDIREFRESHMENU 0x0234
+!define WM_MDIRESTORE 0x0223
+!define WM_MDISETMENU 0x0230
+!define WM_MDITILE 0x0226
+!define WM_MEASUREITEM 0x002C
+!define WM_MENUCHAR 0x0120
+!define WM_MENUCOMMAND 0x0126
+!define WM_MENUDRAG 0x0123
+!define WM_MENUGETOBJECT 0x0124
+!define WM_MENURBUTTONUP 0x0122
+!define WM_MENUSELECT 0x011F
+!define WM_MOUSEACTIVATE 0x0021
+!define WM_MOUSEFIRST 0x0200
+!define WM_MOUSEHOVER 0x02A1
+!define WM_MOUSELAST 0x0209 # 0x020A 0x020D
+!define WM_MOUSELEAVE 0x02A3
+!define WM_MOUSEMOVE 0x0200
+!define WM_MOUSEWHEEL 0x020A
+!define WM_MOVE 0x0003
+!define WM_MOVING 0x0216
+!define WM_NCACTIVATE 0x0086
+!define WM_NCCALCSIZE 0x0083
+!define WM_NCCREATE 0x0081
+!define WM_NCDESTROY 0x0082
+!define WM_NCHITTEST 0x0084
+!define WM_NCLBUTTONDBLCLK 0x00A3
+!define WM_NCLBUTTONDOWN 0x00A1
+!define WM_NCLBUTTONUP 0x00A2
+!define WM_NCMBUTTONDBLCLK 0x00A9
+!define WM_NCMBUTTONDOWN 0x00A7
+!define WM_NCMBUTTONUP 0x00A8
+!define WM_NCMOUSEHOVER 0x02A0
+!define WM_NCMOUSELEAVE 0x02A2
+!define WM_NCMOUSEMOVE 0x00A0
+!define WM_NCPAINT 0x0085
+!define WM_NCRBUTTONDBLCLK 0x00A6
+!define WM_NCRBUTTONDOWN 0x00A4
+!define WM_NCRBUTTONUP 0x00A5
+!define WM_NCXBUTTONDBLCLK 0x00AD
+!define WM_NCXBUTTONDOWN 0x00AB
+!define WM_NCXBUTTONUP 0x00AC
+!define WM_NEXTDLGCTL 0x0028
+!define WM_NEXTMENU 0x0213
+!define WM_NOTIFY 0x004E
+!define WM_NOTIFYFORMAT 0x0055
+!define WM_NULL 0x0000
+!define WM_PAINT 0x000F
+!define WM_PAINTCLIPBOARD 0x0309
+!define WM_PAINTICON 0x0026
+!define WM_PALETTECHANGED 0x0311
+!define WM_PALETTEISCHANGING 0x0310
+!define WM_PARENTNOTIFY 0x0210
+!define WM_PASTE 0x0302
+!define WM_PENWINFIRST 0x0380
+!define WM_PENWINLAST 0x038F
+!define WM_POWER 0x0048
+!define WM_POWERBROADCAST 0x0218
+!define WM_PRINT 0x0317
+!define WM_PRINTCLIENT 0x0318
+!define WM_QUERYDRAGICON 0x0037
+!define WM_QUERYENDSESSION 0x0011
+!define WM_QUERYNEWPALETTE 0x030F
+!define WM_QUERYOPEN 0x0013
+!define WM_QUERYUISTATE 0x0129
+!define WM_QUEUESYNC 0x0023
+!define WM_QUIT 0x0012
+!define WM_RBUTTONDBLCLK 0x0206
+!define WM_RBUTTONDOWN 0x0204
+!define WM_RBUTTONUP 0x0205
+!define WM_RASDIALEVENT 0xCCCD
+!define WM_RENDERALLFORMATS 0x0306
+!define WM_RENDERFORMAT 0x0305
+!define WM_SETCURSOR 0x0020
+!define WM_SETFOCUS 0x0007
+!define WM_SETFONT 0x0030
+!define WM_SETHOTKEY 0x0032
+!define WM_SETICON 0x0080
+!define WM_SETREDRAW 0x000B
+!define WM_SETTEXT 0x000C
+!define WM_SETTINGCHANGE 0x001A # Same as WM_WININICHANGE
+!define WM_SHOWWINDOW 0x0018
+!define WM_SIZE 0x0005
+!define WM_SIZECLIPBOARD 0x030B
+!define WM_SIZING 0x0214
+!define WM_SPOOLERSTATUS 0x002A
+!define WM_STYLECHANGED 0x007D
+!define WM_STYLECHANGING 0x007C
+!define WM_SYNCPAINT 0x0088
+!define WM_SYSCHAR 0x0106
+!define WM_SYSCOLORCHANGE 0x0015
+!define WM_SYSCOMMAND 0x0112
+!define WM_SYSDEADCHAR 0x0107
+!define WM_SYSKEYDOWN 0x0104
+!define WM_SYSKEYUP 0x0105
+!define WM_TABLET_FIRST 0x02C0
+!define WM_TABLET_LAST 0x02DF
+!define WM_THEMECHANGED 0x031A
+!define WM_TCARD 0x0052
+!define WM_TIMECHANGE 0x001E
+!define WM_TIMER 0x0113
+!define WM_UNDO 0x0304
+!define WM_UNICHAR 0x0109
+!define WM_UNINITMENUPOPUP 0x0125
+!define WM_UPDATEUISTATE 0x0128
+!define WM_USERCHANGED 0x0054
+!define WM_VKEYTOITEM 0x002E
+!define WM_VSCROLL 0x0115
+!define WM_VSCROLLCLIPBOARD 0x030A
+!define WM_WINDOWPOSCHANGED 0x0047
+!define WM_WINDOWPOSCHANGING 0x0046
+!define WM_WININICHANGE 0x001A
+!define WM_WTSSESSION_CHANGE 0x02B1
+!define WM_XBUTTONDBLCLK 0x020D
+!define WM_XBUTTONDOWN 0x020B
+!define WM_XBUTTONUP 0x020C
+
+
+#Application desktop toolbar#
+!define ABM_ACTIVATE 0x00000006 # lParam == TRUE/FALSE means activate/deactivate
+!define ABM_GETAUTOHIDEBAR 0x00000007
+!define ABM_GETSTATE 0x00000004
+!define ABM_GETTASKBARPOS 0x00000005
+!define ABM_NEW 0x00000000
+!define ABM_QUERYPOS 0x00000002
+!define ABM_REMOVE 0x00000001
+!define ABM_SETAUTOHIDEBAR 0x00000008 # This can fail, you MUST check the result
+!define ABM_SETPOS 0x00000003
+!define ABM_WINDOWPOSCHANGED 0x0000009
+
+#Device#
+!define DBT_APPYBEGIN 0x0000
+!define DBT_APPYEND 0x0001
+!define DBT_CONFIGCHANGECANCELED 0x0019
+!define DBT_CONFIGCHANGED 0x0018
+!define DBT_CONFIGMGAPI32 0x0022
+!define DBT_CONFIGMGPRIVATE 0x7FFF
+!define DBT_CUSTOMEVENT 0x8006 # User-defined event
+!define DBT_DEVICEARRIVAL 0x8000 # System detected a new device
+!define DBT_DEVICEQUERYREMOVE 0x8001 # Wants to remove, may fail
+!define DBT_DEVICEQUERYREMOVEFAILED 0x8002 # Removal aborted
+!define DBT_DEVICEREMOVECOMPLETE 0x8004 # Device is gone
+!define DBT_DEVICEREMOVEPENDING 0x8003 # About to remove, still avail.
+!define DBT_DEVICETYPESPECIFIC 0x8005 # Type specific event
+!define DBT_DEVNODES_CHANGED 0x0007
+!define DBT_DEVTYP_DEVICEINTERFACE 0x00000005 # Device interface class
+!define DBT_DEVTYP_DEVNODE 0x00000001 # Devnode number
+!define DBT_DEVTYP_HANDLE 0x00000006 # File system handle
+!define DBT_DEVTYP_NET 0x00000004 # Network resource
+!define DBT_DEVTYP_OEM 0x00000000 # Oem-defined device type
+!define DBT_DEVTYP_PORT 0x00000003 # Serial, parallel
+!define DBT_DEVTYP_VOLUME 0x00000002 # Logical volume
+!define DBT_LOW_DISK_SPACE 0x0048
+!define DBT_MONITORCHANGE 0x001B
+!define DBT_NO_DISK_SPACE 0x0047
+!define DBT_QUERYCHANGECONFIG 0x0017
+!define DBT_SHELLLOGGEDON 0x0020
+!define DBT_USERDEFINED 0xFFFF
+!define DBT_VOLLOCKLOCKFAILED 0x8043
+!define DBT_VOLLOCKLOCKRELEASED 0x8045
+!define DBT_VOLLOCKLOCKTAKEN 0x8042
+!define DBT_VOLLOCKQUERYLOCK 0x8041
+!define DBT_VOLLOCKQUERYUNLOCK 0x8044
+!define DBT_VOLLOCKUNLOCKFAILED 0x8046
+!define DBT_VPOWERDAPI 0x8100 # VPOWERD API for Win95
+!define DBT_VXDINITCOMPLETE 0x0023
+
+#Default push button control#
+!define DM_BITSPERPEL 0x00040000
+!define DM_COLLATE 0x00008000
+!define DM_COLOR 0x00000800
+!define DM_COPIES 0x00000100
+!define DM_DEFAULTSOURCE 0x00000200
+!define DM_DISPLAYFLAGS 0x00200000
+!define DM_DISPLAYFREQUENCY 0x00400000
+!define DM_DITHERTYPE 0x04000000
+!define DM_DUPLEX 0x00001000
+!define DM_FORMNAME 0x00010000
+!define DM_GRAYSCALE 0x00000001 # This flag is no longer valid
+!define DM_ICMINTENT 0x01000000
+!define DM_ICMMETHOD 0x00800000
+!define DM_INTERLACED 0x00000002 # This flag is no longer valid
+!define DM_LOGPIXELS 0x00020000
+!define DM_MEDIATYPE 0x02000000
+!define DM_NUP 0x00000040
+!define DM_ORIENTATION 0x00000001
+!define DM_PANNINGHEIGHT 0x10000000
+!define DM_PANNINGWIDTH 0x08000000
+!define DM_PAPERLENGTH 0x00000004
+!define DM_PAPERSIZE 0x00000002
+!define DM_PAPERWIDTH 0x00000008
+!define DM_PELSHEIGHT 0x00100000
+!define DM_PELSWIDTH 0x00080000
+!define DM_POSITION 0x00000020
+!define DM_PRINTQUALITY 0x00000400
+!define DM_SCALE 0x00000010
+!define DM_SPECVERSION 0x0320 # 0x0400 0x0401
+!define DM_TTOPTION 0x00004000
+!define DM_YRESOLUTION 0x00002000
+
+#Header control#
+!define HDM_FIRST 0x1200
+
+#List view control#
+!define LVS_SINGLESEL 4
+!define LVS_SHOWSELALWAYS 8
+!define LVS_SORTASCENDING 0x10
+!define LVS_SORTDESCENDING 0x20
+!define LVS_SHAREIMAGELISTS 0x40
+!define LVS_EDITLABELS 0x200
+!define LVS_NOSCROLL 0x2000
+!define LVS_NOCOLUMNHEADER 0x4000
+!define LVS_NOSORTHEADER 0x8000
+!define LVS_ICON 0
+!define LVS_REPORT 1
+!define LVS_SMALLICON 2
+!define LVS_LIST 3
+!define LVS_EX_CHECKBOXES 4
+!define LVS_EX_FULLROWSELECT 0x20
+!define LVS_EX_INFOTIP 0x400
+!define LVS_EX_LABELTIP 0x4000
+!define LVS_EX_DOUBLEBUFFER 0x10000
+!define LVIF_TEXT 1
+!define LVIF_IMAGE 2
+!define LVIF_PARAM 4
+!define LVIF_STATE 8
+!define LVIS_STATEIMAGEMASK 0xF000
+!define LVCF_FMT 1
+!define LVCF_WIDTH 2
+!define LVCF_TEXT 4
+!define LVCF_SUBITEM 8
+!define SYSSTRUCT_LVITEM_V1 (i,i,i,i,&i${NSIS_PTR_SIZE},t,i,i,p)
+!define SYSSTRUCT_LVITEM_V2 (i,i,i,i,&i${NSIS_PTR_SIZE},t,i,i,p,i) ; IE3
+!define SYSSTRUCT_LVITEM_V3 (i,i,i,i,&i${NSIS_PTR_SIZE},t,i,i,p,i,i,i,i) ; WinXP + ComCtl32 v6
+!define SYSSTRUCT_LVITEM_V4 (i,i,i,i,&i${NSIS_PTR_SIZE},t,i,i,p,i,i,i,i,i,i) ; WinVista + ComCtl32 v6
+!define LVSCW_AUTOSIZE -1
+!define LVSCW_AUTOSIZE_USEHEADER -2
+!define LVM_FIRST 0x00001000
+!define /math LVM_GETIMAGELIST ${LVM_FIRST} + 2
+!define /math LVM_SETIMAGELIST ${LVM_FIRST} + 3
+!define /math LVM_GETITEMCOUNT ${LVM_FIRST} + 4
+!define /math LVM_GETITEMA ${LVM_FIRST} + 5
+!define /math LVM_SETITEMA ${LVM_FIRST} + 6
+!define /math LVM_INSERTITEMA ${LVM_FIRST} + 7
+!define /math LVM_DELETEITEM ${LVM_FIRST} + 8
+!define /math LVM_DELETEALLITEMS ${LVM_FIRST} + 9
+!define /math LVM_INSERTCOLUMNA ${LVM_FIRST} + 27
+!define /math LVM_SETCOLUMNWIDTH ${LVM_FIRST} + 30
+!define /math LVM_SETITEMSTATE ${LVM_FIRST} + 43
+!define /math LVM_GETITEMSTATE ${LVM_FIRST} + 44
+!define /math LVM_GETITEMTEXTA ${LVM_FIRST} + 45
+!define /math LVM_SETITEMTEXTA ${LVM_FIRST} + 46
+!define /math LVM_SETITEMCOUNT ${LVM_FIRST} + 47
+!define /math LVM_SORTITEMS ${LVM_FIRST} + 48
+!define /math LVM_SETEXTENDEDLISTVIEWSTYLE ${LVM_FIRST} + 54
+!define /math LVM_GETEXTENDEDLISTVIEWSTYLE ${LVM_FIRST} + 55
+!define /math LVM_GETITEMW ${LVM_FIRST} + 75
+!define /math LVM_SETITEMW ${LVM_FIRST} + 76
+!define /math LVM_INSERTITEMW ${LVM_FIRST} + 77
+!define /math LVM_INSERTCOLUMNW ${LVM_FIRST} + 97
+!define /math LVM_GETITEMTEXTW ${LVM_FIRST} + 115
+!define /math LVM_SETITEMTEXTW ${LVM_FIRST} + 116
+!define /math LVM_SETSELECTEDCOLUMN ${LVM_FIRST} + 140
+${_NSIS_DEFAW} LVM_GETITEM
+${_NSIS_DEFAW} LVM_SETITEM
+${_NSIS_DEFAW} LVM_INSERTITEM
+${_NSIS_DEFAW} LVM_INSERTCOLUMN
+${_NSIS_DEFAW} LVM_GETITEMTEXT
+${_NSIS_DEFAW} LVM_SETITEMTEXT
+
+#Status bar window#
+!define SB_SIMPLEID 0x00ff
+
+#Scroll bar control#
+!define SBM_ENABLE_ARROWS 0x00E4 # Not in win3.1
+!define SBM_GETPOS 0x00E1 # Not in win3.1
+!define SBM_GETRANGE 0x00E3 # Not in win3.1
+!define SBM_GETSCROLLINFO 0x00EA
+!define SBM_SETPOS 0x00E0 # Not in win3.1
+!define SBM_SETRANGE 0x00E2 # Not in win3.1
+!define SBM_SETRANGEREDRAW 0x00E6 # Not in win3.1
+!define SBM_SETSCROLLINFO 0x00E9
+
+#Static control#
+!define STM_SETICON 0x0170
+!define STM_GETICON 0x0171
+!define STM_SETIMAGE 0x0172
+!define STM_GETIMAGE 0x0173
+!define STM_MSGMAX 0x0174
+
+#Tab control#
+!define TCS_SCROLLOPPOSITE 0x0001
+!define TCIF_TEXT 1
+!define TCIF_PARAM 8
+!define SYSSTRUCT_TCITEM (i,i,&i${NSIS_PTR_SIZE},t,i,i,p)
+!define TCM_FIRST 0x1300
+!define /math TCM_INSERTITEMA ${TCM_FIRST} + 7
+!define /math TCM_GETCURSEL ${TCM_FIRST} + 11
+!define /math TCM_ADJUSTRECT ${TCM_FIRST} + 40
+!define /math TCM_INSERTITEMW ${TCM_FIRST} + 62
+!define TCN_SELCHANGE -551
+!define TCN_SELCHANGING -552
+${_NSIS_DEFAW} TCM_INSERTITEM
+
+#Progress bar control#
+!define PBM_SETRANGE 0x401
+!define PBM_SETPOS 0x402
+!define PBM_DELTAPOS 0x403
+!define PBM_SETSTEP 0x404
+!define PBM_STEPIT 0x405
+!define PBM_SETRANGE32 0x406 ; IE3 + ComCtl32 v4.70
+!define PBM_GETRANGE 0x407
+!define PBM_GETPOS 0x408
+!define PBM_SETBARCOLOR 0x409 ; IE4 + ComCtl32 v4.71
+!define PBM_SETBKCOLOR ${CCM_SETBKCOLOR}
+!define PBM_SETMARQUEE 0x40A ; WinXP + ComCtl32 v6
+!define PBM_GETSTEP 0x40D ; WinVista
+!define PBM_GETBKCOLOR 0x40E
+!define PBM_GETBARCOLOR 0x40F
+!define PBM_SETSTATE 0x410
+!define PBM_GETSTATE 0x411
+
+!define PBST_NORMAL 1
+!define PBST_ERROR 2
+!define PBST_PAUSED 3
+
+#Animation control#
+!define /math ACM_OPENA ${WM_USER} + 100
+!define /math ACM_PLAY ${WM_USER} + 101
+!define /math ACM_STOP ${WM_USER} + 102
+!define /math ACM_OPENW ${WM_USER} + 103
+${_NSIS_DEFAW} ACM_OPEN
+
+#TrackBar control#
+!define /math TBM_GETPOS ${WM_USER} + 0
+!define /math TBM_GETRANGEMIN ${WM_USER} + 1
+!define /math TBM_GETRANGEMAX ${WM_USER} + 2
+!define /math TBM_GETTIC ${WM_USER} + 3
+!define /math TBM_SETTIC ${WM_USER} + 4
+!define /math TBM_SETPOS ${WM_USER} + 5
+!define /math TBM_SETRANGE ${WM_USER} + 6
+!define /math TBM_SETRANGEMIN ${WM_USER} + 7
+!define /math TBM_SETRANGEMAX ${WM_USER} + 8
+!define /math TBM_CLEARTICS ${WM_USER} + 9
+!define /math TBM_SETSEL ${WM_USER} + 10
+!define /math TBM_SETSELSTART ${WM_USER} + 11
+!define /math TBM_SETSELEND ${WM_USER} + 12
+!define /math TBM_GETPTICS ${WM_USER} + 14
+!define /math TBM_GETTICPOS ${WM_USER} + 15
+!define /math TBM_GETNUMTICS ${WM_USER} + 16
+!define /math TBM_GETSELSTART ${WM_USER} + 17
+!define /math TBM_GETSELEND ${WM_USER} + 18
+!define /math TBM_CLEARSEL ${WM_USER} + 19
+!define /math TBM_SETTICFREQ ${WM_USER} + 20 ; TBS_AUTOTICKS required
+!define /math TBM_SETPAGESIZE ${WM_USER} + 21
+!define /math TBM_GETPAGESIZE ${WM_USER} + 22
+!define /math TBM_SETLINESIZE ${WM_USER} + 23
+!define /math TBM_GETLINESIZE ${WM_USER} + 24
+!define /math TBM_GETTHUMBRECT ${WM_USER} + 25
+!define /math TBM_GETCHANNELRECT ${WM_USER} + 26
+!define /math TBM_SETTHUMBLENGTH ${WM_USER} + 27
+!define /math TBM_GETTHUMBLENGTH ${WM_USER} + 28
+!define /math TBM_SETTOOLTIPS ${WM_USER} + 29 ; IE3
+!define /math TBM_GETTOOLTIPS ${WM_USER} + 30 ; IE3
+!define /math TBM_SETTIPSIDE ${WM_USER} + 31 ; IE3
+!define /math TBM_SETBUDDY ${WM_USER} + 32 ; IE3
+!define /math TBM_GETBUDDY ${WM_USER} + 33 ; IE3
+!define TBM_SETUNICODEFORMAT ${CCM_SETUNICODEFORMAT} ; IE4
+!define TBM_GETUNICODEFORMAT ${CCM_GETUNICODEFORMAT} ; IE4
+!define /math TBM_SETPOSNOTIFY ${WM_USER} + 34 ; 7?
+
+#UpDown controls#
+!define /math UDM_SETRANGE ${WM_USER} + 101
+!define /math UDM_GETRANGE ${WM_USER} + 102
+!define /math UDM_SETPOS ${WM_USER} + 103
+!define /math UDM_GETPOS ${WM_USER} + 104
+!define /math UDM_SETBUDDY ${WM_USER} + 105
+!define /math UDM_GETBUDDY ${WM_USER} + 106
+!define /math UDM_SETACCEL ${WM_USER} + 107
+!define /math UDM_GETACCEL ${WM_USER} + 108
+!define /math UDM_SETBASE ${WM_USER} + 109
+!define /math UDM_GETBASE ${WM_USER} + 110
+!define /math UDM_SETRANGE32 ${WM_USER} + 111 ; IE4
+!define /math UDM_GETRANGE32 ${WM_USER} + 112 ; IE4
+!define UDM_SETUNICODEFORMAT ${CCM_SETUNICODEFORMAT} ; IE4
+!define UDM_GETUNICODEFORMAT ${CCM_GETUNICODEFORMAT} ; IE4
+!define /math UDM_SETPOS32 ${WM_USER} + 113 ; IE5
+!define /math UDM_GETPOS32 ${WM_USER} + 114 ; IE5
+
+#HotKey control#
+!define /math HKM_SETHOTKEY ${WM_USER} + 1
+!define /math HKM_GETHOTKEY ${WM_USER} + 2
+!define /math HKM_SETRULES ${WM_USER} + 3
+!define /IfNDef HOTKEYF_SHIFT 0x01
+!define /IfNDef HOTKEYF_CONTROL 0x02
+!define /IfNDef HOTKEYF_ALT 0x04
+!define /IfNDef HOTKEYF_EXT 0x08
+!define HKCOMB_NONE 0x01
+!define HKCOMB_S 0x02
+!define HKCOMB_C 0x04
+!define HKCOMB_A 0x08
+!define HKCOMB_SC 0x10
+!define HKCOMB_SA 0x20
+!define HKCOMB_CA 0x40
+!define HKCOMB_SCA 0x80
+
+#IPAddress control#
+!define /math IPM_CLEARADDRESS ${WM_USER} + 100
+!define /math IPM_SETADDRESS ${WM_USER} + 101
+!define /math IPM_GETADDRESS ${WM_USER} + 102
+!define /math IPM_SETRANGE ${WM_USER} + 103
+!define /math IPM_SETFOCUS ${WM_USER} + 104
+!define /math IPM_ISBLANK ${WM_USER} + 105
+
+#NetworkAddress control#
+!define /math NCM_GETADDRESS ${WM_USER} + 1 ; Vista+
+!define /math NCM_SETALLOWTYPE ${WM_USER} + 2
+!define /math NCM_GETALLOWTYPE ${WM_USER} + 3
+!define /math NCM_DISPLAYERRORTIP ${WM_USER} + 4
+
+#Month calendar control#
+!define MCM_FIRST 0x1000
+!define /math MCM_GETCURSEL ${MCM_FIRST} + 1
+!define /math MCM_SETCURSEL ${MCM_FIRST} + 2
+!define /math MCM_GETMAXSELCOUNT ${MCM_FIRST} + 3
+!define /math MCM_SETMAXSELCOUNT ${MCM_FIRST} + 4
+!define /math MCM_GETSELRANGE ${MCM_FIRST} + 5
+!define /math MCM_SETSELRANGE ${MCM_FIRST} + 6
+!define /math MCM_GETMONTHRANGE ${MCM_FIRST} + 7
+!define /math MCM_SETDAYSTATE ${MCM_FIRST} + 8
+!define /math MCM_GETMINREQRECT ${MCM_FIRST} + 9
+!define /math MCM_SETCOLOR ${MCM_FIRST} + 10
+!define /math MCM_GETCOLOR ${MCM_FIRST} + 11
+!define /math MCM_SETTODAY ${MCM_FIRST} + 12
+!define /math MCM_GETTODAY ${MCM_FIRST} + 13
+!define /math MCM_HITTEST ${MCM_FIRST} + 14
+!define /math MCM_SETFIRSTDAYOFWEEK ${MCM_FIRST} + 15
+!define /math MCM_GETFIRSTDAYOFWEEK ${MCM_FIRST} + 16
+!define /math MCM_GETRANGE ${MCM_FIRST} + 17
+!define /math MCM_SETRANGE ${MCM_FIRST} + 18
+!define /math MCM_GETMONTHDELTA ${MCM_FIRST} + 19
+!define /math MCM_SETMONTHDELTA ${MCM_FIRST} + 20
+!define /math MCM_GETMAXTODAYWIDTH ${MCM_FIRST} + 21
+!define MCM_SETUNICODEFORMAT ${CCM_SETUNICODEFORMAT} ; IE4+
+!define MCM_GETUNICODEFORMAT ${CCM_SETUNICODEFORMAT} ; IE4+
+!define /math MCM_GETCURRENTVIEW ${MCM_FIRST} + 22 ; Vista+
+!define /math MCM_GETCALENDARCOUNT ${MCM_FIRST} + 23
+!define /math MCM_GETCALENDARGRIDINFO ${MCM_FIRST} + 24
+!define /math MCM_GETCALID ${MCM_FIRST} + 27
+!define /math MCM_SETCALID ${MCM_FIRST} + 28
+!define /math MCM_SIZERECTTOMIN ${MCM_FIRST} + 29
+!define /math MCM_SETCALENDARBORDER ${MCM_FIRST} + 30
+!define /math MCM_GETCALENDARBORDER ${MCM_FIRST} + 31
+!define /math MCM_SETCURRENTVIEW ${MCM_FIRST} + 32
+!define MCN_SELCHANGE -749
+!define MCN_GETDAYSTATE -747
+!define MCN_SELECT -746
+!define MCN_VIEWCHANGE -750 ; Vista+?
+
+#DateTime control#
+!define DTM_FIRST 0x1000
+!define /math DTM_GETSYSTEMTIME ${DTM_FIRST} + 1
+!define /math DTM_SETSYSTEMTIME ${DTM_FIRST} + 2
+!define /math DTM_SETFORMATA ${DTM_FIRST} + 5
+!define /math DTM_SETFORMATW ${DTM_FIRST} + 50
+${_NSIS_DEFAW} DTM_SETFORMAT
+!define /math DTM_GETMONTHCAL ${DTM_FIRST} + 8
+!define /math DTM_SETMCFONT ${DTM_FIRST} + 9 ; IE4+?
+!define /math DTM_GETMCFONT ${DTM_FIRST} + 10 ; IE4+?
+!define /math DTM_SETMCSTYLE ${DTM_FIRST} + 11 ; Vista+?
+!define /math DTM_GETMCSTYLE ${DTM_FIRST} + 12 ; Vista+?
+!define /math DTM_CLOSEMONTHCAL ${DTM_FIRST} + 13 ; Vista+?
+!define DTN_DATETIMECHANGE -759
+!define /IfNDef GDT_ERROR -1
+!define /IfNDef GDT_VALID 0
+!define /IfNDef GDT_NONE 1
+
+!verbose pop
+!endif
diff --git a/installer/tools/Include/WinVer.nsh b/installer/tools/Include/WinVer.nsh
new file mode 100644
index 00000000..32564ed7
--- /dev/null
+++ b/installer/tools/Include/WinVer.nsh
@@ -0,0 +1,703 @@
+; ---------------------
+; WinVer.nsh
+; ---------------------
+;
+; LogicLib extensions for handling Windows versions and service packs.
+;
+; IsNT checks if the installer is running on Windows NT family (NT4, 2000, XP, etc.)
+;
+; ${If} ${IsNT}
+; DetailPrint "Running on NT. Installing Unicode enabled application."
+; ${Else}
+; DetailPrint "Not running on NT. Installing ANSI application."
+; ${EndIf}
+;
+; IsServerOS checks if the installer is running on a server version of Windows (2000, 2003, 2008, etc.)
+; IsDomainController checks if the server is a domain controller
+;
+; AtLeastWin checks if the installer is running on Windows version at least as specified.
+; IsWin checks if the installer is running on Windows version exactly as specified.
+; AtMostWin checks if the installer is running on Windows version at most as specified.
+; AtLeastBuild checks if the installer is running on a Windows version with a minimum build number.
+; AtMostBuild checks if the installer is running on a Windows version with a maximum build number.
+; AtLeastWaaS and AtMostWaaS checks Windows 10 "friendly names" against the build number.
+;
+; can be replaced with the following values:
+;
+; 95
+; 98
+; ME
+;
+; NT4
+; 2000
+; XP
+; 2003
+; Vista
+; 2008
+; 7
+; 2008R2
+; 8
+; 2012
+; 8.1
+; 2012R2
+; 10
+; 11
+;
+; Note: Windows 8.1 and later will be detected as Windows 8 unless ManifestSupportedOS is set correctly!
+;
+; AtLeastServicePack checks if the installer is running on Windows service pack version at least as specified.
+; IsServicePack checks if the installer is running on Windows service pack version exactly as specified.
+; AtMostServicePack checks if the installer is running on Windows service version pack at most as specified.
+;
+; Usage examples:
+;
+; ${If} ${IsNT}
+; DetailPrint "Running on NT family."
+; DetailPrint "Surely not running on 95, 98 or ME."
+; ${AndIf} ${AtLeastWinNT4}
+; DetailPrint "Running on NT4 or better. Could even be 2003."
+; ${EndIf}
+;
+; ${If} ${AtLeastWinXP}
+; DetailPrint "Running on XP or better."
+; ${EndIf}
+;
+; ${If} ${IsWin2000}
+; DetailPrint "Running on 2000."
+; ${EndIf}
+;
+; ${If} ${IsWin2000}
+; ${AndIf} ${AtLeastServicePack} 3
+; ${OrIf} ${AtLeastWinXP}
+; DetailPrint "Running Win2000 SP3 or above"
+; ${EndIf}
+;
+; ${If} ${AtMostWinXP}
+; DetailPrint "Running on XP or older. Surely not running on Vista. Maybe 98, or even 95."
+; ${EndIf}
+;
+; Warning:
+;
+; Windows 95 and NT both use the same version number. To avoid getting NT4 misidentified
+; as Windows 95 and vice-versa or 98 as a version higher than NT4, always use IsNT to
+; check if running on the NT family.
+;
+; ${If} ${AtLeastWin95}
+; ${AndIf} ${AtMostWinME}
+; DetailPrint "Running 95, 98 or ME."
+; DetailPrint "Actually, maybe it's NT4?"
+; ${If} ${IsNT}
+; DetailPrint "Yes, it's NT4! oops..."
+; ${Else}
+; DetailPrint "Nope, not NT4. phew..."
+; ${EndIf}
+; ${EndIf}
+;
+;
+; Other useful extensions are:
+;
+; * IsWin2003R2
+; * IsStarterEdition
+; * OSHasMediaCenter
+; * OSHasTabletSupport
+;
+
+!verbose push
+!verbose 3
+
+!ifndef ___WINVER__NSH___
+!define ___WINVER__NSH___
+
+!include LogicLib.nsh
+!include Util.nsh
+
+# masks for our variables
+
+!define _WINVER_VERXBIT 0x00000001 ; Used to boost $__WINVERV
+!define _WINVER_MASKVMAJ 0x7F000000 ; $__WINVERV mask
+!define _WINVER_MASKVMIN 0x00FF0000 ; $__WINVERV mask
+!define _WINVER_NTMASK 0x7FFFFFFF ; $__WINVERV mask used by AtMost/AtLeast
+!define _WINVER_NTBIT 0x80000000 ; $__WINVERV bit used by Is and $__WINVERSP bit used by IsNT
+!define _WINVER_NTSRVBIT 0x40000000 ; $__WINVERSP bit for !VER_NT_WORKSTATION
+!define _WINVER_NTDCBIT 0x20000000 ; $__WINVERSP bit for VER_NT_DOMAIN_CONTROLLER
+!define _WINVER_MASKVBLD 0x0000FFFF ; $__WINVERSP mask for OS build number
+!define _WINVER_MASKSP 0x000F0000 ; $__WINVERSP mask for OS service pack
+
+# possible variable values for different versions
+
+!define WINVER_95_NT 0x04000000 ;4.00.0950
+!define WINVER_95 0x04000000 ;4.00.0950
+!define WINVER_98_NT 0x040a0000 ;4.10.1998
+!define WINVER_98 0x040a0000 ;4.10.1998
+;define WINVER_98SE 0x040a0000 ;4.10.2222
+!define WINVER_ME_NT 0x045a0000 ;4.90.3000
+!define WINVER_ME 0x045a0000 ;4.90.3000
+;define WINVER_NT3.51 ;3.51.1057
+!define WINVER_NT4_NT 0x84000000 ;4.00.1381
+!define WINVER_NT4 0x04000000 ;4.00.1381
+!define WINVER_2000_NT 0x85000000 ;5.00.2195
+!define WINVER_2000 0x05000000 ;5.00.2195
+!define WINVER_XP_NT 0x85010000 ;5.01.2600
+!define WINVER_XP 0x05010000 ;5.01.2600
+;define WINVER_XP64 ;5.02.3790
+!define WINVER_2003_NT 0x85020000 ;5.02.3790
+!define WINVER_2003 0x05020000 ;5.02.3790
+!define WINVER_VISTA_NT 0x86000000 ;6.00.6000
+!define WINVER_VISTA 0x06000000 ;6.00.6000
+!define WINVER_2008_NT 0x86000001 ;6.00.6001
+!define WINVER_2008 0x06000001 ;6.00.6001
+!define WINVER_7_NT 0x86010000 ;6.01.7600
+!define WINVER_7 0x06010000 ;6.01.7600
+!define WINVER_2008R2_NT 0x86010001 ;6.01.7600
+!define WINVER_2008R2 0x06010001 ;6.01.7600
+!define WINVER_8_NT 0x86020000 ;6.02.9200
+!define WINVER_8 0x06020000 ;6.02.9200
+!define WINVER_2012_NT 0x86020001 ;6.02.9200
+!define WINVER_2012 0x06020001 ;6.02.9200
+!define WINVER_8.1_NT 0x86030000 ;6.03.9600
+!define WINVER_8.1 0x06030000 ;6.03.9600
+!define WINVER_2012R2_NT 0x86030001 ;6.03.9600
+!define WINVER_2012R2 0x06030001 ;6.03.9600
+!define WINVER_10_NT 0x8A000000 ;10.0.10240
+!define WINVER_10 0x0A000000 ;10.0.10240
+!define WINVER_2016_NT 0x8A000001 ;10.0.14393
+!define WINVER_2016 0x0A000001 ;10.0.14393
+
+
+# use this to make all nt > 9x
+
+!ifdef WINVER_NT4_OVER_W95
+ !define /redef /math WINVER_NT4 ${WINVER_NT4} | ${_WINVER_VERXBIT}
+!endif
+
+# some definitions from header files
+
+!define OSVERSIONINFOW_SIZE 276
+!define OSVERSIONINFOEXW_SIZE 284
+!define OSVERSIONINFOA_SIZE 148
+!define OSVERSIONINFOEXA_SIZE 156
+!define /ifndef VER_PLATFORM_WIN32_NT 2
+!define /ifndef VER_NT_WORKSTATION 1
+!define /ifndef VER_NT_DOMAIN_CONTROLLER 2
+!define /ifndef VER_NT_SERVER 3
+
+!define SM_TABLETPC 86
+!define SM_MEDIACENTER 87
+!define SM_STARTER 88
+!define SM_SERVERR2 89
+
+# variable declaration
+
+!macro __WinVer_DeclareVars
+
+ !ifndef __WINVER_VARS_DECLARED
+
+ !define __WINVER_VARS_DECLARED
+
+ Var /GLOBAL __WINVERV
+ Var /GLOBAL __WINVERSP
+
+ !endif
+
+!macroend
+
+!macro __WinVer_Optimize
+!ifndef __WINVER_NOOPTIMIZE
+!if "${NSIS_CHAR_SIZE}" > 1
+!define /ReDef AtMostWin95 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef AtMostWin98 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef AtMostWinME '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWin95 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWin98 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWinME '"" LogicLib_AlwaysFalse ""'
+!endif
+!if "${NSIS_PTR_SIZE}" > 4
+!define /ReDef AtMostWin95 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef AtMostWin98 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef AtMostWinME '"" LogicLib_AlwaysFalse ""'
+!define /ReDef AtMostWinNT4 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWin95 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWin98 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWinME '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWinNT4 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef AtLeastWin95 '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWin98 '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWinME '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWinNT4 '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWin2000 '"" LogicLib_AlwaysTrue ""'
+!endif
+!ifdef NSIS_ARM | NSIS_ARM32 | NSIS_ARMNT | NSIS_ARM64
+!define /ReDef AtMostWin2000 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef AtMostWinXP '"" LogicLib_AlwaysFalse ""'
+!define /ReDef AtMostWin2003 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef AtMostWinVista '"" LogicLib_AlwaysFalse ""'
+!define /ReDef AtMostWin7 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWin95 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWin98 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWinME '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWinNT4 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWin2000 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWinXP '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWin2003 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWinVista '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWin2008 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWin7 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef IsWin2008R2 '"" LogicLib_AlwaysFalse ""'
+!define /ReDef AtLeastWin95 '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWin98 '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWinME '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWinNT4 '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWin2000 '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWinXP '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWin2003 '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWinVista '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWin2008 '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWin7 '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWin2008R2 '"" LogicLib_AlwaysTrue ""'
+!define /ReDef AtLeastWin8 '"" LogicLib_AlwaysTrue ""'
+!endif
+!endif
+!macroend
+
+# lazy initialization macro
+
+!define /IfNDef __WinVer_GWV GetWinVer
+
+!macro __WinVer_InitVars_NEW
+ !insertmacro __WinVer_DeclareVars
+ !insertmacro __WinVer_Optimize
+
+ # only calculate version once
+ StrCmp $__WINVERV "" _winver_noveryet
+ Return
+ _winver_noveryet:
+
+ Push $0
+ ${__WinVer_GWV} $0 Product
+ ${__WinVer_GWV} $__WINVERV NTDDIMajMin
+ IntOp $__WINVERV $__WINVERV << 16 ; _WINVER_MASKVMAJ & _WINVER_MASKVMIN
+ IntOp $__WINVERSP $0 & 2
+ IntOp $__WINVERSP $__WINVERSP << 29 ; _WINVER_NTSRVBIT & _WINVER_NTDCBIT
+ !ifndef NSIS_ARM64
+ IntCmp $__WINVERSP 0 notServer
+ IntCmpU 0x06000000 $__WINVERV "" "" not2008 ; ${If} $__WINVERV U>= 0x06000000
+ IntCmpU 0x09000000 $__WINVERV not2008 not2008 "" ; ${AndIf} $__WINVERV U< 0x09000000
+ IntOp $__WINVERV $__WINVERV | ${_WINVER_VERXBIT} ; Extra bit so Server 2008 comes after Vista SP1 that has the same minor version, same for Win7 vs 2008R2
+ not2008:
+ Goto endServer
+ notServer:
+ IntCmp $__WINVERV 0x05020000 "" notXP64 notXP64
+ StrCpy $__WINVERV 0x05010000 ; Change XP 64-bit from 5.2 to 5.1 so it's still XP
+ notXP64:
+ endServer:
+ !endif
+
+ IntCmp $0 0 notNT
+!if "${NSIS_PTR_SIZE}" <= 4
+!ifdef WINVER_NT4_OVER_W95
+ IntCmp $__WINVERV 0x04000000 "" nt4eq95 nt4eq95
+ IntOp $__WINVERV $__WINVERV | ${_WINVER_VERXBIT} ; change NT 4.0.reserved.0 to 4.0.reserved.1
+ nt4eq95:
+!endif
+!endif
+ IntOp $__WINVERSP $__WINVERSP | ${_WINVER_NTBIT} ; _WINVER_NTBIT
+ IntOp $__WINVERV $__WINVERV | ${_WINVER_NTBIT} ; _WINVER_NTBIT
+ notNT:
+
+ ${__WinVer_GWV} $0 Build
+ IntOp $__WINVERSP $__WINVERSP | $0 ; _WINVER_MASKVBLD
+ ${__WinVer_GWV} $0 ServicePack
+ IntOp $0 $0 << 16
+ IntOp $__WINVERSP $__WINVERSP | $0 ; _WINVER_MASKSP
+ Pop $0
+!macroend
+
+!ifmacrondef __WinVer_Call_GetVersionEx
+
+ !macro __WinVer_Call_GetVersionEx STRUCT_SIZE
+
+ System::Call '*$0(i ${STRUCT_SIZE})'
+ System::Call kernel32::GetVersionEx(pr0)i.r3
+
+ !macroend
+
+!endif
+
+!macro __WinVer_InitVars_OLD
+ # variables
+ !insertmacro __WinVer_DeclareVars
+ !insertmacro __WinVer_Optimize
+
+ # only calculate version once
+ StrCmp $__WINVERV "" _winver_noveryet
+ Return
+ _winver_noveryet:
+
+ # push used registers on the stack
+ Push $0
+ Push $1 ;maj
+ Push $2 ;min
+ Push $3 ;bld
+ Push $R0 ;temp
+
+ # a plugin call will lock the Unicode mode, it is now safe to set the struct size
+ !ifdef NSIS_UNICODE
+ !define /redef OSVERSIONINFO_SIZE ${OSVERSIONINFOW_SIZE}
+ !define /redef OSVERSIONINFOEX_SIZE ${OSVERSIONINFOEXW_SIZE}
+ !else
+ !define /redef OSVERSIONINFO_SIZE ${OSVERSIONINFOA_SIZE}
+ !define /redef OSVERSIONINFOEX_SIZE ${OSVERSIONINFOEXA_SIZE}
+ !endif
+
+ # allocate memory
+ System::Call '*(&i${OSVERSIONINFOEX_SIZE})p.r0'
+
+ # use OSVERSIONINFOEX
+ !insertmacro __WinVer_Call_GetVersionEx ${OSVERSIONINFOEX_SIZE}
+
+ IntCmp $3 0 "" _winver_ex _winver_ex
+ # OSVERSIONINFOEX not allowed (Win9x or NT4 w/SP < 6), use OSVERSIONINFO
+ !insertmacro __WinVer_Call_GetVersionEx ${OSVERSIONINFO_SIZE}
+ _winver_ex:
+
+ # get results from struct
+ System::Call '*$0(i.s,i.r1,i.r2,i.r3,i.s,&t128.s,&i2.s,&i2,&i2,&i1.s,&i1)'
+
+ # free struct
+ System::Free $0
+
+ # win9x has major and minor info in high word of dwBuildNumber - remove it
+ IntOp $3 $3 & 0xFFFF
+
+ # get dwOSVersionInfoSize
+ Pop $R0
+
+ # get dwPlatformId
+ Pop $0
+
+ # NT?
+ IntCmp $0 ${VER_PLATFORM_WIN32_NT} "" _winver_notnt _winver_notnt
+ IntOp $__WINVERSP $__WINVERSP | ${_WINVER_NTBIT}
+ IntOp $__WINVERV $__WINVERV | ${_WINVER_NTBIT}
+ _winver_notnt:
+!ifndef NSIS_UNICODE
+!if "${NSIS_PTR_SIZE}" <= 4
+ # get service pack information
+ IntCmp $0 ${VER_PLATFORM_WIN32_NT} _winver_nt "" _winver_nt # win9x
+
+ # get szCSDVersion
+ Pop $0
+
+ # copy second char
+ StrCpy $0 $0 1 1
+
+ # discard invalid wServicePackMajor and wProductType
+ Pop $R0
+ Pop $R0
+
+ # switch
+ StrCmp $0 'A' "" +3
+ StrCpy $0 1
+ Goto _winver_sp_done
+ StrCmp $0 'B' "" +3
+ StrCpy $0 2
+ Goto _winver_sp_done
+ StrCmp $0 'C' "" +3
+ StrCpy $0 3
+ Goto _winver_sp_done
+ StrCpy $0 0
+ Goto _winver_sp_done
+
+ _winver_nt: # nt
+!endif #~ 32-bit
+!endif #~ ANSI
+ IntCmp $R0 ${OSVERSIONINFOEX_SIZE} "" _winver_sp_noex _winver_sp_noex
+
+ # discard szCSDVersion
+ Pop $0
+
+ # get wProductType
+ Exch
+ Pop $0
+
+ # is server?
+ IntCmp $0 ${VER_NT_WORKSTATION} _winver_nt_notsrv
+ IntOp $__WINVERSP $__WINVERSP | ${_WINVER_NTSRVBIT}
+ IntCmp $0 ${VER_NT_DOMAIN_CONTROLLER} "" _winver_nt_notdc _winver_nt_notdc
+ IntOp $__WINVERSP $__WINVERSP | ${_WINVER_NTDCBIT}
+ _winver_nt_notdc:
+ _winver_nt_notsrv:
+
+ # get wServicePackMajor
+ Pop $0
+
+ # done with sp
+ Goto _winver_sp_done
+
+ _winver_sp_noex: # OSVERSIONINFO, not OSVERSIONINFOEX
+
+ #### TODO
+ ## For IsServerOS to support < NT4SP6, we need to check the registry
+ ## here to see if we are a server and/or DC
+
+ # get szCSDVersion
+ Pop $0
+
+ # discard invalid wServicePackMajor and wProductType
+ Pop $R0
+ Pop $R0
+
+ # get service pack number from text
+ StrCpy $R0 $0 13
+ StrCmp $R0 "Service Pack " "" +3
+ StrCpy $0 $0 "" 13 # cut "Service Pack "
+ Goto +2
+ StrCpy $0 0 # no service pack
+
+!ifdef WINVER_NT4_OVER_W95
+ IntOp $__WINVERV $__WINVERV | ${_WINVER_VERXBIT} ; change NT 4.0.reserved.0 to 4.0.reserved.1
+!endif
+
+ _winver_sp_done:
+
+ # store service pack
+ IntOp $0 $0 << 16
+ IntOp $__WINVERSP $__WINVERSP | $0
+
+ ### now for the version
+
+ # is server?
+ IntOp $0 $__WINVERSP & ${_WINVER_NTSRVBIT}
+
+ # windows xp x64?
+ IntCmp $0 0 "" _winver_not_xp_x64 _winver_not_xp_x64 # not server
+ IntCmp $1 5 "" _winver_not_xp_x64 _winver_not_xp_x64 # maj 5
+ IntCmp $2 2 "" _winver_not_xp_x64 _winver_not_xp_x64 # min 2
+ # change XP x64 from 5.2 to 5.1 so it's still XP
+ StrCpy $2 1
+ _winver_not_xp_x64:
+
+ # server 2008?
+ IntCmp $0 0 _winver_not_ntserver # server
+ IntCmp 6 $1 "" "" _winver_not_ntserver # maj 6
+ # extra bit so Server 2008 comes after Vista SP1 that has the same minor version, same for Win7 vs 2008R2
+ IntOp $__WINVERV $__WINVERV | ${_WINVER_VERXBIT}
+ _winver_not_ntserver:
+
+ # pack version
+ IntOp $1 $1 << 24 # VerMajor
+ IntOp $__WINVERV $__WINVERV | $1
+ IntOp $0 $2 << 16
+ IntOp $__WINVERV $__WINVERV | $0 # VerMinor
+ IntOp $__WINVERSP $__WINVERSP | $3 # VerBuild
+
+ # restore registers
+ Pop $R0
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+
+!macroend
+
+!macro __WinVer_InitVars
+ !ifndef WinVer_v3_7
+ !insertmacro __WinVer_InitVars_NEW
+ !else
+ !insertmacro __WinVer_InitVars_OLD
+ !endif
+!macroend
+
+# version comparison LogicLib macros
+
+!macro _WinVerAtLeast _a _b _t _f
+ !insertmacro _LOGICLIB_TEMP
+ ${CallArtificialFunction} __WinVer_InitVars
+ IntOp $_LOGICLIB_TEMP $__WINVERV & ${_WINVER_NTMASK}
+ !insertmacro _>= $_LOGICLIB_TEMP `${_b}` `${_t}` `${_f}`
+!macroend
+!macro _WinVerIs _a _b _t _f
+ ${CallArtificialFunction} __WinVer_InitVars
+ !insertmacro _= $__WINVERV `${_b}` `${_t}` `${_f}`
+!macroend
+!macro _WinVerAtMost _a _b _t _f
+ !insertmacro _LOGICLIB_TEMP
+ ${CallArtificialFunction} __WinVer_InitVars
+ IntOp $_LOGICLIB_TEMP $__WINVERV & ${_WINVER_NTMASK}
+ !insertmacro _<= $_LOGICLIB_TEMP `${_b}` `${_t}` `${_f}`
+!macroend
+
+!macro __WinVer_DefineOSTest Test OS Suffix
+ !define ${Test}Win${OS} `"" WinVer${Test} ${WINVER_${OS}${Suffix}}`
+!macroend
+
+!macro __WinVer_DefineOSTests Test Suffix
+ !insertmacro __WinVer_DefineOSTest ${Test} 95 '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} 98 '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} ME '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} NT4 '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} 2000 '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} XP '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} 2003 '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} VISTA '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} 2008 '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} 7 '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} 2008R2 '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} 8 '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} 2012 '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} 8.1 '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} 2012R2 '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} 10 '${Suffix}'
+ !insertmacro __WinVer_DefineOSTest ${Test} 2016 '${Suffix}'
+ !define /IfNDef AtLeastWin11 'U>= WinVer_BuildNumCheck 22000'
+ !define /IfNDef AtMostWin11 'U<= WinVer_BuildNumCheck 22000'
+!macroend
+
+!insertmacro __WinVer_DefineOSTests AtLeast ""
+!insertmacro __WinVer_DefineOSTests Is _NT
+!insertmacro __WinVer_DefineOSTests AtMost ""
+
+# version feature LogicLib macros
+
+!macro __WinVer_LL_IsBitSet _v _b _t _f
+ !insertmacro _LOGICLIB_TEMP
+ ${CallArtificialFunction} __WinVer_InitVars
+ IntOp $_LOGICLIB_TEMP ${_v} & ${_b}
+ !insertmacro _!= $_LOGICLIB_TEMP 0 `${_t}` `${_f}`
+!macroend
+
+!define IsNT `$__WINVERSP _WinVer_LL_IsBitSet ${_WINVER_NTBIT}`
+!define IsServerOS `$__WINVERSP _WinVer_LL_IsBitSet ${_WINVER_NTSRVBIT}`
+!define IsDomainController `$__WINVERSP _WinVer_LL_IsBitSet ${_WINVER_NTDCBIT}`
+
+# service pack macros
+
+!macro _WinVer_GetServicePackLevel OUTVAR
+ !ifndef WinVer_v3_7
+ ${__WinVer_GWV} ${OUTVAR} ServicePack
+ !else
+ ${CallArtificialFunction} __WinVer_InitVars
+ IntOp ${OUTVAR} $__WINVERSP & ${_WINVER_MASKSP}
+ IntOp ${OUTVAR} ${OUTVAR} >> 16
+ !endif
+!macroend
+!define WinVerGetServicePackLevel '!insertmacro _WinVer_GetServicePackLevel '
+
+!macro _AtLeastServicePack _a _b _t _f
+ !insertmacro _LOGICLIB_TEMP
+ ${WinVerGetServicePackLevel} $_LOGICLIB_TEMP
+ !insertmacro _>= $_LOGICLIB_TEMP `${_b}` `${_t}` `${_f}`
+!macroend
+!define AtLeastServicePack `"" AtLeastServicePack`
+
+!macro _AtMostServicePack _a _b _t _f
+ !insertmacro _LOGICLIB_TEMP
+ ${WinVerGetServicePackLevel} $_LOGICLIB_TEMP
+ !insertmacro _<= $_LOGICLIB_TEMP `${_b}` `${_t}` `${_f}`
+!macroend
+!define AtMostServicePack `"" AtMostServicePack`
+
+!macro _IsServicePack _a _b _t _f
+ !insertmacro _LOGICLIB_TEMP
+ ${WinVerGetServicePackLevel} $_LOGICLIB_TEMP
+ !insertmacro _= $_LOGICLIB_TEMP `${_b}` `${_t}` `${_f}`
+!macroend
+!define IsServicePack `"" IsServicePack`
+
+# special feature LogicLib macros
+
+!macro _WinVer_SysMetricCheck m _b _t _f
+ !insertmacro _LOGICLIB_TEMP
+ System::Call user32::GetSystemMetrics(i${m})i.s
+ pop $_LOGICLIB_TEMP
+ !insertmacro _!= $_LOGICLIB_TEMP 0 `${_t}` `${_f}`
+!macroend
+
+!define IsWin2003R2 `${SM_SERVERR2} WinVer_SysMetricCheck ""`
+!define IsStarterEdition `${SM_STARTER} WinVer_SysMetricCheck ""`
+!define OSHasMediaCenter `${SM_MEDIACENTER} WinVer_SysMetricCheck ""`
+!define OSHasTabletSupport `${SM_TABLETPC} WinVer_SysMetricCheck ""`
+!define IsSafeBootMode `67 WinVer_SysMetricCheck ""`
+
+# version retrieval macros
+
+!macro __WinVer_GetVer var rshift mask outvar
+ ${CallArtificialFunction} __WinVer_InitVars
+ !if "${mask}" != ""
+ IntOp ${outvar} ${var} & ${mask}
+ !if "${rshift}" != ""
+ IntOp ${outvar} ${outvar} >> ${rshift}
+ !endif
+ !else
+ IntOp ${outvar} ${var} >> ${rshift}
+ !endif
+!macroend
+
+!define WinVerGetMajor '!insertmacro __WinVer_GetVer $__WINVERV 24 ${_WINVER_MASKVMAJ}'
+!define WinVerGetMinor '!insertmacro __WinVer_GetVer $__WINVERV 16 ${_WINVER_MASKVMIN}'
+!ifndef WinVer_v3_7
+!macro __WinVer_GetVerBuild outvar
+ ${__WinVer_GWV} ${outvar} Build
+!macroend
+!define WinVerGetBuild '!insertmacro __WinVer_GetVerBuild '
+!else
+!define WinVerGetBuild '!insertmacro __WinVer_GetVer $__WINVERSP "" ${_WINVER_MASKVBLD}'
+!endif
+
+!macro _WinVer_BuildNumCheck op num _t _f
+ !insertmacro _LOGICLIB_TEMP
+ ${WinVerGetBuild} $_LOGICLIB_TEMP
+ !insertmacro _${op} $_LOGICLIB_TEMP ${num} `${_t}` `${_f}`
+!macroend
+!define AtLeastBuild `U>= WinVer_BuildNumCheck `
+!define AtMostBuild `U<= WinVer_BuildNumCheck `
+
+# Windows as a Service macros
+
+!macro WinVer_WaaS id build fu codename marketingname
+ !if "${id}" == "?"
+ # Ignore
+ !else if "${id}" == ${fu}
+ !define WinVer_WaaS_Build ${build}
+ !else if "${id}" == "${codename}"
+ !define WinVer_WaaS_Build ${build}
+ !else if "${id}" == "${marketingname}"
+ !define WinVer_WaaS_Build ${build}
+ !endif
+!macroend
+
+!macro _WinVer_WaaS op id _t _f
+ !insertmacro WinVer_WaaS "${id}" 10240 1507 "Threshold" "Windows 10" ; 10240.16384
+ !insertmacro WinVer_WaaS "${id}" 10586 1511 "Threshold 2" "November Update" ; 10586.0?
+ !insertmacro WinVer_WaaS "${id}" 14393 1607 "Redstone" "Anniversary Update" ; 14393.10
+ !insertmacro WinVer_WaaS "${id}" 15063 1703 "Redstone 2" "Creators Update" ; 15063.13
+ !insertmacro WinVer_WaaS "${id}" 16299 1709 "Redstone 3" "Fall Creators Update" ; 16299.19
+ !insertmacro WinVer_WaaS "${id}" 17134 1803 "Redstone 4" "April 2018 Update" ; 17134.1
+ !insertmacro WinVer_WaaS "${id}" 17763 1809 "Redstone 5" "October 2018 Update" ; 17763.1
+ !insertmacro WinVer_WaaS "${id}" 18362 1903 "19H1" "May 2019 Update" ; 18362.116
+ !insertmacro WinVer_WaaS "${id}" 18363 1909 "19H2" "November 2019 Update" ; 18363.418
+ !insertmacro WinVer_WaaS "${id}" 19041 2004 "20H1" "May 2020 Update" ; 19041.264?
+ !insertmacro WinVer_WaaS "${id}" 19042 20H2 "20H2" "October 2020 Update" ; 19042.572? A.K.A. 2009
+ !insertmacro WinVer_WaaS "${id}" 19043 21H1 "21H1" "May 2021 Update" ; 19043.928
+ !insertmacro WinVer_WaaS "${id}" 19044 21H2 "21H2" "November 2021 Update" ; 19044.1288
+ !insertmacro WinVer_WaaS "${id}" 19045 "?" "?" "October 2022 Update" ; 19045.2130 22H2
+ !insertmacro WinVer_WaaS "${id}" 22000 "?" "Sun Valley" "Windows 11" ; 10.0.22000.194 21H2
+ !insertmacro WinVer_WaaS "${id}" 22621 22H2 "Sun Valley 2" "2022 Update" ; 10.0.22621.521
+
+ !ifmacrodef WinVerExternal_WaaS_MapToBuild
+ !insertmacro WinVerExternal_WaaS_MapToBuild ${op} "${id}" WinVer_WaaS_Build
+ !endif
+ !define /IfNDef WinVer_WaaS_Build 0
+ !if "${WinVer_WaaS_Build}" <= 9600
+ !error 'WinVer: Unknown WaaS name: ${id}'
+ !endif
+ !insertmacro _WinVer_BuildNumCheck ${op} ${WinVer_WaaS_Build} `${_t}` `${_f}`
+ !undef WinVer_WaaS_Build
+!macroend
+
+!define AtLeastWaaS `U>= WinVer_WaaS `
+!define AtMostWaaS `U<= WinVer_WaaS `
+
+!endif # !___WINVER__NSH___
+
+!verbose pop
diff --git a/installer/tools/Include/WordFunc.nsh b/installer/tools/Include/WordFunc.nsh
new file mode 100644
index 00000000..0cb645a0
--- /dev/null
+++ b/installer/tools/Include/WordFunc.nsh
@@ -0,0 +1,1800 @@
+/*
+_____________________________________________________________________________
+
+ Word Functions Header v3.3
+_____________________________________________________________________________
+
+ 2006 Shengalts Aleksander aka Instructor (Shengalts@mail.ru)
+
+ See documentation for more information about the following functions.
+
+ Usage in script:
+ 1. !include "WordFunc.nsh"
+ 2. [Section|Function]
+ ${WordFunction} "Param1" "Param2" "..." $var
+ [SectionEnd|FunctionEnd]
+
+
+ WordFunction=[WordFind|WordFindS|WordFind2X|WordFind2XS|WordFind3X|WordFind3XS|
+ WordReplace|WordReplaceS|WordAdd|WordAddS|WordInsert|WordInsertS|
+ StrFilter|StrFilterS|VersionCompare|VersionConvert]
+
+_____________________________________________________________________________
+
+ Thanks to:
+_____________________________________________________________________________
+
+WordFind3X
+ Afrow UK (Based on his idea of Function "StrSortLR")
+StrFilter
+ sunjammer (Function "StrUpper")
+VersionCompare
+ Afrow UK (Based on his Function "VersionCheckNew2")
+VersionConvert
+ Afrow UK (Based on his idea of Function "CharIndexReplace")
+*/
+
+
+;_____________________________________________________________________________
+;
+; Macros
+;_____________________________________________________________________________
+;
+; Change log window verbosity (default: 3=no script)
+;
+; Example:
+; !include "WordFunc.nsh"
+; !insertmacro WordFind
+; ${WORDFUNC_VERBOSE} 4 # all verbosity
+; !insertmacro WordReplace
+; ${WORDFUNC_VERBOSE} 3 # no script
+
+!ifndef WORDFUNC_INCLUDED
+
+!verbose push 3
+!define /IfNDef _WORDFUNC_VERBOSE 3
+!verbose ${_WORDFUNC_VERBOSE}
+!define WORDFUNC_VERBOSE `!insertmacro WORDFUNC_VERBOSE`
+
+!define WORDFUNC_INCLUDED
+
+!include Util.nsh
+
+
+!macro WORDFUNC_VERBOSE _VERBOSE
+ !verbose push 3
+ !define /ReDef _WORDFUNC_VERBOSE ${_VERBOSE}
+ !verbose pop
+!macroend
+
+
+!macro WordFindCall _ART _STRING _DELIMITER _OPTION _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_STRING}`
+ Push `${_DELIMITER}`
+ Push `${_OPTION}`
+ ${CallArtificialFunction}${_ART} WordFind_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro WordFindSCall _ART _STRING _DELIMITER _OPTION _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_STRING}`
+ Push `${_DELIMITER}`
+ Push `${_OPTION}`
+ ${CallArtificialFunction}${_ART} WordFindS_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro WordFind2XCall _STRING _DELIMITER1 _DELIMITER2 _NUMBER _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_STRING}`
+ Push `${_DELIMITER1}`
+ Push `${_DELIMITER2}`
+ Push `${_NUMBER}`
+ ${CallArtificialFunction} WordFind2X_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro WordFind2XSCall _STRING _DELIMITER1 _DELIMITER2 _NUMBER _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_STRING}`
+ Push `${_DELIMITER1}`
+ Push `${_DELIMITER2}`
+ Push `${_NUMBER}`
+ ${CallArtificialFunction} WordFind2XS_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro WordFind3XCall _STRING _DELIMITER1 _CENTER _DELIMITER2 _NUMBER _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_STRING}`
+ Push `${_DELIMITER1}`
+ Push `${_CENTER}`
+ Push `${_DELIMITER2}`
+ Push `${_NUMBER}`
+ ${CallArtificialFunction} WordFind3X_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro WordFind3XSCall _STRING _DELIMITER1 _CENTER _DELIMITER2 _NUMBER _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_STRING}`
+ Push `${_DELIMITER1}`
+ Push `${_CENTER}`
+ Push `${_DELIMITER2}`
+ Push `${_NUMBER}`
+ ${CallArtificialFunction} WordFind3XS_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro WordReplaceCall _STRING _WORD1 _WORD2 _NUMBER _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_STRING}`
+ Push `${_WORD1}`
+ Push `${_WORD2}`
+ Push `${_NUMBER}`
+ ${CallArtificialFunction} WordReplace_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro WordReplaceSCall _STRING _WORD1 _WORD2 _NUMBER _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_STRING}`
+ Push `${_WORD1}`
+ Push `${_WORD2}`
+ Push `${_NUMBER}`
+ ${CallArtificialFunction} WordReplaceS_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro WordAddCall _STRING1 _DELIMITER _STRING2 _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_STRING1}`
+ Push `${_DELIMITER}`
+ Push `${_STRING2}`
+ ${CallArtificialFunction} WordAdd_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro WordAddSCall _STRING1 _DELIMITER _STRING2 _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_STRING1}`
+ Push `${_DELIMITER}`
+ Push `${_STRING2}`
+ ${CallArtificialFunction} WordAddS_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro WordInsertCall _STRING _DELIMITER _WORD _NUMBER _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_STRING}`
+ Push `${_DELIMITER}`
+ Push `${_WORD}`
+ Push `${_NUMBER}`
+ ${CallArtificialFunction} WordInsert_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro WordInsertSCall _STRING _DELIMITER _WORD _NUMBER _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_STRING}`
+ Push `${_DELIMITER}`
+ Push `${_WORD}`
+ Push `${_NUMBER}`
+ ${CallArtificialFunction} WordInsertS_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro StrFilterCall _STRING _FILTER _INCLUDE _EXCLUDE _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_STRING}`
+ Push `${_FILTER}`
+ Push `${_INCLUDE}`
+ Push `${_EXCLUDE}`
+ ${CallArtificialFunction} StrFilter_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro StrFilterSCall _STRING _FILTER _INCLUDE _EXCLUDE _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_STRING}`
+ Push `${_FILTER}`
+ Push `${_INCLUDE}`
+ Push `${_EXCLUDE}`
+ ${CallArtificialFunction} StrFilterS_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro VersionCompareCall _VER1 _VER2 _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_VER1}`
+ Push `${_VER2}`
+ ${CallArtificialFunction} VersionCompare_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro VersionConvertCall _VERSION _CHARLIST _RESULT
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+ Push `${_VERSION}`
+ Push `${_CHARLIST}`
+ ${CallArtificialFunction} VersionConvert_
+ Pop ${_RESULT}
+ !verbose pop
+!macroend
+
+!macro WordFindBody _WORDFUNC_S
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Exch 2
+ Exch $R0
+ Exch 2
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $8
+ Push $9
+ Push $R1
+ Push $R2
+ ClearErrors
+
+ StrCpy $9 ''
+ StrCpy $2 $1 1
+ StrCpy $1 $1 '' 1
+ StrCmp $2 'E' 0 +3
+ StrCpy $9 E
+ goto -4
+
+ StrCpy $3 ''
+ StrCmp${_WORDFUNC_S} $2 '+' +6
+ StrCmp${_WORDFUNC_S} $2 '-' +5
+ StrCmp${_WORDFUNC_S} $2 '/' WordFunc_WordFind${_WORDFUNC_S}_restart
+ StrCmp${_WORDFUNC_S} $2 '#' WordFunc_WordFind${_WORDFUNC_S}_restart
+ StrCmp${_WORDFUNC_S} $2 '*' WordFunc_WordFind${_WORDFUNC_S}_restart
+ goto WordFunc_WordFind${_WORDFUNC_S}_error3
+
+ StrCpy $4 $1 1 -1
+ StrCmp${_WORDFUNC_S} $4 '*' +4
+ StrCmp${_WORDFUNC_S} $4 '}' +3
+ StrCmp${_WORDFUNC_S} $4 '{' +2
+ goto +4
+ StrCpy $1 $1 -1
+ StrCpy $3 '$4$3'
+ goto -7
+ StrCmp${_WORDFUNC_S} $3 '*' WordFunc_WordFind${_WORDFUNC_S}_error3
+ StrCmp${_WORDFUNC_S} $3 '**' WordFunc_WordFind${_WORDFUNC_S}_error3
+ StrCmp${_WORDFUNC_S} $3 '}{' WordFunc_WordFind${_WORDFUNC_S}_error3
+ IntOp $1 $1 + 0
+ StrCmp${_WORDFUNC_S} $1 0 WordFunc_WordFind${_WORDFUNC_S}_error2
+
+ WordFunc_WordFind${_WORDFUNC_S}_restart:
+ StrCmp${_WORDFUNC_S} $R0 '' WordFunc_WordFind${_WORDFUNC_S}_error1
+ StrCpy $4 0
+ StrCpy $5 0
+ StrCpy $6 0
+ StrLen $7 $0
+ goto WordFunc_WordFind${_WORDFUNC_S}_loop
+
+ WordFunc_WordFind${_WORDFUNC_S}_preloop:
+ IntOp $6 $6 + 1
+
+ WordFunc_WordFind${_WORDFUNC_S}_loop:
+ StrCpy $8 $R0 $7 $6
+ StrCmp${_WORDFUNC_S} $8$5 0 WordFunc_WordFind${_WORDFUNC_S}_error1
+ StrLen $R2 $8
+ IntCmp $R2 0 +2
+ StrCmp${_WORDFUNC_S} $8 $0 +5 WordFunc_WordFind${_WORDFUNC_S}_preloop
+ StrCmp${_WORDFUNC_S} $3 '{' WordFunc_WordFind${_WORDFUNC_S}_minus
+ StrCmp${_WORDFUNC_S} $3 '}' WordFunc_WordFind${_WORDFUNC_S}_minus
+ StrCmp${_WORDFUNC_S} $2 '*' WordFunc_WordFind${_WORDFUNC_S}_minus
+ StrCmp${_WORDFUNC_S} $5 $6 WordFunc_WordFind${_WORDFUNC_S}_minus +5
+ StrCmp${_WORDFUNC_S} $3 '{' +4
+ StrCmp${_WORDFUNC_S} $3 '}' +3
+ StrCmp${_WORDFUNC_S} $2 '*' +2
+ StrCmp${_WORDFUNC_S} $5 $6 WordFunc_WordFind${_WORDFUNC_S}_nextword
+ IntOp $4 $4 + 1
+ StrCmp${_WORDFUNC_S} $2$4 +$1 WordFunc_WordFind${_WORDFUNC_S}_plus
+ StrCmp${_WORDFUNC_S} $2 '/' 0 WordFunc_WordFind${_WORDFUNC_S}_nextword
+ IntOp $8 $6 - $5
+ StrCpy $8 $R0 $8 $5
+ StrCmp${_WORDFUNC_S} $1 $8 0 WordFunc_WordFind${_WORDFUNC_S}_nextword
+ StrCpy $R1 $4
+ goto WordFunc_WordFind${_WORDFUNC_S}_end
+ WordFunc_WordFind${_WORDFUNC_S}_nextword:
+ IntOp $6 $6 + $7
+ StrCpy $5 $6
+ goto WordFunc_WordFind${_WORDFUNC_S}_loop
+
+ WordFunc_WordFind${_WORDFUNC_S}_minus:
+ StrCmp${_WORDFUNC_S} $2 '-' 0 WordFunc_WordFind${_WORDFUNC_S}_sum
+ StrCpy $2 '+'
+ IntOp $1 $4 - $1
+ IntOp $1 $1 + 1
+ IntCmp $1 0 WordFunc_WordFind${_WORDFUNC_S}_error2 WordFunc_WordFind${_WORDFUNC_S}_error2 WordFunc_WordFind${_WORDFUNC_S}_restart
+ WordFunc_WordFind${_WORDFUNC_S}_sum:
+ StrCmp${_WORDFUNC_S} $2 '#' 0 WordFunc_WordFind${_WORDFUNC_S}_sumdelim
+ StrCpy $R1 $4
+ goto WordFunc_WordFind${_WORDFUNC_S}_end
+ WordFunc_WordFind${_WORDFUNC_S}_sumdelim:
+ StrCmp${_WORDFUNC_S} $2 '*' 0 WordFunc_WordFind${_WORDFUNC_S}_error2
+ StrCpy $R1 $4
+ goto WordFunc_WordFind${_WORDFUNC_S}_end
+
+ WordFunc_WordFind${_WORDFUNC_S}_plus:
+ StrCmp${_WORDFUNC_S} $3 '' 0 +4
+ IntOp $6 $6 - $5
+ StrCpy $R1 $R0 $6 $5
+ goto WordFunc_WordFind${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $3 '{' 0 +3
+ StrCpy $R1 $R0 $6
+ goto WordFunc_WordFind${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $3 '}' 0 +4
+ IntOp $6 $6 + $7
+ StrCpy $R1 $R0 '' $6
+ goto WordFunc_WordFind${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $3 '{*' +2
+ StrCmp${_WORDFUNC_S} $3 '*{' 0 +3
+ StrCpy $R1 $R0 $6
+ goto WordFunc_WordFind${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $3 '*}' +2
+ StrCmp${_WORDFUNC_S} $3 '}*' 0 +3
+ StrCpy $R1 $R0 '' $5
+ goto WordFunc_WordFind${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $3 '}}' 0 +3
+ StrCpy $R1 $R0 '' $6
+ goto WordFunc_WordFind${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $3 '{{' 0 +3
+ StrCpy $R1 $R0 $5
+ goto WordFunc_WordFind${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $3 '{}' 0 WordFunc_WordFind${_WORDFUNC_S}_error3
+ StrLen $3 $R0
+ StrCmp${_WORDFUNC_S} $3 $6 0 +3
+ StrCpy $0 ''
+ goto +2
+ IntOp $6 $6 + $7
+ StrCpy $8 $R0 '' $6
+ StrCmp${_WORDFUNC_S} $4$8 1 +6
+ StrCmp${_WORDFUNC_S} $4 1 +2 +7
+ IntOp $6 $6 + $7
+ StrCpy $3 $R0 $7 $6
+ StrCmp${_WORDFUNC_S} $3 '' +2
+ StrCmp${_WORDFUNC_S} $3 $0 -3 +3
+ StrCpy $R1 ''
+ goto WordFunc_WordFind${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $5 0 0 +3
+ StrCpy $0 ''
+ goto +2
+ IntOp $5 $5 - $7
+ StrCpy $3 $R0 $5
+ StrCpy $R1 '$3$0$8'
+ goto WordFunc_WordFind${_WORDFUNC_S}_end
+
+ WordFunc_WordFind${_WORDFUNC_S}_error3:
+ StrCpy $R1 3
+ goto WordFunc_WordFind${_WORDFUNC_S}_error
+ WordFunc_WordFind${_WORDFUNC_S}_error2:
+ StrCpy $R1 2
+ goto WordFunc_WordFind${_WORDFUNC_S}_error
+ WordFunc_WordFind${_WORDFUNC_S}_error1:
+ StrCpy $R1 1
+ WordFunc_WordFind${_WORDFUNC_S}_error:
+ StrCmp $9 'E' 0 +3
+ SetErrors
+
+ WordFunc_WordFind${_WORDFUNC_S}_end:
+ StrCpy $R0 $R1
+
+ Pop $R2
+ Pop $R1
+ Pop $9
+ Pop $8
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+ Exch $R0
+!macroend
+
+!define WordFind `!insertmacro WordFindCall ''`
+!define un.WordFind `!insertmacro WordFindCall ''`
+
+!macro WordFind
+!macroend
+
+!macro un.WordFind
+!macroend
+
+!macro WordFind_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ !insertmacro WordFindBody ''
+
+ !verbose pop
+!macroend
+
+!define WordFindS `!insertmacro WordFindSCall ''`
+!define un.WordFindS `!insertmacro WordFindSCall ''`
+
+!macro WordFindS
+!macroend
+
+!macro un.WordFindS
+!macroend
+
+!macro WordFindS_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ !insertmacro WordFindBody 'S'
+
+ !verbose pop
+!macroend
+
+!macro WordFind2XBody _WORDFUNC_S
+ Exch $2
+ Exch
+ Exch $1
+ Exch
+ Exch 2
+ Exch $0
+ Exch 2
+ Exch 3
+ Exch $R0
+ Exch 3
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $8
+ Push $9
+ Push $R1
+ Push $R2
+ ClearErrors
+
+ StrCpy $R2 ''
+ StrCpy $3 $2 1
+ StrCpy $2 $2 '' 1
+ StrCmp $3 'E' 0 +3
+ StrCpy $R2 E
+ goto -4
+
+ StrCmp${_WORDFUNC_S} $3 '+' +5
+ StrCmp${_WORDFUNC_S} $3 '-' +4
+ StrCmp${_WORDFUNC_S} $3 '#' WordFunc_WordFind2X${_WORDFUNC_S}_restart
+ StrCmp${_WORDFUNC_S} $3 '/' WordFunc_WordFind2X${_WORDFUNC_S}_restart
+ goto WordFunc_WordFind2X${_WORDFUNC_S}_error3
+
+ StrCpy $4 $2 2 -2
+ StrCmp${_WORDFUNC_S} $4 '{{' +9
+ StrCmp${_WORDFUNC_S} $4 '}}' +8
+ StrCmp${_WORDFUNC_S} $4 '{*' +7
+ StrCmp${_WORDFUNC_S} $4 '*{' +6
+ StrCmp${_WORDFUNC_S} $4 '*}' +5
+ StrCmp${_WORDFUNC_S} $4 '}*' +4
+ StrCmp${_WORDFUNC_S} $4 '{}' +3
+ StrCpy $4 ''
+ goto +2
+ StrCpy $2 $2 -2
+ IntOp $2 $2 + 0
+ StrCmp${_WORDFUNC_S} $2 0 WordFunc_WordFind2X${_WORDFUNC_S}_error2
+
+ WordFunc_WordFind2X${_WORDFUNC_S}_restart:
+ StrCmp${_WORDFUNC_S} $R0 '' WordFunc_WordFind2X${_WORDFUNC_S}_error1
+ StrCpy $5 -1
+ StrCpy $6 0
+ StrCpy $7 ''
+ StrLen $8 $0
+ StrLen $9 $1
+
+ WordFunc_WordFind2X${_WORDFUNC_S}_loop:
+ IntOp $5 $5 + 1
+
+ WordFunc_WordFind2X${_WORDFUNC_S}_delim1:
+ StrCpy $R1 $R0 $8 $5
+ StrCmp${_WORDFUNC_S} $R1$6 0 WordFunc_WordFind2X${_WORDFUNC_S}_error1
+ StrCmp${_WORDFUNC_S} $R1 '' WordFunc_WordFind2X${_WORDFUNC_S}_minus
+ StrCmp${_WORDFUNC_S} $R1 $0 +2
+ StrCmp${_WORDFUNC_S} $7 '' WordFunc_WordFind2X${_WORDFUNC_S}_loop WordFunc_WordFind2X${_WORDFUNC_S}_delim2
+ StrCmp${_WORDFUNC_S} $0 $1 0 +2
+ StrCmp${_WORDFUNC_S} $7 '' 0 WordFunc_WordFind2X${_WORDFUNC_S}_delim2
+ IntOp $7 $5 + $8
+ StrCpy $5 $7
+ goto WordFunc_WordFind2X${_WORDFUNC_S}_delim1
+
+ WordFunc_WordFind2X${_WORDFUNC_S}_delim2:
+ StrCpy $R1 $R0 $9 $5
+ StrCmp${_WORDFUNC_S} $R1 $1 0 WordFunc_WordFind2X${_WORDFUNC_S}_loop
+ IntOp $6 $6 + 1
+ StrCmp${_WORDFUNC_S} $3$6 '+$2' WordFunc_WordFind2X${_WORDFUNC_S}_plus
+ StrCmp${_WORDFUNC_S} $3 '/' 0 WordFunc_WordFind2X${_WORDFUNC_S}_nextword
+ IntOp $R1 $5 - $7
+ StrCpy $R1 $R0 $R1 $7
+ StrCmp${_WORDFUNC_S} $R1 $2 0 +3
+ StrCpy $R1 $6
+ goto WordFunc_WordFind2X${_WORDFUNC_S}_end
+ WordFunc_WordFind2X${_WORDFUNC_S}_nextword:
+ IntOp $5 $5 + $9
+ StrCpy $7 ''
+ goto WordFunc_WordFind2X${_WORDFUNC_S}_delim1
+
+ WordFunc_WordFind2X${_WORDFUNC_S}_minus:
+ StrCmp${_WORDFUNC_S} $3 '-' 0 WordFunc_WordFind2X${_WORDFUNC_S}_sum
+ StrCpy $3 +
+ IntOp $2 $6 - $2
+ IntOp $2 $2 + 1
+ IntCmp $2 0 WordFunc_WordFind2X${_WORDFUNC_S}_error2 WordFunc_WordFind2X${_WORDFUNC_S}_error2 WordFunc_WordFind2X${_WORDFUNC_S}_restart
+ WordFunc_WordFind2X${_WORDFUNC_S}_sum:
+ StrCmp${_WORDFUNC_S} $3 '#' 0 WordFunc_WordFind2X${_WORDFUNC_S}_error2
+ StrCpy $R1 $6
+ goto WordFunc_WordFind2X${_WORDFUNC_S}_end
+
+ WordFunc_WordFind2X${_WORDFUNC_S}_plus:
+ StrCmp${_WORDFUNC_S} $4 '' 0 +4
+ IntOp $R1 $5 - $7
+ StrCpy $R1 $R0 $R1 $7
+ goto WordFunc_WordFind2X${_WORDFUNC_S}_end
+ IntOp $5 $5 + $9
+ IntOp $7 $7 - $8
+ StrCmp${_WORDFUNC_S} $4 '{*' +2
+ StrCmp${_WORDFUNC_S} $4 '*{' 0 +3
+ StrCpy $R1 $R0 $5
+ goto WordFunc_WordFind2X${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $4 '*}' +2
+ StrCmp${_WORDFUNC_S} $4 '}*' 0 +3
+ StrCpy $R1 $R0 '' $7
+ goto WordFunc_WordFind2X${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $4 '}}' 0 +3
+ StrCpy $R1 $R0 '' $5
+ goto WordFunc_WordFind2X${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $4 '{{' 0 +3
+ StrCpy $R1 $R0 $7
+ goto WordFunc_WordFind2X${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $4 '{}' 0 WordFunc_WordFind2X${_WORDFUNC_S}_error3
+ StrCpy $5 $R0 '' $5
+ StrCpy $7 $R0 $7
+ StrCpy $R1 '$7$5'
+ goto WordFunc_WordFind2X${_WORDFUNC_S}_end
+
+ WordFunc_WordFind2X${_WORDFUNC_S}_error3:
+ StrCpy $R1 3
+ goto WordFunc_WordFind2X${_WORDFUNC_S}_error
+ WordFunc_WordFind2X${_WORDFUNC_S}_error2:
+ StrCpy $R1 2
+ goto WordFunc_WordFind2X${_WORDFUNC_S}_error
+ WordFunc_WordFind2X${_WORDFUNC_S}_error1:
+ StrCpy $R1 1
+ WordFunc_WordFind2X${_WORDFUNC_S}_error:
+ StrCmp $R2 'E' 0 +3
+ SetErrors
+
+ WordFunc_WordFind2X${_WORDFUNC_S}_end:
+ StrCpy $R0 $R1
+
+ Pop $R2
+ Pop $R1
+ Pop $9
+ Pop $8
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+ Exch $R0
+!macroend
+
+!define WordFind2X `!insertmacro WordFind2XCall`
+!define un.WordFind2X `!insertmacro WordFind2XCall`
+
+!macro WordFind2X
+!macroend
+
+!macro un.WordFind2X
+!macroend
+
+!macro WordFind2X_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ !insertmacro WordFind2XBody ''
+
+ !verbose pop
+!macroend
+
+!define WordFind2XS `!insertmacro WordFind2XSCall`
+!define un.WordFind2XS `!insertmacro WordFind2XSCall`
+
+!macro WordFind2XS
+!macroend
+
+!macro un.WordFind2XS
+!macroend
+
+!macro WordFind2XS_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ !insertmacro WordFind2XBody 'S'
+
+ !verbose pop
+!macroend
+
+!macro WordFind3XBody _WORDFUNC_S
+ Exch $3
+ Exch
+ Exch $2
+ Exch
+ Exch 2
+ Exch $1
+ Exch 2
+ Exch 3
+ Exch $0
+ Exch 3
+ Exch 4
+ Exch $R0
+ Exch 4
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $8
+ Push $9
+ Push $R1
+ Push $R2
+ Push $R3
+ Push $R4
+ Push $R5
+ ClearErrors
+
+ StrCpy $R5 ''
+ StrCpy $4 $3 1
+ StrCpy $3 $3 '' 1
+ StrCmp $4 'E' 0 +3
+ StrCpy $R5 E
+ goto -4
+
+ StrCmp${_WORDFUNC_S} $4 '+' +5
+ StrCmp${_WORDFUNC_S} $4 '-' +4
+ StrCmp${_WORDFUNC_S} $4 '#' WordFunc_WordFind3X${_WORDFUNC_S}_restart
+ StrCmp${_WORDFUNC_S} $4 '/' WordFunc_WordFind3X${_WORDFUNC_S}_restart
+ goto WordFunc_WordFind3X${_WORDFUNC_S}_error3
+
+ StrCpy $5 $3 2 -2
+ StrCmp${_WORDFUNC_S} $5 '{{' +9
+ StrCmp${_WORDFUNC_S} $5 '}}' +8
+ StrCmp${_WORDFUNC_S} $5 '{*' +7
+ StrCmp${_WORDFUNC_S} $5 '*{' +6
+ StrCmp${_WORDFUNC_S} $5 '*}' +5
+ StrCmp${_WORDFUNC_S} $5 '}*' +4
+ StrCmp${_WORDFUNC_S} $5 '{}' +3
+ StrCpy $5 ''
+ goto +2
+ StrCpy $3 $3 -2
+ IntOp $3 $3 + 0
+ StrCmp${_WORDFUNC_S} $3 0 WordFunc_WordFind3X${_WORDFUNC_S}_error2
+
+ WordFunc_WordFind3X${_WORDFUNC_S}_restart:
+ StrCmp${_WORDFUNC_S} $R0 '' WordFunc_WordFind3X${_WORDFUNC_S}_error1
+ StrCpy $6 -1
+ StrCpy $7 0
+ StrCpy $8 ''
+ StrCpy $9 ''
+ StrLen $R1 $0
+ StrLen $R2 $1
+ StrLen $R3 $2
+
+ WordFunc_WordFind3X${_WORDFUNC_S}_loop:
+ IntOp $6 $6 + 1
+
+ WordFunc_WordFind3X${_WORDFUNC_S}_delim1:
+ StrCpy $R4 $R0 $R1 $6
+ StrCmp${_WORDFUNC_S} $R4$7 0 WordFunc_WordFind3X${_WORDFUNC_S}_error1
+ StrCmp${_WORDFUNC_S} $R4 '' WordFunc_WordFind3X${_WORDFUNC_S}_minus
+ StrCmp${_WORDFUNC_S} $R4 $0 +2
+ StrCmp${_WORDFUNC_S} $8 '' WordFunc_WordFind3X${_WORDFUNC_S}_loop WordFunc_WordFind3X${_WORDFUNC_S}_center
+ StrCmp${_WORDFUNC_S} $0 $1 +2
+ StrCmp${_WORDFUNC_S} $0 $2 0 +2
+ StrCmp${_WORDFUNC_S} $8 '' 0 WordFunc_WordFind3X${_WORDFUNC_S}_center
+ IntOp $8 $6 + $R1
+ StrCpy $6 $8
+ goto WordFunc_WordFind3X${_WORDFUNC_S}_delim1
+
+ WordFunc_WordFind3X${_WORDFUNC_S}_center:
+ StrCmp${_WORDFUNC_S} $9 '' 0 WordFunc_WordFind3X${_WORDFUNC_S}_delim2
+ StrCpy $R4 $R0 $R2 $6
+ StrCmp${_WORDFUNC_S} $R4 $1 0 WordFunc_WordFind3X${_WORDFUNC_S}_loop
+ IntOp $9 $6 + $R2
+ StrCpy $6 $9
+ goto WordFunc_WordFind3X${_WORDFUNC_S}_delim1
+
+ WordFunc_WordFind3X${_WORDFUNC_S}_delim2:
+ StrCpy $R4 $R0 $R3 $6
+ StrCmp${_WORDFUNC_S} $R4 $2 0 WordFunc_WordFind3X${_WORDFUNC_S}_loop
+ IntOp $7 $7 + 1
+ StrCmp${_WORDFUNC_S} $4$7 '+$3' WordFunc_WordFind3X${_WORDFUNC_S}_plus
+ StrCmp${_WORDFUNC_S} $4 '/' 0 WordFunc_WordFind3X${_WORDFUNC_S}_nextword
+ IntOp $R4 $6 - $8
+ StrCpy $R4 $R0 $R4 $8
+ StrCmp${_WORDFUNC_S} $R4 $3 0 +3
+ StrCpy $R4 $7
+ goto WordFunc_WordFind3X${_WORDFUNC_S}_end
+ WordFunc_WordFind3X${_WORDFUNC_S}_nextword:
+ IntOp $6 $6 + $R3
+ StrCpy $8 ''
+ StrCpy $9 ''
+ goto WordFunc_WordFind3X${_WORDFUNC_S}_delim1
+
+ WordFunc_WordFind3X${_WORDFUNC_S}_minus:
+ StrCmp${_WORDFUNC_S} $4 '-' 0 WordFunc_WordFind3X${_WORDFUNC_S}_sum
+ StrCpy $4 +
+ IntOp $3 $7 - $3
+ IntOp $3 $3 + 1
+ IntCmp $3 0 WordFunc_WordFind3X${_WORDFUNC_S}_error2 WordFunc_WordFind3X${_WORDFUNC_S}_error2 WordFunc_WordFind3X${_WORDFUNC_S}_restart
+ WordFunc_WordFind3X${_WORDFUNC_S}_sum:
+ StrCmp${_WORDFUNC_S} $4 '#' 0 WordFunc_WordFind3X${_WORDFUNC_S}_error2
+ StrCpy $R4 $7
+ goto WordFunc_WordFind3X${_WORDFUNC_S}_end
+
+ WordFunc_WordFind3X${_WORDFUNC_S}_plus:
+ StrCmp${_WORDFUNC_S} $5 '' 0 +4
+ IntOp $R4 $6 - $8
+ StrCpy $R4 $R0 $R4 $8
+ goto WordFunc_WordFind3X${_WORDFUNC_S}_end
+ IntOp $6 $6 + $R3
+ IntOp $8 $8 - $R1
+ StrCmp${_WORDFUNC_S} $5 '{*' +2
+ StrCmp${_WORDFUNC_S} $5 '*{' 0 +3
+ StrCpy $R4 $R0 $6
+ goto WordFunc_WordFind3X${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $5 '*}' +2
+ StrCmp${_WORDFUNC_S} $5 '}*' 0 +3
+ StrCpy $R4 $R0 '' $8
+ goto WordFunc_WordFind3X${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $5 '}}' 0 +3
+ StrCpy $R4 $R0 '' $6
+ goto WordFunc_WordFind3X${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $5 '{{' 0 +3
+ StrCpy $R4 $R0 $8
+ goto WordFunc_WordFind3X${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $5 '{}' 0 WordFunc_WordFind3X${_WORDFUNC_S}_error3
+ StrCpy $6 $R0 '' $6
+ StrCpy $8 $R0 $8
+ StrCpy $R4 '$8$6'
+ goto WordFunc_WordFind3X${_WORDFUNC_S}_end
+
+ WordFunc_WordFind3X${_WORDFUNC_S}_error3:
+ StrCpy $R4 3
+ goto WordFunc_WordFind3X${_WORDFUNC_S}_error
+ WordFunc_WordFind3X${_WORDFUNC_S}_error2:
+ StrCpy $R4 2
+ goto WordFunc_WordFind3X${_WORDFUNC_S}_error
+ WordFunc_WordFind3X${_WORDFUNC_S}_error1:
+ StrCpy $R4 1
+ WordFunc_WordFind3X${_WORDFUNC_S}_error:
+ StrCmp $R5 'E' 0 +3
+ SetErrors
+
+ WordFunc_WordFind3X${_WORDFUNC_S}_end:
+ StrCpy $R0 $R4
+ Pop $R5
+ Pop $R4
+ Pop $R3
+ Pop $R2
+ Pop $R1
+ Pop $9
+ Pop $8
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+ Exch $R0
+!macroend
+
+!define WordFind3X `!insertmacro WordFind3XCall`
+!define un.WordFind3X `!insertmacro WordFind3XCall`
+
+!macro WordFind3X
+!macroend
+
+!macro un.WordFind3X
+!macroend
+
+!macro WordFind3X_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ !insertmacro WordFind3XBody ''
+
+ !verbose pop
+!macroend
+
+!define WordFind3XS `!insertmacro WordFind3XSCall`
+!define un.WordFind3XS `!insertmacro WordFind3XSCall`
+
+!macro WordFind3XS
+!macroend
+
+!macro un.WordFind3XS
+!macroend
+
+!macro WordFind3XS_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ !insertmacro WordFind3XBody 'S'
+
+ !verbose pop
+!macroend
+
+!macro WordReplaceBody _WORDFUNC_S
+ Exch $2
+ Exch
+ Exch $1
+ Exch
+ Exch 2
+ Exch $0
+ Exch 2
+ Exch 3
+ Exch $R0
+ Exch 3
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $8
+ Push $9
+ Push $R1
+ ClearErrors
+
+ StrCpy $R1 $R0
+ StrCpy $9 ''
+ StrCpy $3 $2 1
+ StrCpy $2 $2 '' 1
+ StrCmp $3 'E' 0 +3
+ StrCpy $9 E
+ goto -4
+
+ StrCpy $4 $2 1 -1
+ StrCpy $5 ''
+ StrCpy $6 ''
+ StrLen $7 $0
+
+ StrCmp${_WORDFUNC_S} $7 0 WordFunc_WordReplace${_WORDFUNC_S}_error1
+ StrCmp${_WORDFUNC_S} $R0 '' WordFunc_WordReplace${_WORDFUNC_S}_error1
+ StrCmp${_WORDFUNC_S} $3 '{' WordFunc_WordReplace${_WORDFUNC_S}_beginning
+ StrCmp${_WORDFUNC_S} $3 '}' WordFunc_WordReplace${_WORDFUNC_S}_ending WordFunc_WordReplace${_WORDFUNC_S}_errorchk
+
+ WordFunc_WordReplace${_WORDFUNC_S}_beginning:
+ StrCpy $8 $R0 $7
+ StrCmp${_WORDFUNC_S} $8 $0 0 +4
+ StrCpy $R0 $R0 '' $7
+ StrCpy $5 '$5$1'
+ goto -4
+ StrCpy $3 $2 1
+ StrCmp${_WORDFUNC_S} $3 '}' 0 WordFunc_WordReplace${_WORDFUNC_S}_merge
+
+ WordFunc_WordReplace${_WORDFUNC_S}_ending:
+ StrCpy $8 $R0 '' -$7
+ StrCmp${_WORDFUNC_S} $8 $0 0 +4
+ StrCpy $R0 $R0 -$7
+ StrCpy $6 '$6$1'
+ goto -4
+
+ WordFunc_WordReplace${_WORDFUNC_S}_merge:
+ StrCmp${_WORDFUNC_S} $4 '*' 0 +5
+ StrCmp${_WORDFUNC_S} $5 '' +2
+ StrCpy $5 $1
+ StrCmp${_WORDFUNC_S} $6 '' +2
+ StrCpy $6 $1
+ StrCpy $R0 '$5$R0$6'
+ goto WordFunc_WordReplace${_WORDFUNC_S}_end
+
+ WordFunc_WordReplace${_WORDFUNC_S}_errorchk:
+ StrCmp${_WORDFUNC_S} $3 '+' +2
+ StrCmp${_WORDFUNC_S} $3 '-' 0 WordFunc_WordReplace${_WORDFUNC_S}_error3
+
+ StrCpy $5 $2 1
+ IntOp $2 $2 + 0
+ StrCmp${_WORDFUNC_S} $2 0 0 WordFunc_WordReplace${_WORDFUNC_S}_one
+ StrCmp${_WORDFUNC_S} $5 0 WordFunc_WordReplace${_WORDFUNC_S}_error2
+ StrCpy $3 ''
+
+ WordFunc_WordReplace${_WORDFUNC_S}_all:
+ StrCpy $5 0
+ StrCpy $2 $R0 $7 $5
+ StrCmp${_WORDFUNC_S} $2 '' +4
+ StrCmp${_WORDFUNC_S} $2 $0 +6
+ IntOp $5 $5 + 1
+ goto -4
+ StrCmp${_WORDFUNC_S} $R0 $R1 WordFunc_WordReplace${_WORDFUNC_S}_error1
+ StrCpy $R0 '$3$R0'
+ goto WordFunc_WordReplace${_WORDFUNC_S}_end
+ StrCpy $2 $R0 $5
+ IntOp $5 $5 + $7
+ StrCmp${_WORDFUNC_S} $4 '*' 0 +3
+ StrCpy $6 $R0 $7 $5
+ StrCmp${_WORDFUNC_S} $6 $0 -3
+ StrCpy $R0 $R0 '' $5
+ StrCpy $3 '$3$2$1'
+ goto WordFunc_WordReplace${_WORDFUNC_S}_all
+
+ WordFunc_WordReplace${_WORDFUNC_S}_one:
+ StrCpy $5 0
+ StrCpy $8 0
+ goto WordFunc_WordReplace${_WORDFUNC_S}_loop
+
+ WordFunc_WordReplace${_WORDFUNC_S}_preloop:
+ IntOp $5 $5 + 1
+
+ WordFunc_WordReplace${_WORDFUNC_S}_loop:
+ StrCpy $6 $R0 $7 $5
+ StrCmp${_WORDFUNC_S} $6$8 0 WordFunc_WordReplace${_WORDFUNC_S}_error1
+ StrCmp${_WORDFUNC_S} $6 '' WordFunc_WordReplace${_WORDFUNC_S}_minus
+ StrCmp${_WORDFUNC_S} $6 $0 0 WordFunc_WordReplace${_WORDFUNC_S}_preloop
+ IntOp $8 $8 + 1
+ StrCmp${_WORDFUNC_S} $3$8 +$2 WordFunc_WordReplace${_WORDFUNC_S}_found
+ IntOp $5 $5 + $7
+ goto WordFunc_WordReplace${_WORDFUNC_S}_loop
+
+ WordFunc_WordReplace${_WORDFUNC_S}_minus:
+ StrCmp${_WORDFUNC_S} $3 '-' 0 WordFunc_WordReplace${_WORDFUNC_S}_error2
+ StrCpy $3 +
+ IntOp $2 $8 - $2
+ IntOp $2 $2 + 1
+ IntCmp $2 0 WordFunc_WordReplace${_WORDFUNC_S}_error2 WordFunc_WordReplace${_WORDFUNC_S}_error2 WordFunc_WordReplace${_WORDFUNC_S}_one
+
+ WordFunc_WordReplace${_WORDFUNC_S}_found:
+ StrCpy $3 $R0 $5
+ StrCmp${_WORDFUNC_S} $4 '*' 0 +5
+ StrCpy $6 $3 '' -$7
+ StrCmp${_WORDFUNC_S} $6 $0 0 +3
+ StrCpy $3 $3 -$7
+ goto -3
+ IntOp $5 $5 + $7
+ StrCmp${_WORDFUNC_S} $4 '*' 0 +3
+ StrCpy $6 $R0 $7 $5
+ StrCmp${_WORDFUNC_S} $6 $0 -3
+ StrCpy $R0 $R0 '' $5
+ StrCpy $R0 '$3$1$R0'
+ goto WordFunc_WordReplace${_WORDFUNC_S}_end
+
+ WordFunc_WordReplace${_WORDFUNC_S}_error3:
+ StrCpy $R0 3
+ goto WordFunc_WordReplace${_WORDFUNC_S}_error
+ WordFunc_WordReplace${_WORDFUNC_S}_error2:
+ StrCpy $R0 2
+ goto WordFunc_WordReplace${_WORDFUNC_S}_error
+ WordFunc_WordReplace${_WORDFUNC_S}_error1:
+ StrCpy $R0 1
+ WordFunc_WordReplace${_WORDFUNC_S}_error:
+ StrCmp $9 'E' +3
+ StrCpy $R0 $R1
+ goto +2
+ SetErrors
+
+ WordFunc_WordReplace${_WORDFUNC_S}_end:
+ Pop $R1
+ Pop $9
+ Pop $8
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+ Exch $R0
+!macroend
+
+!define WordReplace `!insertmacro WordReplaceCall`
+!define un.WordReplace `!insertmacro WordReplaceCall`
+
+!macro WordReplace
+!macroend
+
+!macro un.WordReplace
+!macroend
+
+!macro WordReplace_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ !insertmacro WordReplaceBody ''
+
+ !verbose pop
+!macroend
+
+!define WordReplaceS `!insertmacro WordReplaceSCall`
+!define un.WordReplaceS `!insertmacro WordReplaceSCall`
+
+!macro WordReplaceS
+!macroend
+
+!macro un.WordReplaceS
+!macroend
+
+!macro WordReplaceS_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ !insertmacro WordReplaceBody 'S'
+
+ !verbose pop
+!macroend
+
+!macro WordAddBody _WORDFUNC_S
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Exch 2
+ Exch $R0
+ Exch 2
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $R1
+ ClearErrors
+
+ StrCpy $7 ''
+ StrCpy $2 $1 1
+ StrCmp $2 'E' 0 +4
+ StrCpy $7 E
+ StrCpy $1 $1 '' 1
+ goto -4
+
+ StrCpy $5 0
+ StrCpy $R1 $R0
+ StrCpy $2 $1 '' 1
+ StrCpy $1 $1 1
+ StrCmp${_WORDFUNC_S} $1 '+' +2
+ StrCmp${_WORDFUNC_S} $1 '-' 0 WordFunc_WordAdd${_WORDFUNC_S}_error3
+
+ StrCmp${_WORDFUNC_S} $0 '' WordFunc_WordAdd${_WORDFUNC_S}_error1
+ StrCmp${_WORDFUNC_S} $2 '' WordFunc_WordAdd${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $R0 '' 0 +5
+ StrCmp${_WORDFUNC_S} $1 '-' WordFunc_WordAdd${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $1 '+' 0 +3
+ StrCpy $R0 $2
+ goto WordFunc_WordAdd${_WORDFUNC_S}_end
+
+ WordFunc_WordAdd${_WORDFUNC_S}_loop:
+ IntOp $5 $5 + 1
+ !insertmacro WordFind${_WORDFUNC_S}Call 2 $2 $0 E+$5 $3
+ IfErrors 0 WordFunc_WordAdd${_WORDFUNC_S}_/word
+ StrCmp${_WORDFUNC_S} $3 2 +4
+ StrCmp${_WORDFUNC_S} $3$5 11 0 +3
+ StrCpy $3 $2
+ goto WordFunc_WordAdd${_WORDFUNC_S}_/word
+ StrCmp${_WORDFUNC_S} $1 '-' WordFunc_WordAdd${_WORDFUNC_S}_end WordFunc_WordAdd${_WORDFUNC_S}_preend
+
+ WordFunc_WordAdd${_WORDFUNC_S}_/word:
+ !insertmacro WordFind${_WORDFUNC_S}Call 2 $R0 $0 E/$3 $4
+ IfErrors +2
+ StrCmp${_WORDFUNC_S} $1 '-' WordFunc_WordAdd${_WORDFUNC_S}_delete WordFunc_WordAdd${_WORDFUNC_S}_loop
+ StrCmp${_WORDFUNC_S} $1$4 '-1' +2
+ StrCmp${_WORDFUNC_S} $1 '-' WordFunc_WordAdd${_WORDFUNC_S}_loop +4
+ StrCmp${_WORDFUNC_S} $R0 $3 0 WordFunc_WordAdd${_WORDFUNC_S}_loop
+ StrCpy $R0 ''
+ goto WordFunc_WordAdd${_WORDFUNC_S}_end
+ StrCmp${_WORDFUNC_S} $1$4 '+1' 0 +2
+ StrCmp${_WORDFUNC_S} $R0 $3 WordFunc_WordAdd${_WORDFUNC_S}_loop
+ StrCmp${_WORDFUNC_S} $R0 $R1 +3
+ StrCpy $R1 '$R1$0$3'
+ goto WordFunc_WordAdd${_WORDFUNC_S}_loop
+ StrLen $6 $0
+ StrCpy $6 $R0 '' -$6
+ StrCmp${_WORDFUNC_S} $6 $0 0 -4
+ StrCpy $R1 '$R1$3'
+ goto WordFunc_WordAdd${_WORDFUNC_S}_loop
+
+ WordFunc_WordAdd${_WORDFUNC_S}_delete:
+ !insertmacro WordFind${_WORDFUNC_S}Call 2 $R0 $0 E+$4{} $R0
+ goto WordFunc_WordAdd${_WORDFUNC_S}_/word
+
+ WordFunc_WordAdd${_WORDFUNC_S}_error3:
+ StrCpy $R1 3
+ goto WordFunc_WordAdd${_WORDFUNC_S}_error
+ WordFunc_WordAdd${_WORDFUNC_S}_error1:
+ StrCpy $R1 1
+ WordFunc_WordAdd${_WORDFUNC_S}_error:
+ StrCmp $7 'E' 0 WordFunc_WordAdd${_WORDFUNC_S}_end
+ SetErrors
+
+ WordFunc_WordAdd${_WORDFUNC_S}_preend:
+ StrCpy $R0 $R1
+
+ WordFunc_WordAdd${_WORDFUNC_S}_end:
+ Pop $R1
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+ Exch $R0
+!macroend
+
+!define WordAdd `!insertmacro WordAddCall`
+!define un.WordAdd `!insertmacro WordAddCall`
+
+!macro WordAdd
+!macroend
+
+!macro un.WordAdd
+!macroend
+
+!macro WordAdd_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ !insertmacro WordAddBody ''
+
+ !verbose pop
+!macroend
+
+!define WordAddS `!insertmacro WordAddSCall`
+!define un.WordAddS `!insertmacro WordAddSCall`
+
+!macro WordAddS
+!macroend
+
+!macro un.WordAddS
+!macroend
+
+!macro WordAddS_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ !insertmacro WordAddBody 'S'
+
+ !verbose pop
+!macroend
+
+!macro WordInsertBody _WORDFUNC_S
+ Exch $2
+ Exch
+ Exch $1
+ Exch
+ Exch 2
+ Exch $0
+ Exch 2
+ Exch 3
+ Exch $R0
+ Exch 3
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $8
+ Push $9
+ Push $R1
+ ClearErrors
+
+ StrCpy $5 ''
+ StrCpy $6 $0
+ StrCpy $7 }
+
+ StrCpy $9 ''
+ StrCpy $R1 $R0
+ StrCpy $3 $2 1
+ StrCpy $2 $2 '' 1
+ StrCmp $3 'E' 0 +3
+ StrCpy $9 'E'
+ goto -4
+
+ StrCmp${_WORDFUNC_S} $3 '+' +2
+ StrCmp${_WORDFUNC_S} $3 '-' 0 WordFunc_WordInsert${_WORDFUNC_S}_error3
+ IntOp $2 $2 + 0
+ StrCmp${_WORDFUNC_S} $2 0 WordFunc_WordInsert${_WORDFUNC_S}_error2
+ StrCmp${_WORDFUNC_S} $0 '' WordFunc_WordInsert${_WORDFUNC_S}_error1
+
+ StrCmp${_WORDFUNC_S} $2 1 0 WordFunc_WordInsert${_WORDFUNC_S}_two
+ GetLabelAddress $8 WordFunc_WordInsert${_WORDFUNC_S}_oneback
+ StrCmp${_WORDFUNC_S} $3 '+' WordFunc_WordInsert${_WORDFUNC_S}_call
+ StrCpy $7 {
+ goto WordFunc_WordInsert${_WORDFUNC_S}_call
+ WordFunc_WordInsert${_WORDFUNC_S}_oneback:
+ IfErrors 0 +2
+ StrCpy $4 $R0
+ StrCmp${_WORDFUNC_S} $3 '+' 0 +3
+ StrCpy $R0 '$1$0$4'
+ goto WordFunc_WordInsert${_WORDFUNC_S}_end
+ StrCpy $R0 '$4$0$1'
+ goto WordFunc_WordInsert${_WORDFUNC_S}_end
+
+ WordFunc_WordInsert${_WORDFUNC_S}_two:
+ IntOp $2 $2 - 1
+ GetLabelAddress $8 WordFunc_WordInsert${_WORDFUNC_S}_twoback
+ StrCmp${_WORDFUNC_S} $3 '+' 0 WordFunc_WordInsert${_WORDFUNC_S}_call
+ StrCpy $7 {
+ goto WordFunc_WordInsert${_WORDFUNC_S}_call
+ WordFunc_WordInsert${_WORDFUNC_S}_twoback:
+ IfErrors 0 WordFunc_WordInsert${_WORDFUNC_S}_tree
+ StrCmp${_WORDFUNC_S} $2$4 11 0 WordFunc_WordInsert${_WORDFUNC_S}_error2
+ StrCmp${_WORDFUNC_S} $3 '+' 0 +3
+ StrCpy $R0 '$R0$0$1'
+ goto WordFunc_WordInsert${_WORDFUNC_S}_end
+ StrCpy $R0 '$1$0$R0'
+ goto WordFunc_WordInsert${_WORDFUNC_S}_end
+
+ WordFunc_WordInsert${_WORDFUNC_S}_tree:
+ StrCpy $7 }
+ StrCpy $5 $4
+ IntOp $2 $2 + 1
+ GetLabelAddress $8 WordFunc_WordInsert${_WORDFUNC_S}_treeback
+ StrCmp${_WORDFUNC_S} $3 '+' WordFunc_WordInsert${_WORDFUNC_S}_call
+ StrCpy $7 {
+ goto WordFunc_WordInsert${_WORDFUNC_S}_call
+ WordFunc_WordInsert${_WORDFUNC_S}_treeback:
+ IfErrors 0 +3
+ StrCpy $4 ''
+ StrCpy $6 ''
+ StrCmp${_WORDFUNC_S} $3 '+' 0 +3
+ StrCpy $R0 '$5$0$1$6$4'
+ goto WordFunc_WordInsert${_WORDFUNC_S}_end
+ StrCpy $R0 '$4$6$1$0$5'
+ goto WordFunc_WordInsert${_WORDFUNC_S}_end
+
+ WordFunc_WordInsert${_WORDFUNC_S}_call:
+ !insertmacro WordFind${_WORDFUNC_S}Call 2 $R0 $0 E$3$2*$7 $4
+ goto $8
+
+ WordFunc_WordInsert${_WORDFUNC_S}_error3:
+ StrCpy $R0 3
+ goto WordFunc_WordInsert${_WORDFUNC_S}_error
+ WordFunc_WordInsert${_WORDFUNC_S}_error2:
+ StrCpy $R0 2
+ goto WordFunc_WordInsert${_WORDFUNC_S}_error
+ WordFunc_WordInsert${_WORDFUNC_S}_error1:
+ StrCpy $R0 1
+ WordFunc_WordInsert${_WORDFUNC_S}_error:
+ StrCmp $9 'E' +3
+ StrCpy $R0 $R1
+ goto +2
+ SetErrors
+
+ WordFunc_WordInsert${_WORDFUNC_S}_end:
+ Pop $R1
+ Pop $9
+ Pop $8
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+ Exch $R0
+!macroend
+
+!define WordInsert `!insertmacro WordInsertCall`
+!define un.WordInsert `!insertmacro WordInsertCall`
+
+!macro WordInsert
+!macroend
+
+!macro un.WordInsert
+!macroend
+
+!macro WordInsert_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ !insertmacro WordInsertBody ''
+
+ !verbose pop
+!macroend
+
+
+!define WordInsertS `!insertmacro WordInsertSCall`
+!define un.WordInsertS `!insertmacro WordInsertSCall`
+
+!macro WordInsertS
+!macroend
+
+!macro un.WordInsertS
+!macroend
+
+!macro WordInsertS_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ !insertmacro WordInsertBody 'S'
+
+ !verbose pop
+!macroend
+
+!macro StrFilterBody _WORDFUNC_S
+ Exch $2
+ Exch
+ Exch $1
+ Exch
+ Exch 2
+ Exch $0
+ Exch 2
+ Exch 3
+ Exch $R0
+ Exch 3
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+ Push $R1
+ Push $R2
+ Push $R3
+ Push $R4
+ Push $R5
+ Push $R6
+ Push $R7
+ Push $R8
+ ClearErrors
+
+ StrCpy $R2 $0 '' -3
+ StrCmp $R2 "eng" WordFunc_StrFilter${_WORDFUNC_S}_eng
+ StrCmp $R2 "rus" WordFunc_StrFilter${_WORDFUNC_S}_rus
+ WordFunc_StrFilter${_WORDFUNC_S}_eng:
+ StrCpy $4 65
+ StrCpy $5 90
+ StrCpy $6 97
+ StrCpy $7 122
+ goto WordFunc_StrFilter${_WORDFUNC_S}_langend
+ WordFunc_StrFilter${_WORDFUNC_S}_rus:
+ StrCpy $4 192
+ StrCpy $5 223
+ StrCpy $6 224
+ StrCpy $7 255
+ goto WordFunc_StrFilter${_WORDFUNC_S}_langend
+ ;...
+
+ WordFunc_StrFilter${_WORDFUNC_S}_langend:
+ StrCpy $R7 ''
+ StrCpy $R8 ''
+
+ StrCmp${_WORDFUNC_S} $2 '' 0 WordFunc_StrFilter${_WORDFUNC_S}_begin
+
+ WordFunc_StrFilter${_WORDFUNC_S}_restart1:
+ StrCpy $2 ''
+ StrCpy $3 $0 1
+ StrCmp${_WORDFUNC_S} $3 '+' +2
+ StrCmp${_WORDFUNC_S} $3 '-' 0 +3
+ StrCpy $0 $0 '' 1
+ goto +2
+ StrCpy $3 ''
+
+ IntOp $0 $0 + 0
+ StrCmp${_WORDFUNC_S} $0 0 +5
+ StrCpy $R7 $0 1 0
+ StrCpy $R8 $0 1 1
+ StrCpy $R2 $0 1 2
+ StrCmp${_WORDFUNC_S} $R2 '' WordFunc_StrFilter${_WORDFUNC_S}_filter WordFunc_StrFilter${_WORDFUNC_S}_error
+
+ WordFunc_StrFilter${_WORDFUNC_S}_restart2:
+ StrCmp${_WORDFUNC_S} $3 '' WordFunc_StrFilter${_WORDFUNC_S}_end
+ StrCpy $R7 ''
+ StrCpy $R8 '+-'
+ goto WordFunc_StrFilter${_WORDFUNC_S}_begin
+
+ WordFunc_StrFilter${_WORDFUNC_S}_filter:
+ StrCmp${_WORDFUNC_S} $R7 '1' +3
+ StrCmp${_WORDFUNC_S} $R7 '2' +2
+ StrCmp${_WORDFUNC_S} $R7 '3' 0 WordFunc_StrFilter${_WORDFUNC_S}_error
+
+ StrCmp${_WORDFUNC_S} $R8 '' WordFunc_StrFilter${_WORDFUNC_S}_begin
+ StrCmp${_WORDFUNC_S} $R7$R8 '23' +2
+ StrCmp${_WORDFUNC_S} $R7$R8 '32' 0 +3
+ StrCpy $R7 -1
+ goto WordFunc_StrFilter${_WORDFUNC_S}_begin
+ StrCmp${_WORDFUNC_S} $R7$R8 '13' +2
+ StrCmp${_WORDFUNC_S} $R7$R8 '31' 0 +3
+ StrCpy $R7 -2
+ goto WordFunc_StrFilter${_WORDFUNC_S}_begin
+ StrCmp${_WORDFUNC_S} $R7$R8 '12' +2
+ StrCmp${_WORDFUNC_S} $R7$R8 '21' 0 WordFunc_StrFilter${_WORDFUNC_S}_error
+ StrCpy $R7 -3
+
+ WordFunc_StrFilter${_WORDFUNC_S}_begin:
+ StrCpy $R6 0
+ StrCpy $R1 ''
+
+ WordFunc_StrFilter${_WORDFUNC_S}_loop:
+ StrCpy $R2 $R0 1 $R6
+ StrCmp${_WORDFUNC_S} $R2 '' WordFunc_StrFilter${_WORDFUNC_S}_restartchk
+
+ StrCmp${_WORDFUNC_S} $2 '' +7
+ StrCpy $R4 0
+ StrCpy $R5 $2 1 $R4
+ StrCmp${_WORDFUNC_S} $R5 '' WordFunc_StrFilter${_WORDFUNC_S}_addsymbol
+ StrCmp${_WORDFUNC_S} $R5 $R2 WordFunc_StrFilter${_WORDFUNC_S}_skipsymbol
+ IntOp $R4 $R4 + 1
+ goto -4
+
+ StrCmp${_WORDFUNC_S} $1 '' +7
+ StrCpy $R4 0
+ StrCpy $R5 $1 1 $R4
+ StrCmp${_WORDFUNC_S} $R5 '' +4
+ StrCmp${_WORDFUNC_S} $R5 $R2 WordFunc_StrFilter${_WORDFUNC_S}_addsymbol
+ IntOp $R4 $R4 + 1
+ goto -4
+
+ StrCmp${_WORDFUNC_S} $R7 '1' +2
+ StrCmp${_WORDFUNC_S} $R7 '-1' 0 +4
+ StrCpy $R4 48
+ StrCpy $R5 57
+ goto WordFunc_StrFilter${_WORDFUNC_S}_loop2
+ StrCmp${_WORDFUNC_S} $R8 '+-' 0 +2
+ StrCmp${_WORDFUNC_S} $3 '+' 0 +4
+ StrCpy $R4 $4
+ StrCpy $R5 $5
+ goto WordFunc_StrFilter${_WORDFUNC_S}_loop2
+ StrCpy $R4 $6
+ StrCpy $R5 $7
+
+ WordFunc_StrFilter${_WORDFUNC_S}_loop2:
+ IntFmt $R3 '%c' $R4
+ StrCmp $R2 $R3 WordFunc_StrFilter${_WORDFUNC_S}_found
+ StrCmp $R4 $R5 WordFunc_StrFilter${_WORDFUNC_S}_notfound
+ IntOp $R4 $R4 + 1
+ goto WordFunc_StrFilter${_WORDFUNC_S}_loop2
+
+ WordFunc_StrFilter${_WORDFUNC_S}_found:
+ StrCmp${_WORDFUNC_S} $R8 '+-' WordFunc_StrFilter${_WORDFUNC_S}_setcase
+ StrCmp${_WORDFUNC_S} $R7 '3' WordFunc_StrFilter${_WORDFUNC_S}_skipsymbol
+ StrCmp${_WORDFUNC_S} $R7 '-3' WordFunc_StrFilter${_WORDFUNC_S}_addsymbol
+ StrCmp${_WORDFUNC_S} $R8 '' WordFunc_StrFilter${_WORDFUNC_S}_addsymbol WordFunc_StrFilter${_WORDFUNC_S}_skipsymbol
+
+ WordFunc_StrFilter${_WORDFUNC_S}_notfound:
+ StrCmp${_WORDFUNC_S} $R8 '+-' WordFunc_StrFilter${_WORDFUNC_S}_addsymbol
+ StrCmp${_WORDFUNC_S} $R7 '3' 0 +2
+ StrCmp${_WORDFUNC_S} $R5 57 WordFunc_StrFilter${_WORDFUNC_S}_addsymbol +3
+ StrCmp${_WORDFUNC_S} $R7 '-3' 0 +5
+ StrCmp${_WORDFUNC_S} $R5 57 WordFunc_StrFilter${_WORDFUNC_S}_skipsymbol
+ StrCpy $R4 48
+ StrCpy $R5 57
+ goto WordFunc_StrFilter${_WORDFUNC_S}_loop2
+ StrCmp${_WORDFUNC_S} $R8 '' WordFunc_StrFilter${_WORDFUNC_S}_skipsymbol WordFunc_StrFilter${_WORDFUNC_S}_addsymbol
+
+ WordFunc_StrFilter${_WORDFUNC_S}_setcase:
+ StrCpy $R2 $R3
+ WordFunc_StrFilter${_WORDFUNC_S}_addsymbol:
+ StrCpy $R1 $R1$R2
+ WordFunc_StrFilter${_WORDFUNC_S}_skipsymbol:
+ IntOp $R6 $R6 + 1
+ goto WordFunc_StrFilter${_WORDFUNC_S}_loop
+
+ WordFunc_StrFilter${_WORDFUNC_S}_error:
+ SetErrors
+ StrCpy $R0 ''
+ goto WordFunc_StrFilter${_WORDFUNC_S}_end
+
+ WordFunc_StrFilter${_WORDFUNC_S}_restartchk:
+ StrCpy $R0 $R1
+ StrCmp${_WORDFUNC_S} $2 '' 0 WordFunc_StrFilter${_WORDFUNC_S}_restart1
+ StrCmp${_WORDFUNC_S} $R8 '+-' 0 WordFunc_StrFilter${_WORDFUNC_S}_restart2
+
+ WordFunc_StrFilter${_WORDFUNC_S}_end:
+ Pop $R8
+ Pop $R7
+ Pop $R6
+ Pop $R5
+ Pop $R4
+ Pop $R3
+ Pop $R2
+ Pop $R1
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Pop $0
+ Exch $R0
+!macroend
+
+!define StrFilter `!insertmacro StrFilterCall`
+!define un.StrFilter `!insertmacro StrFilterCall`
+
+!macro StrFilter
+!macroend
+
+!macro un.StrFilter
+!macroend
+
+!macro StrFilter_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ !insertmacro StrFilterBody ''
+
+ !verbose pop
+!macroend
+
+
+!define StrFilterS `!insertmacro StrFilterSCall`
+!define un.StrFilterS `!insertmacro StrFilterSCall`
+
+!macro StrFilterS
+!macroend
+
+!macro un.StrFilterS
+!macroend
+
+!macro StrFilterS_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ !insertmacro StrFilterBody 'S'
+
+ !verbose pop
+!macroend
+
+!define VersionCompare `!insertmacro VersionCompareCall`
+!define un.VersionCompare `!insertmacro VersionCompareCall`
+
+!macro VersionCompare
+!macroend
+
+!macro un.VersionCompare
+!macroend
+
+!macro VersionCompare_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+
+ WordFunc_VersionCompare_begin:
+ StrCpy $2 -1
+ IntOp $2 $2 + 1
+ StrCpy $3 $0 1 $2
+ StrCmp $3 '' +2
+ StrCmp $3 '.' 0 -3
+ StrCpy $4 $0 $2
+ IntOp $2 $2 + 1
+ StrCpy $0 $0 '' $2
+
+ StrCpy $2 -1
+ IntOp $2 $2 + 1
+ StrCpy $3 $1 1 $2
+ StrCmp $3 '' +2
+ StrCmp $3 '.' 0 -3
+ StrCpy $5 $1 $2
+ IntOp $2 $2 + 1
+ StrCpy $1 $1 '' $2
+
+ StrCmp $4$5 '' WordFunc_VersionCompare_equal
+
+ StrCpy $6 -1
+ IntOp $6 $6 + 1
+ StrCpy $3 $4 1 $6
+ StrCmp $3 '0' -2
+ StrCmp $3 '' 0 +2
+ StrCpy $4 0
+
+ StrCpy $7 -1
+ IntOp $7 $7 + 1
+ StrCpy $3 $5 1 $7
+ StrCmp $3 '0' -2
+ StrCmp $3 '' 0 +2
+ StrCpy $5 0
+
+ StrCmp $4 0 0 +2
+ StrCmp $5 0 WordFunc_VersionCompare_begin WordFunc_VersionCompare_newer2
+ StrCmp $5 0 WordFunc_VersionCompare_newer1
+ IntCmp $6 $7 0 WordFunc_VersionCompare_newer1 WordFunc_VersionCompare_newer2
+
+ StrCpy $4 '1$4'
+ StrCpy $5 '1$5'
+ IntCmp $4 $5 WordFunc_VersionCompare_begin WordFunc_VersionCompare_newer2 WordFunc_VersionCompare_newer1
+
+ WordFunc_VersionCompare_equal:
+ StrCpy $0 0
+ goto WordFunc_VersionCompare_end
+ WordFunc_VersionCompare_newer1:
+ StrCpy $0 1
+ goto WordFunc_VersionCompare_end
+ WordFunc_VersionCompare_newer2:
+ StrCpy $0 2
+
+ WordFunc_VersionCompare_end:
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!define VersionConvert `!insertmacro VersionConvertCall`
+!define un.VersionConvert `!insertmacro VersionConvertCall`
+
+!macro VersionConvert
+!macroend
+
+!macro un.VersionConvert
+!macroend
+
+!macro VersionConvert_
+ !verbose push
+ !verbose ${_WORDFUNC_VERBOSE}
+
+ Exch $1
+ Exch
+ Exch $0
+ Exch
+ Push $2
+ Push $3
+ Push $4
+ Push $5
+ Push $6
+ Push $7
+
+ StrCmp $1 '' 0 +2
+ StrCpy $1 'abcdefghijklmnopqrstuvwxyz'
+ StrCpy $1 $1 99
+
+ StrCpy $2 0
+ StrCpy $7 'dot'
+ goto WordFunc_VersionConvert_loop
+
+ WordFunc_VersionConvert_preloop:
+ IntOp $2 $2 + 1
+
+ WordFunc_VersionConvert_loop:
+ StrCpy $3 $0 1 $2
+ StrCmp $3 '' WordFunc_VersionConvert_endcheck
+ StrCmp $3 '.' WordFunc_VersionConvert_dot
+ StrCmp $3 '0' WordFunc_VersionConvert_digit
+ IntCmp $3 '0' WordFunc_VersionConvert_letter WordFunc_VersionConvert_letter WordFunc_VersionConvert_digit
+
+ WordFunc_VersionConvert_dot:
+ StrCmp $7 'dot' WordFunc_VersionConvert_replacespecial
+ StrCpy $7 'dot'
+ goto WordFunc_VersionConvert_preloop
+
+ WordFunc_VersionConvert_digit:
+ StrCmp $7 'letter' WordFunc_VersionConvert_insertdot
+ StrCpy $7 'digit'
+ goto WordFunc_VersionConvert_preloop
+
+ WordFunc_VersionConvert_letter:
+ StrCpy $5 0
+ StrCpy $4 $1 1 $5
+ IntOp $5 $5 + 1
+ StrCmp $4 '' WordFunc_VersionConvert_replacespecial
+ StrCmp $4 $3 0 -3
+ IntCmp $5 9 0 0 +2
+ StrCpy $5 '0$5'
+
+ StrCmp $7 'letter' +2
+ StrCmp $7 'dot' 0 +3
+ StrCpy $6 ''
+ goto +2
+ StrCpy $6 '.'
+
+ StrCpy $4 $0 $2
+ IntOp $2 $2 + 1
+ StrCpy $0 $0 '' $2
+ StrCpy $0 '$4$6$5$0'
+ StrLen $4 '$6$5'
+ IntOp $2 $2 + $4
+ IntOp $2 $2 - 1
+ StrCpy $7 'letter'
+ goto WordFunc_VersionConvert_loop
+
+ WordFunc_VersionConvert_replacespecial:
+ StrCmp $7 'dot' 0 +3
+ StrCpy $6 ''
+ goto +2
+ StrCpy $6 '.'
+
+ StrCpy $4 $0 $2
+ IntOp $2 $2 + 1
+ StrCpy $0 $0 '' $2
+ StrCpy $0 '$4$6$0'
+ StrLen $4 $6
+ IntOp $2 $2 + $4
+ IntOp $2 $2 - 1
+ StrCpy $7 'dot'
+ goto WordFunc_VersionConvert_loop
+
+ WordFunc_VersionConvert_insertdot:
+ StrCpy $4 $0 $2
+ StrCpy $0 $0 '' $2
+ StrCpy $0 '$4.$0'
+ StrCpy $7 'dot'
+ goto WordFunc_VersionConvert_preloop
+
+ WordFunc_VersionConvert_endcheck:
+ StrCpy $4 $0 1 -1
+ StrCmp $4 '.' 0 WordFunc_VersionConvert_end
+ StrCpy $0 $0 -1
+ goto -3
+
+ WordFunc_VersionConvert_end:
+ Pop $7
+ Pop $6
+ Pop $5
+ Pop $4
+ Pop $3
+ Pop $2
+ Pop $1
+ Exch $0
+
+ !verbose pop
+!macroend
+
+!verbose pop
+!endif
diff --git a/installer/tools/Include/nsDialogs.nsh b/installer/tools/Include/nsDialogs.nsh
new file mode 100644
index 00000000..6fc27821
--- /dev/null
+++ b/installer/tools/Include/nsDialogs.nsh
@@ -0,0 +1,1249 @@
+/*
+
+nsDialogs.nsh
+Header file for creating custom installer pages with nsDialogs
+
+*/
+
+!ifndef NSDIALOGS_INCLUDED
+!verbose push 2
+!define NSDIALOGS_INCLUDED
+!verbose 3
+
+!include LogicLib.nsh
+!include WinMessages.nsh
+
+!define /ifndef WS_EX_DLGMODALFRAME 0x00000001
+!define /ifndef WS_EX_NOPARENTNOTIFY 0x00000004
+!define /ifndef WS_EX_TOPMOST 0x00000008
+!define /ifndef WS_EX_ACCEPTFILES 0x00000010
+!define /ifndef WS_EX_TRANSPARENT 0x00000020
+!define /ifndef WS_EX_MDICHILD 0x00000040
+!define /ifndef WS_EX_TOOLWINDOW 0x00000080
+!define /ifndef WS_EX_WINDOWEDGE 0x00000100
+!define /ifndef WS_EX_CLIENTEDGE 0x00000200
+!define /ifndef WS_EX_CONTEXTHELP 0x00000400
+!define /ifndef WS_EX_RIGHT 0x00001000
+!define /ifndef WS_EX_LEFT 0x00000000
+!define /ifndef WS_EX_RTLREADING 0x00002000
+!define /ifndef WS_EX_LTRREADING 0x00000000
+!define /ifndef WS_EX_LEFTSCROLLBAR 0x00004000
+!define /ifndef WS_EX_RIGHTSCROLLBAR 0x00000000
+!define /ifndef WS_EX_CONTROLPARENT 0x00010000
+!define /ifndef WS_EX_STATICEDGE 0x00020000
+!define /ifndef WS_EX_APPWINDOW 0x00040000
+
+!define /ifndef WS_CHILD 0x40000000
+!define /ifndef WS_VISIBLE 0x10000000
+!define /ifndef WS_DISABLED 0x08000000
+!define /ifndef WS_CLIPSIBLINGS 0x04000000
+!define /ifndef WS_CLIPCHILDREN 0x02000000
+!define /ifndef WS_MAXIMIZE 0x01000000
+!define /ifndef WS_BORDER 0x00800000
+!define /ifndef WS_VSCROLL 0x00200000
+!define /ifndef WS_HSCROLL 0x00100000
+!define /ifndef WS_GROUP 0x00020000
+!define /ifndef WS_MINIMIZEBOX 0x00020000
+!define /ifndef WS_MAXIMIZEBOX 0x00010000
+!define /ifndef WS_TABSTOP 0x00010000
+
+!define ES_LEFT 0x00000000
+!define ES_CENTER 0x00000001
+!define ES_RIGHT 0x00000002
+!define ES_MULTILINE 0x00000004
+!define ES_UPPERCASE 0x00000008
+!define ES_LOWERCASE 0x00000010
+!define ES_PASSWORD 0x00000020
+!define ES_AUTOVSCROLL 0x00000040
+!define ES_AUTOHSCROLL 0x00000080
+!define ES_NOHIDESEL 0x00000100
+!define ES_OEMCONVERT 0x00000400
+!define ES_READONLY 0x00000800
+!define ES_WANTRETURN 0x00001000
+!define ES_NUMBER 0x00002000
+!define ES_SAVESEL 0x00008000
+
+!define SS_LEFT 0x00000000
+!define SS_CENTER 0x00000001
+!define SS_RIGHT 0x00000002
+!define SS_ICON 0x00000003
+!define SS_BLACKRECT 0x00000004
+!define SS_GRAYRECT 0x00000005
+!define SS_WHITERECT 0x00000006
+!define SS_BLACKFRAME 0x00000007
+!define SS_GRAYFRAME 0x00000008
+!define SS_WHITEFRAME 0x00000009
+!define SS_USERITEM 0x0000000A
+!define SS_SIMPLE 0x0000000B
+!define SS_LEFTNOWORDWRAP 0x0000000C
+!define SS_OWNERDRAW 0x0000000D
+!define SS_BITMAP 0x0000000E
+!define SS_ENHMETAFILE 0x0000000F
+!define SS_ETCHEDHORZ 0x00000010
+!define SS_ETCHEDVERT 0x00000011
+!define SS_ETCHEDFRAME 0x00000012
+!define SS_TYPEMASK 0x0000001F
+!define SS_REALSIZECONTROL 0x00000040
+!define SS_NOPREFIX 0x00000080
+!define SS_NOTIFY 0x00000100
+!define SS_CENTERIMAGE 0x00000200
+!define SS_RIGHTJUST 0x00000400
+!define SS_REALSIZEIMAGE 0x00000800
+!define SS_SUNKEN 0x00001000
+!define SS_EDITCONTROL 0x00002000
+!define SS_ENDELLIPSIS 0x00004000
+!define SS_PATHELLIPSIS 0x00008000
+!define SS_WORDELLIPSIS 0x0000C000
+!define SS_ELLIPSISMASK 0x0000C000
+
+!define BS_PUSHBUTTON 0x00000000
+!define BS_DEFPUSHBUTTON 0x00000001
+!define BS_CHECKBOX 0x00000002
+!define BS_AUTOCHECKBOX 0x00000003
+!define BS_RADIOBUTTON 0x00000004
+!define BS_3STATE 0x00000005
+!define BS_AUTO3STATE 0x00000006
+!define BS_GROUPBOX 0x00000007
+!define BS_USERBUTTON 0x00000008
+!define BS_AUTORADIOBUTTON 0x00000009
+!define BS_PUSHBOX 0x0000000A
+!define BS_OWNERDRAW 0x0000000B
+!define BS_TYPEMASK 0x0000000F
+!define BS_LEFTTEXT 0x00000020
+!define BS_TEXT 0x00000000
+!define BS_ICON 0x00000040
+!define BS_BITMAP 0x00000080
+!define BS_LEFT 0x00000100
+!define BS_RIGHT 0x00000200
+!define BS_CENTER 0x00000300
+!define BS_TOP 0x00000400
+!define BS_BOTTOM 0x00000800
+!define BS_VCENTER 0x00000C00
+!define BS_PUSHLIKE 0x00001000
+!define BS_MULTILINE 0x00002000
+!define BS_NOTIFY 0x00004000
+!define BS_FLAT 0x00008000
+!define BS_RIGHTBUTTON ${BS_LEFTTEXT}
+
+!define CBS_SIMPLE 0x0001
+!define CBS_DROPDOWN 0x0002
+!define CBS_DROPDOWNLIST 0x0003
+!define CBS_OWNERDRAWFIXED 0x0010
+!define CBS_OWNERDRAWVARIABLE 0x0020
+!define CBS_AUTOHSCROLL 0x0040
+!define CBS_OEMCONVERT 0x0080
+!define CBS_SORT 0x0100
+!define CBS_HASSTRINGS 0x0200
+!define CBS_NOINTEGRALHEIGHT 0x0400
+!define CBS_DISABLENOSCROLL 0x0800
+!define CBS_UPPERCASE 0x2000
+!define CBS_LOWERCASE 0x4000
+
+!define LBS_NOTIFY 0x0001
+!define LBS_SORT 0x0002
+!define LBS_NOREDRAW 0x0004
+!define LBS_MULTIPLESEL 0x0008
+!define LBS_OWNERDRAWFIXED 0x0010
+!define LBS_OWNERDRAWVARIABLE 0x0020
+!define LBS_HASSTRINGS 0x0040
+!define LBS_USETABSTOPS 0x0080
+!define LBS_NOINTEGRALHEIGHT 0x0100
+!define LBS_MULTICOLUMN 0x0200
+!define LBS_WANTKEYBOARDINPUT 0x0400
+!define LBS_EXTENDEDSEL 0x0800
+!define LBS_DISABLENOSCROLL 0x1000
+!define LBS_NODATA 0x2000
+!define LBS_NOSEL 0x4000
+!define LBS_COMBOBOX 0x8000
+
+!define ACS_CENTER 0x0001
+!define ACS_TRANSPARENT 0x0002 ; The parent of the animation control must not have the WS_CLIPCHILDREN style
+!define ACS_AUTOPLAY 0x0004
+!define ACS_TIMER 0x0008 ; < CC6
+
+!define TBS_AUTOTICKS 0x0001
+!define TBS_VERT 0x0002
+!define TBS_HORZ 0x0000
+!define TBS_TOP 0x0004
+!define TBS_BOTTOM 0x0000
+!define TBS_LEFT 0x0004
+!define TBS_RIGHT 0x0000
+!define TBS_BOTH 0x0008
+!define TBS_NOTICKS 0x0010
+!define TBS_ENABLESELRANGE 0x0020
+!define TBS_FIXEDLENGTH 0x0040
+!define TBS_NOTHUMB 0x0080
+!define TBS_TOOLTIPS 0x0100 ; IE3
+!define TBS_REVERSED 0x0200 ; IE5
+!define TBS_DOWNISLEFT 0x0400 ; _WIN32_IE >= 0x0501
+!define TBS_NOTIFYBEFOREMOVE 0x0800 ; IE6?
+!define TBS_TRANSPARENTBKGND 0x1000 ; Vista
+
+!define UDS_WRAP 0x0001
+!define UDS_SETBUDDYINT 0x0002
+!define UDS_ALIGNRIGHT 0x0004
+!define UDS_ALIGNLEFT 0x0008
+!define UDS_AUTOBUDDY 0x0010
+!define UDS_ARROWKEYS 0x0020
+!define UDS_HORZ 0x0040
+!define UDS_NOTHOUSANDS 0x0080
+!define UDS_HOTTRACK 0x0100 ; 98+
+
+!define MCS_DAYSTATE 0x0001
+!define MCS_MULTISELECT 0x0002
+!define MCS_WEEKNUMBERS 0x0004
+!define MCS_NOTODAYCIRCLE 0x0008
+!define MCS_NOTODAY 0x0010 ; IE4+?
+!define MCS_NOTRAILINGDATES 0x0040 ; Vista+
+!define MCS_SHORTDAYSOFWEEK 0x0080 ; Vista+
+!define MCS_NOSELCHANGEONNAV 0x0100 ; Vista+
+
+!define DTS_UPDOWN 0x01
+!define DTS_SHOWNONE 0x02
+!define DTS_SHORTDATEFORMAT 0x00
+!define DTS_LONGDATEFORMAT 0x04
+!define DTS_SHORTDATECENTURYFORMAT 0x0C
+!define DTS_TIMEFORMAT 0x09
+!define DTS_APPCANPARSE 0x10
+!define DTS_RIGHTALIGN 0x20
+
+!define /ifndef LR_DEFAULTCOLOR 0x0000
+!define /ifndef LR_MONOCHROME 0x0001
+!define /ifndef LR_COLOR 0x0002
+!define /ifndef LR_COPYRETURNORG 0x0004
+!define /ifndef LR_COPYDELETEORG 0x0008
+!define /ifndef LR_LOADFROMFILE 0x0010
+!define /ifndef LR_LOADTRANSPARENT 0x0020
+!define /ifndef LR_DEFAULTSIZE 0x0040
+!define /ifndef LR_VGACOLOR 0x0080
+!define /ifndef LR_LOADMAP3DCOLORS 0x1000
+!define /ifndef LR_CREATEDIBSECTION 0x2000
+!define /ifndef LR_COPYFROMRESOURCE 0x4000
+!define /ifndef LR_SHARED 0x8000
+
+!define /ifndef IMAGE_BITMAP 0
+!define /ifndef IMAGE_ICON 1
+!define /ifndef IMAGE_CURSOR 2
+!define /ifndef IMAGE_ENHMETAFILE 3
+
+!define /ifndef GWL_STYLE -16
+!define /ifndef GWL_EXSTYLE -20
+
+#define /ifndef ICC_LISTVIEW_CLASSES 0x0001 ; SysListView32 and SysHeader32
+#define /ifndef ICC_TREEVIEW_CLASSES 0x0002 ; SysTabControl32 and tooltips_class32
+#define /ifndef ICC_BAR_CLASSES 0x0004 ; ToolbarWindow32, msctls_statusbar32, msctls_trackbar32 and tooltips_class32
+#define /ifndef ICC_TAB_CLASSES 0x0008 ; SysTabControl32 and tooltips_class32
+#define /ifndef ICC_UPDOWN_CLASS 0x0010 ; msctls_updown32
+#define /ifndef ICC_PROGRESS_CLASS 0x0020 ; msctls_progress32
+#define /ifndef ICC_HOTKEY_CLASS 0x0040 ; msctls_hotkey32
+#define /ifndef ICC_ANIMATE_CLASS 0x0080 ; SysAnimate32
+#define /ifndef ICC_WIN95_CLASSES 0x00FF
+!define /ifndef ICC_DATE_CLASSES 0x0100 ; CC4.70+ (NT4+/IE3.1+/Win95 OSR2) SysDateTimePick32, SysMonthCal32 and CC6.10+(Vista+) DropDown
+!define /ifndef ICC_USEREX_CLASSES 0x0200 ; CC4.??+ (NT4+/IE3.?+/Win95 OSR2) ComboBoxEx32
+!define /ifndef ICC_COOL_CLASSES 0x0400 ; CC4.70+ (NT4+/IE3.1+/Win95 OSR2) ReBarWindow32
+!define /ifndef ICC_INTERNET_CLASSES 0x0800 ; CC4.71+ (IE4+) SysIPAddress32
+!define /ifndef ICC_PAGESCROLLER_CLASS 0x1000 ; CC4.71+ (IE4+) SysPager
+!define /ifndef ICC_NATIVEFNTCTL_CLASS 0x2000 ; CC4.71+ (IE4+) NativeFontCtl
+!define /ifndef ICC_STANDARD_CLASSES 0x4000 ; WinXP+ Button, Static, Edit, ListBox, ComboBox, ComboLBox, ScrollBar and ReaderModeCtl
+!define /ifndef ICC_LINK_CLASS 0x8000 ; WinXP+ SysLink
+
+
+!define DEFAULT_STYLES ${WS_CHILD}|${WS_VISIBLE}|${WS_CLIPSIBLINGS}
+
+!define __NSD_HLine_CLASS STATIC
+!define __NSD_HLine_STYLE ${DEFAULT_STYLES}|${SS_ETCHEDHORZ}|${SS_SUNKEN}
+!define __NSD_HLine_EXSTYLE ${WS_EX_TRANSPARENT}
+
+!define __NSD_VLine_CLASS STATIC
+!define __NSD_VLine_STYLE ${DEFAULT_STYLES}|${SS_ETCHEDVERT}|${SS_SUNKEN}
+!define __NSD_VLine_EXSTYLE ${WS_EX_TRANSPARENT}
+
+!define __NSD_Label_CLASS STATIC
+!define __NSD_Label_STYLE ${DEFAULT_STYLES}|${SS_NOTIFY}
+!define __NSD_Label_EXSTYLE ${WS_EX_TRANSPARENT}
+
+!define __NSD_Icon_CLASS STATIC
+!define __NSD_Icon_STYLE ${DEFAULT_STYLES}|${SS_ICON}|${SS_NOTIFY}
+!define __NSD_Icon_EXSTYLE 0
+
+!define __NSD_Bitmap_CLASS STATIC
+!define __NSD_Bitmap_STYLE ${DEFAULT_STYLES}|${SS_BITMAP}|${SS_NOTIFY}
+!define __NSD_Bitmap_EXSTYLE 0
+
+!define __NSD_BrowseButton_CLASS BUTTON
+!define __NSD_BrowseButton_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}
+!define __NSD_BrowseButton_EXSTYLE 0
+
+!define __NSD_Link_CLASS LINK
+!define __NSD_Link_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${BS_OWNERDRAW}
+!define __NSD_Link_EXSTYLE 0
+
+!define __NSD_Button_CLASS BUTTON
+!define __NSD_Button_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}
+!define __NSD_Button_EXSTYLE 0
+
+!define __NSD_GroupBox_CLASS BUTTON
+!define __NSD_GroupBox_STYLE ${DEFAULT_STYLES}|${BS_GROUPBOX}
+!define __NSD_GroupBox_EXSTYLE ${WS_EX_TRANSPARENT}
+
+!define __NSD_CheckBox_CLASS BUTTON
+!define __NSD_CheckBox_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${BS_TEXT}|${BS_VCENTER}|${BS_AUTOCHECKBOX}|${BS_MULTILINE}
+!define __NSD_CheckBox_EXSTYLE 0
+
+!define __NSD_RadioButton_CLASS BUTTON
+!define __NSD_RadioButton_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${BS_TEXT}|${BS_VCENTER}|${BS_AUTORADIOBUTTON}|${BS_MULTILINE}
+!define __NSD_RadioButton_EXSTYLE 0
+
+!define __NSD_FirstRadioButton_CLASS ${__NSD_RadioButton_CLASS}
+!define __NSD_FirstRadioButton_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${WS_GROUP}|${BS_TEXT}|${BS_VCENTER}|${BS_AUTORADIOBUTTON}|${BS_MULTILINE}
+!define __NSD_FirstRadioButton_EXSTYLE ${__NSD_RadioButton_EXSTYLE}
+
+!define __NSD_AdditionalRadioButton_CLASS ${__NSD_RadioButton_CLASS}
+!define __NSD_AdditionalRadioButton_STYLE ${DEFAULT_STYLES}|${BS_TEXT}|${BS_VCENTER}|${BS_AUTORADIOBUTTON}|${BS_MULTILINE}
+!define __NSD_AdditionalRadioButton_EXSTYLE ${__NSD_RadioButton_EXSTYLE}
+
+!define __NSD_Text_CLASS EDIT
+!define __NSD_Text_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${ES_AUTOHSCROLL}
+!define __NSD_Text_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+!define __NSD_MLText_CLASS EDIT
+!define __NSD_MLText_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${ES_AUTOHSCROLL}|${ES_AUTOVSCROLL}|${ES_MULTILINE}|${ES_WANTRETURN}|${WS_HSCROLL}|${WS_VSCROLL}
+!define __NSD_MLText_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+!define __NSD_Password_CLASS EDIT
+!define __NSD_Password_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${ES_AUTOHSCROLL}|${ES_PASSWORD}
+!define __NSD_Password_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+!define __NSD_Number_CLASS EDIT
+!define __NSD_Number_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${ES_AUTOHSCROLL}|${ES_NUMBER}
+!define __NSD_Number_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+!define __NSD_FileRequest_CLASS EDIT
+!define __NSD_FileRequest_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${ES_AUTOHSCROLL}
+!define __NSD_FileRequest_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+!define __NSD_DirRequest_CLASS EDIT
+!define __NSD_DirRequest_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${ES_AUTOHSCROLL}
+!define __NSD_DirRequest_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+!define __NSD_RichEdit_CLASS_10 "RICHEDIT" ; 1.0 (Riched32.dll) Win95/NT4
+!define __NSD_RichEdit_CLASS_20A "RICHEDIT20A" ; 2.0 (Riched20.dll) Win98/NT4 (NSIS makes sure this is registered even on Windows 95)
+!define __NSD_RichEdit_CLASS_20W "RICHEDIT20W"
+!define __NSD_RichEdit_CLASS_41W "RICHEDIT50W" ; 4.1 (MsftEdit.DLL) WinXP.SP1
+!ifdef NSIS_UNICODE
+!define /ifndef __NSD_RichEdit_CLASS ${__NSD_RichEdit_CLASS_20W}
+!else
+!define /ifndef __NSD_RichEdit_CLASS ${__NSD_RichEdit_CLASS_20A}
+!endif
+!define __NSD_RichEdit_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${ES_AUTOHSCROLL}|${ES_AUTOVSCROLL}|${ES_MULTILINE}|${ES_WANTRETURN}|${ES_SAVESEL}|${WS_HSCROLL}|${WS_VSCROLL}
+!define __NSD_RichEdit_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+!define __NSD_ComboBox_CLASS COMBOBOX
+!define __NSD_ComboBox_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${WS_VSCROLL}|${WS_CLIPCHILDREN}|${CBS_AUTOHSCROLL}|${CBS_HASSTRINGS}|${CBS_DROPDOWN}
+!define __NSD_ComboBox_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+!define __NSD_DropList_CLASS COMBOBOX
+!define __NSD_DropList_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${WS_VSCROLL}|${WS_CLIPCHILDREN}|${CBS_AUTOHSCROLL}|${CBS_HASSTRINGS}|${CBS_DROPDOWNLIST}
+!define __NSD_DropList_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+!define __NSD_ListBox_CLASS LISTBOX
+!define __NSD_ListBox_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${WS_VSCROLL}|${LBS_DISABLENOSCROLL}|${LBS_HASSTRINGS}|${LBS_NOINTEGRALHEIGHT}|${LBS_NOTIFY}
+!define __NSD_ListBox_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+!define __NSD_SortedListBox_CLASS LISTBOX
+!define __NSD_SortedListBox_STYLE ${__NSD_ListBox_STYLE}|${LBS_SORT}
+!define __NSD_SortedListBox_EXSTYLE ${__NSD_ListBox_EXSTYLE}
+
+!define __NSD_ProgressBar_CLASS msctls_progress32
+!define __NSD_ProgressBar_STYLE ${DEFAULT_STYLES}
+!define __NSD_ProgressBar_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+!define __NSD_Animation_CLASS SysAnimate32
+!define __NSD_Animation_STYLE ${DEFAULT_STYLES}|${ACS_TRANSPARENT}|${ACS_AUTOPLAY}
+!define __NSD_Animation_EXSTYLE 0
+
+!define __NSD_HTrackBar_CLASS msctls_trackbar32
+!define __NSD_HTrackBar_STYLE ${DEFAULT_STYLES}|${TBS_HORZ}|${TBS_AUTOTICKS}|${TBS_TOOLTIPS}
+!define __NSD_HTrackBar_EXSTYLE 0
+
+!define __NSD_VTrackBar_CLASS msctls_trackbar32
+!define __NSD_VTrackBar_STYLE ${DEFAULT_STYLES}|${TBS_VERT}|${TBS_AUTOTICKS}|${TBS_TOOLTIPS}
+!define __NSD_VTrackBar_EXSTYLE 0
+
+!define __NSD_UpDown_CLASS msctls_updown32
+!define __NSD_UpDown_STYLE ${DEFAULT_STYLES}|${UDS_SETBUDDYINT}|${UDS_ARROWKEYS}|${UDS_NOTHOUSANDS}|${UDS_ALIGNRIGHT}
+!define __NSD_UpDown_EXSTYLE 0
+
+!define __NSD_AutoUpDown_CLASS msctls_updown32
+!define __NSD_AutoUpDown_STYLE ${__NSD_UpDown_STYLE}|${UDS_AUTOBUDDY}
+!define __NSD_AutoUpDown_EXSTYLE ${__NSD_UpDown_EXSTYLE}
+
+!define __NSD_HotKey_CLASS msctls_hotkey32
+!define __NSD_HotKey_STYLE ${DEFAULT_STYLES}
+!define __NSD_HotKey_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+!define __NSD_Calendar_CLASS SysMonthCal32
+!define __NSD_Calendar_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}
+!define __NSD_Calendar_EXSTYLE 0
+
+!define __NSD_DatePicker_CLASS SysDateTimePick32
+!define __NSD_DatePicker_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}
+!define __NSD_DatePicker_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+!define __NSD_TimePicker_CLASS SysDateTimePick32
+!define __NSD_TimePicker_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}|${DTS_TIMEFORMAT}
+!define __NSD_TimePicker_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+!define __NSD_IPAddress_CLASS SysIPAddress32 ; IE4+/CC4.71+
+!define __NSD_IPAddress_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}
+!define __NSD_IPAddress_EXSTYLE 0
+
+!define __NSD_NetAddress_CLASS msctls_netaddress ; Vista+
+!define __NSD_NetAddress_STYLE ${DEFAULT_STYLES}|${WS_TABSTOP}
+!define __NSD_NetAddress_EXSTYLE ${WS_EX_WINDOWEDGE}|${WS_EX_CLIENTEDGE}
+
+
+!macro __NSD_DefineControl NAME
+ !define NSD_Create${NAME} "nsDialogs::CreateControl ${__NSD_${Name}_CLASS} ${__NSD_${Name}_STYLE} ${__NSD_${Name}_EXSTYLE}"
+!macroend
+!insertmacro __NSD_DefineControl HLine
+!insertmacro __NSD_DefineControl VLine
+!insertmacro __NSD_DefineControl Label
+!insertmacro __NSD_DefineControl Icon
+!insertmacro __NSD_DefineControl Bitmap
+!insertmacro __NSD_DefineControl BrowseButton
+!insertmacro __NSD_DefineControl Link
+!insertmacro __NSD_DefineControl Button
+!insertmacro __NSD_DefineControl GroupBox
+!insertmacro __NSD_DefineControl CheckBox
+!insertmacro __NSD_DefineControl RadioButton
+!insertmacro __NSD_DefineControl FirstRadioButton
+!insertmacro __NSD_DefineControl AdditionalRadioButton
+!insertmacro __NSD_DefineControl Text
+!insertmacro __NSD_DefineControl MLText
+!insertmacro __NSD_DefineControl Password
+!insertmacro __NSD_DefineControl Number
+!insertmacro __NSD_DefineControl FileRequest
+!insertmacro __NSD_DefineControl DirRequest
+!insertmacro __NSD_DefineControl RichEdit
+!insertmacro __NSD_DefineControl ComboBox
+!insertmacro __NSD_DefineControl DropList
+!insertmacro __NSD_DefineControl ListBox
+!insertmacro __NSD_DefineControl SortedListBox
+!insertmacro __NSD_DefineControl ProgressBar
+!insertmacro __NSD_DefineControl Animation
+!insertmacro __NSD_DefineControl HTrackBar
+!insertmacro __NSD_DefineControl VTrackBar
+!insertmacro __NSD_DefineControl UpDown
+!insertmacro __NSD_DefineControl AutoUpDown
+!insertmacro __NSD_DefineControl HotKey
+!insertmacro __NSD_DefineControl Calendar
+!insertmacro __NSD_DefineControl DatePicker
+!insertmacro __NSD_DefineControl TimePicker
+!insertmacro __NSD_DefineControl IPAddress
+!insertmacro __NSD_DefineControl NetAddress
+
+
+!macro __NSD_OnControlEvent EVENT HWND FUNCTION
+ Push $0
+ Push $1
+
+ StrCpy $1 "${HWND}"
+
+ GetFunctionAddress $0 "${FUNCTION}"
+ nsDialogs::On${EVENT} $1 $0
+
+ Pop $1
+ Pop $0
+!macroend
+
+!macro __NSD_DefineControlCallback EVENT
+ !define NSD_On${EVENT} `!insertmacro __NSD_OnControlEvent ${EVENT} `
+!macroend
+
+!macro __NSD_OnDialogEvent EVENT FUNCTION
+ Push $0
+
+ GetFunctionAddress $0 "${FUNCTION}"
+ nsDialogs::On${EVENT} $0
+
+ Pop $0
+!macroend
+
+!macro __NSD_DefineDialogCallback EVENT
+ !define NSD_On${EVENT} `!insertmacro __NSD_OnDialogEvent ${EVENT} `
+!macroend
+!insertmacro __NSD_DefineControlCallback Click
+!insertmacro __NSD_DefineControlCallback Change
+!insertmacro __NSD_DefineControlCallback Notify
+!insertmacro __NSD_DefineDialogCallback Back
+
+!define NSD_Return "!insertmacro NSD_Return "
+!macro NSD_Return val
+StrCpy $_OUTDIR ${val}
+SetSilent silent
+Return
+!macroend
+
+
+!define __NSD_MkCtlCmd "!insertmacro __NSD_MkCtlCmd "
+!macro __NSD_MkCtlCmd msg wp lp hCtl
+SendMessage ${hCtl} ${${msg}} ${wp} ${lp}
+!macroend
+!define __NSD_MkCtlCmd_WP "!insertmacro __NSD_MkCtlCmd_WP "
+!macro __NSD_MkCtlCmd_WP msg lp hCtl wp
+SendMessage ${hCtl} ${${msg}} ${wp} ${lp}
+!macroend
+!define __NSD_MkCtlCmd_LP "!insertmacro __NSD_MkCtlCmd_LP "
+!macro __NSD_MkCtlCmd_LP msg wp hCtl lp
+SendMessage ${hCtl} ${${msg}} ${wp} ${lp}
+!macroend
+!define __NSD_MkCtlCmd_WPLP "!insertmacro __NSD_MkCtlCmd_WPLP "
+!macro __NSD_MkCtlCmd_WPLP msg hCtl wp lp
+SendMessage ${hCtl} ${${msg}} ${wp} ${lp}
+!macroend
+!define __NSD_MkCtlCmd_RV "!insertmacro __NSD_MkCtlCmd_RV "
+!macro __NSD_MkCtlCmd_RV msg wp lp hCtl VAR
+SendMessage ${hCtl} ${${msg}} ${wp} ${lp} ${VAR}
+!macroend
+
+
+!define NSD_InitCommonControlsEx "!insertmacro __NSD_InitCommonControlsEx "
+!macro __NSD_InitCommonControlsEx ICC
+!pragma warning push
+!pragma warning disable 7070 ; Invalid number
+!if ${ICC} <> 0
+!define /ReDef /IntFmt NSD_InitCommonControlsEx_TEMP "0x%X" ${ICC}
+System::Call 'COMCTL32::InitCommonControlsEx(*l${NSD_InitCommonControlsEx_TEMP}00000008)'
+!undef NSD_InitCommonControlsEx_TEMP
+!else
+System::Int64Op ${ICC} << 32
+System::Int64Op 8 |
+System::Call 'COMCTL32::InitCommonControlsEx(*ls)' ; INITCOMMONCONTROLSEX as UINT64
+!endif
+!pragma warning pop
+!macroend
+!define NSD_InitCommonControl_IPAddress `${NSD_InitCommonControlsEx} ${ICC_INTERNET_CLASSES}`
+!define NSD_InitCommonControl_NetAddress `System::Call SHELL32::InitNetworkAddressControl()i`
+!define NSD_InitCommonControl_SysLink `${NSD_InitCommonControlsEx} ${ICC_LINK_CLASS}`
+
+
+!define NSD_CreateTimer `!insertmacro _NSD_CreateTimer `
+!macro _NSD_CreateTimer FUNCTION INTERVAL
+ Push $0
+
+ GetFunctionAddress $0 "${FUNCTION}"
+ nsDialogs::CreateTimer $0 "${INTERVAL}"
+
+ Pop $0
+!macroend
+
+
+!define NSD_KillTimer `!insertmacro _NSD_KillTimer `
+!macro _NSD_KillTimer FUNCTION
+ Push $0
+
+ GetFunctionAddress $0 "${FUNCTION}"
+ nsDialogs::KillTimer $0
+
+ Pop $0
+!macroend
+
+
+!define NSD_AddStyle "!insertmacro _NSD_GWLAddFlags ${GWL_STYLE} "
+!define NSD_AddExStyle "!insertmacro _NSD_GWLAddFlags ${GWL_EXSTYLE} "
+!macro _NSD_GWLAddFlags GWL HWND DATA
+ System::Call "user32::GetWindowLong(p${HWND},i${GWL})p.s"
+ System::Int64Op "${DATA}" |
+ System::Call "user32::SetWindowLong(p${HWND},p${GWL},ps)"
+!macroend
+
+!define NSD_RemoveStyle "!insertmacro _NSD_GWLRemoveFlags ${GWL_STYLE} "
+!define NSD_RemoveExStyle "!insertmacro _NSD_GWLRemoveFlags ${GWL_EXSTYLE} "
+!macro _NSD_GWLRemoveFlags GWL HWND DATA
+System::Call "user32::GetWindowLong(p${HWND},i${GWL})p.s"
+System::Int64Op "${DATA}" ~ & ; Perform ~ and prepare the stack for &
+System::Int64Op ; Perform &
+System::Call "user32::SetWindowLong(p${HWND},i${GWL},ps)"
+!macroend
+
+!define NSD_GetStyle "!insertmacro _NSD_GWLGetFlags ${GWL_STYLE} "
+!define NSD_GetExStyle "!insertmacro _NSD_GWLGetFlags ${GWL_EXSTYLE} "
+!macro _NSD_GWLGetFlags GWL HWND RET
+System::Call "user32::GetWindowLong(p${HWND},i${GWL})p.s"
+Pop ${RET}
+!macroend
+
+!macro __NSD_GetStyleBit GWL BIT HWND RET
+!insertmacro _NSD_GWLGetFlags ${GWL} ${HWND} ${RET}
+IntOp ${RET} ${RET} & ${BIT}
+!macroend
+
+
+!define NSD_SetFocus `!insertmacro __NSD_SetFocus `
+!macro __NSD_SetFocus HWND
+ System::Call "user32::SetFocus(p${HWND})"
+!macroend
+
+
+!define NSD_GetText "!insertmacro __NSD_GetText "
+!macro __NSD_GetText CONTROL VAR
+ System::Call user32::GetWindowText(p${CONTROL},t.s,i${NSIS_MAX_STRLEN})
+ Pop ${VAR}
+!macroend
+
+
+!define NSD_SetText "!insertmacro __NSD_SetText "
+!macro __NSD_SetText CONTROL TEXT
+ SendMessage ${CONTROL} ${WM_SETTEXT} 0 `STR:${TEXT}`
+!macroend
+
+
+### Edit ###
+
+!define NSD_Edit_GetTextLimit `${__NSD_MkCtlCmd_RV} EM_GETLIMITTEXT 0 0 `
+!define NSD_Edit_SetTextLimit `${__NSD_MkCtlCmd_WP} EM_SETLIMITTEXT 0 `
+!define NSD_Edit_SetPasswordChar `${__NSD_MkCtlCmd_WP} EM_SETPASSWORDCHAR 0 `
+!define NSD_Edit_GetReadOnly `!insertmacro __NSD_GetStyleBit ${GWL_STYLE} ${ES_READONLY} ` ; Non-zero if read-only
+!define NSD_Edit_SetReadOnly `${__NSD_MkCtlCmd_WP} EM_SETREADONLY 0 ` ; Toggles the ES_READONLY style
+!define NSD_Edit_GetModify `${__NSD_MkCtlCmd_RV} EM_GETMODIFY 0 0 `
+!define NSD_Edit_SetModify `${__NSD_MkCtlCmd_WP} EM_SETMODIFY 0 `
+!define NSD_Edit_EmptyUndoBuffer `${__NSD_MkCtlCmd} EM_EMPTYUNDOBUFFER 0 0 `
+!define NSD_Edit_CanUndo `${__NSD_MkCtlCmd_RV} EM_CANUNDO 0 0 `
+!define NSD_Edit_ScrollCaret `${__NSD_MkCtlCmd} EM_SCROLLCARET 0 0 `
+!define NSD_Edit_LineScroll `${__NSD_MkCtlCmd_WPLP} EM_LINESCROLL `
+!define NSD_Edit_SetSel `${__NSD_MkCtlCmd_WPLP} EM_SETSEL ` ; WP:Start LP:End
+
+!define NSD_Edit_SetCueBannerText "!insertmacro __NSD_Edit_SetCueBannerText " ; CC6+
+!macro __NSD_Edit_SetCueBannerText CONTROL SHOWWHENFOCUSED TEXT
+!if ${NSIS_CHAR_SIZE} > 1
+ SendMessage ${CONTROL} ${EM_SETCUEBANNER} ${SHOWWHENFOCUSED} `STR:${TEXT}`
+!else
+ System::Call 'USER32::SendMessage(p${CONTROL},i${EM_SETCUEBANNER},p${SHOWWHENFOCUSED},ws)' `${TEXT}` ; Must be PWSTR
+!endif
+!macroend
+
+!define NSD_Edit_GetLineCount `${__NSD_MkCtlCmd_RV} EM_GETLINECOUNT 0 0 `
+!define NSD_Edit_GetLine "!insertmacro __NSD_Edit_GetLine "
+!macro __NSD_Edit_GetLine CONTROL LINEINDEX OUTPUT
+ System::Call '*(&i2 ${NSIS_MAX_STRLEN},&t${NSIS_MAX_STRLEN})p.s'
+ System::Call 'USER32::SendMessage(p${CONTROL},i${EM_GETLINE},p${LINEINDEX},pss)'
+ System::Call 'KERNEL32::lstrcpyn(t.s,pss,i${NSIS_MAX_STRLEN})'
+ Pop ${OUTPUT}
+ System::Free
+!macroend
+
+!define NSD_SetTextLimit `${NSD_Edit_SetTextLimit} ` ; Legacy alias
+
+
+### RichEdit ###
+
+!define NSD_RichEd_SetTextLimit `${__NSD_MkCtlCmd_LP} EM_EXLIMITTEXT 0 `
+!define NSD_RichEd_GetEventMask `${__NSD_MkCtlCmd_RV} EM_GETEVENTMASK 0 0 `
+!define NSD_RichEd_SetEventMask `${__NSD_MkCtlCmd_LP} EM_SETEVENTMASK 0 ` ; LP:ENM_*
+!define NSD_RichEd_SetSystemBackgroundColor `${__NSD_MkCtlCmd} EM_SETBKGNDCOLOR 1 0 ` ; COLOR_WINDOW
+!define NSD_RichEd_SetCustomBackgroundColor `${__NSD_MkCtlCmd_LP} EM_SETBKGNDCOLOR 0 ` ; LP:COLORREF
+!define NSD_RichEd_SetHideSelection `${__NSD_MkCtlCmd_WP} EM_HIDESELECTION 0 ` ; WP(BOOL):HideSelWithoutFocus (Toggles ES_NOHIDESEL & TXTBIT_HIDESELECTION)
+
+
+### CheckBox ###
+
+!define NSD_GetState `!insertmacro __NSD_GetState `
+!macro __NSD_GetState CONTROL VAR
+ SendMessage ${CONTROL} ${BM_GETCHECK} 0 0 ${VAR}
+!macroend
+
+
+!define NSD_SetState `!insertmacro __NSD_SetState `
+!macro __NSD_SetState CONTROL STATE
+ SendMessage ${CONTROL} ${BM_SETCHECK} ${STATE} 0
+!macroend
+
+!define NSD_Check `!insertmacro __NSD_Check `
+!macro __NSD_Check CONTROL
+ ${NSD_SetState} ${CONTROL} ${BST_CHECKED}
+!macroend
+
+
+!define NSD_Uncheck `!insertmacro __NSD_Uncheck `
+!macro __NSD_Uncheck CONTROL
+ ${NSD_SetState} ${CONTROL} ${BST_UNCHECKED}
+!macroend
+
+!define NSD_GetChecked `!insertmacro __NSD_GetState `
+!define NSD_SetChecked `!insertmacro __NSD_SetState `
+
+
+### ComboBox ###
+
+!define NSD_CB_AddString "!insertmacro _NSD_CB_AddString "
+!macro _NSD_CB_AddString CONTROL STRING
+ SendMessage ${CONTROL} ${CB_ADDSTRING} 0 `STR:${STRING}`
+!macroend
+
+
+!define NSD_CB_InsertString "!insertmacro _NSD_CB_InsertString "
+!macro _NSD_CB_InsertString CONTROL INDEX STRING
+SendMessage ${CONTROL} ${CB_INSERTSTRING} ${INDEX} `STR:${STRING}`
+!macroend
+
+!define NSD_CB_PrependString "!insertmacro _NSD_CB_PrependString "
+!macro _NSD_CB_PrependString CONTROL STRING
+SendMessage ${CONTROL} ${CB_INSERTSTRING} 0 `STR:${STRING}`
+!macroend
+
+!define NSD_CB_AppendString "!insertmacro _NSD_CB_AppendString "
+!macro _NSD_CB_AppendString CONTROL STRING
+SendMessage ${CONTROL} ${CB_INSERTSTRING} -1 `STR:${STRING}`
+!macroend
+
+
+!define NSD_CB_SelectString "!insertmacro _NSD_CB_SelectString "
+!macro _NSD_CB_SelectString CONTROL STRING
+ SendMessage ${CONTROL} ${CB_SELECTSTRING} -1 `STR:${STRING}`
+!macroend
+
+
+!define NSD_CB_GetSelectionIndex `!insertmacro __NSD_CB_GetSelectionIndex `
+!macro __NSD_CB_GetSelectionIndex CONTROL VAR
+ SendMessage ${CONTROL} ${CB_GETCURSEL} 0 0 ${VAR}
+!macroend
+
+
+!define NSD_CB_SetSelectionIndex `!insertmacro __NSD_CB_SetSelectionIndex `
+!macro __NSD_CB_SetSelectionIndex CONTROL INDEX
+ SendMessage ${CONTROL} ${CB_SETCURSEL} ${INDEX} 0
+!macroend
+
+
+!define NSD_CB_GetItemData `!insertmacro __NSD_CB_GetItemData `
+!macro __NSD_CB_GetItemData CONTROL INDEX VAR
+SendMessage ${CONTROL} ${CB_GETITEMDATA} ${INDEX} 0 ${VAR}
+!macroend
+!define NSD_CB_SetItemData `${__NSD_MkCtlCmd_WPLP} CB_SETITEMDATA ` ; Index Data
+
+
+!define NSD_CB_DelItem `${__NSD_MkCtlCmd_WP} CB_DELETESTRING 0 `
+!define NSD_CB_LimitText `${__NSD_MkCtlCmd_WP} CB_LIMITTEXT 0 `
+!define /IfNDef NSD_CB_Clear `${__NSD_MkCtlCmd} CB_RESETCONTENT 0 0 `
+!define /IfNDef NSD_CB_GetCount `${__NSD_MkCtlCmd_RV} CB_GETCOUNT 0 0 `
+!ifndef NSD_CB_DelString
+!define NSD_CB_DelString `!insertmacro __NSD_CB_DelString `
+!macro __NSD_CB_DelString CONTROL STRING
+ System::Call 'USER32::SendMessage(p${CONTROL},i${CB_FINDSTRINGEXACT},p-1,ts)p.s' `${STRING}`
+ System::Call 'USER32::SendMessage(p${CONTROL},i${CB_DELETESTRING},ps,p0)'
+!macroend
+!endif
+;define /IfNDef NSD_CB_GetSelection
+
+
+### ListBox ###
+
+!define NSD_LB_AddString "!insertmacro _NSD_LB_AddString "
+!macro _NSD_LB_AddString CONTROL STRING
+ SendMessage ${CONTROL} ${LB_ADDSTRING} 0 `STR:${STRING}`
+!macroend
+
+
+!define NSD_LB_InsertString "!insertmacro _NSD_LB_InsertString "
+!macro _NSD_LB_InsertString CONTROL INDEX STRING
+SendMessage ${CONTROL} ${LB_INSERTSTRING} ${INDEX} `STR:${STRING}`
+!macroend
+
+!define NSD_LB_PrependString "!insertmacro _NSD_LB_PrependString "
+!macro _NSD_LB_PrependString CONTROL STRING
+SendMessage ${CONTROL} ${LB_INSERTSTRING} 0 `STR:${STRING}`
+!macroend
+
+!define NSD_LB_AppendString "!insertmacro _NSD_LB_AppendString "
+!macro _NSD_LB_AppendString CONTROL STRING
+SendMessage ${CONTROL} ${LB_INSERTSTRING} -1 `STR:${STRING}`
+!macroend
+
+
+!define NSD_LB_DelString `!insertmacro __NSD_LB_DelString `
+!macro __NSD_LB_DelString CONTROL STRING
+ System::Call 'USER32::SendMessage(p${CONTROL},i${LB_FINDSTRINGEXACT},p-1,ts)p.s' `${STRING}`
+ System::Call 'USER32::SendMessage(p${CONTROL},i${LB_DELETESTRING},ps,p0)'
+!macroend
+
+
+!define NSD_LB_DelItem "!insertmacro __NSD_LB_DelItem "
+!macro __NSD_LB_DelItem CONTROL INDEX
+ SendMessage ${CONTROL} ${LB_DELETESTRING} ${INDEX} 0
+!macroend
+
+
+!define NSD_LB_Clear `${__NSD_MkCtlCmd} LB_RESETCONTENT 0 0 `
+
+
+!define NSD_LB_GetCount `!insertmacro __NSD_LB_GetCount `
+!macro __NSD_LB_GetCount CONTROL VAR
+ SendMessage ${CONTROL} ${LB_GETCOUNT} 0 0 ${VAR}
+!macroend
+
+
+!define NSD_LB_SelectString "!insertmacro _NSD_LB_SelectString "
+!macro _NSD_LB_SelectString CONTROL STRING
+ SendMessage ${CONTROL} ${LB_SELECTSTRING} -1 `STR:${STRING}`
+!macroend
+
+
+!define NSD_LB_GetSelection `!insertmacro __NSD_LB_GetSelection `
+!macro __NSD_LB_GetSelection CONTROL VAR
+ SendMessage ${CONTROL} ${LB_GETCURSEL} 0 0 ${VAR}
+ System::Call 'user32::SendMessage(p ${CONTROL}, i ${LB_GETTEXT}, p ${VAR}, t .s)'
+ Pop ${VAR}
+!macroend
+
+
+!define NSD_LB_GetSelectionIndex `!insertmacro __NSD_LB_GetSelectionIndex `
+!macro __NSD_LB_GetSelectionIndex CONTROL VAR
+ SendMessage ${CONTROL} ${LB_GETCURSEL} 0 0 ${VAR}
+!macroend
+
+
+!define NSD_LB_SetSelectionIndex `!insertmacro __NSD_LB_SetSelectionIndex `
+!macro __NSD_LB_SetSelectionIndex CONTROL INDEX
+ SendMessage ${CONTROL} ${LB_SETCURSEL} ${INDEX} 0
+!macroend
+
+
+!define NSD_LB_GetSelectionCount `!insertmacro __NSD_LB_GetSelectionCount `
+!macro __NSD_LB_GetSelectionCount CONTROL VAR
+ SendMessage ${CONTROL} ${LB_GETSELCOUNT} 0 0 ${VAR}
+!macroend
+
+
+!define NSD_LB_GetItemText `!insertmacro __NSD_LB_GetItemText `
+!macro __NSD_LB_GetItemText CONTROL INDEX VAR
+ System::Call 'user32::SendMessage(p${CONTROL}, i${LB_GETTEXT}, p${INDEX}, t.s)'
+ Pop ${VAR}
+!macroend
+
+
+!define NSD_LB_GetItemData `!insertmacro __NSD_LB_GetItemData `
+!macro __NSD_LB_GetItemData CONTROL INDEX VAR
+SendMessage ${CONTROL} ${LB_GETITEMDATA} ${INDEX} 0 ${VAR}
+!macroend
+!define NSD_LB_SetItemData `${__NSD_MkCtlCmd_WPLP} LB_SETITEMDATA ` ; Index Data
+
+
+!define NSD_LB_FindStringPrefix `!insertmacro __NSD_LB_FindStringPrefix `
+!macro __NSD_LB_FindStringPrefix CONTROL STRING VAR
+ SendMessage ${CONTROL} ${LB_FINDSTRING} -1 `STR:${STRING}` ${VAR}
+!macroend
+
+
+!define NSD_LB_FindStringExact `!insertmacro __NSD_LB_FindStringExact `
+!macro __NSD_LB_FindStringExact CONTROL STRING VAR
+ SendMessage ${CONTROL} ${LB_FINDSTRINGEXACT} -1 `STR:${STRING}` ${VAR}
+!macroend
+
+
+### ProgressBar ###
+
+!define NSD_ProgressBar_SetPos `${__NSD_MkCtlCmd_WP} PBM_SETPOS 0 `
+!define NSD_ProgressBar_SetStep `${__NSD_MkCtlCmd_WP} PBM_SETSTEP 0 `
+!define NSD_ProgressBar_StepIt `${__NSD_MkCtlCmd} PBM_STEPIT 0 0 `
+!define NSD_ProgressBar_AdvanceBy `${__NSD_MkCtlCmd_WP} PBM_DELTAPOS 0 `
+!define NSD_ProgressBar_SetPackedRange `${__NSD_MkCtlCmd_LP} PBM_SETRANGE 0 ` ; LP(DWORD):MAKELONG(min,max)
+!define NSD_ProgressBar_SetRange32 `${__NSD_MkCtlCmd_WPLP} PBM_SETRANGE32 ` ; [IE3+] WP:min LP:max
+!define NSD_ProgressBar_GetPos `${__NSD_MkCtlCmd_RV} PBM_GETPOS 0 0 ` ; [IE3+]
+
+
+### Animation ###
+
+!define NSD_Anim_Close `${__NSD_MkCtlCmd} ACM_OPEN 0 0 `
+!define NSD_Anim_Play `${__NSD_MkCtlCmd} ACM_PLAY -1 0xFFFF0000 `
+!define NSD_Anim_PlayLoops `${__NSD_MkCtlCmd_WP} ACM_PLAY 0xFFFF0000 ` ; WP(UINT16):LoopCount
+!define NSD_Anim_Stop `${__NSD_MkCtlCmd} ACM_STOP 0 0 `
+!define NSD_Anim_IsPlaying `${__NSD_MkCtlCmd_RV} ACM_ISPLAYING 0 0 `
+
+!define NSD_Anim_OpenFile `!insertmacro __NSD_Anim_OpenFile `
+!macro __NSD_Anim_OpenFile CONTROL PATH
+ SendMessage ${CONTROL} ${ACM_OPEN} 0 "STR:${PATH}"
+!macroend
+
+!define NSD_Anim_OpenResource `!insertmacro __NSD_Anim_OpenResource `
+!macro __NSD_Anim_OpenResource CONTROL HINSTANCE_CC471 RESID
+ SendMessage ${CONTROL} ${ACM_OPEN} "${HINSTANCE_CC471}" "${RESID}"
+!macroend
+
+
+### TrackBar ###
+
+!define NSD_TrackBar_GetPos `${__NSD_MkCtlCmd_RV} TBM_GETPOS 0 0 `
+!define NSD_TrackBar_SetPos `${__NSD_MkCtlCmd_LP} TBM_SETPOS 1 `
+!define NSD_TrackBar_SetRangeMin `${__NSD_MkCtlCmd_LP} TBM_SETRANGEMIN 1 `
+!define NSD_TrackBar_SetRangeMax `${__NSD_MkCtlCmd_LP} TBM_SETRANGEMAX 1 `
+!define NSD_TrackBar_GetLineSize `${__NSD_MkCtlCmd_RV} TBM_GETLINESIZE 0 0 `
+!define NSD_TrackBar_SetLineSize `${__NSD_MkCtlCmd_LP} TBM_SETLINESIZE 0 `
+!define NSD_TrackBar_GetPageSize `${__NSD_MkCtlCmd_RV} TBM_GETPAGESIZE 0 0 `
+!define NSD_TrackBar_SetPageSize `${__NSD_MkCtlCmd_LP} TBM_SETPAGESIZE 0 `
+!define NSD_TrackBar_ClearTics `${__NSD_MkCtlCmd} TBM_CLEARTICS 0 0 `
+!define NSD_TrackBar_GetNumTics `${__NSD_MkCtlCmd_RV} TBM_GETNUMTICS 0 0 `
+!define NSD_TrackBar_SetTic `${__NSD_MkCtlCmd_LP} TBM_SETTIC 0 `
+!define NSD_TrackBar_SetTicFreq `${__NSD_MkCtlCmd_WP} TBM_SETTICFREQ 0 `
+!define NSD_TrackBar_GetThumbLength `${__NSD_MkCtlCmd_RV} TBM_GETTHUMBLENGTH 0 0 `
+!define NSD_TrackBar_SetBuddy `${__NSD_MkCtlCmd_WPLP} TBM_SETBUDDY ` ; WP(BOOL):Left/Right LP:HWND
+
+
+### UpDown ###
+
+!define NSD_UD_SetBuddy `${__NSD_MkCtlCmd_WP} UDM_SETBUDDY 0 `
+!define NSD_UD_GetPos `${__NSD_MkCtlCmd_RV} UDM_GETPOS 0 0 `
+!define NSD_UD_SetPos `${__NSD_MkCtlCmd_LP} UDM_SETPOS 0 `
+!define NSD_UD_GetPackedRange `${__NSD_MkCtlCmd_RV} UDM_GETRANGE 0 0 `
+!define NSD_UD_SetPackedRange `${__NSD_MkCtlCmd_LP} UDM_SETRANGE 0 ` ; LP(DWORD):MAKELONG(min,max)
+!define NSD_UD_GetPos32 `${__NSD_MkCtlCmd_RV} UDM_GETPOS32 0 0 `
+!define NSD_UD_SetPos32 `${__NSD_MkCtlCmd_LP} UDM_SETPOS32 0 `
+!define NSD_UD_SetRange32 `${__NSD_MkCtlCmd_WPLP} UDM_SETRANGE32 ` ; WP(INT32):min LP(INT32):max
+
+!define NSD_UD_GetRange32 `!insertmacro __NSD_UD_GetRange32 `
+!macro __NSD_UD_GetRange32 CONTROL OUTLO OUTHI
+ System::Call 'USER32::SendMessage(p${CONTROL},i${UDM_GETRANGE32},*i.s,*i.s)'
+ Pop ${OUTLO}
+ Pop ${OUTHI}
+!macroend
+
+!define NSD_UD_SetStaticRange `!insertmacro __NSD_UD_SetStaticRange `
+!macro __NSD_UD_SetStaticRange CONTROL MI MA
+ !define /redef /math MI ${MI} << 16
+ !define /redef /math MA ${MA} & 0xffff
+ !define /redef /math MA ${MI} | ${MA}
+ SendMessage ${CONTROL} ${UDM_SETRANGE} 0 ${MA}
+!macroend
+
+
+### HotKey ###
+
+!define NSD_HK_GetHotKey `${__NSD_MkCtlCmd_RV} HKM_GETHOTKEY 0 0 ` ; RV(WORD):MAKEWORD(VK,HOTKEYF)
+!define NSD_HK_SetHotKey `${__NSD_MkCtlCmd_WP} HKM_SETHOTKEY 0 `
+!define NSD_HK_SetRules `${__NSD_MkCtlCmd_WPLP} HKM_SETRULES `
+
+
+### IP Address ###
+
+!define NSD_IPAddress_Clear `${__NSD_MkCtlCmd} IPM_CLEARADDRESS 0 0 `
+!define NSD_IPAddress_SetPackedIPv4 `${__NSD_MkCtlCmd_LP} IPM_SETADDRESS 0 `
+!define NSD_IPAddress_IsBlank `${__NSD_MkCtlCmd_RV} IPM_ISBLANK 0 0 `
+
+!define NSD_IPAddress_GetPackedIPv4 `!insertmacro __NSD_IPAddress_GetPackedIPv4 `
+!macro __NSD_IPAddress_GetPackedIPv4 CONTROL VAR
+System::Call 'USER32::SendMessage(p${CONTROL},i${IPM_GETADDRESS},p0,*i0s)'
+Pop ${VAR}
+!macroend
+
+
+### Date ###
+!define NSD_Date_GetDateFields `!insertmacro __NSD_Date_GetDateFields `
+!macro __NSD_Date_GetDateFields CONTROL
+Push $0
+System::Call 'USER32::SendMessage(p${CONTROL},i${DTM_GETSYSTEMTIME},p0,@r0)'
+System::Call '*$0(&i2.s,&i2.s,&i2,&i2.s)'
+Exch 3
+Pop $0
+!macroend
+
+!define NSD_Time_GetTimeFields `!insertmacro __NSD_Time_GetTimeFields `
+!macro __NSD_Time_GetTimeFields CONTROL
+Push $0
+System::Call 'USER32::SendMessage(p${CONTROL},i${DTM_GETSYSTEMTIME},p0,@r0)'
+System::Call '*$0(&i2,&i2,&i2,&i2,&i2.s,&i2.s,&i2.s)'
+Exch 3
+Pop $0
+Exch
+!macroend
+
+
+### Static ###
+
+!macro __NSD_LoadAndSetImage _LIHINSTMODE _IMGTYPE _LIHINSTSRC _LIFLAGS CONTROL IMAGE HANDLE
+ !if "${_LIHINSTMODE}" == "exeresource"
+ LoadAndSetImage /EXERESOURCE /STRINGID "${CONTROL}" ${_IMGTYPE} ${_LIFLAGS} "${IMAGE}" ${HANDLE}
+ !else #if "${_LIHINSTMODE}" == "file"
+ LoadAndSetImage /STRINGID "${CONTROL}" ${_IMGTYPE} ${_LIFLAGS} "${IMAGE}" ${HANDLE}
+ !endif
+!macroend
+
+!macro __NSD_SetIconFromExeResource CONTROL IMAGE HANDLE
+ LoadAndSetImage /EXERESOURCE /STRINGID "${CONTROL}" ${IMAGE_ICON} ${LR_DEFAULTSIZE} "${IMAGE}" ${HANDLE}
+!macroend
+
+!macro __NSD_SetIconFromInstaller CONTROL HANDLE
+ LoadAndSetImage /EXERESOURCE "${CONTROL}" ${IMAGE_ICON} ${LR_DEFAULTSIZE} 103 ${HANDLE}
+!macroend
+
+!define NSD_SetImage `!insertmacro __NSD_LoadAndSetImage file ${IMAGE_BITMAP} 0 "${LR_LOADFROMFILE}" `
+!define NSD_SetBitmap `${NSD_SetImage} `
+
+!define NSD_SetIcon `!insertmacro __NSD_LoadAndSetImage file ${IMAGE_ICON} 0 "${LR_LOADFROMFILE}|${LR_DEFAULTSIZE}" `
+!define NSD_SetIconFromExeResource `!insertmacro __NSD_SetIconFromExeResource `
+!define NSD_SetIconFromInstaller `!insertmacro __NSD_SetIconFromInstaller `
+
+
+!define NSD_SetStretchedImage `!insertmacro __NSD_SetStretchedImage `
+!define NSD_SetStretchedBitmap `!insertmacro __NSD_SetStretchedImage `
+!macro __NSD_SetStretchedImage CONTROL IMAGE HANDLE
+ LoadAndSetImage /STRINGID /RESIZETOFIT "${CONTROL}" ${IMAGE_BITMAP} ${LR_LOADFROMFILE} "${IMAGE}" ${HANDLE}
+!macroend
+
+
+!define NSD_FreeImage `!insertmacro __NSD_FreeImage `
+!define NSD_FreeBitmap `${NSD_FreeImage} `
+!macro __NSD_FreeImage IMAGE
+ ${If} ${IMAGE} P<> 0
+ System::Call gdi32::DeleteObject(ps) ${IMAGE}
+ ${EndIf}
+!macroend
+
+
+!define NSD_FreeIcon `!insertmacro __NSD_FreeIcon `
+!macro __NSD_FreeIcon IMAGE
+ System::Call user32::DestroyIcon(ps) ${IMAGE}
+!macroend
+
+
+!define NSD_ClearImage `!insertmacro __NSD_ClearImage ${IMAGE_BITMAP} `
+!define NSD_ClearBitmap `${NSD_ClearImage} `
+!define NSD_ClearIcon `!insertmacro __NSD_ClearImage ${IMAGE_ICON} `
+!macro __NSD_ClearImage _IMGTYPE CONTROL
+ SendMessage ${CONTROL} ${STM_SETIMAGE} ${_IMGTYPE} 0
+!macroend
+
+
+### INI ###
+
+!define /IfNDef NSD_Debug `System::Call kernel32::OutputDebugString(ts)`
+
+!macro __NSD_ControlCase TYPE
+ ${Case} ${TYPE}
+ ${NSD_Create${TYPE}} $R3u $R4u $R5u $R6u $R7
+ Pop $R9
+ ${Break}
+!macroend
+
+!macro __NSD_ControlCaseEx TYPE
+ ${Case} ${TYPE}
+ Call ${TYPE}
+ ${Break}
+!macroend
+
+!macro NSD_FUNCTION_INIFILE
+ !insertmacro NSD_INIFILE ""
+!macroend
+
+!macro NSD_UNFUNCTION_INIFILE
+ !insertmacro NSD_INIFILE un.
+!macroend
+
+!macro NSD_INIFILE UNINSTALLER_FUNCPREFIX
+
+ ;Functions to create dialogs based on old InstallOptions INI files
+
+ Function ${UNINSTALLER_FUNCPREFIX}CreateDialogFromINI
+
+ # $0 = ini
+
+ ReadINIStr $R0 $0 Settings RECT
+ ${If} $R0 == ""
+ StrCpy $R0 1018
+ ${EndIf}
+
+ nsDialogs::Create $R0
+ Pop $R9
+
+ ReadINIStr $R0 $0 Settings RTL
+ nsDialogs::SetRTL $R0
+
+ ReadINIStr $R0 $0 Settings NumFields
+
+ ${NSD_Debug} "NumFields = $R0"
+
+ ${For} $R1 1 $R0
+ ${NSD_Debug} "Creating field $R1"
+ ReadINIStr $R2 $0 "Field $R1" Type
+ ${NSD_Debug} " Type = $R2"
+ ReadINIStr $R3 $0 "Field $R1" Left
+ ${NSD_Debug} " Left = $R3"
+ ReadINIStr $R4 $0 "Field $R1" Top
+ ${NSD_Debug} " Top = $R4"
+ ReadINIStr $R5 $0 "Field $R1" Right
+ ${NSD_Debug} " Right = $R5"
+ ReadINIStr $R6 $0 "Field $R1" Bottom
+ ${NSD_Debug} " Bottom = $R6"
+ IntOp $R5 $R5 - $R3
+ ${NSD_Debug} " Width = $R5"
+ IntOp $R6 $R6 - $R4
+ ${NSD_Debug} " Height = $R6"
+ ReadINIStr $R7 $0 "Field $R1" Text
+ ${NSD_Debug} " Text = $R7"
+ ${Switch} $R2
+ !insertmacro __NSD_ControlCase HLine
+ !insertmacro __NSD_ControlCase VLine
+ !insertmacro __NSD_ControlCase Label
+ !insertmacro __NSD_ControlCase Icon
+ !insertmacro __NSD_ControlCase Bitmap
+ !insertmacro __NSD_ControlCaseEx Link
+ !insertmacro __NSD_ControlCase Button
+ !insertmacro __NSD_ControlCase GroupBox
+ !insertmacro __NSD_ControlCase CheckBox
+ !insertmacro __NSD_ControlCase RadioButton
+ !insertmacro __NSD_ControlCase Text
+ !insertmacro __NSD_ControlCase Password
+ !insertmacro __NSD_ControlCaseEx FileRequest
+ !insertmacro __NSD_ControlCaseEx DirRequest
+ !insertmacro __NSD_ControlCase ComboBox
+ !insertmacro __NSD_ControlCase DropList
+ !insertmacro __NSD_ControlCase ListBox
+ ${EndSwitch}
+
+ WriteINIStr $0 "Field $R1" HWND $R9
+ ${Next}
+
+ nsDialogs::Show
+
+ FunctionEnd
+
+ Function ${UNINSTALLER_FUNCPREFIX}UpdateINIState
+
+ ${NSD_Debug} "Updating INI state"
+
+ ReadINIStr $R0 $0 Settings NumFields
+
+ ${NSD_Debug} "NumField = $R0"
+
+ ${For} $R1 1 $R0
+ ReadINIStr $R2 $0 "Field $R1" HWND
+ ReadINIStr $R3 $0 "Field $R1" "Type"
+ ${Switch} $R3
+ ${Case} "CheckBox"
+ ${Case} "RadioButton"
+ ${NSD_Debug} " HWND = $R2"
+ ${NSD_GetState} $R2 $R2
+ ${NSD_Debug} " Window selection = $R2"
+ ${Break}
+ ${CaseElse}
+ ${NSD_Debug} " HWND = $R2"
+ ${NSD_GetText} $R2 $R2
+ ${NSD_Debug} " Window text = $R2"
+ ${Break}
+ ${EndSwitch}
+ WriteINIStr $0 "Field $R1" STATE $R2
+ ${Next}
+
+ FunctionEnd
+
+ Function ${UNINSTALLER_FUNCPREFIX}FileRequest
+
+ IntOp $R5 $R5 - 15
+ IntOp $R8 $R3 + $R5
+
+ ${NSD_CreateBrowseButton} $R8u $R4u 15u $R6u ...
+ Pop $R8
+
+ nsDialogs::SetUserData $R8 $R1 # remember field id
+
+ WriteINIStr $0 "Field $R1" HWND2 $R8
+
+ ${NSD_OnClick} $R8 ${UNINSTALLER_FUNCPREFIX}OnFileBrowseButton
+
+ ReadINIStr $R9 $0 "Field $R1" State
+
+ ${NSD_CreateFileRequest} $R3u $R4u $R5u $R6u $R9
+ Pop $R9
+
+ FunctionEnd
+
+ Function ${UNINSTALLER_FUNCPREFIX}DirRequest
+
+ IntOp $R5 $R5 - 15
+ IntOp $R8 $R3 + $R5
+
+ ${NSD_CreateBrowseButton} $R8u $R4u 15u $R6u ...
+ Pop $R8
+
+ nsDialogs::SetUserData $R8 $R1 # remember field id
+
+ WriteINIStr $0 "Field $R1" HWND2 $R8
+
+ ${NSD_OnClick} $R8 ${UNINSTALLER_FUNCPREFIX}OnDirBrowseButton
+
+ ReadINIStr $R9 $0 "Field $R1" State
+
+ ${NSD_CreateFileRequest} $R3u $R4u $R5u $R6u $R9
+ Pop $R9
+
+ FunctionEnd
+
+ Function ${UNINSTALLER_FUNCPREFIX}OnFileBrowseButton
+
+ Pop $R0
+
+ nsDialogs::GetUserData $R0
+ Pop $R1
+
+ ReadINIStr $R2 $0 "Field $R1" HWND
+ ReadINIStr $R4 $0 "Field $R1" Filter
+
+ ${NSD_GetText} $R2 $R3
+
+ nsDialogs::SelectFileDialog save $R3 $R4
+ Pop $R3
+
+ ${If} $R3 != ""
+ SendMessage $R2 ${WM_SETTEXT} 0 STR:$R3
+ ${EndIf}
+
+ FunctionEnd
+
+ Function ${UNINSTALLER_FUNCPREFIX}OnDirBrowseButton
+
+ Pop $R0
+
+ nsDialogs::GetUserData $R0
+ Pop $R1
+
+ ReadINIStr $R2 $0 "Field $R1" HWND
+ ReadINIStr $R3 $0 "Field $R1" Text
+
+ ${NSD_GetText} $R2 $R4
+
+ nsDialogs::SelectFolderDialog $R3 $R4
+ Pop $R3
+
+ ${If} $R3 != error
+ SendMessage $R2 ${WM_SETTEXT} 0 STR:$R3
+ ${EndIf}
+
+ FunctionEnd
+
+ Function ${UNINSTALLER_FUNCPREFIX}Link
+
+ ${NSD_CreateLink} $R3u $R4u $R5u $R6u $R7
+ Pop $R9
+
+ nsDialogs::SetUserData $R9 $R1 # remember field id
+
+ ${NSD_OnClick} $R9 ${UNINSTALLER_FUNCPREFIX}OnLink
+
+ FunctionEnd
+
+ Function ${UNINSTALLER_FUNCPREFIX}OnLink
+
+ Pop $R0
+
+ nsDialogs::GetUserData $R0
+ Pop $R1
+
+ ReadINIStr $R1 $0 "Field $R1" STATE
+
+ ExecShell "" $R1
+
+ FunctionEnd
+
+!macroend
+
+!verbose pop
+!endif
diff --git a/installer/tools/Include/x64.nsh b/installer/tools/Include/x64.nsh
new file mode 100644
index 00000000..59d9e8c2
--- /dev/null
+++ b/installer/tools/Include/x64.nsh
@@ -0,0 +1,120 @@
+; ---------------------
+; x64.nsh
+; ---------------------
+;
+; A few simple macros to handle installations on x64 machines.
+;
+; RunningX64 checks if the installer is running on a 64-bit OS.
+; IsWow64 checks if the installer is a 32-bit application running on a 64-bit OS.
+;
+; ${If} ${RunningX64}
+; MessageBox MB_OK "Running on 64-bit Windows"
+; ${EndIf}
+;
+; IsNative* checks the OS native CPU architecture.
+;
+; ${If} ${IsNativeAMD64}
+; ; Install AMD64 64-bit driver/library
+; ${ElseIf} ${IsNativeARM64}
+; ; Install ARM64 64-bit driver/library
+; ${ElseIf} ${IsNativeIA32}
+; ; Install i386 32-bit driver/library
+; ${Else}
+; Abort "Unsupported CPU architecture!"
+; ${EndIf}
+;
+; ${If} ${IsNativeAMD64}
+; File "amd64\myapp.exe"
+; ${ElseIf} ${IsNativeIA32}
+; ${OrIf} ${IsWow64}
+; File "x86\myapp.exe"
+; ${Else}
+; Abort "Unsupported CPU architecture!"
+; ${EndIf}
+;
+; DisableX64FSRedirection disables file system redirection.
+; EnableX64FSRedirection enables file system redirection.
+;
+; SetOutPath $SYSDIR
+; ${DisableX64FSRedirection}
+; File something.bin # extracts to C:\Windows\System32
+; ${EnableX64FSRedirection}
+; File something.bin # extracts to C:\Windows\SysWOW64
+;
+
+!ifndef ___X64__NSH___
+!define ___X64__NSH___
+
+!include LogicLib.nsh
+
+
+!define IsWow64 `"" IsWow64 ""`
+!macro _IsWow64 _a _b _t _f
+ !insertmacro _LOGICLIB_TEMP
+ System::Call kernel32::GetCurrentProcess()p.s
+ System::Call kernel32::IsWow64Process2(ps,*i0s,*i) ; [Win10.1511+] 0 if not WOW64
+ Push |
+ System::Call kernel32::IsWow64Process(p-1,*i0s) ; [WinXP+] FALSE for a 32-bit application on ARM64!
+ System::Int64Op
+ Pop $_LOGICLIB_TEMP
+ !insertmacro _!= $_LOGICLIB_TEMP 0 `${_t}` `${_f}`
+!macroend
+
+
+!define RunningX64 `"" RunningX64 ""`
+!macro _RunningX64 _a _b _t _f
+ !if ${NSIS_PTR_SIZE} > 4
+ !insertmacro LogicLib_JumpToBranch `${_t}` `${_f}`
+ !else
+ !insertmacro _IsWow64 `${_a}` `${_b}` `${_t}` `${_f}`
+ !endif
+!macroend
+
+
+!define GetNativeMachineArchitecture "!insertmacro GetNativeMachineArchitecture "
+!macro GetNativeMachineArchitecture outvar
+ !define GetNativeMachineArchitecture_lbl lbl_GNMA_${__COUNTER__}
+ System::Call kernel32::GetCurrentProcess()p.s
+ System::Call kernel32::IsWow64Process2(ps,*i,*i0s)
+ Pop ${outvar}
+ IntCmp ${outvar} 0 "" ${GetNativeMachineArchitecture_lbl}_done ${GetNativeMachineArchitecture_lbl}_done
+ !if "${NSIS_PTR_SIZE}" <= 4
+ !if "${NSIS_CHAR_SIZE}" <= 1
+ System::Call 'USER32::CharNextW(w"")p.s'
+ Pop ${outvar}
+ IntPtrCmpU ${outvar} 0 "" ${GetNativeMachineArchitecture_lbl}_oldnt ${GetNativeMachineArchitecture_lbl}_oldnt
+ StrCpy ${outvar} 332 ; Always IMAGE_FILE_MACHINE_I386 on Win9x
+ Goto ${GetNativeMachineArchitecture_lbl}_done
+ ${GetNativeMachineArchitecture_lbl}_oldnt:
+ !endif
+ !endif
+ System::Call '*0x7FFE002E(&i2.s)'
+ Pop ${outvar}
+ ${GetNativeMachineArchitecture_lbl}_done:
+ !undef GetNativeMachineArchitecture_lbl
+!macroend
+
+!macro _IsNativeMachineArchitecture _ignore _arc _t _f
+ !insertmacro _LOGICLIB_TEMP
+ ${GetNativeMachineArchitecture} $_LOGICLIB_TEMP
+ !insertmacro _= $_LOGICLIB_TEMP ${_arc} `${_t}` `${_f}`
+!macroend
+
+!define IsNativeMachineArchitecture `"" IsNativeMachineArchitecture `
+!define IsNativeIA32 '${IsNativeMachineArchitecture} 332' ; Intel x86
+!define IsNativeAMD64 '${IsNativeMachineArchitecture} 34404' ; x86-64/x64
+!define IsNativeARM64 '${IsNativeMachineArchitecture} 43620'
+
+
+!define DisableX64FSRedirection "!insertmacro DisableX64FSRedirection"
+!macro DisableX64FSRedirection
+ System::Call kernel32::Wow64EnableWow64FsRedirection(i0)
+!macroend
+
+!define EnableX64FSRedirection "!insertmacro EnableX64FSRedirection"
+!macro EnableX64FSRedirection
+ System::Call kernel32::Wow64EnableWow64FsRedirection(i1)
+!macroend
+
+
+!endif # !___X64__NSH___
diff --git a/installer/tools/Plugins/x86-unicode/AdvSplash.dll b/installer/tools/Plugins/x86-unicode/AdvSplash.dll
new file mode 100644
index 00000000..2665804d
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/AdvSplash.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/Banner.dll b/installer/tools/Plugins/x86-unicode/Banner.dll
new file mode 100644
index 00000000..5faa70b2
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/Banner.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/BgImage.dll b/installer/tools/Plugins/x86-unicode/BgImage.dll
new file mode 100644
index 00000000..02ed7112
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/BgImage.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/Dialer.dll b/installer/tools/Plugins/x86-unicode/Dialer.dll
new file mode 100644
index 00000000..121ebf7e
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/Dialer.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/InstallOptions.dll b/installer/tools/Plugins/x86-unicode/InstallOptions.dll
new file mode 100644
index 00000000..a842ac64
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/InstallOptions.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/LangDLL.dll b/installer/tools/Plugins/x86-unicode/LangDLL.dll
new file mode 100644
index 00000000..1e28c761
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/LangDLL.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/Math.dll b/installer/tools/Plugins/x86-unicode/Math.dll
new file mode 100644
index 00000000..2636d09d
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/Math.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/NSISdl.dll b/installer/tools/Plugins/x86-unicode/NSISdl.dll
new file mode 100644
index 00000000..9c2b7e1a
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/NSISdl.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/Splash.dll b/installer/tools/Plugins/x86-unicode/Splash.dll
new file mode 100644
index 00000000..2bc507fb
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/Splash.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/StartMenu.dll b/installer/tools/Plugins/x86-unicode/StartMenu.dll
new file mode 100644
index 00000000..be975dae
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/StartMenu.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/System.dll b/installer/tools/Plugins/x86-unicode/System.dll
new file mode 100644
index 00000000..921bc86e
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/System.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/TypeLib.dll b/installer/tools/Plugins/x86-unicode/TypeLib.dll
new file mode 100644
index 00000000..73cf6dd8
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/TypeLib.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/UserInfo.dll b/installer/tools/Plugins/x86-unicode/UserInfo.dll
new file mode 100644
index 00000000..24094c21
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/UserInfo.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/VPatch.dll b/installer/tools/Plugins/x86-unicode/VPatch.dll
new file mode 100644
index 00000000..8583310a
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/VPatch.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/nsDialogs.dll b/installer/tools/Plugins/x86-unicode/nsDialogs.dll
new file mode 100644
index 00000000..90740b34
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/nsDialogs.dll differ
diff --git a/installer/tools/Plugins/x86-unicode/nsExec.dll b/installer/tools/Plugins/x86-unicode/nsExec.dll
new file mode 100644
index 00000000..074ea462
Binary files /dev/null and b/installer/tools/Plugins/x86-unicode/nsExec.dll differ
diff --git a/installer/tools/Stubs/lzma-x86-unicode b/installer/tools/Stubs/lzma-x86-unicode
new file mode 100644
index 00000000..df2860f7
Binary files /dev/null and b/installer/tools/Stubs/lzma-x86-unicode differ
diff --git a/installer/tools/Stubs/lzma_solid-x86-unicode b/installer/tools/Stubs/lzma_solid-x86-unicode
new file mode 100644
index 00000000..52f10219
Binary files /dev/null and b/installer/tools/Stubs/lzma_solid-x86-unicode differ
diff --git a/installer/tools/Stubs/uninst b/installer/tools/Stubs/uninst
new file mode 100644
index 00000000..90d7d225
Binary files /dev/null and b/installer/tools/Stubs/uninst differ
diff --git a/installer/tools/Stubs/zlib-x86-unicode b/installer/tools/Stubs/zlib-x86-unicode
new file mode 100644
index 00000000..14b3b544
Binary files /dev/null and b/installer/tools/Stubs/zlib-x86-unicode differ
diff --git a/installer/tools/Stubs/zlib_solid-x86-unicode b/installer/tools/Stubs/zlib_solid-x86-unicode
new file mode 100644
index 00000000..0f2cf9ee
Binary files /dev/null and b/installer/tools/Stubs/zlib_solid-x86-unicode differ
diff --git a/installer/tools/makensis.exe b/installer/tools/makensis.exe
new file mode 100644
index 00000000..20628c7e
Binary files /dev/null and b/installer/tools/makensis.exe differ
diff --git a/installer/tools/nsisconf.nsh b/installer/tools/nsisconf.nsh
new file mode 100644
index 00000000..716522fa
--- /dev/null
+++ b/installer/tools/nsisconf.nsh
@@ -0,0 +1,63 @@
+;------------------------
+;DEFAULT NSIS CONFIG FILE
+;------------------------
+
+;This header file will be included when compiling any NSIS installer,
+;you can use it to add script code to every installer you compile.
+
+;This file is treated as if it is in the directory of your script.
+;When using relative paths, the files have to be in your build directory.
+
+;------------------------
+;EXAMPLES
+;------------------------
+
+;Compress installer exehead with an executable compressor (such as UPX / Petite).
+
+;Paths should be absolute to allow building from any location.
+;Note that your executable compressor should not compress the first icon.
+
+;!packhdr temp.dat '"C:\Program Files\upx\upx" -9 -q temp.dat'
+;!packhdr temp.dat '"C:\Program Files\petite\petite" -9 -b0 -r** -p0 -y temp.dat'
+
+;------------------------
+
+;Set default compressor
+
+SetCompressor lzma
+; etCompressor bzip2
+
+;------------------------
+
+;Change the default icons
+
+;Icon "${NSISDIR}\Contrib\Graphics\Icons\arrow-install.ico"
+;UninstallIcon "${NSISDIR}\Contrib\Graphics\Icons\arrow-uninstall.ico"
+
+;------------------------
+
+;Define symbols
+
+;!define COMPANYNAME "bla"
+
+;------------------------
+;MODERN UI
+;------------------------
+
+;The Modern UI will insert the MUI_NSISCONF macro just before processing the settings.
+;Here you can set default settings for the Modern UI.
+
+;------------------------
+
+!define MUI_INSERT_NSISCONF
+
+!macro MUI_NSISCONF
+
+ ;Example: Change the default Modern UI icons
+
+ ;!ifndef MUI_ICON & MUI_UNICON
+ ; !define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\arrow-install.ico"
+ ; !define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\arrow-uninstall.ico"
+ ;!endif
+
+!macroend
\ No newline at end of file