create_player(source, unique_id, char_id, data)
Function to create player object for the user using the provided character data
Copy local function create_player ( source , unique_id , char_id , data )
local self = {}
self.source = source
self.unique_id = unique_id
self.char_id = char_id
self.identity = data.identity
self.balances = data.balances
self.jobs = data.jobs
self.paychecks = data.paychecks
self.skills = data.skills
self.inventory = data.inventory
self.statuses = data.statuses
self.booleans = data.booleans
self.licences = data.licences
self.genetics = data.genetics
self.barber = data.barber
self.clothing = data.clothing
self.tattoos = data.tattoos
self.position = data.position
-- function to set players updated data on client
function self: set_data ( data_types , save_to_db )
local data_table = {}
local data_map = {
unique_id = self.unique_id,
char_id = self.char_id,
identity = self.identity,
balances = self.balances,
jobs = self.jobs,
paychecks = self.paychecks,
skills = self.skills,
inventory = self.inventory,
statuses = self.statuses,
booleans = self.booleans,
licences = self.licences,
genetics = self.genetics,
barber = self.barber,
clothing = self.clothing,
tattoos = self.tattoos,
position = self.position
}
if data_types[ 1 ] == 'all' then
data_table = data_map
else
for _, data_type in ipairs (data_types) do
if data_map[data_type] then
data_table[data_type] = data_map[data_type]
end
end
end
TriggerClientEvent ( 'boii_base:cl:set_data' , self.source, data_table)
if save_to_db then
self: save_data ()
end
end
-- function to modify balance
function self: modify_balance ( balance , action , amount , from )
if not self.balances[balance] then print ( 'invalid balance type' ) return end
local current_amount = self.balances[balance].amount
if action == 'add' then
self.balances[balance].amount = current_amount + amount
elseif action == 'remove' then
self.balances[balance].amount = current_amount - amount
elseif action == 'set' then
self.balances[balance].amount = amount
else
print ( 'invalid action type' )
return
end
if self.balances[balance].amount < 0 and not self.balances[balance].negative_allowed then
self.balances[balance].amount = 0
end
self: set_data ({ 'balances' }, true )
end
-- function to add a paycheck
function self: add_pending_paycheck ( job_id , amount , info )
if not self.paychecks[job_id] then
self.paychecks[job_id] = {}
end
local formated_timestamp = os.date ( '%Y-%m-%d %H:%M:%S' , os.time ())
self.paychecks[job_id][ # self.paychecks[job_id] + 1 ] = { amount = amount, timestamp = formated_timestamp }
self: set_data ({ 'paychecks' }, true )
end
-- function to set a players jobs
function self: set_job ( new_job_id , grade_id )
local job_data = boii. get_job_data (new_job_id)
if not job_data then print ( "Error: The job with ID" , new_job_id, "does not exist." ) return false end
if not job_data.grades[grade_id] then print("Error: The grade with ID", grade_id, "does not exist for job", new_job_id) return false end
local secondary_count = 0
local has_primary = false
for job_id, job_details in pairs (self.jobs) do
if job_details.type == 'secondary' then
secondary_count = secondary_count + 1
elseif job_details.type == 'primary' then
has_primary = true
end
end
if job_data.type == "primary" and has_primary and not self.jobs[new_job_id] then
for job_id, job_details in pairs (self.jobs) do
if job_details.type == 'primary' then
self.jobs[job_id] = nil
break
end
end
end
if job_data.type == "secondary" and not self.jobs[new_job_id] and secondary_count >= shared_data.jobs.max_secondary_jobs then print("Error: Maximum number of secondary jobs reached.") return false end
if self.jobs[new_job_id] then
if self.jobs[new_job_id].grade ~= job_data.grades[grade_id].grade then
self.jobs[new_job_id].grade = job_data.grades[grade_id].grade
self.jobs[new_job_id].grade_label = job_data.grades[grade_id].label
self.jobs[new_job_id].salary = job_data.grades[grade_id].pay
end
else
self.jobs[new_job_id] = {
id = job_data.id,
label = job_data.label,
type = job_data.type,
category = job_data.category,
salary = job_data.grades[grade_id].pay,
grade_label = job_data.grades[grade_id].label,
grade = job_data.grades[grade_id].grade,
on_duty = false
}
end
self: set_data ({ 'jobs' }, true )
return true
end
-- function to get inventory weight
function self: get_total_inventory_weight ()
local total_weight = 0
for item_id, item in pairs (self.inventory.items) do
local item_data = boii. get_item_data (item_id)
if item_data then
total_weight = total_weight + (item_data.weight * item.quantity)
else
print ( "No data found for item_id: " .. item_id)
end
end
return total_weight
end
-- function to find the first available empty slot in the inventory
function self: get_empty_slot ()
local max_slots = self.inventory.slots
local occupied_slots = {}
for _, item in pairs (self.inventory.items) do
if item.slot then
occupied_slots[item.slot] = true
end
end
for i = 1 , max_slots do
if not occupied_slots[i] then
return i
end
end
return nil
end
-- function to modify inventory items
function self: modify_inventory ( item_id , action , amount )
if type (amount) ~= "number" or amount < 0 then print ( "Invalid item amount." ) return end
local item_data = boii. get_item_data (item_id)
if not item_data then print ( "Item doesnt exist: " .. item_id) return end
if not self.inventory.items[item_id] then
self.inventory.items[item_id] = item_data
self.inventory.items[item_id].quantity = 0
self.inventory.items[item_id].hotbar = false
local empty_slot = self: get_empty_slot ()
if empty_slot then
self.inventory.items[item_id].slot = empty_slot
else
print ( "No empty slot available in inventory." )
return
end
end
local new_quantity = 0
if action == 'add' then
if item_data.unique and amount > 1 then
print ( "Cannot add more than one of a unique item." )
return
elseif item_data.unique and self.inventory.items[item_id].quantity == 1 then
print ( "Unique item already in inventory." )
return
end
new_quantity = self.inventory.items[item_id].quantity + amount
if (self: get_total_inventory_weight () + item_data.weight * amount) > self.inventory.weight then
print ( "Item addition exceeds weight limit." )
return
end
elseif action == 'remove' then
new_quantity = self.inventory.items[item_id].quantity - amount
if new_quantity < 0 then print ( "Not enough items to remove." ) return end
else
print ( 'Invalid action type: ' .. action)
return
end
self.inventory.items[item_id].quantity = new_quantity
if self.inventory.items[item_id].quantity == 0 then
self.inventory.items[item_id] = nil
end
self: set_data ({ 'inventory' }, true )
end
-- function to save players data to the database
function self: save_data ()
local query = 'UPDATE players SET identity = ?, balances = ?, jobs = ?, paychecks = ?, skills = ?, inventory = ?, statuses = ?, booleans = ?, licences = ?, genetics = ?, barber = ?, clothing = ?, tattoos = ?, position = ? WHERE unique_id = ? AND char_id = ?'
local params = {json.encode(self.identity), json.encode(self.balances), json.encode(self.jobs), json.encode(self.paychecks), json.encode(self.skills), json.encode(self.inventory), json.encode(self.statuses), json.encode(self.booleans), json.encode(self.licences), json.encode(self.genetics), json.encode(self.barber), json.encode(self.clothing), json.encode(self.tattoos), json.encode(self.position), self.unique_id, self.char_id}
MySQL.Async. execute (query, params, function ( rows_changed )
if rows_changed > 0 then
print ( 'data saved successfully' )
else
print ( 'data save failed' )
end
end )
end
self: set_data ({ 'all' })
boii.connected_users[source] = self
TriggerEvent ( 'boii_base:sv:player_joined' , self)
return self
end
Using Self Functions
To use self functions you need to use our utlity get_user() function like so
Copy local _src = source
local player = boii. get_user (_src)
self:set_data(data_types, save_to_db)
Function to set a players data and sync to the client.
You can update an individual data type like so;
Copy player.statuses.health = 0
player: set_data ({ 'statuses' }) -- does not save to database
player: set_data ({ 'statuses' }, true ) -- saves to database
You can also update all datatypes at once by sending 'all'
Copy player: set_data ({ 'all' }) -- does not save to database
player: set_data ({ 'all' }, true ) -- saves to database
self:modify_balance(balance, action, amount, from)
Function to modify balance you can use this to add or remove money from one of your balance types, "from" is simply a logging marker.
Copy player: modify_balance ( 'bank' , 'add' , 1000 , "Add Money" ) -- add money to bank
player: modify_balance ( 'bank' , 'remove' , 1000 , "Remove Money" ) -- remove money from bank
self:add_pending_paycheck(job_id, amount, info)
Function to add a new pay check for a job, these are added periodically depending on the pay_frequency
and direct_pay
options within the shared jobs data or you can use this function to add a manual pay check.
Copy player: add_pending_paycheck ( 'lspd' , 1000 , 'Arrest bonus!' )
self:set_job(new_job_id, grade_id)
Function to update the players job and grade. The framework uses a multi-job setup where players can have 1 primary job and multiple secondary jobs. If a job type primary is set this will update this existing primary job. If job type secondary is set this will add a new secondary job to the character up until the max_secondary_jobs
value is reached. You can adjust this in shared/jobs
Copy player: set_job ( 'lspd' , 'recruit' )
self:get_total_inventory_weight()
Helper function to get total inventory weight of character, this will most likely be removed and placed into inventory functions for now it is here
self:get_empty_slot()
Helper function to place item in next empty slot in the inventory, this will most likely be removed and placed into inventory functions also.
self:modify_inventory(item_id, action, amount)
Function to modify a players inventory items. If the item does not already exist a new item will be added, if the item does exist the quantity will be increased/lowered by the amount.
Copy player: modify_inventory ( 'burger' , 'add' , 1 ) -- add an item
player: modify_inventory ( 'burger' , 'remove' , 1 ) -- remove an item
self:save_data()
Function to save the entire encoded data set of the object to the database. This is done automatically through the set_data
function provided save_to_db
is true
Copy self: save_data () -- save data
self: set_data ({ 'all' }, true ) -- saving all data through set_data function