├── .yarn.installed ├── .gitignore ├── fxmanifest.lua ├── src └── client │ ├── tsconfig.json │ ├── utils.ts │ └── index.ts ├── .prettierrc ├── client.config.js ├── package.json ├── README.md └── LICENSE /.yarn.installed: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | dist/ 3 | node_modules/ 4 | package-lock.json 5 | yarn-error.log 6 | yarn.lock 7 | *.zip 8 | *.txt 9 | temp/* 10 | logs/* 11 | logs2/ 12 | docs/ 13 | ui/ -------------------------------------------------------------------------------- /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'cerulean' 2 | game 'common' 3 | 4 | client_scripts { 5 | 'dist/client/*.js', 6 | } 7 | 8 | exports { 9 | 'CreateMenu', 10 | 'CreateSubmenu', 11 | 'CloseMenu', 12 | 'CloseSubmenu', 13 | 'ResetMenu' 14 | } 15 | -------------------------------------------------------------------------------- /src/client/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "*": ["types/*"] 6 | }, 7 | "outDir": "./", 8 | "module": "es6", 9 | "target": "es6", 10 | "lib": ["es2017"], 11 | "types": ["@citizenfx/client", "@types/node"], 12 | "moduleResolution": "node", 13 | "strict": true, 14 | "alwaysStrict": true, 15 | "diagnostics": true, 16 | "removeComments": true 17 | }, 18 | "include": ["./**/*"], 19 | "exclude": [] 20 | } 21 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSpacing": true, 4 | "endOfLine": "auto", 5 | "htmlWhitespaceSensitivity": "css", 6 | "insertPragma": false, 7 | "jsxBracketSameLine": true, 8 | "jsxSingleQuote": false, 9 | "printWidth": 80, 10 | "proseWrap": "preserve", 11 | "quoteProps": "as-needed", 12 | "requirePragma": false, 13 | "semi": true, 14 | "tabWidth": 2, 15 | "useTabs": true, 16 | "vueIndentScriptAndStyle": false, 17 | "parser": "typescript" 18 | } -------------------------------------------------------------------------------- /client.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fivemPath = "./" 3 | 4 | module.exports = { 5 | entry: "./src/client/index.ts", 6 | module: { 7 | rules: [ 8 | { 9 | test: /\.tsx?$/, 10 | use: "ts-loader", 11 | exclude: /node_modules/ 12 | } 13 | ] 14 | }, 15 | optimization: { 16 | minimize: true 17 | }, 18 | resolve: { 19 | extensions: [".tsx", ".ts", ".js"] 20 | }, 21 | output: { 22 | filename: "client.js", 23 | path: path.resolve(fivemPath, "dist/client") 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "coraui", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "build": "webpack --mode production --config client.config.js", 7 | "lint": "prettier --write \"src/**/*.{ts,tsx}\"", 8 | "watch": "webpack --mode development --watch true --config client.config.js" 9 | }, 10 | "license": "MIT", 11 | "private": false, 12 | "dependencies": { 13 | "@citizenfx/client": "^2.0.3923-1", 14 | "@citizenfx/server": "^2.0.3923-1", 15 | "@types/node": "^15.0.2", 16 | "prettier": "^2.3.0" 17 | }, 18 | "devDependencies": { 19 | "ts-loader": "^6.0.2", 20 | "typescript": "^3.7.4", 21 | "webpack": "^4.41.5", 22 | "webpack-cli": "^3.3.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FiveM-CoraUI 2 | Library written in typescript to create menus on FiveM 3 | 4 | # Lua : https://github.com/hoyame/FiveM-CoraUI/tree/lua 5 | 6 | # Features 7 | 8 | - Color Panel 9 | - Slidebar panel 10 | - Slider panel 11 | - Straight text 12 | - Glare in the header 13 | - Submenus 14 | - Heritidy Panel 15 | 16 | # Example 17 | ## Create menu 18 | ```ts 19 | import { CoraUI } from "./menu/menu" 20 | 21 | CoraUI.openMenu({ 22 | name: 'Menu F5', 23 | subtitle: "Menu intéractions", 24 | glare: true, 25 | buttons: [ 26 | { name: 'Am', onClick: () => console.log(15641)}, 27 | { name: 'Checkbox', checkbox: (checked1: boolean) => { 28 | console.log('boolean', checked1) 29 | }}, 30 | { name: 'Am 2', onClick: () => { 31 | console.log('amonaguyem') 32 | }}, 33 | { 34 | name: "Glace", onClick: () => null, 35 | slider: ["Chocolat", "Vanille", "Rien"] 36 | }, 37 | { name: 'Test', onClick: () => CoraUI.openSubmenu('submenu')}, 38 | { name: 'Test 2', onClick: () => CoraUI.openSubmenu('amona')}, 39 | { name: 'Close menu', rightText: "~g~100 000 $", onClick: () => CoraUI.closeMenu()}, 40 | ], 41 | submenus: { 42 | 'submenu': { 43 | name: 'Submenu F5', 44 | subtitle: "", 45 | glare: true, 46 | buttons: [ 47 | { name: 'Button 1', onClick: () => null}, 48 | ], 49 | }, 50 | 51 | 'amona': { 52 | name: 'Submenu F5', 53 | subtitle: "", 54 | glare: true, 55 | buttons: [ 56 | { name: 'Amonaguyem', onClick: () => null}, 57 | ], 58 | } 59 | } 60 | }) 61 | ``` 62 | # Prewiew 63 | ![unknown](https://cdn.discordapp.com/attachments/836192469359394856/842524671185911818/unknown.png) 64 | -------------------------------------------------------------------------------- /src/client/utils.ts: -------------------------------------------------------------------------------- 1 | export const DrawText2 = ( 2 | content: string, 3 | x: number, 4 | y: number, 5 | scale: number, 6 | font: number, 7 | color: any, 8 | intAlign: any, 9 | wrap: number 10 | ) => { 11 | SetTextFont(font); 12 | SetTextScale(scale, scale); 13 | 14 | if (intAlign) { 15 | SetTextCentre(true); 16 | } else { 17 | SetTextJustification(intAlign || 1); 18 | if (intAlign == 2) { 19 | SetTextWrap(0.0, wrap || x); 20 | } 21 | } 22 | 23 | SetTextEntry("STRING"); 24 | SetTextColour(color[0], color[1], color[2], color[3]); 25 | AddTextComponentString(content); 26 | DrawText(x, y); 27 | }; 28 | 29 | export const RenderSprite = ( 30 | TextureDictionary: string, 31 | TextureName: string, 32 | X: number, 33 | Y: number, 34 | Width: number, 35 | Height: number, 36 | Heading: number, 37 | R: number, 38 | G: number, 39 | B: number, 40 | A: number 41 | ) => { 42 | var [Xe, Ye] = GetScreenResolution(); 43 | X: X || 0 / Xe; 44 | Y: Y || 0 / Ye; 45 | Width: Width || 0 / Xe; 46 | Height: Height || 0 / Ye; 47 | if (!HasStreamedTextureDictLoaded(TextureDictionary)) { 48 | RequestStreamedTextureDict(TextureDictionary, true); 49 | } 50 | DrawSprite( 51 | TextureDictionary, 52 | TextureName, 53 | X + Width * 0.5, 54 | Y + Height * 0.5, 55 | Width, 56 | Height, 57 | Heading || 0, 58 | R, 59 | G, 60 | B, 61 | A 62 | ); 63 | }; 64 | 65 | export const DrawRectg = (x: any, y: any, w: any, h: any, color: any) => { 66 | DrawRect(x + w / 2, y + h / 2, w, h, color[0], color[1], color[2], color[3]); 67 | }; 68 | 69 | export const calc = (n: any) => { 70 | return 100 / n; 71 | }; 72 | 73 | export const GetTextWidth = (txt: string, font: number, scale: number) => { 74 | BeginTextCommandGetWidth("CELL_EMAIL_BCON"); 75 | SetTextFont(font); 76 | SetTextScale(1.0, scale); 77 | AddTextComponentSubstringPlayerName(txt); 78 | let width = EndTextCommandGetWidth(true); 79 | return width; 80 | } 81 | 82 | function clamp(min: any, max: any) { 83 | return Math.min(Math.max(0, min), max); 84 | }; 85 | 86 | function StringToArray(str: string) { 87 | let charcount = str.length 88 | let strCount = Math.ceil(charcount / 99); 89 | let strings = [] 90 | 91 | for (let i = 1; strCount; i++) { 92 | let start = (i-1) * 99 +1 93 | let clamp2 = clamp(str.substring(start), 99); 94 | let finish = ((i != 1) && (start - 1) || 0) + clamp2 95 | 96 | strings[i] = str.substring(start, finish) 97 | } 98 | 99 | return strings 100 | } 101 | 102 | function AddText(str: string) { 103 | let charCount = str.length 104 | if (charCount < 100) { 105 | AddTextComponentSubstringPlayerName(str) 106 | } else { 107 | let strings = StringToArray(str) 108 | for (let s = 1; strings.length; s++) { 109 | AddTextComponentSubstringPlayerName(strings[s]) 110 | } 111 | } 112 | } 113 | 114 | export const breakString = (str: string, limit: number) => { 115 | let brokenString = ''; 116 | for(let i = 0, count = 0; i < str.length; i++){ 117 | if(count >= limit && str[i] === ' '){ 118 | count = 0; 119 | brokenString += '\n'; 120 | }else{ 121 | count++; 122 | brokenString += str[i]; 123 | } 124 | } 125 | return brokenString; 126 | } 127 | 128 | export const GetLineCount = (Text: string, X: number, Y: number) => { 129 | var [Xe, Ye] = GetScreenResolution(); 130 | var x = X / Xe 131 | var y = Y / Ye 132 | BeginTextCommandLineCount("CELL_EMAIL_BCON") 133 | AddText(Text) 134 | return GetTextScreenLineCount(x,y) 135 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright 2021-2022 Hoyame 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /src/client/index.ts: -------------------------------------------------------------------------------- 1 | import { calc, DrawRectg, DrawText2, RenderSprite, GetTextWidth, GetLineCount, breakString } from "./utils"; 2 | 3 | interface IButtons { 4 | name: string; 5 | description?: string; 6 | rightText?: string; 7 | checkbox?: any; 8 | statusCheckbox?: boolean; 9 | slider?: Array; 10 | indexSlider?: number; 11 | slideNum?: number; 12 | backgroundColor?: any; 13 | 14 | onClick?: any; 15 | onSlide?: any; 16 | onPourcentage?: any; 17 | valuePourcentage?: any; 18 | 19 | onColorPanel?: any; 20 | customColorPanel?: number[][]; 21 | 22 | indexColorPanel?: number; 23 | showColorPanel?: number; 24 | lenghtColorPanel?: number; 25 | } 26 | 27 | interface ICMenu { 28 | name: string; 29 | subtitle: string; 30 | glare: boolean; 31 | closable?: (boolean | undefined) 32 | submenus?: any; 33 | buttons: IButtons[]; 34 | 35 | heritagePanel?: any; 36 | indexHeritagePanel?: [number, number, number, number]; 37 | } 38 | 39 | let init = true; 40 | let tick: any; 41 | 42 | export class CoraUI { 43 | static Config = { 44 | colors: { 45 | dark: { 46 | header: [16, 16, 16, 255], 47 | }, 48 | 49 | white: { 50 | header: [250, 242, 117, 255], 51 | }, 52 | }, 53 | 54 | x: 0.14, 55 | y: 0.175, 56 | width: 0.225, 57 | bottomHeight: 0.029, 58 | headerHeight: 0.095, 59 | colorProps: 0.04, 60 | glare: true, 61 | 62 | SettingsCheckbox: { 63 | Dictionary: "commonmenu", 64 | TexturesUnchecked: "shop_box_blank", 65 | TexturesChecked: "shop_box_tick", 66 | TexturesCheckedOver: "shop_box_tickb", 67 | }, 68 | 69 | SettingsPercentagePanel: { 70 | Text: { 71 | Middle: { X: 215.5, Y: 15, Scale: 0.35 }, 72 | }, 73 | }, 74 | 75 | ColoursPanel: [ 76 | [255, 255, 255, 255], // pure white 77 | [240, 240, 240, 255], // white 78 | [0, 0, 0, 255], // black 79 | [155, 155, 155, 255], // grey 80 | [205, 205, 205, 255], // LightGrey 81 | [77, 77, 77, 255], // DarkGrey 82 | [224, 50, 50, 255], //Red 83 | [240, 153, 153, 255], // RedLight 84 | [112, 25, 25, 255], // RedDark 85 | [93, 182, 229, 255], // Blue 86 | [174, 219, 242, 255], // LightBlue 87 | [47, 92, 115, 255], // DarkBlue 88 | [240, 200, 80, 255], // Yellow 89 | [254, 235, 169, 255], // LightYellow 90 | [126, 107, 41, 255], // DarkYellow 91 | [255, 133, 85, 255], // Orange 92 | [255, 194, 170, 255], // LightOrange 93 | [127, 66, 42, 255], // DarkOrange 94 | [114, 204, 114, 255], // Green 95 | [185, 230, 185, 255], // LightGreen 96 | [57, 102, 57, 255], // DarkGreen 97 | [132, 102, 226, 255], // Purple 98 | [192, 179, 239, 255], // LightPurple 99 | [67, 57, 111, 255], // DarkPurple 100 | [203, 54, 148, 255], // Pink 101 | [255, 215, 0, 255], // Gold 102 | [255, 228, 181, 255], // Moccasin 103 | [240, 230, 140, 255], // Khaki 104 | ], 105 | }; 106 | 107 | static Menu = { 108 | Opened: false, 109 | MenuOpened: "", 110 | submenu: [false, ""], 111 | IndexButton: 0, 112 | }; 113 | 114 | static Temp: ICMenu = { 115 | name: "", 116 | subtitle: "", 117 | glare: false, 118 | closable: true, 119 | buttons: [], 120 | submenus: {}, 121 | heritagePanel: false, 122 | indexHeritagePanel: [0, 0, 0, 0] 123 | }; 124 | 125 | static CurrentMenu: ICMenu = { 126 | name: "", 127 | subtitle: "", 128 | glare: false, 129 | closable: true, 130 | buttons: [], 131 | submenus: {}, 132 | heritagePanel: false, 133 | indexHeritagePanel: [0, 0, 0, 0] 134 | }; 135 | 136 | public static drawHeader() { 137 | let Glare = RequestScaleformMovie("MP_MENU_GLARE"); 138 | 139 | if (this.Menu.Opened == true) { 140 | DrawRect( 141 | this.Config.x, 142 | this.Config.y, 143 | this.Config.width, 144 | this.Config.headerHeight, 145 | this.Config.colors.dark.header[0], 146 | this.Config.colors.dark.header[1], 147 | this.Config.colors.dark.header[2], 148 | this.Config.colors.dark.header[3] 149 | ); 150 | 151 | if (this.CurrentMenu.glare) { 152 | PushScaleformMovieFunction(Glare, "initScreenLayout"); 153 | PopScaleformMovieFunctionVoid(); 154 | DrawScaleformMovie( 155 | Glare, 156 | this.Config.x + 0.297, 157 | this.Config.y + 0.3985, 158 | this.Config.width + 0.7, 159 | this.Config.headerHeight + 0.953, 160 | 255, 161 | 255, 162 | 255, 163 | 255, 164 | 0 165 | ); 166 | } 167 | 168 | DrawText2( 169 | this.CurrentMenu.name, 170 | this.Config.x - 0.095, 171 | this.Config.y - 0.024, 172 | 0.75, 173 | 1, 174 | [255, 255, 255, 255], 175 | false, 176 | 2 177 | ); 178 | DrawRect( 179 | this.Config.x, 180 | this.Config.y + (this.Config.headerHeight - 0.03065), 181 | this.Config.width, 182 | this.Config.bottomHeight + 0.003, 183 | this.Config.colors.dark.header[0], 184 | this.Config.colors.dark.header[1], 185 | this.Config.colors.dark.header[2], 186 | 230 187 | ); 188 | DrawText2( 189 | this.CurrentMenu.subtitle, 190 | this.Config.x - 0.1075, 191 | this.Config.y + (this.Config.headerHeight - 0.042), 192 | 0.265, 193 | 0, 194 | [255, 255, 255, 255], 195 | false, 196 | 2 197 | ); 198 | DrawText2( 199 | this.Menu.IndexButton + 1 + "/" + this.CurrentMenu.buttons.length, 200 | this.Config.x + 0.1, 201 | this.Config.y + (this.Config.headerHeight - 0.041), 202 | 0.265, 203 | 0, 204 | [255, 255, 255, 255], 205 | true, 206 | 2.5 207 | ); 208 | } 209 | } 210 | 211 | public static drawButtons() { 212 | if (this.Menu.Opened == true) { 213 | let startIndex = Math.max(0, this.Menu.IndexButton - 9); 214 | let endIndex = Math.min(this.CurrentMenu.buttons.length, startIndex + 10); 215 | let startY = this.Config.y + (this.Config.bottomHeight + 0.0055); 216 | 217 | if (this.CurrentMenu.heritagePanel == true) { 218 | startY += 0.203; 219 | } 220 | 221 | for (let i = startIndex; i < endIndex; i++) { 222 | if (this.CurrentMenu.buttons[i].checkbox !== null && init) { 223 | this.CurrentMenu.buttons[i].statusCheckbox = false; 224 | init = false; 225 | } 226 | 227 | const color_def = i == this.Menu.IndexButton ? [255, 255, 255, 255] : [16, 16, 16, 120] 228 | let color_cust: any 229 | if (this.CurrentMenu.buttons[i].backgroundColor) { 230 | color_cust = i == this.Menu.IndexButton ? [this.CurrentMenu.buttons[i].backgroundColor[0], this.CurrentMenu.buttons[i].backgroundColor[1], this.CurrentMenu.buttons[i].backgroundColor[2], 255] : [this.CurrentMenu.buttons[i].backgroundColor[0], this.CurrentMenu.buttons[i].backgroundColor[1], this.CurrentMenu.buttons[i].backgroundColor[2], 100] 231 | } 232 | 233 | const color = 234 | this.CurrentMenu.buttons[i].backgroundColor ? color_cust : color_def 235 | const colorText = 236 | i == this.Menu.IndexButton ? [0, 0, 0, 255] : [255, 255, 255, 255]; 237 | const checkboxColor = 238 | i == this.Menu.IndexButton ? [0, 0, 0, 255] : [255, 255, 255, 255]; 239 | const lenghtforright2 = this.CurrentMenu.buttons[i].rightText || ""; 240 | const lenghtforright = lenghtforright2.length || 0; 241 | 242 | DrawRect( 243 | this.Config.x, 244 | startY + 245 | (this.Config.bottomHeight * (i - startIndex + 1) + 0.033), 246 | this.Config.width, 247 | this.Config.bottomHeight + 0.0011, 248 | color[0], 249 | color[1], 250 | color[2], 251 | color[3] 252 | ); 253 | DrawText2( 254 | this.CurrentMenu.buttons[i].name, 255 | this.Config.x - 0.1075, 256 | startY + 0.022 + 257 | (this.Config.bottomHeight * (i - startIndex + 1)), 258 | 0.265, 259 | 0, 260 | [colorText[0], colorText[1], colorText[2], colorText[3]], 261 | false, 262 | 2 263 | ); 264 | 265 | if (this.CurrentMenu.buttons[i].description && this.CurrentMenu.buttons[i].description != "") { 266 | if (i == this.Menu.IndexButton) { 267 | const lenght = this.CurrentMenu.buttons[i].description || "" 268 | if (lenght.length < 100) { 269 | const colorfordescback = [16, 16, 16, 165]; 270 | const colorfordesctext = [255, 255, 255, 255]; 271 | const buttonsLenght = this.CurrentMenu.buttons.length > 10 ? 10 : this.CurrentMenu.buttons.length 272 | 273 | let DescLineCount = GetLineCount(this.CurrentMenu.buttons[i].description || "", this.Config.x - 0.1075, startY + (this.Config.bottomHeight * (buttonsLenght + 1) - 0.208) + 0.2350) 274 | 275 | if (DescLineCount == 1) { 276 | DrawRect( 277 | this.Config.x, 278 | startY + 279 | (this.Config.bottomHeight * (buttonsLenght + 1) - 0.208) + 0.2450, 280 | this.Config.width, 281 | this.Config.bottomHeight + 0.0011, 282 | colorfordescback[0], 283 | colorfordescback[1], 284 | colorfordescback[2], 285 | colorfordescback[3] 286 | ); 287 | DrawText2( 288 | this.CurrentMenu.buttons[i].description || "", 289 | this.Config.x - 0.1075, 290 | startY + 291 | (this.Config.bottomHeight * (buttonsLenght + 1) - 0.208) + 0.2350, 292 | 0.265, 293 | 0, 294 | [colorfordesctext[0], colorfordesctext[1], colorfordesctext[2], colorfordesctext[3]], 295 | false, 296 | 2 297 | ); 298 | } else if (DescLineCount >= 2) { 299 | DrawRect( 300 | this.Config.x, 301 | startY + 302 | (this.Config.bottomHeight * (buttonsLenght + 1) - 0.208) + 0.2545, 303 | this.Config.width, 304 | this.Config.bottomHeight + 0.0201, 305 | colorfordescback[0], 306 | colorfordescback[1], 307 | colorfordescback[2], 308 | colorfordescback[3] 309 | ); 310 | DrawText2( 311 | breakString(this.CurrentMenu.buttons[i].description || "", 40), 312 | this.Config.x - 0.1075, 313 | startY + 314 | (this.Config.bottomHeight * (buttonsLenght + 1) - 0.208) + 0.2350, 315 | 0.265, 316 | 0, 317 | [colorfordesctext[0], colorfordesctext[1], colorfordesctext[2], colorfordesctext[3]], 318 | false, 319 | 2 320 | ); 321 | } 322 | } 323 | } 324 | } 325 | 326 | if (this.CurrentMenu.buttons[i].rightText) { 327 | const lenght = this.CurrentMenu.buttons[i].rightText || ""; 328 | 329 | DrawText2( 330 | this.CurrentMenu.buttons[i].rightText || "", 331 | this.Config.x + 0.102 - lenght.length / 1000, 332 | startY + 0.0225 + 333 | (this.Config.bottomHeight * (i - startIndex + 1)), 334 | 0.235, 335 | 0, 336 | [colorText[0], colorText[1], colorText[2], colorText[3]], 337 | true, 338 | 2 339 | ); 340 | } 341 | 342 | if (this.CurrentMenu.buttons[i].checkbox) { 343 | if (this.CurrentMenu.buttons[i].statusCheckbox) { 344 | if (i == this.Menu.IndexButton) { 345 | RenderSprite( 346 | this.Config.SettingsCheckbox.Dictionary, 347 | this.Config.SettingsCheckbox.TexturesCheckedOver, 348 | this.Config.x + 0.094, 349 | startY + 350 | (this.Config.bottomHeight * (i - startIndex + 1) + 0.018), 351 | this.Config.width - 0.2078, 352 | this.Config.bottomHeight + 0.0014, 353 | 0, 354 | 255, 355 | 255, 356 | 255, 357 | 255 358 | ); 359 | } else { 360 | RenderSprite( 361 | this.Config.SettingsCheckbox.Dictionary, 362 | this.Config.SettingsCheckbox.TexturesChecked, 363 | this.Config.x + 0.094, 364 | startY + 365 | (this.Config.bottomHeight * (i - startIndex + 1) + 0.018), 366 | this.Config.width - 0.2078, 367 | this.Config.bottomHeight + 0.0014, 368 | 0, 369 | 255, 370 | 255, 371 | 255, 372 | 255 373 | ); 374 | } 375 | } else { 376 | RenderSprite( 377 | this.Config.SettingsCheckbox.Dictionary, 378 | this.Config.SettingsCheckbox.TexturesUnchecked, 379 | this.Config.x + 0.094, 380 | startY + 381 | (this.Config.bottomHeight * (i - startIndex + 1) + 0.018), 382 | this.Config.width - 0.2078, 383 | this.Config.bottomHeight + 0.0014, 384 | 90, 385 | checkboxColor[0], 386 | checkboxColor[1], 387 | checkboxColor[2], 388 | checkboxColor[3] 389 | ); 390 | } 391 | } 392 | 393 | if (this.CurrentMenu.buttons[i].slider) { 394 | const slider = this.CurrentMenu.buttons[i].slider || []; 395 | const index = this.CurrentMenu.buttons[i].indexSlider || 0; 396 | const lenght = slider[index] || ""; 397 | 398 | let changelenght = (GetTextWidth(lenght, 0, 0.235)) 399 | 400 | let LengthToGive = lenght.length / 1000; 401 | if (lenght.length >= 9) { 402 | LengthToGive = lenght.length / 350; 403 | } 404 | 405 | let LengthToGive2 = lenght.length / 1000; 406 | if (lenght.length >= 9) { 407 | LengthToGive2 = lenght.length / 600; 408 | } 409 | 410 | //console.log(changelenght) 411 | 412 | DrawSprite( 413 | "commonmenu", 414 | "arrowleft", 415 | this.Config.x + 0.0775 - LengthToGive, 416 | // (changelenght), 417 | startY + 0.033 + 418 | (this.Config.bottomHeight * (i - startIndex + 1)), 419 | 0.009, 420 | 0.018, 421 | 0.0, 422 | colorText[0], 423 | colorText[1], 424 | colorText[2], 425 | colorText[3] 426 | ); 427 | DrawText2( 428 | slider[index] || "", 429 | this.Config.x + 0.0935 - LengthToGive2, 430 | startY + 0.023 + 431 | (this.Config.bottomHeight * (i - startIndex + 1)), 432 | 0.235, 433 | 0, 434 | [colorText[0], colorText[1], colorText[2], colorText[3]], 435 | true, 436 | 2 437 | ); 438 | DrawSprite( 439 | "commonmenu", 440 | "arrowright", 441 | this.Config.x + 0.1045, 442 | startY + 0.033 + 443 | (this.Config.bottomHeight * (i - startIndex + 1)), 444 | 0.009, 445 | 0.018, 446 | 0.0, 447 | colorText[0], 448 | colorText[1], 449 | colorText[2], 450 | colorText[3] 451 | ); 452 | } 453 | 454 | if (this.CurrentMenu.buttons[i].slideNum) { 455 | let slider: any = []; 456 | const index = this.CurrentMenu.buttons[i].indexSlider || 0; 457 | const slideNum = this.CurrentMenu.buttons[i].slideNum || 0; 458 | 459 | for (let z = 0; z <= slideNum; z++) { 460 | slider.push(z.toString()); 461 | } 462 | 463 | DrawSprite( 464 | "commonmenu", 465 | "arrowleft", 466 | this.Config.x + 0.089, 467 | startY + 0.033 + 468 | (this.Config.bottomHeight * (i - startIndex + 1)), 469 | 0.009, 470 | 0.018, 471 | 0.0, 472 | colorText[0], 473 | colorText[1], 474 | colorText[2], 475 | colorText[3] 476 | ); 477 | DrawText2( 478 | slider[index] || "", 479 | this.Config.x + 0.097, 480 | startY + 0.023 + 481 | (this.Config.bottomHeight * (i - startIndex + 1)), 482 | 0.235, 483 | 0, 484 | [colorText[0], colorText[1], colorText[2], colorText[3]], 485 | true, 486 | 2 487 | ); 488 | DrawSprite( 489 | "commonmenu", 490 | "arrowright", 491 | this.Config.x + 0.1045, 492 | startY + 0.033 + 493 | (this.Config.bottomHeight * (i - startIndex + 1)), 494 | 0.009, 495 | 0.018, 496 | 0.0, 497 | colorText[0], 498 | colorText[1], 499 | colorText[2], 500 | colorText[3] 501 | ); 502 | } 503 | 504 | if ( 505 | this.CurrentMenu.buttons[i].onPourcentage !== undefined && 506 | i == this.Menu.IndexButton 507 | ) { 508 | if ( 509 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage == 510 | undefined 511 | ) { 512 | this.CurrentMenu.buttons[ 513 | this.Menu.IndexButton 514 | ].valuePourcentage = 0; 515 | } 516 | 517 | this.DrawPercentagePanel( 518 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage + 519 | "%" 520 | ); 521 | } 522 | 523 | if ( 524 | this.CurrentMenu.buttons[i].onColorPanel !== undefined && 525 | i == this.Menu.IndexButton 526 | ) { 527 | this.DrawColorPanel(undefined, this.CurrentMenu.buttons[i].customColorPanel); 528 | } 529 | 530 | if (this.CurrentMenu.heritagePanel) { 531 | this.DrawHeritagePanel(); 532 | } 533 | } 534 | } 535 | } 536 | 537 | public static DrawColorPanel( 538 | Title?: string, 539 | Colors?: number[][] 540 | ) { 541 | const buttonsLenght = this.CurrentMenu.buttons.length > 10 ? 10 : this.CurrentMenu.buttons.length 542 | 543 | const ColorArray = Colors || this.Config.ColoursPanel; 544 | 545 | this.CurrentMenu.buttons[this.Menu.IndexButton].lenghtColorPanel = 546 | ColorArray.length; 547 | const colorText = [255, 255, 255, 255]; 548 | const lenghtforTitle2 = Title || "Colors"; 549 | const lenghtforTitle = lenghtforTitle2.length || 0; 550 | 551 | this.CurrentMenu.buttons[this.Menu.IndexButton].showColorPanel = 8; 552 | const indexAColorPanel = 553 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexColorPanel || 0; 554 | 555 | DrawRect( 556 | this.Config.x, 557 | this.Config.y + 558 | (this.Config.bottomHeight * (buttonsLenght + 1) - 559 | 0.201) + 560 | 0.304, 561 | this.Config.width - 0.45, 562 | this.Config.bottomHeight + 0.065, 563 | 0, 564 | 0, 565 | 0, 566 | 105 567 | ); // background 568 | 569 | DrawText2( 570 | Title || "Colors", 571 | this.Config.x - 0.004 - lenghtforTitle / 1000, 572 | this.Config.y + 573 | (this.Config.bottomHeight * (buttonsLenght + 1) - 574 | 0.201) + 575 | 0.263, 576 | this.Config.SettingsPercentagePanel.Text.Middle.Scale, 577 | 6, 578 | [colorText[0], colorText[1], colorText[2], colorText[3]], 579 | false, 580 | 2 581 | ); 582 | DrawSprite( 583 | "commonmenu", 584 | "arrowleft", 585 | this.Config.x - 0.105, 586 | this.Config.y + 587 | (this.Config.bottomHeight * (buttonsLenght + 1) - 588 | 0.188) + 589 | 0.263, 590 | 0.009, 591 | 0.018, 592 | 0.0, 593 | colorText[0], 594 | colorText[1], 595 | colorText[2], 596 | colorText[3] 597 | ); 598 | DrawSprite( 599 | "commonmenu", 600 | "arrowright", 601 | this.Config.x + 0.105, 602 | this.Config.y + 603 | (this.Config.bottomHeight * (buttonsLenght + 1) - 604 | 0.188) + 605 | 0.263, 606 | 0.009, 607 | 0.018, 608 | 0.0, 609 | colorText[0], 610 | colorText[1], 611 | colorText[2], 612 | colorText[3] 613 | ); 614 | 615 | const startIndex = Math.max(0, indexAColorPanel - 7); 616 | const endIndex = Math.min(ColorArray.length, startIndex + 8); 617 | const rectWidth = this.Config.colorProps - 0.0175; 618 | const startX = this.Config.x - rectWidth * 3.5; 619 | 620 | for (let ColorIndex = startIndex; ColorIndex < endIndex; ColorIndex++) { 621 | let rgb = 622 | ColorIndex == indexAColorPanel 623 | ? [ 624 | ColorArray[ColorIndex][0], 625 | ColorArray[ColorIndex][1], 626 | ColorArray[ColorIndex][2], 627 | ColorArray[ColorIndex].length > 3 ? (ColorArray[ColorIndex][3] - 150) : 105 628 | ] 629 | : [ 630 | ColorArray[ColorIndex][0], 631 | ColorArray[ColorIndex][1], 632 | ColorArray[ColorIndex][2], 633 | ColorArray[ColorIndex].length > 3 ? ColorArray[ColorIndex][3] : 255, 634 | ]; 635 | DrawRect( 636 | startX + rectWidth * (ColorIndex - startIndex), 637 | this.Config.y + 638 | (this.Config.bottomHeight * (buttonsLenght + 1) - 639 | 0.201) + 640 | 0.3185, 641 | 642 | rectWidth, 643 | this.Config.colorProps, 644 | rgb[0], 645 | rgb[1], 646 | rgb[2], 647 | rgb[3] 648 | ); // Colors 649 | } 650 | 651 | DrawRect( 652 | startX + rectWidth * Math.min(indexAColorPanel, 7), 653 | this.Config.y + (this.Config.bottomHeight * (buttonsLenght + 1) - 0.201) + 0.3185 - this.Config.colorProps / 2 - 0.002, 654 | rectWidth, 655 | 0.004, 656 | 255, 657 | 255, 658 | 255, 659 | 255 660 | ); // Colors 661 | } 662 | 663 | public static DrawPercentagePanel(TextHeader?: string) { 664 | const colorText = [255, 255, 255, 255]; 665 | const lenghtforPercentage2 = TextHeader || "Percentage"; 666 | const lenghtforPercentage = lenghtforPercentage2.length || 0; 667 | const buttonsLenght = this.CurrentMenu.buttons.length > 10 ? 10 : this.CurrentMenu.buttons.length 668 | 669 | const percentage = 670 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage || 100; 671 | 672 | DrawRect( 673 | this.Config.x, 674 | this.Config.y + 675 | (this.Config.bottomHeight * (buttonsLenght + 1) - 676 | 0.208) + 677 | 0.2935, 678 | this.Config.width - 0.45, 679 | this.Config.bottomHeight + 0.0294, 680 | 0, 681 | 0, 682 | 0, 683 | 105 684 | ); // background 685 | DrawRectg( 686 | this.Config.x - 0.103, 687 | this.Config.y + 688 | (this.Config.bottomHeight * (buttonsLenght + 1) - 689 | 0.201) + 690 | 0.2935, 691 | this.Config.width - 0.017, 692 | 0.008, 693 | [0, 0, 0, 120] 694 | ); 695 | DrawRectg( 696 | this.Config.x - 0.103, 697 | this.Config.y + 698 | (this.Config.bottomHeight * (buttonsLenght + 1) - 699 | 0.201) + 700 | 0.2935, 701 | (this.Config.width - 0.017) / calc(percentage), 702 | 0.008, 703 | [255, 255, 255, 255] 704 | ); 705 | 706 | DrawText2( 707 | TextHeader || "Percentage", 708 | this.Config.x - 0.004 - lenghtforPercentage / 1000, 709 | this.Config.y + 710 | (this.Config.bottomHeight * (buttonsLenght + 1) - 711 | 0.208) + 712 | 0.2695, 713 | this.Config.SettingsPercentagePanel.Text.Middle.Scale, 714 | 6, 715 | [colorText[0], colorText[1], colorText[2], colorText[3]], 716 | false, 717 | 2 718 | ); 719 | DrawText2( 720 | "0%", 721 | this.Config.x - 0.1045, 722 | this.Config.y + 723 | (this.Config.bottomHeight * (buttonsLenght + 1) - 724 | 0.208) + 725 | 0.2695, 726 | this.Config.SettingsPercentagePanel.Text.Middle.Scale, 727 | 6, 728 | [colorText[0], colorText[1], colorText[2], colorText[3]], 729 | false, 730 | 2 731 | ); 732 | DrawText2( 733 | "100%", 734 | this.Config.x + 0.087, 735 | this.Config.y + 736 | (this.Config.bottomHeight * (buttonsLenght + 1) - 737 | 0.208) + 738 | 0.2695, 739 | this.Config.SettingsPercentagePanel.Text.Middle.Scale, 740 | 6, 741 | [colorText[0], colorText[1], colorText[2], colorText[3]], 742 | false, 743 | 2 744 | ); 745 | } 746 | 747 | public static DrawHeritagePanel() { 748 | const indexHeritagePanel = this.CurrentMenu.indexHeritagePanel || [0, 0, 0, 0] 749 | // DrawRect( 750 | // this.Config.x, 751 | // this.Config.y + 752 | // (this.Config.bottomHeight + 0.0055) + 753 | // (this.Config.bottomHeight * (i - startIndex + 1) + 0.033), 754 | // this.Config.width, 755 | // this.Config.bottomHeight + 0.0011, 756 | // color[0], 757 | // color[1], 758 | // color[2], 759 | // color[3] 760 | // ); 761 | 762 | DrawSprite("pause_menu_pages_char_mom_dad", "mumdadbg", 763 | this.Config.x, 764 | this.Config.y + (this.Config.bottomHeight + 0.0055) + 0.10894 + 0.0385, 765 | 0.225, 0.20, .0, 255, 255, 255, 255) 766 | 767 | DrawSprite("pause_menu_pages_char_mom_dad", "vignette", 768 | this.Config.x, 769 | this.Config.y + (this.Config.bottomHeight + 0.0055) + 0.10895 + 0.0385, 770 | 0.225, 0.20, .0, 255, 255, 255, 255) 771 | 772 | DrawSprite("char_creator_portraits", "male_" + + indexHeritagePanel[0], 773 | this.Config.x - 0.040, 774 | this.Config.y + (this.Config.bottomHeight + 0.0055) + 0.10892 + 0.0385, 775 | 0.11, 0.20, .0, 255, 255, 255, 255) 776 | 777 | DrawSprite("char_creator_portraits", "female_" + indexHeritagePanel[1], 778 | this.Config.x + 0.040, 779 | this.Config.y + (this.Config.bottomHeight + 0.0055) + 0.10892 + 0.0385, 780 | 0.11, 0.20, .0, 255, 255, 255, 255) 781 | } 782 | 783 | public static controlMenu() { 784 | if (IsControlJustPressed(0, 27)) { 785 | if (this.Menu.IndexButton <= 0) { 786 | this.Menu.IndexButton = this.CurrentMenu.buttons.length - 1; 787 | } else { 788 | this.Menu.IndexButton--; 789 | } 790 | } else if (IsControlJustPressed(0, 173)) { 791 | if (this.Menu.IndexButton >= this.CurrentMenu.buttons.length - 1) { 792 | this.Menu.IndexButton = 0; 793 | } else { 794 | this.Menu.IndexButton++; 795 | } 796 | } else if (IsControlJustPressed(0, 201)) { 797 | if (this.CurrentMenu.buttons[this.Menu.IndexButton].onClick) { 798 | this.CurrentMenu.buttons[this.Menu.IndexButton].onClick(); 799 | } else if (this.CurrentMenu.buttons[this.Menu.IndexButton].checkbox) { 800 | this.CurrentMenu.buttons[this.Menu.IndexButton].statusCheckbox = 801 | !this.CurrentMenu.buttons[this.Menu.IndexButton].statusCheckbox; 802 | this.CurrentMenu.buttons[this.Menu.IndexButton].checkbox( 803 | this.CurrentMenu.buttons[this.Menu.IndexButton].statusCheckbox 804 | ); 805 | } 806 | } else if (IsControlJustPressed(0, 202)) { 807 | const menu: ICMenu = this.CurrentMenu; 808 | if (this.Menu.submenu[0] == true) { 809 | this.closeSubMenu(); 810 | } else { 811 | const blockHandler = (): void => { }; 812 | ((menu.closable === true) || (menu.closable === undefined) ? this.closeMenu() : blockHandler); 813 | } 814 | } else if (IsControlJustPressed(0, 174)) { 815 | 816 | if ( 817 | this.CurrentMenu.buttons[this.Menu.IndexButton].slider || 818 | this.CurrentMenu.buttons[this.Menu.IndexButton].slideNum 819 | ) { 820 | // Sliders 821 | 822 | const indexSlider = 823 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexSlider || 0; 824 | const lenghtSlider = this.CurrentMenu.buttons[this.Menu.IndexButton] 825 | .slider 826 | ? this.CurrentMenu.buttons[this.Menu.IndexButton].slider?.length || 0 827 | : this.CurrentMenu.buttons[this.Menu.IndexButton].slideNum || 0; 828 | 829 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexSlider = 830 | indexSlider > 0 ? indexSlider - 1 : lenghtSlider - 1; 831 | this.CurrentMenu.buttons[this.Menu.IndexButton].onSlide( 832 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexSlider 833 | ); 834 | } 835 | 836 | if (this.CurrentMenu.buttons[this.Menu.IndexButton].onColorPanel) { 837 | const indexColorPanel = 838 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexColorPanel || 0; 839 | const lenghtColorPanel = 840 | this.CurrentMenu.buttons[this.Menu.IndexButton].lenghtColorPanel || 0; 841 | 842 | if (indexColorPanel <= 0) { 843 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexColorPanel = 844 | this.CurrentMenu.buttons[this.Menu.IndexButton].lenghtColorPanel; 845 | } else { 846 | if (indexColorPanel > 8) { 847 | this.CurrentMenu.buttons[this.Menu.IndexButton].showColorPanel = -1; 848 | } 849 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexColorPanel = 850 | indexColorPanel - 1; // remove 1 851 | } 852 | 853 | console.log( 854 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexColorPanel 855 | ); 856 | } 857 | } else if (IsControlJustPressed(0, 175)) { 858 | // right just press 859 | if ( 860 | this.CurrentMenu.buttons[this.Menu.IndexButton].slider || 861 | this.CurrentMenu.buttons[this.Menu.IndexButton].slideNum 862 | ) { 863 | // Sliders 864 | const indexSlider = 865 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexSlider || 0; 866 | const lenghtSlider = this.CurrentMenu.buttons[this.Menu.IndexButton] 867 | .slider 868 | ? this.CurrentMenu.buttons[this.Menu.IndexButton].slider?.length || 0 869 | : this.CurrentMenu.buttons[this.Menu.IndexButton].slideNum || 0; 870 | 871 | if (indexSlider >= lenghtSlider - 1) { 872 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexSlider = 0; 873 | } else { 874 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexSlider = 875 | indexSlider + 1; 876 | } 877 | 878 | this.CurrentMenu.buttons[this.Menu.IndexButton].onSlide( 879 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexSlider 880 | ); 881 | } 882 | 883 | if (this.CurrentMenu.buttons[this.Menu.IndexButton].onColorPanel) { 884 | const indexColorPanel = 885 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexColorPanel || 0; 886 | const lenghtColorPanel = 887 | this.CurrentMenu.buttons[this.Menu.IndexButton].lenghtColorPanel || 0; 888 | 889 | if (indexColorPanel >= lenghtColorPanel) { 890 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexColorPanel = 0; 891 | } else { 892 | if (indexColorPanel > 8) { 893 | this.CurrentMenu.buttons[this.Menu.IndexButton].showColorPanel = +1; 894 | } 895 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexColorPanel = 896 | indexColorPanel + 1; // remove 1 897 | } 898 | 899 | console.log( 900 | this.CurrentMenu.buttons[this.Menu.IndexButton].indexColorPanel 901 | ); 902 | } 903 | } else if (IsControlPressed(0, 174)) { 904 | // left press 905 | if (this.CurrentMenu.buttons[this.Menu.IndexButton].onPourcentage) { 906 | if ( 907 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage <= 0 908 | ) { 909 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage = 910 | this.CurrentMenu.buttons[ 911 | this.Menu.IndexButton 912 | ].valuePourcentage = 100; 913 | this.CurrentMenu.buttons[this.Menu.IndexButton].onPourcentage( 914 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage 915 | ); 916 | } else { 917 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage = 918 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage - 919 | 1; 920 | this.CurrentMenu.buttons[this.Menu.IndexButton].onPourcentage( 921 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage 922 | ); 923 | } 924 | } 925 | } else if (IsControlPressed(0, 175)) { 926 | // right press 927 | if (this.CurrentMenu.buttons[this.Menu.IndexButton].onPourcentage) { 928 | if ( 929 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage >= 930 | 100 931 | ) { 932 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage = 933 | this.CurrentMenu.buttons[ 934 | this.Menu.IndexButton 935 | ].valuePourcentage = 0; 936 | this.CurrentMenu.buttons[this.Menu.IndexButton].onPourcentage( 937 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage 938 | ); 939 | } else { 940 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage = 941 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage + 942 | 1; 943 | this.CurrentMenu.buttons[this.Menu.IndexButton].onPourcentage( 944 | this.CurrentMenu.buttons[this.Menu.IndexButton].valuePourcentage 945 | ); 946 | } 947 | } 948 | } 949 | } 950 | 951 | public static drawMenu() { 952 | if (this.Menu.Opened) { 953 | this.drawHeader(); 954 | this.drawButtons(); 955 | this.controlMenu(); 956 | 957 | //this.DrawPercentagePanel("Pipi, caca"); 958 | //this.DrawColorPanel(); 959 | } 960 | } 961 | 962 | public static openSubmenu(name: string) { 963 | this.Menu.IndexButton = 0; 964 | this.CurrentMenu = this.CurrentMenu.submenus[name]; 965 | this.Menu.submenu = [true, name]; 966 | } 967 | 968 | public static closeSubMenu() { 969 | this.Menu.IndexButton = 0; 970 | this.CurrentMenu = this.Temp; 971 | this.Menu.submenu = [false, ")"]; 972 | } 973 | 974 | public static openMenu(obj: ICMenu) { 975 | SetStreamedTextureDictAsNoLongerNeeded("pause_menu_pages_char_mom_dad"); 976 | SetStreamedTextureDictAsNoLongerNeeded("commonmenu"); 977 | SetStreamedTextureDictAsNoLongerNeeded("char_creator_portraits"); 978 | RequestStreamedTextureDict("pause_menu_pages_char_mom_dad", false); 979 | RequestStreamedTextureDict("commonmenu", false); 980 | RequestStreamedTextureDict("char_creator_portraits", false); 981 | 982 | this.Menu.Opened = true; 983 | this.CurrentMenu = obj; 984 | this.Temp = obj; 985 | 986 | if (tick) clearTick(tick); 987 | tick = setTick(() => { 988 | if (!this.Menu.Opened) clearTick(tick); 989 | this.drawMenu(); 990 | }); 991 | } 992 | 993 | public static resetMenu() { 994 | this.Menu.IndexButton = 0; 995 | 996 | this.Temp = { 997 | name: "", 998 | subtitle: "", 999 | glare: false, 1000 | closable: true, 1001 | buttons: [], 1002 | submenus: {}, 1003 | heritagePanel: false, 1004 | indexHeritagePanel: [0, 0, 0, 0] 1005 | }; 1006 | 1007 | this.CurrentMenu = this.Temp; 1008 | } 1009 | 1010 | public static updateIndexHeritagePanel(i: number, c: number) { 1011 | if (this.CurrentMenu.indexHeritagePanel !== undefined) { 1012 | this.CurrentMenu.indexHeritagePanel[i] = c 1013 | } 1014 | } 1015 | 1016 | public static closeMenu() { 1017 | this.resetMenu(); 1018 | this.Menu.Opened = false; 1019 | } 1020 | } 1021 | 1022 | exports('CreateMenu', (arg: any) => { 1023 | CoraUI.openMenu(arg); 1024 | }) 1025 | 1026 | exports('CreateSubmenu', (arg: any) => { 1027 | CoraUI.openSubmenu(arg); 1028 | }) 1029 | 1030 | exports('CloseMenu', (arg: any) => { 1031 | CoraUI.closeMenu(); 1032 | }) 1033 | 1034 | exports('CloseSubmenu', (arg: any) => { 1035 | CoraUI.closeSubMenu(); 1036 | }) 1037 | 1038 | exports('ResetMenu', (arg: any) => { 1039 | CoraUI.resetMenu(); 1040 | }) 1041 | --------------------------------------------------------------------------------