├── .github
├── FUNDING.yml
└── workflows
│ ├── build.yml
│ ├── release.yml
│ ├── unex_check.yml
│ └── update_info.yml
├── .gitignore
├── .gitmodules
├── LICENSE
├── README.md
├── README_zh.md
├── Third_Party_LICENSES
├── build.lua
├── metadata.json
├── scripts
├── dofiles
│ ├── set_time_to_noon.lua
│ ├── suicide.lua
│ └── to-the-moon.lua
├── init.lua
├── lang
│ ├── de_de.lua
│ ├── en_us.lua
│ ├── example.lua
│ ├── fr_fr.lua
│ ├── ja_jp.lua
│ ├── lang.lua
│ ├── pt_br.lua
│ ├── ro_ro.lua
│ ├── ru_ru.lua
│ ├── tr_tc.lua
│ ├── zh_cn.lua
│ └── zh_tw.lua
└── modules
│ ├── CETMM.lua
│ ├── backend.lua
│ ├── core
│ ├── class
│ │ ├── dofile.lua
│ │ └── path.lua
│ └── helper.lua
│ ├── dofiles.lua
│ ├── event.lua
│ ├── gui
│ ├── dpi.lua
│ ├── init.lua
│ ├── themeSys.lua
│ ├── themes
│ │ ├── baseTheme.lua
│ │ ├── default.lua
│ │ ├── ua_special.lua
│ │ └── white.lua
│ ├── widgets
│ │ ├── btnToggle.lua
│ │ ├── button.lua
│ │ └── init.lua
│ ├── window.lua
│ └── windows
│ │ ├── init.lua
│ │ └── uninstall.lua
│ ├── hotkeys.lua
│ ├── i18n
│ ├── README.md
│ ├── init.lua
│ ├── interpolate.lua
│ ├── plural.lua
│ ├── variants.lua
│ └── version.lua
│ ├── locale.lua
│ ├── options.lua
│ └── types.lua
├── src
├── CETMM
│ ├── CETMM.cpp
│ ├── CETMM.h
│ ├── EXT
│ │ ├── Auth.cpp
│ │ ├── Auth.h
│ │ ├── CETMMEXT.cpp
│ │ ├── CETMMEXT.h
│ │ ├── Misc.cpp
│ │ ├── Misc.h
│ │ ├── Mod.cpp
│ │ ├── Mod.h
│ │ ├── Mods.cpp
│ │ ├── Mods.h
│ │ ├── TypeRegister.h
│ │ ├── Uninstall.cpp
│ │ └── Uninstall.h
│ ├── Logger.cpp
│ ├── Logger.h
│ ├── Utilities.cpp
│ ├── Utilities.h
│ ├── dllmain.cpp
│ └── pch.h
├── Common
│ ├── Paths.cpp
│ ├── Paths.h
│ └── Version.h.in
└── Installer
│ ├── Installer.cpp
│ ├── Installer.h
│ ├── Logger.cpp
│ ├── Logger.h
│ ├── Update.cpp
│ ├── Update.h
│ ├── dllmain.cpp
│ └── pch.h
├── vendor
└── bin2cpp
│ ├── LICENSE
│ ├── README.md
│ └── bin2cpp.exe
└── xmake.lua
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | ko_fi: mingm
2 | custom: buymeacoffee.com/mingm
3 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: Build
2 | on:
3 | push:
4 | branches: [ master ]
5 | paths:
6 | - 'scripts/**'
7 | - 'src/**'
8 | - 'vendor/**'
9 | - '**.lua'
10 | - '.github/workflows/build.yml'
11 | pull_request:
12 | branches: [ master ]
13 |
14 | jobs:
15 | build:
16 | runs-on: windows-latest
17 | steps:
18 | - uses: actions/checkout@v2
19 | with:
20 | fetch-depth: 0
21 | submodules: recursive
22 |
23 | - name: Setup xmake
24 | uses: xmake-io/github-action-setup-xmake@v1
25 |
26 | - name: Update xmake repository and install dependencies
27 | run: |
28 | xmake.exe repo --update
29 | xmake.exe q --yes
30 |
31 | - name: Build and Package
32 | run: |
33 | xmake.exe build cet_mod_manager
34 | xmake.exe embed
35 | xmake.exe package installer
36 |
37 | - name: Upload Artifacts
38 | uses: actions/upload-artifact@v2
39 | with:
40 | name: package
41 | path: build/package/
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 | on:
3 | release:
4 | types: [published]
5 |
6 | jobs:
7 | build:
8 | runs-on: windows-latest
9 | steps:
10 | - uses: actions/checkout@v2
11 | with:
12 | fetch-depth: 0
13 | submodules: recursive
14 |
15 | - name: Setup xmake
16 | uses: xmake-io/github-action-setup-xmake@v1
17 |
18 | - name: Update xmake repository and install dependencies
19 | run: |
20 | xmake.exe repo --update
21 | xmake.exe q --yes
22 |
23 | - name: Build and Package
24 | run: |
25 | xmake.exe build cet_mod_manager
26 | xmake.exe embed
27 | xmake.exe package installer
28 |
29 | - name: Upload Artifacts
30 | uses: actions/upload-artifact@v2
31 | with:
32 | name: package
33 | path: build/package/
34 |
35 | release-github:
36 | runs-on: ubuntu-latest
37 | needs: build
38 | steps:
39 | - uses: actions/checkout@v2
40 |
41 | - name: Set environment variables
42 | uses: antifree/json-to-variables@v1.0.1
43 | with:
44 | filename: metadata.json
45 | prefix: META
46 |
47 | - name: Download Artifact
48 | uses: actions/download-artifact@v2.0.9
49 |
50 | - name: Create zip
51 | uses: ihiroky/archive-action@v1
52 | with:
53 | root_dir: "package/"
54 | file_path: "${{ env.META_MOD_FILE_NAME }}_${{ github.event.release.tag_name }}.zip"
55 |
56 | - name: Upload to Github Release
57 | uses: ncipollo/release-action@v1
58 | with:
59 | allowUpdates: true
60 | omitNameDuringUpdate: true
61 | omitBodyDuringUpdate: true
62 | artifacts: "${{ env.META_MOD_FILE_NAME }}_${{ github.event.release.tag_name }}.zip"
63 | token: ${{ secrets.GITHUB_TOKEN }}
64 | prerelease: ${{ github.event.release.prerelease }}
65 |
66 | release-nexus:
67 | runs-on: ubuntu-latest
68 | needs: build
69 | steps:
70 | - uses: actions/checkout@v2
71 |
72 | - name: Update release note
73 | uses: jossef/action-set-json-field@v1
74 | with:
75 | file: metadata.json
76 | field: UNEX_FILEDESCRIPTION
77 | value: ${{ github.event.release.body }}
78 |
79 | - name: Set environment variables
80 | uses: antifree/json-to-variables@v1.0.1
81 | with:
82 | filename: metadata.json
83 | prefix: META
84 |
85 | - name: Download Artifact
86 | uses: actions/download-artifact@v2.0.9
87 |
88 | - name: Create zip
89 | uses: ihiroky/archive-action@v1
90 | with:
91 | root_dir: "package/"
92 | file_path: "${{ env.META_MOD_FILE_NAME }}_${{ github.event.release.tag_name }}.zip"
93 |
94 | - name: Setup dotnet
95 | uses: actions/setup-dotnet@v1
96 | with:
97 | dotnet-version: '3.1.x'
98 |
99 | - name: Upload to Nexus Mods
100 | env:
101 | UNEX_APIKEY: ${{ secrets.UNEX_APIKEY }}
102 | UNEX_COOKIES: ${{ secrets.UNEX_COOKIES }}
103 | UNEX_GAME: ${{ env.META_UNEX_GAME }}
104 | UNEX_MODID: ${{ env.META_UNEX_MODID }}
105 | UNEX_PREVIOUSFILE: auto
106 | UNEX_FILENAME: ${{ env.META_UNEX_FILENAME }}
107 | UNEX_FILEDESCRIPTION: ${{ github.event.release.body }}
108 | UNEX_FILEPATH: ${{ env.META_MOD_FILE_NAME }}_${{ github.event.release.tag_name }}.zip
109 | UNEX_VERSION: ${{ github.event.release.tag_name }}
110 | run: |
111 | dotnet tool install -g NexusUploader
112 | unex upload $UNEX_MODID $UNEX_FILEPATH -v $UNEX_VERSION
113 |
114 | release-3dm:
115 | runs-on: ubuntu-latest
116 | needs: build
117 | steps:
118 | - uses: actions/checkout@v2
119 |
120 | - name: Set environment variables
121 | uses: antifree/json-to-variables@v1.0.1
122 | with:
123 | filename: metadata.json
124 | prefix: META
125 |
126 | - name: Download Artifact
127 | uses: actions/download-artifact@v2.0.9
128 |
129 | - name: Upload to 3DM Mods
130 | id: upload_3dm
131 | uses: GlossMod/ActionUpdateMod@v1
132 | with:
133 | appid: ${{ secrets.APPID_3DM }}
134 | appkey: ${{ secrets.APPKEY_3DM }}
135 | id: ${{ env.META_3DM_MOD_ID }}
136 | title: ${{ env.META_3DM_MOD_TITLE }}
137 | version: ${{ github.event.release.tag_name }}
138 | tags: ${{ env.META_3DM_MOD_TAGS }}
139 | desc: ${{ env.META_3DM_MOD_DESC }}
140 | content: ${{ env.META_3DM_MOD_CONTENT }}
141 | file: package/
142 |
143 | - name: Check 3DM upload status
144 | run: "echo 'Code: ${{ steps.test3.outputs.code }}\tMessage: ${{ steps.test3.outputs.msg }}'"
145 |
--------------------------------------------------------------------------------
/.github/workflows/unex_check.yml:
--------------------------------------------------------------------------------
1 | # This is a basic workflow to help you get started with Actions
2 |
3 | name: UNEX Check
4 |
5 | # Controls when the action will run.
6 | on:
7 |
8 | workflow_dispatch:
9 |
10 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
11 | jobs:
12 | # This workflow contains a single job called "build"
13 | check:
14 | # The type of runner that the job will run on
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v2
18 |
19 | - name: Setup dotnet
20 | uses: actions/setup-dotnet@v1
21 | with:
22 | dotnet-version: '3.1.x'
23 |
24 | - name: Check
25 | env:
26 | UNEX_APIKEY: ${{ secrets.UNEX_APIKEY }}
27 | UNEX_COOKIES: ${{ secrets.UNEX_COOKIES }}
28 | run: |
29 | dotnet tool install -g NexusUploader
30 | unex check
31 |
--------------------------------------------------------------------------------
/.github/workflows/update_info.yml:
--------------------------------------------------------------------------------
1 | name: Update Mod info
2 |
3 | on:
4 | workflow_dispatch:
5 |
6 | jobs:
7 | update-3dm:
8 | runs-on: ubuntu-latest
9 | steps:
10 | - uses: actions/checkout@v2
11 |
12 | - name: Set environment variables
13 | uses: antifree/json-to-variables@v1.0.1
14 | with:
15 | filename: metadata.json
16 | prefix: META
17 |
18 | - name: Update infomation on 3DM Mods
19 | id: update_3dm
20 | uses: Nats-ji/3dm-release-action@master
21 | with:
22 | appid: ${{ secrets.APPID_3DM }}
23 | appkey: ${{ secrets.APPKEY_3DM }}
24 | mod_id: ${{ env.META_3DM_MOD_ID }}
25 | mod_title: ${{ env.META_3DM_MOD_TITLE }}
26 | mod_tags: ${{ env.META_3DM_MOD_TAGS }}
27 | mod_desc: ${{ env.META_3DM_MOD_DESC }}
28 | mod_content: ${{ env.META_3DM_MOD_CONTENT }}
29 |
30 | - name: Check 3DM update status
31 | run: echo ${{ steps.update_3dm.outputs.RESPONSE }}
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # dev
2 | .vscode/
3 | .xmake/
4 | build/
5 |
6 | cet_mod_manager.code-workspace
7 |
8 | src/Common/Version.h
9 | scripts/modules/version.lua
10 | src/Installer/embeds/
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "vendor/RED4ext.SDK"]
2 | path = vendor/RED4ext.SDK
3 | url = https://github.com/WopsS/RED4ext.SDK.git
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | [![github][github-badge]][github-link] [![build][build-badge]][build-link] ![license][license-badge] [![release][release-badge]][release-link] [![nexus][nexus-badge]][nexus-link] [![3dm][3dm-badge]][3dm-link]
6 |
7 | # Cyber Engine Tweaks Mod Manager
8 |
9 | ## Features
10 |
11 | Download: https://github.com/Nats-ji/CET-Mod-Manager/releases/
12 |
13 | Nexusmods: https://www.nexusmods.com/cyberpunk2077/mods/895
14 |
15 | - A Mod Manager for CyberEngineTweaks based mods
16 | - Enable/Disable CyberEngineTweaks based mods inside game with a single click
17 | - Open the interface by pressing the hotkey you bound in CET
18 |
19 |
20 | 
21 |
22 | ## Installation
23 |
24 | This mod requires:
25 | 1. the latest version of **Cyber Engine Tweaks** Mod. [[nexusmods]](https://www.nexusmods.com/cyberpunk2077/mods/107) | [[github]](https://github.com/yamashi/CyberEngineTweaks)
26 | 2. the latest version of **Red4EXT**. [[nexusmods]](https://www.nexusmods.com/cyberpunk2077/mods/2380) | [[github]](https://github.com/WopsS/RED4ext)
27 |
28 | Extract `bin` into the root directory of Cyberpunk2077's install path.
29 |
30 | Restart the game.
31 |
32 | ## Usage
33 |
34 | 1. To use it, you just simply press `hotkey` you bound to open the inertface.
35 |
36 | 2. Press the button `Scan` to scan your installed mods.
37 |
38 | 3. Tick/untick the checkbox in front of the mod name to enable/disable them.
39 |
40 | 4. Press the `Reload ALL Mods` button on the console to reload the mods.
41 |
42 | ### Change language
43 | Check this [guide](https://wiki.redmodding.org/cyber-engine-tweaks/getting-started/configuration/change-font-and-font-size#how-to-display-non-english-characters) for more information.
44 |
45 | ### API (deprecated)
46 |
47 | 1. To use the API (currently only supports CET) to query the mod list
48 | ```lua
49 | -- returns a table
50 | modlist = GetMod("cet_mod_manager").GetModList()
51 |
52 | -- print the mod list in console
53 | GetMod("cet_mod_manager").PrintModList()
54 | ```
55 | 2. Return format by the API
56 | ```lua
57 | {
58 | archive = { "a", "list", "of", "mods"},
59 | asi = { "a", "list", "of", "mods"},
60 | cet = { "a", "list", "of", "mods"},
61 | red4ext = { "a", "list", "of", "mods"},
62 | redscript = { "a", "list", "of", "mods"}
63 | }
64 | ```
65 |
66 | ## Uninstallation
67 |
68 | 1. Before you uninstall this mod, make sure you have **re-enabled** all the mods.
69 |
70 | 2. Remove `cet_mod_manager.asi` from `\Cyberpunk 2077\bin\x64\plugins\`
71 |
72 | ## Translations
73 | - English
74 | - Simplified Chinese (Translator: Nats-ji)
75 | - Traditional Chinese (Translator: Nats-ji)
76 | - Japanese (Translator: Nats-ji)
77 | - German (Translator: keanuWheeze)
78 | - Russian (Translator: vanja-san)
79 | - Turkish (Translator: sebepne)
80 | - Romanian (Translator: Maddmaniak)
81 | - Brazilian Portuguese (Translator: mathfelin)
82 | - French (Translator : ReActif)
83 |
84 | ## Credits
85 |
86 | - yamashi's CyberEngineTweaks https://github.com/yamashi?tab=repositories
87 | - WhySoSerious for answering every question I had about lua https://github.com/WSSDude420
88 | - Development Team behind CyberEngineTweaks and and RED4extSDK
89 | - CP77 Modding Tools Discord Community https://discord.gg/cp77modding
90 | - And people who translated for this project.
91 |
92 | [github-badge]: https://img.shields.io/badge/source-Github-red?style=social&logo=github
93 | [github-link]: https://github.com/Nats-ji/CET-Mod-Manager
94 | [build-badge]: https://img.shields.io/github/actions/workflow/status/Nats-ji/CET-Mod-Manager/build.yml?branch=master
95 | [build-link]: https://github.com/Nats-ji/CET-Mod-Manager/actions/workflows/build.yml
96 | [license-badge]: https://img.shields.io/github/license/Nats-ji/CET-Mod-Manager
97 | [release-badge]: https://img.shields.io/github/v/release/Nats-ji/CET-Mod-Manager?include_prereleases
98 | [release-link]: https://github.com/Nats-ji/CET-Mod-Manager/releases/latest
99 | [nexus-badge]: https://img.shields.io/badge/download-Nexus%20Mods-orange
100 | [nexus-link]: https://www.nexusmods.com/cyberpunk2077/mods/895
101 | [3dm-badge]: https://img.shields.io/badge/download-3DM%20Mods-blueviolet
102 | [3dm-link]: https://mod.3dmgame.com/mod/172144
103 |
--------------------------------------------------------------------------------
/README_zh.md:
--------------------------------------------------------------------------------
1 | [![github][github-badge]][github-link] [![build][build-badge]][build-link] ![license][license-badge] [![release][release-badge]][release-link] [![nexus][nexus-badge]][nexus-link] [![3dm][3dm-badge]][3dm-link]
2 |
3 | ### 现已支持中文,需要把控制台的默认字体改成中文字体
4 | 点按钮 ! 选择语言。
5 |
6 | 
7 |
8 | # 功能
9 | - 在游戏中启用或者禁用基于Cyber Engine Tweaks的mod
10 | - 用不到的mod在游戏中一键关闭
11 | - 可以直接从mod管理器运行使用`dofile()`命令的脚本mod
12 |
13 |  
14 |
15 | # 安装
16 | 1. 首先安装最新版 [Cyber Engine Tweaks](https://www.nexusmods.com/cyberpunk2077/mods/107)
17 | 2. 其次安装最新版 [Red4EXT](https://www.nexusmods.com/cyberpunk2077/mods/2380)
18 | 3. 解压后把 `bin` 文件夹放到游戏安装主路径
19 |
20 | - 安装后目录应该像这样
21 |
22 | Cyberpunk 2077
23 | └── bin
24 | └── x64
25 | └── plugins
26 | ├── cet_mod_manager.asi
27 | └── cyber_engine_tweaks.asi
28 |
29 |
30 | # 使用方法
31 | 1. 在游戏中按绑定的热键打开Mod管理界面
32 | 2. 点`扫描`按钮扫描安装的mod (如果你的游戏是全屏模式的话会弹到桌面,再切换回游戏就行了,把游戏改成全屏无边框窗口的话就不会弹到桌面了)
33 | 3. 把不需要的mod勾掉
34 | 4. 点控制台的`Reload All Mods`按钮以重载Cyber Engine Tweaks
35 | 5. 在游戏中按绑定的热键可以打开脚本Mod运行界面
36 | 6. 要从mod管理器运行脚本mod的话,把脚本文件直接放到 `cet_mod_manager` 文件夹里的`dofiles`文件夹(点mod管理器里的`Dofile文件夹`按钮可以直接打开)。
37 | 7. 点左上角的`Dofile Mods`按钮进入脚本mod的列表。
38 | 8. 点mod前面的`运行`按钮就可以直接运行了。
39 | 9. 自带了几个示例脚本,不需要的话自行删除即可。
40 |
41 | # 卸载
42 | 1. 先把所有mod都重新启用
43 | 2. 删除 `<赛博朋克2077的安装路径>/bin/x64/plugins/` 里的 `cet_mod_manager.asi`
44 |
45 | # 目前支持的语言
46 | - 英文
47 | - 简体中文(翻译者:Ming)
48 | - 繁体中文(翻译者:Ming)
49 | - 日语(翻译者:Ming)
50 | - 德语(翻译者:keanuWheeze)
51 | - 俄语(翻译者:vanja-san)
52 | - 土耳其语(翻译者:sebepne)
53 | - 罗马尼亚语(翻译者:Maddmaniak)
54 | - 葡萄牙语(巴西)(翻译者:mathfelin)
55 | - 法语(翻译者:ReActif)
56 |
57 | # Github
58 | https://github.com/Nats-ji/CET-Mod-Manager
59 |
60 | [github-badge]: https://img.shields.io/badge/source-Github-red?style=social&logo=github
61 | [github-link]: https://github.com/Nats-ji/CET-Mod-Manager
62 | [build-badge]: https://img.shields.io/github/workflow/status/Nats-ji/CET-Mod-Manager/Build?event=push
63 | [build-link]: https://github.com/Nats-ji/CET-Mod-Manager/actions/workflows/build.yml
64 | [license-badge]: https://img.shields.io/github/license/Nats-ji/CET-Mod-Manager
65 | [release-badge]: https://img.shields.io/github/v/release/Nats-ji/CET-Mod-Manager?include_prereleases
66 | [release-link]: https://github.com/Nats-ji/CET-Mod-Manager/releases/latest
67 | [nexus-badge]: https://img.shields.io/badge/download-Nexus%20Mods-orange
68 | [nexus-link]: https://www.nexusmods.com/cyberpunk2077/mods/895
69 | [3dm-badge]: https://img.shields.io/badge/download-3DM%20Mods-blueviolet
70 | [3dm-link]: https://mod.3dmgame.com/mod/172144
--------------------------------------------------------------------------------
/Third_Party_LICENSES:
--------------------------------------------------------------------------------
1 | i18n.lua
2 |
3 | MIT License Terms
4 | =================
5 |
6 | Copyright (c) 2012 Enrique García Cota.
7 |
8 | Permission is hereby granted, free of charge, to any person obtaining a copy of
9 | this software and associated documentation files (the "Software"), to deal in
10 | the Software without restriction, including without limitation the rights to
11 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 | of the Software, and to permit persons to whom the Software is furnished to do
13 | so, subject to the following conditions:
14 |
15 | The above copyright notice and this permission notice shall be included in all
16 | copies or substantial portions of the Software.
17 |
18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | SOFTWARE.
25 |
26 | *******************************************************************************
27 |
28 | spdlog
29 |
30 | The MIT License (MIT)
31 |
32 | Copyright (c) 2016 Gabi Melman.
33 |
34 | Permission is hereby granted, free of charge, to any person obtaining a copy
35 | of this software and associated documentation files (the "Software"), to deal
36 | in the Software without restriction, including without limitation the rights
37 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
38 | copies of the Software, and to permit persons to whom the Software is
39 | furnished to do so, subject to the following conditions:
40 |
41 | The above copyright notice and this permission notice shall be included in
42 | all copies or substantial portions of the Software.
43 |
44 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
45 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
46 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
47 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
48 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
49 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
50 | THE SOFTWARE.
51 |
52 | -- NOTE: Third party dependency used by this software --
53 | This software depends on the fmt lib (MIT License),
54 | and users must comply to its license:
55 | https://github.com/fmtlib/fmt/blob/master/LICENSE.rst
56 |
57 | *******************************************************************************
58 |
59 | fmt
60 |
61 | Copyright (c) 2012 - present, Victor Zverovich
62 |
63 | Permission is hereby granted, free of charge, to any person obtaining a copy of
64 | this software and associated documentation files (the "Software"), to deal in the
65 | Software without restriction, including without limitation the rights to use,
66 | copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
67 | Software, and to permit persons to whom the Software is furnished to do so,
68 | subject to the following conditions:
69 |
70 | The above copyright notice and this permission notice shall be included in all
71 | copies or substantial portions of the Software.
72 |
73 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
74 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
75 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
76 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
77 | AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
78 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
79 |
80 | --- Optional exception to the license ---
81 |
82 | As an exception, if, as a result of your compiling your source code, portions of
83 | this Software are embedded into a machine-executable object form of such source
84 | code, you may redistribute such embedded portions in such object form without
85 | including the above copyright and permission notices.
86 |
87 | *******************************************************************************
88 |
89 | bin2cpp
90 |
91 | MIT License
92 |
93 | Copyright (c) 2018 Antoine Beauchamp
94 |
95 | Permission is hereby granted, free of charge, to any person obtaining a copy
96 | of this software and associated documentation files (the "Software"), to deal
97 | in the Software without restriction, including without limitation the rights
98 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
99 | copies of the Software, and to permit persons to whom the Software is
100 | furnished to do so, subject to the following conditions:
101 |
102 | The above copyright notice and this permission notice shall be included in all
103 | copies or substantial portions of the Software.
104 |
105 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
106 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
107 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
108 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
109 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
110 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
111 | SOFTWARE.
112 |
113 | *********************************************************************************
114 |
115 | RED4ext.SDK
116 |
117 | MIT License
118 |
119 | Copyright (c) 2020 - present Octavian Dima
120 |
121 | Permission is hereby granted, free of charge, to any person obtaining a copy of
122 | this software and associated documentation files (the "Software"), to deal in
123 | the Software without restriction, including without limitation the rights to
124 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
125 | the Software, and to permit persons to whom the Software is furnished to do so,
126 | subject to the following conditions:
127 |
128 | The above copyright notice and this permission notice shall be included in all
129 | copies or substantial portions of the Software.
130 |
131 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
132 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
133 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
134 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
135 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
136 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/build.lua:
--------------------------------------------------------------------------------
1 | -- build script for xmake
2 | local package_path = vformat("$(buildir)/package")
3 |
4 | -- embed settings
5 | local embeds_path = "src/Installer/embeds"
6 |
7 | local embed_files = {
8 | "LICENSE",
9 | "Third_Party_LICENSES",
10 | "README.md",
11 | "README_zh.md",
12 | }
13 |
14 | local function check_game_installation(install_path)
15 | assert(install_path, format("Install path not set.\n\tUse the follow command to set install path:\n\txmake f --installpath=%s", [["C:\Program Files (x86)\Steam\steamapps\common\Cyberpunk 2077"]]))
16 | local exe_path = path.join(install_path, "bin", "x64", "Cyberpunk2077.exe")
17 | assert(os.exists(exe_path), format("Can't find the game installation. Make sure the install path is set to game root directory.\n\tUse the follow command to set install path:\n\txmake f --installpath=%s", [["C:\Program Files (x86)\Steam\steamapps\common\Cyberpunk 2077"]]))
18 | end
19 |
20 | local function generate_version_lua(git_tag)
21 | local file = io.open("scripts/modules/version.lua", "w")
22 |
23 | assert(file, "can't open file scripts/modules/version.lua")
24 | local content = format([[return "%s"]], git_tag)
25 | file:write(content)
26 | file:close()
27 | end
28 |
29 | -- Export functions
30 | function UpdateVersion()
31 | local git_tag = os.iorun("git describe --tags"):gsub("\n", "")
32 | generate_version_lua(git_tag)
33 | cprint("generating scripts\\modules\\version.lua ... ${bright green}ok")
34 |
35 | if os.exists("src/Common/Version.h.in") then
36 | local file = io.open("src/Common/Version.h.in", "r")
37 | local content = file:read("*a")
38 | file:close()
39 | cprint("generating src\\Common\\Version.h.in ... ${bright green}ok")
40 | content = content:gsub("${GIT_TAG}", git_tag)
41 | cprint("updating the git tag in src\\Common\\Version.h ... ${bright green}ok")
42 | file = io.open("src/Common/Version.h", "w")
43 | file:write(content)
44 | file:close()
45 | end
46 | end
47 |
48 | function GenerateEmbeds()
49 | -- clear embed directories
50 | if os.isdir(embeds_path) then
51 | os.tryrm(path.join(embeds_path, "**"))
52 | end
53 |
54 | -- create directories for embed files
55 | local embeds_lua_path = path.join(embeds_path, "lua")
56 | local embeds_red4ext_path = path.join(embeds_path, "red4ext")
57 | os.mkdir(embeds_lua_path)
58 | os.mkdir(embeds_red4ext_path)
59 |
60 | -- embed red4ext plugin
61 | import("core.project.config")
62 | config.load()
63 | import("core.project.project")
64 | local target = project.target("cet_mod_manager")
65 | print(target:targetfile())
66 | assert(os.exists(target:targetfile()), "target file for cet_mod_manager doesn't exist, run xmake build cet_mod_manager to build the target first.")
67 | os.exec([[.\vendor\bin2cpp\bin2cpp.exe --file=%s --managerfile=EmbedFileManager_Red4ExtPlugin.h --registerfile --namespace=bin2cppRed4ExtPlugin --output=%s --noheader]], target:targetfile(), path.translate(embeds_red4ext_path))
68 |
69 | -- embed loose files
70 | for _, file in ipairs(embed_files) do
71 | os.exec([[.\vendor\bin2cpp\bin2cpp.exe --file=%s --managerfile=EmbedFileManager_LooseFiles.h --registerfile --output=%s --namespace=bin2cppLooseFiles --noheader]], file, path.translate(embeds_lua_path))
72 | end
73 |
74 | -- embed lua files
75 | os.exec([[.\vendor\bin2cpp\bin2cpp.exe --dir=scripts --managerfile=EmbedFileManager_Lua.h --output=%s --namespace=bin2cppLua --keepdirs --noheader]], path.translate(embeds_lua_path))
76 |
77 | cprint("generating files for embedding to %s ... ${bright green}ok", embeds_path)
78 | end
79 |
80 | function Package(target)
81 | if os.tryrm(path.join(package_path, "**")) then
82 | cprint("cleaning old package files ... ${bright green}ok")
83 | else
84 | cprint("cleaning old package files ... ${bright red}failed")
85 | end
86 | local output_path = path.join(package_path, "bin/x64/plugins")
87 | os.mkdir(output_path)
88 | cprint("creating file structure ... ${bright green}ok")
89 |
90 | if target then
91 | os.cp(target:targetfile(), output_path)
92 | cprint("copying cet_mod_manager.asi ... ${bright green}ok")
93 | end
94 | end
95 |
96 | function Install()
97 | import("core.project.config")
98 | config.load()
99 | import("core.project.project")
100 | local target = project.target("installer")
101 | local install_path = config.get("installpath")
102 | cprint("${green bright}Installing CET Mod Manager ..")
103 | check_game_installation(install_path)
104 | assert(os.exists(target:targetfile()), "target file doesn't exist, run xmake to build the target first.")
105 | local output_dir = path.join(install_path, "bin/x64/plugins")
106 | os.cp(target:targetfile(), output_dir)
107 | cprint("CET Mod Manager installed at: ${underline}%s", output_dir)
108 | end
109 |
110 | function InstallLua()
111 | import("core.project.config")
112 | config.load()
113 | local install_path = config.get("installpath")
114 | cprint("${green bright}Installing CET Mod Manager Lua ..")
115 | check_game_installation(install_path)
116 | local from_path = path.translate("./scripts")
117 | local to_path = path.translate(path.join(install_path, "bin/x64/plugins/cyber_engine_tweaks/mods/cet_mod_manager"))
118 | os.execv("xcopy", {from_path, to_path, "/s", "/e", "/y", "/q"}) -- Don't use os.cp(), it will remove the contents from the destination directory.
119 | cprint("CET Mod Manager Lua installed at: ${underline}%s", path.translate(path.join(install_path, "bin/x64/plugins/cyber_engine_tweaks/mods/cet_mod_manager")))
120 | end
121 |
122 | function InstallExt()
123 | import("core.project.config")
124 | config.load()
125 | import("core.project.project")
126 | local target = project.target("cet_mod_manager")
127 | local install_path = config.get("installpath")
128 | cprint("${green bright}Installing CET Mod Manager Red4ext plugin ..")
129 | check_game_installation(install_path)
130 | assert(os.exists(target:targetfile()), "target file doesn't exist, run xmake to build the target first.")
131 | local output_dir = path.join(install_path, "red4ext/plugins/cet_mod_manager")
132 | os.mkdir(output_dir)
133 | os.cp(target:targetfile(), output_dir)
134 | cprint("CET Mod Manager Lua installed at: ${underline}%s", path.translate(output_dir))
135 | end
136 |
137 | function Clean()
138 | if os.tryrm(path.join(embeds_path, "**")) then
139 | cprint("cleaning embed files ... ${bright green}ok")
140 | else
141 | cprint("cleaning embed files ... ${bright red}failed")
142 | end
143 |
144 | if os.tryrm(path.join(package_path, "**")) then
145 | cprint("cleaning package files ... ${bright green}ok")
146 | else
147 | cprint("cleaning package files ... ${bright red}failed")
148 | end
149 | end
150 |
151 | function BuildAll()
152 | os.execv("xmake", {"b", "cet_mod_manager"})
153 | GenerateEmbeds()
154 | os.execv("xmake", {"b", "installer"})
155 | end
--------------------------------------------------------------------------------
/metadata.json:
--------------------------------------------------------------------------------
1 | {
2 | "3DM_MOD_ID": 172144,
3 | "3DM_MOD_TITLE": "(已支持中文) Cyber Engine Tweaks 控制台 内置 MOD管理器",
4 | "3DM_MOD_TAGS": "Cyber Engine Tweaks,赛博朋克2077,Cyberpunk 2077,MOD管理器,控制台",
5 | "3DM_MOD_DESC": "在游戏中启用禁用基于Cyber Engine Tweaks的mod",
6 | "3DM_MOD_CONTENT": "README_zh.md",
7 | "UNEX_GAME": "cyberpunk2077",
8 | "UNEX_MODID": 895,
9 | "UNEX_FILENAME": "CET Mod Manager",
10 | "UNEX_FILEDESCRIPTION": "Check here for release note: https://github.com/Nats-ji/CET-Mod-Manager/releases/latest",
11 | "MOD_FILE_NAME": "cet_mod_manager"
12 | }
13 |
--------------------------------------------------------------------------------
/scripts/dofiles/set_time_to_noon.lua:
--------------------------------------------------------------------------------
1 | local tms = Game.GetTimeSystem()
2 | tms:SetGameTimeByHMS(12, 0, 0)
3 | print("Good Morning, sleepy head!")
--------------------------------------------------------------------------------
/scripts/dofiles/suicide.lua:
--------------------------------------------------------------------------------
1 | local player = Game.GetPlayer()
2 | player:OnDied()
3 | print("YOLO")
4 |
--------------------------------------------------------------------------------
/scripts/dofiles/to-the-moon.lua:
--------------------------------------------------------------------------------
1 | local cood = {4743.650879, -1091.755127, 1310.439575}
2 |
3 | Game.TeleportPlayerToPosition(cood[1], cood[2], cood[3])
4 |
--------------------------------------------------------------------------------
/scripts/init.lua:
--------------------------------------------------------------------------------
1 | require ("modules/CETMM")
2 |
3 | CETMM.Initialize()
4 | CETMM.Event()
5 | CETMM.Update()
6 | CETMM.Render()
7 | CETMM.Shutdown()
--------------------------------------------------------------------------------
/scripts/lang/de_de.lua:
--------------------------------------------------------------------------------
1 | -- Translator : keanuWheeze
2 | return {
3 | de_de = {
4 | console_msg_loaded1 = "**************************************************" ,
5 | console_msg_loaded2 = " Cyber Engine Tweaks Mod Manager geladen... " ,
6 | console_msg_loaded3 = " Bitte lege einen Hotkey in Cyber Engine Tweaks " ,
7 | console_msg_loaded4 = " fest wenn dies der erste Start ist. " ,
8 | console_msg_loaded5 = "**************************************************" ,
9 | hotkey_manager = "Mod Manager Fenster" ,
10 | hotkey_dofiles = "Dofile Fenster" ,
11 | console_msg_scan = "[CETMM] Mod scan abgeschlossen." ,
12 | console_msg_autoscan_on = "[CETMM] Auto scan aktiviert." ,
13 | console_msg_autoscan_off = "[CETMM] Auto scan deaktiviert." ,
14 | console_msg_autoapear_on = "[CETMM] Öffnet sich automatisch mit der Konsole." ,
15 | console_msg_autoapear_off = "[CETMM] Öffnet sich nicht mehr automatisch mit der Konsole." ,
16 | console_msg_dofile_run = "[CETMM] Führe %{dofilename} aus." ,
17 | console_msg_dofile_done = "[CETMM] Fertig." ,
18 | window_title = "Cyber Engine Tweaks Mod Manager" ,
19 | button_dofiles = "Dofile Mods" ,
20 | button_scan = "Scan" ,
21 | button_autoscan_on = "Auto Scan an" ,
22 | button_autoscan_off = "Auto Scan aus" ,
23 | button_autoappear_on = "Automatisch öffnen an" ,
24 | button_autoappear_off = "Automatisch öffnen aus" ,
25 | text_help_manager_1 = "Drücke [Scan] um nach installierten Cyber Engine Tweaks Mods zu scannen." ,
26 | text_help_manager_2 = "Nutze die Boxen um die Mods zu (de)aktivieren." ,
27 | text_help_manager_3 = "Wechsele zu [Fenstermodus ohne Rand] in [Einstellungen] - [Video] um beim drücken von [Scan] nicht auf den Desktop geworfen zu werden." ,
28 | text_help_manager_4 = "Nach dem (de)aktivieren von Mods, drücke den [Reload ALL Mods] Knopf in der Knosole um alle Mods neu zu laden." ,
29 | text_help_manager_5 = "Drücke [Auto Scan] um den Auto Scan zu aktivieren." ,
30 | text_help_dofiles_1 = "Hier kannst du deine lieblings \"dofile()\" lua mods per Knopfdruck ausführen." ,
31 | text_help_dofiles_2 = "Drücke den [Dofile Ordner] Knopf um dieses Feature zu nutzen. Kopiere nun deine *.lua mods welche mit \"dofile()\" ausgeführt werden sollen hier hinein." ,
32 | text_help_dofiles_3 = "Drücke [Scan] um die Mod Liste zu aktualisieren." ,
33 | text_help_dofiles_4 = "Drücke den [Run] Knopf vor den Mods, nachdem die Mod Liste geladen ist, um diese per Knopfdruck auszuführen. Nie wieder dofile()!" ,
34 | text_help_dofiles_5 = "Wenn du möchtest kannst du die beispiel Dofile Mods löschen." ,
35 | text_no_dofiles = "Du hast keine dofile mods..." ,
36 | text_please_scan = "Bitte scanne zuerst nach mods..." ,
37 | button_mods_folder = "Mods Ordner" ,
38 | button_dofile_folder = "Dofile Ordner" ,
39 | button_dofile_run = "Run" , -- German translation would be too long for the button
40 | console_msg_mod_enable = "[CETMM] %{modname} wurde aktiviert." ,
41 | console_msg_mod_enable_error = "[CETMM] Fehler beim aktivieren von %{modname}" ,
42 | console_msg_mod_disable = "[CETMM] %{modname} wurde deaktiviert." ,
43 | console_msg_mod_disable_error = "[CETMM] Fehler beim deaktivieren von %{modname}" ,
44 | text_select_settings = "Einstellungen" ,
45 | text_select_lang = "Wähle eine Sprache aus (Benötigt evtl. Schriftart)",
46 | tooltip_btn_settings = "Einstellungen" ,
47 | tooltip_btn_help = "Hilfe",
48 | -- text_error_window_1 = "Error!!" ,
49 | -- text_error_window_2 = "CET Mod Manager failed to load it's file module!" ,
50 | -- text_error_window_3 = "Please make sure it's installed correctly." ,
51 | -- text_error_window_4 = "1. Try to uninstall the old version first, and make a clean installation." ,
52 | -- text_error_window_5 = "2. If you are using vortex, try to install manually." ,
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/scripts/lang/en_us.lua:
--------------------------------------------------------------------------------
1 | return {
2 | en_us = {
3 | console_msg_loaded1 = "************************************************" ,
4 | console_msg_loaded2 = " Cyber Engine Tweaks Mod Manager Loaded... " ,
5 | console_msg_loaded3 = " Please bind a hotkey in Cyber Engine Tweaks, " ,
6 | console_msg_loaded4 = " if this is your first time launch. " ,
7 | console_msg_loaded5 = "************************************************" ,
8 | hotkey_manager = "Mod Manager Interface" ,
9 | hotkey_dofiles = "Dofile Interface" ,
10 | console_msg_scan = "[CETMM] Mod scan complete." ,
11 | console_msg_autoscan_on = "[CETMM] Auto scan enabled." ,
12 | console_msg_autoscan_off = "[CETMM] Auto scan disabled." ,
13 | console_msg_autoapear_on = "[CETMM] Now automatically opens with console." ,
14 | console_msg_autoapear_off = "[CETMM] No longer automatically opens with console." ,
15 | console_msg_dofile_run = "[CETMM] Executing %{dofilename}." ,
16 | console_msg_dofile_done = "[CETMM] Done." ,
17 | window_title = "Cyber Engine Tweaks Mod Manager" ,
18 | button_dofiles = "Dofile Mods" ,
19 | button_scan = "Scan" ,
20 | button_autoscan_on = "Auto Scan On" ,
21 | button_autoscan_off = "Auto Scan Off" ,
22 | button_autoappear_on = "Auto Appear On" ,
23 | button_autoappear_off = "Auto Appear Off" ,
24 | text_help_manager_1 = "Press [Scan] to scan the Cyber Engine Tweaks mods you have installed." ,
25 | text_help_manager_2 = "Tick/untick the checkbox to enable/disable mods." ,
26 | text_help_manager_3 = "Change [Windowed Mode] in Game\'s [Settings] - [Video] to [Windows Borderless] to avoid being thrown out to desktop when pressing [Scan]." ,
27 | text_help_manager_4 = "After Enabling/Disabling mods, press the [Reload ALL Mods] button on console to reload the mods." ,
28 | text_help_manager_5 = "Press [Auto Scan] button to enable auto scan when the mod manager is loaded." ,
29 | text_help_dofiles_1 = "You can run your favorite \"dofile()\" lua mods here with a press of button." ,
30 | text_help_dofiles_2 = "To use this feature, press the [Dofile Folder] button on the button to open the folder. Copy your *.lua mod that runs with \"dofile()\" in here." ,
31 | text_help_dofiles_3 = "Press [Scan] button to refresh the mod list." ,
32 | text_help_dofiles_4 = "After the mod list has been loaded, press the [Run] button in front of them to run them with a press of button. No moar dofile()!" ,
33 | text_help_dofiles_5 = "You can delete the example dofile modes if you want." ,
34 | text_no_dofiles = "You don't have any dofile mods..." ,
35 | text_please_scan = "Please scan the mods first..." ,
36 | button_mods_folder = "Mods Folder" ,
37 | button_dofile_folder = "Dofile Folder" ,
38 | button_dofile_run = "Run" ,
39 | console_msg_mod_enable = "[CETMM] %{modname} has been enabled." ,
40 | console_msg_mod_enable_error = "[CETMM] Error when trying to enable %{modname}" ,
41 | console_msg_mod_disable = "[CETMM] %{modname} has been disabled." ,
42 | console_msg_mod_disable_error = "[CETMM] Error when trying to disable %{modname}" ,
43 | text_select_lang = "Selecte a Language (Needs font support)",
44 | tooltip_btn_howto_change_font = "How to change font",
45 | text_select_settings = "Settings" ,
46 | tooltip_btn_settings = "Settings" ,
47 | tooltip_btn_help = "Help" ,
48 | text_error_window_1 = "Error!!" ,
49 | text_error_window_2 = "CET Mod Manager failed to load it's file module!" ,
50 | text_error_window_3 = "Please make sure it's installed correctly." ,
51 | text_error_window_4 = "1. Try to uninstall the old version first, and make a clean installation." ,
52 | text_error_window_5 = "2. If you are using vortex, try to install manually." ,
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/scripts/lang/example.lua:
--------------------------------------------------------------------------------
1 | return {
2 | example = { --Example needs to be changed to language code.
3 | console_msg_loaded1 = "************************************************" ,
4 | console_msg_loaded2 = " Cyber Engine Tweaks Mod Manager Loaded... " ,
5 | console_msg_loaded3 = " Please bind a hotkey in Cyber Engine Tweaks, " ,
6 | console_msg_loaded4 = " if this is your first time launch. " ,
7 | console_msg_loaded5 = "************************************************" ,
8 | hotkey_manager = "Mod Manager Interface" ,
9 | hotkey_dofiles = "Dofile Interface" ,
10 | console_msg_scan = "[CETMM] Mod scan complete." ,
11 | console_msg_autoscan_on = "[CETMM] Auto scan enabled." ,
12 | console_msg_autoscan_off = "[CETMM] Auto scan disabled." ,
13 | console_msg_autoapear_on = "[CETMM] Now automatically opens with console." ,
14 | console_msg_autoapear_off = "[CETMM] No longer automatically opens with console." ,
15 | console_msg_dofile_run = "[CETMM] Executing %{dofilename}." ,
16 | console_msg_dofile_done = "[CETMM] Done." ,
17 | window_title = "Cyber Engine Tweaks Mod Manager" ,
18 | button_dofiles = "Dofile Mods" ,
19 | button_scan = "Scan" ,
20 | button_autoscan_on = "Auto Scan On" ,
21 | button_autoscan_off = "Auto Scan Off" ,
22 | button_autoappear_on = "Auto Appear On" ,
23 | button_autoappear_off = "Auto Appear Off" ,
24 | text_help_manager_1 = "Press [Scan] to scan the Cyber Engine Tweaks mods you have installed." ,
25 | text_help_manager_2 = "Tick/untick the checkbox to enable/disable mods." ,
26 | text_help_manager_3 = "Change [Windowed Mode] in Game\'s [Settings] - [Video] to [Windows Borderless] to avoid being thrown out to desktop when pressing [Scan]." ,
27 | text_help_manager_4 = "After Enabling/Disabling mods, press the [Reload ALL Mods] button on console to reload the mods." ,
28 | text_help_manager_5 = "Press [Auto Scan] button to enable auto scan when the mod manager is loaded." ,
29 | text_help_dofiles_1 = "You can run your favorite \"dofile()\" lua mods here with a press of button." ,
30 | text_help_dofiles_2 = "To use this feature, press the [Dofile Folder] button on the button to open the folder. Copy your *.lua mod that runs with \"dofile()\" in here." ,
31 | text_help_dofiles_3 = "Press [Scan] button to refresh the mod list." ,
32 | text_help_dofiles_4 = "After the mod list has been loaded, press the [Run] button in front of them to run them with a press of button. No moar dofile()!" ,
33 | text_help_dofiles_5 = "You can delete the example dofile modes if you want." ,
34 | text_no_dofiles = "You don't have any dofile mods..." ,
35 | text_please_scan = "Please scan the mods first..." ,
36 | button_mods_folder = "Mods Folder" ,
37 | button_dofile_folder = "Dofile Folder" ,
38 | button_dofile_run = "Run" ,
39 | console_msg_mod_enable = "[CETMM] %{modname} has been enabled." ,
40 | console_msg_mod_enable_error = "[CETMM] Error when trying to enable %{modname}" ,
41 | console_msg_mod_disable = "[CETMM] %{modname} has been disabled." ,
42 | console_msg_mod_disable_error = "[CETMM] Error when trying to disable %{modname}" ,
43 | text_select_lang = "Selecte a Language (Needs font support)",
44 | text_select_settings = "Settings" ,
45 | tooltip_btn_settings = "Settings" ,
46 | tooltip_btn_help = "Help" ,
47 | text_error_window_1 = "Error!!" ,
48 | text_error_window_2 = "CET Mod Manager failed to load it's file module!" ,
49 | text_error_window_3 = "Please make sure it's installed correctly." ,
50 | text_error_window_4 = "1. Try to uninstall the old version first, and make a clean installation." ,
51 | text_error_window_5 = "2. If you are using vortex, try to install manually." ,
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/scripts/lang/fr_fr.lua:
--------------------------------------------------------------------------------
1 | -- Translator : ReActif
2 | return {
3 | fr_fr = {
4 | console_msg_loaded1 = "************************************************" ,
5 | console_msg_loaded2 = " Cyber Engine Tweaks Mod Manager est chargé... " ,
6 | console_msg_loaded3 = " Lier un raccourci dans Cyber Engine Tweaks, " ,
7 | console_msg_loaded4 = " si c'est votre premier lancement. " ,
8 | console_msg_loaded5 = "************************************************" ,
9 | hotkey_manager = "Interface de Mod Manager" ,
10 | hotkey_dofiles = "Interface de Dofile" ,
11 | console_msg_scan = "[CETMM] Analyse du mod terminée." ,
12 | console_msg_autoscan_on = "[CETMM] Analyse auto activée." ,
13 | console_msg_autoscan_off = "[CETMM] Analyse auto désactivée." ,
14 | console_msg_autoapear_on = "[CETMM] S'ouvre automatiquement avec la console." ,
15 | console_msg_autoapear_off = "[CETMM] Ne s'ouvre plus automatiquement avec la console." ,
16 | console_msg_dofile_run = "[CETMM] Exécution de %{dofilename}." ,
17 | console_msg_dofile_done = "[CETMM] Terminé." ,
18 | window_title = "Cyber Engine Tweaks Mod Manager" ,
19 | button_dofiles = "Mods Dofile" ,
20 | button_scan = "Scanner" ,
21 | button_autoscan_on = "Scanner auto ON" ,
22 | button_autoscan_off = "Scanner auto OFF" ,
23 | button_autoappear_on = "Apparition auto ON" ,
24 | button_autoappear_off = "Apparition auto OFF" ,
25 | text_help_manager_1 = "Appuyez sur [Scanner] pour analyser les mods CET que vous avez installés." ,
26 | text_help_manager_2 = "Cochez/décochez la case pour activer/désactiver les mods." ,
27 | text_help_manager_3 = "Changez le [Mode fenêtré] dans [Paramètres] - [Vidéo] du jeu en [Fenêtré sans bordure] pour éviter d'être basculer sur le bureau en appuyant sur [Scanner]." ,
28 | text_help_manager_4 = "Après avoir activé/désactivé les mods, appuyez sur le bouton [Reload all mods] de la console pour recharger les mods." ,
29 | text_help_manager_5 = "Appuyez sur le bouton [Auto Scan] pour activer le scan automatique lorsque le gestionnaire de mods est chargé." ,
30 | text_help_dofiles_1 = "Vous pouvez exécuter vos mods lua favoris \"dofile()\" ici en appuyant sur un bouton." ,
31 | text_help_dofiles_2 = "Pour utiliser cette fonction, appuyez sur le bouton [Dossier Dofile] pour ouvrir le dossier. Copiez votre mod *.lua qui fonctionne avec \"dofile()\" dans ce dossier." ,
32 | text_help_dofiles_3 = "Appuyez sur le bouton [Scanner] pour actualiser la liste des modules." ,
33 | text_help_dofiles_4 = "Une fois la liste des mods chargée, appuyez sur le bouton [Run] en face de chacun d'eux pour les exécuter en appuyant sur le bouton. Plus besoin de dofile() !" ,
34 | text_help_dofiles_5 = "Vous pouvez supprimer les exemples de mods dofile si vous le souhaitez." ,
35 | text_no_dofiles = "Vous n'avez pas de mods dofile..." ,
36 | text_please_scan = "Veuillez d'abord scanner les mods..." ,
37 | button_mods_folder = "Dossier Mods" ,
38 | button_dofile_folder = "Dossier Dofile" ,
39 | button_dofile_run = "Exécuter" ,
40 | console_msg_mod_enable = "[CETMM] %{modname} a été activé." ,
41 | console_msg_mod_enable_error = "[CETMM] Erreur d'activation de %{modname}." ,
42 | console_msg_mod_disable = "[CETMM] %{modname} a été désactivé." ,
43 | console_msg_mod_disable_error = "[CETMM] Erreur de désactivation de %{modname}." ,
44 | text_select_lang = "Sélection de langue (nécessite une police adapté)" ,
45 | tooltip_btn_howto_change_font = "Comment changer de police" ,
46 | text_select_settings = "Paramètres" ,
47 | tooltip_btn_settings = "Paramètres" ,
48 | tooltip_btn_help = "Aide" ,
49 | text_error_window_1 = "Erreur !" ,
50 | text_error_window_2 = "CET Mod Manager n'a pas réussi à charger son module de fichier !" ,
51 | text_error_window_3 = "Assure-toi qu'il est installé correctement." ,
52 | text_error_window_4 = "1. Essaie de désinstaller l'ancienne version d'abord, et fais une installation propre." ,
53 | text_error_window_5 = "2. Si vous utilisez vortex, essayez d'installer manuellement." ,
54 | }
55 | }
--------------------------------------------------------------------------------
/scripts/lang/ja_jp.lua:
--------------------------------------------------------------------------------
1 | -- Translator : Mingming Cui
2 | return {
3 | ja_jp = {
4 | console_msg_loaded1 = "**********************************************************" ,
5 | console_msg_loaded2 = " Cyber Engine Tweaksモッドマネージャーがロードされました" ,
6 | console_msg_loaded3 = " 初めての起動される場合は、Cyber Engine Tweaksで" ,
7 | console_msg_loaded4 = " ホットキーを設定してください" ,
8 | console_msg_loaded5 = "**********************************************************" ,
9 | hotkey_manager = "モッドマネージャー界面" ,
10 | hotkey_dofiles = "Dofileスクリプト界面" ,
11 | console_msg_scan = "[CETMM] モッドスキャンが完了しました。" ,
12 | console_msg_autoscan_on = "[CETMM] 自動スキャンが有効化されました。" ,
13 | console_msg_autoscan_off = "[CETMM] 自動スキャンが無効化されました。" ,
14 | console_msg_autoapear_on = "[CETMM] コンソールと一緒に自動的に開くようになりました。" ,
15 | console_msg_autoapear_off = "[CETMM] コンソールと一緒に自動的に開かないようになりました。" ,
16 | console_msg_dofile_run = "[CETMM] %{dofilename}実行中。" ,
17 | console_msg_dofile_done = "[CETMM] 実行完了。" ,
18 | window_title = "Cyber Engine Tweaksモッドマネージャー" ,
19 | button_dofiles = "Dofileスクリプト" ,
20 | button_scan = "スキャン" ,
21 | button_autoscan_on = "自動スキャンオン" ,
22 | button_autoscan_off = "自動スキャンオフ" ,
23 | button_autoappear_on = "自動表示オン" ,
24 | button_autoappear_off = "自動表示オフ" ,
25 | text_help_manager_1 = "「スキャン」を押して、インストールしたCyber Engine Tweaksモッドをスキャンします。" ,
26 | text_help_manager_2 = "チェックボックスをオン/オフにして、モッドを有効か/無効かにすることができます。" ,
27 | text_help_manager_3 = "ゲームの「設定」-「ビデオ」-「画面モード」を「ボーダレスウィンドウ」に変更したら、「スキャン」を押したときにデスクトップに戻されないようなります。" ,
28 | text_help_manager_4 = "モッドを有効/無効にした後、コンソールの「Reload ALL Mods」ボタンを押してモッドをリロードしてください。" ,
29 | text_help_manager_5 = "「自動スキャン」ボタンを押すと、モッドマネージャーがロードされるときに自動的にモッドをスキャンすることになります。" ,
30 | text_help_dofiles_1 = "お気に入りの\"dofile()\"スクリプトをボタン一つで実行することができます。" ,
31 | text_help_dofiles_2 = "この機能を使用するには、「Dofileフォルダ」ボタンを押して、フォルダを開いてください。そして、*.lua のスクリプトをこのフォルダにコピーしてください。" ,
32 | text_help_dofiles_3 = "「スキャン」ボタンを押して、モッドリストを更新してください。" ,
33 | text_help_dofiles_4 = "モッドリストがロードされたら、スクリプト前の「実行」ボタンを押すだけで実行することができます。さらばdofile()!" ,
34 | text_help_dofiles_5 = "必要に応じて、サンプルのdofileスクリプトを削除してください。" ,
35 | text_no_dofiles = "dofileスクリプがありません..." ,
36 | text_please_scan = "モッドをスキャンしてください..." ,
37 | button_mods_folder = "モッドフォルダ" ,
38 | button_dofile_folder = "Dofileフォルダ" ,
39 | button_dofile_run = "実行" ,
40 | console_msg_mod_enable = "[CETMM] %{modname}が有効化されました。" ,
41 | console_msg_mod_enable_error = "[CETMM] %{modname}を有効化するときにエラーが発生されました。" ,
42 | console_msg_mod_disable = "[CETMM] %{modname}が無効化されました。" ,
43 | console_msg_mod_disable_error = "[CETMM] %{modname}を無効化するときにエラーが発生されました。" ,
44 | text_select_settings = "設定" ,
45 | text_select_lang = "言語の選択(フォントのサポートが必要)" ,
46 | tooltip_btn_settings = "設定" ,
47 | tooltip_btn_help = "ヘルプ",
48 | text_error_window_1 = "エラー!!" ,
49 | text_error_window_2 = "CETモッドマネージャーがモジュールのロードに失敗しました!" ,
50 | -- text_error_window_3 = "Please make sure it's installed correctly." ,
51 | -- text_error_window_4 = "1. Try to uninstall the old version first, and make a clean installation." ,
52 | -- text_error_window_5 = "2. If you are using vortex, try to install manually." ,
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/scripts/lang/lang.lua:
--------------------------------------------------------------------------------
1 | return {
2 | { id = "en_us", name = "English" },
3 | { id = "zh_cn", name = "简体中文 (Simplified Chinese)" },
4 | { id = "zh_tw", name = "正體中文 (Traditional Chinese)" },
5 | { id = "ja_jp", name = "日本語 (Japanese)" },
6 | { id = "ru_ru", name = "Русский (Russian)" },
7 | { id = "de_de", name = "Deutsch (German)" },
8 | { id = "tr_tc", name = "Türkçe (Turkish)" },
9 | { id = "ro_ro", name = "Limba Română (Romanian)" },
10 | { id = "pt_br", name = "português (Brazilian Portuguese)" },
11 | { id = "fr_fr", name = "Français (French)"},
12 | -- { id = "example", name = "Example Language (Example)"},
13 | }
14 |
--------------------------------------------------------------------------------
/scripts/lang/pt_br.lua:
--------------------------------------------------------------------------------
1 | -- Translator: mathfelin
2 | return {
3 | pt_br = {
4 | console_msg_loaded1 = "************************************************" ,
5 | console_msg_loaded2 = " Cyber Engine Tweaks Mod Manager Carregado... " ,
6 | console_msg_loaded3 = " Por favor, aperte uma tecla de atalho em Cyber Engine Tweaks, " ,
7 | console_msg_loaded4 = " esta e a sua primeira vez de lancamento. " ,
8 | console_msg_loaded5 = "************************************************" ,
9 | hotkey_manager = "Interface do Mod Manager" ,
10 | hotkey_dofiles = "Interface de Arquivo" ,
11 | console_msg_scan = "[CETMM] Varredura de Mod Completa." ,
12 | console_msg_autoscan_on = "[CETMM] Varredura automatica ativado." ,
13 | console_msg_autoscan_off = "[CETMM] Varredura automatica desativado." ,
14 | console_msg_autoapear_on = "[CETMM] Abre automaticamente o console." ,
15 | console_msg_autoapear_off = "[CETMM] Não abre automaticamente o console." ,
16 | console_msg_dofile_run = "[CETMM] Executando %{nome do ficheiro}." ,
17 | console_msg_dofile_done = "[CETMM] Feito." ,
18 | window_title = "Cyber Engine Tweaks Mod gestor" ,
19 | button_dofiles = "Modos de arquivo" ,
20 | button_scan = "Analisar" ,
21 | button_autoscan_on = "Varredura automatica ligado" ,
22 | button_autoscan_off = "Varredura automatica desligado" ,
23 | button_autoappear_on = "Aparecimento automatico ligado" ,
24 | button_autoappear_off = "Aparecimento automatico desligado" ,
25 | text_help_manager_1 = "Pressionar [Varrer] para analisar mods instalados em Cyber Engine Tweaks." ,
26 | text_help_manager_2 = "Marcar/desmarcar a caixa de verificação para ativar/desativar mods." ,
27 | text_help_manager_3 = "Alterar [Windowed Mode] em Jogo\'s [Configurações] - [Video] para [Janelas sem Bordas] para evitar ser atirado para o ambiente de trabalho, pressionar [Varrer]." ,
28 | text_help_manager_4 = "Depois de habilitar/desabilitar os mods, pressione o [Recarregar TODOS os Mods] botão no console para recarregar os mods." ,
29 | text_help_manager_5 = "Pressionar [Varredura automatica] para ativar a varredura automática quando o mod gestor é carregado." ,
30 | text_help_dofiles_1 = "Pode executar o seu favorito \"arquivo()\" lua mods aqui com uma prensa de botão." ,
31 | text_help_dofiles_2 = "Para utilizar esta funcionalidade, pressionar o botão [Arquivo pasta] para abrir a pasta. Copie o seu *.lua mod que corre com \"arquivo()\" aqui." ,
32 | text_help_dofiles_3 = "Pressionar [Varrer] botão para atualizar a lista mod." ,
33 | text_help_dofiles_4 = "Após a lista de mods ser carregada, pressionar o botão [Executar] botão na frente deles para os executar com um apertar de botão. Nenhum arquivo do moar()!" ,
34 | text_help_dofiles_5 = "Pode apagar os modos de arquivo de exemplo, se quiser." ,
35 | text_no_dofiles = "Não tem nenhum mods de arquivo..." ,
36 | text_please_scan = "Por favor, escaneie os mods primeiro..." ,
37 | button_mods_folder = "Pasta de Mods" ,
38 | button_dofile_folder = "Arquivar Pasta" ,
39 | button_dofile_run = "Executar" ,
40 | console_msg_mod_enable = "[CETMM] %{nome do mod} foi ativado." ,
41 | console_msg_mod_enable_error = "[CETMM] Erro ao tentar ativar %{nome do mod}" ,
42 | console_msg_mod_disable = "[CETMM] %{nome do mod} foi desativado." ,
43 | console_msg_mod_disable_error = "[CETMM] Erro ao tentar desativar %{nome do mod}" ,
44 | text_select_lang = "Seleccionar um idioma (Necessita de suporte de fontes)",
45 | text_select_settings = "Configurações" ,
46 | tooltip_btn_settings = "Configurações" ,
47 | tooltip_btn_help = "Ajuda" ,
48 | text_error_window_1 = "Erro!!" ,
49 | text_error_window_2 = "CET Mod gestor Não carregou o seu modulo de arquivo!" ,
50 | text_error_window_3 = "Por favor, certifique-se de que esta instalado correctamente." ,
51 | text_error_window_4 = "1. desinstalar primeiro a versao antiga, e fazer uma instalacao limpa." ,
52 | text_error_window_5 = "2. Se estiver a utilizar o vortex, tente instalar manualmente." ,
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/scripts/lang/ro_ro.lua:
--------------------------------------------------------------------------------
1 | -- Translator: Maddmaniak
2 | return {
3 | ro_ro = {
4 | console_msg_loaded1 = "************************************************" ,
5 | console_msg_loaded2 = " Cyber Engine Tweaks Mod Manager Incarcat... " ,
6 | console_msg_loaded3 = " Setati o tasta in Cyber Engine Tweaks, " ,
7 | console_msg_loaded4 = " daca sunteti la prima setare/lansare. " ,
8 | console_msg_loaded5 = "************************************************" ,
9 | hotkey_manager = "Interfata Mod Manager" ,
10 | hotkey_dofiles = "Dofile Interfata" ,
11 | console_msg_scan = "[CETMM] Mod scanare complet." ,
12 | console_msg_autoscan_on = "[CETMM] Auto scanare activata." ,
13 | console_msg_autoscan_off = "[CETMM] Auto scanare dezactivata." ,
14 | console_msg_autoapear_on = "[CETMM] Acum se deschide automat cu consola." ,
15 | console_msg_autoapear_off = "[CETMM] Nu se mai deschide automat cu consola." ,
16 | console_msg_dofile_run = "[CETMM] Se executa %{dofilename}." ,
17 | console_msg_dofile_done = "[CETMM] Terminat." ,
18 | window_title = "Cyber Engine Tweaks Mod Manager" ,
19 | button_dofiles = "Dofile Mod" ,
20 | button_scan = "Scanare" ,
21 | button_autoscan_on = "Auto Scanare pornita" ,
22 | button_autoscan_off = "Auto Scanare oprita" ,
23 | button_autoappear_on = "Auto Aparitie pornit" ,
24 | button_autoappear_off = "Auto Aparitie oprit" ,
25 | text_help_manager_1 = "Apasa [Scan] pentru a scana modurile Cyber Engine Tweaks pe care le-ati instalat." ,
26 | text_help_manager_2 = "Bifati / debifati caseta de selectare pentru a activa / dezactiva modurile." ,
27 | text_help_manager_3 = "Schimbati [Modul Windowed] in [Setari] - [Video] a jocului din [Windows fara margini- Borderless] pentru a evita iesirea aplicatiei pe desktop cand apasati [Scanare]." ,
28 | text_help_manager_4 = "Dupa activarea / dezactivarea modurilor, apasati butonul [Reincarcati toate modurile] de pe consolaă pentru a reincarca modurile." ,
29 | text_help_manager_5 = "Apasati butonul [Scanare automata] pentru a activa scanarea automata la incarcarea mod managerului." ,
30 | text_help_dofiles_1 = "Puteti rula modurile preferate \"dofile ()\" .lua aici, doar la o apasare de buton." ,
31 | text_help_dofiles_2 = "Pentru a utiliza aceasta caracteristica, apasati butonul [Dofile Folder] pentru a deschide folderul. Copiati modul dvs. * .lua care ruleaza cu \"dofile ()\" aici." ,
32 | text_help_dofiles_3 = "Apasati butonul [Scan] pentru a re-incarca lista cu moduri. " ,
33 | text_help_dofiles_4 = "Dupaă ce lista de moduri a fost incarcata, apasati butonul [Run] din fata lor pentru a le rula cu o apasare de buton. Fara fisier moar ()!" ,
34 | text_help_dofiles_5 = "Puteti șsterge exemplele de moduri de fisier dofile, daca doriti." ,
35 | text_no_dofiles = "Nu aveti niciun mod de fisier do..." ,
36 | text_please_scan = "Va rugam saăscanati mai intai modificarile(modurile)..." ,
37 | button_mods_folder = "Foldere Mods. " ,
38 | button_dofile_folder = "Foldere Dofile. " ,
39 | button_dofile_run = "Ruleaza " ,
40 | console_msg_mod_enable = "[CETMM] %{modname} a fost activat. " ,
41 | console_msg_mod_enable_error = "[CETMM] Eroare la incarcarea modului.. %{modname}" ,
42 | console_msg_mod_disable = "[CETMM] %{modname} a fost dezactivat." ,
43 | console_msg_mod_disable_error = "[CETMM] Eroare la dezactivarea modului.. %{modname}" ,
44 | text_select_lang = "Selectati o limba (Necesita suport pentru fonturi)",
45 | text_select_settings = "Setari" ,
46 | tooltip_btn_settings = "Setari" ,
47 | tooltip_btn_help = "Ajutor" ,
48 | -- text_error_window_1 = "Error!!" ,
49 | -- text_error_window_2 = "CET Mod Manager failed to load it's file module!" ,
50 | -- text_error_window_3 = "Please make sure it's installed correctly." ,
51 | -- text_error_window_4 = "1. Try to uninstall the old version first, and make a clean installation." ,
52 | -- text_error_window_5 = "2. If you are using vortex, try to install manually." ,
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/scripts/lang/ru_ru.lua:
--------------------------------------------------------------------------------
1 | -- Translator : vanja-san
2 | return {
3 | ru_ru = {
4 | console_msg_loaded1 = "****************************************************" ,
5 | console_msg_loaded2 = " Менеджер модов Cyber Engine Tweaks загружен... " ,
6 | console_msg_loaded3 = " Привяжите горячую клавишу в Cyber Engine Tweaks, " ,
7 | console_msg_loaded4 = " если это ваш первый запуск. " ,
8 | console_msg_loaded5 = "****************************************************" ,
9 | hotkey_manager = "Интерфейс менеджера модов" ,
10 | hotkey_dofiles = "Интерфейс Dofile" ,
11 | console_msg_scan = "[CETMM] Сканирование модов завершено." ,
12 | console_msg_autoscan_on = "[CETMM] Автосканирование включено." ,
13 | console_msg_autoscan_off = "[CETMM] Автосканирование выключено." ,
14 | console_msg_autoapear_on = "[CETMM] Теперь автоматически открывается с консолью." ,
15 | console_msg_autoapear_off = "[CETMM] Больше не открывается автоматически с консолью." ,
16 | console_msg_dofile_run = "[CETMM] Выполнение %{dofilename}." ,
17 | console_msg_dofile_done = "[CETMM] Готово." ,
18 | window_title = "Менеджер модов Cyber Engine Tweaks" ,
19 | button_dofiles = "Dofile моды" ,
20 | button_scan = "Сканировать" ,
21 | button_autoscan_on = "Автосканирование: ВКЛЮЧЕНО" ,
22 | button_autoscan_off = "Автосканирование: ВЫКЛЮЧЕНО" ,
23 | button_autoappear_on = "Автооткрытие: ВКЛЮЧЕНО" ,
24 | button_autoappear_off = "Автооткрытие: ВЫКЛЮЧЕНО" ,
25 | text_help_manager_1 = "Нажмите [Сканировать], чтобы Cyber Engine Tweaks произвёл поиск установленных модов." ,
26 | text_help_manager_2 = "Установите/снимите флажок для включения/отключения модов." ,
27 | text_help_manager_3 = "Измените [Оконный режим] в игре: [Настройки] - [Видео] на [Оконный без полей], чтобы избежать вылета игры на рабочий стол при нажатии [Сканировать]." ,
28 | text_help_manager_4 = "После включения/отключения модов, нажмите кнопку [Перезагрузить все моды] на консоли, чтобы перезагрузить моды." ,
29 | text_help_manager_5 = "Нажмите кнопку [Автосканирование], чтобы включить автоматическое сканирование при загрузке менеджера модов." ,
30 | text_help_dofiles_1 = "Здесь вы можете запускать свои любимые lua-моды \"dofile()\" одним нажатием кнопки." ,
31 | text_help_dofiles_2 = "Чтобы использовать эту функцию, нажмите кнопку [Папка Dofile], чтобы открыть папку. Скопируйте сюда свой мод *.lua который работает с \"dofile()\"." ,
32 | text_help_dofiles_3 = "Нажмите кнопку [Сканировать], чтобы обновить список модов." ,
33 | text_help_dofiles_4 = "После загрузки списка модов нажмите кнопку [Запустить] перед ними, чтобы запустить их одним нажатием кнопки. Теперь без dofile()!" ,
34 | text_help_dofiles_5 = "Если хотите, вы можете удалить примеры режимов dofile." ,
35 | text_no_dofiles = "У вас нет dofile модов..." ,
36 | text_please_scan = "Сначала просканируйте моды..." ,
37 | button_mods_folder = "Папка модов" ,
38 | button_dofile_folder = "Папка Dofile" ,
39 | button_dofile_run = "Запустить" ,
40 | console_msg_mod_enable = "[CETMM] %{modname}: Включен" ,
41 | console_msg_mod_enable_error = "[CETMM] %{modname}: Ошибка включения" ,
42 | console_msg_mod_disable = "[CETMM] %{modname}: Отключен" ,
43 | console_msg_mod_disable_error = "[CETMM] %{modname}: Ошибка отключения" ,
44 | text_select_lang = "Выберите язык (Требуется поддержка шрифтов)",
45 | text_select_settings = "Настройки" ,
46 | tooltip_btn_settings = "Настройки" ,
47 | tooltip_btn_help = "Помощь",
48 | text_error_window_1 = "Ошибка!!!" ,
49 | text_error_window_2 = "Менеджер модов CET: Не удалось загрузить модуль!" ,
50 | text_error_window_3 = "Убедитесь, что он установлен правильно." ,
51 | text_error_window_4 = "1. Попробуйте сначала удалить старую версию и произвести чистую установку." ,
52 | text_error_window_5 = "2. Если вы используете Vortex, попробуйте установить его вручную." ,
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/scripts/lang/tr_tc.lua:
--------------------------------------------------------------------------------
1 | --Translator: sebepne
2 | return {
3 | tr_tc = {
4 | console_msg_loaded1 = "********************************************************" ,
5 | console_msg_loaded2 = " Cyber Engine Tweaks Mod Yöneticisi Yüklendi... " ,
6 | console_msg_loaded3 = " Lütfen Cyber Engine Tweaks'e bir kısayol tuşu bağlayın, " ,
7 | console_msg_loaded4 = " Bunu ilk kez başlatıyorsanız. " ,
8 | console_msg_loaded5 = "********************************************************" ,
9 | hotkey_manager = "Mod Yöneticisi Arayüzü" ,
10 | hotkey_dofiles = "Dofile Arayüzü" ,
11 | console_msg_scan = "[CETMM] Mod taraması tamamlandı." ,
12 | console_msg_autoscan_on = "[CETMM] Otomatik tarama etkinleştirildi." ,
13 | console_msg_autoscan_off = "[CETMM] Otomatik tarama devre dışı bırakıldı." ,
14 | console_msg_autoapear_on = "[CETMM] Artık konsol ile otomatik olarak açılıyor." ,
15 | console_msg_autoapear_off = "[CETMM] Artık konsol ile otomatik olarak açılmıyor." ,
16 | console_msg_dofile_run = "[CETMM] Yürütülüyor %{dofilename}." ,
17 | console_msg_dofile_done = "[CETMM] Bitti." ,
18 | window_title = "Cyber Engine Tweaks Mod Yöneticisi" ,
19 | button_dofiles = "Dofile Modları" ,
20 | button_scan = "Tarama" ,
21 | button_autoscan_on = "Otomatik Tarama Açık" ,
22 | button_autoscan_off = "Otomatik Tarama Kapalı" ,
23 | button_autoappear_on = "Otomatik Görünme Açık" ,
24 | button_autoappear_off = "Otomatik Görünme Kapalı" ,
25 | text_help_manager_1 = "Yüklediğiniz Cyber Engine Tweaks modlarını taramak için [Tara] ya basın." ,
26 | text_help_manager_2 = "Modları etkinleştirmek devre dışı bırakmak için onay kutusunu işaretleyin işaretini kaldırın." ,
27 | text_help_manager_3 = "[Tara] tuşuna basıldığında masaüstüne atılmasını önlemek için Oyunlar [Ayarlar] - [Video] 'da [Pencereli Mod]' u [Windows Kenarlıksız] olarak değiştirin." ,
28 | text_help_manager_4 = "Modları Etkinleştirdikten Devre Dışı Bıraktıktan sonra, modları yeniden yüklemek için konsoldaki [TÜM Modları Yeniden Yükle] düğmesine basın.." ,
29 | text_help_manager_5 = "Mod yöneticisi yüklendiğinde otomatik taramayı etkinleştirmek için [Otomatik Tarama] düğmesine basın." ,
30 | text_help_dofiles_1 = "Favori \"dofile()\" lua modlarınızı burada bir düğmeye basarak çalıştırabilirsiniz." ,
31 | text_help_dofiles_2 = "Bu özelliği kullanmak için, klasörü açmak üzere düğme üzerindeki [Dofile Folder] düğmesine basın. \"dofile()\" ile çalışan .lua modunuzu buraya kopyalayın." ,
32 | text_help_dofiles_3 = "Mod listesini yenilemek için [Tara] düğmesine basın." ,
33 | text_help_dofiles_4 = "Mod listesi yüklendikten sonra, bir düğmeye basarak çalıştırmak için önlerindeki [Çalıştır] düğmesine basın. Moar dofile()!" ,
34 | text_help_dofiles_5 = "İsterseniz örnek dofile modlarını silebilirsiniz.." ,
35 | text_no_dofiles = "Dofile modunuz yok ..." ,
36 | text_please_scan = "Lütfen önce modları tarayın ..." ,
37 | button_mods_folder = "Mod Klasörü" ,
38 | button_dofile_folder = "Dofile Klasörü" ,
39 | button_dofile_run = "Çalıştır" ,
40 | console_msg_mod_enable = "[CETMM] %{modname} etkinleştirildi." ,
41 | console_msg_mod_enable_error = "[CETMM] Etkinleştirmeye çalışırken hata oluştu %{modname}" ,
42 | console_msg_mod_disable = "[CETMM] %{modname} devre dışı bırakıldı." ,
43 | console_msg_mod_disable_error = "[CETMM] Devre dışı bırakmaya çalışırken hata oluştu %{modname}" ,
44 | text_select_lang = "Bir Dil Seçin (Yazı tipi desteği gerekir)",
45 | text_select_settings = "Ayarlar" ,
46 | tooltip_btn_settings = "Ayarlar" ,
47 | tooltip_btn_help = "Yardım" ,
48 | -- text_error_window_1 = "Error!!" ,
49 | -- text_error_window_2 = "CET Mod Manager failed to load it's file module!" ,
50 | -- text_error_window_3 = "Please make sure it's installed correctly." ,
51 | -- text_error_window_4 = "1. Try to uninstall the old version first, and make a clean installation." ,
52 | -- text_error_window_5 = "2. If you are using vortex, try to install manually." ,
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/scripts/lang/zh_cn.lua:
--------------------------------------------------------------------------------
1 | -- Translator : Mingming Cui
2 | return {
3 | zh_cn = {
4 | console_msg_loaded1 = "************************************************" ,
5 | console_msg_loaded2 = " Cyber Engine Tweaks模组管理器已加载..." ,
6 | console_msg_loaded3 = " 如果是初次安装使用,请先在Cyber Engine Tweaks" ,
7 | console_msg_loaded4 = " 里设置开启界面的热键。" ,
8 | console_msg_loaded5 = "************************************************" ,
9 | hotkey_manager = "模组管理界面" ,
10 | hotkey_dofiles = "Dofile脚本界面" ,
11 | console_msg_scan = "[CETMM] 模组扫描完成。" ,
12 | console_msg_autoscan_on = "[CETMM] 自动扫描已打开。" ,
13 | console_msg_autoscan_off = "[CETMM] 自动扫描已关闭。" ,
14 | console_msg_autoapear_on = "[CETMM] 现在跟随控制台自动显示。" ,
15 | console_msg_autoapear_off = "[CETMM] 不在跟随控制台自动显示。" ,
16 | console_msg_dofile_run = "[CETMM] 正在执行 %{dofilename}。" ,
17 | console_msg_dofile_done = "[CETMM] 执行完毕。" ,
18 | window_title = "Cyber Engine Tweaks模组管理器" ,
19 | button_dofiles = "Dofile脚本" ,
20 | button_scan = "扫描" ,
21 | button_autoscan_on = "自动扫描已打开" ,
22 | button_autoscan_off = "自动扫描已关闭" ,
23 | button_autoappear_on = "自动显示已打开" ,
24 | button_autoappear_off = "自动显示已关闭" ,
25 | text_help_manager_1 = "点击【扫描】按钮以扫描你已安装的Cyber Engine Tweaks模组。" ,
26 | text_help_manager_2 = "勾选或取消模组前的选择框以启用或禁用该模组。" ,
27 | text_help_manager_3 = "把游戏【设置】-【视频】-【窗口模式】改成【无边框窗口】以避免点击【扫描】按钮时游戏弹出至桌面。" ,
28 | text_help_manager_4 = "在启用或禁用模组之后,点击控制台里的【重载全部模组】按钮以生效。" ,
29 | text_help_manager_5 = "点击【自动扫描】按钮以打开模组管理器加载时自动扫描的功能。" ,
30 | text_help_dofiles_1 = "你可以在这里不需要输入任何代码一键运行你喜爱的“dofile()”脚本模组。" ,
31 | text_help_dofiles_2 = "点击【Dofile脚本文件夹】按钮打开文件夹。把你的 *.lua 脚本放进该文件里。" ,
32 | text_help_dofiles_3 = "点击【扫描】按钮以刷新脚本列表。" ,
33 | text_help_dofiles_4 = "脚本列表更新之后,点击你想运行的脚本前的【执行】按钮以执行该脚本。" ,
34 | text_help_dofiles_5 = "你可以随时删除这些示例脚本。" ,
35 | text_no_dofiles = "你没有任何Dofile脚本..." ,
36 | text_please_scan = "请先扫描模组..." ,
37 | button_mods_folder = "模组文件夹" ,
38 | button_dofile_folder = "Dofile脚本文件夹" ,
39 | button_dofile_run = "执行" ,
40 | console_msg_mod_enable = "[CETMM] 模组%{modname}已启用。" ,
41 | console_msg_mod_enable_error = "[CETMM] 尝试启用模组%{modname}时发生错误" ,
42 | console_msg_mod_disable = "[CETMM] 模组%{modname}已禁用。" ,
43 | console_msg_mod_disable_error = "[CETMM] 尝试禁用模组%{modname}时发生错误",
44 | text_select_settings = "设置" ,
45 | text_select_lang = "选择语言(需要字体支持)" ,
46 | tooltip_btn_settings = "设置" ,
47 | tooltip_btn_help = "帮助",
48 | text_error_window_1 = "错误!!" ,
49 | text_error_window_2 = "CET模组管理器无法加载运行库!" ,
50 | -- text_error_window_3 = "Please make sure it's installed correctly." ,
51 | -- text_error_window_4 = "1. Try to uninstall the old version first, and make a clean installation." ,
52 | -- text_error_window_5 = "2. If you are using vortex, try to install manually." ,
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/scripts/lang/zh_tw.lua:
--------------------------------------------------------------------------------
1 | -- Translator : Mingming Cui
2 | return {
3 | zh_tw = {
4 | console_msg_loaded1 = "************************************************" ,
5 | console_msg_loaded2 = " Cyber Engine Tweaks模組管理器已加載..." ,
6 | console_msg_loaded3 = " 如果這是您的首次啟動,請在Cyber Engine Tweaks" ,
7 | console_msg_loaded4 = " 中綁定一個熱鍵。 " ,
8 | console_msg_loaded5 = "************************************************" ,
9 | hotkey_manager = "模組管理界面" ,
10 | hotkey_dofiles = "Dofile腳本界面" ,
11 | console_msg_scan = "[CETMM] 模组掃描完成。" ,
12 | console_msg_autoscan_on = "[CETMM] 已啟用自動掃描。" ,
13 | console_msg_autoscan_off = "[CETMM] 已禁用自動掃描。" ,
14 | console_msg_autoapear_on = "[CETMM] 現在隨著控制台自動打開。" ,
15 | console_msg_autoapear_off = "[CETMM] 不在隨著控制台自動打開。" ,
16 | console_msg_dofile_run = "[CETMM] 正在執行 %{dofilename}。" ,
17 | console_msg_dofile_done = "[CETMM] 執行完畢。" ,
18 | window_title = "Cyber Engine Tweaks模組管理器" ,
19 | button_dofiles = "Dofile腳本" ,
20 | button_scan = "掃描" ,
21 | button_autoscan_on = "自動掃描已啟用" ,
22 | button_autoscan_off = "自動掃描已禁用" ,
23 | button_autoappear_on = "自動顯示已啟用" ,
24 | button_autoappear_off = "自動顯示已禁用" ,
25 | text_help_manager_1 = "按【掃描】按鈕掃描您已安裝的Cyber Engine Tweaks模組。" ,
26 | text_help_manager_2 = "勾選或取消勾選模組前的複選框以啟用或禁用該模組。" ,
27 | text_help_manager_3 = "將游戲的【設定】-【影像】中的【視窗模式】更改為【無邊框視窗】,以避免在按【掃描】時被彈出到桌面上。" ,
28 | text_help_manager_4 = "啟用/禁用模組後,按控制台上的【Reload ALL Mods】按鈕以重新加載模組。" ,
29 | text_help_manager_5 = "按【自動掃描】按鈕以啟用模組管理器加載後自動掃描的功能。" ,
30 | text_help_dofiles_1 = "您可以在這裡不需要輸入任何代碼一鍵運行您喜愛的“dofile()”腳本模組。" ,
31 | text_help_dofiles_2 = "按【Dofile腳本資料夾】按鈕打開資料夾。把您的 *.lua 腳本放進該文件裡。" ,
32 | text_help_dofiles_3 = "按【掃描】按鈕以刷新腳本列表。" ,
33 | text_help_dofiles_4 = "加載腳本列表後,按它們前面的【執行】按鈕以一鍵運行它們。" ,
34 | text_help_dofiles_5 = "您可以根據需要刪除示例的Dofile腳本。" ,
35 | text_no_dofiles = "您沒有任何dofile腳本..." ,
36 | text_please_scan = "請先掃描模組..." ,
37 | button_mods_folder = "模组資料夾" ,
38 | button_dofile_folder = "Dofile腳本資料夾" ,
39 | button_dofile_run = "執行" ,
40 | console_msg_mod_enable = "[CETMM] 模组%{modname}已啟用。" ,
41 | console_msg_mod_enable_error = "[CETMM] 嘗試啟用、%{modname}模组時出錯" ,
42 | console_msg_mod_disable = "[CETMM] 模组%{modname}已禁用。" ,
43 | console_msg_mod_disable_error = "[CETMM] 嘗試禁用%{modname}模组時出錯" ,
44 | text_select_settings = "設置" ,
45 | text_select_lang = "選擇語言(需要字體支持)" ,
46 | tooltip_btn_settings = "設置" ,
47 | tooltip_btn_help = "幫助",
48 | text_error_window_1 = "錯誤!!" ,
49 | text_error_window_2 = "CET模組管理器無法加載運行庫!" ,
50 | -- text_error_window_3 = "Please make sure it's installed correctly." ,
51 | -- text_error_window_4 = "1. Try to uninstall the old version first, and make a clean installation." ,
52 | -- text_error_window_5 = "2. If you are using vortex, try to install manually." ,
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/scripts/modules/CETMM.lua:
--------------------------------------------------------------------------------
1 | ---@class CETMM
2 | CETMM = {}
3 |
4 | local m_gui ---@type gui
5 | local m_event ---@type event
6 | local m_hotkeys ---@type hotkeys
7 | local m_options ---@type options
8 | local m_locale ---@type locale
9 | local m_dofiles ---@type dofiles
10 | local m_version ---@type string
11 | local m_backend ---@type backend
12 | local m_uninstalled = false
13 |
14 | function CETMM.GetUISystem()
15 | return m_gui
16 | end
17 |
18 | function CETMM.GetOptions()
19 | return m_options
20 | end
21 |
22 | function CETMM.GetLocale()
23 | return m_locale
24 | end
25 |
26 | function CETMM.GetDofiles()
27 | return m_dofiles
28 | end
29 |
30 | function CETMM.GetVersion()
31 | return m_version
32 | end
33 |
34 | function CETMM.GetBackEnd()
35 | return m_backend
36 | end
37 |
38 | function CETMM.IsUninstalled()
39 | return m_uninstalled
40 | end
41 |
42 | function CETMM.Initialize()
43 | m_options = require ("modules/options")
44 | m_locale = require ("modules/locale")
45 | m_dofiles = require ("modules/dofiles")
46 | m_event = require ("modules/event")
47 | m_hotkeys = require("modules/hotkeys")
48 | m_version = require ("modules/version")
49 |
50 | -- Load config
51 | m_options.Load()
52 | m_locale.Initialize()
53 |
54 | registerForEvent("onInit", function()
55 | -- init
56 | m_backend = require ("modules/backend")
57 | m_uninstalled = m_backend.GetUninstall().IsAsiRemoved()
58 | if not m_uninstalled then
59 | m_backend.GetMods().Scan()
60 | m_dofiles.Scan()
61 | end
62 | m_gui = require ("modules/gui")
63 | end)
64 | end
65 |
66 | function CETMM.Update()
67 | registerForEvent("onUpdate", function()
68 |
69 | end)
70 | end
71 |
72 | function CETMM.Event() -- Hotkey, Console event..
73 | if not m_uninstalled then
74 | m_event.Register()
75 | m_hotkeys.Register()
76 | end
77 | end
78 |
79 | function CETMM.Render()
80 | registerForEvent("onDraw", function()
81 | m_gui.Initialize()
82 | m_gui.Render()
83 | end)
84 | end
85 |
86 | function CETMM.Shutdown()
87 | registerForEvent("onShutdown", function()
88 | m_options.Save()
89 | end)
90 | end
--------------------------------------------------------------------------------
/scripts/modules/backend.lua:
--------------------------------------------------------------------------------
1 | ---@class backend
2 | local backend = {
3 | GetMods = CETMMEXT.GetMods, ---@type fun(): Mods
4 | OpenModsFolder = CETMMEXT.OpenModsFolder, ---@type fun(): void
5 | OpenDofilesFolder = CETMMEXT.OpenDofilesFolder, ---@type fun(): void
6 | OpenUrl = CETMMEXT.OpenUrl, ---@type fun(url: string): void
7 | GetFonts = CETMMEXT.GetFonts, ---@type fun(): Fonts
8 | GetUninstall = CETMMEXT.GetUninstall ---@type fun(): Uninstall
9 | }
10 |
11 | return backend
--------------------------------------------------------------------------------
/scripts/modules/core/class/dofile.lua:
--------------------------------------------------------------------------------
1 | local helper = require ("modules/core/helper")
2 |
3 | ---@class dofile
4 | ---@field m_name string
5 | ---@field m_path path
6 | ---@field m_formated_name string
7 | local _dofile = {}
8 | _dofile.__index = _dofile
9 |
10 | -- dofile constructor
11 |
12 | setmetatable(_dofile, {
13 | __call = function (cls, ...)
14 | return cls.New(...)
15 | end,
16 | })
17 |
18 |
19 | ---@param aPath path
20 | ---@return dofile
21 | function _dofile.New(aPath) -- path: aPath
22 | local self = setmetatable({}, _dofile)
23 | self.m_name = aPath:Stem():ToString()
24 | self.m_path = aPath
25 | self.m_formated_name = helper.format_name(self.m_name)
26 | return self
27 | end
28 |
29 | -- methods
30 |
31 | function _dofile.GetName(self)
32 | return self.m_name
33 | end
34 |
35 | function _dofile.GetPath(self)
36 | return self.m_path
37 | end
38 |
39 | function _dofile.GetFormatedName(self)
40 | return self.m_formated_name
41 | end
42 |
43 | function _dofile.Run(self)
44 | local rt, err = pcall(dofile, self.m_path:ToString())
45 | if (not rt) then
46 | print(string.format("Error executing \"%s\": %s.", self.m_formated_name, err))
47 | end
48 | end
49 |
50 | return _dofile
--------------------------------------------------------------------------------
/scripts/modules/core/class/path.lua:
--------------------------------------------------------------------------------
1 | -- Path class
2 |
3 | ---@class path
4 | ---@field m_path string
5 | local path = {}
6 | path.__index = path
7 |
8 | -- private functions
9 |
10 | ---@param aPath string
11 | ---@return string
12 | local function sanitize_Path(aPath)
13 | local sanitized_Path = aPath:gsub("\\", "/")
14 | return sanitized_Path
15 | end
16 |
17 | -- Path constructor
18 |
19 | setmetatable(path, {
20 | __call = function (cls, ...)
21 | return cls.New(...)
22 | end,
23 | })
24 |
25 | ---@param aPath string
26 | ---@return path
27 | function path.New(aPath)
28 | local self = setmetatable({}, path)
29 | self.m_path = sanitize_Path(aPath)
30 | return self
31 | end
32 |
33 | -- Path methods
34 |
35 | ---Path "/" operator
36 | ---@param lhs string|path
37 | ---@param rhs string|path
38 | ---@return path
39 | function path.__div (lhs, rhs)
40 | local new_path = (type(lhs) == "string" and sanitize_Path(lhs) or lhs:ToString()) .. "/" .. (type(rhs) == "string" and sanitize_Path(rhs) or rhs:ToString())
41 | return path.New(new_path)
42 | end
43 |
44 | function path.ToString(self)
45 | return self.m_path
46 | end
47 |
48 | function path.ToWinFormat(self)
49 | local win_formated = self.m_path:gsub("/", "\\")
50 | return win_formated
51 | end
52 |
53 | function path.ToWinExcFormat(self)
54 | local win_excformated = self.m_path:gsub("/", "\\\\")
55 | return win_excformated
56 | end
57 |
58 | function path.Append(self, aPath)
59 | local new_path = self.m_path .. "/" .. aPath
60 | return path.New(new_path)
61 | end
62 |
63 | function path.ParentPath(self)
64 | local parent_Path
65 | if self.m_path == "/" then
66 | parent_Path = self.m_path
67 | elseif self.m_path:find("/$") then
68 | parent_Path = self.m_path:gsub("/[^/]-/$", "")
69 | else
70 | parent_Path = self.m_path:gsub("/[^/]-$", "")
71 | end
72 | return path.New(parent_Path)
73 | end
74 |
75 | function path.FileName(self)
76 | local file_name = self.m_path:gsub(".*/", "")
77 | return path.New(file_name)
78 | end
79 |
80 | function path.Stem(self)
81 | local stem
82 | local file_name = self:FileName():ToString()
83 | if file_name:find("^%.[^%.]*$") then
84 | stem = file_name
85 | else
86 | stem = file_name:gsub("%.[^%.]-$", "")
87 | end
88 | return path.New(stem)
89 | end
90 |
91 | function path.Extension(self)
92 | local file_name = self:FileName():ToString()
93 | local extension = file_name:match("%.[^%.]*$")
94 | return path.New(extension)
95 | end
96 |
97 | function path.HasExtension(self)
98 | local file_name = self:FileName():ToString()
99 | return file_name:find("%.[^%.]*$") and true or false
100 | end
101 |
102 | return path
--------------------------------------------------------------------------------
/scripts/modules/core/helper.lua:
--------------------------------------------------------------------------------
1 | ---@class helper
2 | local helper = {}
3 |
4 | ---@param aName string
5 | function helper.format_name(aName)
6 | if string.find(aName, "_") then
7 | return string.gsub(" "..string.gsub(aName, "_" , " "), "%W%l", string.upper):sub(2)
8 | elseif string.find(aName, "-") then
9 | return string.gsub(" "..string.gsub(aName, "-" , " "), "%W%l", string.upper):sub(2)
10 | else
11 | return string.gsub(" "..aName, "%W%l", string.upper):sub(2)
12 | end
13 | end
14 |
15 | -- https://gist.github.com/haggen/2fd643ea9a261fea2094#gistcomment-2339900
16 | ---@param length number
17 | function helper.randomHash(length)
18 | local charset = {} do -- [0-9a-zA-Z]
19 | for c = 48, 57 do table.insert(charset, string.char(c)) end
20 | for c = 65, 90 do table.insert(charset, string.char(c)) end
21 | for c = 97, 122 do table.insert(charset, string.char(c)) end
22 | end
23 | if not length or length <= 0 then return '' end
24 | math.randomseed(os.clock()^5)
25 | return helper.randomHash(length - 1) .. charset[math.random(1, #charset)]
26 | end
27 |
28 | return helper
--------------------------------------------------------------------------------
/scripts/modules/dofiles.lua:
--------------------------------------------------------------------------------
1 | local path = require ("modules/core/class/path")
2 | local _dofile = require ("modules/core/class/dofile")
3 |
4 | ---@class dofiles
5 | ---@field m_data dofile[]
6 | local dofiles = {
7 | m_data = {},
8 | }
9 |
10 | -- public methods
11 |
12 | function dofiles.Scan()
13 | dofiles.Clear()
14 |
15 | local dofile_list = dir("dofiles")
16 | for _, entry in ipairs(dofile_list) do
17 | if entry.type == "file" and entry.name:match("(.+)%.lua$") then
18 | local entry_path = path("dofiles") / entry.name
19 | table.insert(dofiles.m_data, _dofile(entry_path))
20 | end
21 | end
22 |
23 | end
24 |
25 | function dofiles.Clear()
26 | dofiles.m_data = {}
27 | end
28 |
29 | function dofiles.Get()
30 | return dofiles.m_data
31 | end
32 |
33 | return dofiles
--------------------------------------------------------------------------------
/scripts/modules/event.lua:
--------------------------------------------------------------------------------
1 | ---@class event
2 | local event = {}
3 |
4 | function event.Register()
5 | registerForEvent("onOverlayOpen", function()
6 | if CETMM.GetOptions().m_autoappear then
7 | CETMM.GetUISystem().GetWindow().m_draw = true
8 | end
9 | end)
10 |
11 | registerForEvent("onOverlayClose", function()
12 | if CETMM.GetOptions().m_autoappear then
13 | CETMM.GetUISystem().GetWindow().m_draw = false
14 | end
15 | end)
16 | end
17 |
18 | return event
19 |
--------------------------------------------------------------------------------
/scripts/modules/gui/dpi.lua:
--------------------------------------------------------------------------------
1 | ---@class dpi
2 | local dpi = {}
3 | local m_fontscale
4 | local m_displayRes = {}
5 | local m_defaultVars = {}
6 |
7 | local function get_vars()
8 | local style = ImGui.GetStyle()
9 | local vars = {
10 | WindowPadding = { x = style.WindowPadding.x, y = style.WindowPadding.y },
11 | WindowRounding = style.WindowRounding,
12 | ChildRounding = style.ChildRounding,
13 | PopupRounding = style.PopupRounding,
14 | FramePadding = { x = style.FramePadding.x, y = style.FramePadding.y },
15 | FrameRounding = style.FrameRounding,
16 | ItemSpacing = { x = style.ItemSpacing.x, y = style.ItemSpacing.y },
17 | ItemInnerSpacing = { x = style.ItemInnerSpacing.x, y = style.ItemInnerSpacing.y },
18 | CellPadding = { x = style.CellPadding.x, y = style.CellPadding.y },
19 | TouchExtraPadding = { x = style.TouchExtraPadding.x, y = style.TouchExtraPadding.y },
20 | IndentSpacing = style.IndentSpacing,
21 | ColumnsMinSpacing = style.ColumnsMinSpacing,
22 | ScrollbarSize = style.ScrollbarSize,
23 | ScrollbarRounding = style.ScrollbarRounding,
24 | GrabMinSize = style.GrabMinSize,
25 | GrabRounding = style.GrabRounding,
26 | LogSliderDeadzone = style.LogSliderDeadzone,
27 | TabRounding = style.TabRounding,
28 | TabMinWidthForCloseButton = style.TabMinWidthForCloseButton,
29 | DisplayWindowPadding = { x = style.DisplayWindowPadding.x, y = style.DisplayWindowPadding.y },
30 | DisplaySafeAreaPadding = { x = style.DisplaySafeAreaPadding.x, y = style.DisplaySafeAreaPadding.y },
31 | MouseCursorScale = style.MouseCursorScale;
32 | }
33 | return vars
34 | end
35 |
36 | function dpi.Initialize()
37 | m_displayRes.x, m_displayRes.y = GetDisplayResolution()
38 | m_fontscale = ImGui.GetFontSize()/18
39 | m_defaultVars = get_vars()
40 | end
41 |
42 | function dpi.GetDisplayResolution()
43 | return m_displayRes
44 | end
45 |
46 |
47 | function dpi.GetScale()
48 | return m_fontscale
49 | end
50 |
51 | function dpi.Scale(aNumber)
52 | return aNumber * m_fontscale
53 | end
54 |
55 | function dpi.PushScale()
56 | local vars = get_vars()
57 | local style = ImGui.GetStyle()
58 | for key, value in pairs(vars) do
59 | if type(value) == "table" then
60 | style[key].x = math.floor(value.x * m_fontscale)
61 | style[key].y = math.floor(value.y * m_fontscale)
62 | else
63 | style[key] = math.floor(value * m_fontscale)
64 | end
65 | end
66 | end
67 |
68 | function dpi.PopScale()
69 | local style = ImGui.GetStyle()
70 | for key, value in pairs(m_defaultVars) do
71 | if type(value) == "table" then
72 | style[key].x = value.x
73 | style[key].y = value.y
74 | else
75 | style[key] = value
76 | end
77 | end
78 | end
79 |
80 | return dpi
--------------------------------------------------------------------------------
/scripts/modules/gui/init.lua:
--------------------------------------------------------------------------------
1 | ---@class gui
2 | local gui = {}
3 | local m_dpi = require ("modules/gui/dpi")
4 | local m_themeSys = require ("modules/gui/themeSys")
5 | local m_widgets = require ("modules/gui/widgets")
6 | local m_window = require ("modules/gui/window")
7 | local m_windows = require ("modules/gui/windows")
8 | local m_initialized = false
9 | local m_showUninstall = false
10 |
11 | function gui.GetDPI()
12 | return m_dpi
13 | end
14 |
15 | function gui.GetThemeSys()
16 | return m_themeSys
17 | end
18 |
19 | function gui.GetWindow()
20 | return m_window
21 | end
22 |
23 | function gui.Initialize()
24 | if not m_initialized then
25 | m_showUninstall = CETMM.IsUninstalled()
26 | m_dpi.Initialize()
27 | if m_showUninstall then
28 | m_themeSys.Load("default", true)
29 | else
30 | m_themeSys.Initialize()
31 | m_window.Initialize()
32 | end
33 | m_initialized = true
34 | end
35 | end
36 |
37 | function gui.Render()
38 | m_themeSys.PushTheme()
39 | if m_showUninstall then
40 | m_windows.uninstall.Render()
41 | else
42 | m_window.Render()
43 | end
44 | m_themeSys.PopTheme()
45 | end
46 |
47 | return gui
--------------------------------------------------------------------------------
/scripts/modules/gui/themeSys.lua:
--------------------------------------------------------------------------------
1 | ---@class themeSys
2 | local themeSys = {
3 | themes = {
4 | default = require("modules/gui/themes/default"),
5 | ua_special = require("modules/gui/themes/ua_special"),
6 | white = require("modules/gui/themes/white"),
7 | },
8 | currentTheme = {} ---@type baseTheme
9 | }
10 |
11 | function themeSys.Initialize()
12 | local theme = CETMM.GetOptions().m_theme
13 | themeSys.Load(theme)
14 | end
15 |
16 | ---Load theme
17 | ---@param aTheme string
18 | ---@param aNoSave? bool
19 | function themeSys.Load(aTheme, aNoSave)
20 | if themeSys.themes[aTheme] then
21 | themeSys.currentTheme = themeSys.themes[aTheme]
22 | else
23 | themeSys.currentTheme = themeSys.themes.default
24 | spdlog.error(string.format("Failed to load theme %s, loaded default theme instead.", aTheme))
25 | end
26 | if not aNoSave then
27 | CETMM.GetOptions().m_theme = themeSys.currentTheme:GetName()
28 | CETMM.GetOptions().Save()
29 | end
30 | end
31 |
32 | function themeSys.GetCurrentTheme()
33 | return themeSys.currentTheme
34 | end
35 |
36 | ---@param aStyle ImGuiCol
37 | ---@param aColor number[]
38 | function themeSys.PushColor(aStyle, aColor)
39 | ImGui.PushStyleColor(aStyle, unpack(aColor))
40 | end
41 |
42 | function themeSys.PushTheme()
43 | themeSys.PushColor(ImGuiCol.TitleBg, themeSys.currentTheme:GetStyleColor("TitleBg" ))
44 | themeSys.PushColor(ImGuiCol.TitleBgCollapsed, themeSys.currentTheme:GetStyleColor("TitleBgCollapsed" ))
45 | themeSys.PushColor(ImGuiCol.TitleBgActive, themeSys.currentTheme:GetStyleColor("TitleBgActive" ))
46 | themeSys.PushColor(ImGuiCol.Border, themeSys.currentTheme:GetStyleColor("Border" ))
47 | themeSys.PushColor(ImGuiCol.WindowBg, themeSys.currentTheme:GetStyleColor("WindowBg" ))
48 | themeSys.PushColor(ImGuiCol.ScrollbarBg, themeSys.currentTheme:GetStyleColor("ScrollbarBg" ))
49 | themeSys.PushColor(ImGuiCol.ScrollbarGrab, themeSys.currentTheme:GetStyleColor("ScrollbarGrab" ))
50 | themeSys.PushColor(ImGuiCol.ScrollbarGrabHovered, themeSys.currentTheme:GetStyleColor("ScrollbarGrabHovered" ))
51 | themeSys.PushColor(ImGuiCol.ScrollbarGrabActive, themeSys.currentTheme:GetStyleColor("ScrollbarGrabActive" ))
52 | themeSys.PushColor(ImGuiCol.ResizeGrip, themeSys.currentTheme:GetStyleColor("ResizeGrip" ))
53 | themeSys.PushColor(ImGuiCol.ResizeGripHovered, themeSys.currentTheme:GetStyleColor("ResizeGripHovered" ))
54 | themeSys.PushColor(ImGuiCol.ResizeGripActive, themeSys.currentTheme:GetStyleColor("ResizeGripActive" ))
55 | themeSys.PushColor(ImGuiCol.Text, themeSys.currentTheme:GetStyleColor("Text" ))
56 | themeSys.PushColor(ImGuiCol.Header, themeSys.currentTheme:GetStyleColor("Header" ))
57 | themeSys.PushColor(ImGuiCol.HeaderHovered, themeSys.currentTheme:GetStyleColor("HeaderHovered" ))
58 | themeSys.PushColor(ImGuiCol.HeaderActive, themeSys.currentTheme:GetStyleColor("HeaderActive" ))
59 | themeSys.PushColor(ImGuiCol.CheckMark, themeSys.currentTheme:GetStyleColor("CheckMark" ))
60 | themeSys.PushColor(ImGuiCol.FrameBg, themeSys.currentTheme:GetStyleColor("FrameBg" ))
61 | themeSys.PushColor(ImGuiCol.FrameBgHovered, themeSys.currentTheme:GetStyleColor("FrameBgHovered" ))
62 | themeSys.PushColor(ImGuiCol.FrameBgActive, themeSys.currentTheme:GetStyleColor("FrameBgActive" ))
63 | themeSys.PushColor(ImGuiCol.Button, themeSys.currentTheme:GetStyleColor("Button" ))
64 | themeSys.PushColor(ImGuiCol.ButtonHovered, themeSys.currentTheme:GetStyleColor("ButtonHovered" ))
65 | themeSys.PushColor(ImGuiCol.ButtonActive, themeSys.currentTheme:GetStyleColor("ButtonActive" ))
66 | themeSys.PushColor(ImGuiCol.Separator, themeSys.currentTheme:GetStyleColor("Separator" ))
67 | themeSys.PushColor(ImGuiCol.PopupBg, themeSys.currentTheme:GetStyleColor("PopupBg" ))
68 |
69 | ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, 8, 8)
70 | ImGui.PushStyleVar(ImGuiStyleVar.WindowRounding, 0)
71 | end
72 |
73 | function themeSys.PopTheme()
74 | ImGui.PopStyleColor(25)
75 | ImGui.PopStyleVar(2)
76 | end
77 |
78 | return themeSys
--------------------------------------------------------------------------------
/scripts/modules/gui/themes/baseTheme.lua:
--------------------------------------------------------------------------------
1 | ---@class baseTheme
2 | ---@operator call(string):baseTheme
3 | local baseTheme = {
4 | name = "default",
5 | colors = {},
6 | }
7 | baseTheme.__index = baseTheme
8 |
9 | -- baseTheme constructor
10 |
11 | setmetatable(baseTheme, {
12 | __call = function (cls, ...)
13 | return cls.New(...)
14 | end,
15 | })
16 |
17 |
18 | ---@param aName string
19 | ---@return baseTheme
20 | function baseTheme.New(aName) -- path: aPath
21 | local self = setmetatable({}, baseTheme)
22 | self.name = aName or self.name
23 | return self
24 | end
25 |
26 | -- methods
27 | function baseTheme.GetName(self)
28 | return self.name
29 | end
30 |
31 | ---Safe call method
32 | ---@param self baseTheme
33 | ---@param aMethod string
34 | ---@param ... any
35 | ---@return any
36 | function baseTheme.Call(self, aMethod, ...)
37 | if self[aMethod] then
38 | return self[aMethod](self, ...)
39 | end
40 | end
41 |
42 | ---Only call method in specific theme
43 | ---@param self baseTheme
44 | ---@param aThemeName string
45 | ---@param aMethod string
46 | ---@param ... any
47 | ---@return any
48 | function baseTheme.CallIf(self, aThemeName, aMethod, ...)
49 | if self.name == aThemeName and self[aMethod] then
50 | return self[aMethod](self, ...)
51 | end
52 | end
53 |
54 | ---@param self baseTheme
55 | ---@param aGuiColor string
56 | ---@return float[]
57 | function baseTheme.GetStyleColor(self, aGuiColor)
58 | return self.colors[aGuiColor]
59 | end
60 |
61 | return baseTheme
--------------------------------------------------------------------------------
/scripts/modules/gui/themes/default.lua:
--------------------------------------------------------------------------------
1 | local baseTheme = require("modules/gui/themes/baseTheme")
2 |
3 | ---@class themeDefault : baseTheme
4 | local themeDefault = baseTheme("default")
5 |
6 | themeDefault.colors = {
7 | Text = { 1 , 0.44, 0.4 , 1 },
8 | TextDisabled = { 0.48, 0.39, 0.40, 1 },
9 | WindowBg = { 0.06, 0.04, 0.06, 0.9 },
10 | ChildBg = { 0.06, 0.04, 0.06, 0.9 },
11 | PopupBg = { 0.06, 0.04, 0.06, 0.9 },
12 | Border = { 0.3 , 0.07, 0.08, 1 },
13 | BorderShadow = { 0 , 0 , 0 , 0 },
14 | FrameBg = { 0.57, 0.17, 0.16, 1 },
15 | FrameBgHovered = { 0.32, 0.09, 0.11, 1 },
16 | FrameBgActive = { 0.1 , 0.05, 0.05, 1 },
17 | FrameBgDisabled = { 0.48, 0.39, 0.40, 1 },
18 | FrameBgHoveredDisabled = { 0.48, 0.39, 0.40, 1 },
19 | FrameBgActiveDisabled = { 0.48, 0.39, 0.40, 1 },
20 | TitleBg = { 0.06, 0.04, 0.06, 0.9 },
21 | TitleBgActive = { 0.06, 0.04, 0.06, 0.9 },
22 | TitleBgCollapsed = { 0.06, 0.04, 0.06, 0.9 },
23 | MenuBarBg = { 0 , 0 , 0 , 0 },
24 | ScrollbarBg = { 0.06, 0.04, 0.06, 0 },
25 | ScrollbarGrab = { 0.57, 0.17, 0.16, 1 },
26 | ScrollbarGrabHovered = { 0.57, 0.17, 0.16, 1 },
27 | ScrollbarGrabActive = { 0.57, 0.17, 0.16, 1 },
28 | CheckMark = { 1 , 0.44, 0.4 , 1 },
29 | CheckMarkTrueDisabled = { 0.34, 0.22, 0.24, 1 },
30 | CheckMarkFalseDisabled = { 0.48, 0.39, 0.40, 1 },
31 | SliderGrab = { 0 , 0 , 0 , 0 },
32 | SliderGrabActive = { 0 , 0 , 0 , 0 },
33 | Button = { 0.57, 0.17, 0.16, 1 },
34 | ButtonHovered = { 0.45, 0.13, 0.14, 1 },
35 | ButtonActive = { 0.57, 0.17, 0.16, 1 },
36 | Header = { 0.22, 0.64, 0.69, 0.2 },
37 | HeaderHovered = { 0.22, 0.64, 0.69, 0.3 },
38 | HeaderActive = { 0.22, 0.64, 0.69, 0.5 },
39 | Separator = { 0.3 , 0.07, 0.08, 1 },
40 | SeparatorHovered = { 0.29, 0.77, 0.79, 1 },
41 | SeparatorActive = { 0.29, 0.77, 0.79, 1 },
42 | ResizeGrip = { 0.06, 0.04, 0.06, 1 },
43 | ResizeGripHovered = { 1 , 0.44, 0.4 , 1 },
44 | ResizeGripActive = { 1 , 0.44, 0.4 , 1 },
45 | Tab = { 0 , 0 , 0 , 0 },
46 | TabHovered = { 0 , 0 , 0 , 0 },
47 | TabActive = { 0 , 0 , 0 , 0 },
48 | TabUnfocused = { 0 , 0 , 0 , 0 },
49 | TabUnfocusedActive = { 0 , 0 , 0 , 0 },
50 | DockingPreview = { 0 , 0 , 0 , 0 },
51 | DockingEmptyBg = { 0 , 0 , 0 , 0 },
52 | PlotLines = { 0 , 0 , 0 , 0 },
53 | PlotLinesHovered = { 0 , 0 , 0 , 0 },
54 | PlotHistogram = { 0 , 0 , 0 , 0 },
55 | PlotHistogramHovered = { 0 , 0 , 0 , 0 },
56 | TextSelectedBg = { 0 , 0 , 0 , 0 },
57 | DragDropTarget = { 0 , 0 , 0 , 0 },
58 | NavHighlight = { 0 , 0 , 0 , 0 },
59 | NavWindowingHighlight = { 0 , 0 , 0 , 0 },
60 | NavWindowingDimBg = { 0 , 0 , 0 , 0 },
61 | ModalWindowDimBg = { 0 , 0 , 0 , 0 },
62 | ModalWindowDarkening = { 0 , 0 , 0 , 0 },
63 | COUNT = { 0 , 0 , 0 , 0 },
64 | CustomToggleOn = { 0.29, 0.77, 0.79, 1 },
65 | CustomToggleOnHovered = { 0.20, 0.56, 0.59, 1 },
66 | CustomToggleOnActive = { 0.29, 0.77, 0.79, 1 },
67 | CustomToggleOnText = { 0 , 0 , 0 , 1 },
68 | CustomToggleOnDisable = { 0.04, 0.11, 0.12, 1 },
69 | CustomToggleOnDisableHovered = { 0.05, 0.16, 0.16, 1 },
70 | CustomToggleOnDisableText = { 0.06, 0.18, 0.2 , 1 },
71 | CustomToggleOff = { 0.57, 0.18, 0.16, 1 },
72 | CustomToggleOffHovered = { 0.45, 0.13, 0.14, 1 },
73 | CustomToggleOffDisable = { 0.1 , 0.04, 0.07, 1 },
74 | CustomToggleOffDisableHovered = { 0.16, 0.06, 0.07, 1 },
75 | CustomToggleOffDisableText = { 0.22, 0.07, 0.07, 1 },
76 | AltText = { 0.29, 0.77, 0.79, 1 },
77 | Hidden = { 0 , 0 , 0 , 0 },
78 | }
79 |
80 | return themeDefault
--------------------------------------------------------------------------------
/scripts/modules/gui/themes/ua_special.lua:
--------------------------------------------------------------------------------
1 | local baseTheme = require("modules/gui/themes/baseTheme")
2 |
3 | ---@class themeUA : baseTheme
4 | local themeUA = baseTheme("ua_special")
5 |
6 | themeUA.colors = {
7 | Text = { 0.96, 0.81, 0.00, 1 },
8 | TextDisabled = { 0.48, 0.39, 0.40, 1 },
9 | WindowBg = { 0.05, 0.11, 0.18, 0.9 },
10 | ChildBg = { 0.05, 0.11, 0.18, 0.9 },
11 | PopupBg = { 0.05, 0.11, 0.18, 0.9 },
12 | Border = { 0.60, 0.51, 0.00, 1 },
13 | BorderShadow = { 0 , 0 , 0 , 0 },
14 | FrameBg = { 0.00, 0.35, 0.71, 1 },
15 | FrameBgHovered = { 0.00, 0.44, 0.90, 1 },
16 | FrameBgActive = { 0.00, 0.35, 0.71, 1 },
17 | FrameBgDisabled = { 0.48, 0.39, 0.40, 1 },
18 | FrameBgHoveredDisabled = { 0.48, 0.39, 0.40, 1 },
19 | FrameBgActiveDisabled = { 0.48, 0.39, 0.40, 1 },
20 | TitleBg = { 0.05, 0.11, 0.18, 0.9 },
21 | TitleBgActive = { 0.05, 0.11, 0.18, 0.9 },
22 | TitleBgCollapsed = { 0.05, 0.11, 0.18, 0.9 },
23 | MenuBarBg = { 0.05, 0.11, 0.18, 0.9 },
24 | ScrollbarBg = { 0.06, 0.04, 0.06, 0 },
25 | ScrollbarGrab = { 0.00, 0.35, 0.71, 1 },
26 | ScrollbarGrabHovered = { 0.00, 0.44, 0.90, 1 },
27 | ScrollbarGrabActive = { 0.00, 0.35, 0.71, 1 },
28 | CheckMark = { 0.96, 0.81, 0.00, 1 },
29 | CheckMarkTrueDisabled = { 0.34, 0.22, 0.24, 1 },
30 | CheckMarkFalseDisabled = { 0.48, 0.39, 0.40, 1 },
31 | SliderGrab = { 0 , 0 , 0 , 0 },
32 | SliderGrabActive = { 0 , 0 , 0 , 0 },
33 | Button = { 0.00, 0.35, 0.71, 1 },
34 | ButtonHovered = { 0.00, 0.44, 0.90, 1 },
35 | ButtonActive = { 0.00, 0.35, 0.71, 1 },
36 | Header = { 0.00, 0.21, 0.43, 0.6 },
37 | HeaderHovered = { 0.00, 0.21, 0.43, 0.9 },
38 | HeaderActive = { 0.00, 0.21, 0.43, 0.9 },
39 | Separator = { 0.60, 0.51, 0.00, 0.5 },
40 | SeparatorHovered = { 0.29, 0.77, 0.79, 1 },
41 | SeparatorActive = { 0.29, 0.77, 0.79, 1 },
42 | ResizeGrip = { 0.05, 0.11, 0.18, 1 },
43 | ResizeGripHovered = { 0.96, 0.81, 0.00, 1 },
44 | ResizeGripActive = { 0.96, 0.81, 0.00, 1 },
45 | Tab = { 0 , 0 , 0 , 0 },
46 | TabHovered = { 0 , 0 , 0 , 0 },
47 | TabActive = { 0 , 0 , 0 , 0 },
48 | TabUnfocused = { 0 , 0 , 0 , 0 },
49 | TabUnfocusedActive = { 0 , 0 , 0 , 0 },
50 | DockingPreview = { 0 , 0 , 0 , 0 },
51 | DockingEmptyBg = { 0 , 0 , 0 , 0 },
52 | PlotLines = { 0 , 0 , 0 , 0 },
53 | PlotLinesHovered = { 0 , 0 , 0 , 0 },
54 | PlotHistogram = { 0 , 0 , 0 , 0 },
55 | PlotHistogramHovered = { 0 , 0 , 0 , 0 },
56 | TextSelectedBg = { 0 , 0 , 0 , 0 },
57 | DragDropTarget = { 0 , 0 , 0 , 0 },
58 | NavHighlight = { 0 , 0 , 0 , 0 },
59 | NavWindowingHighlight = { 0 , 0 , 0 , 0 },
60 | NavWindowingDimBg = { 0 , 0 , 0 , 0 },
61 | ModalWindowDimBg = { 0 , 0 , 0 , 0 },
62 | ModalWindowDarkening = { 0 , 0 , 0 , 0 },
63 | COUNT = { 0 , 0 , 0 , 0 },
64 | CustomToggleOn = { 0.96, 0.81, 0.00, 1 },
65 | CustomToggleOnHovered = { 0.81, 0.67, 0.00, 1 },
66 | CustomToggleOnActive = { 0.96, 0.81, 0.00, 1 },
67 | CustomToggleOnText = { 0.00, 0.44, 0.90, 1 },
68 | CustomToggleOnDisable = { 0.04, 0.11, 0.12, 1 },
69 | CustomToggleOnDisableHovered = { 0.05, 0.16, 0.16, 1 },
70 | CustomToggleOnDisableText = { 0.06, 0.18, 0.2 , 1 },
71 | CustomToggleOff = { 0.57, 0.18, 0.16, 1 },
72 | CustomToggleOffHovered = { 0.45, 0.13, 0.14, 1 },
73 | CustomToggleOffDisable = { 0.1 , 0.04, 0.07, 1 },
74 | CustomToggleOffDisableHovered = { 0.16, 0.06, 0.07, 1 },
75 | CustomToggleOffDisableText = { 0.22, 0.07, 0.07, 1 },
76 | AltText = { 0.00, 0.44, 0.90, 1 },
77 | Hidden = { 0 , 0 , 0 , 0 },
78 | }
79 |
80 | function themeUA.RenderFooter(self)
81 | ImGui.TableSetColumnIndex(1)
82 | ImGui.PushStyleColor(ImGuiCol.Text, unpack(self.colors.Border))
83 | ImGui.Text("We stand with Ukraine!")
84 | ImGui.PopStyleColor(1)
85 | end
86 |
87 | return themeUA
--------------------------------------------------------------------------------
/scripts/modules/gui/themes/white.lua:
--------------------------------------------------------------------------------
1 | local baseTheme = require("modules/gui/themes/baseTheme")
2 |
3 | ---@class themeWhite : baseTheme
4 | local themeWhite = baseTheme("white")
5 |
6 | themeWhite.states = {}
7 |
8 | themeWhite.def_colors = {
9 | Text = { 1 , 1 , 1 , 1 },
10 | TextDisabled = { 1 , 1 , 1 , 1 },
11 | WindowBg = { 1 , 1 , 1 , 1 },
12 | ChildBg = { 1 , 1 , 1 , 1 },
13 | PopupBg = { 1 , 1 , 1 , 1 },
14 | Border = { 1 , 1 , 1 , 1 },
15 | BorderShadow = { 1 , 1 , 1 , 1 },
16 | FrameBg = { 1 , 1 , 1 , 1 },
17 | FrameBgHovered = { 1 , 1 , 1 , 1 },
18 | FrameBgActive = { 1 , 1 , 1 , 1 },
19 | FrameBgDisabled = { 1 , 1 , 1 , 1 },
20 | FrameBgHoveredDisabled = { 1 , 1 , 1 , 1 },
21 | FrameBgActiveDisabled = { 1 , 1 , 1 , 1 },
22 | TitleBg = { 1 , 1 , 1 , 1 },
23 | TitleBgActive = { 1 , 1 , 1 , 1 },
24 | TitleBgCollapsed = { 1 , 1 , 1 , 1 },
25 | MenuBarBg = { 1 , 1 , 1 , 1 },
26 | ScrollbarBg = { 1 , 1 , 1 , 1 },
27 | ScrollbarGrab = { 1 , 1 , 1 , 1 },
28 | ScrollbarGrabHovered = { 1 , 1 , 1 , 1 },
29 | ScrollbarGrabActive = { 1 , 1 , 1 , 1 },
30 | CheckMark = { 1 , 1 , 1 , 1 },
31 | CheckMarkTrueDisabled = { 1 , 1 , 1 , 1 },
32 | CheckMarkFalseDisabled = { 1 , 1 , 1 , 1 },
33 | SliderGrab = { 1 , 1 , 1 , 1 },
34 | SliderGrabActive = { 1 , 1 , 1 , 1 },
35 | Button = { 1 , 1 , 1 , 1 },
36 | ButtonHovered = { 1 , 1 , 1 , 1 },
37 | ButtonActive = { 1 , 1 , 1 , 1 },
38 | Header = { 1 , 1 , 1 , 1 },
39 | HeaderHovered = { 1 , 1 , 1 , 1 },
40 | HeaderActive = { 1 , 1 , 1 , 1 },
41 | Separator = { 1 , 1 , 1 , 1 },
42 | SeparatorHovered = { 1 , 1 , 1 , 1 },
43 | SeparatorActive = { 1 , 1 , 1 , 1 },
44 | ResizeGrip = { 1 , 1 , 1 , 1 },
45 | ResizeGripHovered = { 1 , 1 , 1 , 1 },
46 | ResizeGripActive = { 1 , 1 , 1 , 1 },
47 | Tab = { 1 , 1 , 1 , 1 },
48 | TabHovered = { 1 , 1 , 1 , 1 },
49 | TabActive = { 1 , 1 , 1 , 1 },
50 | TabUnfocused = { 1 , 1 , 1 , 1 },
51 | TabUnfocusedActive = { 1 , 1 , 1 , 1 },
52 | DockingPreview = { 1 , 1 , 1 , 1 },
53 | DockingEmptyBg = { 1 , 1 , 1 , 1 },
54 | PlotLines = { 1 , 1 , 1 , 1 },
55 | PlotLinesHovered = { 1 , 1 , 1 , 1 },
56 | PlotHistogram = { 1 , 1 , 1 , 1 },
57 | PlotHistogramHovered = { 1 , 1 , 1 , 1 },
58 | TextSelectedBg = { 1 , 1 , 1 , 1 },
59 | DragDropTarget = { 1 , 1 , 1 , 1 },
60 | NavHighlight = { 1 , 1 , 1 , 1 },
61 | NavWindowingHighlight = { 1 , 1 , 1 , 1 },
62 | NavWindowingDimBg = { 1 , 1 , 1 , 1 },
63 | ModalWindowDimBg = { 1 , 1 , 1 , 1 },
64 | ModalWindowDarkening = { 1 , 1 , 1 , 1 },
65 | COUNT = { 1 , 1 , 1 , 1 },
66 | CustomToggleOn = { 1 , 1 , 1 , 1 },
67 | CustomToggleOnHovered = { 1 , 1 , 1 , 1 },
68 | CustomToggleOnActive = { 1 , 1 , 1 , 1 },
69 | CustomToggleOnText = { 1 , 1 , 1 , 1 },
70 | CustomToggleOnDisable = { 1 , 1 , 1 , 1 },
71 | CustomToggleOnDisableHovered = { 1 , 1 , 1 , 1 },
72 | CustomToggleOnDisableText = { 1 , 1 , 1 , 1 },
73 | CustomToggleOff = { 1 , 1 , 1 , 1 },
74 | CustomToggleOffHovered = { 1 , 1 , 1 , 1 },
75 | CustomToggleOffDisable = { 1 , 1 , 1 , 1 },
76 | CustomToggleOffDisableHovered = { 1 , 1 , 1 , 1 },
77 | CustomToggleOffDisableText = { 1 , 1 , 1 , 1 },
78 | AltText = { 1 , 1 , 1 , 1 },
79 | Hidden = { 1 , 1 , 1 , 1 },
80 | }
81 |
82 | themeWhite.hvr_colors = {
83 | Text = { 0.20, 0.20, 0.20, 1 },
84 | TextDisabled = { 0.48, 0.39, 0.40, 1 },
85 | WindowBg = { 1 , 1 , 1 , 0.9 },
86 | ChildBg = { 1 , 1 , 1 , 0.9 },
87 | PopupBg = { 1 , 1 , 1 , 0.9 },
88 | Border = { 0.5 , 0.5 , 0.5 , 1 },
89 | BorderShadow = { 0 , 0 , 0 , 0 },
90 | FrameBg = { 1 , 1 , 1 , 1 },
91 | FrameBgHovered = { 0.80, 0.80, 0.80, 1 },
92 | FrameBgActive = { 1 , 1 , 1 , 1 },
93 | FrameBgDisabled = { 0.48, 0.39, 0.40, 1 },
94 | FrameBgHoveredDisabled = { 0.48, 0.39, 0.40, 1 },
95 | FrameBgActiveDisabled = { 0.48, 0.39, 0.40, 1 },
96 | TitleBg = { 1 , 1 , 1 , 0.9 },
97 | TitleBgActive = { 1 , 1 , 1 , 0.9 },
98 | TitleBgCollapsed = { 1 , 1 , 1 , 0.9 },
99 | MenuBarBg = { 1 , 1 , 1 , 0.9 },
100 | ScrollbarBg = { 0.06, 0.04, 0.06, 0 },
101 | ScrollbarGrab = { 1 , 1 , 1 , 1 },
102 | ScrollbarGrabHovered = { 0.80, 0.80, 0.80, 1 },
103 | ScrollbarGrabActive = { 1 , 1 , 1 , 1 },
104 | CheckMark = { 0.20, 0.20, 0.20, 1 },
105 | CheckMarkTrueDisabled = { 0.20, 0.20, 0.20, 1 },
106 | CheckMarkFalseDisabled = { 0.20, 0.20, 0.20, 1 },
107 | SliderGrab = { 0 , 0 , 0 , 0 },
108 | SliderGrabActive = { 0 , 0 , 0 , 0 },
109 | Button = { 1 , 1 , 1 , 1 },
110 | ButtonHovered = { 0.80, 0.80, 0.80, 1 },
111 | ButtonActive = { 1 , 1 , 1 , 1 },
112 | Header = { 0.80, 0.80, 0.80, 0.6 },
113 | HeaderHovered = { 0.80, 0.80, 0.80, 0.9 },
114 | HeaderActive = { 0.80, 0.80, 0.80, 0.9 },
115 | Separator = { 0.5 , 0.5 , 0.5 , 1 },
116 | SeparatorHovered = { 0.5 , 0.5 , 0.5 , 1 },
117 | SeparatorActive = { 0.5 , 0.5 , 0.5 , 1 },
118 | ResizeGrip = { 0.80, 0.80, 0.80, 1 },
119 | ResizeGripHovered = { 0.70, 0.70, 0.70, 1 },
120 | ResizeGripActive = { 0.70, 0.70, 0.70, 1 },
121 | Tab = { 0 , 0 , 0 , 0 },
122 | TabHovered = { 0 , 0 , 0 , 0 },
123 | TabActive = { 0 , 0 , 0 , 0 },
124 | TabUnfocused = { 0 , 0 , 0 , 0 },
125 | TabUnfocusedActive = { 0 , 0 , 0 , 0 },
126 | DockingPreview = { 0 , 0 , 0 , 0 },
127 | DockingEmptyBg = { 0 , 0 , 0 , 0 },
128 | PlotLines = { 0 , 0 , 0 , 0 },
129 | PlotLinesHovered = { 0 , 0 , 0 , 0 },
130 | PlotHistogram = { 0 , 0 , 0 , 0 },
131 | PlotHistogramHovered = { 0 , 0 , 0 , 0 },
132 | TextSelectedBg = { 0 , 0 , 0 , 0 },
133 | DragDropTarget = { 0 , 0 , 0 , 0 },
134 | NavHighlight = { 0 , 0 , 0 , 0 },
135 | NavWindowingHighlight = { 0 , 0 , 0 , 0 },
136 | NavWindowingDimBg = { 0 , 0 , 0 , 0 },
137 | ModalWindowDimBg = { 0 , 0 , 0 , 0 },
138 | ModalWindowDarkening = { 0 , 0 , 0 , 0 },
139 | COUNT = { 0 , 0 , 0 , 0 },
140 | CustomToggleOn = { 0.80, 0.80, 0.80, 1 },
141 | CustomToggleOnHovered = { 0.70, 0.70, 0.70, 1 },
142 | CustomToggleOnActive = { 0.80, 0.80, 0.80, 1 },
143 | CustomToggleOnText = { 0.20, 0.20, 0.20, 1 },
144 | CustomToggleOnDisable = { 0.04, 0.11, 0.12, 1 },
145 | CustomToggleOnDisableHovered = { 0.05, 0.16, 0.16, 1 },
146 | CustomToggleOnDisableText = { 0.06, 0.18, 0.2 , 1 },
147 | CustomToggleOff = { 0.57, 0.18, 0.16, 1 },
148 | CustomToggleOffHovered = { 0.45, 0.13, 0.14, 1 },
149 | CustomToggleOffDisable = { 0.1 , 0.04, 0.07, 1 },
150 | CustomToggleOffDisableHovered = { 0.16, 0.06, 0.07, 1 },
151 | CustomToggleOffDisableText = { 0.22, 0.07, 0.07, 1 },
152 | AltText = { 0.80, 0.80, 0.80, 1 },
153 | Hidden = { 0 , 0 , 0 , 0 },
154 | }
155 |
156 | ---@param self themeWhite
157 | ---@param aGuiColor string
158 | ---@return float[]
159 | function themeWhite.GetStyleColor(self, aGuiColor)
160 | for window, hovering in pairs(self.states) do
161 | if hovering then
162 | return self.hvr_colors[aGuiColor]
163 | end
164 | end
165 | return self.def_colors[aGuiColor]
166 | end
167 |
168 | ---@param aWindow string
169 | function themeWhite.GetHoverState(self, aWindow)
170 | self.states[aWindow] = ImGui.IsWindowHovered(bit32.bor(ImGuiHoveredFlags.RootAndChildWindows, ImGuiHoveredFlags.AllowWhenBlockedByActiveItem, ImGuiHoveredFlags.AllowWhenBlockedByPopup))
171 | end
172 |
173 | return themeWhite
--------------------------------------------------------------------------------
/scripts/modules/gui/widgets/btnToggle.lua:
--------------------------------------------------------------------------------
1 | local dpi = require ("modules/gui/dpi")
2 | local themeSys = require ("modules/gui/themeSys")
3 |
4 | -- config
5 | local padding_x = 5
6 | local padding_y = 5
7 |
8 | ---@param aLabel string|string[]
9 | ---@param aValue boolean
10 | ---@param aSizeX? number
11 | ---@param aSizeY? number
12 | ---@param aAutoscale? boolean
13 | local function btnToggle(aLabel, aValue, aSizeX, aSizeY, aAutoscale)
14 | if type(aLabel) == "table" then
15 | aLabel = aValue and aLabel[1] or aLabel[2]
16 | end
17 | aSizeX = aSizeX or 0
18 | aSizeY = aSizeY or 0
19 | aAutoscale = aAutoscale==nil or aAutoscale
20 | if aAutoscale then
21 | aSizeX = dpi.Scale(aSizeX)
22 | aSizeY = dpi.Scale(aSizeY)
23 | end
24 | local imgui_style = ImGui.GetStyle()
25 | ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, imgui_style.FramePadding.x + dpi.Scale(padding_x), imgui_style.FramePadding.y + dpi.Scale(padding_y))
26 | if aValue then
27 | themeSys.PushColor(ImGuiCol.Button, themeSys.GetCurrentTheme():GetStyleColor("CustomToggleOn"))
28 | themeSys.PushColor(ImGuiCol.ButtonHovered, themeSys.GetCurrentTheme():GetStyleColor("CustomToggleOnHovered"))
29 | themeSys.PushColor(ImGuiCol.ButtonActive, themeSys.GetCurrentTheme():GetStyleColor("CustomToggleOnActive"))
30 | themeSys.PushColor(ImGuiCol.Text, themeSys.GetCurrentTheme():GetStyleColor("CustomToggleOnText"))
31 | else
32 | themeSys.PushColor(ImGuiCol.Button, themeSys.GetCurrentTheme():GetStyleColor("Button"))
33 | themeSys.PushColor(ImGuiCol.ButtonHovered, themeSys.GetCurrentTheme():GetStyleColor("ButtonHovered"))
34 | themeSys.PushColor(ImGuiCol.ButtonActive, themeSys.GetCurrentTheme():GetStyleColor("ButtonActive"))
35 | themeSys.PushColor(ImGuiCol.Text, themeSys.GetCurrentTheme():GetStyleColor("Text"))
36 | end
37 | if ImGui.Button(aLabel, aSizeX, aSizeY) then
38 | aValue = not aValue
39 | end
40 | ImGui.PopStyleColor(4)
41 | ImGui.PopStyleVar(1)
42 | return aValue
43 | end
44 |
45 | return btnToggle
--------------------------------------------------------------------------------
/scripts/modules/gui/widgets/button.lua:
--------------------------------------------------------------------------------
1 | local dpi = require ("modules/gui/dpi")
2 |
3 | -- config
4 | local padding_x = 5
5 | local padding_y = 5
6 |
7 | ---Button autoscales by default
8 | ---@param aLabel string
9 | ---@param aSizeX? number
10 | ---@param aSizeY? number
11 | ---@param aAutoscale? boolean
12 | ---@return boolean
13 | local function button(aLabel, aSizeX, aSizeY, aAutoscale)
14 | aSizeX = aSizeX or 0
15 | aSizeY = aSizeY or 0
16 | aAutoscale = aAutoscale==nil or aAutoscale
17 | if aAutoscale then
18 | aSizeX = dpi.Scale(aSizeX)
19 | aSizeY = dpi.Scale(aSizeY)
20 | end
21 | local imgui_style = ImGui.GetStyle()
22 | ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, imgui_style.FramePadding.x + dpi.Scale(padding_x), imgui_style.FramePadding.y + dpi.Scale(padding_y))
23 | local pressed = ImGui.Button(aLabel, aSizeX, aSizeY)
24 | ImGui.PopStyleVar(1)
25 | return pressed
26 | end
27 |
28 | return button
--------------------------------------------------------------------------------
/scripts/modules/gui/widgets/init.lua:
--------------------------------------------------------------------------------
1 | ---@class widget
2 | local widgets = {
3 | btnToggle = require ("modules/gui/widgets/btnToggle"),
4 | button = require("modules/gui/widgets/button"),
5 | }
6 |
7 | return widgets
--------------------------------------------------------------------------------
/scripts/modules/gui/window.lua:
--------------------------------------------------------------------------------
1 | local dpi = require("modules/gui/dpi")
2 | local i18n = require("modules/i18n")
3 | local languages = require("lang/lang")
4 | local widgets = require("modules/gui/widgets")
5 | local themeSys = require("modules/gui/themeSys")
6 | local options = CETMM.GetOptions()
7 | local mods = CETMM.GetBackEnd().GetMods()
8 | local dofiles = CETMM.GetDofiles()
9 |
10 | ---@class window
11 | local window = {
12 | m_draw = false,
13 | m_draw_about = false,
14 | m_about_title = "",
15 | m_about_text = "",
16 | m_over_size = false,
17 | m_btn_Dofiles = false,
18 | m_btn_Scan = false,
19 | m_btn_Help = false
20 | }
21 |
22 | local layout = {
23 | _ = 0,
24 | tb_modlist_height = 0,
25 | tb_footer_heigh = 0,
26 | header_btn_height = 0
27 | }
28 |
29 | local function renderAboutWindow()
30 | local draw_lastframe = window.m_draw_about
31 | window.m_draw_about = ImGui.Begin(window.m_about_title, window.m_draw_about, bit32.bor(ImGuiWindowFlags.NoSavedSettings, ImGuiWindowFlags.NoResize))
32 | if draw_lastframe then
33 | themeSys.GetCurrentTheme():CallIf("white", "GetHoverState", "about")
34 | ImGui.SetWindowPos(dpi.GetDisplayResolution().x / 2 - dpi.Scale(300),
35 | dpi.Scale(dpi.GetDisplayResolution().y * 0.1),
36 | ImGuiCond.FirstUseEver)
37 | ImGui.SetWindowSize(dpi.Scale(600),
38 | dpi.GetDisplayResolution().y * 0.8, ImGuiCond.FirstUseEver)
39 | ImGui.Text(window.m_about_text)
40 | ImGui.End()
41 | end
42 | end
43 |
44 | ---@param aFile string
45 | ---@return string
46 | local function loadFile(aFile)
47 | local text = ""
48 | local file = io.open(aFile)
49 | if file ~= nil then
50 | text = file:read("*a")
51 | file:close()
52 | end
53 | return text
54 | end
55 |
56 | local function settings_popup()
57 | ImGui.PushStyleVar(ImGuiStyleVar.WindowPadding, dpi.Scale(8), dpi.Scale(12))
58 | if ImGui.BeginPopup("Settings", ImGuiWindowFlags.NoMove) then
59 | ImGui.PushStyleVar(ImGuiStyleVar.ItemSpacing, dpi.Scale(8), dpi.Scale(15)) -- Menu item height
60 | ImGui.Text(i18n("text_select_settings"))
61 |
62 | options.m_autoappear = widgets.btnToggle({
63 | i18n("button_autoappear_on"), i18n("button_autoappear_off"),
64 | }, options.m_autoappear)
65 |
66 | ImGui.Separator()
67 |
68 | -- Theme
69 | if ImGui.BeginMenu(IconGlyphs.TelevisionGuide.."\t".."Theme") then
70 | if select(2, ImGui.MenuItem("Default", "", options.m_theme == "default")) then
71 | themeSys.Load("default")
72 | end
73 | if select(2, ImGui.MenuItem("UA Special", "", options.m_theme == "ua_special")) then
74 | themeSys.Load("ua_special")
75 | end
76 | if select(2, ImGui.MenuItem("White", "", options.m_theme == "white")) then
77 | themeSys.Load("white")
78 | end
79 | ImGui.EndMenu()
80 | end
81 |
82 | -- Language menu
83 | if ImGui.BeginMenu(IconGlyphs.Translate.."\t".."Language") then
84 | for _, entry in ipairs(languages) do
85 | if select(2, ImGui.MenuItem(entry.name, "", options.m_lang == entry.id)) then
86 | options.m_lang = entry.id
87 | CETMM.GetLocale().SetLocale()
88 | end
89 | end
90 |
91 | ImGui.EndMenu()
92 | end
93 |
94 | -- Select language hint text and help button
95 |
96 | ImGui.Separator()
97 |
98 | if ImGui.MenuItem(IconGlyphs.CardAccountDetails.."\t".."License") then
99 | window.m_about_title = "License"
100 | window.m_draw_about = true
101 | window.m_about_text = loadFile("LICENSE")
102 | end
103 | if ImGui.MenuItem(IconGlyphs.License.."\t".."Third Party License") then
104 | window.m_about_title = "Third Party License"
105 | window.m_draw_about = true
106 | window.m_about_text = loadFile("Third_Party_LICENSES")
107 | end
108 | if ImGui.MenuItem(IconGlyphs.Update.."\t"..string.format([[%s (v%s)]], "Check Update",
109 | CETMM.GetVersion())) then
110 | CETMM.GetBackEnd().OpenUrl("update")
111 | end
112 |
113 | ImGui.Separator()
114 |
115 | if ImGui.MenuItem(IconGlyphs.Coffee.."\t".."Buy me a coffee") then
116 | CETMM.GetBackEnd().OpenUrl("coffee")
117 | end
118 |
119 | ImGui.PopStyleVar() -- Pop menu item height
120 | ImGui.EndPopup()
121 | end
122 | ImGui.PopStyleVar()
123 | end
124 |
125 | -- public methods
126 |
127 | function window.Initialize()
128 | window.m_over_size = 600 * dpi.GetScale() > dpi.GetDisplayResolution().y * 0.8
129 | end
130 |
131 | function window.Render()
132 | local draw_lastframe = window.m_draw
133 | window.m_draw = ImGui.Begin(i18n("window_title").."###CETMM_MAIN_WINDOW", window.m_draw)
134 | if draw_lastframe then
135 | -- Hover check for white theme
136 | themeSys.GetCurrentTheme():CallIf("white", "GetHoverState", "main")
137 | -- Set window size and position
138 | ImGui.SetWindowPos(dpi.GetDisplayResolution().x / 2 - 210 * dpi.GetScale(),
139 | dpi.GetDisplayResolution().y / 2 - 320 * dpi.GetScale(),
140 | ImGuiCond.FirstUseEver)
141 | if window.m_over_size then
142 | ImGui.SetWindowSize(420 * dpi.GetScale(),
143 | dpi.GetDisplayResolution().y * 0.8, ImGuiCond.FirstUseEver)
144 | else
145 | ImGui.SetWindowSize(420 * dpi.GetScale(), 640 * dpi.GetScale(),
146 | ImGuiCond.FirstUseEver)
147 | end
148 |
149 | -- Header Buttons
150 | if ImGui.BeginTable("header_btns", 2, ImGuiTableFlags.NoSavedSettings) then
151 | ImGui.TableSetupColumn("col1", ImGuiTableColumnFlags.WidthStretch)
152 | ImGui.TableSetupColumn("col2", ImGuiTableColumnFlags.WidthFixed)
153 | ImGui.TableNextRow()
154 | ImGui.TableSetColumnIndex(0)
155 | window.m_btn_Dofiles = widgets.btnToggle(i18n("button_dofiles"),
156 | window.m_btn_Dofiles)
157 | ImGui.TableSetColumnIndex(1)
158 |
159 | -- Scan Button
160 | if widgets.button(IconGlyphs.MagnifyScan.." "..i18n("button_scan")) then
161 | mods.Scan()
162 | dofiles.Scan()
163 | end
164 |
165 | layout._, layout.header_btn_height = ImGui.GetItemRectSize()
166 |
167 | ImGui.SameLine()
168 |
169 | -- Settings Button
170 | if widgets.button(IconGlyphs.Cog, layout.header_btn_height, layout.header_btn_height, false) then
171 | ImGui.OpenPopup("Settings")
172 | end
173 | if ImGui.IsItemHovered() then
174 | ImGui.SetTooltip(i18n("tooltip_btn_settings"))
175 | end
176 |
177 | -- Settings Popup Menu
178 | settings_popup()
179 |
180 | ImGui.SameLine()
181 |
182 | -- Help Button
183 | window.m_btn_Help = widgets.btnToggle(IconGlyphs.Help, window.m_btn_Help,
184 | layout.header_btn_height,
185 | layout.header_btn_height, false)
186 | if ImGui.IsItemHovered() then
187 | ImGui.SetTooltip(i18n("tooltip_btn_help"))
188 | end
189 |
190 | ImGui.EndTable()
191 | end
192 |
193 | -- Helper Text
194 | if window.m_btn_Help then
195 | if not window.m_btn_Dofiles then
196 | ImGui.TextWrapped(i18n("text_help_manager_1"))
197 | ImGui.Spacing()
198 | ImGui.TextWrapped(i18n("text_help_manager_2"))
199 | ImGui.Spacing()
200 | ImGui.TextWrapped(i18n("text_help_manager_3"))
201 | ImGui.Spacing()
202 | ImGui.TextWrapped(i18n("text_help_manager_4"))
203 | ImGui.Spacing()
204 | ImGui.TextWrapped(i18n("text_help_manager_5"))
205 | else
206 | themeSys.PushColor(ImGuiCol.Text, themeSys.GetCurrentTheme():GetStyleColor("AltText"))
207 | ImGui.TextWrapped(i18n("text_help_dofiles_1"))
208 | ImGui.Spacing()
209 | ImGui.TextWrapped(i18n("text_help_dofiles_2"))
210 | ImGui.Spacing()
211 | ImGui.TextWrapped(i18n("text_help_dofiles_3"))
212 | ImGui.Spacing()
213 | ImGui.TextWrapped(i18n("text_help_dofiles_4"))
214 | ImGui.Spacing()
215 | ImGui.TextWrapped(i18n("text_help_dofiles_5"))
216 | ImGui.PopStyleColor(1)
217 | end
218 | ImGui.Spacing()
219 | end
220 |
221 | -- Mod List
222 | layout._, layout.tb_modlist_height = ImGui.GetContentRegionAvail()
223 | ImGui.PushStyleVar(ImGuiStyleVar.CellPadding, dpi.Scale(4), dpi.Scale(6))
224 | if ImGui.BeginTable("mod_list", 2, bit32.bor(
225 | ImGuiTableFlags.NoSavedSettings,
226 | ImGuiTableFlags.ScrollY), 0,
227 | layout.tb_modlist_height - layout.tb_footer_heigh -
228 | ImGui.GetStyle().ItemSpacing.y) then
229 |
230 | ImGui.TableSetupColumn("cb", ImGuiTableColumnFlags.WidthFixed)
231 | ImGui.TableSetupColumn("name", ImGuiTableColumnFlags.WidthStretch)
232 |
233 | -- Mod list
234 | if not window.m_btn_Dofiles then
235 | ImGui.PushStyleVar(ImGuiStyleVar.FramePadding, 5, 5)
236 |
237 | if #mods.GetCETMods() == 0 then -- Hint text when not scanned
238 | ImGui.TableNextRow(ImGuiTableRowFlags.None, 30 * dpi.GetScale())
239 | ImGui.TableSetColumnIndex(0)
240 | ImGui.Text(i18n.translate("text_please_scan"))
241 |
242 | else
243 | for _, entry in ipairs(mods.GetCETMods()) do
244 | ImGui.TableNextRow(ImGuiTableRowFlags.None, 30 * dpi.GetScale())
245 | ImGui.TableSetColumnIndex(0)
246 | ImGui.BeginDisabled(entry:GetName() == "cet_mod_manager")
247 | local state, pressed = ImGui.Checkbox("##" .. entry:GetName(),
248 | entry:IsEnabled())
249 | ImGui.EndDisabled()
250 | if pressed then
251 | entry:Toggle()
252 | end
253 | ImGui.TableSetColumnIndex(1)
254 | ImGui.Text(entry:GetFormatedName())
255 | end
256 | end
257 |
258 | ImGui.PopStyleVar(1)
259 |
260 | -- Dofile list
261 | else
262 | if (#dofiles.Get()) == 0 then -- Hint text when no dofiles
263 | ImGui.TableNextRow(ImGuiTableRowFlags.None, 30 * dpi.GetScale())
264 | ImGui.TableSetColumnIndex(0)
265 | ImGui.Text(i18n.translate("text_no_dofiles"))
266 |
267 | else
268 | for _, entry in ipairs(dofiles.Get()) do
269 | ImGui.TableNextRow(ImGuiTableRowFlags.None, 30 * dpi.GetScale())
270 | ImGui.TableSetColumnIndex(0)
271 | if widgets.button(i18n("button_dofile_run").."##" .. entry:GetName()) then
272 | entry:Run()
273 | end
274 | ImGui.TableSetColumnIndex(1)
275 | ImGui.Text(entry:GetFormatedName())
276 | end
277 | end
278 | end
279 |
280 | ImGui.EndTable()
281 | end
282 | ImGui.PopStyleVar(1)
283 |
284 | -- Footer Buttons
285 | if ImGui.BeginTable("footer_btns", 2, ImGuiTableFlags.NoSavedSettings) then
286 | ImGui.TableSetupColumn("col1", ImGuiTableColumnFlags.WidthStretch)
287 | ImGui.TableSetupColumn("col2", ImGuiTableColumnFlags.WidthFixed)
288 | ImGui.TableNextRow()
289 | ImGui.TableSetColumnIndex(0)
290 |
291 | if widgets.button(IconGlyphs.FolderHome.." "..i18n("button_mods_folder")) then
292 | CETMM.GetBackEnd().OpenModsFolder()
293 | end
294 |
295 | ImGui.SameLine()
296 |
297 | if widgets.button(IconGlyphs.FolderFile.." "..i18n("button_dofile_folder")) then
298 | CETMM.GetBackEnd().OpenDofilesFolder()
299 | end
300 |
301 | themeSys.GetCurrentTheme():CallIf("ua_special", "RenderFooter")
302 |
303 | ImGui.EndTable()
304 | end
305 | layout._, layout.tb_footer_heigh = ImGui.GetItemRectSize()
306 | ImGui.End()
307 | end
308 |
309 | renderAboutWindow()
310 | -- renderFontWidnow()
311 | end
312 |
313 | return window
314 |
--------------------------------------------------------------------------------
/scripts/modules/gui/windows/init.lua:
--------------------------------------------------------------------------------
1 | local windows = {
2 | uninstall = require("modules/gui/windows/uninstall"),
3 | }
4 |
5 |
6 | return windows
--------------------------------------------------------------------------------
/scripts/modules/gui/windows/uninstall.lua:
--------------------------------------------------------------------------------
1 | local backend = require("modules/backend")
2 | local EXT_Uninstall = backend.GetUninstall()
3 | local widget = require("modules/gui/widgets")
4 | local dpi = require("modules/gui/dpi")
5 |
6 | ---@class windows.uninstall
7 | local uninstall = {
8 | m_draw = true,
9 | m_removeConfig = false,
10 | m_removeDofiles = false,
11 | }
12 |
13 | function uninstall.Render()
14 | if uninstall.m_draw then
15 | ImGui.Begin(IconGlyphs.AlertDecagramOutline.." CET Mod Manager Uninstalled", bit32.bor(ImGuiWindowFlags.NoSavedSettings, ImGuiWindowFlags.AlwaysAutoResize, ImGuiWindowFlags.NoCollapse))
16 | ImGui.SetWindowPos((dpi.GetDisplayResolution().x - ImGui.GetWindowWidth())/2, (dpi.GetDisplayResolution().y - ImGui.GetWindowHeight())/2, ImGuiCond.Always)
17 | ImGui.Text("It appears that you have uninstalled CET Mod Manager,\nDo you want to remove the leftover files?")
18 | ImGui.Spacing()
19 | uninstall.m_removeConfig = ImGui.Checkbox("Remove the config file.", uninstall.m_removeConfig)
20 | uninstall.m_removeDofiles = ImGui.Checkbox("Remove the Dofile folder and it's contents.", uninstall.m_removeDofiles)
21 | ImGui.Spacing()
22 |
23 | if ImGui.BeginTable("footer_btns", 2, ImGuiTableFlags.NoSavedSettings) then
24 | ImGui.TableSetupColumn("col1", ImGuiTableColumnFlags.WidthStretch)
25 | ImGui.TableSetupColumn("col2", ImGuiTableColumnFlags.WidthStretch)
26 | ImGui.TableNextRow()
27 | ImGui.TableSetColumnIndex(1)
28 |
29 | if widget.button(IconGlyphs.CheckBold.."\tYes\t", 80, 0, true) then
30 | EXT_Uninstall.SetFilesToRemove(true, uninstall.m_removeConfig, uninstall.m_removeDofiles)
31 | uninstall.m_draw = false
32 | end
33 | ImGui.SameLine()
34 | if widget.button(IconGlyphs.CloseThick.."\tNo\t", 80, 0, true) then
35 | uninstall.m_draw = false
36 | end
37 |
38 | ImGui.EndTable()
39 | end
40 | ImGui.End()
41 | end
42 | end
43 |
44 | return uninstall
--------------------------------------------------------------------------------
/scripts/modules/hotkeys.lua:
--------------------------------------------------------------------------------
1 | local i18n = require("modules/i18n")
2 |
3 | ---@class hotkeys
4 | local hotkeys = {}
5 |
6 | -- public
7 | function hotkeys.Register()
8 | registerHotkey("hotkey_manager", i18n.translate("hotkey_manager"), function ()
9 | CETMM.GetUISystem().GetWindow().m_btn_Dofiles = false
10 | CETMM.GetUISystem().GetWindow().m_draw = not CETMM.GetUISystem().GetWindow().m_draw
11 | end)
12 |
13 | registerHotkey("hotkey_dofiles", i18n.translate("hotkey_dofiles"), function ()
14 | CETMM.GetUISystem().GetWindow().m_btn_Dofiles = true
15 | CETMM.GetUISystem().GetWindow().m_draw = not CETMM.GetUISystem().GetWindow().m_draw
16 | end)
17 | end
18 |
19 | return hotkeys
--------------------------------------------------------------------------------
/scripts/modules/i18n/README.md:
--------------------------------------------------------------------------------
1 | Forked from https://github.com/kikito/i18n.lua
2 |
3 | i18n.lua
4 | ========
5 |
6 | [](https://travis-ci.org/kikito/i18n.lua)
7 |
8 | A very complete i18n lib for Lua
9 |
10 | Description
11 | ===========
12 |
13 | ``` lua
14 | i18n = require 'i18n'
15 |
16 | -- loading stuff
17 | i18n.set('en.welcome', 'welcome to this program')
18 | i18n.load({
19 | en = {
20 | good_bye = "good-bye!",
21 | age_msg = "your age is %{age}.",
22 | phone_msg = {
23 | one = "you have one new message.",
24 | other = "you have %{count} new messages."
25 | }
26 | }
27 | })
28 | i18n.loadFile('path/to/your/project/i18n/de.lua') -- load German language file
29 | i18n.loadFile('path/to/your/project/i18n/fr.lua') -- load French language file
30 | … -- section 'using language files' below describes structure of files
31 |
32 | -- setting the translation context
33 | i18n.setLocale('en') -- English is the default locale anyway
34 |
35 | -- getting translations
36 | i18n.translate('welcome') -- Welcome to this program
37 | i18n('welcome') -- Welcome to this program
38 | i18n('age_msg', {age = 18}) -- Your age is 18.
39 | i18n('phone_msg', {count = 1}) -- You have one new message.
40 | i18n('phone_msg', {count = 2}) -- You have 2 new messages.
41 | i18n('good_bye') -- Good-bye!
42 |
43 | ```
44 |
45 | Interpolation
46 | =============
47 |
48 | You can interpolate variables in 3 different ways:
49 |
50 | ``` lua
51 | -- the most usual one
52 | i18n.set('variables', 'Interpolating variables: %{name} %{age}')
53 | i18n('variables', {name='john', 'age'=10}) -- Interpolating variables: john 10
54 |
55 | i18n.set('lua', 'Traditional Lua way: %d %s')
56 | i18n('lua', {1, 'message'}) -- Traditional Lua way: 1 message
57 |
58 | i18n.set('combined', 'Combined: %.q %.d %.o')
59 | i18n('combined', {name='john', 'age'=10}) -- Combined: john 10 12k
60 | ```
61 |
62 |
63 |
64 | Pluralization
65 | =============
66 |
67 | This lib implements the [unicode.org plural rules](http://cldr.unicode.org/index/cldr-spec/plural-rules). Just set the locale you want to use and it will deduce the appropiate pluralization rules:
68 |
69 | ``` lua
70 | i18n = require 'i18n'
71 |
72 | i18n.load({
73 | en = {
74 | msg = {
75 | one = "one message",
76 | other = "%{count} messages"
77 | }
78 | },
79 | ru = {
80 | msg = {
81 | one = "1 сообщение",
82 | few = "%{count} сообщения",
83 | many = "%{count} сообщений",
84 | other = "%{count} сообщения"
85 | }
86 | }
87 | })
88 |
89 | i18n('msg', {count = 1}) -- one message
90 | i18n.setLocale('ru')
91 | i18n('msg', {count = 5}) -- 5 сообщений
92 | ```
93 |
94 | The appropiate rule is chosen by finding the 'root' of the locale used: for example if the current locale is 'fr-CA', the 'fr' rules will be applied.
95 |
96 | If the provided functions are not enough (i.e. invented languages) it's possible to specify a custom pluralization function in the second parameter of setLocale. This function must return 'one', 'few', 'other', etc given a number.
97 |
98 | Fallbacks
99 | =========
100 |
101 | When a value is not found, the lib has several fallback mechanisms:
102 |
103 | * First, it will look in the current locale's parents. For example, if the locale was set to 'en-US' and the key 'msg' was not found there, it will be looked over in 'en'.
104 | * Second, if the value is not found in the locale ancestry, a 'fallback locale' (by default: 'en') can be used. If the fallback locale has any parents, they will be looked over too.
105 | * Third, if all the locales have failed, but there is a param called 'default' on the provided data, it will be used.
106 | * Otherwise the translation will return nil.
107 |
108 | The parents of a locale are found by splitting the locale by its hyphens. Other separation characters (spaces, underscores, etc) are not supported.
109 |
110 | Using language files
111 | ====================
112 |
113 | It might be a good idea to store each translation in a different file. This is supported via the 'i18n.loadFile' directive:
114 |
115 | ``` lua
116 | …
117 | i18n.loadFile('path/to/your/project/i18n/de.lua') -- German translation
118 | i18n.loadFile('path/to/your/project/i18n/en.lua') -- English translation
119 | i18n.loadFile('path/to/your/project/i18n/fr.lua') -- French translation
120 | …
121 | ```
122 |
123 | The German language file 'de.lua' should read:
124 |
125 | ``` lua
126 | return {
127 | de = {
128 | good_bye = "Auf Wiedersehen!",
129 | age_msg = "Ihr Alter beträgt %{age}.",
130 | phone_msg = {
131 | one = "Sie haben eine neue Nachricht.",
132 | other = "Sie haben %{count} neue Nachrichten."
133 | }
134 | }
135 | }
136 | ```
137 |
138 | If desired, you can also store all translations in one single file (eg. 'translations.lua'):
139 |
140 | ``` lua
141 | return {
142 | de = {
143 | good_bye = "Auf Wiedersehen!",
144 | age_msg = "Ihr Alter beträgt %{age}.",
145 | phone_msg = {
146 | one = "Sie haben eine neue Nachricht.",
147 | other = "Sie haben %{count} neue Nachrichten."
148 | }
149 | },
150 | fr = {
151 | good_bye = "Au revoir !",
152 | age_msg = "Vous avez %{age} ans.",
153 | phone_msg = {
154 | one = "Vous avez une noveau message.",
155 | other = "Vous avez %{count} noveaux messages."
156 | }
157 | },
158 | …
159 | }
160 | ```
161 |
162 | Specs
163 | =====
164 | This project uses [busted](https://github.com/Olivine-Labs/busted) for its specs. If you want to run the specs, you will have to install it first. Then just execute the following from the root inspect folder:
165 |
166 | busted
167 |
--------------------------------------------------------------------------------
/scripts/modules/i18n/init.lua:
--------------------------------------------------------------------------------
1 | local i18n = {}
2 |
3 | local store
4 | local locale
5 | local pluralizeFunction
6 | local defaultLocale = 'en_us'
7 | local fallbackLocale = defaultLocale
8 |
9 | local currentFilePath = "modules/i18n"
10 |
11 | local plural = require(currentFilePath .. '/plural')
12 | local interpolate = require(currentFilePath .. '/interpolate')
13 | local variants = require(currentFilePath .. '/variants')
14 | local version = require(currentFilePath .. '/version')
15 |
16 | i18n.plural, i18n.interpolate, i18n.variants, i18n.version, i18n._VERSION =
17 | plural, interpolate, variants, version, version
18 |
19 | -- private stuff
20 |
21 | local function dotSplit(str)
22 | local fields, length = {},0
23 | str:gsub("[^%.]+", function(c)
24 | length = length + 1
25 | fields[length] = c
26 | end)
27 | return fields, length
28 | end
29 |
30 | local function isPluralTable(t)
31 | return type(t) == 'table' and type(t.other) == 'string'
32 | end
33 |
34 | local function isPresent(str)
35 | return type(str) == 'string' and #str > 0
36 | end
37 |
38 | local function assertPresent(functionName, paramName, value)
39 | if isPresent(value) then return end
40 |
41 | local msg = "i18n.%s requires a non-empty string on its %s. Got %s (a %s value)."
42 | error(msg:format(functionName, paramName, tostring(value), type(value)))
43 | end
44 |
45 | local function assertPresentOrPlural(functionName, paramName, value)
46 | if isPresent(value) or isPluralTable(value) then return end
47 |
48 | local msg = "i18n.%s requires a non-empty string or plural-form table on its %s. Got %s (a %s value)."
49 | error(msg:format(functionName, paramName, tostring(value), type(value)))
50 | end
51 |
52 | local function assertPresentOrTable(functionName, paramName, value)
53 | if isPresent(value) or type(value) == 'table' then return end
54 |
55 | local msg = "i18n.%s requires a non-empty string or table on its %s. Got %s (a %s value)."
56 | error(msg:format(functionName, paramName, tostring(value), type(value)))
57 | end
58 |
59 | local function assertFunctionOrNil(functionName, paramName, value)
60 | if value == nil or type(value) == 'function' then return end
61 |
62 | local msg = "i18n.%s requires a function (or nil) on param %s. Got %s (a %s value)."
63 | error(msg:format(functionName, paramName, tostring(value), type(value)))
64 | end
65 |
66 | local function defaultPluralizeFunction(count)
67 | return plural.get(variants.root(i18n.getLocale()), count)
68 | end
69 |
70 | local function pluralize(t, data)
71 | assertPresentOrPlural('interpolatePluralTable', 't', t)
72 | data = data or {}
73 | local count = data.count or 1
74 | local plural_form = pluralizeFunction(count)
75 | return t[plural_form]
76 | end
77 |
78 | local function treatNode(node, data)
79 | if type(node) == 'string' then
80 | return interpolate(node, data)
81 | elseif isPluralTable(node) then
82 | return interpolate(pluralize(node, data), data)
83 | end
84 | return node
85 | end
86 |
87 | local function recursiveLoad(currentContext, data)
88 | local composedKey
89 | for k,v in pairs(data) do
90 | composedKey = (currentContext and (currentContext .. '.') or "") .. tostring(k)
91 | assertPresent('load', composedKey, k)
92 | assertPresentOrTable('load', composedKey, v)
93 | if type(v) == 'string' then
94 | i18n.set(composedKey, v)
95 | else
96 | recursiveLoad(composedKey, v)
97 | end
98 | end
99 | end
100 |
101 | local function localizedTranslate(key, loc, data)
102 | local path, length = dotSplit(loc .. "." .. key)
103 | local node = store
104 |
105 | for i=1, length do
106 | node = node[path[i]]
107 | if not node then return nil end
108 | end
109 |
110 | return treatNode(node, data)
111 | end
112 |
113 | -- public interface
114 |
115 | function i18n.set(key, value)
116 | assertPresent('set', 'key', key)
117 | assertPresentOrPlural('set', 'value', value)
118 |
119 | local path, length = dotSplit(key)
120 | local node = store
121 |
122 | for i=1, length-1 do
123 | key = path[i]
124 | node[key] = node[key] or {}
125 | node = node[key]
126 | end
127 |
128 | local lastKey = path[length]
129 | node[lastKey] = value
130 | end
131 |
132 | function i18n.translate(key, data)
133 | assertPresent('translate', 'key', key)
134 |
135 | data = data or {}
136 | local usedLocale = data.locale or locale
137 |
138 | local fallbacks = variants.fallbacks(usedLocale, fallbackLocale)
139 | for i=1, #fallbacks do
140 | local value = localizedTranslate(key, fallbacks[i], data)
141 | if value then return value end
142 | end
143 |
144 | return data.default
145 | end
146 |
147 | function i18n.setLocale(newLocale, newPluralizeFunction)
148 | assertPresent('setLocale', 'newLocale', newLocale)
149 | assertFunctionOrNil('setLocale', 'newPluralizeFunction', newPluralizeFunction)
150 | locale = newLocale
151 | pluralizeFunction = newPluralizeFunction or defaultPluralizeFunction
152 | end
153 |
154 | function i18n.setFallbackLocale(newFallbackLocale)
155 | assertPresent('setFallbackLocale', 'newFallbackLocale', newFallbackLocale)
156 | fallbackLocale = newFallbackLocale
157 | end
158 |
159 | function i18n.getFallbackLocale()
160 | return fallbackLocale
161 | end
162 |
163 | function i18n.getLocale()
164 | return locale
165 | end
166 |
167 | function i18n.reset()
168 | store = {}
169 | plural.reset()
170 | i18n.setLocale(defaultLocale)
171 | i18n.setFallbackLocale(defaultLocale)
172 | end
173 |
174 | function i18n.load(data)
175 | recursiveLoad(nil, data)
176 | end
177 |
178 | function i18n.loadFile(path)
179 | local chunk = assert(loadfile(path))
180 | local data = chunk()
181 | i18n.load(data)
182 | end
183 |
184 | setmetatable(i18n, {__call = function(_, ...) return i18n.translate(...) end})
185 |
186 | i18n.reset()
187 |
188 | return i18n
189 |
--------------------------------------------------------------------------------
/scripts/modules/i18n/interpolate.lua:
--------------------------------------------------------------------------------
1 | local unpack = unpack or table.unpack -- lua 5.2 compat
2 |
3 | local FORMAT_CHARS = { c=1, d=1, E=1, e=1, f=1, g=1, G=1, i=1, o=1, u=1, X=1, x=1, s=1, q=1, ['%']=1 }
4 |
5 | -- matches a string of type %{age}
6 | local function interpolateValue(string, variables)
7 | return string:gsub("(.?)%%{%s*(.-)%s*}",
8 | function (previous, key)
9 | if previous == "%" then
10 | return
11 | else
12 | return previous .. tostring(variables[key])
13 | end
14 | end)
15 | end
16 |
17 | -- matches a string of type %.d
18 | local function interpolateField(string, variables)
19 | return string:gsub("(.?)%%<%s*(.-)%s*>%.([cdEefgGiouXxsq])",
20 | function (previous, key, format)
21 | if previous == "%" then
22 | return
23 | else
24 | return previous .. string.format("%" .. format, variables[key] or "nil")
25 | end
26 | end)
27 | end
28 |
29 | local function escapePercentages(string)
30 | return string:gsub("(%%)(.?)", function(_, char)
31 | if FORMAT_CHARS[char] then
32 | return "%" .. char
33 | else
34 | return "%%" .. char
35 | end
36 | end)
37 | end
38 |
39 | local function unescapePercentages(string)
40 | return string:gsub("(%%%%)(.?)", function(_, char)
41 | if FORMAT_CHARS[char] then
42 | return "%" .. char
43 | else
44 | return "%%" .. char
45 | end
46 | end)
47 | end
48 |
49 | local function interpolate(pattern, variables)
50 | variables = variables or {}
51 | local result = pattern
52 | result = interpolateValue(result, variables)
53 | result = interpolateField(result, variables)
54 | result = escapePercentages(result)
55 | result = string.format(result, unpack(variables))
56 | result = unescapePercentages(result)
57 | return result
58 | end
59 |
60 | return interpolate
61 |
--------------------------------------------------------------------------------
/scripts/modules/i18n/plural.lua:
--------------------------------------------------------------------------------
1 | local plural = {}
2 | local defaultFunction = nil
3 | -- helper functions
4 |
5 | local function assertPresentString(functionName, paramName, value)
6 | if type(value) ~= 'string' or #value == 0 then
7 | local msg = "Expected param %s of function %s to be a string, but got %s (a value of type %s) instead"
8 | error(msg:format(paramName, functionName, tostring(value), type(value)))
9 | end
10 | end
11 |
12 | local function assertNumber(functionName, paramName, value)
13 | if type(value) ~= 'number' then
14 | local msg = "Expected param %s of function %s to be a number, but got %s (a value of type %s) instead"
15 | error(msg:format(paramName, functionName, tostring(value), type(value)))
16 | end
17 | end
18 |
19 | -- transforms "foo bar baz" into {'foo','bar','baz'}
20 | local function words(str)
21 | local result, length = {}, 0
22 | str:gsub("%S+", function(word)
23 | length = length + 1
24 | result[length] = word
25 | end)
26 | return result
27 | end
28 |
29 | local function isInteger(n)
30 | return n == math.floor(n)
31 | end
32 |
33 | local function between(value, min, max)
34 | return value >= min and value <= max
35 | end
36 |
37 | local function inside(v, list)
38 | for i=1, #list do
39 | if v == list[i] then return true end
40 | end
41 | return false
42 | end
43 |
44 |
45 | -- pluralization functions
46 |
47 | local pluralization = {}
48 |
49 | local f1 = function(n)
50 | return n == 1 and "one" or "other"
51 | end
52 | pluralization[f1] = words([[
53 | af asa bem bez bg bn brx ca cgg chr da de dv ee el
54 | en eo es et eu fi fo fur fy gl gsw gu ha haw he is
55 | it jmc kaj kcg kk kl ksb ku lb lg mas ml mn mr nah
56 | nb nd ne nl nn no nr ny nyn om or pa pap ps pt rm
57 | rof rwk saq seh sn so sq ss ssy st sv sw syr ta te
58 | teo tig tk tn ts ur ve vun wae xh xog zu
59 | ]])
60 |
61 | local f2 = function(n)
62 | return (n == 0 or n == 1) and "one" or "other"
63 | end
64 | pluralization[f2] = words("ak am bh fil guw hi ln mg nso ti tl wa")
65 |
66 | local f3 = function(n)
67 | if not isInteger(n) then return 'other' end
68 | return (n == 0 and "zero") or
69 | (n == 1 and "one") or
70 | (n == 2 and "two") or
71 | (between(n % 100, 3, 10) and "few") or
72 | (between(n % 100, 11, 99) and "many") or
73 | "other"
74 | end
75 | pluralization[f3] = {'ar'}
76 |
77 | local f4 = function()
78 | return "other"
79 | end
80 | pluralization[f4] = words([[
81 | az bm bo dz fa hu id ig ii ja jv ka kde kea km kn
82 | ko lo ms my root sah ses sg th to tr vi wo yo zh
83 | ]])
84 |
85 | local f5 = function(n)
86 | if not isInteger(n) then return 'other' end
87 | local n_10, n_100 = n % 10, n % 100
88 | return (n_10 == 1 and n_100 ~= 11 and 'one') or
89 | (between(n_10, 2, 4) and not between(n_100, 12, 14) and 'few') or
90 | ((n_10 == 0 or between(n_10, 5, 9) or between(n_100, 11, 14)) and 'many') or
91 | 'other'
92 | end
93 | pluralization[f5] = words('be bs hr ru sh sr uk')
94 |
95 | local f6 = function(n)
96 | if not isInteger(n) then return 'other' end
97 | local n_10, n_100 = n % 10, n % 100
98 | return (n_10 == 1 and not inside(n_100, {11,71,91}) and 'one') or
99 | (n_10 == 2 and not inside(n_100, {12,72,92}) and 'two') or
100 | (inside(n_10, {3,4,9}) and
101 | not between(n_100, 10, 19) and
102 | not between(n_100, 70, 79) and
103 | not between(n_100, 90, 99)
104 | and 'few') or
105 | (n ~= 0 and n % 1000000 == 0 and 'many') or
106 | 'other'
107 | end
108 | pluralization[f6] = {'br'}
109 |
110 | local f7 = function(n)
111 | return (n == 1 and 'one') or
112 | ((n == 2 or n == 3 or n == 4) and 'few') or
113 | 'other'
114 | end
115 | pluralization[f7] = {'cz', 'sk'}
116 |
117 | local f8 = function(n)
118 | return (n == 0 and 'zero') or
119 | (n == 1 and 'one') or
120 | (n == 2 and 'two') or
121 | (n == 3 and 'few') or
122 | (n == 6 and 'many') or
123 | 'other'
124 | end
125 | pluralization[f8] = {'cy'}
126 |
127 | local f9 = function(n)
128 | return (n >= 0 and n < 2 and 'one') or
129 | 'other'
130 | end
131 | pluralization[f9] = {'ff', 'fr', 'kab'}
132 |
133 | local f10 = function(n)
134 | return (n == 1 and 'one') or
135 | (n == 2 and 'two') or
136 | ((n == 3 or n == 4 or n == 5 or n == 6) and 'few') or
137 | ((n == 7 or n == 8 or n == 9 or n == 10) and 'many') or
138 | 'other'
139 | end
140 | pluralization[f10] = {'ga'}
141 |
142 | local f11 = function(n)
143 | return ((n == 1 or n == 11) and 'one') or
144 | ((n == 2 or n == 12) and 'two') or
145 | (isInteger(n) and (between(n, 3, 10) or between(n, 13, 19)) and 'few') or
146 | 'other'
147 | end
148 | pluralization[f11] = {'gd'}
149 |
150 | local f12 = function(n)
151 | local n_10 = n % 10
152 | return ((n_10 == 1 or n_10 == 2 or n % 20 == 0) and 'one') or
153 | 'other'
154 | end
155 | pluralization[f12] = {'gv'}
156 |
157 | local f13 = function(n)
158 | return (n == 1 and 'one') or
159 | (n == 2 and 'two') or
160 | 'other'
161 | end
162 | pluralization[f13] = words('iu kw naq se sma smi smj smn sms')
163 |
164 | local f14 = function(n)
165 | return (n == 0 and 'zero') or
166 | (n == 1 and 'one') or
167 | 'other'
168 | end
169 | pluralization[f14] = {'ksh'}
170 |
171 | local f15 = function(n)
172 | return (n == 0 and 'zero') or
173 | (n > 0 and n < 2 and 'one') or
174 | 'other'
175 | end
176 | pluralization[f15] = {'lag'}
177 |
178 | local f16 = function(n)
179 | if not isInteger(n) then return 'other' end
180 | if between(n % 100, 11, 19) then return 'other' end
181 | local n_10 = n % 10
182 | return (n_10 == 1 and 'one') or
183 | (between(n_10, 2, 9) and 'few') or
184 | 'other'
185 | end
186 | pluralization[f16] = {'lt'}
187 |
188 | local f17 = function(n)
189 | return (n == 0 and 'zero') or
190 | ((n % 10 == 1 and n % 100 ~= 11) and 'one') or
191 | 'other'
192 | end
193 | pluralization[f17] = {'lv'}
194 |
195 | local f18 = function(n)
196 | return((n % 10 == 1 and n ~= 11) and 'one') or
197 | 'other'
198 | end
199 | pluralization[f18] = {'mk'}
200 |
201 | local f19 = function(n)
202 | return (n == 1 and 'one') or
203 | ((n == 0 or
204 | (n ~= 1 and isInteger(n) and between(n % 100, 1, 19)))
205 | and 'few') or
206 | 'other'
207 | end
208 | pluralization[f19] = {'mo', 'ro'}
209 |
210 | local f20 = function(n)
211 | if n == 1 then return 'one' end
212 | if not isInteger(n) then return 'other' end
213 | local n_100 = n % 100
214 | return ((n == 0 or between(n_100, 2, 10)) and 'few') or
215 | (between(n_100, 11, 19) and 'many') or
216 | 'other'
217 | end
218 | pluralization[f20] = {'mt'}
219 |
220 | local f21 = function(n)
221 | if n == 1 then return 'one' end
222 | if not isInteger(n) then return 'other' end
223 | local n_10, n_100 = n % 10, n % 100
224 |
225 | return ((between(n_10, 2, 4) and not between(n_100, 12, 14)) and 'few') or
226 | ((n_10 == 0 or n_10 == 1 or between(n_10, 5, 9) or between(n_100, 12, 14)) and 'many') or
227 | 'other'
228 | end
229 | pluralization[f21] = {'pl'}
230 |
231 | local f22 = function(n)
232 | return (n == 0 or n == 1) and 'one' or
233 | 'other'
234 | end
235 | pluralization[f22] = {'shi'}
236 |
237 | local f23 = function(n)
238 | local n_100 = n % 100
239 | return (n_100 == 1 and 'one') or
240 | (n_100 == 2 and 'two') or
241 | ((n_100 == 3 or n_100 == 4) and 'few') or
242 | 'other'
243 | end
244 | pluralization[f23] = {'sl'}
245 |
246 | local f24 = function(n)
247 | return (isInteger(n) and (n == 0 or n == 1 or between(n, 11, 99)) and 'one')
248 | or 'other'
249 | end
250 | pluralization[f24] = {'tzm'}
251 |
252 | local pluralizationFunctions = {}
253 | for f,locales in pairs(pluralization) do
254 | for _,locale in ipairs(locales) do
255 | pluralizationFunctions[locale] = f
256 | end
257 | end
258 |
259 | -- public interface
260 |
261 | function plural.get(locale, n)
262 | assertPresentString('i18n.plural.get', 'locale', locale)
263 | assertNumber('i18n.plural.get', 'n', n)
264 |
265 | local f = pluralizationFunctions[locale] or defaultFunction
266 |
267 | return f(math.abs(n))
268 | end
269 |
270 | function plural.setDefaultFunction(f)
271 | defaultFunction = f
272 | end
273 |
274 | function plural.reset()
275 | defaultFunction = pluralizationFunctions['en']
276 | end
277 |
278 | plural.reset()
279 |
280 | return plural
281 |
--------------------------------------------------------------------------------
/scripts/modules/i18n/variants.lua:
--------------------------------------------------------------------------------
1 | local variants = {}
2 |
3 | local function reverse(arr, length)
4 | local result = {}
5 | for i=1, length do result[i] = arr[length-i+1] end
6 | return result, length
7 | end
8 |
9 | local function concat(arr1, len1, arr2, len2)
10 | for i = 1, len2 do
11 | arr1[len1 + i] = arr2[i]
12 | end
13 | return arr1, len1 + len2
14 | end
15 |
16 | function variants.ancestry(locale)
17 | local result, length, accum = {},0,nil
18 | locale:gsub("[^%-]+", function(c)
19 | length = length + 1
20 | accum = accum and (accum .. '-' .. c) or c
21 | result[length] = accum
22 | end)
23 | return reverse(result, length)
24 | end
25 |
26 | function variants.isParent(parent, child)
27 | return not not child:match("^".. parent .. "%-")
28 | end
29 |
30 | function variants.root(locale)
31 | return locale:match("[^%-]+")
32 | end
33 |
34 | function variants.fallbacks(locale, fallbackLocale)
35 | if locale == fallbackLocale or
36 | variants.isParent(fallbackLocale, locale) then
37 | return variants.ancestry(locale)
38 | end
39 | if variants.isParent(locale, fallbackLocale) then
40 | return variants.ancestry(fallbackLocale)
41 | end
42 |
43 | local ancestry1, length1 = variants.ancestry(locale)
44 | local ancestry2, length2 = variants.ancestry(fallbackLocale)
45 |
46 | return concat(ancestry1, length1, ancestry2, length2)
47 | end
48 |
49 | return variants
50 |
--------------------------------------------------------------------------------
/scripts/modules/i18n/version.lua:
--------------------------------------------------------------------------------
1 | return '0.9.2'
2 |
--------------------------------------------------------------------------------
/scripts/modules/locale.lua:
--------------------------------------------------------------------------------
1 | local i18n = require ("modules/i18n")
2 |
3 | ---@class locale
4 | local locale = {}
5 |
6 | function locale.Initialize()
7 | i18n.loadFile("lang/en_us.lua")
8 | locale.SetLocale()
9 | end
10 |
11 | function locale.SetLocale()
12 | i18n.loadFile(string.format("lang/%s.lua", CETMM.GetOptions().m_lang))
13 | i18n.setLocale(CETMM.GetOptions().m_lang)
14 | end
15 |
16 | return locale
--------------------------------------------------------------------------------
/scripts/modules/options.lua:
--------------------------------------------------------------------------------
1 | ---@class options
2 | ---@field m_lang string
3 | ---@field m_autoappear boolean
4 | ---@field m_theme string
5 | local options = {
6 | m_lang = "en_us",
7 | m_autoappear = true,
8 | m_theme = "default" -- change the default theme here
9 | }
10 |
11 | -- private functions
12 |
13 | -- set the option to default value if it doesn't exist in the config file
14 | local function setOption(val, def)
15 | if val == nil then
16 | return def
17 | else
18 | return val
19 | end
20 | end
21 |
22 | -- public methods
23 |
24 | function options.Load()
25 | local file = io.open("config.json", "r")
26 |
27 | if file then
28 | local config = json.decode(file:read("*a"))
29 | file:close()
30 |
31 | options.m_lang = setOption(config.lang, options.m_lang)
32 | options.m_autoappear = setOption(config.autoappear, options.m_autoappear)
33 | options.m_theme = setOption(config.theme, options.m_theme)
34 | end
35 |
36 | options.Save()
37 | end
38 |
39 | function options.Save()
40 | local config = {}
41 |
42 | config["lang"] = options.m_lang
43 | config["autoappear"] = options.m_autoappear
44 | config["theme"] = options.m_theme
45 |
46 | local file = io.open("config.json", "w")
47 | if file ~= nil then
48 | file:write(json.encode(config))
49 | file:close()
50 | end
51 | end
52 |
53 | return options
--------------------------------------------------------------------------------
/scripts/modules/types.lua:
--------------------------------------------------------------------------------
1 | ---Type defines for backend
2 | ---@meta
3 | ---@diagnostic disable
4 |
5 | ---@class FontStyle
6 | ---@field family string
7 | ---@field style string
8 |
9 | ---@class FontFamily
10 | ---@field family string
11 | ---@field styles FontStyle[]
12 |
13 | ---@class Fonts
14 | ---@field currentFamily FontFamily
15 | ---@field currentStyle FontStyle
16 | ---@field currentGlyph string
17 | ---@field currentSize number
18 | ---@field settingChanged boolean
19 | ---@field families FontFamily[]
20 | ---@field SetFont fun(aFontFamily: FontFamily, aFontStyle: FontStyle, aGlyph: string, aSize: number): nil
21 |
22 | ---@class Mod
23 | ---@field GetName fun(): string
24 | ---@field GetFormatedName fun(): string
25 | ---@field IsEnabled fun(): boolean
26 | ---@field Toggle fun(): nil
27 |
28 | ---@class Mods
29 | ---@field Scan fun(): nil
30 | ---@field GetCETMods fun(): Mod[]
31 |
32 | ---@class Uninstall
33 | ---@field IsAsiRemoved fun(): bool
34 | ---@field SetFilesToRemove fun(aRemoveFiles: bool, aRemoveConfig: bool, aRemoveDofiles: bool): nil
--------------------------------------------------------------------------------
/src/CETMM/CETMM.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "CETMM.h"
3 |
4 | void CETMM::Initialize()
5 | {
6 | GetUninstall().Initialize();
7 | }
8 |
9 | void CETMM::Shutdown()
10 | {
11 |
12 | // final execute;
13 | if (ShouldRestart())
14 | Get().restartGame();
15 |
16 | GetUninstall().Uninitialize();
17 | }
18 |
19 | CETMM& CETMM::Get()
20 | {
21 | static CETMM instance;
22 | return instance;
23 | }
24 |
25 | const Paths& CETMM::GetPaths()
26 | {
27 | return Get().m_paths;
28 | }
29 |
30 | Mods& CETMM::GetMods()
31 | {
32 | return Get().m_mods;
33 | }
34 |
35 | CETMMEXT& CETMM::GetCETMMEXT()
36 | {
37 | return Get().m_cetmmext;
38 | }
39 |
40 | Uninstall& CETMM::GetUninstall()
41 | {
42 | return Get().m_uninstall;
43 | }
44 |
45 | const bool CETMM::ShouldRestart()
46 | {
47 | return Get().m_restart;
48 | }
49 |
50 | void CETMM::SetRestart(bool aRestart)
51 | {
52 | Get().m_restart = aRestart;
53 | }
54 |
55 |
56 | void CETMM::restartGame()
57 | {
58 | STARTUPINFO lpStartupInfo;
59 | PROCESS_INFORMATION lpProcessInfo;
60 |
61 | ZeroMemory( &lpStartupInfo, sizeof( lpStartupInfo ) );
62 | lpStartupInfo.cb = sizeof( lpStartupInfo );
63 | ZeroMemory( &lpProcessInfo, sizeof( lpProcessInfo ) );
64 |
65 | LPWSTR cmdArgs = LPWSTR(L" -modded"); // launch game with redmod enabled
66 | CreateProcess( GetPaths().EXE().wstring().c_str(),
67 | cmdArgs, NULL, NULL,
68 | NULL, NULL, NULL, NULL,
69 | &lpStartupInfo,
70 | &lpProcessInfo
71 | );
72 | }
--------------------------------------------------------------------------------
/src/CETMM/CETMM.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Paths.h"
4 | #include "EXT/Mods.h"
5 | #include "EXT/CETMMEXT.h"
6 | #include "EXT/Uninstall.h"
7 |
8 | class CETMM
9 | {
10 | public:
11 | static void Initialize();
12 | static void Shutdown();
13 | static CETMM& Get();
14 |
15 | static const Paths& GetPaths();
16 | static Mods& GetMods();
17 | static CETMMEXT& GetCETMMEXT();
18 | static Uninstall& GetUninstall();
19 |
20 | static const bool ShouldRestart();
21 | static void SetRestart(bool aRestart);
22 |
23 | CETMM(const CETMM&) = delete;
24 | CETMM(CETMM&&) = delete;
25 | CETMM& operator=(const CETMM&) = delete;
26 | CETMM& operator=(CETMM&&) = delete;
27 |
28 | private:
29 | CETMM() {}
30 | ~CETMM() {}
31 |
32 | void restartGame();
33 |
34 | Paths m_paths;
35 | Mods m_mods;
36 | CETMMEXT m_cetmmext;
37 | Uninstall m_uninstall;
38 | bool m_restart {false};
39 | };
--------------------------------------------------------------------------------
/src/CETMM/EXT/Auth.cpp:
--------------------------------------------------------------------------------
1 | #include "Auth.h"
2 |
3 |
4 | void Auth::Initialize() {
5 | genAuthCode();
6 | writeAuthCodeToFile();
7 | writeRandNamesToFile();
8 | }
9 |
10 | void Auth::Uninitialize() {
11 | revertFiles();
12 | }
13 |
14 | bool Auth::Authenticate(std::string aAuthCode) {
15 | return aAuthCode == m_authCode;
16 | }
17 |
18 | std::string Auth::RandomizeName(std::string aClassName)
19 | {
20 | if (m_randNames.find(aClassName) != m_randNames.end())
21 | return m_randNames[aClassName];
22 | else
23 | {
24 | std::string rand_name = Utilities::random_string(m_randStrLength);
25 | m_randNames.insert({aClassName, rand_name});
26 | return rand_name;
27 | }
28 | }
29 |
30 | const std::string Auth::GetClassName(std::string aClassName)
31 | {
32 | if (m_randNames.find(aClassName) != m_randNames.end())
33 | {
34 | return m_randNames[aClassName];
35 | }
36 | else
37 | spdlog::error("Can't get the hash of class: {}.", aClassName);
38 | }
39 |
40 | void Auth::genAuthCode()
41 | {
42 | m_authCode = Utilities::random_string(m_randStrLength);
43 | }
44 |
45 | void Auth::writeAuthCodeToFile() {}
46 | void Auth::writeRandNamesToFile() {
47 | std::string file_content = fmt::format(\
48 | R"(local CETMMEXT = {{
49 | OpenFolder = {CETMM}.OpenFolder,
50 | OpenUrl = {CETMM}.OpenUrl,
51 | }}
52 |
53 | return CETMMEXT)",
54 | fmt::arg("CETMM", GetClassName("CETMM")));
55 | std::filesystem::path file_path = CETMM::GetPaths().RandNames();
56 | // write to file
57 | }
58 | void Auth::revertFiles() {
59 | // remove this file
60 | CETMM::GetPaths().RandNames();
61 | }
--------------------------------------------------------------------------------
/src/CETMM/EXT/Auth.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "pch.h"
4 |
5 | class Auth
6 | {
7 | public:
8 | void Initialize();
9 | void Uninitialize();
10 | bool Authenticate(std::string aAuthCode);
11 | std::string RandomizeName(std::string aClassName);
12 | const std::string GetClassName(std::string aClassName);
13 |
14 | private:
15 | int m_randStrLength {12};
16 | std::unordered_map m_randNames;
17 | std::string m_authCode;
18 |
19 | void genAuthCode();
20 | void writeAuthCodeToFile();
21 | void writeRandNamesToFile();
22 | void revertFiles();
23 | };
24 |
--------------------------------------------------------------------------------
/src/CETMM/EXT/CETMMEXT.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "RED4ext/Scripting/Natives/Generated/ink/ISystemRequestsHandler.hpp"
3 | #include "Misc.h"
4 | #include "CETMMEXT.h"
5 |
6 | // RED4ext impl
7 |
8 | RED4ext::TTypedClass cls("CETMMEXT");
9 |
10 | RED4ext::CClass* CETMMEXT::GetNativeType()
11 | {
12 | return &cls;
13 | }
14 |
15 |
16 | // functions
17 | void RED4ext_CETMM::GetMods(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, RED4ext::Handle* aOut, int64_t a4)
18 | {
19 | aFrame->code++;
20 |
21 | if (aOut)
22 | {
23 | RED4ext::Handle handle(&CETMM::GetMods());
24 | auto type = RED4ext::CRTTISystem::Get()->GetType("handle:Mods");
25 | type->Assign(aOut, &handle);
26 | }
27 | }
28 |
29 | void RED4ext_CETMM::GetUninstall(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, RED4ext::Handle* aOut, int64_t a4)
30 | {
31 | aFrame->code++;
32 |
33 | if (aOut)
34 | {
35 | RED4ext::Handle handle(&CETMM::GetUninstall());
36 | auto type = RED4ext::CRTTISystem::Get()->GetType("handle:Uninstall");
37 | type->Assign(aOut, &handle);
38 | }
39 | }
40 |
41 | void RED4ext_CETMM::OpenModsFolder(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, void* aOut, int64_t a4)
42 | {
43 | aFrame->code++;
44 |
45 | Misc::openFolder(CETMM::GetPaths().CETMods());
46 | }
47 |
48 | void RED4ext_CETMM::OpenDofilesFolder(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, void* aOut, int64_t a4)
49 | {
50 | aFrame->code++;
51 |
52 | Misc::openFolder(CETMM::GetPaths().CETMMRoot() / "dofiles");
53 | }
54 |
55 | void RED4ext_CETMM::OpenUrl(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, void* aOut, int64_t a4)
56 | {
57 | RED4ext::CString* url_name;
58 | RED4ext::GetParameter(aFrame, &url_name);
59 |
60 | aFrame->code++;
61 |
62 | if (*url_name == "update")
63 | Misc::openUrl("https://www.nexusmods.com/cyberpunk2077/mods/895?tab=files");
64 |
65 | if (*url_name == "coffee")
66 | Misc::openUrl("https://www.buymeacoffee.com/mingm");
67 |
68 | if (*url_name == "font_wiki")
69 | Misc::openUrl("https://wiki.redmodding.org/cyber-engine-tweaks/getting-started/configuration/change-font-and-font-size#how-to-display-non-english-characters");
70 | }
71 |
72 | void RED4ext_CETMM::RestartGame(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, void* aOut, int64_t a4)
73 | {
74 | aFrame->code++;
75 | CETMM::SetRestart(true);
76 | }
77 |
78 |
79 | // register
80 |
81 | void RED4ext_CETMM::Register()
82 | {
83 | RED4ext::CNamePool::Add("CETMMEXT");
84 | cls.flags = {.isNative = true};
85 | RED4ext::CRTTISystem::Get()->RegisterType(&cls);
86 | }
87 |
88 | void RED4ext_CETMM::PostRegister()
89 | {
90 | auto func_getMods = RED4ext::CClassStaticFunction::Create(&cls, "GetMods", "GetMods", &GetMods, {.isNative = true, .isStatic = true});
91 | func_getMods->SetReturnType("handle:Mods");
92 | cls.RegisterFunction(func_getMods);
93 |
94 | auto func_getUninstall = RED4ext::CClassStaticFunction::Create(&cls, "GetUninstall", "GetUninstall", &GetUninstall, {.isNative = true, .isStatic = true});
95 | func_getUninstall->SetReturnType("handle:Uninstall");
96 | cls.RegisterFunction(func_getUninstall);
97 |
98 | auto func_openModsFolder = RED4ext::CClassStaticFunction::Create(&cls, "OpenModsFolder", "OpenModsFolder", &OpenModsFolder, {.isNative = true, .isStatic = true});
99 | cls.RegisterFunction(func_openModsFolder);
100 |
101 | auto func_openDofilesFolder = RED4ext::CClassStaticFunction::Create(&cls, "OpenDofilesFolder", "OpenDofilesFolder", &OpenDofilesFolder, {.isNative = true, .isStatic = true});
102 | cls.RegisterFunction(func_openDofilesFolder);
103 |
104 | auto func_openUrl = RED4ext::CClassStaticFunction::Create(&cls, "OpenUrl", "OpenUrl", &OpenUrl, {.isNative = true, .isStatic = true});
105 | func_openUrl->AddParam("String", "URLName");
106 | cls.RegisterFunction(func_openUrl);
107 |
108 | auto func_restarGame = RED4ext::CClassStaticFunction::Create(&cls, "RestartGame", "RestartGame", &RestartGame, {.isNative = true, .isStatic = true});
109 | cls.RegisterFunction(func_restarGame);
110 | }
--------------------------------------------------------------------------------
/src/CETMM/EXT/CETMMEXT.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Mods.h"
4 | #include "Uninstall.h"
5 |
6 | struct CETMMEXT : RED4ext::IScriptable
7 | {
8 | public:
9 | CETMMEXT() {};
10 | RED4ext::CClass *GetNativeType();
11 |
12 | private:
13 |
14 | };
15 |
16 | namespace RED4ext_CETMM
17 | {
18 | void GetMods(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, RED4ext::Handle* aOut, int64_t a4);
19 | void GetUninstall(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, RED4ext::Handle* aOut, int64_t a4);
20 | void OpenModsFolder(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, void* aOut, int64_t a4);
21 | void OpenDofilesFolder(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, void* aOut, int64_t a4);
22 | void OpenUrl(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, void* aOut, int64_t a4);
23 | void RestartGame(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, void* aOut, int64_t a4);
24 |
25 | void Register();
26 | void PostRegister();
27 | }
--------------------------------------------------------------------------------
/src/CETMM/EXT/Misc.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "Misc.h"
3 |
4 | void Misc::openFolder(std::filesystem::path aFolder)
5 | {
6 | ShellExecute(NULL, NULL, aFolder.wstring().c_str(), NULL, NULL, SW_SHOWNORMAL);
7 | }
8 |
9 | void Misc::openUrl(std::string aUrl)
10 | {
11 | ShellExecuteA(NULL, NULL, aUrl.c_str(), NULL, NULL , SW_SHOWNORMAL);
12 | }
--------------------------------------------------------------------------------
/src/CETMM/EXT/Misc.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace Misc
4 | {
5 | void openFolder(std::filesystem::path aFolder);
6 | void openUrl(std::string aUrl);
7 | } // namespace Misc
8 |
--------------------------------------------------------------------------------
/src/CETMM/EXT/Mod.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "Mod.h"
3 |
4 | std::string to_string(MODTYPE aEnum)
5 | {
6 | switch (aEnum)
7 | {
8 | case MODTYPE::CET: return "CET";
9 | case MODTYPE::ARCHIVE: return "ARCHIVE";
10 | case MODTYPE::REDSCRIPT: return "REDSCRIPT";
11 | case MODTYPE::ASI: return "ASI";
12 | case MODTYPE::RED4EXT: return "RED4EXT";
13 | case MODTYPE::REDMOD: return "REDMOD";
14 | default: return "unknown";
15 | }
16 | }
17 |
18 | Mod::Mod(RED4ext::CString aName, std::filesystem::path aPath, bool aEnabled, MODTYPE aType)
19 | :m_name{ aName }, m_path{ aPath }, m_enabled{ aEnabled }, m_type{ aType }
20 | {
21 | m_formatedName = formatName(m_name);
22 | }
23 |
24 | const RED4ext::CString Mod::GetName() const
25 | {
26 | return m_name;
27 | }
28 |
29 | const RED4ext::CString Mod::GetFormatedName() const
30 | {
31 | return m_formatedName;
32 | }
33 |
34 | const std::filesystem::path Mod::GetPath() const
35 | {
36 | return m_path;
37 | }
38 |
39 | const bool Mod::IsEnabled() const
40 | {
41 | return m_enabled;
42 | }
43 |
44 | const MODTYPE Mod::GetType() const
45 | {
46 | return m_type;
47 | }
48 |
49 | const std::string Mod::GetTypeName()
50 | {
51 | return to_string(m_type);
52 | }
53 |
54 | void Mod::SetName(RED4ext::CString aName)
55 | {
56 | m_name = aName;
57 | m_formatedName = formatName(m_name);
58 | }
59 |
60 | void Mod::SetPath(std::filesystem::path aPath)
61 | {
62 | m_path = aPath;
63 | }
64 |
65 | void Mod::SetEnabled(bool aEnabled)
66 | {
67 | m_enabled = aEnabled;
68 | }
69 |
70 | void Mod::SetType(MODTYPE aType)
71 | {
72 | m_type = aType;
73 | }
74 |
75 | void Mod::Toggle()
76 | {
77 | if (m_type != MODTYPE::CET)
78 | {
79 | return;
80 | }
81 | switch (m_enabled)
82 | {
83 | case true:
84 | if (changeCETModState(false))
85 | m_enabled = false;
86 | break;
87 |
88 | case false:
89 | if (changeCETModState(true))
90 | m_enabled = true;
91 | break;
92 | }
93 | }
94 |
95 | RED4ext::CString Mod::formatName(RED4ext::CString aName)
96 | {
97 | std::string name = std::string(aName.c_str());
98 | std::replace( name.begin(), name.end(), '_', ' ');
99 | std::replace( name.begin(), name.end(), '-', ' ');
100 | for (int x = 0; x < name.length(); x++)
101 | {
102 | if (x == 0)
103 | {
104 | name[x] = toupper(name[x]);
105 | }
106 | else if (name[x - 1] == ' ')
107 | {
108 | name[x] = toupper(name[x]);
109 | }
110 | }
111 | return RED4ext::CString(name.c_str());
112 | }
113 |
114 | bool Mod::changeCETModState(bool aEnable)
115 | {
116 | std::filesystem::path enabled_filename = "init.lua";
117 | std::filesystem::path disabled_filename = "init.lua_disabled";
118 | std::error_code err;
119 | switch (aEnable)
120 | {
121 | case true:
122 | std::filesystem::rename(m_path / disabled_filename, m_path / enabled_filename, err);
123 | if (err) {
124 | return false;
125 | }
126 | return true;
127 |
128 | case false:
129 | std::filesystem::rename(m_path / enabled_filename, m_path / disabled_filename, err);
130 | if (err)
131 | {
132 | return false;
133 | }
134 | return true;
135 | }
136 | }
137 |
138 |
139 | // RED4ext impl
140 |
141 | RED4ext::TTypedClass cls("Mod");
142 |
143 | RED4ext::CClass* Mod::GetNativeType()
144 | {
145 | return &cls;
146 | }
147 |
148 | void red4ext_GetName(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, RED4ext::CString* aOut, int64_t a4)
149 | {
150 | aFrame->code++;
151 |
152 | if (aOut)
153 | {
154 | *aOut = reinterpret_cast(aContext)->GetName();
155 | }
156 | }
157 |
158 | void red4ext_GetFormatedName(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, RED4ext::CString* aOut, int64_t a4)
159 | {
160 | aFrame->code++;
161 |
162 | if (aOut)
163 | {
164 | *aOut = reinterpret_cast(aContext)->GetFormatedName();
165 | }
166 | }
167 |
168 | void red4ext_IsEnabled(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, bool* aOut, int64_t a4)
169 | {
170 | aFrame->code++;
171 |
172 | if (aOut)
173 | {
174 | *aOut = reinterpret_cast(aContext)->IsEnabled();
175 | }
176 | }
177 |
178 | void red4ext_Toggle(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, void* aOut, int64_t a4)
179 | {
180 | aFrame->code++;
181 |
182 | reinterpret_cast(aContext)->Toggle();
183 | }
184 |
185 | void RED4ext_Mod::Register()
186 | {
187 | RED4ext::CNamePool::Add("Mod");
188 | RED4ext::CNamePool::Add("handle:Mod");
189 | RED4ext::CRTTISystem::Get()->RegisterType(&cls);
190 | }
191 |
192 | void RED4ext_Mod::PostRegister()
193 | {
194 | auto func_getName = RED4ext::CClassFunction::Create(&cls, "GetName", "GetName",
195 | &red4ext_GetName, {.isNative = true});
196 | func_getName->SetReturnType("String");
197 | cls.RegisterFunction(func_getName);
198 |
199 | auto func_getFormatedName = RED4ext::CClassFunction::Create(&cls, "GetFormatedName", "GetFormatedName",
200 | &red4ext_GetFormatedName, {.isNative = true});
201 | func_getFormatedName->SetReturnType("String");
202 | cls.RegisterFunction(func_getFormatedName);
203 |
204 | auto func_isEnabled = RED4ext::CClassFunction::Create(&cls, "IsEnabled", "IsEnabled",
205 | &red4ext_IsEnabled, {.isNative = true});
206 | func_isEnabled->SetReturnType("Bool");
207 | cls.RegisterFunction(func_isEnabled);
208 |
209 | auto func_toggle = RED4ext::CClassFunction::Create(&cls, "Toggle", "Toggle",
210 | &red4ext_Toggle, {.isNative = true});
211 | cls.RegisterFunction(func_toggle);
212 | }
--------------------------------------------------------------------------------
/src/CETMM/EXT/Mod.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | enum class MODTYPE
4 | {
5 | CET,
6 | ARCHIVE,
7 | REDSCRIPT,
8 | ASI,
9 | RED4EXT,
10 | REDMOD
11 | };
12 |
13 | struct Mod : RED4ext::IScriptable
14 | {
15 | public:
16 | RED4ext::CClass *GetNativeType();
17 |
18 | Mod() {};
19 | Mod(RED4ext::CString aName, std::filesystem::path aPath, bool aEnabled, MODTYPE aType);
20 |
21 | const RED4ext::CString GetName() const;
22 | const RED4ext::CString GetFormatedName() const;
23 | const std::filesystem::path GetPath() const;
24 | const bool IsEnabled() const;
25 | const MODTYPE GetType() const;
26 | const std::string GetTypeName();
27 | void SetName(RED4ext::CString aName);
28 | void SetPath(std::filesystem::path aPath);
29 | void SetEnabled(bool aEnabled);
30 | void SetType(MODTYPE aType);
31 | void Toggle();
32 |
33 | private:
34 | RED4ext::CString m_name;
35 | RED4ext::CString m_formatedName;
36 | std::filesystem::path m_path;
37 | bool m_enabled;
38 | MODTYPE m_type;
39 |
40 | RED4ext::CString formatName(RED4ext::CString aName);
41 | bool changeCETModState(bool aEnable);
42 | };
43 |
44 | namespace RED4ext_Mod
45 | {
46 | void Register();
47 | void PostRegister();
48 | }
--------------------------------------------------------------------------------
/src/CETMM/EXT/Mods.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "Mods.h"
3 |
4 | void Mods::Scan()
5 | {
6 | m_cet = scan_mods(MODTYPE::CET);
7 | // m_archive = scan_mods(MODTYPE::ARCHIVE);
8 | // m_redscript = scan_mods(MODTYPE::REDSCRIPT);
9 | // m_asi = scan_mods(MODTYPE::ASI);
10 | // m_red4ext = scan_mods(MODTYPE::RED4EXT);
11 | // m_redmod = scan_mods(MODTYPE::REDMOD);
12 | }
13 |
14 | RED4ext::DynArray> &Mods::GetCETMods()
15 | {
16 | return m_cet;
17 | }
18 |
19 | RED4ext::DynArray> Mods::scan_mods(MODTYPE aType)
20 | {
21 | RED4ext::DynArray> mod_hnds;
22 | auto modType = RED4ext::CRTTISystem::Get()->GetClass("Mod");
23 | switch (aType)
24 | {
25 | case MODTYPE::CET:
26 | for (const auto& entry : std::filesystem::directory_iterator(CETMM::GetPaths().CETMods()))
27 | {
28 | if (entry.is_directory() && std::filesystem::exists(entry.path() / "init.lua"))
29 | {
30 | auto mod = reinterpret_cast(modType->AllocInstance());
31 | modType->ConstructCls(mod);
32 | mod->SetName(RED4ext::CString(entry.path().filename().string().c_str()));
33 | mod->SetPath(entry.path());
34 | mod->SetEnabled(true);
35 | mod->SetType(MODTYPE::CET);
36 | mod_hnds.EmplaceBack(mod);
37 | }
38 |
39 | else if (entry.is_directory() && std::filesystem::exists(entry.path() / "init.lua_disabled"))
40 | {
41 | auto mod = reinterpret_cast(modType->AllocInstance());
42 | modType->ConstructCls(mod);
43 | mod->SetName(RED4ext::CString(entry.path().filename().string().c_str()));
44 | mod->SetPath(entry.path());
45 | mod->SetEnabled(false);
46 | mod->SetType(MODTYPE::CET);
47 | mod_hnds.EmplaceBack(mod);
48 | }
49 | }
50 | break;
51 |
52 | case MODTYPE::ARCHIVE:
53 | break;
54 |
55 | case MODTYPE::REDSCRIPT:
56 | break;
57 |
58 | case MODTYPE::ASI:
59 | break;
60 |
61 | case MODTYPE::RED4EXT:
62 | break;
63 |
64 | case MODTYPE::REDMOD:
65 | break;
66 | }
67 |
68 | return mod_hnds;
69 | }
70 |
71 | // red4ext impl
72 |
73 | RED4ext::TTypedClass cls("Mods");
74 |
75 | RED4ext::CClass* Mods::GetNativeType()
76 | {
77 | return &cls;
78 | }
79 |
80 | void red4ext_Scan(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, void* aOut, int64_t a4)
81 | {
82 | RED4EXT_UNUSED_PARAMETER(aContext);
83 | RED4EXT_UNUSED_PARAMETER(a4);
84 | RED4EXT_UNUSED_PARAMETER(aOut);
85 | RED4EXT_UNUSED_PARAMETER(aFrame);
86 |
87 | aFrame->code++;
88 |
89 | CETMM::GetMods().Scan();
90 | }
91 |
92 | void red4ext_GetCETMods(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, RED4ext::DynArray* aOut, int64_t a4)
93 | {
94 | aFrame->code++;
95 |
96 | if (aOut)
97 | {
98 | auto type = RED4ext::CRTTISystem::Get()->GetType("array:handle:Mod");
99 | type->Assign(aOut, &CETMM::GetMods().GetCETMods());
100 | }
101 | }
102 |
103 | void RED4ext_Mods::Register()
104 | {
105 | RED4ext::CNamePool::Add("Mods");
106 | RED4ext::CNamePool::Add("handle:Mods");
107 | RED4ext::CNamePool::Add("array:handle:Mod");
108 | RED4ext::CRTTISystem::Get()->RegisterType(&cls);
109 | }
110 |
111 | void RED4ext_Mods::PostRegister()
112 | {
113 | auto func_scan = RED4ext::CClassStaticFunction::Create(&cls, "Scan", "Scan",
114 | &red4ext_Scan, {.isNative = true, .isStatic = true});
115 | cls.RegisterFunction(func_scan);
116 |
117 | auto func_getCETMods = RED4ext::CClassStaticFunction::Create(&cls, "GetCETMods", "GetCETMods",
118 | &red4ext_GetCETMods, {.isNative = true, .isStatic = true});
119 | func_getCETMods->SetReturnType("array:handle:Mod");
120 | cls.RegisterFunction(func_getCETMods);
121 | }
--------------------------------------------------------------------------------
/src/CETMM/EXT/Mods.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Mod.h"
4 |
5 | struct Mods : RED4ext::IScriptable
6 | {
7 | public:
8 | Mods() {};
9 | RED4ext::CClass *GetNativeType();
10 | void Scan();
11 | RED4ext::DynArray> &GetCETMods();
12 |
13 | private:
14 | RED4ext::DynArray> m_archive;
15 | RED4ext::DynArray> m_asi;
16 | RED4ext::DynArray> m_red4ext;
17 | RED4ext::DynArray> m_redscript;
18 | RED4ext::DynArray> m_cet;
19 | RED4ext::DynArray> m_redmod;
20 |
21 | RED4ext::DynArray> scan_mods(MODTYPE aType);
22 | };
23 |
24 | namespace RED4ext_Mods
25 | {
26 | void Register();
27 | void PostRegister();
28 | }
--------------------------------------------------------------------------------
/src/CETMM/EXT/TypeRegister.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "Mod.h"
3 | #include "Mods.h"
4 | #include "CETMMEXT.h"
5 |
6 | namespace TypeRegister
7 | {
8 | void Register()
9 | {
10 | RED4ext_Mod::Register();
11 | RED4ext_Mods::Register();
12 | RED4ext_CETMM::Register();
13 | RED4ext_Uninstall::Register();
14 | }
15 |
16 | void PostRegister()
17 | {
18 | RED4ext_Mod::PostRegister();
19 | RED4ext_Mods::PostRegister();
20 | RED4ext_CETMM::PostRegister();
21 | RED4ext_Uninstall::PostRegister();
22 | }
23 | }
--------------------------------------------------------------------------------
/src/CETMM/EXT/Uninstall.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "Uninstall.h"
3 |
4 | void Uninstall::Initialize()
5 | {
6 | auto asi_path = CETMM::GetPaths().Plugins() / "cet_mod_manager.asi";
7 | m_asiExists = std::filesystem::exists(asi_path);
8 | }
9 |
10 | void Uninstall::Uninitialize()
11 | {
12 | if (m_removeFiles)
13 | {
14 | // generate remove cmd
15 | std::vector dirs_to_del = {};
16 | std::vector files_to_del = {};
17 |
18 | auto ext_path = CETMM::GetPaths().Red4Ext() / "cet_mod_manager";
19 | if (std::filesystem::exists(ext_path))
20 | dirs_to_del.push_back(ext_path);
21 |
22 | auto lua_path = CETMM::GetPaths().CETMMRoot();
23 | if (std::filesystem::exists(lua_path))
24 | {
25 | if (m_removeConfig && m_removeDofiles)
26 | dirs_to_del.push_back(lua_path);
27 | else
28 | {
29 | for (auto const& dir_entry : std::filesystem::directory_iterator{lua_path})
30 | {
31 | if (dir_entry.is_directory())
32 | {
33 | if (!m_removeDofiles && dir_entry.path().filename() == "dofiles") continue;
34 | dirs_to_del.push_back(dir_entry.path());
35 | }
36 | if (dir_entry.is_regular_file())
37 | {
38 | if (!m_removeConfig && dir_entry.path().filename() == "config.json") continue;
39 | files_to_del.push_back(dir_entry.path());
40 | }
41 | }
42 | }
43 | }
44 |
45 | std::wstring rmdir_str = L"";
46 | std::wstring del_str = L"";
47 |
48 | for (auto const& dir : dirs_to_del)
49 | {
50 | rmdir_str += L" \"" + dir.wstring() + L"\"";
51 | }
52 |
53 | for (auto const& file : files_to_del)
54 | {
55 | del_str += L" \"" + file.wstring() + L"\"";
56 | }
57 |
58 | if (dirs_to_del.size() > 0)
59 | rmdir_str = fmt::format(L" & rd /s /q{}", rmdir_str);
60 | if (files_to_del.size() > 0)
61 | del_str = fmt::format(L" & del{} /f /q", del_str);
62 |
63 | std::wstring cmdArgs = fmt::format(L"/c ping localhost -n 5 > nul{}{}", rmdir_str, del_str);
64 |
65 | // remove red4ext plugin
66 | STARTUPINFO lpStartupInfo;
67 | PROCESS_INFORMATION lpProcessInfo;
68 |
69 | ZeroMemory( &lpStartupInfo, sizeof( lpStartupInfo ) );
70 | lpStartupInfo.cb = sizeof( lpStartupInfo );
71 | ZeroMemory( &lpProcessInfo, sizeof( lpProcessInfo ) );
72 |
73 | CreateProcess( L"C:\\Windows\\System32\\cmd.exe",
74 | cmdArgs.data(), NULL, NULL,
75 | FALSE, CREATE_NO_WINDOW, NULL, NULL,
76 | &lpStartupInfo,
77 | &lpProcessInfo
78 | );
79 | CloseHandle(lpProcessInfo.hThread);
80 | CloseHandle(lpProcessInfo.hProcess);
81 | }
82 | }
83 |
84 | const bool Uninstall::IsAsiRemoved() const
85 | {
86 | return !m_asiExists;
87 | }
88 |
89 | void Uninstall::SetFilesToRemove(bool aRemove, bool aConfig, bool aDofiles)
90 | {
91 | m_removeFiles = aRemove;
92 | m_removeConfig = aConfig;
93 | m_removeDofiles = aDofiles;
94 | }
95 |
96 | // red4ext impl
97 |
98 | RED4ext::TTypedClass cls("Uninstall");
99 |
100 | RED4ext::CClass* Uninstall::GetNativeType()
101 | {
102 | return &cls;
103 | }
104 |
105 | void red4ext_IsAsiRemoved(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, bool* aOut, int64_t a4)
106 | {
107 | aFrame->code++;
108 |
109 | if (aOut)
110 | {
111 | *aOut = CETMM::GetUninstall().IsAsiRemoved();
112 | }
113 | }
114 |
115 | void red4ext_SetFilesToRemove(RED4ext::IScriptable* aContext, RED4ext::CStackFrame* aFrame, void* aOut, int64_t a4)
116 | {
117 | bool removeFiles;
118 | bool removeConfig;
119 | bool removeDofiles;
120 | RED4ext::GetParameter(aFrame, &removeFiles);
121 | RED4ext::GetParameter(aFrame, &removeConfig);
122 | RED4ext::GetParameter(aFrame, &removeDofiles);
123 | aFrame->code++;
124 | CETMM::GetUninstall().SetFilesToRemove(removeFiles, removeConfig, removeDofiles);
125 | }
126 |
127 | void RED4ext_Uninstall::Register()
128 | {
129 | RED4ext::CNamePool::Add("Uninstall");
130 | RED4ext::CNamePool::Add("handle:Uninstall");
131 | RED4ext::CRTTISystem::Get()->RegisterType(&cls);
132 | }
133 |
134 | void RED4ext_Uninstall::PostRegister()
135 | {
136 | auto func_IsAsiRemoved = RED4ext::CClassStaticFunction::Create(&cls, "IsAsiRemoved", "IsAsiRemoved",
137 | &red4ext_IsAsiRemoved, {.isNative = true, .isStatic = true});
138 | func_IsAsiRemoved->SetReturnType("Bool");
139 | cls.RegisterFunction(func_IsAsiRemoved);
140 |
141 | auto func_SetFilesToRemove = RED4ext::CClassStaticFunction::Create(&cls, "SetFilesToRemove", "SetFilesToRemove",
142 | &red4ext_SetFilesToRemove, {.isNative = true, .isStatic = true});
143 | func_SetFilesToRemove->AddParam("Bool", "removeFiles");
144 | func_SetFilesToRemove->AddParam("Bool", "removeConfig");
145 | func_SetFilesToRemove->AddParam("Bool", "removeDofiles");
146 | cls.RegisterFunction(func_SetFilesToRemove);
147 | }
--------------------------------------------------------------------------------
/src/CETMM/EXT/Uninstall.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct Uninstall : RED4ext::IScriptable
4 | {
5 | public:
6 | RED4ext::CClass *GetNativeType();
7 |
8 | Uninstall() {};
9 | void Initialize();
10 | void Uninitialize();
11 | const bool IsAsiRemoved() const;
12 | void SetFilesToRemove(bool aRemove, bool aConfig = false, bool aDofiles = false);
13 |
14 | private:
15 | bool m_asiExists {true};
16 | bool m_removeFiles {false};
17 | bool m_removeConfig {false};
18 | bool m_removeDofiles {false};
19 | };
20 |
21 | namespace RED4ext_Uninstall
22 | {
23 | void Register();
24 | void PostRegister();
25 | }
--------------------------------------------------------------------------------
/src/CETMM/Logger.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include
3 |
4 | #include "Logger.h"
5 | #include "Version.h"
6 |
7 | std::shared_ptr CreateLogger()
8 | {
9 | const std::string pattern = fmt::format("[%Y-%m-%d %T UTC%z] [{}] [%l] %v",CETMM_VERSION);
10 | const auto fileName = CETMM::GetPaths().CETMMRoot() / "cet_mod_manager_ext.log";
11 | auto logger = spdlog::basic_logger_mt("CETMM", fileName.string());
12 | logger->set_pattern(pattern);
13 | return logger;
14 | }
15 |
--------------------------------------------------------------------------------
/src/CETMM/Logger.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | std::shared_ptr CreateLogger();
--------------------------------------------------------------------------------
/src/CETMM/Utilities.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "pch.h"
3 | #include "Utilities.h"
4 |
5 |
6 | // https://inversepalindrome.com/blog/how-to-create-a-random-string-in-cpp
7 | std::string Utilities::random_string(std::size_t aLength)
8 | {
9 | const std::string CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
10 |
11 | std::random_device random_device;
12 | std::mt19937 generator(random_device());
13 | std::uniform_int_distribution<> distribution(0, CHARACTERS.size() - 1);
14 |
15 | std::string random_string;
16 |
17 | for (std::size_t i = 0; i < aLength; ++i)
18 | {
19 | random_string += CHARACTERS[distribution(generator)];
20 | }
21 |
22 | return random_string;
23 | }
--------------------------------------------------------------------------------
/src/CETMM/Utilities.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | namespace Utilities {
4 |
5 | std::string random_string(std::size_t aLength);
6 |
7 | }
--------------------------------------------------------------------------------
/src/CETMM/dllmain.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "version.h"
3 | #include
4 | #include "EXT/TypeRegister.h"
5 |
6 | static void Initialize()
7 | {
8 | try
9 | {
10 | spdlog::set_default_logger(CreateLogger());
11 | CETMM::Initialize();
12 | }
13 | catch (...)
14 | {}
15 | }
16 |
17 | static void Shutdown()
18 | {
19 | CETMM::Shutdown();
20 | }
21 |
22 | RED4ext::v0::SemVer CETMM_Version()
23 | {
24 | std::string version = CETMM_VERSION;
25 | std::regex rgx(R"((\d+)\.(\d+)\.(\d+)-*(\d+)*(?=-|$))");
26 | std::smatch matches;
27 |
28 | if(std::regex_search(version, matches, rgx)) {
29 | uint8_t major = std::stoi(matches[1].str());
30 | uint16_t minor = std::stoi(matches[2].str());
31 | uint32_t patch = std::stoi(matches[3].str());
32 | uint32_t prereleaseType = RED4EXT_V0_SEMVER_PRERELEASE_TYPE_NONE;
33 | uint32_t prereleaseNumber = 0;
34 |
35 | if (matches[4].length() != 0) {
36 | prereleaseType = RED4EXT_V0_SEMVER_PRERELEASE_TYPE_RC;
37 | prereleaseNumber = std::stoi(matches[4].str());
38 | }
39 | return RED4EXT_SEMVER_EX(major, minor, patch, prereleaseType, prereleaseNumber);
40 | } else {
41 | return RED4EXT_SEMVER(1, 0, 0);
42 | }
43 | }
44 |
45 | RED4EXT_C_EXPORT void RED4EXT_CALL RegisterTypes()
46 | {
47 | TypeRegister::Register();
48 | }
49 |
50 | RED4EXT_C_EXPORT void RED4EXT_CALL PostRegisterTypes()
51 | {
52 | TypeRegister::PostRegister();
53 | }
54 |
55 | RED4EXT_C_EXPORT bool RED4EXT_CALL Main(RED4ext::PluginHandle aHandle, RED4ext::EMainReason aReason,
56 | const RED4ext::Sdk* aSdk)
57 | {
58 | RED4EXT_UNUSED_PARAMETER(aHandle);
59 | RED4EXT_UNUSED_PARAMETER(aSdk);
60 |
61 | switch (aReason)
62 | {
63 | case RED4ext::EMainReason::Load:
64 | {
65 | Initialize();
66 |
67 | RED4ext::CRTTISystem::Get()->AddRegisterCallback(RegisterTypes);
68 | RED4ext::CRTTISystem::Get()->AddPostRegisterCallback(PostRegisterTypes);
69 |
70 | break;
71 | }
72 | case RED4ext::EMainReason::Unload:
73 | {
74 | Shutdown();
75 | break;
76 | }
77 | }
78 |
79 | return true;
80 | }
81 |
82 | RED4EXT_C_EXPORT void RED4EXT_CALL Query(RED4ext::PluginInfo* aInfo)
83 | {
84 | aInfo->name = L"CET Mod Manager";
85 | aInfo->author = L"Ming";
86 | aInfo->version = CETMM_Version();
87 | aInfo->runtime = RED4EXT_RUNTIME_INDEPENDENT;
88 | aInfo->sdk = RED4EXT_SDK_LATEST;
89 | }
90 |
91 | RED4EXT_C_EXPORT uint32_t RED4EXT_CALL Supports()
92 | {
93 | return RED4EXT_API_VERSION_LATEST;
94 | }
--------------------------------------------------------------------------------
/src/CETMM/pch.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include
16 | #include
17 | #include
18 | #include
19 |
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 |
30 | #include "CETMM.h"
31 | #include "Logger.h"
32 | #include "Utilities.h"
--------------------------------------------------------------------------------
/src/Common/Paths.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "Paths.h"
3 |
4 | Paths::Paths()
5 | {
6 | TCHAR exePathBuf[MAX_PATH] = { 0 };
7 | GetModuleFileName(GetModuleHandle(nullptr), exePathBuf, std::size(exePathBuf));
8 | m_exe = exePathBuf;
9 | m_exeRoot = m_exe.parent_path();
10 | m_gameRoot = m_exeRoot.parent_path().parent_path();
11 | m_archives = m_gameRoot / "archive" / "pc" / "mod";
12 | m_plugins = m_exeRoot / "plugins";
13 | m_red4ext = m_gameRoot / "red4ext" / "plugins";
14 | m_redscript = m_gameRoot / "r6" / "scripts";
15 | m_cetmods = m_plugins / "cyber_engine_tweaks" / "mods";
16 | m_cetconfig = m_plugins / "cyber_engine_tweaks" / "config.json";
17 | m_cetmmRoot = m_cetmods / "cet_mod_manager";
18 | m_config = m_cetmmRoot / "config.json";
19 | m_authCode = m_cetmmRoot / "authCode.lua";
20 | m_randNames = m_cetmmRoot / "coreFunc.lua";
21 |
22 | #ifdef DEBUG
23 | spdlog::info("m_exe: {}", m_exe.string());
24 | spdlog::info("m_exeRoot: {}", m_exeRoot.string());
25 | spdlog::info("m_gameRoot: {}", m_gameRoot.string());
26 | spdlog::info("m_archives: {}", m_archives.string());
27 | spdlog::info("m_plugins: {}", m_plugins.string());
28 | spdlog::info("m_red4ext: {}", m_red4ext.string());
29 | spdlog::info("m_redscript: {}", m_redscript.string());
30 | spdlog::info("m_cetmods: {}", m_cetmods.string());
31 | spdlog::info("m_cetconfig: {}", m_cetconfig.string());
32 | spdlog::info("m_cetmmRoot: {}", m_cetmmRoot.string());
33 | spdlog::info("m_config: {}", m_config.string());
34 | #endif // DEBUG
35 | }
36 |
37 | const std::filesystem::path& Paths::GameRoot() const
38 | {
39 | return m_gameRoot;
40 | }
41 |
42 | const std::filesystem::path& Paths::Archives() const
43 | {
44 | return m_archives;
45 | }
46 |
47 | const std::filesystem::path& Paths::Plugins() const
48 | {
49 | return m_plugins;
50 | }
51 |
52 | const std::filesystem::path& Paths::Red4Ext() const
53 | {
54 | return m_red4ext;
55 | }
56 |
57 | const std::filesystem::path& Paths::RedScript() const
58 | {
59 | return m_redscript;
60 | }
61 |
62 | const std::filesystem::path& Paths::CETMods() const
63 | {
64 | return m_cetmods;
65 | }
66 |
67 | const std::filesystem::path& Paths::CETConfig() const
68 | {
69 | return m_cetconfig;
70 | }
71 |
72 | const std::filesystem::path& Paths::CETMMRoot() const
73 | {
74 | return m_cetmmRoot;
75 | }
76 |
77 | const std::filesystem::path& Paths::Config() const
78 | {
79 | return m_config;
80 | }
81 |
82 | const std::filesystem::path& Paths::AuthCode() const
83 | {
84 | return m_authCode;
85 | }
86 |
87 | const std::filesystem::path& Paths::RandNames() const
88 | {
89 | return m_randNames;
90 | }
91 |
92 | const std::filesystem::path& Paths::EXE() const
93 | {
94 | return m_exe;
95 | }
--------------------------------------------------------------------------------
/src/Common/Paths.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | struct Paths
4 | {
5 | Paths();
6 | const std::filesystem::path& GameRoot() const;
7 | const std::filesystem::path& Archives() const;
8 | const std::filesystem::path& Plugins() const;
9 | const std::filesystem::path& Red4Ext() const;
10 | const std::filesystem::path& RedScript() const;
11 | const std::filesystem::path& CETMods() const;
12 | const std::filesystem::path& CETConfig() const;
13 | const std::filesystem::path& CETMMRoot() const;
14 | const std::filesystem::path& Config() const;
15 | const std::filesystem::path& AuthCode() const;
16 | const std::filesystem::path& RandNames() const;
17 | const std::filesystem::path& EXE() const;
18 |
19 | std::filesystem::path m_exe;
20 | std::filesystem::path m_exeRoot;
21 | std::filesystem::path m_gameRoot;
22 | std::filesystem::path m_cetmmRoot;
23 | std::filesystem::path m_archives;
24 | std::filesystem::path m_plugins;
25 | std::filesystem::path m_red4ext;
26 | std::filesystem::path m_redscript;
27 | std::filesystem::path m_cetmods;
28 | std::filesystem::path m_cetconfig;
29 | std::filesystem::path m_config;
30 | std::filesystem::path m_authCode;
31 | std::filesystem::path m_randNames;
32 | };
33 |
--------------------------------------------------------------------------------
/src/Common/Version.h.in:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #define CETMM_VERSION "${GIT_TAG}"
--------------------------------------------------------------------------------
/src/Installer/Installer.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include "Installer.h"
3 |
4 | void Installer::Initialize()
5 | {
6 | GetUpdate().UpdateModule();
7 | }
8 |
9 | void Installer::Shutdown()
10 | {
11 |
12 | }
13 |
14 | Installer& Installer::Get()
15 | {
16 | static Installer instance;
17 | return instance;
18 | }
19 |
20 | const Paths& Installer::GetPaths()
21 | {
22 | return Get().m_paths;
23 | }
24 |
25 | Update& Installer::GetUpdate()
26 | {
27 | return Get().m_update;
28 | }
--------------------------------------------------------------------------------
/src/Installer/Installer.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Paths.h"
4 | #include "Update.h"
5 |
6 | class Installer
7 | {
8 | public:
9 | static void Initialize();
10 | static void Shutdown();
11 | static Installer& Get();
12 |
13 | static const Paths& GetPaths();
14 | static Update& GetUpdate();
15 |
16 | Installer(const Installer&) = delete;
17 | Installer(Installer&&) = delete;
18 | Installer& operator=(const Installer&) = delete;
19 | Installer& operator=(Installer&&) = delete;
20 |
21 | private:
22 | Installer() {}
23 | ~Installer() {}
24 |
25 | Paths m_paths;
26 | Update m_update;
27 | };
--------------------------------------------------------------------------------
/src/Installer/Logger.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 | #include
3 |
4 | #include "Logger.h"
5 | #include "Version.h"
6 |
7 | std::shared_ptr CreateLogger()
8 | {
9 | const std::string pattern = fmt::format("[%Y-%m-%d %T UTC%z] [{}] [%l] %v",CETMM_VERSION);
10 | const auto fileName = Installer::GetPaths().CETMMRoot() / "cet_mod_manager_asi.log";
11 | auto logger = spdlog::basic_logger_mt("CETMM", fileName.string());
12 | logger->set_pattern(pattern);
13 | return logger;
14 | }
15 |
--------------------------------------------------------------------------------
/src/Installer/Logger.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | std::shared_ptr CreateLogger();
--------------------------------------------------------------------------------
/src/Installer/Update.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | #include "Update.h"
4 | #include "embeds/lua/EmbedFileManager_LooseFiles.h"
5 | #include "embeds/lua/EmbedFileManager_Lua.h"
6 | #include "embeds/red4ext/EmbedFileManager_Red4ExtPlugin.h"
7 |
8 | void Update::LogVersion()
9 | {
10 | spdlog::info("CETMM version: {}", m_version);
11 | }
12 |
13 | void Update::UpdateModule()
14 | {
15 | std::filesystem::path scriptDir = Installer::GetPaths().CETMMRoot();
16 | std::string installed_version = getModuleVersion();
17 | // need to deal when red4ext plugin doesn't exist
18 | if (!std::filesystem::exists(scriptDir / "modules" / "version.lua"))
19 | {
20 | spdlog::info("Scripts doesn't exist, extracting scripts..", scriptDir.string());
21 | removeOldModule();
22 | extractModule();
23 | }
24 | else if (installed_version != m_version)
25 | {
26 | spdlog::info("Old scripts version({}) found, updating scripts.", installed_version);
27 | removeOldModule();
28 | extractModule();
29 | }
30 | std::filesystem::create_directory(scriptDir / "dofiles");
31 | }
32 |
33 | const std::string Update::GetVersion() const
34 | {
35 | return m_version;
36 | }
37 |
38 | std::string Update::getModuleVersion()
39 | {
40 | std::filesystem::path script_version_file = Installer::GetPaths().CETMMRoot() / "modules" / "version.lua";
41 | std::string line;
42 | std::ifstream file (script_version_file);
43 |
44 | if (!file.is_open())
45 | {
46 | spdlog::error("Couldn't open version.lua at: {}.", script_version_file.string());
47 | return "";
48 | }
49 | std::getline(file, line);
50 | file.close();
51 |
52 | std::size_t pos1 = line.find("\"");
53 | std::size_t pos2 = line.find("\"", pos1 + 1);
54 | std::string version = line.substr(pos1 + 1, pos2 - pos1 - 1);
55 | return version;
56 | }
57 |
58 | void Update::extractModule()
59 | {
60 | spdlog::info("Extracting red4ext plugin..");
61 | std::filesystem::path pluginDir = Installer::GetPaths().Red4Ext() / "cet_mod_manager";
62 | bin2cppRed4ExtPlugin::FileManager& mgr_ext = bin2cppRed4ExtPlugin::FileManager::getInstance();
63 | bool saved_ext = mgr_ext.saveFiles(pluginDir.string().c_str());
64 | if (saved_ext)
65 | spdlog::info("Extracted Red4ext plugin file to \"{}\"", pluginDir.string());
66 | else
67 | spdlog::error("Failed to Red4ext plugin file to \"{}\"", pluginDir.string());
68 |
69 | spdlog::info("Extracting scripts..");
70 | std::filesystem::path scriptDir = Installer::GetPaths().CETMMRoot();
71 | bin2cppLooseFiles::FileManager& mgr_loose = bin2cppLooseFiles::FileManager::getInstance();
72 | bool saved_loose = mgr_loose.saveFiles(scriptDir.string().c_str());
73 |
74 | bin2cppLua::FileManager& mgr_lua = bin2cppLua::FileManager::getInstance();
75 | bool saved_lua = mgr_lua.saveFiles(scriptDir.string().c_str());
76 | if (saved_loose && saved_lua)
77 | {
78 | spdlog::info("Extracted script files to \"{}\"", scriptDir.string());
79 | // setConfig(); // white update
80 | }
81 | else
82 | spdlog::error("Failed to extract script files to \"{}\"", scriptDir.string());
83 | }
84 |
85 | void Update::removeOldModule()
86 | {
87 | spdlog::info("Removing old files..");
88 |
89 | {
90 | std::filesystem::path pluginPath = Installer::GetPaths().Red4Ext() / "cet_mod_manager" / "cet_mod_manager.dll";
91 | std::error_code ec;
92 | std::filesystem::remove(pluginPath, ec);
93 | if (ec)
94 | spdlog::error("Failed to remove: {}. Error: {}", pluginPath.string(), ec.message());
95 | spdlog::info("Removed: {}", pluginPath.string());
96 | }
97 |
98 | std::vector exclude_files = {"dofiles", "config.json", "cet_mod_manager.log", "cet_mod_manager_asi.log"};
99 | for (auto const& dir_entry : std::filesystem::directory_iterator{Installer::GetPaths().CETMMRoot()})
100 | {
101 | if (std::find(exclude_files.begin(), exclude_files.end(), dir_entry.path().filename()) == exclude_files.end())
102 | {
103 | std::error_code ec;
104 | std::filesystem::remove_all(dir_entry.path(), ec);
105 | if (ec)
106 | spdlog::error("Failed to remove: {}. Error: {}", dir_entry.path().string(), ec.message());
107 | spdlog::info("Removed: {}", dir_entry.path().string());
108 | }
109 | }
110 | }
111 |
112 | void Update::setConfig() // white update
113 | {
114 | spdlog::info("Updating theme config..");
115 |
116 | std::filesystem::path configPath = Installer::GetPaths().CETMMRoot() / "config.json";
117 |
118 | std::fstream file;
119 | file.open(configPath, std::fstream::in | std::fstream::out);
120 | if (!file.is_open()) return;
121 |
122 | nlohmann::json cetmm_config = nlohmann::json::parse(file);
123 | std::filesystem::resize_file(configPath, 0);
124 | file.seekg(0);
125 |
126 | cetmm_config["theme"] = "white";
127 |
128 | file << cetmm_config.dump() << std::endl;
129 | file.close();
130 | }
--------------------------------------------------------------------------------
/src/Installer/Update.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include "Version.h"
4 |
5 | class Update
6 | {
7 | public:
8 | void LogVersion();
9 | void UpdateModule();
10 | const std::string GetVersion() const;
11 |
12 | private:
13 | const std::string m_version = CETMM_VERSION;
14 | const std::vector m_ignore_list = {"config.json", "dofiles"};
15 |
16 | std::string getModuleVersion();
17 | void extractModule();
18 | void removeOldModule();
19 | void setConfig(); //white update
20 | };
--------------------------------------------------------------------------------
/src/Installer/dllmain.cpp:
--------------------------------------------------------------------------------
1 | #include "pch.h"
2 |
3 | HANDLE hMutexHandle = nullptr;
4 |
5 | static void Initialize()
6 | {
7 | try
8 | {
9 | //Single instance check
10 | hMutexHandle = CreateMutex(NULL, TRUE, L"CETMM_Installer");
11 | if (GetLastError() == ERROR_ALREADY_EXISTS)
12 | {
13 | return;
14 | }
15 |
16 | spdlog::set_default_logger(CreateLogger());
17 | spdlog::flush_on(spdlog::level::info);
18 | Installer::Initialize();
19 | }
20 | catch (...)
21 | {}
22 | }
23 |
24 | static void Shutdown()
25 | {
26 | Installer::Shutdown();
27 | spdlog::shutdown();
28 | }
29 |
30 | BOOL APIENTRY DllMain( HMODULE hModule,
31 | DWORD ul_reason_for_call,
32 | LPVOID lpReserved
33 | )
34 | {
35 | switch (ul_reason_for_call)
36 | {
37 | case DLL_PROCESS_ATTACH:
38 | Initialize();
39 | break;
40 | case DLL_PROCESS_DETACH:
41 | Shutdown();
42 | break;
43 | default:
44 | break;
45 | }
46 | return TRUE;
47 | }
--------------------------------------------------------------------------------
/src/Installer/pch.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #include
4 | #include
5 |
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 | #include
14 |
15 | #include
16 | #include
17 |
18 | #include
19 | #include
20 | #include
21 |
22 | #include "Installer.h"
23 | #include "Logger.h"
--------------------------------------------------------------------------------
/vendor/bin2cpp/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018 Antoine Beauchamp
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/vendor/bin2cpp/bin2cpp.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nats-ji/CET-Mod-Manager/7d85c841f5a199170ef972cec9b1aa2a2b062c35/vendor/bin2cpp/bin2cpp.exe
--------------------------------------------------------------------------------
/xmake.lua:
--------------------------------------------------------------------------------
1 | set_languages("cxx20")
2 | set_arch("x64")
3 | add_rules("mode.debug", "mode.release")
4 | add_requires("spdlog 1.10.*", "nlohmann_json 3.11.*", "fmt 9.1.*")
5 |
6 | add_defines("RED4EXT_STATIC_LIB")
7 |
8 | target("RED4ext.SDK")
9 | set_default(false)
10 | set_kind("static")
11 | set_group("vendor")
12 | add_files("vendor/RED4ext.SDK/src/**.cpp")
13 | add_headerfiles("vendor/RED4ext.SDK/include/**.hpp")
14 | add_includedirs("vendor/RED4ext.SDK/include/", { public = true })
15 | add_syslinks("User32")
16 |
17 | target("cet_mod_manager")
18 | set_default(false)
19 | set_kind("shared")
20 | set_filename("cet_mod_manager.dll")
21 | add_packages("spdlog", "nlohmann_json", "fmt")
22 | add_defines("UNICODE", "WIN32_LEAN_AND_MEAN")
23 | add_files("src/CETMM/**.cpp", "src/Common/**.cpp")
24 | add_headerfiles("src/CETMM/**.h", "src/Common/**.h")
25 | add_includedirs("src/CETMM/", "src/Common/")
26 | add_syslinks("Dwrite", "Shell32")
27 | add_deps("RED4ext.SDK")
28 | before_build(function ()
29 | import("build")
30 | build.UpdateVersion()
31 | end)
32 |
33 | target("installer")
34 | set_kind("shared")
35 | set_filename("cet_mod_manager.asi")
36 | add_packages("spdlog", "nlohmann_json", "fmt")
37 | add_defines("UNICODE", "WIN32_LEAN_AND_MEAN")
38 | add_files("src/Installer/**.cpp", "src/Common/**.cpp")
39 | add_headerfiles("src/Installer/**.h", "src/Common/**.h")
40 | add_includedirs("src/Installer/", "src/Installer/embeds/lua/", "src/Installer/embeds/red4ext/", "src/Common/")
41 | add_syslinks("Shell32")
42 | on_package(function (target)
43 | import("build")
44 | build.Package(target)
45 | end)
46 | on_install(function ()
47 | import("build")
48 | build.Install()
49 | end)
50 | after_clean(function ()
51 | import("build")
52 | build.Clean()
53 | end)
54 |
55 | option("installpath")
56 | set_showmenu(true)
57 | set_description("Set the path to Cyberpunk 2077 root directory.", "e.g.", format("\t-xmake f --installpath=%s", [["C:\Program Files (x86)\Steam\steamapps\common\Cyberpunk 2077"]]))
58 |
59 | task("run")
60 | on_run(function ()
61 | import("core.project.config")
62 | config.load()
63 | local install_path = config.get("installpath")
64 | print("Launching Cyberpunk 2077 ...")
65 | os.cd(path.join(install_path, "bin", "x64"))
66 | os.run("Cyberpunk2077.exe")
67 | end)
68 | set_menu { usage = "xmake run", description = "Launch Cyberpunk 2077"}
69 |
70 | task("embed")
71 | on_run(function ()
72 | import("build")
73 | build.GenerateEmbeds()
74 | end)
75 | set_menu { usage = "xmake embed", description = "Generate embed files"}
76 |
77 | task("install-lua")
78 | on_run(function ()
79 | import("build")
80 | build.InstallLua()
81 | end)
82 | set_menu { usage = "xmake install-lua", description = "Only Package and install CET Mod Manager Lua files"}
83 |
84 | task("install-ext")
85 | on_run(function ()
86 | import("build")
87 | build.InstallExt()
88 | end)
89 | set_menu { usage = "xmake install-ext", description = "Only Package and install CET Mod Manager Red4ext plugin file"}
90 |
91 | task("build-all")
92 | on_run(function ()
93 | import("build")
94 | build.BuildAll()
95 | end)
96 | set_menu { usage = "xmake build-all", description = "Build all targets."}
97 |
98 | task("update-ext")
99 | on_run(function ()
100 | local rootDir = os.curdir()
101 |
102 | print("Pull RED4ext.SDK")
103 | os.cd("./vendor/RED4ext.SDK")
104 | os.execv("git", {"pull", "origin", "master"})
105 |
106 | print("Commit changes")
107 | os.cd(rootDir)
108 | os.execv("git", {"add", "vendor/RED4ext.SDK"})
109 | os.execv("git", {"commit", "-m", "Update RED4ext.SDK"})
110 | end)
111 | set_menu { usage = "xmake update-ext", description = "Update RED4ext.SDK."}
--------------------------------------------------------------------------------