├── README.md ├── client └── main.lua ├── config.lua ├── fxmanifest.lua ├── html ├── assets │ ├── car.jpg │ ├── image2.png │ └── multi.gif ├── css │ ├── reset.css │ └── style.css ├── index.html └── js │ └── script.js ├── locales └── en.lua └── server └── main.lua /README.md: -------------------------------------------------------------------------------- 1 | # qb-multicharacter 2 | Multi Character Feature for QB-Core Framework :people_holding_hands: 3 | 4 | Added support for setting default number of characters per player per Rockstar license 5 | 6 | # License 7 | 8 | QBCore Framework 9 | Copyright (C) 2021 Joshua Eger 10 | 11 | This program is free software: you can redistribute it and/or modify 12 | it under the terms of the GNU General Public License as published by 13 | the Free Software Foundation, either version 3 of the License, or 14 | (at your option) any later version. 15 | 16 | This program is distributed in the hope that it will be useful, 17 | but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | GNU General Public License for more details. 20 | 21 | You should have received a copy of the GNU General Public License 22 | along with this program. If not, see 23 | 24 | 25 | ## Dependencies 26 | - [qb-core](https://github.com/qbcore-framework/qb-core) 27 | - [qb-spawn](https://github.com/qbcore-framework/qb-spawn) - Spawn selector 28 | - [qb-apartments](https://github.com/qbcore-framework/qb-apartments) - For giving the player a apartment after creating a character. 29 | - [qb-clothing](https://github.com/qbcore-framework/qb-clothing) - For the character creation and saving outfits. 30 | - [qb-weathersync](https://github.com/qbcore-framework/qb-weathersync) - For adjusting the weather while player is creating a character. 31 | 32 | Can also be used with my other reskins 33 | - [qb-clothing](https://github.com/ST4LTH/qb-clothing) 34 | 35 | ## Screenshots 36 | ![Character Selection](https://i.imgur.com/OPg242t.png) 37 | ![Character Registration](https://i.imgur.com/eUEeWEt.png) 38 | 39 | ## Features 40 | - Ability to create up to 4 characters and delete any character. 41 | - Ability to see character information during selection. 42 | 43 | ## Installation 44 | ### Manual 45 | - Download the script and put it in the `[qb]` directory. 46 | - Add the following code to your server.cfg/resouces.cfg 47 | ``` 48 | ensure qb-core 49 | ensure qb-multicharacter 50 | ensure qb-spawn 51 | ensure qb-apartments 52 | ensure qb-clothing 53 | ensure qb-weathersync 54 | ``` 55 | "# qb-multicharacter" 56 | "# qb-multicharacter" 57 | -------------------------------------------------------------------------------- /client/main.lua: -------------------------------------------------------------------------------- 1 | local cam = nil 2 | local charPed = nil 3 | local QBCore = exports['qb-core']:GetCoreObject() 4 | 5 | -- Main Thread 6 | 7 | CreateThread(function() 8 | while true do 9 | Wait(0) 10 | if NetworkIsSessionStarted() then 11 | TriggerEvent('qb-multicharacter:client:chooseChar') 12 | return 13 | end 14 | end 15 | end) 16 | 17 | -- Functions 18 | 19 | local function skyCam(bool) 20 | TriggerEvent('qb-weathersync:client:DisableSync') 21 | if bool then 22 | DoScreenFadeIn(1000) 23 | SetTimecycleModifier('hud_def_blur') 24 | SetTimecycleModifierStrength(1.0) 25 | FreezeEntityPosition(PlayerPedId(), false) 26 | cam = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", Config.CamCoords.x, Config.CamCoords.y, Config.CamCoords.z, 0.0 ,0.0, Config.CamCoords.w, 60.00, false, 0) 27 | SetCamActive(cam, true) 28 | RenderScriptCams(true, false, 1, true, true) 29 | else 30 | SetTimecycleModifier('default') 31 | SetCamActive(cam, false) 32 | DestroyCam(cam, true) 33 | RenderScriptCams(false, false, 1, true, true) 34 | FreezeEntityPosition(PlayerPedId(), false) 35 | end 36 | end 37 | local function openCharMenu(bool) 38 | QBCore.Functions.TriggerCallback("qb-multicharacter:server:GetNumberOfCharacters", function(result) 39 | local translations = {} 40 | for k in pairs(Lang.fallback and Lang.fallback.phrases or Lang.phrases) do 41 | if k:sub(0, ('ui.'):len()) then 42 | translations[k:sub(('ui.'):len() + 1)] = Lang:t(k) 43 | end 44 | end 45 | SetNuiFocus(bool, bool) 46 | SendNUIMessage({ 47 | action = "ui", 48 | customNationality = Config.customNationality, 49 | toggle = bool, 50 | nChar = result, 51 | enableDeleteButton = Config.EnableDeleteButton, 52 | translations = translations 53 | }) 54 | skyCam(bool) 55 | if not loadScreenCheckState then 56 | ShutdownLoadingScreenNui() 57 | loadScreenCheckState = true 58 | end 59 | end) 60 | end 61 | 62 | -- Events 63 | 64 | RegisterNetEvent('qb-multicharacter:client:closeNUIdefault', function() -- This event is only for no starting apartments 65 | DeleteEntity(charPed) 66 | SetNuiFocus(false, false) 67 | DoScreenFadeOut(500) 68 | Wait(2000) 69 | SetEntityCoords(PlayerPedId(), Config.DefaultSpawn.x, Config.DefaultSpawn.y, Config.DefaultSpawn.z) 70 | TriggerServerEvent('QBCore:Server:OnPlayerLoaded') 71 | TriggerEvent('QBCore:Client:OnPlayerLoaded') 72 | TriggerServerEvent('qb-houses:server:SetInsideMeta', 0, false) 73 | TriggerServerEvent('qb-apartments:server:SetInsideMeta', 0, 0, false) 74 | Wait(500) 75 | openCharMenu() 76 | SetEntityVisible(PlayerPedId(), true) 77 | Wait(500) 78 | DoScreenFadeIn(250) 79 | TriggerEvent('qb-weathersync:client:EnableSync') 80 | TriggerEvent('qb-clothes:client:CreateFirstCharacter') 81 | end) 82 | 83 | RegisterNetEvent('qb-multicharacter:client:closeNUI', function() 84 | DeleteEntity(charPed) 85 | SetNuiFocus(false, false) 86 | end) 87 | 88 | RegisterNetEvent('qb-multicharacter:client:chooseChar', function() 89 | SetNuiFocus(false, false) 90 | DoScreenFadeOut(10) 91 | Wait(1000) 92 | local interior = GetInteriorAtCoords(Config.Interior.x, Config.Interior.y, Config.Interior.z - 18.9) 93 | LoadInterior(interior) 94 | while not IsInteriorReady(interior) do 95 | Wait(1000) 96 | end 97 | FreezeEntityPosition(PlayerPedId(), true) 98 | SetEntityCoords(PlayerPedId(), Config.HiddenCoords.x, Config.HiddenCoords.y, Config.HiddenCoords.z) 99 | Wait(1500) 100 | ShutdownLoadingScreen() 101 | ShutdownLoadingScreenNui() 102 | openCharMenu(true) 103 | end) 104 | 105 | -- NUI Callbacks 106 | 107 | RegisterNUICallback('closeUI', function(_, cb) 108 | openCharMenu(false) 109 | cb("ok") 110 | end) 111 | 112 | RegisterNUICallback('disconnectButton', function(_, cb) 113 | SetEntityAsMissionEntity(charPed, true, true) 114 | DeleteEntity(charPed) 115 | TriggerServerEvent('qb-multicharacter:server:disconnect') 116 | cb("ok") 117 | end) 118 | 119 | RegisterNUICallback('selectCharacter', function(data, cb) 120 | local cData = data.cData 121 | DoScreenFadeOut(10) 122 | TriggerServerEvent('qb-multicharacter:server:loadUserData', cData) 123 | openCharMenu(false) 124 | SetEntityAsMissionEntity(charPed, true, true) 125 | DeleteEntity(charPed) 126 | cb("ok") 127 | end) 128 | 129 | RegisterNUICallback('cDataPed', function(nData, cb) 130 | local cData = nData.cData 131 | SetEntityAsMissionEntity(charPed, true, true) 132 | DeleteEntity(charPed) 133 | if cData ~= nil then 134 | QBCore.Functions.TriggerCallback('qb-multicharacter:server:getSkin', function(model, data) 135 | model = model ~= nil and tonumber(model) or false 136 | if model ~= nil then 137 | CreateThread(function() 138 | RequestModel(model) 139 | while not HasModelLoaded(model) do 140 | Wait(0) 141 | end 142 | charPed = CreatePed(2, model, Config.PedCoords.x, Config.PedCoords.y, Config.PedCoords.z - 0.98, Config.PedCoords.w, false, true) 143 | local RandomAnimins = { 144 | "WORLD_HUMAN_HANG_OUT_STREET", 145 | "WORLD_HUMAN_STAND_IMPATIENT", 146 | "WORLD_HUMAN_STAND_MOBILE", 147 | "WORLD_HUMAN_SMOKING_POT", 148 | "WORLD_HUMAN_LEANING", 149 | "WORLD_HUMAN_DRUG_DEALER_HARD" 150 | } 151 | local PlayAnimin = RandomAnimins[math.random(#RandomAnimins)] 152 | SetPedCanPlayAmbientAnims(charPed, true) 153 | TaskStartScenarioInPlace(charPed, PlayAnimin, 0, true) 154 | SetPedComponentVariation(charPed, 0, 0, 0, 2) 155 | FreezeEntityPosition(charPed, false) 156 | SetEntityInvincible(charPed, true) 157 | PlaceObjectOnGroundProperly(charPed) 158 | SetBlockingOfNonTemporaryEvents(charPed, true) 159 | data = json.decode(data) 160 | TriggerEvent('qb-clothing:client:loadPlayerClothing', data, charPed) 161 | end) 162 | else 163 | CreateThread(function() 164 | charPed = CreatePed(2, model, Config.PedCoords.x, Config.PedCoords.y, Config.PedCoords.z - 0.98, Config.PedCoords.w, false, true) 165 | SetPedComponentVariation(charPed, 0, 0, 0, 2) 166 | FreezeEntityPosition(charPed, false) 167 | SetEntityInvincible(charPed, true) 168 | PlaceObjectOnGroundProperly(charPed) 169 | SetBlockingOfNonTemporaryEvents(charPed, true) 170 | end) 171 | end 172 | cb("ok") 173 | end, cData.citizenid) 174 | else 175 | CreateThread(function() 176 | charPed = CreatePed(2, model, Config.PedCoords.x, Config.PedCoords.y, Config.PedCoords.z - 0.98, Config.PedCoords.w, false, true) 177 | SetPedComponentVariation(charPed, 0, 0, 0, 2) 178 | FreezeEntityPosition(charPed, false) 179 | SetEntityInvincible(charPed, true) 180 | PlaceObjectOnGroundProperly(charPed) 181 | SetBlockingOfNonTemporaryEvents(charPed, true) 182 | end) 183 | cb("ok") 184 | end 185 | end) 186 | 187 | RegisterNUICallback('setupCharacters', function(_, cb) 188 | QBCore.Functions.TriggerCallback("qb-multicharacter:server:setupCharacters", function(result) 189 | SendNUIMessage({ 190 | action = "setupCharacters", 191 | characters = result 192 | }) 193 | cb("ok") 194 | end) 195 | end) 196 | 197 | RegisterNUICallback('removeBlur', function(_, cb) 198 | SetTimecycleModifier('default') 199 | cb("ok") 200 | end) 201 | 202 | RegisterNUICallback('createNewCharacter', function(data, cb) 203 | local cData = data 204 | DoScreenFadeOut(150) 205 | if cData.gender == "Male" then 206 | cData.gender = 0 207 | elseif cData.gender == "Female" then 208 | cData.gender = 1 209 | end 210 | TriggerServerEvent('qb-multicharacter:server:createCharacter', cData) 211 | Wait(500) 212 | cb("ok") 213 | end) 214 | 215 | RegisterNUICallback('removeCharacter', function(data, cb) 216 | TriggerServerEvent('qb-multicharacter:server:deleteCharacter', data.citizenid) 217 | TriggerEvent('qb-multicharacter:client:chooseChar') 218 | cb("ok") 219 | end) -------------------------------------------------------------------------------- /config.lua: -------------------------------------------------------------------------------- 1 | Config = {} 2 | Config.Interior = vector3(-1004.36, -477.9, 51.63) -- Interior to load where characters are previewed 3 | Config.DefaultSpawn = vector3(-1004.36, -477.9, 51.63) -- Default spawn coords if you have start apartments disabled 4 | Config.PedCoords = vector4(-1008.49, -474.51, 50.03, 208.64) -- Create preview ped at these coordinates 5 | Config.HiddenCoords = vector4(-1001.11, -478.06, 50.03, 24.55) -- Hides your actual ped while you are in selection 6 | Config.CamCoords = vector4(-1005.53, -480.73, 50.52, 27.44) -- Camera coordinates for character preview screen 7 | Config.EnableDeleteButton = true -- Define if the player can delete the character or not 8 | 9 | Config.DefaultNumberOfCharacters = 2 -- Define maximum amount of default characters, Max 4 //ST4LTH 10 | Config.PlayersNumberOfCharacters = { -- Define maximum amount of player characters by rockstar license (you can find this license in your server's database in the player table) 11 | { license = "license:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", numberOfChars = 2 }, 12 | } 13 | 14 | Config.cinematiclocation = { 15 | [1] = vector4(-1007.53, -480.73, 50.22, 15.44), --start 16 | [2] = vector4(-1007.53, -479.14, 50.52, 15.44), --start left to right 17 | [3] = vector4(-1004.53, -477.33, 50.52, 75.44), --stop right 18 | [4] = vector4(-1006.53, -473.53, 50.52, 135.00), --move other way and right to left 19 | [5] = vector4(-1011.03, -476.33, 50.52, 275.00), --stop left 20 | } -------------------------------------------------------------------------------- /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'cerulean' 2 | game 'gta5' 3 | 4 | description 'QB-Multicharacter' 5 | version '1.0.0' 6 | 7 | shared_scripts { 8 | '@qb-core/shared/locale.lua', 9 | 'locales/en.lua', 10 | 'locales/*.lua', 11 | 'config.lua' 12 | } 13 | client_script 'client/main.lua' 14 | server_scripts { 15 | '@oxmysql/lib/MySQL.lua', 16 | '@qb-apartments/config.lua', 17 | 'server/main.lua' 18 | } 19 | 20 | ui_page 'html/index.html' 21 | 22 | files { 23 | "html/js/*", 24 | 'html/assets/*.png', 25 | 'html/assets/*.jpg', 26 | 'html/assets/*.gif', 27 | 'html/index.html', 28 | 'html/css/*', 29 | } 30 | 31 | dependencies { 32 | 'qb-core', 33 | 'qb-spawn' 34 | } 35 | 36 | lua54 'yes' 37 | -------------------------------------------------------------------------------- /html/assets/car.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brave-developments/qb-multicharacter/701c72f746a9f6cbfd8809a4b611dab2d230abd6/html/assets/car.jpg -------------------------------------------------------------------------------- /html/assets/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brave-developments/qb-multicharacter/701c72f746a9f6cbfd8809a4b611dab2d230abd6/html/assets/image2.png -------------------------------------------------------------------------------- /html/assets/multi.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Brave-developments/qb-multicharacter/701c72f746a9f6cbfd8809a4b611dab2d230abd6/html/assets/multi.gif -------------------------------------------------------------------------------- /html/css/reset.css: -------------------------------------------------------------------------------- 1 | html, body, div, span, applet, object, iframe, 2 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 3 | a, abbr, acronym, address, big, cite, code, 4 | del, dfn, em, img, ins, kbd, q, s, samp, 5 | small, strike, strong, sub, sup, tt, var, 6 | b, u, i, center, 7 | dl, dt, dd, ol, ul, li, 8 | fieldset, form, label, legend, 9 | table, caption, tbody, tfoot, thead, tr, th, td, 10 | article, aside, canvas, details, embed, 11 | figure, figcaption, footer, header, hgroup, 12 | menu, nav, output, ruby, section, summary, 13 | time, mark, audio, video { 14 | margin: 0; 15 | padding: 0; 16 | border: 0; 17 | font-size: 100%; 18 | font: inherit; 19 | vertical-align: baseline; 20 | font-family: 'Inter', sans-serif; 21 | overflow: hidden !important; 22 | } 23 | /* HTML5 display-role reset for older browsers */ 24 | article, aside, details, figcaption, figure, 25 | footer, header, hgroup, menu, nav, section { 26 | display: block; 27 | } 28 | body { 29 | line-height: 1; 30 | } 31 | ol, ul { 32 | list-style: none; 33 | } 34 | blockquote, q { 35 | quotes: none; 36 | } 37 | blockquote:before, blockquote:after, 38 | q:before, q:after { 39 | content: ''; 40 | content: none; 41 | } 42 | table { 43 | border-collapse: collapse; 44 | border-spacing: 0; 45 | } 46 | -------------------------------------------------------------------------------- /html/css/style.css: -------------------------------------------------------------------------------- 1 | /* @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@100&display=swap'); 2 | @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300&display=swap'); */ 3 | .container { 4 | display: none; 5 | } 6 | 7 | body { 8 | user-select: none; /* supported by Chrome and Opera */ 9 | -webkit-user-select: none; /* Safari */ 10 | -khtml-user-select: none; /* Konqueror HTML */ 11 | -moz-user-select: none; /* Firefox */ 12 | -ms-user-select: none; /* Internet Explorer/Edge */ 13 | } 14 | :focus { 15 | outline: 0; 16 | border-color: #09b18a00; 17 | -webkit-box-shadow: 0 0 0 0px #09b18a00; 18 | box-shadow: 0 0 0 0px #09b18a00; 19 | } 20 | 21 | .mydict2{ 22 | display: -webkit-box; 23 | display: -ms-flexbox; 24 | display: flex; 25 | -ms-flex-wrap: wrap; 26 | flex-wrap: wrap; 27 | margin-top: 0.5rem; 28 | position: absolute; 29 | border: none; 30 | border: 0.1vh solid #cecece4b; 31 | background-color: #cecece2c; 32 | /* box-shadow:1px 1px 10px #cecece8a; */ 33 | outline: none; 34 | width: 94%; 35 | top: -13.9vh; 36 | left: 0vh; 37 | color: rgb(255, 255, 255); 38 | max-width: 97.5%; 39 | border-radius: 2px; 40 | font-size: 14px; 41 | padding-left: 18px; 42 | padding-bottom: 11px; 43 | padding-top: 11px; 44 | font-family: Inter, sans-serif; 45 | text-align: left; 46 | -webkit-appearance: none; 47 | -moz-appearance: none; 48 | text-indent: 1px; 49 | text-overflow: ''; 50 | transition: all 0.2s ease-in-out; 51 | cursor: pointer; 52 | 53 | 54 | } 55 | 56 | 57 | .mydict{ 58 | display: -webkit-box; 59 | display: -ms-flexbox; 60 | display: flex; 61 | -ms-flex-wrap: wrap; 62 | flex-wrap: wrap; 63 | margin-top: 0.5rem; 64 | -webkit-box-pack: center; 65 | -ms-flex-pack: center; 66 | 67 | position: absolute; 68 | border: none; 69 | border: 0.1vh solid #cecece4b; 70 | background-color: #cecece2c; 71 | /* box-shadow:1px 1px 10px #cecece8a; */ 72 | outline: none; 73 | width: 96.5%; 74 | height: 5.5vh; 75 | top: -9.7vh; 76 | left: 0vh; 77 | color: rgb(255, 255, 255); 78 | max-width: 120%; 79 | padding: 4px; 80 | border-radius: 2px; 81 | font-size: 15px; 82 | font-family: 'Gilroy'; 83 | text-align-last: center; 84 | -webkit-appearance: none; 85 | -moz-appearance: none; 86 | text-indent: 1px; 87 | text-overflow: ''; 88 | transition: all 0.2s ease-in-out; 89 | cursor: pointer; 90 | text-align: center; 91 | justify-content: center; 92 | 93 | text-align-last: center 94 | } 95 | 96 | .mydict input[type="radio"] { 97 | clip: rect(0 0 0 0); 98 | -webkit-clip-path: inset(100%); 99 | clip-path: inset(100%); 100 | height: 1px; 101 | overflow: hidden; 102 | text-align: center; 103 | justify-content: center; 104 | position: absolute; 105 | white-space: nowrap; 106 | width: 1px; 107 | } 108 | 109 | .mydict input[type="radio"]:checked + span { 110 | background: radial-gradient(rgba(0, 248, 185, 0.55) 0%, rgba(0, 248, 185, 0.22) 100%); 111 | text-align: center; 112 | justify-content: center; 113 | z-index: 1; 114 | } 115 | .mydict label { 116 | width: 48%; 117 | text-align: center; 118 | justify-content: center; 119 | 120 | } 121 | .mydict label span p { 122 | text-align: center; 123 | justify-content: center; 124 | float: left; 125 | width: 100%; 126 | padding-top: 8.7%; 127 | 128 | } 129 | .mydict label span { 130 | height: 75%; 131 | /* padding-top: 10%; */ 132 | display: flex; 133 | left: 3px; 134 | cursor: pointer; 135 | background-color: #cecece4b; 136 | border: 0.1vh solid #cecece2c; 137 | width: 94%; 138 | top: 7px; 139 | position: relative; 140 | margin-left: .0925em; 141 | letter-spacing: .05em; 142 | color: #fff; 143 | text-align: center; 144 | justify-content: center; 145 | -webkit-transition: #cecece4b .5s ease; 146 | transition: #cecece4b .5s ease; 147 | } 148 | .mydict input[type="radio"]:checked+ span:hover{ 149 | background-color: #cecece4b; 150 | -webkit-box-shadow: 0 0 0 0.0625em #09b18ad5; 151 | box-shadow: 0 0 0 0.0625em #09b18ad5; 152 | transition: all 0.5s ease-in-out; 153 | } 154 | .mydict label span:hover{ 155 | background-color: #09b18ad5; 156 | transition: all 0.5s ease-in-out; 157 | } 158 | 159 | .mydict label:first-child span { 160 | border-radius: 2px; 161 | } 162 | 163 | .mydict label:last-child span { 164 | border-radius: 2px; 165 | } 166 | 167 | .characters::-webkit-scrollbar { 168 | display: none; 169 | } 170 | 171 | .main-screen { 172 | position: absolute; 173 | height: 100vh; 174 | width: 100vw; 175 | left: 0; 176 | z-index: 100; 177 | } 178 | 179 | .characters-block-header>p { 180 | text-align: center; 181 | color: #ededed; 182 | line-height: 24px; 183 | font-family: 'Inter', sans-serif; 184 | } 185 | 186 | .characters-list { 187 | display: none; 188 | position: absolute; 189 | width: 80%; 190 | /* left: 8%; */ 191 | top: 36%; 192 | background-color: #20273100; 193 | padding: 10px; 194 | margin-left: 10%; 195 | } 196 | 197 | .bar { 198 | display: none; 199 | position: absolute; 200 | width: 86%; 201 | height: 2.1px; 202 | /* left: 8%; */ 203 | top: 16%; 204 | bottom: 50%; 205 | background: linear-gradient(90deg, rgba(255,255,255,0.014443277310924318) 0%, rgba(140,140,140,1) 33%, rgba(181,181,181,1) 66%, rgba(255,255,255,0) 100%); 206 | /* padding: 10px; */ 207 | margin-left: 7%; 208 | } 209 | .bar2 { 210 | display: none; 211 | position: absolute; 212 | width: 10%; 213 | height: 4px; 214 | /* left: 8%; */ 215 | top: 17%; 216 | bottom: 50%; 217 | border-radius: 0px; 218 | background: #1df0bb; 219 | box-shadow: 0px 5px 30px #1df0bb73, 0px -5px 30px #1df0bb; 220 | /* padding: 10px; */ 221 | margin-left: 45%; 222 | } 223 | 224 | .characters-icon { 225 | display: none; 226 | position: absolute; 227 | width: 10%; 228 | height: 10%; 229 | top: 16%; 230 | line-height: 90px; 231 | font-size: 5vh; 232 | text-align: center; 233 | margin-left: 45%; 234 | } 235 | 236 | .characters-text { 237 | display: none; 238 | position: absolute; 239 | width: 20%; 240 | height: 10%; 241 | top: 16%; 242 | font-family: 'Gilroy'; 243 | line-height: 90px; 244 | font-size: 2.0vh; 245 | text-align: center; 246 | font-weight: 500; 247 | margin-left: 40%; 248 | color: #00F8B9; 249 | } 250 | 251 | .characters-text2 { 252 | display: none; 253 | position: absolute; 254 | width: 20%; 255 | height: 10%; 256 | font-family: 'Gilroy'; 257 | top: 16%; 258 | line-height: 90px; 259 | font-size: 1.3vh; 260 | text-align: center; 261 | font-weight: 600; 262 | margin-left: 40%; 263 | color: rgb(125, 125, 125); 264 | } 265 | 266 | 267 | .character-list-header { 268 | text-transform: uppercase; 269 | position: relative; 270 | top: -10vh; 271 | width: 100%; 272 | height: 10%; 273 | right: 0; 274 | } 275 | 276 | .character-list-header>p { 277 | text-align: center; 278 | font-size: 2vh; 279 | margin-top: 3.1vh; 280 | font-family: 'Inter', sans-serif; 281 | letter-spacing: .1vh; 282 | font-weight: 900; 283 | color: #ededed; 284 | } 285 | 286 | .characters { 287 | display: flex; 288 | width: 100%; 289 | height: 65%; 290 | overflow: scroll !important; 291 | margin-right: spx; 292 | align-items: center; 293 | justify-content: center; 294 | } 295 | 296 | .character { 297 | position: relative; 298 | width: 26%; 299 | height: 122px; 300 | transition: .1s linear; 301 | cursor: pointer; 302 | margin-right: 12px; 303 | font-family: gilroy400; 304 | font-weight: normal; 305 | /* border: calc(0.092592592vh * 1) solid rgba(255, 255, 255, 0.15); */ 306 | color: #FFFFFF; 307 | /* background: radial-gradient(83.87% 1043.26% at 50% 50%, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.08) 100%); */ 308 | } 309 | 310 | 311 | .characterr { 312 | position: relative; 313 | width: 110%; 314 | height: 92px; 315 | /* margin-top: 15px; */ 316 | font-family: 'Inter', sans-serif; 317 | border: 0.2px solid #a3a3a3; 318 | transition: .1s linear; 319 | /* border-radius: .3vh; */ 320 | cursor: pointer; 321 | margin-right: 12px; 322 | background: #888c92; 323 | } 324 | 325 | /* .character:hover { 326 | background-color: #cecece65; 327 | width: 110%; 328 | } */ 329 | 330 | .character>span { 331 | color: #ededed; 332 | letter-spacing: .1vh; 333 | font-family: 'Inter', sans-serif; 334 | } 335 | 336 | .user { 337 | color: white; 338 | /* margin: auto 0%; */ 339 | font-size: 40px; 340 | width: 7.4vh; 341 | height: 7.4vh; 342 | position: relative; 343 | margin-left: 1px; 344 | font-weight: bold; 345 | margin-top: 1px; 346 | border-radius: calc(0.092592592vh * 2) !important; 347 | background: rgba(88, 88, 88, 0.35); 348 | } 349 | .user img{ 350 | object-fit: cover; 351 | /* width: 300px; */ 352 | 353 | width: 100%; 354 | height: 100%; 355 | } 356 | .user2 { 357 | color: white; 358 | font-size: 40px; 359 | width: 11.4vh; 360 | height: 7.4vh; 361 | position: relative; 362 | margin-left: 4px; 363 | font-weight: bold; 364 | margin-top: 1px; 365 | /* background: rgba(88, 88, 88, 0.35); */ 366 | border-radius: calc(0.185185vh) !important; 367 | } 368 | .user2 img{ 369 | object-fit: cover; 370 | /* width: 300px; */ 371 | 372 | transform: scaleY(-1); 373 | transition: transform 1s ease 1.1s; 374 | animation: 3s ease-in 3s; 375 | width: 100%; 376 | height: 100%; 377 | 378 | } 379 | .user3 { 380 | color: white; 381 | font-size: 40px; 382 | width: 11.4vh; 383 | height: 7.4vh; 384 | position: relative; 385 | margin-left: 4px; 386 | font-weight: bold; 387 | margin-top: 1px; 388 | /* background: rgba(88, 88, 88, 0.35); */ 389 | border-radius: calc(0.185185vh) !important; 390 | } 391 | .user3 img{ 392 | object-fit: cover; 393 | /* width: 300px; */ 394 | 395 | width: 100%; 396 | height: 100%; 397 | 398 | -webkit-mask-image: linear-gradient(to left, rgba(0,0,0,1), rgba(0,0,0,0)), linear-gradient(to right, rgba(0,0,0,0), rgba(0,0,0,0)); 399 | -webkit-mask-size: 100% 50%; 400 | } 401 | 402 | #cid { 403 | color: #5a3c3c; 404 | position: relative; 405 | float: right; 406 | font-size: 0vh; 407 | right: 35px; 408 | } 409 | .char-selected { 410 | transition: 250ms; 411 | } 412 | 413 | .disabled { 414 | background-color: rgba(0, 0, 0, 0.691); 415 | } 416 | 417 | #slot-name { 418 | position: relative; 419 | color: rgba(255, 255, 255, 0.925); 420 | font-size: 13px; 421 | line-height: 87px; 422 | /* top: -84px; */ 423 | /* left: 101px; */ 424 | font-family: Gilroy; 425 | font-weight: 410; 426 | width: 44%; 427 | text-align: start; 428 | margin-left: 15px; 429 | } 430 | 431 | .btns { 432 | display: flex; 433 | /* width: 34.9vh; */ 434 | height: 50px; 435 | margin-left: -1px; 436 | /* bottom: 83.86%; */ 437 | position: relative; 438 | background: #20273100; 439 | padding: 0px 0px; 440 | z-index: 1; 441 | margin-top: 2px; 442 | /* right: 124.5vh; */ 443 | border-radius: calc(0.092592592vh * 3); 444 | } 445 | .character-div { 446 | height: 66.9%; 447 | border: calc(0.092592592vh * 1) solid rgba(255, 255, 255, 0.15); 448 | border-radius: calc(0.092592592vh * 3); 449 | background: radial-gradient(83.87% 1043.26% at 50% 50%, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.08) 100%); 450 | display: flex; 451 | } 452 | .character-btn { 453 | position: static; 454 | width: 9.9vh; 455 | height: 2.5vh; 456 | top: 18%; 457 | transition: 0.2s; 458 | float: left; 459 | margin-top: 1px; 460 | /* margin-right: 10px; */ 461 | cursor: pointer; 462 | overflow: visible !important; 463 | margin-bottom: -3px; 464 | margin-left: 1px; 465 | margin-right: 0px; 466 | } 467 | 468 | .character-btn>p { 469 | color: #ffffff; 470 | /* letter-spacing: .1vh; */ 471 | text-align: center; 472 | font-size: 1.2vh; 473 | line-height: 2.5vh; 474 | font-family: 'Gilroy'; 475 | border-radius: calc(0.092592592vh * 3); 476 | font-weight: 500; 477 | } 478 | 479 | 480 | #play { 481 | display: none; 482 | background: radial-gradient(rgba(0, 248, 185, 0.55) 0%, rgba(0, 248, 185, 0.22) 100%); 483 | border: calc(0.092592592vh * 1.4) solid rgba(255, 255, 255, 0.15); 484 | border-radius: calc(0.092592592vh * 0); 485 | width: 100%; 486 | margin-right: 0px; 487 | padding-top: -2px; 488 | padding-bottom: 0px; 489 | transition: all 0.2s ease; 490 | } 491 | 492 | #play:hover { 493 | background-color: #09b18ad5; 494 | } 495 | 496 | #info { 497 | display: block; 498 | background-color: #cccccc; 499 | border-radius: .3vh; 500 | transition: all 0.2s ease; 501 | } 502 | 503 | #info:hover { 504 | background-color: #bdbdbd; 505 | } 506 | #select { 507 | /* display: none; */ 508 | background: radial-gradient(rgba(0, 248, 185, 0.55) 0%, rgba(0, 248, 185, 0.22) 100%); 509 | border-radius: calc(0.092592592vh * 0); 510 | border: calc(0.092592592vh * 1.4) solid rgba(255, 255, 255, 0.15); 511 | /* padding-left: 38px; 512 | padding-right: 38px; */ 513 | padding-top: 0px; 514 | padding-bottom: 0px; 515 | transition: all 0.2s ease; 516 | width: 100%; 517 | } 518 | 519 | #select:hover { 520 | background-color: #09b18ad5; 521 | } 522 | #delete { 523 | display: none; 524 | background: radial-gradient(117.32% 117.32% at 50% -13.97%, rgba(248, 105, 105, 0.55) 0%, rgba(248, 105, 105, 0.43) 100%); 525 | border-radius: calc(0.092592592vh * 0); 526 | border: calc(0.092592592vh * 1.4) solid rgba(255, 255, 255, 0.15); 527 | width: 100%; 528 | padding-top: 0px; 529 | padding-bottom: 0px; 530 | transition: all 0.2s ease; 531 | } 532 | 533 | #delete:hover { 534 | background-color: #a54850d0; 535 | } 536 | 537 | .character-info { 538 | display: none; 539 | position: absolute; 540 | width: 20%; 541 | height: 50%; 542 | /* right: 4%; */ 543 | top: 10%; 544 | padding: 30px; 545 | background-color: #202731; 546 | overflow: visible !important; 547 | left: 10.5%; 548 | } 549 | 550 | #char-info-icon { 551 | position: relative; 552 | font-size: 1.5vh; 553 | color: #ededed; 554 | right: 20px; 555 | overflow: visible !important; 556 | } 557 | 558 | #char-info-titel { 559 | text-transform: uppercase; 560 | position: absolute; 561 | font-size: 2vh; 562 | color: #ededed; 563 | left: -9.8vh; 564 | letter-spacing: .1vh; 565 | font-weight: 900; 566 | overflow: visible !important; 567 | } 568 | 569 | #no-char { 570 | position: absolute; 571 | color: #ededed; 572 | font-size: 16px; 573 | top: 30%; 574 | text-align: center; 575 | } 576 | 577 | .char-info-titel { 578 | position: relative; 579 | left: 28%; 580 | top: 3%; 581 | overflow: visible !important; 582 | } 583 | 584 | .character-info-valid { 585 | position: relative; 586 | top: 15%; 587 | overflow: visible !important; 588 | } 589 | 590 | .character-info-box { 591 | position: relative; 592 | color: #ededed; 593 | font-size: 1.5vh; 594 | width: 100%; 595 | height: 2.9vh; 596 | font-weight: 900; 597 | text-transform: uppercase; 598 | margin-bottom: 12px; 599 | } 600 | 601 | .char-info-js { 602 | position: absolute; 603 | left: 50%; 604 | } 605 | 606 | #info-label { 607 | margin-left: 10px; 608 | } 609 | 610 | .character-delete { 611 | display: none; 612 | position: absolute; 613 | width: 23vh; 614 | height: 1.5vh; 615 | top: 73vh; 616 | border: calc(0.092592592vh * 1) solid rgba(255, 255, 255, 0.15); 617 | border-radius: calc(0.092592592vh * 3); 618 | background: radial-gradient(83.87% 1043.26% at 50% 50%, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.08) 100%); 619 | right: 9%; 620 | /* margin-left: auto; */ 621 | /* margin-right: auto; */ 622 | /* background-color: #202731; */ 623 | padding: 18px; 624 | font-family: 'Inter', sans-serif; 625 | color: #ededed; 626 | font-family: 'Inter', sans-serif; 627 | overflow: visible !important; 628 | /* border-radius: 5px; */ 629 | } 630 | 631 | .characters-delete-block-header { 632 | position: absolute; 633 | width: 100%; 634 | height: 11%; 635 | color: #ededed; 636 | text-align: left; 637 | font-size: 2vh; 638 | line-height: 29px; 639 | font-family: 'Inter', sans-serif; 640 | font-weight: 900; 641 | text-transform: uppercase; 642 | overflow: visible !important; 643 | } 644 | 645 | .characters-delete-block-header>p { 646 | font-family: 'Inter', sans-serif; 647 | overflow: visible !important; 648 | } 649 | 650 | .character-delete>p { 651 | padding-top: 50px; 652 | font-size: 1.3vh; 653 | overflow: visible !important; 654 | } 655 | 656 | .error { 657 | 658 | display: none; 659 | position: relative; 660 | width: 34vh; 661 | height: 10vh; 662 | top: -44.7vh; 663 | left: 0vh; 664 | margin-left: auto; 665 | margin-right: auto; 666 | border-radius: calc(0.092592592vh * 3); 667 | background: radial-gradient(83.87% 1043.26% at 50% 50%, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.08) 100%); 668 | /* background-color: rgba(104, 104, 104, 0.808); */ 669 | /* border-radius: 0.8vh; */ 670 | padding: 30px; 671 | border: calc(0.092592592vh * 1) solid rgba(255, 255, 255, 0.15); 672 | /* box-shadow: 0 4px 8px 0 rgb(0 0 0 / 20%), 0 6px 20px 0 rgb(0 0 0 / 19%); */ 673 | color: #ededed; 674 | font-family: "Gilroy"; 675 | font-weight: 500; 676 | overflow: visible !important; 677 | } 678 | 679 | .error-title{ 680 | position: relative; 681 | width: 100%; 682 | height: 11%; 683 | margin-bottom: 16px; 684 | color: #ededed; 685 | text-align: left; 686 | font-size: 18px; 687 | line-height: 29px; 688 | vertical-align: middle; 689 | font-family: "Gilroy"; 690 | font-weight: 500; 691 | overflow: visible !important; 692 | } 693 | .error-title > .material-symbols-outlined{ 694 | line-height: 27px; 695 | vertical-align: bottom; 696 | margin-top: -12px; 697 | margin-bottom: auto; 698 | font-weight: 400; 699 | font-family: 'Gilroy'; 700 | /* padding: 8px; */ 701 | font-size: 13px; 702 | margin-right: 11px; 703 | color: #ffffff; 704 | /* background: radial-gradient(117.32% 117.32% at 50% -13.97%, rgb(185, 49, 49) 0%, rgb(88, 29, 29) 100%); */ 705 | background: radial-gradient(rgba(0, 248, 185, 0.55) 0%, rgba(0, 248, 185, 0.22) 100%); 706 | border-radius: calc(0.092592592vh * 3); 707 | width: 32.4vh; 708 | position: absolute; 709 | padding-left: 1.5vh; 710 | } 711 | 712 | .error-msg { 713 | font-family: 'Inter', sans-serif; 714 | overflow: visible !important; 715 | padding: 8px; 716 | } 717 | 718 | #yeet { 719 | overflow: visible !important; 720 | } 721 | 722 | .character-acceptdel-btn { 723 | position: absolute; 724 | width: 47%; 725 | height: 3.6vh; 726 | bottom: 0; 727 | left: 2%; 728 | margin-bottom: 7px; 729 | /* background-color: #6CAC59; */ 730 | background: radial-gradient(rgba(0, 248, 185, 0.55) 0%, rgba(0, 248, 185, 0.22) 100%); 731 | border-radius: 2px; 732 | transition: 0.2s; 733 | overflow: visible !important; 734 | cursor: pointer; 735 | } 736 | 737 | .character-canceldel-btn { 738 | position: absolute; 739 | width: 47%; 740 | height: 3.6vh; 741 | bottom: 0; 742 | right: 2%; 743 | margin-bottom: 7px; 744 | background: radial-gradient(117.32% 117.32% at 50% -13.97%, rgba(248, 105, 105, 0.55) 0%, rgba(248, 105, 105, 0.43) 100%); 745 | /* background-color: #F5A15B; */ 746 | border-radius: 2px; 747 | transition: 0.2s; 748 | overflow: visible !important; 749 | cursor: pointer; 750 | } 751 | 752 | .close-err-btn { 753 | font-weight: 550; 754 | /* text-transform: uppercase; */ 755 | width: 3.4vh; 756 | height: auto; 757 | font-weight: 400; 758 | font-family: 'Gilroy'; 759 | padding: 8px; 760 | font-size: 13px; 761 | padding-left: 11px; 762 | margin-top: 3.5vh; 763 | /* background: radial-gradient(117.32% 117.32% at 50% -13.97%, rgb(185, 49, 49) 0%, rgb(88, 29, 29) 100%); */ 764 | background: radial-gradient(117.32% 117.32% at 50% -13.97%, rgba(248, 105, 105, 0.55) 0%, rgba(248, 105, 105, 0.43) 100%); 765 | border-radius: 4px; 766 | transition: 0.2s; 767 | overflow: visible !important; 768 | cursor: pointer; 769 | } 770 | 771 | .character-acceptdel-btn>p { 772 | color: #ffffff; 773 | text-align: center; 774 | padding-top: 1.2vh; 775 | font-family: 'Gilroy'; 776 | font-size: 14px; 777 | /* font-family: 'Inter', sans-serif; */ 778 | font-weight: 400; 779 | /* text-transform: uppercase; */ 780 | } 781 | 782 | .character-canceldel-btn>p { 783 | color: #ffffff; 784 | text-align: center; 785 | padding-top: 1.2vh; 786 | font-family: 'Gilroy'; 787 | font-size: 14px; 788 | /* font-family: 'Inter', sans-serif; */ 789 | font-weight: 400; 790 | /* text-transform: uppercase; */ 791 | 792 | } 793 | 794 | .character-register { 795 | display: none; 796 | position: relative; 797 | width: 25%; 798 | height: 42%; 799 | top: 125%; 800 | /* margin-left: auto; 801 | margin-right: auto; */ 802 | left: 48px; 803 | background-color: #1b1e2300; 804 | padding: 30px; 805 | font-family: 'Inter', sans-serif; 806 | box-shadow: 0 0px 1px 0 #7b7b7b00; 807 | } 808 | 809 | #close-reg { 810 | position: relative; 811 | bottom: 2.45vh; 812 | font-size: 1.5vh; 813 | left: 1.6vh; 814 | cursor: pointer; 815 | /* background-color: #7c3a3f; */ 816 | background: radial-gradient(117.32% 117.32% at 50% -13.97%, rgba(248, 105, 105, 0.55) 0%, rgba(248, 105, 105, 0.43) 100%); 817 | color: #fdfdfd; 818 | width: 34%; 819 | height: 3vh; 820 | border-radius: 0px; 821 | } 822 | 823 | /* #close-reg:hover { 824 | background-color: #FFBC5E; 825 | } */ 826 | 827 | .material-symbols-outlined { 828 | color: #ededed; 829 | background-color: #dc143c; 830 | font-weight: 900; 831 | border-radius: .3vh; 832 | padding: .3vh; 833 | } 834 | 835 | .characters-register-block-header { 836 | position: absolute; 837 | width: 100%; 838 | height: 2vh; 839 | top: 20px; 840 | left: 9.4vh; 841 | color: #00f8b9; 842 | font-family: 'Gilroy'; 843 | text-align: left; 844 | font-size: 1.8vh; 845 | font-weight: 500; 846 | } 847 | .input-div{ 848 | /* width: 140%; */ 849 | height: 3.5vh; 850 | margin-bottom: 5px; 851 | margin-right: 3px; 852 | display: flex; 853 | border: 0.1vh solid #cecece4b; 854 | border-radius: 2px; 855 | background-color: #cecece2c; 856 | align-items: center; 857 | justify-content: center; 858 | } 859 | .input-div2{ 860 | /* width: 140%; */ 861 | height: 3.5vh; 862 | margin-bottom: 5px; 863 | margin-right: 3px; 864 | display: flex; 865 | border: 0.1vh solid #cecece4b; 866 | border-radius: 2px; 867 | background-color: #cecece2c; 868 | align-items: center; 869 | justify-content: center; 870 | } 871 | .char-register-inputs { 872 | position: absolute; 873 | top: 50%; 874 | overflow: visible !important; 875 | width: 71%; 876 | z-index: 1001; 877 | } 878 | 879 | 880 | .char-register-icon { 881 | position: absolute; 882 | top: 3.3%; 883 | margin-left: 2px; 884 | overflow: visible !important; 885 | } 886 | 887 | .char-register-text { 888 | position: absolute; 889 | top: 9%; 890 | left: 20px; 891 | font-family: 'Gilroy'; 892 | font-weight: 480; 893 | font-size: 14px; 894 | text-align: left; 895 | margin-left: 82px; 896 | color: #9c9c9cd7; 897 | overflow: visible !important; 898 | } 899 | 900 | .char-register-bar { 901 | position: absolute; 902 | top: 15%; 903 | left: 9px; 904 | width: 39.4vh; 905 | height: 1.7px; 906 | background: linear-gradient(90deg, rgba(255,255,255,0.014443277310924318) 0%, rgba(140,140,140,1) 33%, rgba(140,140,140,1) 66%, rgba(255,255,255,0) 100%); 907 | margin-left: 0px; 908 | color: #9c9c9cd7; 909 | overflow: visible !important; 910 | } 911 | 912 | .char-register-bar2 { 913 | position: absolute; 914 | top: 14.9%; 915 | left: 19px; 916 | width: 15vh; 917 | height: 2.5px; 918 | background: #1df0bb; 919 | box-shadow: 0px 5px 30px #1df0bb73, 0px -5px 30px #1df0bb; 920 | margin-left: 125px; 921 | overflow: visible !important; 922 | } 923 | 924 | .char-reg-bar{ 925 | width: 52%; 926 | height: 2.1px; 927 | background: linear-gradient(90deg, rgba(255,255,255,0.014443277310924318) 0%, rgba(140,140,140,1) 33%, rgba(181,181,181,1) 66%, rgba(255,255,255,0) 100%); 928 | /* padding: 10px; */ 929 | } 930 | 931 | .char-register-inputsss { 932 | position: absolute; 933 | top: 81%; 934 | overflow: visible !important; 935 | width: 71%; 936 | z-index: 1001; 937 | } 938 | 939 | 940 | .char-register-inputss { 941 | position: absolute; 942 | height: 50px; 943 | width: 50vh; 944 | top: 97%; 945 | margin-right: 4px; 946 | overflow: visible !important; 947 | } 948 | 949 | 950 | .char-reg-inputt { 951 | /* background-color: #cecece4b; */ 952 | outline: none; 953 | /* box-shadow:1px 1px 10px #cecece8a; */ 954 | /* border: none; */ 955 | color: #ffffff; 956 | font-weight: 500; 957 | font-family: 'Inter', sans-serif; 958 | height: 3vh; 959 | margin-right: 4px; 960 | padding-left: 7px; 961 | width: 95%; 962 | padding-right: 7px; 963 | } 964 | .char-reg-inputt3 { 965 | position: relative; 966 | float: left; 967 | margin-top: 1vh; 968 | width: 95%; 969 | height: 4vh; 970 | color: rgb(255, 255, 255); 971 | max-width: 104%; 972 | font-weight: 530; 973 | padding-left: 6px; 974 | font-family: 'Inter', sans-serif; 975 | text-align: left; 976 | cursor: text; 977 | margin-bottom: 1vh; 978 | margin-right: 1vh; 979 | transition: all 0.2s ease-in-out 0s; 980 | border: 0; 981 | outline: 0; 982 | background: none; 983 | } 984 | .char-reg-inputt2 { 985 | position: relative; 986 | float: left; 987 | margin-top: 1vh; 988 | width: 95%; 989 | height: 4vh; 990 | color: rgb(255, 255, 255); 991 | max-width: 104%; 992 | font-weight: 530; 993 | padding-left: 6px; 994 | font-family: 'Inter', sans-serif; 995 | text-align: left; 996 | cursor: text; 997 | margin-bottom: 1vh; 998 | margin-right: 1vh; 999 | transition: all 0.2s ease-in-out 0s; 1000 | border: 0; 1001 | outline: 0; 1002 | background: none; 1003 | } 1004 | .adress-icon{ 1005 | display: flex; 1006 | width: 19px; 1007 | padding: 7px; 1008 | align-items: center; 1009 | justify-content: center; 1010 | font-size: 15px; 1011 | margin-top: 1vh; 1012 | /* border: 0.1vh solid #cecece4b; */ 1013 | background-color: #2d9b7fc7; 1014 | color: #2c2c2cc2; 1015 | margin: 10px; 1016 | border-radius: 1px; 1017 | } 1018 | .nationality-icon{ 1019 | display: flex; 1020 | width: 19px; 1021 | padding: 7px; 1022 | align-items: center; 1023 | justify-content: center; 1024 | font-size: 15px; 1025 | margin-top: 1vh; 1026 | /* border: 0.1vh solid #cecece4b; */ 1027 | background-color: #2d9b7fc7; 1028 | color: #2c2c2cc2; 1029 | margin: 10px; 1030 | border-radius: 1px; 1031 | } 1032 | .calendar-icon{ 1033 | display: flex; 1034 | width: 19px; 1035 | padding: 7px; 1036 | align-items: center; 1037 | justify-content: center; 1038 | font-size: 15px; 1039 | margin-top: 1vh; 1040 | /* border: 0.1vh solid #cecece4b; */ 1041 | background-color: #2d9b7fc7; 1042 | color: #2c2c2cc2; 1043 | margin: 10px; 1044 | border-radius: 1px; 1045 | } 1046 | .char-reg-input { 1047 | position: relative; 1048 | float: left; 1049 | margin-top: 1vh; 1050 | /* border: none; */ 1051 | /* background-color: #cecece4b; */ 1052 | /* border: 0.1vh solid #cecece4b; */ 1053 | /* background-color: #aba1a12c; */ 1054 | /* box-shadow: 1px 1px 10px #cecece8a; */ 1055 | outline: none; 1056 | width: 95%; 1057 | height: 4vh; 1058 | color: #ffffff; 1059 | max-width: 104%; 1060 | font-weight: 530; 1061 | padding-left: 6px; 1062 | /* border-radius: 2px; */ 1063 | font-family: 'Inter', sans-serif; 1064 | text-align: left; 1065 | transition: all 0.2s ease-in-out; 1066 | cursor: text; 1067 | /* display: flex; */ 1068 | border: 0; 1069 | outline: 0; 1070 | background: none; 1071 | margin-bottom: 1vh; 1072 | margin-right: 1vh; 1073 | } 1074 | 1075 | 1076 | select { 1077 | position: absolute; 1078 | border: none; 1079 | border: 0vh solid #cecece4b; 1080 | background-color: #cecece2c; 1081 | outline: none; 1082 | width: 104.5%; 1083 | height: 5.5vh; 1084 | top: -8.9vh; 1085 | left: .1vh; 1086 | color: rgb(255, 255, 255); 1087 | max-width: 120%; 1088 | padding: 4px; 1089 | border-radius: 3px; 1090 | font-size: 18px; 1091 | font-family: 'Inter', sans-serif; 1092 | text-align-last: center; 1093 | -webkit-appearance: none; 1094 | -moz-appearance: none; 1095 | text-indent: 1px; 1096 | text-overflow: ''; 1097 | transition: all 0.2s ease-in-out; 1098 | cursor: pointer; 1099 | text-align: center; 1100 | margin: 0 auto; 1101 | text-align-last: center 1102 | } 1103 | 1104 | select:hover { 1105 | background-color: #cecece4b; 1106 | } 1107 | 1108 | select:focus { 1109 | background-color: #cecece4b; 1110 | } 1111 | 1112 | #gender option { 1113 | background-color: transparent; 1114 | border: none; 1115 | outline: none; 1116 | text-align: center; 1117 | align-content: center; 1118 | } 1119 | 1120 | select::placeholder { 1121 | text-align: center; 1122 | } 1123 | 1124 | select::-ms-expand { 1125 | display: none; 1126 | text-align: center; 1127 | margin: 0 auto; 1128 | text-align-last: center 1129 | } 1130 | 1131 | select::content { 1132 | align-items: center; 1133 | text-align: center; 1134 | } 1135 | 1136 | select::selection { 1137 | align-items: center; 1138 | text-align: center; 1139 | } 1140 | 1141 | select::-moz-selection { 1142 | align-items: center; 1143 | text-align: center; 1144 | } 1145 | 1146 | 1147 | .char-reg-input::placeholder { 1148 | color: #ffffff; 1149 | } 1150 | 1151 | .char-reg-inputt::placeholder { 1152 | color: #ffffff; 1153 | } 1154 | 1155 | .char-reg-inputt3::placeholder { 1156 | color: #ffffff; 1157 | } 1158 | 1159 | input[type="date"] { 1160 | color: #ededed; 1161 | text-align: left; 1162 | } 1163 | 1164 | input[type=date]::-webkit-calendar-picker-indicator { 1165 | background-image: url(https://cdn.discordapp.com/attachments/1194309035483213874/1212328869907144744/white-arrow-png-41963.png?ex=65f1703e&is=65defb3e&hm=abb7eaa93b7763dfb352e17296b9dd8b16da69fb89bc9fe17bf0d2b9bf063ba0&); 1166 | } 1167 | /* 1168 | input[type=date]::-webkit-inner-spin-button, 1169 | input[type=date]::-webkit-outer-spin-button { 1170 | -webkit-appearance: none; 1171 | margin: 0; 1172 | } 1173 | 1174 | input[type="date"]::-webkit-input-placeholder { 1175 | visibility: hidden !important; 1176 | } 1177 | 1178 | input[type="date"]::-webkit-clear-button { 1179 | display: none; 1180 | }*/ 1181 | 1182 | #birthdate { 1183 | color: #333943; 1184 | text-align: left; 1185 | font-family: 'Inter', sans-serif; 1186 | } 1187 | 1188 | .character-reg-btn { 1189 | position: absolute; 1190 | width: 34%; 1191 | height: 3vh; 1192 | /* background-color: #0a8b6d; */ 1193 | background: radial-gradient(rgba(0, 248, 185, 0.55) 0%, rgba(0, 248, 185, 0.22) 100%); 1194 | border: calc(0.092592592vh * 1.4) solid rgba(255, 255, 255, 0.15); 1195 | border-radius: 0vh; 1196 | bottom: 3.8vh; 1197 | margin: 0 auto; 1198 | left: 0px; 1199 | cursor: pointer; 1200 | } 1201 | 1202 | .character-reg-btn>p { 1203 | text-align: center; 1204 | line-height: 3vh; 1205 | color: #ffffff; 1206 | font-family: 'Gilroy'; 1207 | font-size: 1.2vh; 1208 | font-weight: 440; 1209 | 1210 | } 1211 | 1212 | .loading-rondje { 1213 | position: absolute; 1214 | margin: 0 auto; 1215 | left: 0; 1216 | right: 0; 1217 | top: 50%; 1218 | width: 150px; 1219 | height: 150px; 1220 | transform: translateY(-50%); 1221 | text-align: center; 1222 | padding: 1vh; 1223 | } 1224 | 1225 | .loading-rondje > p { 1226 | color: white; 1227 | margin-top: 1vh; 1228 | font-family: 'Inter', sans-serif; 1229 | text-shadow: 1px 1px 0px #00000000; 1230 | } 1231 | 1232 | #loading-text { 1233 | color: #ffffff00; 1234 | } 1235 | 1236 | .lds-ring { 1237 | display: inline-block; 1238 | position: relative; 1239 | width: 80px; 1240 | height: 80px; 1241 | } 1242 | 1243 | .lds-ring div { 1244 | box-sizing: border-box; 1245 | display: block; 1246 | position: absolute; 1247 | width: 64px; 1248 | height: 64px; 1249 | border: 8px solid #fff; 1250 | border-radius: 50%; 1251 | animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; 1252 | border-color: #fff transparent transparent transparent; 1253 | } 1254 | 1255 | .lds-ring div:nth-child(1) { 1256 | animation-delay: -0.45s; 1257 | } 1258 | 1259 | .lds-ring div:nth-child(2) { 1260 | animation-delay: -0.3s; 1261 | } 1262 | 1263 | .lds-ring div:nth-child(3) { 1264 | animation-delay: -0.15s; 1265 | } 1266 | 1267 | @keyframes lds-ring { 1268 | 0% { 1269 | transform: rotate(0deg); 1270 | } 1271 | 100% { 1272 | transform: rotate(360deg); 1273 | } 1274 | } 1275 | 1276 | 1277 | 1278 | .lds-spinner { 1279 | display: inline-block; 1280 | position: relative; 1281 | width: 80px; 1282 | height: 80px; 1283 | } 1284 | .lds-spinner div { 1285 | box-sizing: border-box; 1286 | display: block; 1287 | position: absolute; 1288 | width: 64px; 1289 | height: 64px; 1290 | animation: lds-spinner 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite; 1291 | } 1292 | .lds-spinner div:after { 1293 | content: " "; 1294 | display: block; 1295 | position: absolute; 1296 | top: 3px; 1297 | left: 29px; 1298 | width: 5px; 1299 | height: 14px; 1300 | border-radius: 20%; 1301 | background: #1df0bb; 1302 | box-shadow: 1px 1px 15px #1df0bb; 1303 | } 1304 | .lds-spinner div:nth-child(1) { 1305 | transform: rotate(0deg); 1306 | animation-delay: -1.1s; 1307 | } 1308 | .lds-spinner div:nth-child(2) { 1309 | transform: rotate(30deg); 1310 | animation-delay: -1s; 1311 | } 1312 | .lds-spinner div:nth-child(3) { 1313 | transform: rotate(60deg); 1314 | animation-delay: -0.9s; 1315 | } 1316 | .lds-spinner div:nth-child(4) { 1317 | transform: rotate(90deg); 1318 | animation-delay: -0.8s; 1319 | } 1320 | .lds-spinner div:nth-child(5) { 1321 | transform: rotate(120deg); 1322 | animation-delay: -0.7s; 1323 | } 1324 | .lds-spinner div:nth-child(6) { 1325 | transform: rotate(150deg); 1326 | animation-delay: -0.6s; 1327 | } 1328 | .lds-spinner div:nth-child(7) { 1329 | transform: rotate(180deg); 1330 | animation-delay: -0.5s; 1331 | } 1332 | .lds-spinner div:nth-child(8) { 1333 | transform: rotate(210deg); 1334 | animation-delay: -0.4s; 1335 | } 1336 | .lds-spinner div:nth-child(9) { 1337 | transform: rotate(240deg); 1338 | animation-delay: -0.3s; 1339 | } 1340 | .lds-spinner div:nth-child(10) { 1341 | transform: rotate(270deg); 1342 | animation-delay: -0.2s; 1343 | } 1344 | .lds-spinner div:nth-child(11) { 1345 | transform: rotate(300deg); 1346 | animation-delay: -0.1s; 1347 | } 1348 | .lds-spinner div:nth-child(12) { 1349 | transform: rotate(330deg); 1350 | animation-delay: 0s; 1351 | } 1352 | @keyframes lds-spinner { 1353 | 0% { 1354 | opacity: 1; 1355 | } 1356 | 100% { 1357 | opacity: 0.6; 1358 | } 1359 | } 1360 | 1361 | 1362 | .bars div{ 1363 | animation-name: an-height; 1364 | animation-duration: .6s; 1365 | z-index: 101; 1366 | } 1367 | 1368 | @keyframes an-height { 1369 | from{ height: 0px; } 1370 | } 1371 | 1372 | 1373 | -------------------------------------------------------------------------------- /html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | qb-Multicharacter 16 | 17 | 18 |
19 |
20 |
21 |
22 |
Character Selector
23 |
2 / 20 characters
24 |
25 |
26 |
27 |
28 |
29 |
30 | 31 |
32 |
33 |
34 | 35 | 41 | 42 |
43 | 44 |
45 |

