optimizations + more modules

This commit is contained in:
Jérémie N'gadi
2020-05-11 19:23:02 +02:00
parent bc5ac22bda
commit 960998037e
44 changed files with 1890 additions and 204 deletions
+55
View File
@@ -1,4 +1,6 @@
ESX = {}
ESX.Loops = {}
ESX.LoopsRunning = {}
ESX.Modules = {}
ESX.PlayerData = {}
ESX.PlayerLoaded = false
@@ -57,6 +59,59 @@ RegisterNUICallback('frame_message', function(data, cb)
cb('')
end)
ESX.LogError = function(err)
local str = err .. ' ' .. debug.traceback()
print(str)
TriggerServerEvent('esx:error:log', str);
end
ESX.LogScopeError = function(scope, err)
local str = '[esx] error in scope (' .. scope .. ') ' .. err .. ' ' .. debug.traceback()
print(str)
TriggerServerEvent('esx:error:log', str);
end
ESX.LogLoopError = function(loop, err)
local str = '[esx] error in loop (' .. loop .. ') ' .. err .. ' ' .. debug.traceback()
print(str)
TriggerServerEvent('esx:error:log', str);
end
ESX.Loop = function(name, func, wait, conditions)
ESX.Loops[name] = {
func = func,
wait = wait,
conditons = conditions or {},
name = name,
}
end
ESX.Scope = function(name, func)
local status, result = xpcall(func, function(err)
ESX.LogScopeError(name, err)
end)
return result
end
ESX.MakeScope = function(name, func)
return function(...)
local status, result = xpcall(func, ESX.LogError, function(err)
ESX.LogScopeError(name, err)
end)
return result
end
end
ESX.IsPlayerLoaded = function()
return ESX.PlayerLoaded
end
+191 -93
View File
@@ -1,5 +1,80 @@
local isLoadoutLoaded, isPaused, pickups = false, false, {}
Citizen.CreateThread(function()
AddTextEntry('FE_THDR_GTAO', 'ESX')
local logLoopError = function(err)
ESX.LogLoopError(name, err)
end
local runLoop = function(name, loop)
local conditionsMet = true
for j=1, #loop.conditons, 1 do
if not loop.conditons[j]() then
conditionsMet = false
break
end
end
if conditionsMet then
ESX.LoopsRunning[name] = true
Citizen.CreateThread(function()
while true do
local tests = #loop.conditons
for i=1, #loop.conditons, 1 do
if not loop.conditons[i]() then
break
end
tests = tests - 1
end
if tests > 0 then
ESX.LoopsRunning[name] = false
return
end
local status, result = xpcall(loop.func, logLoopError)
if not status then
ESX.Loops[name] = nil
ESX.LoopsRunning[name] = false
return
end
Citizen.Wait(loop.wait)
end
end)
end
end
while true do
for name, loop in pairs(ESX.Loops) do
if ESX.LoopsRunning[name] ~= true then
local status, result = xpcall(runLoop, ESX.LogError, name, loop)
end
end
Citizen.Wait(250)
end
end)
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
@@ -56,8 +131,6 @@ AddEventHandler('esx:playerLoaded', function(playerData)
TriggerEvent('esx:onPlayerSpawn')
TriggerEvent('esx:restoreLoadout')
StartServerSyncLoops()
end)
end)
@@ -80,7 +153,8 @@ AddEventHandler('skinchanger:modelLoaded', function()
end)
AddEventHandler('esx:restoreLoadout', function()
local playerPed = PlayerPedId()
local playerPed = PlayerPedId()
local ammoTypes = {}
RemoveAllPedWeapons(playerPed, true)
@@ -272,10 +346,11 @@ AddEventHandler('esx:createPickup', function(pickupId, label, playerId, type, na
SetEntityCollision(obj, false, true)
pickups[pickupId] = {
obj = obj,
label = label,
id = pickupId,
obj = obj,
label = label,
inRange = false,
coords = objectCoords
coords = objectCoords
}
end
@@ -420,116 +495,139 @@ if Config.EnableHud then
end)
end
function StartServerSyncLoops()
-- keep track of ammo
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
ESX.Loop('server-sync-ammo', function()
if ESX.IsDead then
Citizen.Wait(500)
else
local playerPed = PlayerPedId()
local playerPed = PlayerPedId()
if IsPedShooting(playerPed) then
local _,weaponHash = GetCurrentPedWeapon(playerPed, true)
local weapon = ESX.GetWeaponFromHash(weaponHash)
if IsPedShooting(playerPed) then
local _,weaponHash = GetCurrentPedWeapon(playerPed, true)
local weapon = ESX.GetWeaponFromHash(weaponHash)
if weapon then
local ammoCount = GetAmmoInPedWeapon(playerPed, weaponHash)
TriggerServerEvent('esx:updateWeaponAmmo', weapon.name, ammoCount)
end
end
end
end
end)
if weapon then
local ammoCount = GetAmmoInPedWeapon(playerPed, weaponHash)
TriggerServerEvent('esx:updateWeaponAmmo', weapon.name, ammoCount)
end
end
-- sync current player coords with server
Citizen.CreateThread(function()
local previousCoords = vector3(ESX.PlayerData.coords.x, ESX.PlayerData.coords.y, ESX.PlayerData.coords.z)
end, 250, {
function() return ESX.PlayerLoaded and (not ESX.IsDead) end
})
while true do
Citizen.Wait(1000)
local playerPed = PlayerPedId()
local previousCoords
if DoesEntityExist(playerPed) then
local playerCoords = GetEntityCoords(playerPed)
local distance = #(playerCoords - previousCoords)
ESX.Loop('server-sync-coords', function()
if distance > 1 then
previousCoords = playerCoords
local playerHeading = ESX.Math.Round(GetEntityHeading(playerPed), 1)
local formattedCoords = {x = ESX.Math.Round(playerCoords.x, 1), y = ESX.Math.Round(playerCoords.y, 1), z = ESX.Math.Round(playerCoords.z, 1), heading = playerHeading}
TriggerServerEvent('esx:updateCoords', formattedCoords)
end
end
end
end)
end
local playerPed = PlayerPedId()
if DoesEntityExist(playerPed) then
local playerCoords = GetEntityCoords(playerPed)
previousCoords = previousCoords or playerCoords
local distance = #(playerCoords - previousCoords)
if distance > 1 then
previousCoords = playerCoords
local playerHeading = ESX.Math.Round(GetEntityHeading(playerPed), 1)
local formattedCoords = {x = ESX.Math.Round(playerCoords.x, 1), y = ESX.Math.Round(playerCoords.y, 1), z = ESX.Math.Round(playerCoords.z, 1), heading = playerHeading}
TriggerServerEvent('esx:updateCoords', formattedCoords)
end
end
end, 1000, {
function() return ESX.PlayerLoaded and (not ESX.IsDead) end
})
-- Disable wanted level
if Config.DisableWantedLevel then
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
local playerId = PlayerId()
if GetPlayerWantedLevel(playerId) ~= 0 then
SetPlayerWantedLevel(playerId, 0, false)
SetPlayerWantedLevelNow(playerId, false)
end
end
end)
ESX.Loop('disable-wanted-level', function()
local playerId = PlayerId()
if GetPlayerWantedLevel(playerId) ~= 0 then
SetPlayerWantedLevel(playerId, 0, false)
SetPlayerWantedLevelNow(playerId, false)
end
end, 0)
end
-- Pickups
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
local playerPed = PlayerPedId()
local playerCoords, letSleep = GetEntityCoords(playerPed), true
local closestPlayer, closestDistance = ESX.Game.GetClosestPlayer(playerCoords)
local pickupsInRange = {}
local closestUsablePickup = nil
for pickupId,pickup in pairs(pickups) do
local distance = #(playerCoords - pickup.coords)
ESX.Loop('get-pickups-in-range', function()
if distance < 5 then
local label = pickup.label
letSleep = false
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
if distance < 1 then
if IsControlJustReleased(0, 38) then
if IsPedOnFoot(playerPed) and (closestDistance == -1 or closestDistance > 3) and not pickup.inRange then
pickup.inRange = true
pickupsInRange = {}
closestUsablePickup = nil
local dict, anim = 'weapons@first_person@aim_rng@generic@projectile@sticky_bomb@', 'plant_floor'
ESX.Streaming.RequestAnimDict(dict)
TaskPlayAnim(playerPed, dict, anim, 8.0, 1.0, 1000, 16, 0.0, false, false, false)
Citizen.Wait(1000)
for pickupId, pickup in pairs(pickups) do
TriggerServerEvent('esx:onPickup', pickupId)
PlaySoundFrontend(-1, 'PICK_UP', 'HUD_FRONTEND_DEFAULT_SOUNDSET', false)
end
end
local distance = #(playerCoords - pickup.coords)
end
if distance < 5.0 then
ESX.ShowFloatingHelpNotification(label, {
x = pickup.coords.x,
y = pickup.coords.y,
z = pickup.coords.z + 0.25
}, 100)
pickupsInRange[#pickupsInRange + 1] = pickup
elseif pickup.inRange then
pickup.inRange = false
end
end
if distance < 1.0 then
closestUsablePickup = pickup
end
if letSleep then
Citizen.Wait(500)
end
end
end)
end
end
end, 500)
ESX.Loop('draw-pickups', function()
local playerPed = PlayerPedId()
local playerCoords = GetEntityCoords(playerPed)
for i=1, #pickupsInRange, 1 do
local pickup = pickupsInRange[i]
ESX.ShowFloatingHelpNotification(pickup.label, {
x = pickup.coords.x,
y = pickup.coords.y,
z = pickup.coords.z + 0.25
}, 100)
end
end, 0)
ESX.Loop('pickup-actions', function()
local playerPed = PlayerPedId()
local pickup = closestUsablePickup
if IsControlJustReleased(0, 38) then
if IsPedOnFoot(playerPed) then
Citizen.CreateThread(function()
local dict, anim = 'weapons@first_person@aim_rng@generic@projectile@sticky_bomb@', 'plant_floor'
ESX.Streaming.RequestAnimDict(dict)
TaskPlayAnim(playerPed, dict, anim, 8.0, 1.0, 1000, 16, 0.0, false, false, false)
Citizen.Wait(1000)
TriggerServerEvent('esx:onPickup', pickup.id)
PlaySoundFrontend(-1, 'PICK_UP', 'HUD_FRONTEND_DEFAULT_SOUNDSET', false)
end)
end
end
end, 0, {
function() return closestUsablePickup ~= nil end
})
AddEventHandler('luaconsole:getHandlers', function(cb)
+40 -53
View File
@@ -1,64 +1,51 @@
Citizen.CreateThread(function()
local isDead = false
AddEventHandler('baseevents:onPlayerDied', function(killerType, deathCoords)
while true do
Citizen.Wait(0)
local player = PlayerId()
local playerPed = PlayerPedId()
if NetworkIsPlayerActive(player) then
local playerPed = PlayerPedId()
local data = {
killed = false,
killerType = killerType,
deathCoords = deathCoords,
deathCause = GetPedCauseOfDeath(playerPed)
}
if IsPedFatallyInjured(playerPed) and not isDead then
isDead = true
TriggerEvent('esx:onPlayerDeath', data)
TriggerServerEvent('esx:onPlayerDeath', data)
local killerEntity, deathCause = GetPedSourceOfDeath(playerPed), GetPedCauseOfDeath(playerPed)
local killerClientId = NetworkGetPlayerIndexFromPed(killerEntity)
if killerEntity ~= playerPed and killerClientId and NetworkIsPlayerActive(killerClientId) then
PlayerKilledByPlayer(GetPlayerServerId(killerClientId), killerClientId, deathCause)
else
PlayerKilled(deathCause)
end
elseif not IsPedFatallyInjured(playerPed) then
isDead = false
end
end
end
end)
function PlayerKilledByPlayer(killerServerId, killerClientId, deathCause)
local victimCoords = GetEntityCoords(PlayerPedId())
local killerCoords = GetEntityCoords(GetPlayerPed(killerClientId))
local distance = #(victimCoords - killerCoords)
local data = {
victimCoords = {x = ESX.Math.Round(victimCoords.x, 1), y = ESX.Math.Round(victimCoords.y, 1), z = ESX.Math.Round(victimCoords.z, 1)},
killerCoords = {x = ESX.Math.Round(killerCoords.x, 1), y = ESX.Math.Round(killerCoords.y, 1), z = ESX.Math.Round(killerCoords.z, 1)},
killedByPlayer = true,
deathCause = deathCause,
distance = ESX.Math.Round(distance, 1),
killerServerId = killerServerId,
killerClientId = killerClientId
}
TriggerEvent('esx:onPlayerDeath', data)
TriggerServerEvent('esx:onPlayerDeath', data)
end
function PlayerKilled(deathCause)
AddEventHandler('baseevents:onPlayerKilled', function(killerId, data)
local playerPed = PlayerPedId()
local victimCoords = GetEntityCoords(playerPed)
local killer = GetPlayerFromServerId(killerId)
local data = {
victimCoords = {x = ESX.Math.Round(victimCoords.x, 1), y = ESX.Math.Round(victimCoords.y, 1), z = ESX.Math.Round(victimCoords.z, 1)},
if NetworkIsPlayerActive(killer) then
killedByPlayer = false,
deathCause = deathCause
}
local victimCoords = data.killerpos
local weaponHash = data.weaponhash
data.killerpos = nil
data.weaponhash = nil
local killerPed = GetPlayerPed(killer)
local killerCoords = GetEntityCoords(killerPed)
local distance = GetDistanceBetweenCoords(victimCoords[1], victimCoords[2], victimCoords[3], killerCoords, false)
data.victimCoords = victimCoords
data.weaponHash = weaponHash
data.deathCause = GetPedCauseOfDeath(playerPed)
data.killed = true
data.killerId = killerId
data.killerCoords = {x = killerCoords.x, y = killerCoords.y, z = killerCoords.z}
data.distance = distance
else
data.killed = false
data.deathCause = GetPedCauseOfDeath(playerPed)
end
TriggerEvent('esx:onPlayerDeath', data)
TriggerServerEvent('esx:onPlayerDeath', data)
end
TriggerServerEvent('esx:onPlayerDeath', data)
end)
+7 -1
View File
@@ -94,7 +94,9 @@ server_exports {
dependencies {
'mysql-async',
'async'
'async',
'cron',
'skinchanger',
}
-- ESX Modules
@@ -120,6 +122,7 @@ esxmodule 'interact' -- Interact menu (marker / npc)
esxmodule 'addonaccount' -- Addon account
esxmodule 'addoninventory' -- Addon inventory
esxmodule 'datastore' -- Arbitrary data store
esxmodule 'society' -- Society management
-- UI
esxmodule 'hud' -- Money / society etc... HUD
@@ -127,5 +130,8 @@ esxmodule 'menu_default' -- Default menu
esxmodule 'menu_dialog' -- Dialog menu
esxmodule 'menu_list' -- List menu
-- Misc
esxmodule 'skin' -- Skin management
-- Jobs
esxmodule 'job_police' -- Job police
+2
View File
@@ -1,5 +1,7 @@
local self = ESX.Modules['input']
self.InitESX()
Citizen.CreateThread(function()
while true do
+2 -2
View File
@@ -454,8 +454,8 @@ end
self.InitESX = function()
self.RegisterControl(Input.Groups.MOVE, Input.Controls[Config.InventoryKey])
self.On('released', Input.Groups.MOVE, Input.Controls[Config.InventoryKey], function(lastPressed)
self.RegisterControl(self.Groups.MOVE, self.Controls[Config.InventoryKey])
self.On('released', self.Groups.MOVE, self.Controls[Config.InventoryKey], function(lastPressed)
if (not ESX.IsDead) and (not ESX.UI.Menu.IsOpen('default', 'es_extended', 'inventory')) then
ESX.ShowInventory()
+16 -20
View File
@@ -31,7 +31,7 @@ Citizen.CreateThread(function()
local distance = #(data.pos - self.Cache.player.coords);
if
(distance <= data.distance) and
(ESX.Table.FindIndex(self.Cache.current, function(e) return e.__id == data.__id end) == -1)
(ESX.Table.FindIndex(self.Cache.current , function(e) return e.__id == data.__id end) == -1)
then
if (data.check == nil) or data.check(self.Cache.player.ped, self.Cache.player.coords) then
@@ -62,33 +62,29 @@ Citizen.CreateThread(function()
end)
-- Markers
Citizen.CreateThread(function()
while true do
ESX.Loop('input-markers', function()
Citizen.Wait(0)
for i=1, #self.Cache.current, 1 do
for i=1, #self.Cache.current, 1 do
local curr = self.Cache.current[i]
local curr = self.Cache.current[i]
if curr.type == 'marker' then
if curr.type == 'marker' then
DrawMarker(
curr.mtype,
curr.pos.x + 0.0, curr.pos.y + 0.0, curr.pos.z + 0.0,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
curr.size.x + 0.0, curr.size.y + 0.0, curr.size.z + 0.0,
curr.color.r, curr.color.g, curr.color.b, curr.color.a,
curr.bobUpAndDown, curr.faceCamera, 2, curr.rotate, nil, nil, false
)
end
DrawMarker(
curr.mtype,
curr.pos.x + 0.0, curr.pos.y + 0.0, curr.pos.z + 0.0,
0.0, 0.0, 0.0,
0.0, 0.0, 0.0,
curr.size.x + 0.0, curr.size.y + 0.0, curr.size.z + 0.0,
curr.color.r, curr.color.g, curr.color.b, curr.color.a,
curr.bobUpAndDown, curr.faceCamera, 2, curr.rotate, nil, nil, false
)
end
end
end)
end, 0)
-- NPCs
Citizen.CreateThread(function()
+4 -1
View File
@@ -9,7 +9,10 @@ self.Cache = {
ped = 0,
coords = vector3(0.0, 0.0, 0.0)
},
current = {},
current = {
marker = {},
npc = {},
},
using = {},
}
+2 -1
View File
@@ -108,6 +108,7 @@ Citizen.CreateThread(function()
end
end)
--[[
-- Enter / Exit entity zone events
Citizen.CreateThread(function()
local trackedEntities = {
@@ -154,4 +155,4 @@ Citizen.CreateThread(function()
end
end
end)
]]--
+1 -1
View File
@@ -5,7 +5,7 @@ Config.MarkerType = 1
Config.MarkerSize = {x = 1.5, y = 1.5, z = 0.5}
Config.MarkerColor = {r = 50, g = 50, b = 204, a = 100}
Config.EnablePlayerManagement = false
Config.EnablePlayerManagement = true
Config.EnableArmoryManagement = true
Config.EnableESXIdentity = false -- enable if you're using esx_identity
Config.EnableLicenses = false -- enable if you're using esx_license
+2 -9
View File
@@ -4,12 +4,5 @@ if self.Config.EnableESXService then
TriggerEvent('esx_service:activateService', 'police', self.Config.MaxInService)
end
AddEventHandler('onResourceStart', function(resource)
if resource == 'esx_society' then
TriggerEvent('esx_society:registerSociety', 'police', 'Police', 'society_police', 'society_police', 'society_police', {type = 'public'})
elseif resource == 'esx_phone' then
TriggerEvent('esx_phone:registerNumber', 'police', _U('alert_police'), true, true)
end
end)
TriggerEvent('esx_society:registerSociety', 'police', 'Police', 'society_police', 'society_police', 'society_police', {type = 'public'})
TriggerEvent('esx_phone:registerNumber', 'police', _U('alert_police'), true, true)
-19
View File
@@ -3,22 +3,3 @@ local self = ESX.Modules['menu_dialog']
ESX.UI.Menu.RegisterType(self.MenuType, self.openMenu, self.closeMenu)
Citizen.CreateThread(function()
while true do
Citizen.Wait(10)
if ESX.Table.SizeOf(self.OpenedMenus) > 0 then
DisableControlAction(0, 1, true) -- LookLeftRight
DisableControlAction(0, 2, true) -- LookUpDown
DisableControlAction(0, 142, true) -- MeleeAttackAlternate
DisableControlAction(0, 106, true) -- VehicleMouseControlOverride
DisableControlAction(0, 12, true) -- WeaponWheelUpDown
DisableControlAction(0, 14, true) -- WeaponWheelNext
DisableControlAction(0, 15, true) -- WeaponWheelPrev
DisableControlAction(0, 16, true) -- SelectNextWeapon
DisableControlAction(0, 17, true) -- SelectPrevWeapon
else
Citizen.Wait(500)
end
end
end)
+51 -4
View File
@@ -1,12 +1,55 @@
ESX.Modules['menu_dialog'] = {};
local self = ESX.Modules['menu_dialog']
local Input = ESX.Modules['input']
self.Timeouts = {}
self.OpenedMenus = {}
self.MenuType = 'dialog'
self.RegisterControls = function()
Input.RegisterControl(Input.Groups.LOOK, Input.Controls.LOOK_LR)
Input.RegisterControl(Input.Groups.LOOK, Input.Controls.LOOK_UD)
Input.RegisterControl(Input.Groups.LOOK, Input.Controls.MELEE_ATTACK_ALTERNATE)
Input.RegisterControl(Input.Groups.LOOK, Input.Controls.VEH_MOUSE_CONTROL_OVERRIDE)
Input.RegisterControl(Input.Groups.LOOK, Input.Controls.WEAPON_WHEEL_UD)
Input.RegisterControl(Input.Groups.LOOK, Input.Controls.WEAPON_WHEEL_NEXT)
Input.RegisterControl(Input.Groups.LOOK, Input.Controls.WEAPON_WHEEL_PREV)
Input.RegisterControl(Input.Groups.LOOK, Input.Controls.SELECT_NEXT_WEAPON)
Input.RegisterControl(Input.Groups.LOOK, Input.Controls.SELECT_PREV_WEAPON)
end
self.EnableControls = function()
Input.EnableControl(Input.Groups.LOOK, Input.Controls.LOOK_LR)
Input.EnableControl(Input.Groups.LOOK, Input.Controls.LOOK_UD)
Input.EnableControl(Input.Groups.LOOK, Input.Controls.MELEE_ATTACK_ALTERNATE)
Input.EnableControl(Input.Groups.LOOK, Input.Controls.VEH_MOUSE_CONTROL_OVERRIDE)
Input.EnableControl(Input.Groups.LOOK, Input.Controls.WEAPON_WHEEL_UD)
Input.EnableControl(Input.Groups.LOOK, Input.Controls.WEAPON_WHEEL_NEXT)
Input.EnableControl(Input.Groups.LOOK, Input.Controls.WEAPON_WHEEL_PREV)
Input.EnableControl(Input.Groups.LOOK, Input.Controls.SELECT_NEXT_WEAPON)
Input.EnableControl(Input.Groups.LOOK, Input.Controls.SELECT_PREV_WEAPON)
end
self.DisableControls = function()
Input.DisableControl(Input.Groups.LOOK, Input.Controls.LOOK_LR)
Input.DisableControl(Input.Groups.LOOK, Input.Controls.LOOK_UD)
Input.DisableControl(Input.Groups.LOOK, Input.Controls.MELEE_ATTACK_ALTERNATE)
Input.DisableControl(Input.Groups.LOOK, Input.Controls.VEH_MOUSE_CONTROL_OVERRIDE)
Input.DisableControl(Input.Groups.LOOK, Input.Controls.WEAPON_WHEEL_UD)
Input.DisableControl(Input.Groups.LOOK, Input.Controls.WEAPON_WHEEL_NEXT)
Input.DisableControl(Input.Groups.LOOK, Input.Controls.WEAPON_WHEEL_PREV)
Input.DisableControl(Input.Groups.LOOK, Input.Controls.SELECT_NEXT_WEAPON)
Input.DisableControl(Input.Groups.LOOK, Input.Controls.SELECT_PREV_WEAPON)
end
self.openMenu = function(namespace, name, data)
for i=1, #self.Timeouts, 1 do
ESX.ClearTimeout(self.Timeouts[i])
end
@@ -24,11 +67,14 @@ self.openMenu = function(namespace, name, data)
ESX.FocusFrame('menu_dialog', true, true)
end)
table.insert(self.Timeouts, timeoutId)
table.insert(self.Timeouts, timeoutId)
self.DisableControls()
end
self.closeMenu = function(namespace, name)
self.OpenedMenus[namespace .. '_' .. name] = nil
ESX.SendFrameMessage('menu_dialog', {
@@ -38,7 +84,8 @@ self.closeMenu = function(namespace, name)
data = data
})
if ESX.Table.SizeOf(self.OpenedMenus) == 0 then
if ESX.Table.SizeOf(self.OpenedMenus) == 0 then
self.EnableControls()
SetNuiFocus(false)
end
+58
View File
@@ -0,0 +1,58 @@
local self = ESX.Modules['skin']
AddEventHandler('esx:onPlayerSpawn', function()
Citizen.CreateThread(function()
while not ESX.PlayerLoaded do
Citizen.Wait(100)
end
if self.firstSpawn then
ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin, jobSkin)
if skin == nil then
TriggerEvent('skinchanger:loadSkin', {sex = 0}, OpenSaveableMenu)
else
TriggerEvent('skinchanger:loadSkin', skin)
end
end)
self.firstSpawn = false
end
end)
end)
AddEventHandler('esx_skin:getLastSkin', function(cb)
cb(self.lastSkin)
end)
AddEventHandler('esx_skin:setLastSkin', function(skin)
self.lastSkin = skin
end)
RegisterNetEvent('esx_skin:openMenu')
AddEventHandler('esx_skin:openMenu', function(submitCb, cancelCb)
self.OpenMenu(submitCb, cancelCb, nil)
end)
RegisterNetEvent('esx_skin:openRestrictedMenu')
AddEventHandler('esx_skin:openRestrictedMenu', function(submitCb, cancelCb, restrict)
self.OpenMenu(submitCb, cancelCb, restrict)
end)
RegisterNetEvent('esx_skin:openSaveableMenu')
AddEventHandler('esx_skin:openSaveableMenu', function(submitCb, cancelCb)
self.OpenSaveableMenu(submitCb, cancelCb, nil)
end)
RegisterNetEvent('esx_skin:openSaveableRestrictedMenu')
AddEventHandler('esx_skin:openSaveableRestrictedMenu', function(submitCb, cancelCb, restrict)
self.OpenSaveableMenu(submitCb, cancelCb, restrict)
end)
RegisterNetEvent('esx_skin:requestSaveSkin')
AddEventHandler('esx_skin:requestSaveSkin', function()
TriggerEvent('skinchanger:getSkin', function(skin)
TriggerServerEvent('esx_skin:responseSaveSkin', skin)
end)
end)
+84
View File
@@ -0,0 +1,84 @@
local self = ESX.Modules['skin']
Citizen.CreateThread(function()
while true do
Citizen.Wait(0)
if self.isCameraActive then
DisableControlAction(2, 30, true)
DisableControlAction(2, 31, true)
DisableControlAction(2, 32, true)
DisableControlAction(2, 33, true)
DisableControlAction(2, 34, true)
DisableControlAction(2, 35, true)
DisableControlAction(0, 25, true) -- Input Aim
DisableControlAction(0, 24, true) -- Input Attack
local playerPed = PlayerPedId()
local coords = GetEntityCoords(playerPed)
local angle = heading * math.pi / 180.0
local theta = {
x = math.cos(angle),
y = math.sin(angle)
}
local pos = {
x = coords.x + (zoomOffset * theta.x),
y = coords.y + (zoomOffset * theta.y)
}
local angleToLook = heading - 140.0
if angleToLook > 360 then
angleToLook = angleToLook - 360
elseif angleToLook < 0 then
angleToLook = angleToLook + 360
end
angleToLook = angleToLook * math.pi / 180.0
local thetaToLook = {
x = math.cos(angleToLook),
y = math.sin(angleToLook)
}
local posToLook = {
x = coords.x + (zoomOffset * thetaToLook.x),
y = coords.y + (zoomOffset * thetaToLook.y)
}
SetCamCoord(cam, pos.x, pos.y, coords.z + camOffset)
PointCamAtCoord(cam, posToLook.x, posToLook.y, coords.z + camOffset)
ESX.ShowHelpNotification(_U('use_rotate_view'))
else
Citizen.Wait(500)
end
end
end)
Citizen.CreateThread(function()
local angle = 90
while true do
Citizen.Wait(0)
if self.isCameraActive then
if IsControlPressed(0, 108) then
self.angle = angle - 1
elseif IsControlPressed(0, 109) then
self.angle = angle + 1
end
if self.angle > 360 then
self.angle = self.angle - 360
elseif angle < 0 then
self.angle = self.angle + 360
end
self.heading = angle + 0.0
else
Citizen.Wait(500)
end
end
end)
+178
View File
@@ -0,0 +1,178 @@
ESX.Modules['skin'] = {}
local self = ESX.Modules['skin']
self.lastSkin = nil
self.playerLoaded = false
self.cam = nil
self.isCameraActive = false
self.firstSpawn = true
self.zoomOffset = 0.0
self.camOffset = 0.0
self.heading = 90.0
self.OpenMenu = function(submitCb, cancelCb, restrict)
local playerPed = PlayerPedId()
TriggerEvent('skinchanger:getSkin', function(skin)
self.lastSkin = skin
end)
TriggerEvent('skinchanger:getData', function(components, maxVals)
local elements = {}
local _components = {}
-- Restrict menu
if restrict == nil then
for i=1, #components, 1 do
_components[i] = components[i]
end
else
for i=1, #components, 1 do
local found = false
for j=1, #restrict, 1 do
if components[i].name == restrict[j] then
found = true
end
end
if found then
table.insert(_components, components[i])
end
end
end
-- Insert elements
for i=1, #_components, 1 do
local value = _components[i].value
local componentId = _components[i].componentId
if componentId == 0 then
value = GetPedPropIndex(playerPed, _components[i].componentId)
end
local data = {
label = _components[i].label,
name = _components[i].name,
value = value,
min = _components[i].min,
textureof = _components[i].textureof,
zoomOffset= _components[i].zoomOffset,
camOffset = _components[i].camOffset,
type = 'slider'
}
for k,v in pairs(maxVals) do
if k == _components[i].name then
data.max = v
break
end
end
table.insert(elements, data)
end
self.CreateSkinCam()
self.zoomOffset = _components[1].zoomOffset
self.camOffset = _components[1].camOffset
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'skin', {
title = _U('skin_menu'),
align = 'top-left',
elements = elements
}, function(data, menu)
TriggerEvent('skinchanger:getSkin', function(skin)
self.lastSkin = skin
end)
submitCb(data, menu)
DeleteSkinCam()
end, function(data, menu)
menu.close()
self.DeleteSkinCam()
TriggerEvent('skinchanger:loadSkin', lastSkin)
if cancelCb ~= nil then
cancelCb(data, menu)
end
end, function(data, menu)
local skin, components, maxVals
TriggerEvent('skinchanger:getSkin', function(getSkin)
skin = getSkin
end)
zoomOffset = data.current.zoomOffset
camOffset = data.current.camOffset
if skin[data.current.name] ~= data.current.value then
-- Change skin element
TriggerEvent('skinchanger:change', data.current.name, data.current.value)
-- Update max values
TriggerEvent('skinchanger:getData', function(comp, max)
components, maxVals = comp, max
end)
local newData = {}
for i=1, #elements, 1 do
newData = {}
newData.max = maxVals[elements[i].name]
if elements[i].textureof ~= nil and data.current.name == elements[i].textureof then
newData.value = 0
end
menu.update({name = elements[i].name}, newData)
end
menu.refresh()
end
end, function(data, menu)
DeleteSkinCam()
end)
end)
end
self.CreateSkinCam = function()
if not DoesCamExist(cam) then
self.cam = CreateCam('DEFAULT_SCRIPTED_CAMERA', true)
end
SetCamActive(cam, true)
RenderScriptCams(true, true, 500, true, true)
self.isCameraActive = true
SetCamRot(cam, 0.0, 0.0, 270.0, true)
SetEntityHeading(playerPed, 90.0)
end
self.DeleteSkinCam = function()
self.isCameraActive = false
SetCamActive(cam, false)
RenderScriptCams(false, true, 500, true, true)
cam = nil
end
self.OpenSaveableMenu = function(submitCb, cancelCb, restrict)
TriggerEvent('skinchanger:getSkin', function(skin)
lastSkin = skin
end)
self.OpenMenu(function(data, menu)
menu.close()
DeleteSkinCam()
TriggerEvent('skinchanger:getSkin', function(skin)
TriggerServerEvent('esx_skin:save', skin)
if submitCb ~= nil then
submitCb(data, menu)
end
end)
end, cancelCb, restrict)
end
+7
View File
@@ -0,0 +1,7 @@
Config = {}
Config.Locale = 'fr'
Config.BackpackWeight = {
[40] = 16, [41] = 20, [44] = 25, [45] = 23
}
+6
View File
@@ -0,0 +1,6 @@
Locales['br'] = {
['skin_menu'] = 'Skin Menu',
['use_rotate_view'] = 'Use ~INPUT_VEH_FLY_ROLL_LEFT_ONLY~ e ~INPUT_VEH_FLY_ROLL_RIGHT_ONLY~ para girar a visão.',
['skin'] = 'Trocar',
['saveskin'] = 'Salvar',
}
+6
View File
@@ -0,0 +1,6 @@
Locales['de'] = {
['skin_menu'] = 'Skin Menü',
['use_rotate_view'] = 'benutze ~INPUT_VEH_FLY_ROLL_LEFT_ONLY~ und ~INPUT_VEH_FLY_ROLL_RIGHT_ONLY~ um die Sicht zu drehen.',
['skin'] = 'Skin ändern',
['saveskin'] = 'Skin speichern',
}
+6
View File
@@ -0,0 +1,6 @@
Locales['en'] = {
['skin_menu'] = 'Skin Menu',
['use_rotate_view'] = 'use ~INPUT_VEH_FLY_ROLL_LEFT_ONLY~ and ~INPUT_VEH_FLY_ROLL_RIGHT_ONLY~ to rotate the view.',
['skin'] = 'change skin',
['saveskin'] = 'save skin to a file',
}
+6
View File
@@ -0,0 +1,6 @@
Locales['fi'] = {
['skin_menu'] = 'ulkonäkö',
['use_rotate_view'] = 'paina ~INPUT_VEH_FLY_ROLL_LEFT_ONLY~ tai ~INPUT_VEH_FLY_ROLL_RIGHT_ONLY~ liikutaaksesi kameraa.',
['skin'] = 'vaihda ulkonäköä',
['saveskin'] = 'talleta ulkonäkö tiedostoon',
}
+6
View File
@@ -0,0 +1,6 @@
Locales['fr'] = {
['skin_menu'] = 'Skin Menu',
['use_rotate_view'] = 'utilisez ~INPUT_VEH_FLY_ROLL_LEFT_ONLY~ et ~INPUT_VEH_FLY_ROLL_RIGHT_ONLY~ pour tourner la vue.',
['skin'] = 'changer de skin',
['saveskin'] = 'sauvegarder skin dans un fichier',
}
+6
View File
@@ -0,0 +1,6 @@
Locales['pl'] = {
['skin_menu'] = 'menu wyglądu',
['use_rotate_view'] = 'użyj ~INPUT_VEH_FLY_ROLL_LEFT_ONLY~ i ~INPUT_VEH_FLY_ROLL_RIGHT_ONLY~ aby obrócić ekran.',
['skin'] = 'zmień wygląd',
['saveskin'] = 'zapisz wygląd do pliku',
}
+6
View File
@@ -0,0 +1,6 @@
Locales['sv'] = {
['skin_menu'] = 'skin meny',
['use_rotate_view'] = 'använd ~INPUT_VEH_FLY_ROLL_LEFT_ONLY~ och ~INPUT_VEH_FLY_ROLL_RIGHT_ONLY~ för att rotera.',
['skin'] = 'ändra skin',
['saveskin'] = 'spara skin till fil',
}
+1
View File
@@ -0,0 +1 @@
ALTER TABLE `users` ADD COLUMN `skin` LONGTEXT NULL DEFAULT NULL;
+64
View File
@@ -0,0 +1,64 @@
local self = ESX.Modules['skin']
RegisterServerEvent('esx_skin:save')
AddEventHandler('esx_skin:save', function(skin)
local xPlayer = ESX.GetPlayerFromId(source)
local defaultMaxWeight = ESX.GetConfig().MaxWeight
local backpackModifier = Config.BackpackWeight[skin.bags_1]
if backpackModifier then
xPlayer.setMaxWeight(defaultMaxWeight + backpackModifier)
else
xPlayer.setMaxWeight(defaultMaxWeight)
end
MySQL.Async.execute('UPDATE users SET skin = @skin WHERE identifier = @identifier', {
['@skin'] = json.encode(skin),
['@identifier'] = xPlayer.identifier
})
end)
RegisterServerEvent('esx_skin:responseSaveSkin')
AddEventHandler('esx_skin:responseSaveSkin', function(skin)
local xPlayer = ESX.GetPlayerFromId(source)
if xPlayer.getGroup() == 'admin' then
local file = io.open('resources/[esx]/esx_skin/skins.txt', "a")
file:write(json.encode(skin) .. "\n\n")
file:flush()
file:close()
else
print(('esx_skin: %s attempted saving skin to file'):format(xPlayer.getIdentifier()))
end
end)
ESX.RegisterServerCallback('esx_skin:getPlayerSkin', function(source, cb)
local xPlayer = ESX.GetPlayerFromId(source)
MySQL.Async.fetchAll('SELECT skin FROM users WHERE identifier = @identifier', {
['@identifier'] = xPlayer.identifier
}, function(users)
local user, skin = users[1]
local jobSkin = {
skin_male = xPlayer.job.skin_male,
skin_female = xPlayer.job.skin_female
}
if user.skin then
skin = json.decode(user.skin)
end
cb(skin, jobSkin)
end)
end)
ESX.RegisterCommand('skin', 'admin', function(xPlayer, args, showError)
xPlayer.triggerEvent('esx_skin:openSaveableMenu')
end, false, {help = _U('skin')})
ESX.RegisterCommand('skinsave', 'admin', function(xPlayer, args, showError)
xPlayer.triggerEvent('esx_skin:requestSaveSkin')
end, false, {help = _U('saveskin')})
+2
View File
@@ -0,0 +1,2 @@
local self = ESX.Modules['skin']
+3
View File
@@ -0,0 +1,3 @@
ESX.Modules['skin'] = {}
local self = ESX.Modules['skin']
+21
View File
@@ -0,0 +1,21 @@
local self = ESX.Modules['society']
AddEventHandler('esx:migrations:ensure', function(register)
register('society')
end)
RegisterNetEvent('esx_addonaccount:setMoney')
AddEventHandler('esx_addonaccount:setMoney', function(society, money)
if ESX.PlayerData.job and ESX.PlayerData.job.grade_name == 'boss' and 'society_' .. ESX.PlayerData.job.name == society then
self.UpdateSocietyMoneyHUDElement(money)
end
end)
RegisterNetEvent('esx:setJob')
AddEventHandler('esx:setJob', function(job)
self.RefreshBossHUD()
end)
AddEventHandler('esx_society:openBossMenu', function(society, close, options)
self.OpenBossMenu(society, close, options)
end)
+13
View File
@@ -0,0 +1,13 @@
local self = ESX.Modules['society']
self.Init()
Citizen.CreateThread(function()
while ESX.PlayerData.job == nil do
Citizen.Wait(10)
end
self.RefreshBossHUD()
end)
+345
View File
@@ -0,0 +1,345 @@
ESX.Modules['society'] = {}
local self = ESX.Modules['society']
self.Config = ESX.EvalFile(GetCurrentResourceName(), 'modules/society/data/config.lua', {
vector3 = vector3
})['Config']
self.Init = function()
local translations = ESX.EvalFile(GetCurrentResourceName(), 'modules/society/data/locales/' .. Config.Locale .. '.lua')['Translations']
LoadLocale('society', Config.Locale, translations)
end
self.base64MoneyIcon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAFoAAABaCAMAAAAPdrEwAAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAMAUExURQAAACmvPCmwPCuwPiywPi2wPy6xQC6xQS+yQTCxQTCyQTCyQjGyQzKyRDOzRTSzRTSzRjW0RjW0Rza0SDe0STi0STm1Sjq1Szq2Szu2TDy2TDy2TT22Tj63Tz+3UEC4UEG4UUG4UkK4U0O5VES5VEW6VUa6Vke6V0i7WEm7WUu8Wku8W0y8W028XE29XU++XlC9X1C+X1G+YFK+YVO/YlW/ZFXAZFfAZVfAZljBZlnBZ1rBaVvCaVvCalzDal7CbF/DbV/EbWHEbmLEb2LEcGTFcWfGdGjHdWrHd2vId2vIeGzIeW3JenHKfXLKfnPLf3TLgHXLgXXMgHXMgXbMgnjNg3nMhHrNhnrOhnzOiH7PiYLQjYPRjoTRjoTRj4XRkIXSkIfSkojSk4rUlYzUlo7VmJDWmpHWm5LXnJTXnZTXnpXYnpbYn5nZopzapJ3bpZ7bpp7bp6DcqKLcqqPcq6Tcq6TdrKberqjfr6jfsKnfsavgs6zgs6zgtK7hta/htrDit7LiuLLiubPjurTjurXju7bkvLbkvbnlv7rlwLrmwLzmwr3nw77nxMDnxcLox8PpyMTpycXpysXqysbqy8fqzMnrzcrrz8vsz8vs0Mzs0c3t0tHu1dHu1tPv19Tv2NXv2dXw2dbw2tfw29jw3Nnx3drx3t7z4d/z4uD04+H05OP15eP15uT15uT15+X16OX26Of26en36+r37Ov37er47Ov47ez47e347u347+758PD58fD68fD68vL69PT79fX79vb79/b89vb89/f8+Pj9+fn9+vr9+/v++/v+/Pz+/P3+/f3+/v7//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALfZHJgAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjb9TgnoAAAGdUlEQVRoQ7WZ93sURRiAFZO76O1eklt215OgBwqJgmgCRhAhRrAAiogBK4gBJEFEgWAEYiGIYEGp1kjXQECkiF0OWyjJ/k34zcy3db7Zu8fHe3/KTXnzPbPT56orRTEYAhMLUFgNKkeiGH8BNaV1KWSPVXveU9s3LW9pvhdoblm+afspTHZi5Wo1BnzpaOfcnFmWSBv29YBtpBNlZm5u59FLPDsmdJUaxQeXNugZw5IwMnrD0oO8iFKuUHNx/+bGZLWNMgm7Otm4uZ/LsVIEUs3F+Y5a3USNAlOv7cgr5ZSamQffyOnKgH1sPdfFi2PVILKaReEcmKwVIWbY2uQDvApW95HULIb+Ng0rFoXWxppcCjyqZuZjk4oNWWBrk44R7oiamXdkC3w9GTO7Q3aH1cy8OkWFnHtitstM4j/bqdWSO6Rm5nYdS4e5FbKQwxlMC6G3Q1bIHVQz8+IKLBphJLdydlRjWpiKxZAXdAfUPOak4gOO4FZOdxWmhbGTkbh9NTOvoVsDuGmAaxkdlZgWRV8Dub7bV0PyzhQWkqk5z7WMdjpqILUTslEXUEPQJ7Lq7pz9WXiBZ4iZUGBnTwTCdtVgvjgxpj+b3vTvTEteq5KbEy/6blcNVZapR3cmdc9Z4QV6Pnxzdr1GF9aWQQFUohqCPqQc3ZV17X3C6tP31kyL+Jy2dsgLW6jBPDgVc6OkR3XxCV/i9IqRRFedylxc6qk30L3DNF7ikz1Jft0oLOaT2hBSg/l8jmwOo24/amimYzkfOwfdlLtdNT1YjIaf0EFzgGhuNnB8teNcqCWDvs3vzSSLqC9Ze0F0EqaGoDeSQWt7UaHgXA0WDKFvFGEzNRS6mxot6VZhUNJNdm7zbsgSagj6UAKTQ5hnhEHJffRISIi+LdRLyNn9cTSoOExP3FZmiat2nIF66t9Xb0GFz8Df+AenVTEF2vUwAzM1BN1LfsTkcVS4bJs+fnRj84z3joqf+eFYUELvZWFzdSfZHjeeEwqXl6/myWaZ0bSVDf3uJP9NkOn01HPISXIMTJAB/hiB6WBPN+xxBpvxl4wxR6ihll8pSL1QupwLLhR22YL9ysVGrKRcfZJeAu4QSo+1yWA3rla2NGCeZGpoj13lmBJm1F/odDm+fv68phorU0l+miDlu6BFmLqbHDCWdhqVQQb/zPesW1inqxdoRqIb1SvSmBJG+wR1BF+/NkmLWUnTK1DdQq+i5gvoIbn85QPqtdRoQfU0TIgy4h/UKOi+gZ5DgGmonqIoob2CDhXHblE0ij2lgNo2YMcSy7fkhF2E2rIm/IoOFV/Q+78i1JkJheJ+jOzjnlr1GRk18swa4iC9t3U/o6LzCVLTP4dlVM14LBfC63yKIYOYeuMqcRoneZFqEW/IKAY6Q8xumla3YP2+PNnNt1Jqb6Arpifg5kXuHjNTaVi1s5/eJs0r+6gFUkxP6kkV2mKBs8UMZSYMdmAJcpxqTTGpqpcCEO1znCMTwlPFNbuF0uUs1UVwKYAWoRcwGDHsbNS/algwu+J1bvToI9TuAgZqetm1roPVk/FDazbhjaryr0SiSw/R1oFll94sWNnfsLrzS1eTkawyjKrE6HcwyeVtIix3s6Dc4ljzsTbnx74P1na83+uf8ZBn5cb0tjgsbHJjlvoMa8dxWT4XBDZmoCa3k7eH9yE0u4l9jr+dZN2P2ASnVorK8TwoVwxsglnYxNY9852oHMseogMEt+4QtnzgGDoTa8eRH4ulA4QOHCxs6ZhUBdNAIS7NIjp1+JgEaulwZzwsnXCjDDxPzB+Rwx1zS0fSoVZb/Mp4/lFqQxk5kjI1cZDWa179HTUEe8eRW9XoQZq5qeN/5fCFigWmd14VNRXLx3/et8lLC7N8XNtH0VP6mXfvV+z4iEsLFrbqqkXXho2Z8dynwgo8NdZK0SXpqxbmjrsgquhCsXrhgOYgL4h4k8Rca5VvFV7gTkySUVxrsbBjLuOGfMy1jCZFa6gv47hbeYU4ZA/XMmbRy13MFaJwqy4+Ez1cy3iSVsddfGLcdJvo33Ato5VcSeOva4WbvmQ2v+daxkrqfqXQJbNwk1fj9kOPuNwlZxdxNS7c5IW+MdRFMhd3oS/cpXmG4EOnRI8nAAt8sKsETz4AK1yahyqAy0vxvAaU7lEQcJ8yj9BPmUf+81MmR8iB//kBllOyZ2NOqR67XUAVABNjuXLlX2rCcoFjOcGoAAAAAElFTkSuQmCC'
self.RefreshBossHUD = function()
self.DisableSocietyMoneyHUDElement()
if ESX.PlayerData.job.grade_name == 'boss' then
self.EnableSocietyMoneyHUDElement()
ESX.TriggerServerCallback('esx_society:getSocietyMoney', function(money)
self.UpdateSocietyMoneyHUDElement(money)
end, ESX.PlayerData.job.name)
end
end
self.EnableSocietyMoneyHUDElement = function()
local societyMoneyHUDElementTpl = '<div><img src="' .. self.base64MoneyIcon .. '" style="width:20px; height:20px; vertical-align:middle;">&nbsp;{{money}}</div>'
if ESX.GetConfig().EnableHud then
ESX.UI.HUD.RegisterElement('society_money', 3, 0, societyMoneyHUDElementTpl, {
money = 0
})
end
TriggerEvent('esx_society:toggleSocietyHud', true)
end
self.DisableSocietyMoneyHUDElement = function()
if ESX.GetConfig().EnableHud then
ESX.UI.HUD.RemoveElement('society_money')
end
TriggerEvent('esx_society:toggleSocietyHud', false)
end
self.UpdateSocietyMoneyHUDElement = function(money)
if ESX.GetConfig().EnableHud then
ESX.UI.HUD.UpdateElement('society_money', {
money = ESX.Math.GroupDigits(money)
})
end
TriggerEvent('esx_society:setSocietyMoney', money)
end
self.OpenBossMenu = function(society, close, options)
options = options or {}
local elements = {}
ESX.TriggerServerCallback('esx_society:isBoss', function(isBoss)
if isBoss then
local defaultOptions = {
withdraw = true,
deposit = true,
wash = true,
employees = true,
grades = true
}
for k,v in pairs(defaultOptions) do
if options[k] == nil then
options[k] = v
end
end
if options.withdraw then
table.insert(elements, {label = _U('society:withdraw_society_money'), value = 'withdraw_society_money'})
end
if options.deposit then
table.insert(elements, {label = _U('society:deposit_society_money'), value = 'deposit_money'})
end
if options.wash then
table.insert(elements, {label = _U('society:wash_money'), value = 'wash_money'})
end
if options.employees then
table.insert(elements, {label = _U('society:employee_management'), value = 'manage_employees'})
end
if options.grades then
table.insert(elements, {label = _U('society:salary_management'), value = 'manage_grades'})
end
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'boss_actions_' .. society, {
title = _U('society:boss_menu'),
align = 'top-left',
elements = elements
}, function(data, menu)
if data.current.value == 'withdraw_society_money' then
ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'withdraw_society_money_amount_' .. society, {
title = _U('society:withdraw_amount')
}, function(data2, menu2)
local amount = tonumber(data2.value)
if amount == nil then
ESX.ShowNotification(_U('society:invalid_amount'))
else
menu2.close()
TriggerServerEvent('esx_society:withdrawMoney', society, amount)
end
end, function(data2, menu2)
menu2.close()
end)
elseif data.current.value == 'deposit_money' then
ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'deposit_money_amount_' .. society, {
title = _U('society:deposit_amount')
}, function(data2, menu2)
local amount = tonumber(data2.value)
if amount == nil then
ESX.ShowNotification(_U('society:invalid_amount'))
else
menu2.close()
TriggerServerEvent('esx_society:depositMoney', society, amount)
end
end, function(data2, menu2)
menu2.close()
end)
elseif data.current.value == 'wash_money' then
ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'wash_money_amount_' .. society, {
title = _U('society:wash_money_amount')
}, function(data2, menu2)
local amount = tonumber(data2.value)
if amount == nil then
ESX.ShowNotification(_U('society:invalid_amount'))
else
menu2.close()
TriggerServerEvent('esx_society:washMoney', society, amount)
end
end, function(data2, menu2)
menu2.close()
end)
elseif data.current.value == 'manage_employees' then
OpenManageEmployeesMenu(society)
elseif data.current.value == 'manage_grades' then
OpenManageGradesMenu(society)
end
end, function(data, menu)
if close then
close(data, menu)
end
end)
end
end, society)
end
self.OpenManageEmployeesMenu = function(society)
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'manage_employees_' .. society, {
title = _U('society:employee_management'),
align = 'top-left',
elements = {
{label = _U('society:employee_list'), value = 'employee_list'},
{label = _U('society:recruit'), value = 'recruit'}
}}, function(data, menu)
if data.current.value == 'employee_list' then
OpenEmployeeList(society)
elseif data.current.value == 'recruit' then
OpenRecruitMenu(society)
end
end, function(data, menu)
menu.close()
end)
end
self.OpenEmployeeList = function(society)
ESX.TriggerServerCallback('esx_society:getEmployees', function(employees)
local elements = {
head = {_U('society:employee'), _U('society:grade'), _U('society:actions')},
rows = {}
}
for i=1, #employees, 1 do
local gradeLabel = (employees[i].job.grade_label == '' and employees[i].job.label or employees[i].job.grade_label)
table.insert(elements.rows, {
data = employees[i],
cols = {
employees[i].name,
gradeLabel,
'{{' .. _U('society:promote') .. '|promote}} {{' .. _U('society:fire') .. '|fire}}'
}
})
end
ESX.UI.Menu.Open('list', GetCurrentResourceName(), 'employee_list_' .. society, elements, function(data, menu)
local employee = data.data
if data.value == 'promote' then
menu.close()
OpenPromoteMenu(society, employee)
elseif data.value == 'fire' then
ESX.ShowNotification(_U('society:you_have_fired', employee.name))
ESX.TriggerServerCallback('esx_society:setJob', function()
OpenEmployeeList(society)
end, employee.identifier, 'unemployed', 0, 'fire')
end
end, function(data, menu)
menu.close()
OpenManageEmployeesMenu(society)
end)
end, society)
end
self.OpenRecruitMenu = function(society)
ESX.TriggerServerCallback('esx_society:getOnlinePlayers', function(players)
local elements = {}
for i=1, #players, 1 do
if players[i].job.name ~= society then
table.insert(elements, {
label = players[i].name,
value = players[i].source,
name = players[i].name,
identifier = players[i].identifier
})
end
end
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'recruit_' .. society, {
title = _U('society:recruiting'),
align = 'top-left',
elements = elements
}, function(data, menu)
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'recruit_confirm_' .. society, {
title = _U('society:do_you_want_to_recruit', data.current.name),
align = 'top-left',
elements = {
{label = _U('society:no'), value = 'no'},
{label = _U('society:yes'), value = 'yes'}
}}, function(data2, menu2)
menu2.close()
if data2.current.value == 'yes' then
ESX.ShowNotification(_U('society:you_have_hired', data.current.name))
ESX.TriggerServerCallback('esx_society:setJob', function()
OpenRecruitMenu(society)
end, data.current.identifier, society, 0, 'hire')
end
end, function(data2, menu2)
menu2.close()
end)
end, function(data, menu)
menu.close()
end)
end)
end
self.OpenPromoteMenu = function(society, employee)
ESX.TriggerServerCallback('esx_society:getJob', function(job)
local elements = {}
for i=1, #job.grades, 1 do
local gradeLabel = (job.grades[i].label == '' and job.label or job.grades[i].label)
table.insert(elements, {
label = gradeLabel,
value = job.grades[i].grade,
selected = (employee.job.grade == job.grades[i].grade)
})
end
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'promote_employee_' .. society, {
title = _U('society:promote_employee', employee.name),
align = 'top-left',
elements = elements
}, function(data, menu)
menu.close()
ESX.ShowNotification(_U('society:you_have_promoted', employee.name, data.current.label))
ESX.TriggerServerCallback('esx_society:setJob', function()
OpenEmployeeList(society)
end, employee.identifier, society, data.current.value, 'promote')
end, function(data, menu)
menu.close()
OpenEmployeeList(society)
end)
end, society)
end
self.OpenManageGradesMenu = function(society)
ESX.TriggerServerCallback('esx_society:getJob', function(job)
local elements = {}
for i=1, #job.grades, 1 do
local gradeLabel = (job.grades[i].label == '' and job.label or job.grades[i].label)
table.insert(elements, {
label = ('%s - <span style="color:green;">%s</span>'):format(gradeLabel, _U('society:money_generic', ESX.Math.GroupDigits(job.grades[i].salary))),
value = job.grades[i].grade
})
end
ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'manage_grades_' .. society, {
title = _U('society:salary_management'),
align = 'top-left',
elements = elements
}, function(data, menu)
ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'manage_grades_amount_' .. society, {
title = _U('society:salary_amount')
}, function(data2, menu2)
local amount = tonumber(data2.value)
if amount == nil then
ESX.ShowNotification(_U('society:invalid_amount'))
elseif amount > Config.MaxSalary then
ESX.ShowNotification(_U('society:invalid_amount_max'))
else
menu2.close()
ESX.TriggerServerCallback('esx_society:setJobSalary', function()
OpenManageGradesMenu(society)
end, society, data.current.value, amount)
end
end, function(data2, menu2)
menu2.close()
end)
end, function(data, menu)
menu.close()
end)
end, society)
end
+5
View File
@@ -0,0 +1,5 @@
Config = {}
Config.Locale = 'fr'
Config.EnableESXIdentity = false
Config.MaxSalary = 3500
+38
View File
@@ -0,0 +1,38 @@
Translations = {
['actions'] = 'ações',
['boss_menu'] = 'menu chefe',
['money_generic'] = '$%s',
['deposit_amount'] = 'valor do depósito',
['deposit_society_money'] = 'depositar dinheiro da sociedade',
['do_you_want_to_recruit'] = 'você quer recrutar %s?',
['employee'] = 'empregado',
['employee_list'] = 'lista de empregados',
['employee_management'] = 'gestão de funcionários',
['fire'] = 'fogo',
['grade'] = 'grau(escolaridade)',
['have_deposited'] = 'você depositou ~r~$%s~s~',
['have_withdrawn'] = 'você retirou ~g~$%s~s~',
['invalid_amount'] = 'montante inválido',
['invalid_amount_max'] = 'esse salário não é permitido',
['no'] = 'não',
['promote'] = 'promover',
['promote_employee'] = 'promover %s',
['recruit'] = 'recrutar',
['recruiting'] = 'recrutamento',
['salary_amount'] = 'valor do salário',
['salary_management'] = 'gestão salarial',
['wash_money'] = 'lavar dinheiro',
['wash_money_amount'] = 'quantidade a lavar',
['withdraw_amount'] = 'retirar montante',
['withdraw_society_money'] = 'retirar dinheiro da sociedade',
['yes'] = 'sim',
['you_have'] = 'você tem ~g~$%s~s~ esperando lavagem de dinheiro (24h).',
['you_have_laundered'] = 'você lavou ~g~$%s~s~ do seu dinheiro ',
['you_have_hired'] = 'você recrutou %s',
['you_have_been_hired'] = 'você foi contratado por %s',
['you_have_fired'] = 'você demitiu %s',
['you_have_been_fired'] = 'você foi demitido de %s',
['you_have_promoted'] = 'você promoveu %s a %s',
['you_have_been_promoted'] = 'você foi promovido ~b~promoted~s~!',
}
+37
View File
@@ -0,0 +1,37 @@
Translations = {
['actions'] = 'akce',
['boss_menu'] = 'akce šéfa',
['money_generic'] = '$%s',
['deposit_amount'] = 'množství vkladu',
['deposit_society_money'] = 'vložit peníze do společnosti',
['do_you_want_to_recruit'] = 'chceš najmout %s?',
['employee'] = 'zaměstnanec',
['employee_list'] = 'seznam zaměstnanců',
['employee_management'] = 'správa zaměstnanců',
['fire'] = 'vyhodit',
['grade'] = 'povýšit',
['have_deposited'] = 'vložil jsi ~r~$%s~s~',
['have_withdrawn'] = 'vybral jsi ~g~$%s~s~',
['invalid_amount'] = 'neplatná částka',
['invalid_amount_max'] = 'tento plat není povolen',
['no'] = 'ne',
['promote'] = 'povýšit',
['promote_employee'] = 'povýšit %s',
['recruit'] = 'najmout',
['recruiting'] = 'najímání',
['salary_amount'] = 'váše platu',
['salary_management'] = 'správa platů',
['wash_money'] = 'vyprat peníze',
['wash_money_amount'] = 'množství na vyprání',
['withdraw_amount'] = 'výběr peněz',
['withdraw_society_money'] = 'vybrat peníze společnosti',
['yes'] = 'ano',
['you_have'] = 'máš ~g~$%s~s~ čekajících na vyprání~s~ (24h).',
['you_have_laundered'] = '~r~Vypral jsi~s~ tvé peníze: ~g~$%s~s~',
['you_have_hired'] = 'najmul jsi %s',
['you_have_been_hired'] = 'byl jsi najmut hráčem %s',
['you_have_fired'] = 'vyhodil jsi %s',
['you_have_been_fired'] = 'byl jsi vyhozen hráčem %s',
['you_have_promoted'] = 'byl jsi povýšen hráčem %s na %s',
['you_have_been_promoted'] = 'byl jsi ~b~povýšen~s~!',
}
+37
View File
@@ -0,0 +1,37 @@
Translations = {
['actions'] = 'actions',
['boss_menu'] = 'boss menu',
['money_generic'] = '$%s',
['deposit_amount'] = 'deposit amount',
['deposit_society_money'] = 'deposit society money',
['do_you_want_to_recruit'] = 'do you want to recruit %s?',
['employee'] = 'employee',
['employee_list'] = 'employee list',
['employee_management'] = 'employee management',
['fire'] = 'fire',
['grade'] = 'grade',
['have_deposited'] = 'you have deposited ~r~$%s~s~',
['have_withdrawn'] = 'you have withdrawn ~g~$%s~s~',
['invalid_amount'] = 'invalid amount',
['invalid_amount_max'] = 'that salary is not allowed',
['no'] = 'no',
['promote'] = 'promote',
['promote_employee'] = 'promote %s',
['recruit'] = 'recruit',
['recruiting'] = 'recruiting',
['salary_amount'] = 'salary amount',
['salary_management'] = 'salary management',
['wash_money'] = 'wash money',
['wash_money_amount'] = 'amount to wash',
['withdraw_amount'] = 'witdraw amount',
['withdraw_society_money'] = 'withdraw society money',
['yes'] = 'yes',
['you_have'] = 'you have ~g~$%s~s~ waiting in ~y~money laundering~s~ (24h).',
['you_have_laundered'] = 'you have ~r~laundered~s~ your money: ~g~$%s~s~',
['you_have_hired'] = 'you have recruited %s',
['you_have_been_hired'] = 'you have been hired by %s',
['you_have_fired'] = 'you have fired %s',
['you_have_been_fired'] = 'you have been fired from %s',
['you_have_promoted'] = 'you have promoted %s as %s',
['you_have_been_promoted'] = 'you have been ~b~promoted~s~!',
}
+37
View File
@@ -0,0 +1,37 @@
Translations = {
['actions'] = 'toiminnot',
['boss_menu'] = 'boss menu',
['money_generic'] = '€%s',
['deposit_amount'] = 'talletus summa',
['deposit_society_money'] = 'talleta yritykselle rahaa',
['do_you_want_to_recruit'] = 'do you want to recruit %s?',
['employee'] = 'työntekijä',
['employee_list'] = 'työntekijä lista',
['employee_management'] = 'työntekijöiden hallinta',
['fire'] = 'anna potkut',
['grade'] = 'taso',
['have_deposited'] = 'sinä talletit ~r~€%s~s~',
['have_withdrawn'] = 'sinä nostit ~g~€%s~s~',
['invalid_amount'] = 'virheellinen summa',
['invalid_amount_max'] = 'that salary is not allowed',
['no'] = 'ei',
['promote'] = 'ylennä',
['promote_employee'] = 'ylennä henkilö %s',
['recruit'] = 'rekrytoi',
['recruiting'] = 'rekrytointi',
['salary_amount'] = 'palkan määrä',
['salary_management'] = 'palkan hallinta',
['wash_money'] = 'pese rahaa',
['wash_money_amount'] = 'pestävä määrä',
['withdraw_amount'] = 'nostettava määrä',
['withdraw_society_money'] = 'nosta yrityksen rahoja',
['yes'] = 'kyllä',
['you_have'] = 'you have ~g~€%s~s~ waiting in ~y~money laundering~s~ (24h).',
['you_have_laundered'] = 'olet ~r~pessyt~s~ rahojasi: ~g~€%s~s~',
['you_have_hired'] = 'sinä palkkasit henkilön %s',
['you_have_been_hired'] = 'sinut on palkattu pelaajan %s toimesta',
['you_have_fired'] = 'sinä annoit potkut pelaajalle %s',
['you_have_been_fired'] = 'sinulle annettiin potkut työstä %s',
['you_have_promoted'] = 'sinä ylensit henkilön %s arvolle %s',
['you_have_been_promoted'] = 'sinut ylennettiin',
}
+37
View File
@@ -0,0 +1,37 @@
Translations = {
['actions'] = 'actions',
['boss_menu'] = 'patron',
['money_generic'] = '$%s',
['deposit_amount'] = 'montant du dépôt',
['deposit_society_money'] = 'déposer argent société',
['do_you_want_to_recruit'] = 'Voulez-vous recruter %s?',
['employee'] = 'employé',
['employee_list'] = 'liste des employés',
['employee_management'] = 'gestion employés',
['fire'] = 'licencier',
['grade'] = 'grade',
['have_deposited'] = 'vous avez déposé ~r~$%s~s~',
['have_withdrawn'] = 'vous avez retiré ~g~$%s~s~',
['invalid_amount'] = 'montant invalide',
['invalid_amount_max'] = 'that salary is not allowed',
['no'] = 'non',
['promote'] = 'promouvoir',
['promote_employee'] = 'promouvoir %s',
['recruit'] = 'recruter',
['recruiting'] = 'recrutement',
['salary_amount'] = 'montant du salaire',
['salary_management'] = 'gestion salaires',
['wash_money'] = 'blanchir argent',
['wash_money_amount'] = 'montant à blanchir',
['withdraw_amount'] = 'montant du retrait',
['withdraw_society_money'] = 'retirer argent société',
['yes'] = 'oui',
['you_have'] = 'vous avez ~g~$%s~s~ en attente de ~r~blanchiement~s~ (24h).',
['you_have_laundered'] = 'vous avez ~r~blanchi~s~ votre argent : ~g~$%s~s~',
['you_have_hired'] = 'Vous avez recruté %s',
['you_have_been_hired'] = 'Vous avez été recruté dans la société %s',
['you_have_fired'] = 'Vous avez viré %s',
['you_have_been_fired'] = 'Vous avez été viré de la société %s',
['you_have_promoted'] = 'Vous avez promu %s en tant que %s',
['you_have_been_promoted'] = 'Vous avez été promu',
}
+38
View File
@@ -0,0 +1,38 @@
Translations = {
['actions'] = 'acties',
['boss_menu'] = 'baas menu',
['money_generic'] = '€%s',
['deposit_amount'] = 'stort hoeveelheid',
['deposit_society_money'] = 'stort maatschappij geld',
['do_you_want_to_recruit'] = 'Wil je %s aannemen?',
['employee'] = 'werknemer',
['employee_list'] = 'werknemer lijst',
['employee_management'] = 'werknemer beheer',
['fire'] = 'ontslaan',
['grade'] = 'schaal',
['have_deposited'] = 'je hebt gestort ~r~$%s~s~',
['have_withdrawn'] = 'je hebt opgenomen ~g~$%s~s~',
['invalid_amount'] = 'ongeldige hoeveelheid',
['invalid_amount_max'] = 'dit salaris is niet toegestaan',
['no'] = 'nee',
['promote'] = 'promoveer',
['promote_employee'] = 'promoveer %s',
['recruit'] = 'werv',
['recruiting'] = 'werven',
['salary_amount'] = 'salaris hoeveelheid',
['salary_management'] = 'salaris beheer',
['wash_money'] = 'witwas geld',
['wash_money_amount'] = 'hoeveelheid om wit te wassen',
['withdraw_amount'] = 'opneem hoeveelheid',
['withdraw_society_money'] = 'neem maatschappelijk geld op',
['yes'] = 'ja',
['you_have'] = 'je hebt ~g~€%s~s~ staan in ~y~geld witwassen~s~ (24h).',
['you_have_laundered'] = 'je hebt je geld: ~g~€%s~s~ ~r~witgewassen~s~ ',
['you_have_hired'] = 'je bent gevraagt %s',
['you_have_been_hired'] = 'je bent aangenomen door %s',
['you_have_fired'] = 'je bent ontslagen %s',
['you_have_been_fired'] = 'je bent ondslagen van %s',
['you_have_promoted'] = 'je hebt gepromoveerd %s naar %s',
['you_have_been_promoted'] = 'je bent ~b~gepromoveerd~s~!',
}
+37
View File
@@ -0,0 +1,37 @@
Translations = {
['actions'] = 'akcje',
['boss_menu'] = 'boss menu',
['money_generic'] = '$%s',
['deposit_amount'] = 'ilość depozytu',
['deposit_society_money'] = 'zdeponuj społeczne pieniądze',
['do_you_want_to_recruit'] = 'czy chcesz zrekrutować %s?',
['employee'] = 'pracownik',
['employee_list'] = 'lista pracowników',
['employee_management'] = 'zarządzanie pracownikami',
['fire'] = 'zwolnij',
['grade'] = 'stopień',
['have_deposited'] = 'zdeponowałeś ~r~$%s~s~',
['have_withdrawn'] = 'wypłaciłeś ~g~$%s~s~',
['invalid_amount'] = 'nieprawidłowa wartość',
['invalid_amount_max'] = 'that salary is not allowed',
['no'] = 'nie',
['promote'] = 'awansuj',
['promote_employee'] = 'awansuj %s',
['recruit'] = 'zrekrutuj',
['recruiting'] = 'rekrutacja',
['salary_amount'] = 'wartość wynagrodzenia',
['salary_management'] = 'zarządzaj wynagrodzeniem',
['wash_money'] = 'wypierz pieniądze',
['wash_money_amount'] = 'wartość do wyprania',
['withdraw_amount'] = 'wartość wypłaty',
['withdraw_society_money'] = 'wypłać społeczne pieniądze',
['yes'] = 'tak',
['you_have'] = 'masz ~g~%s$~s~ czekanie ~y~w pralni pieniędzmi~s~ (24h).',
['you_have_laundered'] = '~r~Wyprałeś~s~ twoje pieniądze: ~g~$%s~s~',
['you_have_hired'] = 'zatrudniłeś %s',
['you_have_been_hired'] = 'zostałeś zatrudniony przez %s',
['you_have_fired'] = 'zwolniłeś %s',
['you_have_been_fired'] = 'zostałeś zwolniony %s',
['you_have_promoted'] = 'awansowałeś %s na %s',
['you_have_been_promoted'] = 'zostałeś awansowany',
}
+37
View File
@@ -0,0 +1,37 @@
Translations= {
['actions'] = 'handlingar',
['boss_menu'] = 'chefmeny',
['money_generic'] = '%s SEK',
['deposit_amount'] = 'insättningsbelopp',
['deposit_society_money'] = 'insätt samhälls pengar',
['do_you_want_to_recruit'] = 'vill du anställa %s?',
['employee'] = 'anställd',
['employee_list'] = 'anställningslista',
['employee_management'] = 'medarbetarhantering',
['fire'] = 'sparka',
['grade'] = 'grade',
['have_deposited'] = 'du har satt in ~r~%s SEK~s~',
['have_withdrawn'] = 'du har tagit ut ~g~%s SEK~s~',
['invalid_amount'] = 'ogiltigt belopp',
['invalid_amount_max'] = 'den lönen är inte tillåten',
['no'] = 'nej',
['promote'] = 'befodra',
['promote_employee'] = 'befodra %s',
['recruit'] = 'rekrytera',
['recruiting'] = 'rekrytering',
['salary_amount'] = 'lön belopp',
['salary_management'] = 'lönhantering',
['wash_money'] = 'tvätta pengar',
['wash_money_amount'] = 'belopp att tvätta',
['withdraw_amount'] = 'Ta ut summan',
['withdraw_society_money'] = 'ta ut samhällspengar',
['yes'] = 'ja',
['you_have'] = 'du har ~g~%s SEK~s~ som väntar på ~y~pengartvätt~s~ (24h).',
['you_have_laundered'] = 'du har ~r~tvättat~s~ dina pengar: ~g~%s SEK~s~',
['you_have_hired'] = 'du har anställt ~y~%s~s~',
['you_have_been_hired'] = 'du har blivit anställd utav %s',
['you_have_fired'] = 'du har ~r~sparkat~s~ ~y~%s~s~',
['you_have_been_fired'] = 'du har blivit ~r~sparkad~s~ utav ~y~%s~s~',
['you_have_promoted'] = 'du har befodrat ~y~%s~s~ till ~b~%s~s~',
['you_have_been_promoted'] = 'du har blivit ~b~befodrad~s~',
}
+10
View File
@@ -0,0 +1,10 @@
USE `es_extended`;
CREATE TABLE IF NOT EXISTS `society_moneywash` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`identifier` varchar(60) NOT NULL,
`society` varchar(60) NOT NULL,
`amount` int(11) NOT NULL,
PRIMARY KEY (`id`)
);
+325
View File
@@ -0,0 +1,325 @@
local self = ESX.Modules['society']
AddEventHandler('esx:migrations:ensure', function(register)
register('society')
end)
AddEventHandler('esx_society:registerSociety', function(name, label, account, datastore, inventory, data)
local found = false
local society = {
name = name,
label = label,
account = account,
datastore = datastore,
inventory = inventory,
data = data
}
for i=1, #self.RegisteredSocieties, 1 do
if self.RegisteredSocieties[i].name == name then
found, self.RegisteredSocieties[i] = true, society
break
end
end
if not found then
table.insert(self.RegisteredSocieties, society)
end
end)
AddEventHandler('esx_society:getSocieties', function(cb)
cb(self.RegisteredSocieties)
end)
AddEventHandler('esx_society:getSociety', function(name, cb)
cb(self.GetSociety(name))
end)
RegisterServerEvent('esx_society:withdrawMoney')
AddEventHandler('esx_society:withdrawMoney', function(societyName, amount)
local xPlayer = ESX.GetPlayerFromId(source)
local society = self.GetSociety(societyName)
amount = ESX.Math.Round(tonumber(amount))
if xPlayer.job.name == society.name then
TriggerEvent('esx_addonaccount:getSharedAccount', society.account, function(account)
if amount > 0 and account.money >= amount then
account.removeMoney(amount)
xPlayer.addMoney(amount)
xPlayer.showNotification(_U('society:have_withdrawn', ESX.Math.GroupDigits(amount)))
else
xPlayer.showNotification(_U('society:invalid_amount'))
end
end)
else
print(('esx_society: %s attempted to call withdrawMoney!'):format(xPlayer.identifier))
end
end)
RegisterServerEvent('esx_society:depositMoney')
AddEventHandler('esx_society:depositMoney', function(societyName, amount)
local xPlayer = ESX.GetPlayerFromId(source)
local society = self.GetSociety(societyName)
amount = ESX.Math.Round(tonumber(amount))
if xPlayer.job.name == society.name then
if amount > 0 and xPlayer.getMoney() >= amount then
TriggerEvent('esx_addonaccount:getSharedAccount', society.account, function(account)
xPlayer.removeMoney(amount)
xPlayer.showNotification(_U('society:have_deposited', ESX.Math.GroupDigits(amount)))
account.addMoney(amount)
end)
else
xPlayer.showNotification(_U('society:invalid_amount'))
end
else
print(('esx_society: %s attempted to call depositMoney!'):format(xPlayer.identifier))
end
end)
RegisterServerEvent('esx_society:washMoney')
AddEventHandler('esx_society:washMoney', function(society, amount)
local xPlayer = ESX.GetPlayerFromId(source)
local account = xPlayer.getAccount('black_money')
amount = ESX.Math.Round(tonumber(amount))
if xPlayer.job.name == society then
if amount and amount > 0 and account.money >= amount then
xPlayer.removeAccountMoney('black_money', amount)
MySQL.Async.execute('INSERT INTO society_moneywash (identifier, society, amount) VALUES (@identifier, @society, @amount)', {
['@identifier'] = xPlayer.identifier,
['@society'] = society,
['@amount'] = amount
}, function(rowsChanged)
xPlayer.showNotification(_U('society:you_have', ESX.Math.GroupDigits(amount)))
end)
else
xPlayer.showNotification(_U('society:invalid_amount'))
end
else
print(('esx_society: %s attempted to call washMoney!'):format(xPlayer.identifier))
end
end)
RegisterServerEvent('esx_society:putVehicleInGarage')
AddEventHandler('esx_society:putVehicleInGarage', function(societyName, vehicle)
local society = self.GetSociety(societyName)
TriggerEvent('esx_datastore:getSharedDataStore', society.datastore, function(store)
local garage = store.get('garage') or {}
table.insert(garage, vehicle)
store.set('garage', garage)
end)
end)
RegisterServerEvent('esx_society:removeVehicleFromGarage')
AddEventHandler('esx_society:removeVehicleFromGarage', function(societyName, vehicle)
local society = self.GetSociety(societyName)
TriggerEvent('esx_datastore:getSharedDataStore', society.datastore, function(store)
local garage = store.get('garage') or {}
for i=1, #garage, 1 do
if garage[i].plate == vehicle.plate then
table.remove(garage, i)
break
end
end
store.set('garage', garage)
end)
end)
ESX.RegisterServerCallback('esx_society:getSocietyMoney', function(source, cb, societyName)
local society = self.GetSociety(societyName)
if society then
TriggerEvent('esx_addonaccount:getSharedAccount', society.account, function(account)
cb(account.money)
end)
else
cb(0)
end
end)
ESX.RegisterServerCallback('esx_society:getEmployees', function(source, cb, society)
if Config.EnableESXIdentity then
MySQL.Async.fetchAll('SELECT firstname, lastname, identifier, job, job_grade FROM users WHERE job = @job ORDER BY job_grade DESC', {
['@job'] = society
}, function(results)
local employees = {}
for i=1, #results, 1 do
table.insert(employees, {
name = results[i].firstname .. ' ' .. results[i].lastname,
identifier = results[i].identifier,
job = {
name = results[i].job,
label = self.Jobs[results[i].job].label,
grade = results[i].job_grade,
grade_name = self.Jobs[results[i].job].grades[tostring(results[i].job_grade)].name,
grade_label = self.Jobs[results[i].job].grades[tostring(results[i].job_grade)].label
}
})
end
cb(employees)
end)
else
MySQL.Async.fetchAll('SELECT name, identifier, job, job_grade FROM users WHERE job = @job ORDER BY job_grade DESC', {
['@job'] = society
}, function(result)
local employees = {}
for i=1, #result, 1 do
table.insert(employees, {
name = result[i].name,
identifier = result[i].identifier,
job = {
name = result[i].job,
label = self.Jobs[result[i].job].label,
grade = result[i].job_grade,
grade_name = self.Jobs[result[i].job].grades[tostring(result[i].job_grade)].name,
grade_label = self.Jobs[result[i].job].grades[tostring(result[i].job_grade)].label
}
})
end
cb(employees)
end)
end
end)
ESX.RegisterServerCallback('esx_society:getJob', function(source, cb, society)
local job = json.decode(json.encode(self.Jobs[society]))
local grades = {}
for k,v in pairs(job.grades) do
table.insert(grades, v)
end
table.sort(grades, function(a, b)
return a.grade < b.grade
end)
job.grades = grades
cb(job)
end)
ESX.RegisterServerCallback('esx_society:setJob', function(source, cb, identifier, job, grade, type)
local xPlayer = ESX.GetPlayerFromId(source)
local isBoss = xPlayer.job.grade_name == 'boss'
if isBoss then
local xTarget = ESX.GetPlayerFromIdentifier(identifier)
if xTarget then
xTarget.setJob(job, grade)
if type == 'hire' then
xTarget.showNotification(_U('society:you_have_been_hired', job))
elseif type == 'promote' then
xTarget.showNotification(_U('society:you_have_been_promoted'))
elseif type == 'fire' then
xTarget.showNotification(_U('society:you_have_been_fired', xTarget.getJob().label))
end
cb()
else
MySQL.Async.execute('UPDATE users SET job = @job, job_grade = @job_grade WHERE identifier = @identifier', {
['@job'] = job,
['@job_grade'] = grade,
['@identifier'] = identifier
}, function(rowsChanged)
cb()
end)
end
else
print(('esx_society: %s attempted to setJob'):format(xPlayer.identifier))
cb()
end
end)
ESX.RegisterServerCallback('esx_society:setJobSalary', function(source, cb, job, grade, salary)
local xPlayer = ESX.GetPlayerFromId(source)
if xPlayer.job.name == job and xPlayer.job.grade_name == 'boss' then
if salary <= Config.MaxSalary then
MySQL.Async.execute('UPDATE job_grades SET salary = @salary WHERE job_name = @job_name AND grade = @grade', {
['@salary'] = salary,
['@job_name'] = job,
['@grade'] = grade
}, function(rowsChanged)
self.Jobs[job].grades[tostring(grade)].salary = salary
local xPlayers = ESX.GetPlayers()
for i=1, #xPlayers, 1 do
local xTarget = ESX.GetPlayerFromId(xPlayers[i])
if xTarget.job.name == job and xTarget.job.grade == grade then
xTarget.setJob(job, grade)
end
end
cb()
end)
else
print(('esx_society: %s attempted to setJobSalary over config limit!'):format(xPlayer.identifier))
cb()
end
else
print(('esx_society: %s attempted to setJobSalary'):format(xPlayer.identifier))
cb()
end
end)
ESX.RegisterServerCallback('esx_society:getOnlinePlayers', function(source, cb)
local xPlayers = ESX.GetPlayers()
local players = {}
for i=1, #xPlayers, 1 do
local xPlayer = ESX.GetPlayerFromId(xPlayers[i])
table.insert(players, {
source = xPlayer.source,
identifier = xPlayer.identifier,
name = xPlayer.name,
job = xPlayer.job
})
end
cb(players)
end)
ESX.RegisterServerCallback('esx_society:getVehiclesInGarage', function(source, cb, societyName)
local society = self.GetSociety(societyName)
TriggerEvent('esx_datastore:getSharedDataStore', society.datastore, function(store)
local garage = store.get('garage') or {}
cb(garage)
end)
end)
ESX.RegisterServerCallback('esx_society:isBoss', function(source, cb, job)
cb(isPlayerBoss(source, job))
end)
MySQL.ready(function()
local result = MySQL.Sync.fetchAll('SELECT * FROM jobs', {})
for i=1, #result, 1 do
self.Jobs[result[i].name] = result[i]
self.Jobs[result[i].name].grades = {}
end
local result2 = MySQL.Sync.fetchAll('SELECT * FROM job_grades', {})
for i=1, #result2, 1 do
self.Jobs[result2[i].job_name].grades[tostring(result2[i].grade)] = result2[i]
end
end)
+5
View File
@@ -0,0 +1,5 @@
local self = ESX.Modules['society']
self.Init()
TriggerEvent('cron:runAt', 3, 0, self.WashMoneyCRON)
+56
View File
@@ -0,0 +1,56 @@
ESX.Modules['society'] = {}
local self = ESX.Modules['society']
self.Jobs = {}
self.RegisteredSocieties = {}
self.Init = function()
local translations = ESX.EvalFile(GetCurrentResourceName(), 'modules/society/data/locales/' .. Config.Locale .. '.lua')['Translations']
LoadLocale('society', Config.Locale, translations)
end
self.GetSociety = function(name)
for i=1, #self.RegisteredSocieties, 1 do
if self.RegisteredSocieties[i].name == name then
return self.RegisteredSocieties[i]
end
end
end
self.isPlayerBoss = function(playerId, job)
local xPlayer = ESX.GetPlayerFromId(playerId)
if xPlayer.job.name == job and xPlayer.job.grade_name == 'boss' then
return true
else
print(('esx_society: %s attempted open a society boss menu!'):format(xPlayer.identifier))
return false
end
end
self.WashMoneyCRON = function(d, h, m)
MySQL.Async.fetchAll('SELECT * FROM society_moneywash', {}, function(result)
for i=1, #result, 1 do
local society = self.GetSociety(result[i].society)
local xPlayer = ESX.GetPlayerFromIdentifier(result[i].identifier)
-- add society money
TriggerEvent('esx_addonaccount:getSharedAccount', society.account, function(account)
account.addMoney(result[i].amount)
end)
-- send notification if player is online
if xPlayer then
xPlayer.showNotification(_U('society:you_have_laundered', ESX.Math.GroupDigits(result[i].amount)))
end
MySQL.Async.execute('DELETE FROM society_moneywash WHERE id = @id', {
['@id'] = result[i].id
})
end
end)
end