diff --git a/.editorconfig b/.editorconfig index 0deca3d..a5ee115 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,3 +11,5 @@ trim_trailing_whitespace = true [*.md] trim_trailing_whitespace = false +[*.yml] +indent_size = 2 diff --git a/.github/workflows/arma.yml b/.github/workflows/arma.yml index 55e030f..293c2d3 100644 --- a/.github/workflows/arma.yml +++ b/.github/workflows/arma.yml @@ -11,8 +11,20 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout the source code - uses: actions/checkout@master + uses: actions/checkout@v4 - name: Validate SQF run: python3 tools/sqf_validator.py - name: Validate Config run: python3 tools/config_style_checker.py + - name: Check for BOM + uses: arma-actions/bom-check@v1 + + build: + runs-on: ubuntu-latest + steps: + - name: Checkout the source code + uses: actions/checkout@v4 + - name: Setup HEMTT + uses: arma-actions/hemtt@v1 + - name: Run HEMTT build + run: hemtt build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f1b11a5..a4b7386 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,45 +12,36 @@ jobs: if: github.repository == 'Metis-Team/mts_enhanced' && ! contains(github.event.head_commit.message, '[ci skip]') runs-on: windows-latest outputs: - NAME: ${{ env.NAME }} MOD_NAME: ${{ env.MOD_NAME }} - MOD_NAME_LOWER: ${{ env.MOD_NAME_LOWER }} - MAIN_PREFIX: ${{ env.MAIN_PREFIX }} VERSION: ${{ env.VERSION }} VERSION_SHORT: ${{ env.VERSION_SHORT }} SHA_SHORT: ${{ env.SHA_SHORT }} steps: - name: Checkout the source code - uses: actions/checkout@v2 + uses: actions/checkout@v4 + + - name: Setup HEMTT + uses: arma-actions/hemtt@v1 - name: Setup Tools run: | C:\msys64\usr\bin\wget.exe ${{ secrets.FTP_SERVER }}/arma_tools.zip --user ${{ secrets.FTP_USERNAME }} --password ${{ secrets.FTP_PASSWORD }} -q Expand-Archive arma_tools.zip -DestinationPath ci - echo "Check HEMTT: $(Test-Path .\\ci\\hemtt.exe)" echo "Check Binarize: $(Test-Path .\\ci\\binarize\\binarize_x64.exe)" - echo "Check ArmaScriptCompiler: $(Test-Path .\\ci\\ArmaScriptCompiler.exe)" - .\ci\hemtt.exe --version + hemtt --version echo "Install Binarize dependencies" cp .\ci\binarize\X3DAudio1_7.dll,.\ci\binarize\XAPOFX1_5.dll C:\Windows\System32\ echo "::group::Set Binarize registry path" New-Item "HKCU:\\Software\\Bohemia Interactive\\binarize" -Force | New-ItemProperty -Name path -Value "${{ github.workspace }}\ci\binarize" echo "::endgroup::" echo "Set env variables" - echo "NAME=$(.\\ci\\hemtt.exe var name)" >> $env:GITHUB_ENV - echo "MOD_NAME=$(.\\ci\\hemtt.exe var modname)" >> $env:GITHUB_ENV - echo "MOD_NAME_LOWER=$((.\\ci\\hemtt.exe var modname).toLower())" >> $env:GITHUB_ENV - echo "MAIN_PREFIX=$(.\\ci\\hemtt.exe var mainprefix)" >> $env:GITHUB_ENV - echo "VERSION=$(.\\ci\\hemtt.exe var version)" >> $env:GITHUB_ENV - echo "VERSION_SHORT=$(($(.\\ci\\hemtt.exe var version) | Select-String -Pattern '^\d+\.\d+\.\d+').Matches.Value)" >> $env:GITHUB_ENV + echo "MOD_NAME=Metis_Enhanced" >> $env:GITHUB_ENV + $version = Select-String -Path "addons\\main\\script_version.hpp" -Pattern '#define (MAJOR|MINOR|PATCHLVL|BUILD) (\d+)' | ForEach-Object { $_.Matches.Groups[2].Value } | Join-String -Separator "." + $version_short = (Select-String -InputObject $version -Pattern '^\d+\.\d+\.\d+').Matches.Value + echo "VERSION=$version" >> $env:GITHUB_ENV + echo "VERSION_SHORT=$version_short" >> $env:GITHUB_ENV echo "SHA_SHORT=$(git rev-parse --short HEAD)" >> $env:GITHUB_ENV - - name: Setup P-Drive for ArmaScriptCompiler - run: | - echo "Creating P: and linking ${{ env.MAIN_PREFIX }}\mts_enhanced\addons" - subst p: include - New-Item -ItemType Junction -Path "p:${{ env.MAIN_PREFIX }}\mts_enhanced\addons" -Target "addons" - - name: Test Binarize run: | echo "::group::Run Binarize without arguments (look for missing DLLs)" @@ -60,16 +51,19 @@ jobs: - name: Build (HEMTT) run: | - echo "${{ env.NAME }} v${{ env.VERSION_SHORT }} (${{ env.VERSION }}; ${{ env.SHA_SHORT }})" - .\ci\hemtt.exe build --release --ci --time + echo "${{ env.MOD_NAME }} v${{ env.VERSION }} (${{ env.SHA_SHORT }})" + hemtt release --no-archive env: BIOUTPUT: 1 # output binarize log + - name: Rename build folder + run: mv .hemttout/release .hemttout/@${{ env.MOD_NAME }} + - name: Upload Artifact - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: ${{ env.MOD_NAME }} - path: releases/${{ env.VERSION }}/* # Upload folder to avoid double-zip artifacts + path: .hemttout/@* retention-days: 1 publish-release: @@ -78,14 +72,16 @@ jobs: runs-on: ubuntu-latest steps: - name: Download Artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v3 + - name: Prepare Archives run: | mv ${{ needs.build.outputs.MOD_NAME }}/* . echo "::group::Archive build" zip -r ${{ needs.build.outputs.MOD_NAME }}_${{ needs.build.outputs.VERSION_SHORT }}.zip @${{ needs.build.outputs.MOD_NAME }} echo "::endgroup::" - - name: Prepare GitHub + + - name: Prepare GitHub Release id: release_drafter uses: release-drafter/release-drafter@v5 with: @@ -94,8 +90,9 @@ jobs: version: ${{ needs.build.outputs.VERSION }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Upload to GitHub - uses: actions/upload-release-asset@v1 + + - name: Upload mod archive to GitHub Release + uses: shogo82148/actions-upload-release-asset@v1.7.2 with: upload_url: ${{ steps.release_drafter.outputs.upload_url }} asset_path: ./${{ needs.build.outputs.MOD_NAME }}_${{ needs.build.outputs.VERSION_SHORT }}.zip diff --git a/.gitignore b/.gitignore index 64dca67..5f6f8a1 100644 --- a/.gitignore +++ b/.gitignore @@ -14,5 +14,5 @@ hemtt hemtt.exe releases/* keys/* -.hemtt/local +.hemttout/ #### diff --git a/.hemtt/hooks/post_release/01_rename_zip.rhai b/.hemtt/hooks/post_release/01_rename_zip.rhai new file mode 100644 index 0000000..3385fbf --- /dev/null +++ b/.hemtt/hooks/post_release/01_rename_zip.rhai @@ -0,0 +1,14 @@ +let releases = HEMTT_RFS.join("releases"); + +let src = releases.join(HEMTT.project().prefix() + "-" + HEMTT.project().version().to_string() + ".zip"); + +if (src.exists()) { + let dst = releases.join(HEMTT.project().name() + "_" + HEMTT.project().version().to_string_short() + ".zip"); + + print("Moving archive to " + dst); + if (!src.move(dst)) { + fatal("Failed to rename " + src + " to " + dst); + } +} else { + warn("Cannot rename archive. File " + src + " does not exist!"); +} diff --git a/.hemtt/project.toml b/.hemtt/project.toml new file mode 100644 index 0000000..821caf1 --- /dev/null +++ b/.hemtt/project.toml @@ -0,0 +1,35 @@ +name = "Metis_Enhanced" +mainprefix = "z" +prefix = "mts" +author = "Bix, PhILoX, Timi007" + +[files] +include = [ + "mod.cpp", + "README.md", + "LICENSE", + "mts_enhanced_picture.paa", + "mts_enhanced_logo_small.paa", + "mts_enhanced_logo_over_small.paa", + "meta.cpp" +] + +[signing] +authority = "mts_enhanced" + +[version] +git_hash = 0 + +[asc] +enabled = true +exclude = [ + "/initsettings.sqf", + "/initkeybinds.sqf", + "/xeh_prep.sqf", +] + +[hemtt.config] +preset = "Hemtt" + +[hemtt.release] +folder = "Metis_Enhanced" diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 629df82..bef2126 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -5,7 +5,7 @@ "label": "Build Debug", "detail": "Build Arma addon with HEMTT in debug mode.", "type": "process", - "command": "hemtt.exe", + "command": "hemtt", "args": ["build"], "group": "build", "presentation": { @@ -18,13 +18,8 @@ "label": "Build Release", "detail": "Build Arma addon with HEMTT for release.", "type": "process", - "command": "hemtt.exe", - "args": [ - "build", - "--release", - "--time", - "-f" - ], + "command": "hemtt", + "args": ["release"], "group": "build" } ] diff --git a/addons/armory/ui/RscAttributes.hpp b/addons/armory/ui/RscAttributes.hpp index 6f9d1bc..4c10d60 100644 --- a/addons/armory/ui/RscAttributes.hpp +++ b/addons/armory/ui/RscAttributes.hpp @@ -46,7 +46,7 @@ class GVAR(dialog) { y = "SafeZoneY + (180 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onCheckedChanged = QUOTE([ARR_2(QQGVAR(updateArsenal), [ARR_2(ctrlText IDC_TEXT_TITLE, (cbChecked (_this select 0)))])] call CBA_fnc_globalEvent); + onCheckedChanged = QUOTE([ARR_2(QQGVAR(updateArsenal),[ARR_2(ctrlText IDC_TEXT_TITLE,(cbChecked (_this select 0)))])] call CBA_fnc_globalEvent); }; class Text_Title : Text { idc = IDC_TEXT_TITLE; @@ -112,7 +112,7 @@ class GVAR(dialog) { y = "SafeZoneY + (310 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); }; class Button_Loadout_2 : Button { idc = IDC_LOADOUT_2; @@ -120,7 +120,7 @@ class GVAR(dialog) { y = "SafeZoneY + (350 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); }; class Button_Loadout_3 : Button { idc = IDC_LOADOUT_3; @@ -128,7 +128,7 @@ class GVAR(dialog) { y = "SafeZoneY + (390 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); }; class Button_Loadout_4 : Button { idc = IDC_LOADOUT_4; @@ -136,7 +136,7 @@ class GVAR(dialog) { y = "SafeZoneY + (430 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); }; class Button_Loadout_5 : Button { idc = IDC_LOADOUT_5; @@ -144,7 +144,7 @@ class GVAR(dialog) { y = "SafeZoneY + (470 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); }; class Button_Loadout_6 : Button { idc = IDC_LOADOUT_6; @@ -152,7 +152,7 @@ class GVAR(dialog) { y = "SafeZoneY + (510 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); }; class Button_Loadout_7 : Button { idc = IDC_LOADOUT_7; @@ -160,7 +160,7 @@ class GVAR(dialog) { y = "SafeZoneY + (550 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); }; class Button_Loadout_8 : Button { idc = IDC_LOADOUT_8; @@ -168,7 +168,7 @@ class GVAR(dialog) { y = "SafeZoneY + (590 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); }; class Button_Loadout_9 : Button { idc = IDC_LOADOUT_9; @@ -176,7 +176,7 @@ class GVAR(dialog) { y = "SafeZoneY + (630 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); }; class Button_Loadout_10 : Button { idc = IDC_LOADOUT_10; @@ -184,7 +184,7 @@ class GVAR(dialog) { y = "SafeZoneY + (670 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); }; class Button_Loadout_11 : Button { idc = IDC_LOADOUT_11; @@ -192,7 +192,7 @@ class GVAR(dialog) { y = "SafeZoneY + (710 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); }; class Button_Loadout_12 : Button { idc = IDC_LOADOUT_12; @@ -200,7 +200,7 @@ class GVAR(dialog) { y = "SafeZoneY + (750 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipLoadout)); }; // Body loadout configure buttons ---------------------------------------- class Button_Loadout_Edit_1 : Button_Image { @@ -209,7 +209,7 @@ class GVAR(dialog) { y = "SafeZoneY + (310 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_1, LOADOUT)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_1,LOADOUT)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_1) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_1) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -219,7 +219,7 @@ class GVAR(dialog) { y = "SafeZoneY + (350 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_2, LOADOUT)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_2,LOADOUT)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_2) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_2) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -229,7 +229,7 @@ class GVAR(dialog) { y = "SafeZoneY + (390 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_3, LOADOUT)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_3,LOADOUT)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_3) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_3) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -239,7 +239,7 @@ class GVAR(dialog) { y = "SafeZoneY + (430 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_4, LOADOUT)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_4,LOADOUT)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_4) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_4) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -249,7 +249,7 @@ class GVAR(dialog) { y = "SafeZoneY + (470 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_5, LOADOUT)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_5,LOADOUT)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_5) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_5) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -259,7 +259,7 @@ class GVAR(dialog) { y = "SafeZoneY + (510 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_6, LOADOUT)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_6,LOADOUT)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_6) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_6) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -269,7 +269,7 @@ class GVAR(dialog) { y = "SafeZoneY + (550 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_7, LOADOUT)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_7,LOADOUT)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_7) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_7) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -279,7 +279,7 @@ class GVAR(dialog) { y = "SafeZoneY + (590 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_8, LOADOUT)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_8,LOADOUT)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_8) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_8) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -289,7 +289,7 @@ class GVAR(dialog) { y = "SafeZoneY + (630 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_9, LOADOUT)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_9,LOADOUT)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_9) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_9) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -299,7 +299,7 @@ class GVAR(dialog) { y = "SafeZoneY + (670 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_10, LOADOUT)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_10,LOADOUT)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_10) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_10) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -309,7 +309,7 @@ class GVAR(dialog) { y = "SafeZoneY + (710 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_11, LOADOUT)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_11,LOADOUT)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_11) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_11) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -319,7 +319,7 @@ class GVAR(dialog) { y = "SafeZoneY + (750 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_12, LOADOUT)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_LOADOUT_12,LOADOUT)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_12) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_LOADOUT_12) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -330,7 +330,7 @@ class GVAR(dialog) { y = "SafeZoneY + (310 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); }; class Button_Backpack_2 : Button { idc = IDC_BACKPACK_2; @@ -338,7 +338,7 @@ class GVAR(dialog) { y = "SafeZoneY + (350 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); }; class Button_Backpack_3 : Button { idc = IDC_BACKPACK_3; @@ -346,7 +346,7 @@ class GVAR(dialog) { y = "SafeZoneY + (390 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); }; class Button_Backpack_4 : Button { idc = IDC_BACKPACK_4; @@ -354,7 +354,7 @@ class GVAR(dialog) { y = "SafeZoneY + (430 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); }; class Button_Backpack_5 : Button { idc = IDC_BACKPACK_5; @@ -362,7 +362,7 @@ class GVAR(dialog) { y = "SafeZoneY + (470 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); }; class Button_Backpack_6 : Button { idc = IDC_BACKPACK_6; @@ -370,7 +370,7 @@ class GVAR(dialog) { y = "SafeZoneY + (510 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); }; class Button_Backpack_7 : Button { idc = IDC_BACKPACK_7; @@ -378,7 +378,7 @@ class GVAR(dialog) { y = "SafeZoneY + (550 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); }; class Button_Backpack_8 : Button { idc = IDC_BACKPACK_8; @@ -386,7 +386,7 @@ class GVAR(dialog) { y = "SafeZoneY + (590 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); }; class Button_Backpack_9 : Button { idc = IDC_BACKPACK_9; @@ -394,7 +394,7 @@ class GVAR(dialog) { y = "SafeZoneY + (630 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); }; class Button_Backpack_10 : Button { idc = IDC_BACKPACK_10; @@ -402,7 +402,7 @@ class GVAR(dialog) { y = "SafeZoneY + (670 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); }; class Button_Backpack_11 : Button { idc = IDC_BACKPACK_11; @@ -410,7 +410,7 @@ class GVAR(dialog) { y = "SafeZoneY + (710 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); }; class Button_Backpack_12 : Button { idc = IDC_BACKPACK_12; @@ -418,7 +418,7 @@ class GVAR(dialog) { y = "SafeZoneY + (750 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); + onButtonClick = QUOTE([ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText (_this select 0))] call LINKFUNC(equipBackpack)); }; // Body backpacks configure buttons ---------------------------------------- class Button_Backpack_Edit_1 : Button_Image { @@ -427,7 +427,7 @@ class GVAR(dialog) { y = "SafeZoneY + (310 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_1, BACKPACK)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_1,BACKPACK)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_1) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_1) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -437,7 +437,7 @@ class GVAR(dialog) { y = "SafeZoneY + (350 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_2, BACKPACK)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_2,BACKPACK)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_2) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_2) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -447,7 +447,7 @@ class GVAR(dialog) { y = "SafeZoneY + (390 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_3, BACKPACK)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_3,BACKPACK)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_3) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_3) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -457,7 +457,7 @@ class GVAR(dialog) { y = "SafeZoneY + (430 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_4, BACKPACK)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_4,BACKPACK)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_4) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_4) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -467,7 +467,7 @@ class GVAR(dialog) { y = "SafeZoneY + (470 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_5, BACKPACK)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_5,BACKPACK)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_5) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_5) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -477,7 +477,7 @@ class GVAR(dialog) { y = "SafeZoneY + (510 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_6, BACKPACK)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_6,BACKPACK)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_6) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_6) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -487,7 +487,7 @@ class GVAR(dialog) { y = "SafeZoneY + (550 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_7, BACKPACK)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_7,BACKPACK)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_7) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_7) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -497,7 +497,7 @@ class GVAR(dialog) { y = "SafeZoneY + (590 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_8, BACKPACK)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_8,BACKPACK)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_8) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_8) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -507,7 +507,7 @@ class GVAR(dialog) { y = "SafeZoneY + (630 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_9, BACKPACK)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_9,BACKPACK)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_9) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_9) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -517,7 +517,7 @@ class GVAR(dialog) { y = "SafeZoneY + (670 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_10, BACKPACK)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_10,BACKPACK)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_10) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_10) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -527,7 +527,7 @@ class GVAR(dialog) { y = "SafeZoneY + (710 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_11, BACKPACK)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_11,BACKPACK)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_11) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_11) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -537,7 +537,7 @@ class GVAR(dialog) { y = "SafeZoneY + (750 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_12, BACKPACK)] call LINKFUNC(setEditArea)); + onButtonClick = QUOTE([ARR_2(IDC_BACKPACK_12,BACKPACK)] call LINKFUNC(setEditArea)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_12) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_EDIT_BACKPACK_12) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -566,7 +566,7 @@ class GVAR(dialog) { y = "SafeZoneY + (800 / 1080) * SafeZoneH"; w = "(30 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(((ctrlParent (_this select 0)) displayCtrl IDC_BUTTON_SAVE_EQUIPMENT), true)] call LINKFUNC(saveEquipment)); + onButtonClick = QUOTE([ARR_2(((ctrlParent (_this select 0)) displayCtrl IDC_BUTTON_SAVE_EQUIPMENT),true)] call LINKFUNC(saveEquipment)); onMouseEnter = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_DELETE_EQUIPMENT) ctrlSetBackgroundColor [ARR_4(0,0,0,1)]); onMouseExit = QUOTE(((ctrlParent (_this select 0)) displayCtrl IDC_BACKGROUND_DELETE_EQUIPMENT) ctrlSetBackgroundColor [ARR_4(0,0,0,0.5)]); }; @@ -599,7 +599,7 @@ class GVAR(dialog) { y = "SafeZoneY + (965 / 1080) * SafeZoneH"; w = "(150 / 1920) * SafeZoneW"; h = "(30 / 1080) * SafeZoneH"; - onButtonClick = QUOTE([ARR_2(QQGVAR(updateEditors),[ARR_2(ctrlText IDC_TEXT_TITLE, ctrlText IDC_EDITBOX_EDITORS)])] call CBA_fnc_serverEvent); + onButtonClick = QUOTE([ARR_2(QQGVAR(updateEditors),[ARR_2(ctrlText IDC_TEXT_TITLE,ctrlText IDC_EDITBOX_EDITORS)])] call CBA_fnc_serverEvent); }; }; class controlsBackground { diff --git a/addons/zeus/functions/fnc_getModuleDestination.sqf b/addons/zeus/functions/fnc_getModuleDestination.sqf index 2f34f4c..2f41b7a 100644 --- a/addons/zeus/functions/fnc_getModuleDestination.sqf +++ b/addons/zeus/functions/fnc_getModuleDestination.sqf @@ -142,7 +142,7 @@ GVAR(moduleDestination_mapDrawEH) = [((findDisplay ZEUS_DISPLAY) displayCtrl ZEU (_this select 0) params ["_startPosASL", "_code", "_text", "_icon", "_color", "_angle", "_drawLine", "_drawIconAtStart", "_beforeDrawingCode"]; if (isNull findDisplay ZEUS_DISPLAY || {!isNull findDisplay PAUSE_MENU_DISPLAY}) then { - TRACE_3("null-exit",isNull findDisplay ZEUS_DISPLAY,isNull findDisplay PAUSE_MENU_DISPLAY); + TRACE_2("null-exit",(isNull findDisplay ZEUS_DISPLAY),(isNull findDisplay PAUSE_MENU_DISPLAY)); GVAR(moduleDestination_running) = false; [false, _startPosASL, [0,0,0], false, false, false, _args] call _code; }; diff --git a/build.bat b/build.bat index 3392b5b..34e67d1 100644 --- a/build.bat +++ b/build.bat @@ -1,3 +1,3 @@ @echo off -hemtt.exe build +hemtt build pause diff --git a/build_release.bat b/build_release.bat index 0b14c1d..8a19ec6 100644 --- a/build_release.bat +++ b/build_release.bat @@ -1,3 +1,3 @@ @echo off -hemtt.exe build --release --time -f +hemtt release pause diff --git a/hemtt.toml b/hemtt.toml deleted file mode 100644 index 499fd7e..0000000 --- a/hemtt.toml +++ /dev/null @@ -1,44 +0,0 @@ -name = "Metis Enhanced" -prefix = "mts" -author = "Bix, PhILoX, Timi007" -files = [ - "*.dll", - "*.so", - "mod.cpp", - "README.md", - "LICENSE", - "mts_enhanced_logo_over_small.paa", - "mts_enhanced_logo_small.paa", - "mts_enhanced_picture.paa", - "meta.cpp" -] - -modname = "Metis_Enhanced" -key_name = "mts_enhanced_{{version}}" -authority = "mts_enhanced_{{version}}-{{git \"id 8\"}}" - -prebuild = ["!compile_sqf"] -postbuild = ["!compile_sqf_cleanup"] -releasebuild = [ - "@zip Metis_Enhanced_{{semver.major}}.{{semver.minor}}.{{semver.patch}}" -] - -[header_exts] -version = "{{git \"id 8\"}}" - -# SQF Compilation -[scripts.compile_sqf] -steps_windows = [ - "echo Compile SQF", - "python tools/compile_sqf.py cleanup build" -] -only_release = true -show_output = true - -[scripts.compile_sqf_cleanup] -steps_windows = [ - "echo Compile SQF Cleanup", - "python tools/compile_sqf.py cleanup" -] -only_release = true -show_output = true diff --git a/include/x/cba/addons/main/script_macros_common.hpp b/include/x/cba/addons/main/script_macros_common.hpp index be13021..7d930c6 100644 --- a/include/x/cba/addons/main/script_macros_common.hpp +++ b/include/x/cba/addons/main/script_macros_common.hpp @@ -15,7 +15,7 @@ - Provide a solid structure that can be dynamic and easy editable (Which sometimes means we cannot adhere to Aim #1 ;-) An example is the path that is built from defines. Some available in this file, others in mods and addons. - Follows Standard: + Follows Standard: Object variables: PREFIX_COMPONENT Main-object variables: PREFIX_main Paths: MAINPREFIX\PREFIX\SUBPREFIX\COMPONENT\SCRIPTNAME.sqf @@ -29,6 +29,10 @@ and include your mod's script_macros.hpp In your scripts you can then include the addon's component.hpp with relative path) + use in subcomponents (subconfigs) + define SUBCOMPONENT and include parent component's script_component.hpp + currently only supported by SUBADDON, additional macros may be added in the future + TODO: - Try only to use 1 string type " vs ' - Evaluate double functions, and simplification @@ -54,6 +58,10 @@ #define ADDON DOUBLES(PREFIX,COMPONENT) #define MAIN_ADDON DOUBLES(PREFIX,main) +#ifdef SUBCOMPONENT + #define SUBADDON DOUBLES(ADDON,SUBCOMPONENT) +#endif + /* ------------------------------------------- Macro: VERSION_CONFIG Define CBA Versioning System config entries. @@ -857,15 +865,10 @@ Macro: ISNILS() #define COMPILE_SCRIPT(var1) compileScript ['PATHTO_SYS(PREFIX,COMPONENT_F,var1)'] -#define VERSIONING_SYS(var1) class CfgSettings \ -{ \ - class CBA \ - { \ - class Versioning \ - { \ - class var1 \ - { \ - }; \ +#define VERSIONING_SYS(var1) class CfgSettings { \ + class CBA { \ + class Versioning { \ + class var1 {}; \ }; \ }; \ }; @@ -1032,12 +1035,9 @@ Macro: PATHTO_FNC() #define QQEFUNC(var1,var2) QUOTE(QEFUNC(var1,var2)) #ifndef PRELOAD_ADDONS - #define PRELOAD_ADDONS class CfgAddons \ -{ \ - class PreloadAddons \ - { \ - class ADDON \ - { \ + #define PRELOAD_ADDONS class CfgAddons { \ + class PreloadAddons { \ + class ADDON { \ list[]={ QUOTE(ADDON) }; \ }; \ }; \ diff --git a/sqfc.json b/sqfc.json deleted file mode 100644 index b5f1b7d..0000000 --- a/sqfc.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "inputDirs": [ - "P:/z/mts_enhanced/addons/" - ], - "includePaths": [ - "P:/" - ], - "excludeList": [ - "\\initsettings.sqf", - "\\initkeybinds.sqf", - "\\xeh_prep.sqf" - ], - "outputDir": "P:/", - "workerThreads": 12 -} diff --git a/tools/build.py b/tools/build.py deleted file mode 100644 index 667851f..0000000 --- a/tools/build.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -import subprocess - -######## GLOBALS ######### -MAINPREFIX = "z" -PREFIX = "mts_" -########################## - -def tryHemttBuild(projectpath): - hemttExe = os.path.join(projectpath, "hemtt.exe") - if os.path.isfile(hemttExe): - os.chdir(projectpath) - ret = subprocess.call([hemttExe, "pack"], stderr=subprocess.STDOUT) - print("Using hemtt: {}".format(ret)) - return True - else: - print("hemtt not installed.") - return False - -def mod_time(path): - if not os.path.isdir(path): - return os.path.getmtime(path) - maxi = os.path.getmtime(path) - for p in os.listdir(path): - maxi = max(mod_time(os.path.join(path, p)), maxi) - return maxi - - -def check_for_changes(addonspath, module): - if not os.path.exists(os.path.join(addonspath, "{}{}.pbo".format(PREFIX,module))): - return True - return mod_time(os.path.join(addonspath, module)) > mod_time(os.path.join(addonspath, "{}{}.pbo".format(PREFIX,module))) - -def check_for_obsolete_pbos(addonspath, file): - module = file[len(PREFIX):-4] - if not os.path.exists(os.path.join(addonspath, module)): - return True - return False - -def main(): - print(""" - #################### - # MTS Debug Build # - #################### -""") - - scriptpath = os.path.realpath(__file__) - projectpath = os.path.dirname(os.path.dirname(scriptpath)) - addonspath = os.path.join(projectpath, "addons") - - if (tryHemttBuild(projectpath)): return - - os.chdir(addonspath) - - made = 0 - failed = 0 - skipped = 0 - removed = 0 - - for file in os.listdir(addonspath): - if os.path.isfile(file): - if check_for_obsolete_pbos(addonspath, file): - removed += 1 - print(" Removing obsolete file => " + file) - os.remove(file) - print("") - - for p in os.listdir(addonspath): - path = os.path.join(addonspath, p) - if not os.path.isdir(path): - continue - if p[0] == ".": - continue - if not check_for_changes(addonspath, p): - skipped += 1 - print(" Skipping {}.".format(p)) - continue - - print("# Making {} ...".format(p)) - - try: - subprocess.check_output([ - "makepbo", - "-NUP", - "-@={}\\{}\\addons\\{}".format(MAINPREFIX,PREFIX.rstrip("_"),p), - p, - "{}{}.pbo".format(PREFIX,p) - ], stderr=subprocess.STDOUT) - except: - failed += 1 - print(" Failed to make {}.".format(p)) - else: - made += 1 - print(" Successfully made {}.".format(p)) - - print("\n# Done.") - print(" Made {}, skipped {}, removed {}, failed to make {}.".format(made, skipped, removed, failed)) - - -if __name__ == "__main__": - sys.exit(main()) diff --git a/tools/compile_sqf.py b/tools/compile_sqf.py deleted file mode 100644 index 75b21e8..0000000 --- a/tools/compile_sqf.py +++ /dev/null @@ -1,55 +0,0 @@ -#!/usr/bin/env python3 - -import os -import sys -import subprocess - -# Handle script being called from either base or /tools folder (e.g. hemmt will run from base) -addon_base_path = os.getcwd() -if os.path.basename(addon_base_path) == "tools": - addon_base_path = os.path.dirname(addon_base_path) - - -def cleanup(): - count = 0 - for root, _dirs, files in os.walk(os.path.join(addon_base_path, "addons")): - for file in files: - if file.endswith(".sqfc"): - os.remove(os.path.join(root, file)) - count += 1 - print("cleaned [{} sqfc files]".format(count)) - - -def build(verbose = False): - compiler_exe = os.path.join(addon_base_path, "ArmaScriptCompiler.exe") - if not os.path.isfile(compiler_exe): - print("ArmaScriptCompiler.exe not found in base addon folder, trying ci folder") - compiler_exe = os.path.join(addon_base_path, "ci", "ArmaScriptCompiler.exe") - if not os.path.isfile(compiler_exe): - print("Warning: ArmaScriptCompiler.exe not found - skipping compiling") - return 1 - print("ArmaScriptCompiler.exe found - starting compiling") - if verbose: - print("\n") - ret = subprocess.call([compiler_exe], cwd=addon_base_path) - print("\n") - else: - ret = subprocess.call([compiler_exe], cwd=addon_base_path, stdout=subprocess.DEVNULL) - print("compiled [ret {}]".format(ret)) - return 0 - - -def main(argv): - ret = 0 - - # print("compile_sqf.py [Base: {}]".format(addon_base_path)) - if ("cleanup" in argv) or (len(argv) < 2): - cleanup() - if ("build" in argv) or (len(argv) < 2): - ret = build("verbose" in argv) - - return ret - - -if __name__ == "__main__": - sys.exit(main(sys.argv)) diff --git a/tools/make.cfg b/tools/make.cfg deleted file mode 100644 index 6357a05..0000000 --- a/tools/make.cfg +++ /dev/null @@ -1,96 +0,0 @@ -# EXAMPLE MAKE.CFG FILE -# Please see the comments for each option. Most options can be left -# off for sane defaults. - -################################################################# -# Default make target -################################################################# -[DEFAULT] - -# Project name (with @ symbol) -# This is used for naming the release files. -# Default: Current folder name -project = @Metis_Enhanced - -# Path to project secret key for signing -# Make sure this isn't in your public repository! -# Default: \private_keys\mts_3.0.0.biprivatekey -# key = P:\private_keys\mts_3.0.0.biprivatekey - -# Path to where private keys are automatically created if the command-line parameter "key" is used -# Make sure this isn't in your public repository! -# Default: \private_keys -# private_key_path = P:\private_keys - -# If set to True, the make system will attempt to autodetect addons in the -# current folder by looking for directories with 'config.cpp' in them. -# Default: True -# module_autodetect = True - -# List of directories to ignore when autodetecting addons. -# Default: release -# ignore = release, my_unfinished_module - -# If autodetect is set to False, only folders whose names are in this list -# will be built as modules. -# Default: None -# modules = my_module, my_supporting_module - -# This is the folder hierarchy that will be used as prefix inside the PBO. -# Default: None -prefix = z\mts_enhanced\addons - -# Set the location where the addon source folders (i.e. P:\z\ace\addons) -# Default: \\addons -module_root = P:\z\mts_enhanced\addons - -# Set the location where the optional addon source folders (i.e. P:\z\ace\optionals) -# Default: \\optionals -optionals_root = P:\z\mts_enhanced\optionals - - -# If the command-line variable test, the addons built will be copied to the following folder. -# Default: %USERPROFILE%\documents\Arma 3\ -# test_dir = %USERPROFILE%\documents\Arma 3\ - - -# Directory where the built addon will be saved. -# Default: release -release_dir = P:\z\mts_enhanced\release - - -# This string will be prefixed to all build PBO file names. -# Default: None -pbo_name_prefix = mts_ - -# This string will be prefixed to release archive. -# Default: None -zipPrefix = Metis_Enhanced - -# Which build tool will be used? Options: pboproject, addonbuilder -# Default: addonbuilder -build_tool = pboproject - -# Which name should be used for the key? -# Default: None -key_name = mts_enhanced_ - -################################################################## -# Alternate build target using a different key -################################################################### -# [DifferentKey] -# key = C:\Keys\different.biprivatekey - -################################################################## -# Alternate build target ignoring some modules when detecting -################################################################### -# [IgnoreSome] -# key = C:\Keys\different.biprivatekey -# ignore = release, my_server_module, my_private_module - -################################################################## -# Alternate build target with fixed build list -################################################################### -# [Fixed] -# module_autodetect = False -# modules = my_module, my_other_module diff --git a/tools/make.py b/tools/make.py deleted file mode 100644 index 5a20a92..0000000 --- a/tools/make.py +++ /dev/null @@ -1,1515 +0,0 @@ -#!/usr/bin/env python3 -# vim: set fileencoding=utf-8 : - -# make.py -# An Arma 3 addon build system - -############################################################################### - -# The MIT License (MIT) - -# Copyright (c) 2013-2014 Ryan Schultz - -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: - -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. - -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -############################################################################### - -__version__ = "0.91" - -import sys - -if sys.version_info[0] == 2: - print("Python 3 is required.") - sys.exit(1) - -import os -import os.path -import shutil -import platform -import glob -import subprocess -import hashlib -import configparser -import json -import traceback -import time -import timeit -import re -from tempfile import mkstemp - -if sys.platform == "win32": - import winreg - -######## GLOBALS ######### -project = "@Metis_Enhanced" -project_version = "1.0.0" -arma3tools_path = "" -work_drive = "" -module_root = "" -make_root = "" -release_dir = "" -module_root_parent = "" -optionals_root = "" -key_name = "mts_enhanced_" -key = "" -dssignfile = "" -prefix = "mts" -pbo_name_prefix = "mts_" -signature_blacklist = [] -importantFiles = ["mod.cpp", "LICENSE", "mts_team_logo_small.paa"] -versionFiles = ["mod.cpp"] - -ciBuild = False # Used for CI builds - -############################################################################### -# http://akiscode.com/articles/sha-1directoryhash.shtml -# Copyright (c) 2009 Stephen Akiki -# MIT License (Means you can do whatever you want with this) -# See http://www.opensource.org/licenses/mit-license.php -# Error Codes: -# -1 -> Directory does not exist -# -2 -> General error (see stack traceback) -def get_directory_hash(directory): - directory_hash = hashlib.sha1() - if not os.path.exists (directory): - return -1 - - try: - for root, dirs, files in os.walk(directory): - for names in files: - path = os.path.join(root, names) - try: - f = open(path, 'rb') - except: - # You can't open the file for some reason - f.close() - continue - - while 1: - # Read file in as little chunks - buf = f.read(4096) - if not buf: break - new = hashlib.sha1(buf) - directory_hash.update(new.digest()) - f.close() - - except: - # Print the stack traceback - traceback.print_exc() - return -2 - - retVal = directory_hash.hexdigest() - #print_yellow("Hash Value for {} is {}".format(directory,retVal)) - return directory_hash.hexdigest() - -def Fract_Sec(s): - temp = float() - temp = float(s) / (60*60*24) - d = int(temp) - temp = (temp - d) * 24 - h = int(temp) - temp = (temp - h) * 60 - m = int(temp) - temp = (temp - m) * 60 - sec = temp - return d,h,m,sec - #endef Fract_Sec - -# Copyright (c) André Burgaud -# http://www.burgaud.com/bring-colors-to-the-windows-console-with-python/ -if sys.platform == "win32": - from ctypes import windll, Structure, c_short, c_ushort, byref - - SHORT = c_short - WORD = c_ushort - - class COORD(Structure): - """struct in wincon.h.""" - _fields_ = [ - ("X", SHORT), - ("Y", SHORT)] - - class SMALL_RECT(Structure): - """struct in wincon.h.""" - _fields_ = [ - ("Left", SHORT), - ("Top", SHORT), - ("Right", SHORT), - ("Bottom", SHORT)] - - class CONSOLE_SCREEN_BUFFER_INFO(Structure): - """struct in wincon.h.""" - _fields_ = [ - ("dwSize", COORD), - ("dwCursorPosition", COORD), - ("wAttributes", WORD), - ("srWindow", SMALL_RECT), - ("dwMaximumWindowSize", COORD)] - - # winbase.h - STD_INPUT_HANDLE = -10 - STD_OUTPUT_HANDLE = -11 - STD_ERROR_HANDLE = -12 - - # wincon.h - FOREGROUND_BLACK = 0x0000 - FOREGROUND_BLUE = 0x0001 - FOREGROUND_GREEN = 0x0002 - FOREGROUND_CYAN = 0x0003 - FOREGROUND_RED = 0x0004 - FOREGROUND_MAGENTA = 0x0005 - FOREGROUND_YELLOW = 0x0006 - FOREGROUND_GREY = 0x0007 - FOREGROUND_INTENSITY = 0x0008 # foreground color is intensified. - - BACKGROUND_BLACK = 0x0000 - BACKGROUND_BLUE = 0x0010 - BACKGROUND_GREEN = 0x0020 - BACKGROUND_CYAN = 0x0030 - BACKGROUND_RED = 0x0040 - BACKGROUND_MAGENTA = 0x0050 - BACKGROUND_YELLOW = 0x0060 - BACKGROUND_GREY = 0x0070 - BACKGROUND_INTENSITY = 0x0080 # background color is intensified. - - stdout_handle = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE) - SetConsoleTextAttribute = windll.kernel32.SetConsoleTextAttribute - GetConsoleScreenBufferInfo = windll.kernel32.GetConsoleScreenBufferInfo - - def get_text_attr(): - """Returns the character attributes (colors) of the console screen - buffer.""" - csbi = CONSOLE_SCREEN_BUFFER_INFO() - GetConsoleScreenBufferInfo(stdout_handle, byref(csbi)) - return csbi.wAttributes - - def set_text_attr(color): - """Sets the character attributes (colors) of the console screen - buffer. Color is a combination of foreground and background color, - foreground and background intensity.""" - SetConsoleTextAttribute(stdout_handle, color) -############################################################################### - -def find_bi_tools(work_drive): - """Find BI tools.""" - - reg = winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) - try: - k = winreg.OpenKey(reg, r"Software\bohemia interactive\arma 3 tools") - arma3tools_path = winreg.QueryValueEx(k, "path")[0] - winreg.CloseKey(k) - except: - raise Exception("BadTools","Arma 3 Tools are not installed correctly or the P: drive needs to be created.") - - addonbuilder_path = os.path.join(arma3tools_path, "AddonBuilder", "AddonBuilder.exe") - dssignfile_path = os.path.join(arma3tools_path, "DSSignFile", "DSSignFile.exe") - dscreatekey_path = os.path.join(arma3tools_path, "DSSignFile", "DSCreateKey.exe") - cfgconvert_path = os.path.join(arma3tools_path, "CfgConvert", "CfgConvert.exe") - - if os.path.isfile(addonbuilder_path) and os.path.isfile(dssignfile_path) and os.path.isfile(dscreatekey_path) and os.path.isfile(cfgconvert_path): - return [addonbuilder_path, dssignfile_path, dscreatekey_path, cfgconvert_path] - else: - raise Exception("BadTools","Arma 3 Tools are not installed correctly or the P: drive needs to be created.") - -def mikero_windows_registry(path, access=winreg.KEY_READ): - try: - return winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Mikero\{}".format(path), access=access) - except FileNotFoundError: - try: - return winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"Software\Mikero\{}".format(path), access=access) - except FileNotFoundError: - try: - return winreg.OpenKey(winreg.HKEY_CURRENT_USER, r"Software\Wow6432Node\Mikero\{}".format(path), access=access) - except FileNotFoundError: - return winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, r"Software\Wow6432Node\Mikero\{}".format(path), access=access) - -def find_depbo_tools(): - """Use registry entries to find DePBO-based tools.""" - requiredToolPaths = {"pboProject": None, "rapify": None, "MakePbo": None} - failed = False - - for tool in requiredToolPaths: - try: - k = mikero_windows_registry(tool) - path = winreg.QueryValueEx(k, "exe")[0] - except FileNotFoundError: - print_error("Could not find {}".format(tool)) - failed = True - else: - #Strip any quotations from the path due to a MikeRo tool bug which leaves a trailing space in some of its registry paths. - requiredToolPaths[tool] = path.strip('"') - print_green("Found {}.".format(tool)) - finally: - winreg.CloseKey(k) - - if failed: - raise Exception("BadDePBO", "DePBO tools not installed correctly") - - return requiredToolPaths - -def pboproject_settings(): - """Use registry entries to configure needed pboproject settings.""" - value_exclude = "thumbs.db,*.txt,*.h,*.dep,*.cpp,*.bak,*.png,*.log,*.pew,source,*.tga" - - try: - k = mikero_windows_registry(r"pboProject\Settings", access=winreg.KEY_SET_VALUE) - winreg.SetValueEx(k, "m_exclude", 0, winreg.REG_SZ, value_exclude) - winreg.SetValueEx(k, "m_exclude2", 0, winreg.REG_SZ, value_exclude) - except: - raise Exception("BadDePBO", "pboProject not installed correctly, make sure to run it at least once") - - -def color(color): - """Set the color. Works on Win32 and normal terminals.""" - if sys.platform == "win32": - if color == "green": - set_text_attr(FOREGROUND_GREEN | get_text_attr() & 0x0070 | FOREGROUND_INTENSITY) - elif color == "yellow": - set_text_attr(FOREGROUND_YELLOW | get_text_attr() & 0x0070 | FOREGROUND_INTENSITY) - elif color == "red": - set_text_attr(FOREGROUND_RED | get_text_attr() & 0x0070 | FOREGROUND_INTENSITY) - elif color == "blue": - set_text_attr(FOREGROUND_BLUE | get_text_attr() & 0x0070 | FOREGROUND_INTENSITY) - elif color == "reset": - set_text_attr(FOREGROUND_GREY | get_text_attr() & 0x0070) - elif color == "grey": - set_text_attr(FOREGROUND_GREY | get_text_attr() & 0x0070) - else : - if color == "green": - sys.stdout.write('\033[92m') - elif color == "red": - sys.stdout.write('\033[91m') - elif color == "blue": - sys.stdout.write('\033[94m') - elif color == "reset": - sys.stdout.write('\033[0m') - -def print_error(msg): - color("red") - print("ERROR: {}".format(msg)) - color("reset") - global printedErrors - printedErrors += 1 - -def print_green(msg): - color("green") - print(msg) - color("reset") - -def print_blue(msg): - color("blue") - print(msg) - color("reset") - -def print_yellow(msg): - color("yellow") - print(msg) - color("reset") - - -def copy_important_files(source_dir,destination_dir): - originalDir = os.getcwd() - - # Copy importantFiles - try: - print_blue("\nSearching for important files in {}".format(source_dir)) - print("Source_dir: {}".format(source_dir)) - print("Destination_dir: {}".format(destination_dir)) - - for file in importantFiles: - filePath = os.path.join(module_root_parent, file) - if os.path.exists(filePath): - print_green("Copying file => {}".format(filePath)) - shutil.copy(os.path.join(source_dir,filePath), destination_dir) - else: - missingFiles.append("{}".format(filePath)) - print_error("Failed copying file => {}".format(filePath)) - except: - print_error("COPYING IMPORTANT FILES.") - raise - - # Copy all extensions - try: - os.chdir(os.path.join(source_dir)) - print_blue("\nSearching for DLLs in {}".format(os.getcwd())) - filenames = glob.glob("*.dll") + glob.glob("*.so") - - if not filenames: - print ("Empty SET") - - for dll in filenames: - print_green("Copying dll => {}".format(os.path.join(source_dir,dll))) - if os.path.isfile(dll): - shutil.copyfile(os.path.join(source_dir,dll),os.path.join(destination_dir,dll)) - except: - print_error("COPYING DLL FILES.") - raise - finally: - os.chdir(originalDir) - - - -def copy_optionals_for_building(mod,pbos): - src_directories = os.listdir(optionals_root) - current_dir = os.getcwd() - - print_blue("\nChecking optionals folder...") - try: - #special server.pbo processing - files = glob.glob(os.path.join(release_dir, project, "optionals", "*.pbo")) - for file in files: - file_name = os.path.basename(file) - #print ("Adding the following file: {}".format(file_name)) - pbos.append(file_name) - pbo_path = os.path.join(release_dir, project, "optionals", file_name) - sigFile_name = file_name +"."+ key_name + ".bisign" - sig_path = os.path.join(release_dir, project, "optionals", sigFile_name) - if (os.path.isfile(pbo_path)): - print("Moving {} for processing.".format(pbo_path)) - shutil.move(pbo_path, os.path.join(release_dir, project, "addons", file_name)) - - if (os.path.isfile(sig_path)): - #print("Moving {} for processing.".format(sig_path)) - shutil.move(sig_path, os.path.join(release_dir, project, "addons", sigFile_name)) - - except: - print_error("Error in moving") - raise - finally: - os.chdir(current_dir) - - try: - for dir_name in src_directories: - mod.append(dir_name) - #userconfig requires special handling since it is not a PBO source folder. - #CfgConvert fails to build server.pbo if userconfig is not found in P:\ - if (dir_name == "userconfig"): - if (os.path.exists(os.path.join(release_dir, project, "optionals", dir_name))): - shutil.rmtree(os.path.join(release_dir, project, "optionals", dir_name), True) - shutil.copytree(os.path.join(optionals_root,dir_name), os.path.join(release_dir, project, "optionals", dir_name)) - destination = os.path.join(work_drive,dir_name) - else: - destination = os.path.join(module_root,dir_name) - - print("Temporarily copying {} => {} for building.".format(os.path.join(optionals_root,dir_name),destination)) - if (os.path.exists(destination)): - shutil.rmtree(destination, True) - shutil.copytree(os.path.join(optionals_root,dir_name), destination) - except: - print_error("Copy Optionals Failed") - raise - finally: - os.chdir(current_dir) - - -def cleanup_optionals(mod): - print("") - try: - for dir_name in mod: - #userconfig requires special handling since it is not a PBO source folder. - if (dir_name == "userconfig"): - destination = os.path.join(work_drive,dir_name) - else: - destination = os.path.join(module_root,dir_name) - - print("Cleaning {}".format(destination)) - - try: - file_name = "{}{}.pbo".format(pbo_name_prefix,dir_name) - folder= "@{}{}".format(pbo_name_prefix,dir_name) - src_file_path = os.path.join(release_dir, project, "addons", file_name) - dst_file_path = os.path.join(release_dir, project, "optionals",folder,"addons",file_name) - - sigFile_name = "{}.{}.bisign".format(file_name,key_name) - src_sig_path = os.path.join(release_dir, project, "addons", sigFile_name) - dst_sig_path = os.path.join(release_dir, project, "optionals",folder,"addons", sigFile_name) - - - if (os.path.isfile(src_file_path)): - if (os.path.isfile(dst_file_path)): - # print("Cleanuping up old file {}".format(dst_file_path)) - os.remove(dst_file_path); - #print("Preserving {}".format(file_name)) - os.renames(src_file_path,dst_file_path) - if (os.path.isfile(src_sig_path)): - if (os.path.isfile(dst_sig_path)): - # print("Cleanuping up old file {}".format(dst_sig_path)) - os.remove(dst_sig_path); - #print("Preserving {}".format(sigFile_name)) - os.renames(src_sig_path,dst_sig_path) - except FileExistsError: - print_error("{} already exists".format(file_name)) - continue - shutil.rmtree(destination) - - except FileNotFoundError: - print_yellow("{} file not found".format(file_name)) - - except: - print_error("Cleaning Optionals Failed") - raise - - -def purge(dir, pattern, friendlyPattern="files"): - print_green("Deleting {} files from directory: {}".format(friendlyPattern,dir)) - if os.path.exists(dir): - for f in os.listdir(dir): - if re.search(pattern, f): - os.remove(os.path.join(dir, f)) - - -def build_signature_file(file_name): - global key - global dssignfile - global signature_blacklist - ret = 0 - baseFile = os.path.basename(file_name) - #print_yellow("Sig_fileName: {}".format(baseFile)) - if not (baseFile in signature_blacklist): - print("Signing with {}.".format(key)) - ret = subprocess.call([dssignfile, key, file_name]) - if ret == 0: - return True - else: - return False - - -def check_for_obsolete_pbos(addonspath, file): - module = file[len(pbo_name_prefix):-4] - if not os.path.exists(os.path.join(addonspath, module)): - return True - return False - - -def backup_config(module): - #backup original $PBOPREFIX$ - global work_drive - global prefix - - try: - configpath = os.path.join(work_drive, prefix, module, "$PBOPREFIX$") - if os.path.isfile(configpath): - shutil.copyfile(configpath, os.path.join(work_drive, prefix, module, "$PBOPREFIX$.backup")) - else: - print_error("$PBOPREFIX$ Does not exist for module: {}.".format(module)) - - except: - print_error("Error creating backup of $PBOPREFIX$ for module {}.".format(module)) - - return True - -def addon_restore(modulePath): - #restore original $PBOPREFIX$ - try: - if os.path.isfile(os.path.join(modulePath, "$PBOPREFIX$.backup")): - if os.path.isfile(os.path.join(modulePath, "$PBOPREFIX$")): - os.remove(os.path.join(modulePath, "$PBOPREFIX$")) - os.rename(os.path.join(modulePath, "$PBOPREFIX$.backup"), os.path.join(modulePath, "$PBOPREFIX$")) - except: - print_yellow("Some error occurred. Check your addon folder {} for integrity".format(modulePath)) - - return True - - -def get_project_version(version_increments=[]): - global project_version - versionStamp = project_version - #do the magic based on https://github.com/acemod/ACE3/issues/806#issuecomment-95639048 - - try: - scriptModPath = os.path.join(module_root, "main\script_version.hpp") - - if os.path.isfile(scriptModPath): - f = open(scriptModPath, "r") - hpptext = f.read() - f.close() - - if hpptext: - majorText = re.search(r"#define MAJOR (.*\b)", hpptext).group(1) - minorText = re.search(r"#define MINOR (.*\b)", hpptext).group(1) - patchText = re.search(r"#define PATCHLVL (.*\b)", hpptext).group(1) - buildText = re.search(r"#define BUILD (.*\b)", hpptext).group(1) - - # Increment version (reset all below except build) - if version_increments != []: - if "major" in version_increments: - majorText = int(majorText) + 1 - minorText = 0 - patchText = 0 - elif "minor" in version_increments: - minorText = int(minorText) + 1 - patchText = 0 - elif "patch" in version_increments: - patchText = int(patchText) + 1 - - # Always increment build - if "build" in version_increments: - buildText = int(buildText) + 1 - - print_green("Incrementing version to {}.{}.{}.{}".format(majorText,minorText,patchText,buildText)) - with open(scriptModPath, "w", newline="\n") as file: - file.writelines([ - "#define MAJOR {}\n".format(majorText), - "#define MINOR {}\n".format(minorText), - "#define PATCHLVL {}\n".format(patchText), - "#define BUILD {}\n".format(buildText) - ]) - - if majorText: - versionStamp = "{}.{}.{}.{}".format(majorText,minorText,patchText,buildText) - - else: - print_error("A Critical file seems to be missing or inaccessible: {}".format(scriptModPath)) - raise FileNotFoundError("File Not Found: {}".format(scriptModPath)) - - except Exception as e: - print_error("Get_project_version error: {}".format(e)) - print_error("Check the integrity of the file: {}".format(scriptModPath)) - versionStamp = project_version - print_error("Resetting to the default version stamp: {}".format(versionStamp)) - input("Press Enter to continue...") - print("Resuming build...") - - print_yellow("{} VERSION set to {}".format(project.lstrip("@").upper(),versionStamp)) - project_version = versionStamp - return project_version - - -def replace_file(filePath, oldSubstring, newSubstring): - global work_drive - fh, absPath = mkstemp(None, None, work_drive + "temp") - os.close(fh) - with open(absPath, "w", encoding="utf-8") as newFile: - with open(filePath, encoding="utf-8") as oldFile: - for line in oldFile: - newFile.write(line.replace(oldSubstring, newSubstring)) - - newFile.close() - os.remove(filePath) - shutil.move(absPath, filePath) - - -def set_version_in_files(): - newVersion = project_version # MAJOR.MINOR.PATCH.BUILD - newVersionArr = newVersion.split(".") - newVersionShort = ".".join((newVersionArr[0],newVersionArr[1],newVersionArr[2])) # MAJOR.MINOR.PATCH - - # Regex patterns - pattern = re.compile(r"([\d]+\.[\d]+\.[\d]+\.[\d]+)") # MAJOR.MINOR.PATCH.BUILD - patternShort = re.compile(r"([\d]+\.[\d]+\.[\d]+)") # MAJOR.MINOR.PATCH - - # Change versions in files containing version - for i in versionFiles: - filePath = os.path.join(module_root_parent, i) - - try: - # Save the file contents to a variable if the file exists - if os.path.isfile(filePath): - f = open(filePath, "r+", encoding="utf-8") - fileText = f.read() - f.close() - - if fileText: - # Version string files - # Search and save version stamp - versionsFound = re.findall(pattern, fileText) + re.findall(patternShort, fileText) - # Filter out sub-versions of other versions - versionsFound = [j for i, j in enumerate(versionsFound) if all(j not in k for k in versionsFound[i + 1:])] - - # Replace version stamp if any of the new version parts is higher than the one found - for versionFound in versionsFound: - if versionFound: - # Use the same version length as the one found - newVersionUsed = "" # In case undefined - if versionFound.count(".") == newVersion.count("."): - newVersionUsed = newVersion - if versionFound.count(".") == newVersionShort.count("."): - newVersionUsed = newVersionShort - - # Print change and modify the file if changed - if newVersionUsed and versionFound != newVersionUsed: - print_green("Changing version {} => {} in {}".format(versionFound, newVersionUsed, filePath)) - replace_file(filePath, versionFound, newVersionUsed) - except WindowsError as e: - # Temporary file is still "in use" by Python, pass this exception - pass - except Exception as e: - print_error("set_version_in_files error: {}".format(e)) - raise - - return True - - -def stash_version_files_for_building(): - try: - for file in versionFiles: - filePath = os.path.join(module_root_parent, file) - if os.path.exists(filePath): - # Take only file name for stash location if in subfolder (otherwise it gets removed when removing folders from release dir) - if "\\" in file: - count = file.count("\\") - file = file.split("\\", count)[-1] - stashPath = os.path.join(release_dir, file) - print("Temporarily stashing {} => {}.bak for version update".format(filePath, stashPath)) - shutil.copy(filePath, "{}.bak".format(stashPath)) - else: - print_error("Failed temporarily stashing {} for version update".format(filePath)) - missingFiles.append("{}".format(filePath)) - except: - print_error("Stashing version files failed") - raise - - # Set version - set_version_in_files() - return True - - -def restore_version_files(): - try: - print_blue("\nRestoring version files...") - - for file in versionFiles: - filePath = os.path.join(module_root_parent, file) - # Take only file name for stash path if in subfolder (otherwise it gets removed when removing folders from release dir) - if "\\" in file: - count = file.count("\\") - file = file.split("\\", count)[-1] - stashPath = os.path.join(release_dir, file) - if os.path.exists(filePath): - print("Restoring {}".format(filePath)) - shutil.move("{}.bak".format(stashPath), filePath) - except: - print_error("Restoring version files failed") - raise - return True - - -def get_private_keyname(commitID,module="main"): - global key_name - global project_version - - keyName = str("{prefix}{version}-{commit_id}".format(prefix=key_name,version=project_version,commit_id=commitID)) - return keyName - - -def get_commit_ID(): - # Get latest commit ID - global make_root - curDir = os.getcwd() - commit_id = "" - - try: - # Verify if Git repository - gitpath = os.path.join(os.path.dirname(make_root), ".git") - assert os.path.exists(gitpath) - - # Try to get commit ID through Git client - os.chdir(make_root) - commit_id = subprocess.check_output(["git", "rev-parse", "HEAD"]) - commit_id = str(commit_id, "utf-8")[:8] - except FileNotFoundError: - # Try to get commit ID from git files (subprocess failed - eg. no Git client) - head_path = os.path.join(gitpath, "HEAD") - if os.path.exists(head_path): - with open(head_path, "r") as head_file: - branch_path = head_file.readline().split(": ") - - # Commit ID is written in HEAD file directly when in detached state - if len(branch_path) == 1: - commit_id = branch_path[0] - else: - branch_path = branch_path[-1].strip() - ref_path = os.path.join(gitpath, branch_path) - if os.path.exists(ref_path): - with open(ref_path, "r") as ref_file: - commit_id = ref_file.readline() - - if commit_id != "": - commit_id = commit_id.strip()[:8] - else: - raise - except: - # All other exceptions (eg. AssertionException) - if commit_id == "": - raise - finally: - pass - if commit_id == "": - print_error("Failed to determine commit ID - folder is not a Git repository.") - commit_id = "NOGIT" - os.chdir(curDir) - - print_yellow("COMMIT ID set to {}".format(commit_id)) - return commit_id - - -def version_stamp_pboprefix(module,commitID): - ### Update pboPrefix with the correct version stamp. Use commit_id as the build number. - #This function will not handle any $PBOPREFIX$ backup or cleanup. - global work_drive - global prefix - - configpath = os.path.join(work_drive, prefix, module, "$PBOPREFIX$") - - try: - f = open(configpath, "r") - configtext = f.read() - f.close() - - if configtext: - if re.search(r"version=(.*?)$", configtext, re.DOTALL): - if configtext: - configtext = re.sub(r"version=(.*?)$", "version={}\n".format(commitID), configtext, flags=re.DOTALL) - f = open(configpath, "w") - f.write(configtext) - f.close() - else: - os.remove(os.path.join(work_drive, prefix, module, "$PBOPREFIX$")) - os.rename(os.path.join(work_drive, prefix, module, "$PBOPREFIX$.backup"), os.path.join(work_drive, prefix, module, "$PBOPREFIX$")) - else: - if configtext: - #append version info - f = open(configpath, "a") - f.write("\nversion = {}".format(commitID)) - f.close() - else: - os.remove(os.path.join(work_drive, prefix, module, "$PBOPREFIX$")) - os.rename(os.path.join(work_drive, prefix, module, "$PBOPREFIX$.backup"), os.path.join(work_drive, prefix, module, "$PBOPREFIX$")) - except Exception as e: - print_error("Failed to include build number: {}".format(e)) - return False - - return True - - -############################################################################### - - -def main(argv): - """Build an Arma addon suite in a directory from rules in a make.cfg file.""" - print_blue("\nmake.py for Arma, modified for Metis v{}".format(__version__)) - - global project_version - global arma3tools_path - global work_drive - global module_root - global make_root - global release_dir - global module_root_parent - global optionals_root - global key_name - global key - global dssignfile - global prefix - global pbo_name_prefix - global ciBuild - global missingFiles - global failedBuilds - global printedErrors - - printedErrors = 0 - - if sys.platform != "win32": - print_error("Non-Windows platform (Cygwin?). Please re-run from cmd.") - sys.exit(1) - - reg = winreg.ConnectRegistry(None, winreg.HKEY_CURRENT_USER) - try: - k = winreg.OpenKey(reg, r"Software\bohemia interactive\arma 3 tools") - arma3tools_path = winreg.QueryValueEx(k, "path")[0] - winreg.CloseKey(k) - except: - raise Exception("BadTools","Arma 3 Tools are not installed correctly or the P: drive needs to be created.") - - # Default behaviors - test = False # Copy to Arma 3 directory? - arg_modules = False # Only build modules on command line? - use_pboproject = True # Default to pboProject build tool - make_target = "DEFAULT" # Which section in make.cfg to use for the build - new_key = True # Make a new key and use it to sign? - quiet = False # Suppress output from build tool? - - # Parse arguments - if "help" in argv or "-h" in argv or "--help" in argv: - print (""" -make.py [help] [test] [force] [key ] [target ] [release ] - [module name] [module name] [...] -test -- Copy result to Arma 3. -release -- Make archive with . -force -- Ignore cache and build all. -target -- Use rules in make.cfg under heading [] rather than - default [Make] -key -- Use key in working directory with to sign. If it does not - exist, create key. -quiet -- Suppress command line output from build tool. -If module names are specified, only those modules will be built. -Examples: - make.py force test - Build all modules (ignoring cache) and copy the mod folder to the Arma 3 - directory. - make.py mymodule_gun - Only build the module named 'mymodule_gun'. - make.py force key MyNewKey release 1.0 - Build all modules (ignoring cache), sign them with NewKey, and pack them - into a zip file for release with version 1.0. -If a file called $NOBIN$ is found in the module directory, that module will not be binarized. -See the make.cfg file for additional build options. -""") - sys.exit(0) - - if "force" in argv: - argv.remove("force") - force_build = True - else: - force_build = False - - if "test" in argv: - test = True - argv.remove("test") - - if "release" in argv: - make_release_zip = True - argv.remove("release") - else: - make_release_zip = False - - if "target" in argv: - make_target = argv[argv.index("target") + 1] - argv.remove("target") - argv.remove(make_target) - force_build = True - - if "key" in argv: - new_key = True - key_name = argv[argv.index("key") + 1] - argv.remove("key") - argv.remove(key_name) - - if "quiet" in argv: - quiet = True - argv.remove("quiet") - - if "version" in argv: - argv.remove("version") - version_update = True - else: - version_update = False - - version_increments = [] - if "increment_build" in argv: - argv.remove("increment_build") - version_increments.append("build") - if "increment_patch" in argv: - argv.remove("increment_patch") - version_increments.append("patch") - if "increment_minor" in argv: - argv.remove("increment_minor") - version_increments.append("minor") - if "increment_major" in argv: - argv.remove("increment_major") - version_increments.append("major") - - if "ci" in argv: - argv.remove("ci") - ciBuild = True - - # Get the directory the make script is in. - make_root = os.path.dirname(os.path.realpath(__file__)) - make_root_parent = os.path.abspath(os.path.join(os.getcwd(), os.pardir)) - os.chdir(make_root) - - - - cfg = configparser.ConfigParser(); - try: - cfg.read(os.path.join(make_root, "make.cfg")) - - # Project name (with @ symbol) - project = cfg.get(make_target, "project", fallback="@"+os.path.basename(os.getcwd())) - - # BI Tools work drive on Windows - work_drive = cfg.get(make_target, "work_drive", fallback="P:\\") - - # Private key path - key = cfg.get(make_target, "key", fallback=None) - - # Private key creation directory - private_key_path = cfg.get(make_target, "private_key_path", fallback=os.path.join(work_drive, "private_keys")) - - # Project prefix (folder path) - prefix = cfg.get(make_target, "prefix", fallback="") - - # Release archive prefix - zipPrefix = cfg.get(make_target, "zipPrefix", fallback=project.lstrip("@").lower()) - - # Should we autodetect modules on a complete build? - module_autodetect = cfg.getboolean(make_target, "module_autodetect", fallback=True) - - # Manual list of modules to build for a complete build - modules = cfg.get(make_target, "modules", fallback=None) - # Parse it out - if modules: - modules = [x.strip() for x in modules.split(',')] - else: - modules = [] - - # List of directories to ignore when detecting - ignore = [x.strip() for x in cfg.get(make_target, "ignore", fallback="release").split(',')] - - # Which build tool should we use? - build_tool = cfg.get(make_target, "build_tool", fallback="addonbuilder").lower() - - # Release/build directory, relative to script dir - release_dir = cfg.get(make_target, "release_dir", fallback="release") - - #Directory to copy the final built PBO's for a test run. - test_dir = cfg.get(make_target, "test_dir", fallback=os.path.join(os.environ["USERPROFILE"],r"documents\Arma 3")) - - # Project PBO file prefix (files are renamed to prefix_name.pbo) - pbo_name_prefix = cfg.get(make_target, "pbo_name_prefix", fallback=None) - - # Project module Root - module_root_parent = os.path.abspath(os.path.join(os.path.join(work_drive, prefix), os.pardir)) - module_root = cfg.get(make_target, "module_root", fallback=os.path.join(make_root_parent, "addons")) - optionals_root = os.path.join(module_root_parent, "optionals") - extensions_root = os.path.join(module_root_parent, "extensions") - - if (os.path.isdir(module_root)): - os.chdir(module_root) - else: - print_error ("Directory {} does not exist.".format(module_root)) - sys.exit(1) - - commit_id = get_commit_ID() - get_project_version(version_increments) - key_name = versionStamp = get_private_keyname(commit_id) - print_green ("module_root: {}".format(module_root)) - - if (os.path.isdir(optionals_root)): - print_green ("optionals_root: {}".format(optionals_root)) - else: - print("optionals_root does not exist: {}".format(optionals_root)) - - print_green ("release_dir: {}".format(release_dir)) - - except: - raise - print_error("Could not parse make.cfg.") - sys.exit(1) - - # See if we have been given specific modules to build from command line. - if len(argv) > 1 and not make_release_zip: - arg_modules = True - modules = [a for a in argv[1:] if a[0] != "-"] - - # Find the tools we need. - try: - tools = find_bi_tools(work_drive) - addonbuilder = tools[0] - dssignfile = tools[1] - dscreatekey = tools[2] - cfgconvert = tools[3] - - except: - print_error("Arma 3 Tools are not installed correctly or the P: drive has not been created.") - sys.exit(1) - - if build_tool == "pboproject": - try: - depbo_tools = find_depbo_tools() - - pboproject = depbo_tools["pboProject"] - rapifyTool = depbo_tools["rapify"] - makepboTool = depbo_tools["MakePbo"] - - pboproject_settings() - except: - raise - print_error("Could not find dePBO tools. Download the needed tools from: https://dev.withsix.com/projects/mikero-pbodll/files") - sys.exit(1) - - # Try to open and deserialize build cache file. - try: - cache = {} - with open(os.path.join(make_root, "make.cache"), 'r') as f: - cache_raw = f.read() - - cache = json.loads(cache_raw) - - except: - print ("No cache found.") - cache = {} - - # Check the build version (from main) with cached version - forces a full rebuild when version changes - cacheVersion = "None"; - if 'cacheVersion' in cache: - cacheVersion = cache['cacheVersion'] - - if (project_version != cacheVersion): - cache = {} - print("Reseting Cache {0} to New Version {1}".format(cacheVersion, project_version)) - cache['cacheVersion'] = project_version - - if not os.path.isdir(os.path.join(release_dir, project, "addons")): - try: - os.makedirs(os.path.join(release_dir, project, "addons")) - except: - print_error("Cannot create release directory") - raise - - if not os.path.isdir(os.path.join(release_dir, project, "keys")): - try: - os.makedirs(os.path.join(release_dir, project, "keys")) - except: - print_error("Cannot create release directory") - raise - - failedBuilds = [] - missingFiles = [] - - # Update version stamp in all files that contain it - # Update version only for release if full update not requested (backup and restore files) - print_blue("\nChecking for obsolete version numbers...") - if not version_update: - stash_version_files_for_building() - else: - # Set version - set_version_in_files(); - print("Version in files has been changed, make sure you commit and push the updates!") - - try: - # Temporarily copy optionals_root for building. They will be removed later. - if (os.path.isdir(optionals_root)): - optionals_modules = [] - optional_files = [] - copy_optionals_for_building(optionals_modules,optional_files) - - # Get list of subdirs in make root. - dirs = next(os.walk(module_root))[1] - - # Autodetect what directories to build. - if module_autodetect and not arg_modules: - modules = [] - for path in dirs: - # Any dir that has a config.cpp in its root is an addon to build. - config_path = os.path.join(path, 'config.cpp') - if os.path.isfile(config_path) and not path in ignore: - modules.append(path) - - # Make the key specified from command line if necessary. - if new_key: - if not os.path.isfile(os.path.join(private_key_path, key_name + ".biprivatekey")): - print_yellow("\nRequested key does not exist.") - try: - os.makedirs(private_key_path) - except: - pass - curDir = os.getcwd() - os.chdir(private_key_path) - ret = subprocess.call([dscreatekey, key_name]) # Created in make_root - os.chdir(curDir) - if ret == 0: - print_green("Created: {}".format(os.path.join(private_key_path, key_name + ".biprivatekey"))) - print("Removing any old signature keys...") - purge(os.path.join(module_root, release_dir, project, "addons"), "^.*\.bisign$","*.bisign") - purge(os.path.join(module_root, release_dir, project, "optionals"), "^.*\.bisign$","*.bisign") - purge(os.path.join(module_root, release_dir, project, "keys"), "^.*\.bikey$","*.bikey") - else: - print_error("Failed to create key!") - - - - else: - print_green("\nNOTE: Using key {}".format(os.path.join(private_key_path, key_name + ".biprivatekey"))) - - try: - print("Copying public key to release directory.") - - try: - os.makedirs(os.path.join(module_root, release_dir, project, "keys")) - except: - pass - - # Use biKeyNameAbrev to attempt to minimize problems from this BI Bug REFERENCE: http://feedback.arma3.com/view.php?id=22133 - biKeyNameAbrev = key_name.split("-")[0] - shutil.copyfile(os.path.join(private_key_path, key_name + ".bikey"), os.path.join(module_root, release_dir, project, "keys", "{}.bikey".format(biKeyNameAbrev))) - - except: - print_error("Could not copy key to release directory.") - raise - - key = os.path.join(private_key_path, "{}.biprivatekey".format(key_name)) - - # Remove any obsolete files. - print_blue("\nChecking for obsolete files...") - obsolete_check_path = os.path.join(module_root, release_dir, project,"addons") - for file in os.listdir(obsolete_check_path): - if (file.endswith(".pbo") and os.path.isfile(os.path.join(obsolete_check_path,file))): - if check_for_obsolete_pbos(module_root, file): - fileName = os.path.splitext(file)[0] - print_yellow("Removing obsolete pbo => {}".format(file)) - purge(obsolete_check_path, "{}\..".format(fileName), "{}.*".format(fileName)) - - obsolete_check_path = os.path.join(module_root, release_dir, project) - for file in os.listdir(obsolete_check_path): - if (file.endswith(".dll") and os.path.isfile(os.path.join(obsolete_check_path,file))): - if not os.path.exists(os.path.join(module_root_parent, file)): - print_yellow("Removing obsolete dll => {}".format(file)) - try: - os.remove(os.path.join(obsolete_check_path,file)) - except: - print_error("\nFailed to delete {}".format(os.path.join(obsolete_check_path,file))) - pass - - # For each module, prep files and then build. - print_blue("\nBuilding...") - for module in modules: - print_green("\nMaking {}".format(module + "-"*max(1, (60-len(module))))) - missing = False - sigMissing = False - - # Cache check - if module in cache: - old_sha = cache[module] - else: - old_sha = "" - - # Hash the module - new_sha = get_directory_hash(os.path.join(module_root, module)) - - # Is the pbo or sig file missing? - missing = not os.path.isfile(os.path.join(release_dir, project, "addons", "{}{}.pbo".format(pbo_name_prefix,module))) - sigFile = "{}{}.pbo.{}.bisign".format(pbo_name_prefix,module,key_name) - sigMissing = not os.path.isfile(os.path.join(release_dir, project, "addons", sigFile)) - - if missing: - print_yellow("Missing PBO file {}{}.pbo. Building...".format(pbo_name_prefix,module)) - - # Check if it needs rebuilt - # print ("Hash:", new_sha) - if old_sha == new_sha and not missing: - if not force_build: - print("Module has not changed.") - if sigMissing: - if key: - print("Missing Signature key {}".format(sigFile)) - build_signature_file(os.path.join(module_root, release_dir, project, "addons", "{}{}.pbo".format(pbo_name_prefix,module))) - # Skip everything else - continue - - # Only do this if the project isn't stored directly on the work drive. - # Split the path at the drive name and see if they are on the same drive (usually P:) - if os.path.splitdrive(module_root)[0] != os.path.splitdrive(work_drive)[0]: - try: - # Remove old work drive version (ignore errors) - shutil.rmtree(os.path.join(work_drive, prefix, module), True) - - # Copy module to the work drive - shutil.copytree(module, os.path.join(work_drive, prefix, module)) - - except: - raise - print_error("Could not copy module to work drive. Does the module exist?") - input("Press Enter to continue...") - print("Resuming build...") - continue - #else: - #print("WARNING: Module is stored on work drive ({}).".format(work_drive)) - - try: - # Remove the old pbo, key, and log - old = os.path.join(module_root, release_dir, project, "addons", "{}{}".format(pbo_name_prefix,module)) + "*" - files = glob.glob(old) - for f in files: - os.remove(f) - - if pbo_name_prefix: - old = os.path.join(module_root, release_dir, project, "addons", "{}{}".format(pbo_name_prefix,module)) + "*" - files = glob.glob(old) - for f in files: - os.remove(f) - except: - raise - print_error("Could not copy module to work drive. Does the module exist?") - input("Press Enter to continue...") - print("Resuming build...") - continue - - # Build the module into a pbo - print_blue("Building: {}".format(os.path.join(work_drive, prefix, module))) - print_blue("Destination: {}".format(os.path.join(module_root, release_dir, project, "addons"))) - - # Make destination folder (if needed) - try: - os.makedirs(os.path.join(module_root, release_dir, project, "addons")) - except: - pass - - - # Run build tool - build_successful = False - if build_tool == "pboproject": - try: - nobinFilePath = os.path.join(work_drive, prefix, module, "$NOBIN$") - backup_config(module) - - version_stamp_pboprefix(module,commit_id) - - if os.path.isfile(nobinFilePath): - print_green("$NOBIN$ Found. Proceeding with non-binarizing!") - cmd = [makepboTool, "-P","-A","-X=*.backup", os.path.join(work_drive, prefix, module),os.path.join(module_root, release_dir, project,"addons")] - - else: - cmd = [pboproject, "-B", "-P", os.path.join(work_drive, prefix, module), "+Engine=Arma3", "-S", "+Noisy", "+Clean", "-Warnings", "+Mod="+os.path.join(module_root, release_dir, project), "-Key"] - - color("grey") - if quiet: - devnull = open(os.devnull, 'w') - ret = subprocess.call(cmd, stdout=devnull) - devnull.close() - else: - ret = subprocess.call(cmd) - color("reset") - - if ret == 0: - print_green("pboProject return code == {}".format(str(ret))) - # Prettyprefix rename the PBO if requested. - if pbo_name_prefix: - try: - os.rename(os.path.join(module_root, release_dir, project, "addons", "{}.pbo".format(module)), os.path.join(module_root, release_dir, project, "addons", "{}{}.pbo".format(pbo_name_prefix,module))) - except: - raise - print_error("Could not rename built PBO with prefix.") - # Sign result - if (key and not "{}{}.pbo".format(pbo_name_prefix,module) in signature_blacklist): - print("Signing with {}.".format(key)) - if pbo_name_prefix: - ret = subprocess.call([dssignfile, key, os.path.join(module_root, release_dir, project, "addons", "{}{}.pbo".format(pbo_name_prefix,module))]) - else: - ret = subprocess.call([dssignfile, key, os.path.join(module_root, release_dir, project, "addons", "{}.pbo".format(module))]) - - if ret == 0: - build_successful = True - else: - build_successful = True - - if not build_successful: - print_error("pboProject return code == {}".format(str(ret))) - print_error("Module not successfully built/signed. Check your {}temp\{}_packing.log for more info.".format(work_drive,module)) - print ("Resuming build...") - failedBuilds.append("{}".format(module)) - continue - - # Back to the root - os.chdir(module_root) - - except: - raise - print_error("Could not run Addon Builder.") - input("Press Enter to continue...") - print ("Resuming build...") - continue - finally: - addon_restore(os.path.join(work_drive, prefix, module)) - - elif build_tool== "addonbuilder": - # Detect $NOBIN$ and do not binarize if found. - if os.path.isfile(os.path.join(work_drive, prefix, module, "$NOBIN$")): - do_binarize = False - print("$NOBIN$ file found in module, packing only.") - else: - do_binarize = True - try: - # Call AddonBuilder - os.chdir("P:\\") - - cmd = [addonbuilder, os.path.join(work_drive, prefix, module), os.path.join(make_root, release_dir, project, "addons"), "-clear", "-project="+work_drive] - if not do_binarize: - cmd.append("-packonly") - - if quiet: - previousDirectory = os.getcwd() - os.chdir(arma3tools_path) - devnull = open(os.devnull, 'w') - ret = subprocess.call(cmd, stdout=devnull) - devnull.close() - os.chdir(previousDirectory) - else: - previousDirectory = os.getcwd() - os.chdir(arma3tools_path) - print_error("Current directory - {}".format(os.getcwd())) - ret = subprocess.call(cmd) - os.chdir(previousDirectory) - print_error("Current directory - {}".format(os.getcwd())) - color("reset") - print_green("completed") - # Prettyprefix rename the PBO if requested. - if pbo_name_prefix: - try: - os.rename(os.path.join(make_root, release_dir, project, "addons", "{}.pbo".format(module)), os.path.join(make_root, release_dir, project, "addons", "{}{}.pbo".format(pbo_name_prefix,module))) - except: - raise - print_error("Could not rename built PBO with prefix.") - - if ret == 0: - # Sign result - - #print_yellow("Sig_fileName: ace_{}.pbo".format(module)) - if (key and not "{}{}.pbo".format(pbo_name_prefix,module) in signature_blacklist) : - print("Signing with {}.".format(key)) - if pbo_name_prefix: - ret = subprocess.call([dssignfile, key, os.path.join(make_root, release_dir, project, "addons","{}{}.pbo".format(pbo_name_prefix,module))]) - else: - ret = subprocess.call([dssignfile, key, os.path.join(make_root, release_dir, project, "addons", "{}.pbo".format(module))]) - - if ret == 0: - build_successful = True - else: - build_successful = True - - if not build_successful: - print_error("Module not successfully built. Check your {}temp\{}_packing.log for more info.".format(work_drive,module)) - - # Back to the root - os.chdir(make_root) - - except: - raise - print_error("Could not run Addon Builder.") - input("Press Enter to continue...") - print ("Resuming build...") - continue - - else: - print_error("Unknown build_tool {}!".format(build_tool)) - - # Update the hash for a successfully built module - if build_successful: - cache[module] = new_sha - - except Exception as e: - print_yellow("Cancel or some error detected: {}".format(e)) - - - finally: - copy_important_files(module_root_parent,os.path.join(release_dir, project)) - if (os.path.isdir(optionals_root)): - cleanup_optionals(optionals_modules) - if not version_update: - restore_version_files() - - # Done building all modules! - - # Write out the cache state - cache_out = json.dumps(cache) - with open(os.path.join(make_root, "make.cache"), 'w') as f: - f.write(cache_out) - - # Delete the pboproject temp files if building a release. - if make_release_zip and build_tool == "pboproject": - try: - shutil.rmtree(os.path.join(release_dir, project, "temp"), True) - except: - print_error("ERROR: Could not delete pboProject temp files.") - - # Make release - if make_release_zip: - release_name = "{}_{}".format(zipPrefix, project_version.rsplit(".", 1)[0]) - - try: - # Delete all log files - for root, dirs, files in os.walk(os.path.join(release_dir, project, "addons")): - for currentFile in files: - if currentFile.lower().endswith("log"): - os.remove(os.path.join(root, currentFile)) - - # Remove all zip files from release folder to prevent zipping the zip - for file in os.listdir(release_dir): - if file.endswith(".zip"): - os.remove(os.path.join(release_dir, file)) - - # Create a zip with the contents of release folder in it - print_blue("\nMaking release: {}.zip ...".format(release_name)) - print("Packing...") - release_zip = shutil.make_archive("{}".format(release_name), "zip", release_dir) - - # Move release zip to release folder - shutil.copy(release_zip, release_dir) - os.remove(release_zip) - except: - raise - print_error("Could not make release.") - - # Copy to Arma 3 folder for testing - if test: - print_blue("\nCopying to Arma 3.") - - if sys.platform == "win32": - reg = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) - try: - k = winreg.OpenKey(reg, r"SOFTWARE\Wow6432Node\Bohemia Interactive\Arma 3") - a3_path = winreg.EnumValue(k, 1)[1] - winreg.CloseKey(k) - except: - print_error("Could not find Arma 3's directory in the registry.") - else: - a3_path = cygwin_a3path - - print_yellow("Path from the registry => {}".format(a3_path)) - a3_path = test_dir - - print_yellow("Copying build files to {}".format(a3_path)) - - if os.path.exists(a3_path): - try: - shutil.rmtree(os.path.join(a3_path, project), True) - shutil.copytree(os.path.join(module_root, release_dir, project), os.path.join(a3_path, project)) - except: - print_error("Could not copy files. Is Arma 3 running?") - - tracedErrors = len(failedBuilds) + len(missingFiles) - if printedErrors > 0: # printedErrors includes tracedErrors - printedOnlyErrors = printedErrors - tracedErrors - print() - print_error("Failed with {} errors.".format(printedErrors)) - if len(failedBuilds) > 0: - for failedBuild in failedBuilds: - print("- {} build failed!".format(failedBuild)) - if len(missingFiles) > 0: - for missingFile in missingFiles: - print("- {} not found!".format(missingFile)) - if printedOnlyErrors > 0: - print_yellow("- {} untraced error(s)!".format(printedOnlyErrors)) - else: - print_green("\nCompleted with 0 errors.") - - -if __name__ == "__main__": - start_time = timeit.default_timer() - main(sys.argv) - d,h,m,s = Fract_Sec(timeit.default_timer() - start_time) - print("\nTotal Program time elapsed: {0:2}h {1:2}m {2:4.5f}s".format(h,m,s)) - - if ciBuild: - if len(failedBuilds) > 0: - sys.exit(1) - else: - sys.exit(0) - - input("Press Enter to continue...") diff --git a/tools/setup.bat b/tools/setup.bat index 3323a12..8d7245a 100644 --- a/tools/setup.bat +++ b/tools/setup.bat @@ -1,28 +1,16 @@ ;@Findstr -bv ;@F "%~f0" | powershell -Command - & pause & goto:eof -# Unzip backwards compatibility (Windows 8) -Add-Type -AssemblyName System.IO.Compression.FileSystem -function Unzip { - param([string]$zipfile, [string]$outpath) - - [System.IO.Compression.ZipFile]::ExtractToDirectory($zipfile, $outpath) -} - +Write-Output "=> Downloading ..." [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 -$client = New-Object Net.WebClient - -Write-Output "=> Downloading tools ..." -$client.DownloadFile("http://dev.idi-systems.com/tools/acre2_tools_user.zip", "acre2_tools_user.zip") -$client.dispose() -Write-Output "=> Cleaning old ..." -Remove-Item "..\hemtt.exe" -ErrorAction Ignore -Remove-Item "..\ArmaScriptCompiler.exe" -ErrorAction Ignore +$url = "https://github.com/BrettMayson/HEMTT/releases/latest/download/windows-x64.zip" +(New-Object Net.WebClient).DownloadFile($url, "hemtt.zip"); Write-Output "$url => hemtt.zip" -Write-Output "=> Extracting ..." -Unzip "acre2_tools_user.zip" "..\." -Remove-Item "acre2_tools_user.zip" +Write-Output "`n=> Extracting ..." +Expand-Archive -Path "hemtt.zip" -DestinationPath "..\." -Force; Write-Output "hemtt.zip" +Remove-Item "hemtt.zip" -Remove-Item "..\hemtt" -ErrorAction Ignore +Write-Output "`n=> Verifying ..." +Start-Process -FilePath ..\hemtt.exe -ArgumentList --version -NoNewWindow -Wait -Write-Output "=> Tools successfully installed to project!" +Write-Output "`nTools successfully installed to project!"