Identity Creation

46 | 47 |
48 |
49 | 50 | 51 | 55 | 56 |
57 | 58 | 62 | 66 | 67 | 68 | 69 |
70 | 82 |
83 | 84 |
85 | 86 |
87 |
Enter your character detalls
88 |
89 |
90 | 91 | 92 |
93 | 94 | 95 |
96 | 97 |
98 |

Confirm

99 |

Cancel

100 |
101 |
102 |
103 | 104 |
105 | 106 |
107 |

Confirm

108 |

Cancel

109 |
110 |
111 |
errorError!
112 |
113 |

Close

114 |
115 |
116 |
117 | 118 | 119 | 120 | 121 | -------------------------------------------------------------------------------- /html/js/script.js: -------------------------------------------------------------------------------- 1 | var selectedChar = null; 2 | var WelcomePercentage = "30vh" 3 | qbMultiCharacters = {} 4 | var translations = {} 5 | var Loaded = false; 6 | var NChar = null; 7 | var EnableDeleteButton = false; 8 | var dollar = Intl.NumberFormat('en-US'); 9 | 10 | $(document).ready(function (){ 11 | window.addEventListener('message', function (event) { 12 | var data = event.data; 13 | if (data.action == "ui") { 14 | NChar = data.nChar; 15 | EnableDeleteButton = data.enableDeleteButton; 16 | 17 | translations = data.translations 18 | if (data.toggle) { 19 | $('.container').show(); 20 | $(".welcomescreen").fadeIn(150); 21 | qbMultiCharacters.resetAll(); 22 | 23 | // var originalText = "Loading."; 24 | var loadingProgress = 0; 25 | var loadingDots = 0; 26 | // $("#loading-text").html(originalText); 27 | var DotsInterval = setInterval(function() { 28 | $("#loading-text").append("."); 29 | loadingDots++; 30 | loadingProgress++; 31 | // if (loadingProgress == 3) { 32 | // originalText = "Loading.." 33 | // $("#loading-text").html(originalText); 34 | // } 35 | // if (loadingProgress == 4) { 36 | // originalText = "Loading.." 37 | // $("#loading-text").html(originalText); 38 | // } 39 | // if (loadingProgress == 6) { 40 | // originalText = "Loading..." 41 | // $("#loading-text").html(originalText); 42 | // } 43 | // if(loadingDots == 4) { 44 | // $("#loading-text").html(originalText); 45 | // loadingDots = 0; 46 | // } 47 | }, 500); 48 | 49 | setTimeout(function(){ 50 | 51 | $.post('https://qb-multicharacter/setupCharacters'); 52 | setTimeout(function(){ 53 | // clearInterval(DotsInterval); 54 | loadingProgress = 0; 55 | // originalText = "Retrieving data"; 56 | $(".welcomescreen").fadeOut(150); 57 | qbMultiCharacters.fadeInDown('.characters-list', '80.6%', 1); 58 | qbMultiCharacters.fadeInDown('.bar', '79%', 1); 59 | qbMultiCharacters.fadeInDown('.bar2', '78.92%', 1); 60 | qbMultiCharacters.fadeInDown('.characters-icon', '66.66%', 1); 61 | qbMultiCharacters.fadeInDown('.characters-text', '70.26%', 1); 62 | qbMultiCharacters.fadeInDown('.characters-text2', '72.66%', 1); 63 | $(".btns").css({"display":"flex"}); 64 | $.post('https://qb-multicharacter/removeBlur'); 65 | SetLocal() 66 | }, 500); 67 | }, 2000); 68 | } else { 69 | $('.container').fadeOut(250); 70 | qbMultiCharacters.resetAll(); 71 | } 72 | } 73 | 74 | if (data.action == "setupCharacters") { 75 | setupCharacters(event.data.characters,event.data.photo1,event.data.photo2,event.data.photo3,event.data.photo4) 76 | } 77 | 78 | // if (data.action == "setupCharInfo") { 79 | // setupCharInfo(event.data.chardata) 80 | // } 81 | }); 82 | 83 | $('.datepicker').datepicker(); 84 | }); 85 | 86 | 87 | 88 | $('.continue-btn').click(function(e){ 89 | e.preventDefault(); 90 | }); 91 | 92 | $('.disconnect-btn').click(function(e){ 93 | e.preventDefault(); 94 | 95 | $.post('https://qb-multicharacter/closeUI'); 96 | $.post('https://qb-multicharacter/disconnectButton'); 97 | }); 98 | 99 | // function setupCharInfo(cData) { 100 | // if (cData == 'empty') { 101 | // $('.character-info-valid').html('

'); 102 | // } else { 103 | // var gender = translations["male"] 104 | // if (cData.charinfo.gender == 1) { gender = translations["Female"] } 105 | // $('.character-info-valid').html( 106 | // '
'+translations["name"]+': '+cData.charinfo.firstname+' '+cData.charinfo.lastname+'
' + 107 | // '
'+translations["birthdate"]+'Birth: '+cData.charinfo.birthdate+'
' + 108 | // '
'+translations["Name"]+'Sex: '+gender+'
' + 109 | // '
'+translations["Name"]+'Nationality: '+cData.charinfo.nationality+'
' + 110 | // '
'+translations["Name"]+'Job: '+cData.job.label+'
' + 111 | // '
'+translations["Name"]+'Grade: ' + cData.job.grade.name + '
' + 112 | // '
'+translations["Name"]+'Cash: $ '+dollar.format(cData.money.cash)+'$
' + 113 | // '
'+translations["Name"]+'Bank: $ '+dollar.format(cData.money.bank)+'$
' + 114 | // '
'+translations["Name"]+'Phone number: '+cData.charinfo.phone+'
' + 115 | // '
'+translations["Name"]+'Account: '+cData.charinfo.account+'
'); 116 | // } 117 | // } 118 | 119 | async function getBase64Image(src, removeImageBackGround, callback, outputFormat) { 120 | const img = new Image(); 121 | img.crossOrigin = 'Anonymous'; 122 | img.addEventListener("load", () => loadFunc(), false); 123 | async function loadFunc() { 124 | const canvas = document.createElement('canvas'); 125 | const ctx = canvas.getContext('2d'); 126 | var convertingCanvas = canvas; 127 | 128 | var selectedSize = 320 129 | canvas.height = selectedSize; 130 | canvas.width = selectedSize; 131 | ctx.drawImage(img, 0, 0, selectedSize, selectedSize); 132 | await removeBackGround(canvas); 133 | const canvas2 = document.createElement('canvas'); 134 | const ctx2 = canvas2.getContext('2d'); 135 | canvas2.height = 64; 136 | canvas2.width = 64; 137 | ctx2.drawImage(canvas, 0, 0, selectedSize, selectedSize, 0, 0, img.naturalHeight, img.naturalHeight); 138 | convertingCanvas = canvas2; 139 | 140 | var dataURL = convertingCanvas.toDataURL(outputFormat); 141 | canvas.remove(); 142 | convertingCanvas.remove(); 143 | img.remove(); 144 | callback(dataURL); 145 | }; 146 | 147 | img.src = src; 148 | if (img.complete || img.complete === undefined) { 149 | img.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAAAkCAIAAACIS8SLAAAAKklEQVRIie3NMQEAAAgDILV/55nBww8K0Enq2XwHDofD4XA4HA6Hw+E4Wwq6A0U+bfCEAAAAAElFTkSuQmCC"; 150 | img.src = src; 151 | } 152 | } 153 | async function removeBackGround(sentCanvas) { 154 | const canvas = sentCanvas; 155 | const ctx = canvas.getContext('2d'); 156 | 157 | // Loading the model 158 | const net = await bodyPix.load({ 159 | architecture: 'MobileNetV1', 160 | outputStride: 16, 161 | multiplier: 0.75, 162 | quantBytes: 2 163 | }); 164 | 165 | // Segmentation 166 | const { data:map } = await net.segmentPerson(canvas, { 167 | internalResolution: 'medium', 168 | }); 169 | 170 | // Extracting image data 171 | const { data:imgData } = ctx.getImageData(0, 0, canvas.width, canvas.height); 172 | 173 | // Creating new image data 174 | const newImg = ctx.createImageData(canvas.width, canvas.height); 175 | const newImgData = newImg.data; 176 | 177 | for (var i=0; i
'+char.cid +'photo
'+char.charinfo.firstname+' '+char.charinfo.lastname+'' + char.citizenid + '
plus

'+translations["select"]+'

'); 233 | $('#char-'+char.cid).data('cData', char) 234 | $('#char-'+char.cid).data('cid', char.cid) 235 | }else{ 236 | 237 | getBase64Image(tempUrl, true, function(dataUrl) { 238 | tempUrl = dataUrl 239 | // 240 | $('#char-'+char.cid).html('
'+char.cid +'photo
'+char.charinfo.firstname+' '+char.charinfo.lastname+'' + char.citizenid + '
plus

'+translations["select"]+'

'); 241 | $('#char-'+char.cid).data('cData', char) 242 | $('#char-'+char.cid).data('cid', char.cid)} 243 | ) 244 | } 245 | 246 | 247 | }, 100) 248 | }) 249 | } 250 | 251 | $(document).on('click', '#close-log', function(e){ 252 | e.preventDefault(); 253 | selectedLog = null; 254 | $('.welcomescreen').css("filter", "none"); 255 | $('.server-log').css("filter", "none"); 256 | $('.server-log-info').fadeOut(250); 257 | logOpen = false; 258 | }); 259 | 260 | // $(document).on('click', '#info-text', function(e){ 261 | // e.preventDefault(); 262 | // $(".character-info").toggle( 'fast', function(){ 263 | // }); 264 | // }); 265 | 266 | $(document).on('click', '.character', function(e) { 267 | var cDataPed = $(this).data('cData'); 268 | e.preventDefault(); 269 | if (selectedChar === null) { 270 | selectedChar = $(this); 271 | if ((selectedChar).data('cid') == "") { 272 | $(selectedChar).addClass("char-selected"); 273 | // setupCharInfo('empty') 274 | $("#play-text").html(''); 275 | // $("#info-text").html('CD'); 276 | $("#delete").css({"display":"none"}); 277 | $(this).find(".btns").find(".character-btn").remove() 278 | $(this).find(".btns").append('

'+translations["create"]+'

'); 279 | $.post('https://qb-multicharacter/cDataPed', JSON.stringify({ 280 | cData: cDataPed 281 | })); 282 | } else { 283 | $(selectedChar).addClass("char-selected"); 284 | // setupCharInfo($(this).data('cData')) 285 | $(this).find(".btns").find(".character-btn").remove() 286 | 287 | 288 | 289 | if (EnableDeleteButton) { 290 | $(this).find(".btns").append('

'+translations["spawn"]+'

'+translations["delete"]+'

'); 291 | 292 | }else{ 293 | $(this).find(".btns").append('

'+translations["spawn"]+'

'); 294 | 295 | } 296 | $("#play-text").html(''+translations["spawn"]+''); 297 | // $("#info-text").html('D'); 298 | $("#delete-text").html(''+translations["delete"]+''); 299 | $.post('https://qb-multicharacter/cDataPed', JSON.stringify({ 300 | cData: cDataPed 301 | })); 302 | } 303 | } else if ($(selectedChar).attr('id') !== $(this).attr('id')) { 304 | $(selectedChar).removeClass("char-selected"); 305 | $(selectedChar).find(".btns").find(".character-btn").remove() 306 | 307 | $(selectedChar).find(".btns").append('

'+translations["select"]+'

'); 308 | 309 | selectedChar = $(this); 310 | if ((selectedChar).data('cid') == "") { 311 | $(selectedChar).addClass("char-selected"); 312 | // setupCharInfo('empty') 313 | $("#play-text").html(''); 314 | // $("#info-text").html(''); 315 | $(this).find(".btns").find(".character-btn").remove() 316 | $(this).find(".btns").append('

'+translations["create"]+'

'); 317 | $("#delete").css({"display":"none"}); 318 | $.post('https://qb-multicharacter/cDataPed', JSON.stringify({ 319 | cData: cDataPed 320 | })); 321 | } else { 322 | $(selectedChar).addClass("char-selected"); 323 | // setupCharInfo($(this).data('cData')) 324 | $(this).find(".btns").find(".character-btn").remove() 325 | 326 | 327 | if (EnableDeleteButton) { 328 | $(this).find(".btns").append('

'+translations["spawn"]+'

'+translations["delete"]+'

'); 329 | 330 | }else{ 331 | $(this).find(".btns").append('

'+translations["spawn"]+'

'); 332 | 333 | } 334 | 335 | $("#play-text").html(''+translations["spawn"]+''); 336 | 337 | // $("#info-text").html(''); 338 | $("#delete-text").html(''+translations["delete"]+''); 339 | $.post('https://qb-multicharacter/cDataPed', JSON.stringify({ 340 | cData: cDataPed 341 | })); 342 | } 343 | } 344 | }); 345 | 346 | var entityMap = { 347 | '&': '&', 348 | '<': '<', 349 | '>': '>', 350 | '"': '"', 351 | "'": ''', 352 | '/': '/', 353 | '': '`', 354 | '=': '=' 355 | }; 356 | 357 | function escapeHtml(string) { 358 | return String(string).replace(/[&<>"'=/]/g, function (s) { 359 | return entityMap[s]; 360 | }); 361 | } 362 | function hasWhiteSpace(s) { 363 | return /\s/g.test(s); 364 | } 365 | 366 | $(document).on('click', '#create', function (e) { 367 | e.preventDefault(); 368 | 369 | let firstname= $.trim(escapeHtml($('#first_name').val())) 370 | let lastname= $.trim(escapeHtml($('#last_name').val())) 371 | let nationality= $.trim(escapeHtml($('#nationality').val())) 372 | let birthdate= $.trim(escapeHtml($('#birthdate').val())) 373 | let gender= $.trim(escapeHtml($('input[name=radio]:checked').val())) 374 | 375 | let cid = $.trim(escapeHtml($(selectedChar).attr('id').replace('char-', ''))) 376 | 377 | if (!firstname || !lastname || !nationality || !birthdate){ 378 | var reqFieldErr = '

'+translations["missing_information"]+'

' 379 | $('.error-msg').html(reqFieldErr) 380 | $('.error-title').html(''+translations["error_title"]+'Error!') 381 | $('#cancel-error').html(translations["close"]) 382 | 383 | $('.error').fadeIn(400) 384 | 385 | return false; 386 | } 387 | 388 | $.post('https://qb-multicharacter/createNewCharacter', JSON.stringify({ 389 | firstname: firstname, 390 | lastname: lastname, 391 | nationality: nationality, 392 | birthdate: birthdate, 393 | gender: gender, 394 | cid: cid, 395 | })); 396 | $(".container").fadeOut(150); 397 | $('.characters-list').css("filter", "none"); 398 | $('.character-info').css("filter", "none"); 399 | 400 | 401 | qbMultiCharacters.fadeOutDown('.character-register', '35%', 1); 402 | refreshCharacters() 403 | 404 | }); 405 | 406 | $(document).on('click', '#accept-delete', function(e){ 407 | $.post('https://qb-multicharacter/removeCharacter', JSON.stringify({ 408 | citizenid: $(selectedChar).data("citizenid"), 409 | })); 410 | $('.character-delete').fadeOut(150); 411 | $('.characters-block').css("filter", "none"); 412 | refreshCharacters(); 413 | }); 414 | 415 | $(document).on('click', '#cancel-delete', function(e){ 416 | e.preventDefault(); 417 | $('.characters-block').css("filter", "none"); 418 | $('.character-delete').fadeOut(150); 419 | }); 420 | 421 | $(document).on('click', '#close-error', function(e){ 422 | e.preventDefault(); 423 | $('.characters-block').css("filter", "none"); 424 | $('.error').fadeOut(150); 425 | }); 426 | 427 | function setCharactersList(max) { 428 | 429 | var htmlResult = '
' 430 | htmlResult += '
' 431 | if(max >= NChar) max = NChar-1 432 | for (let i = 1; i <= max+1; i++) { 433 | htmlResult += '
plus
'+translations["create_new_character"]+'
plus

'+translations["select"]+'

' 434 | } 435 | htmlResult += '
' 436 | $('.characters-list').html(htmlResult) 437 | } 438 | 439 | function refreshCharacters() { 440 | var htmlResult = '' 441 | for (let i = 1; i <= NChar; i++) { 442 | htmlResult += '
plus
'+translations["create_new_character"]+'
plus

'+translations["select"]+'

' 443 | } 444 | 445 | $('.characters-list').html(htmlResult) 446 | 447 | 448 | setTimeout(function(){ 449 | $(selectedChar).removeClass("char-selected"); 450 | selectedChar = null; 451 | $.post('https://qb-multicharacter/setupCharacters'); 452 | $("#delete").css({"display":"none"}); 453 | $("#play").css({"display":"none"}); 454 | qbMultiCharacters.resetAll(); 455 | }, 100) 456 | } 457 | 458 | $("#close-reg").click(function (e) { 459 | e.preventDefault(); 460 | $('.error').fadeOut(150); 461 | $('.characters-list').css("filter", "none") 462 | $('.character-info').css("filter", "none") 463 | qbMultiCharacters.fadeOutDown('.character-register', '20%', 1); 464 | qbMultiCharacters.OpenAll(); 465 | }) 466 | 467 | $("#close-del").click(function (e) { 468 | e.preventDefault(); 469 | $('.characters-block').css("filter", "none"); 470 | $('.character-delete').fadeOut(150); 471 | }) 472 | 473 | $(document).on('click', '#play', function(e) { 474 | e.preventDefault(); 475 | var charData = $(selectedChar).data('cid'); 476 | 477 | if (selectedChar !== null) { 478 | if (charData !== "") { 479 | $.post('https://qb-multicharacter/selectCharacter', JSON.stringify({ 480 | cData: $(selectedChar).data('cData') 481 | })); 482 | setTimeout(function(){ 483 | qbMultiCharacters.fadeOutDown('.characters-list', "-40%", 1); 484 | qbMultiCharacters.fadeOutDown('.bar', "-40%", 1); 485 | qbMultiCharacters.fadeOutDown('.bar2', "-40%", 1); 486 | qbMultiCharacters.fadeOutDown('.characters-icon', "-40%", 1); 487 | qbMultiCharacters.fadeOutDown('.characters-text', "-40%", 1); 488 | qbMultiCharacters.fadeOutDown('.characters-text2', "-40%", 1); 489 | qbMultiCharacters.fadeOutDown('.character-info', "-40%", 1); 490 | qbMultiCharacters.resetAll(); 491 | }, 1500); 492 | } else { 493 | $('.characters-list').css("filter") 494 | $('.bar').css("filter") 495 | $('.bar2').css("filter") 496 | $('.characters-icon').css("filter") 497 | $('.characters-text').css("filter") 498 | $('.characters-text2').css("filter") 499 | $('.character-info').css("filter") 500 | 501 | $(".characters-register-block-header").html('

'+translations["create_header"]+'

'); 502 | $(".char-register-text").html(translations["header_detail"]); 503 | 504 | $(".char-register-inputs").html('
' 505 | +'
' 506 | +'
' 507 | +'
'+translations["gender_marker"]+'
' 508 | +'
'); 510 | 511 | $(".char-register-inputsss").html('
'); 512 | 513 | $("#create-text").html(translations["confirm"]); 514 | $("#close-reg").html('

'+translations["cancel"]+'

'); 515 | qbMultiCharacters.fadeInDown('.character-register', '20%', 1); 516 | qbMultiCharacters.closeAll(); 517 | } 518 | } 519 | }); 520 | 521 | $(document).on('click', '#delete', function(e) { 522 | e.preventDefault(); 523 | var charData = $(selectedChar).data('cid'); 524 | 525 | if (selectedChar !== null) { 526 | if (charData !== "") { 527 | $('.characters-block').css("filter") 528 | $('.character-delete').fadeIn(250); 529 | 530 | $("#accept-delete").html('

'+translations["confirm"]+'

'); 531 | $("#cancel-delete").html('

'+translations["cancel"]+'

'); 532 | } 533 | } 534 | }); 535 | 536 | qbMultiCharacters.fadeOutUp = function(element, time) { 537 | $(element).css({"display":"block"}).animate({top: "-80.5%",}, time, function(){ 538 | $(element).css({"display":"none"}); 539 | }); 540 | } 541 | 542 | qbMultiCharacters.fadeOutDown = function(element, percent, time) { 543 | if (percent !== undefined) { 544 | $(element).css({"display":"block"}).animate({top: percent,}, time, function(){ 545 | $(element).css({"display":"none"}); 546 | }); 547 | } else { 548 | $(element).css({"display":"block"}).animate({top: "103.5%",}, time, function(){ 549 | $(element).css({"display":"none"}); 550 | }); 551 | } 552 | } 553 | 554 | qbMultiCharacters.fadeInDown = function(element, percent, time) { 555 | $(element).css({"display":"block"}).animate({top: percent,}, time); 556 | } 557 | 558 | qbMultiCharacters.closeAll = function() { 559 | $('.characters-list').hide(); 560 | $('.bar').hide(); 561 | $('.bar2').hide(); 562 | $('.characters-text').hide(); 563 | $('.characters-text2').hide(); 564 | $('.characters-icon').hide(); 565 | $('.character-info').hide(); 566 | selectedChar = null; 567 | 568 | } 569 | qbMultiCharacters.OpenAll = function() { 570 | $('.characters-list').show(); 571 | $('.bar').show(); 572 | $('.bar2').show(); 573 | $('.characters-text').show(); 574 | $('.characters-text2').show(); 575 | $('.characters-icon').show(); 576 | $('.character-info').show(); 577 | 578 | 579 | } 580 | qbMultiCharacters.resetAll = function() { 581 | $('.characters-list').hide(); 582 | $('.characters-list').css("top", "-40"); 583 | $('.bar').hide(); 584 | $('.bar').css("top", "-40"); 585 | $('.bar2').hide(); 586 | $('.bar2').css("top", "-40"); 587 | $('.characters-text').hide(); 588 | $('.characters-text').css("top", "-40"); 589 | $('.characters-text2').hide(); 590 | $('.characters-text2').css("top", "-40"); 591 | $('.characters-icon').hide(); 592 | $('.characters-icon').css("top", "-40"); 593 | $('.character-info').hide(); 594 | $('.character-info').css("top", "-40"); 595 | $('.welcomescreen').css("top", WelcomePercentage); 596 | $('.server-log').show(); 597 | $('.server-log').css("top", "25%"); 598 | selectedChar = null; 599 | } 600 | -------------------------------------------------------------------------------- /locales/en.lua: -------------------------------------------------------------------------------- 1 | local Translations = { 2 | notifications = { 3 | ["char_deleted"] = "Character deleted!", 4 | ["deleted_other_char"] = "You successfully deleted the character with citizen id %{citizenid}.", 5 | ["forgot_citizenid"] = "You forgot to input a citizen id!", 6 | }, 7 | 8 | commands = { 9 | -- /deletechar 10 | ["deletechar_description"] = "Deletes another players character", 11 | ["citizenid"] = "Citizen ID", 12 | ["citizenid_help"] = "The Citizen ID of the character you want to delete", 13 | 14 | --Loaded 15 | 16 | 17 | -- /logout 18 | ["logout_description"] = "Logout of Character (Admin Only)", 19 | 20 | -- /closeNUI 21 | ["closeNUI_description"] = "Close Multi NUI" 22 | }, 23 | 24 | misc = { 25 | ["succes_loaded"] = '^2[qb-core]^7 %{value} has succesfully loaded!', 26 | ["droppedplayer"] = "You have disconnected from QBCore" 27 | }, 28 | 29 | ui = { 30 | -- Main 31 | male = "Male", 32 | female = "Female", 33 | error_title = "Error!", 34 | characters_header = "Character Selector", 35 | characters_count = "characters", 36 | 37 | --Setup Characters 38 | default_image = 'https://cdn.discordapp.com/attachments/1274330975266144371/1276848221746102294/removebg.png?ex=66cb0512&is=66c9b392&hm=61100c3d688307ea8e5fae68a9710a839540173641b8227ce8deae6f32676961&', --You can 'assets/yourimage.png' or any put "any link you want" 39 | create_new_character = "Create new character", 40 | default_right_image = 'assets/image2.png', --You can 'assets/yourimage.png' or any put "any link you want" 41 | 42 | --Create character 43 | create_header = "Identity Creation", 44 | header_detail = "Enter your character detalls", 45 | gender_marker = "Gender Marker", 46 | 47 | missing_information = "You wrote missing information.", 48 | badword = "You have used a bad word, try again!", 49 | 50 | create_firstname = "Name", 51 | create_lastname = "Lastname", 52 | create_nationality = "Nationality", 53 | create_birthday = "Birthday", 54 | 55 | -- Buttons 56 | select = "Select", 57 | create = "Create", 58 | spawn = "Spawn", 59 | delete = "Delete", 60 | cancel = "Cancel", 61 | confirm = "Confirm", 62 | close = "Close",} 63 | 64 | } 65 | 66 | Lang = Lang or Locale:new({ 67 | phrases = Translations, 68 | warnOnMissing = true 69 | }) 70 | -------------------------------------------------------------------------------- /server/main.lua: -------------------------------------------------------------------------------- 1 | local QBCore = exports['qb-core']:GetCoreObject() 2 | 3 | -- Functions 4 | 5 | local function GiveStarterItems(source) 6 | local src = source 7 | local Player = QBCore.Functions.GetPlayer(src) 8 | 9 | for _, v in pairs(QBCore.Shared.StarterItems) do 10 | local info = {} 11 | if v.item == "id_card" then 12 | info.citizenid = Player.PlayerData.citizenid 13 | info.firstname = Player.PlayerData.charinfo.firstname 14 | info.lastname = Player.PlayerData.charinfo.lastname 15 | info.birthdate = Player.PlayerData.charinfo.birthdate 16 | info.gender = Player.PlayerData.charinfo.gender 17 | info.nationality = Player.PlayerData.charinfo.nationality 18 | elseif v.item == "driver_license" then 19 | info.firstname = Player.PlayerData.charinfo.firstname 20 | info.lastname = Player.PlayerData.charinfo.lastname 21 | info.birthdate = Player.PlayerData.charinfo.birthdate 22 | info.type = "Class C Driver License" 23 | end 24 | Player.Functions.AddItem(v.item, v.amount, false, info) 25 | end 26 | end 27 | 28 | local function loadHouseData(src) 29 | local HouseGarages = {} 30 | local Houses = {} 31 | local result = MySQL.query.await('SELECT * FROM houselocations', {}) 32 | if result[1] ~= nil then 33 | for _, v in pairs(result) do 34 | local owned = false 35 | if tonumber(v.owned) == 1 then 36 | owned = true 37 | end 38 | local garage = v.garage ~= nil and json.decode(v.garage) or {} 39 | Houses[v.name] = { 40 | coords = json.decode(v.coords), 41 | owned = owned, 42 | price = v.price, 43 | locked = true, 44 | adress = v.label, 45 | tier = v.tier, 46 | garage = garage, 47 | decorations = {}, 48 | } 49 | HouseGarages[v.name] = { 50 | label = v.label, 51 | takeVehicle = garage, 52 | } 53 | end 54 | end 55 | TriggerClientEvent("qb-garages:client:houseGarageConfig", src, HouseGarages) 56 | TriggerClientEvent("qb-houses:client:setHouseConfig", src, Houses) 57 | end 58 | 59 | -- Commands 60 | 61 | QBCore.Commands.Add("logout", "Logout of Character (Admin Only)", {}, false, function(source) 62 | local src = source 63 | QBCore.Player.Logout(src) 64 | TriggerClientEvent('qb-multicharacter:client:chooseChar', src) 65 | end, "admin") 66 | 67 | QBCore.Commands.Add("closeNUI", "Close Multi NUI", {}, false, function(source) 68 | local src = source 69 | TriggerClientEvent('qb-multicharacter:client:closeNUI', src) 70 | end) 71 | 72 | -- Events 73 | 74 | RegisterNetEvent('qb-multicharacter:server:disconnect', function() 75 | local src = source 76 | DropPlayer(src, "You have disconnected from QBCore") 77 | end) 78 | 79 | RegisterNetEvent('qb-multicharacter:server:loadUserData', function(cData) 80 | local src = source 81 | if QBCore.Player.Login(src, cData.citizenid) then 82 | print('^2[qb-core]^7 '..GetPlayerName(src)..' (Citizen ID: '..cData.citizenid..') has succesfully loaded!') 83 | QBCore.Commands.Refresh(src) 84 | loadHouseData(src) 85 | TriggerClientEvent('apartments:client:setupSpawnUI', src, cData) 86 | TriggerEvent("qb-log:server:CreateLog", "joinleave", "Loaded", "green", "**".. GetPlayerName(src) .. "** ("..(QBCore.Functions.GetIdentifier(src, 'discord') or 'undefined') .." | ||" ..(QBCore.Functions.GetIdentifier(src, 'ip') or 'undefined') .. "|| | " ..(QBCore.Functions.GetIdentifier(src, 'license') or 'undefined') .." | " ..cData.citizenid.." | "..src..") loaded..") 87 | end 88 | end) 89 | 90 | RegisterNetEvent('qb-multicharacter:server:createCharacter', function(data) 91 | local src = source 92 | local newData = {} 93 | newData.cid = data.cid 94 | newData.charinfo = data 95 | if QBCore.Player.Login(src, false, newData) then 96 | if Apartments.Starting then 97 | local randbucket = (GetPlayerPed(src) .. math.random(1,999)) 98 | SetPlayerRoutingBucket(src, randbucket) 99 | print('^2[qb-core]^7 '..GetPlayerName(src)..' has succesfully loaded!') 100 | QBCore.Commands.Refresh(src) 101 | loadHouseData(src) 102 | TriggerClientEvent("qb-multicharacter:client:closeNUI", src) 103 | TriggerClientEvent('apartments:client:setupSpawnUI', src, newData) 104 | GiveStarterItems(src) 105 | else 106 | print('^2[qb-core]^7 '..GetPlayerName(src)..' has succesfully loaded!') 107 | QBCore.Commands.Refresh(src) 108 | loadHouseData(src) 109 | TriggerClientEvent("qb-multicharacter:client:closeNUIdefault", src) 110 | GiveStarterItems(src) 111 | end 112 | end 113 | end) 114 | 115 | RegisterNetEvent('qb-multicharacter:server:deleteCharacter', function(citizenid) 116 | local src = source 117 | QBCore.Player.DeleteCharacter(src, citizenid) 118 | TriggerClientEvent('QBCore:Notify', src, "Character deleted!" , "success") 119 | end) 120 | 121 | -- Callbacks 122 | 123 | QBCore.Functions.CreateCallback("qb-multicharacter:server:GetUserCharacters", function(source, cb) 124 | local src = source 125 | local license = QBCore.Functions.GetIdentifier(src, 'license') 126 | 127 | MySQL.query('SELECT * FROM players WHERE license = ?', {license}, function(result) 128 | cb(result) 129 | end) 130 | end) 131 | 132 | QBCore.Functions.CreateCallback("qb-multicharacter:server:GetServerLogs", function(_, cb) 133 | MySQL.query('SELECT * FROM server_logs', {}, function(result) 134 | cb(result) 135 | end) 136 | end) 137 | 138 | QBCore.Functions.CreateCallback("qb-multicharacter:server:GetNumberOfCharacters", function(source, cb) 139 | local src = source 140 | local license = QBCore.Functions.GetIdentifier(src, 'license') 141 | local numOfChars = 0 142 | 143 | if next(Config.PlayersNumberOfCharacters) then 144 | for _, v in pairs(Config.PlayersNumberOfCharacters) do 145 | if v.license == license then 146 | numOfChars = v.numberOfChars 147 | break 148 | else 149 | numOfChars = Config.DefaultNumberOfCharacters 150 | end 151 | end 152 | else 153 | numOfChars = Config.DefaultNumberOfCharacters 154 | end 155 | cb(numOfChars) 156 | end) 157 | 158 | QBCore.Functions.CreateCallback("qb-multicharacter:server:setupCharacters", function(source, cb) 159 | local license = QBCore.Functions.GetIdentifier(source, 'license') 160 | local plyChars = {} 161 | MySQL.query('SELECT * FROM players WHERE license = ?', {license}, function(result) 162 | for i = 1, (#result), 1 do 163 | result[i].charinfo = json.decode(result[i].charinfo) 164 | result[i].money = json.decode(result[i].money) 165 | result[i].job = json.decode(result[i].job) 166 | plyChars[#plyChars+1] = result[i] 167 | end 168 | cb(plyChars) 169 | end) 170 | end) 171 | 172 | QBCore.Functions.CreateCallback("qb-multicharacter:server:getSkin", function(_, cb, cid) 173 | local result = MySQL.query.await('SELECT * FROM playerskins WHERE citizenid = ? AND active = ?', {cid, 1}) 174 | if result[1] ~= nil then 175 | cb(result[1].model, result[1].skin) 176 | else 177 | cb(nil) 178 | end 179 | end) --------------------------------------------------------------------------------