From 33f7dd8274ba9415734c3983c82c61ccd6360846 Mon Sep 17 00:00:00 2001 From: Tizas <141794006+Tiziukas@users.noreply.github.com> Date: Tue, 24 Dec 2024 09:48:29 +0000 Subject: [PATCH 1/4] refactor: Improve readability and use best practices for optimisation. This introduces the code with a lot of improved readability and also keeping a consistent indentation. --- client/main.lua | 186 ++++++++++++++++++++++-------------------------- config.lua | 33 +++++---- server/main.lua | 74 +++++++++++-------- 3 files changed, 148 insertions(+), 145 deletions(-) diff --git a/client/main.lua b/client/main.lua index aa36768..8bc5de1 100644 --- a/client/main.lua +++ b/client/main.lua @@ -1,131 +1,115 @@ local IsDead = false local IsAnimated = false +local function setPlayerNeeds(hunger, thirst) + TriggerEvent('esx_status:set', 'hunger', hunger) + TriggerEvent('esx_status:set', 'thirst', thirst) +end + AddEventHandler('esx_basicneeds:resetStatus', function() - TriggerEvent('esx_status:set', 'hunger', 500000) - TriggerEvent('esx_status:set', 'thirst', 500000) + setPlayerNeeds(500000, 500000) end) + RegisterNetEvent('esx_basicneeds:healPlayer') AddEventHandler('esx_basicneeds:healPlayer', function() - -- restore hunger & thirst - TriggerEvent('esx_status:set', 'hunger', 1000000) - TriggerEvent('esx_status:set', 'thirst', 1000000) + setPlayerNeeds(1000000, 1000000) - -- restore hp - local playerPed = PlayerPedId() - SetEntityHealth(playerPed, GetEntityMaxHealth(playerPed)) + local playerPed = PlayerPedId() + SetEntityHealth(playerPed, GetEntityMaxHealth(playerPed)) end) AddEventHandler('esx:onPlayerDeath', function() - IsDead = true + IsDead = true end) -AddEventHandler('esx:onPlayerSpawn', function(spawn) - if IsDead then - TriggerEvent('esx_basicneeds:resetStatus') - end - - IsDead = false +AddEventHandler('esx:onPlayerSpawn', function() + if IsDead then + TriggerEvent('esx_basicneeds:resetStatus') + end + IsDead = false end) -AddEventHandler('esx_status:loaded', function(status) - TriggerEvent('esx_status:registerStatus', 'hunger', 1000000, '#CFAD0F', function(status) - return Config.Visible - end, function(status) - status.remove(100) - end) - - TriggerEvent('esx_status:registerStatus', 'thirst', 1000000, '#0C98F1', function(status) - return Config.Visible - end, function(status) - status.remove(75) - end) -end) +AddEventHandler('esx_status:loaded', function() + local function registerStatus(name, color, removalRate) + TriggerEvent('esx_status:registerStatus', name, 1000000, color, + function() return Config.Visible end, + function(status) status.remove(removalRate) end + ) + end -AddEventHandler('esx_status:onTick', function(data) - local playerPed = PlayerPedId() - local prevHealth = GetEntityHealth(playerPed) - local health = prevHealth - - for k, v in pairs(data) do - if v.name == 'hunger' and v.percent == 0 then - if prevHealth <= 150 then - health = health - 5 - else - health = health - 1 - end - elseif v.name == 'thirst' and v.percent == 0 then - if prevHealth <= 150 then - health = health - 5 - else - health = health - 1 - end - end - end - - if health ~= prevHealth then SetEntityHealth(playerPed, health) end + registerStatus('hunger', '#CFAD0F', 100) + registerStatus('thirst', '#0C98F1', 75) end) -AddEventHandler('esx_basicneeds:isEating', function(cb) - cb(IsAnimated) +AddEventHandler('esx_status:onTick', function(statuses) + local playerPed = PlayerPedId() + local prevHealth = GetEntityHealth(playerPed) + local newHealth = prevHealth + + for _, status in pairs(statuses) do + if status.percent == 0 then + local damage = (prevHealth <= 150) and 5 or 1 + if status.name == 'hunger' or status.name == 'thirst' then + newHealth = newHealth - damage + end + end + end + + if newHealth ~= prevHealth then + SetEntityHealth(playerPed, newHealth) + end end) -RegisterNetEvent('esx_basicneeds:onUse') -AddEventHandler('esx_basicneeds:onUse', function(type, prop_name, anim) - if not IsAnimated then - local anim = anim - IsAnimated = true - if type == 'food' then - prop_name = prop_name or 'prop_cs_burger_01' - anim = anim - elseif type == 'drink' then - prop_name = prop_name or 'prop_ld_flow_bottle' - anim = anim - end - - CreateThread(function() - local playerPed = PlayerPedId() - local x,y,z = table.unpack(GetEntityCoords(playerPed)) - local prop = CreateObject(joaat(prop_name), x, y, z + 0.2, true, true, true) - local boneIndex = GetPedBoneIndex(playerPed, 18905) - AttachEntityToEntity(prop, playerPed, boneIndex, 0.12, 0.028, 0.001, 10.0, 175.0, 0.0, true, true, false, true, 1, true) - - ESX.Streaming.RequestAnimDict(anim.dict, function() - TaskPlayAnim(playerPed, anim.dict, anim.name, anim.settings[1], anim.settings[2], anim.settings[3], anim.settings[4], anim.settings[5], anim.settings[6], anim.settings[7], anim.settings[8]) - RemoveAnimDict(anim.dict) - - Wait(3000) - IsAnimated = false - ClearPedSecondaryTask(playerPed) - DeleteObject(prop) - end) - end) - end +AddEventHandler('esx_basicneeds:isEating', function(callback) + callback(IsAnimated) end) --- Backwards compatibility -RegisterNetEvent('esx_basicneeds:onEat') -AddEventHandler('esx_basicneeds:onEat', function(prop_name) - local Invoke = GetInvokingResource() +local function handleAnimation(itemType, propName, anim, pos, rot) + if IsAnimated then return end - print(('[^3WARNING^7] ^5%s^7 used ^5esx_basicneeds:onEat^7, this method is deprecated and should not be used! Refer to ^5https://documentation.esx-framework.org/addons/esx_basicneeds/events/oneat^7 for more info!'):format(Invoke)) + IsAnimated = true + local playerPed = PlayerPedId() + local x, y, z = table.unpack(GetEntityCoords(playerPed)) + local prop = CreateObject(joaat(propName), x, y, z + 0.2, true, true, true) + local boneIndex = GetPedBoneIndex(playerPed, 18905) - if not prop_name then - prop_name = 'prop_cs_burger_01' - end - TriggerEvent('esx_basicneeds:onUse', 'food', prop_name) -end) + pos = pos or vector3(0.12, 0.028, 0.001) + rot = rot or vector3(10.0, 175.0, 0.0) -RegisterNetEvent('esx_basicneeds:onDrink') -AddEventHandler('esx_basicneeds:onDrink', function(prop_name) - local Invoke = GetInvokingResource() + AttachEntityToEntity(prop, playerPed, boneIndex, pos.x, pos.y, pos.z, rot.x, rot.y, rot.z, true, true, false, true, 1, true) - print(('[^3WARNING^7] ^5%s^7 used ^5esx_basicneeds:onDrink^7, this method is deprecated and should not be used! Refer to ^5https://documentation.esx-framework.org/addons/esx_basicneeds/events/ondrink^7 for more info!'):format(Invoke)) + CreateThread(function() + ESX.Streaming.RequestAnimDict(anim.dict, function() + TaskPlayAnim(playerPed, anim.dict, anim.name, table.unpack(anim.settings)) + RemoveAnimDict(anim.dict) + Wait(3000) + IsAnimated = false + ClearPedSecondaryTask(playerPed) + DeleteObject(prop) + end) + end) +end - if not prop_name then - prop_name = 'prop_ld_flow_bottle' - end - TriggerEvent('esx_basicneeds:onUse', 'drink', prop_name) +RegisterNetEvent('esx_basicneeds:onUse') +AddEventHandler('esx_basicneeds:onUse', function(itemType, propName, anim, pos, rot) + propName = propName or (itemType == 'food' and 'prop_cs_burger_01' or 'prop_ld_flow_bottle') + handleAnimation(itemType, propName, anim, pos, rot) +end) + +local function warnDeprecated(eventName, itemType, propName) + local invokingResource = GetInvokingResource() + print(('[^3WARNING^7] ^5%s^7 used ^5%s^7, which is deprecated. Refer to ESX documentation for updates.'):format(invokingResource, eventName)) + TriggerEvent('esx_basicneeds:onUse', itemType, propName) +end + +RegisterNetEvent('esx_basicneeds:onEat') +AddEventHandler('esx_basicneeds:onEat', function(propName) + warnDeprecated('esx_basicneeds:onEat', 'food', propName or 'prop_cs_burger_01') +end) + +RegisterNetEvent('esx_basicneeds:onDrink') +AddEventHandler('esx_basicneeds:onDrink', function(propName) + warnDeprecated('esx_basicneeds:onDrink', 'drink', propName or 'prop_ld_flow_bottle') end) diff --git a/config.lua b/config.lua index 9a380a6..264f142 100644 --- a/config.lua +++ b/config.lua @@ -3,19 +3,22 @@ Config.Locale = GetConvar('esx:locale', 'en') Config.Visible = true Config.Items = { - ["bread"] = { - type = "food", - prop = "prop_cs_burger_01", - status = 200000, - remove = true, - anim = {dict = 'mp_player_inteat@burger', name = 'mp_player_int_eat_burger_fp', settings = {8.0, -8, -1, 49, 0, 0, 0, 0}} - }, - - ["water"] = { - type = "drink", - prop = "prop_ld_flow_bottle", - status = 100000, - remove = true, - anim = {dict = 'mp_player_intdrink', name = 'loop_bottle', settings = {1.0, -1.0, 2000, 0, 1, true, true, true}} - } + ["bread"] = { + type = "food", + prop = "prop_cs_burger_01", + status = 200000, + remove = true, + anim = {dict = 'mp_player_inteat@burger', name = 'mp_player_int_eat_burger_fp', settings = {8.0, -8, -1, 49, 0, 0, 0, 0}}, + pos = vector3(0.15, 0.03, 0.0), + rot = vector3(15.0, 175.0, 5.0) + }, + ["water"] = { + type = "drink", + prop = "prop_ld_flow_bottle", + status = 100000, + remove = true, + anim = {dict = 'mp_player_intdrink', name = 'loop_bottle', settings = {1.0, -1.0, 2000, 0, 1, true, true, true}}, + pos = vector3(0.12, 0.028, 0.001), + rot = vector3(10.0, 175.0, 0.0) + } } diff --git a/server/main.lua b/server/main.lua index bbce9f7..ac427d7 100644 --- a/server/main.lua +++ b/server/main.lua @@ -1,36 +1,52 @@ +local function handleItemUsage(itemName, itemConfig, source) + local xPlayer = ESX.GetPlayerFromId(source) + if itemConfig.remove then + xPlayer.removeInventoryItem(itemName, 1) + end + + local statusType, notificationMessage + if itemConfig.type == "food" then + statusType = "hunger" + notificationMessage = TranslateCap('used_food', ESX.GetItemLabel(itemName)) + elseif itemConfig.type == "drink" then + statusType = "thirst" + notificationMessage = TranslateCap('used_drink', ESX.GetItemLabel(itemName)) + else + print(string.format('^1[ERROR]^0 Item "%s" has an invalid type defined.', itemName)) + return + end + + TriggerClientEvent("esx_status:add", source, statusType, itemConfig.status) + TriggerClientEvent('esx_basicneeds:onUse', source, itemConfig.type, itemConfig.prop, itemConfig.anim, itemConfig.pos, itemConfig.rot) + xPlayer.showNotification(notificationMessage) +end + CreateThread(function() - for k,v in pairs(Config.Items) do - ESX.RegisterUsableItem(k, function(source) - local xPlayer = ESX.GetPlayerFromId(source) - if v.remove then - xPlayer.removeInventoryItem(k,1) - end - if v.type == "food" then - TriggerClientEvent("esx_status:add", source, "hunger", v.status) - TriggerClientEvent('esx_basicneeds:onUse', source, v.type, v.prop, v.anim) - xPlayer.showNotification(TranslateCap('used_food', ESX.GetItemLabel(k))) - elseif v.type == "drink" then - TriggerClientEvent("esx_status:add", source, "thirst", v.status) - TriggerClientEvent('esx_basicneeds:onUse', source, v.type, v.prop, v.anim) - xPlayer.showNotification(TranslateCap('used_drink', ESX.GetItemLabel(k))) - else - print(string.format('^1[ERROR]^0 %s has no correct type defined.', k)) - end - end) - end + for itemName, itemConfig in pairs(Config.Items) do + ESX.RegisterUsableItem(itemName, function(source) + handleItemUsage(itemName, itemConfig, source) + end) + end end) ESX.RegisterCommand('heal', 'admin', function(xPlayer, args, showError) - args.playerId.triggerEvent('esx_basicneeds:healPlayer') - args.playerId.showNotification(TranslateCap('got_healed')) -end, true, {help = 'Heal a player, or yourself - restores thirst, hunger and health.', validate = true, arguments = { - {name = 'playerId', help = 'the player id', type = 'player'} -}}) + if args.playerId then + args.playerId.triggerEvent('esx_basicneeds:healPlayer') + args.playerId.showNotification(TranslateCap('got_healed')) + else + showError("Player ID is required.") + end +end, true, { + help = 'Heal a player, or yourself - restores thirst, hunger, and health.', + validate = true, + arguments = { + {name = 'playerId', help = 'The player ID', type = 'player'} + } +}) AddEventHandler('txAdmin:events:healedPlayer', function(eventData) - if GetInvokingResource() ~= "monitor" or type(eventData) ~= "table" or type(eventData.id) ~= "number" then - return - end - - TriggerClientEvent('esx_basicneeds:healPlayer', eventData.id) + if GetInvokingResource() ~= "monitor" or type(eventData) ~= "table" or type(eventData.id) ~= "number" then + return + end + TriggerClientEvent('esx_basicneeds:healPlayer', eventData.id) end) From 9886e5d3bb573470cb0946a9e855a65d5b052b21 Mon Sep 17 00:00:00 2001 From: Tizas <141794006+Tiziukas@users.noreply.github.com> Date: Tue, 24 Dec 2024 09:59:57 +0000 Subject: [PATCH 2/4] replace event for function --- client/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/main.lua b/client/main.lua index 8bc5de1..cc7de1a 100644 --- a/client/main.lua +++ b/client/main.lua @@ -25,7 +25,7 @@ end) AddEventHandler('esx:onPlayerSpawn', function() if IsDead then - TriggerEvent('esx_basicneeds:resetStatus') + setPlayerNeeds(500000, 500000) end IsDead = false end) From 1af5bd7fa382233ca641c4f51681536f0b5460c1 Mon Sep 17 00:00:00 2001 From: Tizas <141794006+Tiziukas@users.noreply.github.com> Date: Tue, 24 Dec 2024 12:52:24 +0000 Subject: [PATCH 3/4] Resolve Changes --- client/main.lua | 4 +--- server/main.lua | 9 ++++----- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/client/main.lua b/client/main.lua index cc7de1a..3f2cad1 100644 --- a/client/main.lua +++ b/client/main.lua @@ -104,12 +104,10 @@ local function warnDeprecated(eventName, itemType, propName) TriggerEvent('esx_basicneeds:onUse', itemType, propName) end -RegisterNetEvent('esx_basicneeds:onEat') -AddEventHandler('esx_basicneeds:onEat', function(propName) +RegisterNetEvent('esx_basicneeds:onEat', function(propName) warnDeprecated('esx_basicneeds:onEat', 'food', propName or 'prop_cs_burger_01') end) -RegisterNetEvent('esx_basicneeds:onDrink') AddEventHandler('esx_basicneeds:onDrink', function(propName) warnDeprecated('esx_basicneeds:onDrink', 'drink', propName or 'prop_ld_flow_bottle') end) diff --git a/server/main.lua b/server/main.lua index ac427d7..42012af 100644 --- a/server/main.lua +++ b/server/main.lua @@ -30,12 +30,11 @@ CreateThread(function() end) ESX.RegisterCommand('heal', 'admin', function(xPlayer, args, showError) - if args.playerId then - args.playerId.triggerEvent('esx_basicneeds:healPlayer') - args.playerId.showNotification(TranslateCap('got_healed')) - else - showError("Player ID is required.") + if not args.playerId then + return showError("Player ID is required") end + args.playerId.triggerEvent('esx_basicneeds:healPlayer') + args.playerId.showNotification(TranslateCap('got_healed')) end, true, { help = 'Heal a player, or yourself - restores thirst, hunger, and health.', validate = true, From 301e1ca90f18fc3c47669223091544bbf9720b4c Mon Sep 17 00:00:00 2001 From: Tizas <141794006+Tiziukas@users.noreply.github.com> Date: Tue, 24 Dec 2024 13:20:02 +0000 Subject: [PATCH 4/4] Update main.lua --- client/main.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/main.lua b/client/main.lua index 3f2cad1..0b6bf1e 100644 --- a/client/main.lua +++ b/client/main.lua @@ -92,8 +92,7 @@ local function handleAnimation(itemType, propName, anim, pos, rot) end) end -RegisterNetEvent('esx_basicneeds:onUse') -AddEventHandler('esx_basicneeds:onUse', function(itemType, propName, anim, pos, rot) +RegisterNetEvent('esx_basicneeds:onUse', function(itemType, propName, anim, pos, rot) propName = propName or (itemType == 'food' and 'prop_cs_burger_01' or 'prop_ld_flow_bottle') handleAnimation(itemType, propName, anim, pos, rot) end)