├── README.md ├── client.lua ├── fxmanifest.lua └── server.lua /README.md: -------------------------------------------------------------------------------- 1 | # tutorial-script 2 | Learn about the fundamentals of QBCore! 3 | 4 | # THIS RESOURCE IS NOT MEANT FOR PRODUCTION USE! 5 | -------------------------------------------------------------------------------- /client.lua: -------------------------------------------------------------------------------- 1 | -- Importing the core object 2 | -- Necessary to access the functions, player data, commands, etc. 3 | 4 | local QBCore = exports['qb-core']:GetCoreObject() 5 | 6 | -- Player loading in after selecting/making a character 7 | -- This event and state change is useful for triggering certain code to happen when a player loads in 8 | 9 | local isLoggedIn = false -- Initialize a global variable in our file to keep track of player login status 10 | 11 | RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function() -- this event is called when a player loads in 12 | isLoggedIn = true 13 | print('You have loaded') -- prints to your F8 console 14 | end) 15 | 16 | -- Player logging out to the multi-character screen (not leaving the server) 17 | -- This event and state change is useful for triggering certain code to happen when a player logs out 18 | 19 | RegisterNetEvent('QBCore:Client:OnPlayerUnload', function() 20 | isLoggedIn = false 21 | print('You have unloaded') 22 | end) 23 | 24 | -- OR 25 | 26 | -- Using this state bag change handler allows you to accomplish the same thing as using both the events above 27 | 28 | AddStateBagChangeHandler('isLoggedIn', nil, function(_, _, value) -- this state bag value is changed when a player loads in 29 | if value then 30 | isLoggedIn = true 31 | print('You have loaded') -- prints to your F8 console 32 | else 33 | isLoggedIn = false 34 | print('You have unloaded') -- prints to your F8 console 35 | end 36 | end) 37 | 38 | -- Accessing a player's data 39 | 40 | RegisterCommand('cplayerdata', function() -- use a generic command to display the data 41 | -- this function will return and store the player's data in a variable 42 | -- Once we have the data, we can access it using the variable name 43 | local PlayerData = QBCore.Functions.GetPlayerData() 44 | -- retrieves the player's unique citizen ID 45 | -- this id is often used to store information about the player in a database 46 | local citizenid = PlayerData.citizenid 47 | -- retrieves the player's cash balance 48 | local cash = PlayerData.money.cash 49 | -- retrieves the player's bank balance 50 | local bank = PlayerData.money.bank 51 | -- retrieves the player's first name 52 | local firstname = PlayerData.charinfo.firstname 53 | -- retrieves the player's last name 54 | local lastname = PlayerData.charinfo.lastname 55 | -- retrieves the player's birthdate 56 | local birthdate = PlayerData.charinfo.birthdate 57 | -- retrieves the player's gender 58 | local gender = PlayerData.charinfo.gender 59 | -- retrieve's the player's nationality 60 | local nationality = PlayerData.charinfo.nationality 61 | -- retrieves the player's phone number 62 | local phone = PlayerData.charinfo.phone 63 | -- retrieves the player's bank account number 64 | local account = PlayerData.charinfo.account 65 | -- retrieves the player's hunger level 66 | local hunger = PlayerData.metadata.hunger 67 | -- retrieves the player's thirst level 68 | local thirst = PlayerData.metadata.thirst 69 | -- retrieves the player's stress level 70 | local stress = PlayerData.metadata.stress 71 | -- retrieves the player's death status 72 | local death = PlayerData.metadata.isdead 73 | -- retrieves the player's last stand status 74 | local laststand = PlayerData.metadata.inlaststand 75 | -- retrieves the player's armor level 76 | local armor = PlayerData.metadata.armor 77 | -- retrieves the player's handcuff status 78 | local handcuff = PlayerData.metadata.ishandcuffed 79 | -- retrieves the player's tracker status 80 | local tracker = PlayerData.metadata.tracker 81 | -- retrieves the player's jail status 82 | local jail = PlayerData.metadata.injail 83 | -- retrieves the player's jail items that were taken (table value) 84 | local jailitems = PlayerData.metadata.jailitems 85 | -- retrieves the player's status (weed or gunpowder) (table value) 86 | local status = PlayerData.metadata.status 87 | -- retrieves the player's phone information (table value) 88 | local phoneinfo = PlayerData.metadata.phone 89 | -- retrieves the player's fitbit status (table value) 90 | local fitbit = PlayerData.metadata.fitbit 91 | -- retrieves the player's command bindings (table value) 92 | local commandbindings = PlayerData.metadata.commandbinds 93 | -- retrieves the player's bloodtype 94 | local bloodtype = PlayerData.metadata.bloodtype 95 | -- retrieves the player's dealer rep level 96 | local dealerrep = PlayerData.metadata.dealerrep 97 | -- retrieves the player's crafting rep level 98 | local craftingrep = PlayerData.metadata.craftingrep 99 | -- retrieves the player's attachment crafting rep level 100 | local attachmentcraftingrep = PlayerData.metadata.attachmentcraftingrep 101 | -- retrieves the player's job rep levels (table value) 102 | local jobrep = PlayerData.metadata.jobrep 103 | -- retrieves the player's tow job rep level 104 | local towjobrep = PlayerData.metadata.jobrep['tow'] 105 | -- retrieves the player's trucker job rep level 106 | local truckerjobrep = PlayerData.metadata.jobrep['trucker'] 107 | -- retrieves the player's taxi job rep level 108 | local taxijobrep = PlayerData.metadata.jobrep['taxi'] 109 | -- retrieves the player's hotdog job rep level 110 | local hotdogjobrep = PlayerData.metadata.jobrep['hotdog'] 111 | -- retrieves the player's callsign 112 | local callsign = PlayerData.metadata.callsign 113 | -- retrieves the player's fingerprint id 114 | local fingerprintid = PlayerData.metadata.fingerprint 115 | -- retrieves the player's unique wallet id for crypto currency 116 | local walletid = PlayerData.metadata.walletid 117 | -- retrieves the player's criminal record (table value) 118 | local criminalrecord = PlayerData.metadata.criminalrecord 119 | -- retrieves the player's criminal record status 120 | local criminalrecordstatus = PlayerData.metadata.criminalrecord['hasRecord'] 121 | -- retrieves the player's criminal record date 122 | local criminalrecorddate = PlayerData.metadata.criminalrecord['date'] 123 | -- retrieves the player's licences (table value) 124 | local licences = PlayerData.metadata.licences 125 | -- retrieves the player's driver's license status 126 | local driverlicense = PlayerData.metadata.licences['driver'] 127 | -- retrieves the player's weapon license status 128 | local weaponlicense = PlayerData.metadata.licences['weapon'] 129 | -- retrieves the player's business license status 130 | local businesslicense = PlayerData.metadata.licences['business'] 131 | -- retrieves the player's inside status 132 | local inside = PlayerData.metadata.inside 133 | -- retrieves the player's house they are inside of 134 | local house = PlayerData.metadata.inside['house'] 135 | -- retrieves the player's apartment info for which one they are in (table value) 136 | local apartment = PlayerData.metadata.inside['apartment'] 137 | -- retrieves the player's apartment type 138 | local apartmenttype = PlayerData.metadata.inside['apartment']['apartmenttype'] 139 | -- retrieves the player's apartment id 140 | local apartmentid = PlayerData.metadata.inside['apartment']['apartmentid'] 141 | -- retrieves the player's phone data (table value) 142 | local phonedata = PlayerData.metadata.phonedata 143 | -- retrieves the player's phone serial number 144 | local serialnumber = PlayerData.metadata.phonedata['serialnumber'] 145 | -- retrieves the player's installed apps (table value) 146 | local installedapps = PlayerData.metadata.phonedata['installedapps'] 147 | -- retrieves the player's job information (table value) 148 | local jobinfo = PlayerData.job 149 | -- retrieves the player's job name 150 | local jobname = PlayerData.job.name 151 | -- retrieves the player's job label 152 | local joblabel = PlayerData.job.label 153 | -- retrieves the player's job payment 154 | local jobpayment = PlayerData.job.payment 155 | -- retrieves the player's job type 156 | local jobtype = PlayerData.job.type 157 | -- retrieves the player's job duty status 158 | local jobduty = PlayerData.job.onduty 159 | -- retrieves the player's job boss status 160 | local jobboss = PlayerData.job.isboss 161 | -- retrieves the player's job grade (table value) 162 | local jobgrade = PlayerData.job.grade 163 | -- retrieves the player's job grade name 164 | local jobgradename = PlayerData.job.grade.name 165 | -- retrieves the player's job grade label 166 | local jobgradelabel = PlayerData.job.grade.label 167 | -- retrieves the player's gang information (table value) 168 | local ganginfo = PlayerData.gang 169 | -- retrieves the player's gang name 170 | local gangname = PlayerData.gang.name 171 | -- retrieves the player's gang label 172 | local ganglabel = PlayerData.gang.label 173 | -- retrieves the player's gang boss status 174 | local gangboss = PlayerData.gang.isboss 175 | -- retrieves the player's gang grade (table value) 176 | local ganggrade = PlayerData.gang.grade 177 | -- retrieves the player's gang grade name 178 | local ganggradename = PlayerData.gang.grade.name 179 | -- retrieves the player's gang grade level 180 | local ganggradelevel = PlayerData.gang.grade.level 181 | end) 182 | -------------------------------------------------------------------------------- /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | fx_version 'cerulean' 2 | game 'gta5' 3 | version '0.0.1' 4 | 5 | author 'Kakarot' 6 | 7 | client_script 'client.lua' 8 | server_script 'server.lua' 9 | -------------------------------------------------------------------------------- /server.lua: -------------------------------------------------------------------------------- 1 | -- Importing the core object 2 | -- Necessary to access the functions, player data, commands, etc. 3 | local QBCore = exports['qb-core']:GetCoreObject() 4 | 5 | RegisterCommand('splayerdata', function(source) 6 | -- this function will return and store the player's data in a variable 7 | -- Once we have the data, we can access it using the variable name 8 | -- Since we are on the server side, we must specify PlayerData as the second index 9 | local Player = QBCore.Functions.GetPlayer(source) 10 | -- retrieves the player's unique citizen ID 11 | -- this id is often used to store information about the player in a database 12 | local citizenid = Player.PlayerData.citizenid 13 | -- retrieves the player's cash balance 14 | local cash = Player.PlayerData.money.cash 15 | -- retrieves the player's bank balance 16 | local bank = Player.PlayerData.money.bank 17 | -- retrieves the player's first name 18 | local firstname = Player.PlayerData.charinfo.firstname 19 | -- retrieves the player's last name 20 | local lastname = Player.PlayerData.charinfo.lastname 21 | -- retrieves the player's birthdate 22 | local birthdate = Player.PlayerData.charinfo.birthdate 23 | -- retrieves the player's gender 24 | local gender = Player.PlayerData.charinfo.gender 25 | -- retrieve's the player's nationality 26 | local nationality = Player.PlayerData.charinfo.nationality 27 | -- retrieves the player's phone number 28 | local phone = Player.PlayerData.charinfo.phone 29 | -- retrieves the player's bank account number 30 | local account = Player.PlayerData.charinfo.account 31 | -- retrieves the player's hunger level 32 | local hunger = Player.PlayerData.metadata.hunger 33 | -- retrieves the player's thirst level 34 | local thirst = Player.PlayerData.metadata.thirst 35 | -- retrieves the player's stress level 36 | local stress = Player.PlayerData.metadata.stress 37 | -- retrieves the player's death status 38 | local death = Player.PlayerData.metadata.isdead 39 | -- retrieves the player's last stand status 40 | local laststand = Player.PlayerData.metadata.inlaststand 41 | -- retrieves the player's armor level 42 | local armor = Player.PlayerData.metadata.armor 43 | -- retrieves the player's handcuff status 44 | local handcuff = Player.PlayerData.metadata.ishandcuffed 45 | -- retrieves the player's tracker status 46 | local tracker = Player.PlayerData.metadata.tracker 47 | -- retrieves the player's jail status 48 | local jail = Player.PlayerData.metadata.injail 49 | -- retrieves the player's jail items that were taken (table value) 50 | local jailitems = Player.PlayerData.metadata.jailitems 51 | -- retrieves the player's status (weed or gunpowder) (table value) 52 | local status = Player.PlayerData.metadata.status 53 | -- retrieves the player's phone information (table value) 54 | local phoneinfo = Player.PlayerData.metadata.phone 55 | -- retrieves the player's fitbit status (table value) 56 | local fitbit = Player.PlayerData.metadata.fitbit 57 | -- retrieves the player's command bindings (table value) 58 | local commandbindings = Player.PlayerData.metadata.commandbinds 59 | -- retrieves the player's bloodtype 60 | local bloodtype = Player.PlayerData.metadata.bloodtype 61 | -- retrieves the player's dealer rep level 62 | local dealerrep = Player.PlayerData.metadata.dealerrep 63 | -- retrieves the player's crafting rep level 64 | local craftingrep = Player.PlayerData.metadata.craftingrep 65 | -- retrieves the player's attachment crafting rep level 66 | local attachmentcraftingrep = Player.PlayerData.metadata.attachmentcraftingrep 67 | -- retrieves the player's job rep levels (table value) 68 | local jobrep = Player.PlayerData.metadata.jobrep 69 | -- retrieves the player's tow job rep level 70 | local towjobrep = Player.PlayerData.metadata.jobrep['tow'] 71 | -- retrieves the player's trucker job rep level 72 | local truckerjobrep = Player.PlayerData.metadata.jobrep['trucker'] 73 | -- retrieves the player's taxi job rep level 74 | local taxijobrep = Player.PlayerData.metadata.jobrep['taxi'] 75 | -- retrieves the player's hotdog job rep level 76 | local hotdogjobrep = Player.PlayerData.metadata.jobrep['hotdog'] 77 | -- retrieves the player's callsign 78 | local callsign = Player.PlayerData.metadata.callsign 79 | -- retrieves the player's fingerprint id 80 | local fingerprintid = Player.PlayerData.metadata.fingerprint 81 | -- retrieves the player's unique wallet id for crypto currency 82 | local walletid = Player.PlayerData.metadata.walletid 83 | -- retrieves the player's criminal record (table value) 84 | local criminalrecord = Player.PlayerData.metadata.criminalrecord 85 | -- retrieves the player's criminal record status 86 | local criminalrecordstatus = Player.PlayerData.metadata.criminalrecord['hasRecord'] 87 | -- retrieves the player's criminal record date 88 | local criminalrecorddate = Player.PlayerData.metadata.criminalrecord['date'] 89 | -- retrieves the player's licences (table value) 90 | local licences = Player.PlayerData.metadata.licences 91 | -- retrieves the player's driver's license status 92 | local driverlicense = Player.PlayerData.metadata.licences['driver'] 93 | -- retrieves the player's weapon license status 94 | local weaponlicense = Player.PlayerData.metadata.licences['weapon'] 95 | -- retrieves the player's business license status 96 | local businesslicense = Player.PlayerData.metadata.licences['business'] 97 | -- retrieves the player's inside status 98 | local inside = Player.PlayerData.metadata.inside 99 | -- retrieves the player's house they are inside of 100 | local house = Player.PlayerData.metadata.inside['house'] 101 | -- retrieves the player's apartment info for which one they are in (table value) 102 | local apartment = Player.PlayerData.metadata.inside['apartment'] 103 | -- retrieves the player's apartment type 104 | local apartmenttype = Player.PlayerData.metadata.inside['apartment']['apartmenttype'] 105 | -- retrieves the player's apartment id 106 | local apartmentid = Player.PlayerData.metadata.inside['apartment']['apartmentid'] 107 | -- retrieves the player's phone data (table value) 108 | local phonedata = Player.PlayerData.metadata.phonedata 109 | -- retrieves the player's phone serial number 110 | local serialnumber = Player.PlayerData.metadata.phonedata['serialnumber'] 111 | -- retrieves the player's installed apps (table value) 112 | local installedapps = Player.PlayerData.metadata.phonedata['installedapps'] 113 | -- retrieves the player's job information (table value) 114 | local jobinfo = Player.PlayerData.job 115 | -- retrieves the player's job name 116 | local jobname = Player.PlayerData.job.name 117 | -- retrieves the player's job label 118 | local joblabel = Player.PlayerData.job.label 119 | -- retrieves the player's job payment 120 | local jobpayment = Player.PlayerData.job.payment 121 | -- retrieves the player's job type 122 | local jobtype = Player.PlayerData.job.type 123 | -- retrieves the player's job duty status 124 | local jobduty = Player.PlayerData.job.onduty 125 | -- retrieves the player's job boss status 126 | local jobboss = Player.PlayerData.job.isboss 127 | -- retrieves the player's job grade (table value) 128 | local jobgrade = Player.PlayerData.job.grade 129 | -- retrieves the player's job grade name 130 | local jobgradename = Player.PlayerData.job.grade.name 131 | -- retrieves the player's job grade label 132 | local jobgradelabel = Player.PlayerData.job.grade.label 133 | -- retrieves the player's gang information (table value) 134 | local ganginfo = Player.PlayerData.gang 135 | -- retrieves the player's gang name 136 | local gangname = Player.PlayerData.gang.name 137 | -- retrieves the player's gang label 138 | local ganglabel = Player.PlayerData.gang.label 139 | -- retrieves the player's gang boss status 140 | local gangboss = Player.PlayerData.gang.isboss 141 | -- retrieves the player's gang grade (table value) 142 | local ganggrade = Player.PlayerData.gang.grade 143 | -- retrieves the player's gang grade name 144 | local ganggradename = Player.PlayerData.gang.grade.name 145 | -- retrieves the player's gang grade level 146 | local ganggradelevel = Player.PlayerData.gang.grade.level 147 | end, false) 148 | 149 | -- Money handling 150 | 151 | RegisterCommand('takemymoney', function(source) 152 | local Player = QBCore.Functions.GetPlayer(source) 153 | local cash = Player.PlayerData.cash 154 | local bank = Player.PlayerData.bank 155 | -- this function is used to remove money from a player 156 | -- you must specify which money account the amount should be taken from 157 | -- the second argument is the amount of money to remove 158 | -- the third optional reason is the reason for the money change 159 | Player.Functions.RemoveMoney('cash', cash, 'Tutorial command') 160 | Player.Functions.RemoveMoney('bank', bank, 'Tutorial command') 161 | end) 162 | 163 | RegisterCommand('makemerich', function(source) 164 | local Player = QBCore.Functions.GetPlayer(source) 165 | -- this function is used to add money to a player 166 | -- you must specify which money account the amount should go towards 167 | -- the second argument is the amount of money to add 168 | -- the third optional reason is the reason for the money change 169 | Player.Functions.AddMoney('cash', 1000000, 'Tutorial command') 170 | Player.Functions.AddMoney('bank', 1000000, 'Tutorial command') 171 | end) 172 | 173 | RegisterCommand('setmymoney', function(source) 174 | local Player = QBCore.Functions.GetPlayer(source) 175 | -- this function is used to set money for a player 176 | -- it doesn't add or remove money, it just sets the amount of money 177 | -- you must specify which money account the amount should be set to 178 | -- the second argument is the amount of money to set 179 | -- the third optional reason is the reason for the money change 180 | Player.Functions.SetMoney('cash', 1000000, 'Tutorial command') 181 | Player.Functions.SetMoney('bank', 1000000, 'Tutorial command') 182 | end) 183 | 184 | RegisterCommand('howrichami', function(source) 185 | local Player = QBCore.Functions.GetPlayer(source) 186 | -- this function is used to get the amount of money a player has 187 | -- you must specify which money account you want to get the amount of 188 | Player.Functions.GetMoney('cash') 189 | Player.Functions.GetMoney('bank') 190 | end) 191 | 192 | -- Job handling 193 | 194 | RegisterCommand('randomjob', function(source) 195 | local Player = QBCore.Functions.GetPlayer(source) 196 | -- this function is used to set a player's job 197 | -- it must exist in the qb-core/shared/jobs.lua file 198 | -- you must specify the job name 199 | -- the second argument is the job rank 200 | Player.Functions.SetJob('tow', 0) 201 | -- we can also set the player on duty after setting their job 202 | Player.Functions.SetJobDuty(true) 203 | end) 204 | 205 | -- Job reputation handling 206 | 207 | RegisterCommand('givejobrep', function(source) 208 | local Player = QBCore.Functions.GetPlayer(source) 209 | -- this function is used to add job reputation to a player 210 | -- it automatically grabs the players job name and assigns rep to it 211 | -- the only argument you need to pass is the amount of reputation to add 212 | Player.Functions.AddJobRep(100) 213 | end) 214 | 215 | -- Gang handling 216 | 217 | RegisterCommand('randomgang', function(source) 218 | local Player = QBCore.Functions.GetPlayer(source) 219 | -- this function is used to set a player's gang 220 | -- it must exist in the qb-core/shared/gangs.lua file 221 | -- you must specify the gang name 222 | -- the second argument is the gang rank 223 | Player.Functions.SetGang('lostmc', 0) 224 | end) 225 | 226 | -- Player metadata handling 227 | 228 | RegisterCommand('makemefeelgood', function(source) 229 | local Player = QBCore.Functions.GetPlayer(source) 230 | -- this function is used to set a player's metadata 231 | -- the metadata must exist in the player object shown above in the long list 232 | -- the first argument is the metadata name 233 | -- the second argument is the metadata value 234 | Player.Functions.SetMetaData('hunger', 100) 235 | Player.Functions.SetMetaData('thirst', 100) 236 | Player.Functions.SetMetaData('stress', 0) 237 | end) 238 | 239 | -- Item handling 240 | 241 | RegisterCommand('gimmeitem', function(source) 242 | local Player = QBCore.Functions.GetPlayer(source) 243 | -- this function is used to give a player an item 244 | -- you must specify the item name 245 | -- the second argument is the item quantity 246 | Player.Functions.AddItem('sandwich', 1) 247 | end) 248 | 249 | RegisterCommand('removeitem', function(source) 250 | local Player = QBCore.Functions.GetPlayer(source) 251 | -- this function is used to remove an item from a player 252 | -- you must specify the item name 253 | -- the second argument is the item quantity 254 | Player.Functions.RemoveItem('sandwich', 1) 255 | end) 256 | 257 | RegisterCommand('clearmyinventory', function(source) 258 | local Player = QBCore.Functions.GetPlayer(source) 259 | -- this function is used to clear a player's inventory 260 | Player.Functions.ClearInventory() 261 | end) 262 | 263 | RegisterCommand('doihavethisitem', function(source) 264 | local Player = QBCore.Functions.GetPlayer(source) 265 | -- this function is used to check if a player has an item 266 | -- you must specify the item name 267 | -- this will return a table value 268 | Player.Functions.GetItemByName('sandwich') 269 | end) 270 | 271 | RegisterCommand('doihavethisitem2', function(source) 272 | local Player = QBCore.Functions.GetPlayer(source) 273 | -- this function is similar to the above function 274 | -- but it does a more in-depth check across all inventory slots 275 | -- you must specify the item name 276 | -- this will return a table value 277 | Player.Functions.GetItemsByName('sandwich') 278 | end) 279 | 280 | RegisterCommand('whichitemisinthatslot', function(source) 281 | local Player = QBCore.Functions.GetPlayer(source) 282 | -- this function is used to check which item is in a specific slot 283 | -- you must specify the slot number 284 | -- this will return a table value 285 | Player.Functions.GetItemInSlot(1) 286 | end) 287 | 288 | RegisterCommand('setmyinventory', function(source) 289 | local Player = QBCore.Functions.GetPlayer(source) 290 | -- this function is used to set a player's inventory 291 | -- this is useful for first getting the players items and then modifying them 292 | -- the first arguments must be a table of items 293 | -- the second argument is for updating chat or not 294 | local playerItems = Player.PlayerData.items 295 | playeritems[1] = {name = 'sandwich', amount = 1} 296 | Player.Functions.SetInventory(playerItems, false) 297 | end) 298 | 299 | -- Player saving 300 | 301 | RegisterCommand('saveme', function(source) 302 | local Player = QBCore.Functions.GetPlayer(source) 303 | -- this function is used to save a player 304 | -- it will save the player's data to the database 305 | Player.Functions.Save() 306 | end) 307 | 308 | -- Updating a player's data 309 | 310 | RegisterCommand('updateme', function(source) 311 | local Player = QBCore.Functions.GetPlayer(source) 312 | -- this function is used to update a player's data 313 | -- this is typically used after modifying a player's data 314 | -- the only argument you need to pass is whether to update chat commands 315 | Player.Functions.UpdatePlayerData(false) 316 | end) 317 | 318 | -- Log a player out 319 | 320 | RegisterCommand('logmeout', function(source) 321 | local Player = QBCore.Functions.GetPlayer(source) 322 | -- this function is used to log a player out 323 | Player.Functions.Logout() 324 | end) 325 | --------------------------------------------------------------------------------