├── 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 | 
37 | 
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 |
33 |
34 |
35 |
41 |
42 |
43 |
44 |
48 |
83 |
84 |
85 |
86 |
87 |
Enter your character detalls
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
101 |
102 |
103 |
104 |
105 |
106 |
110 |
111 |
errorError!
112 |
113 |
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.charinfo.firstname+' '+char.charinfo.lastname+'' + char.citizenid + ' '+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.charinfo.firstname+' '+char.charinfo.lastname+'' + char.citizenid + ' '+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 += '
'+translations["create_new_character"]+' '+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 += ''+translations["create_new_character"]+' '+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)
--------------------------------------------------------------------------------