Skip to content

Commit

Permalink
Merge pull request #25 from Tiziukas/main
Browse files Browse the repository at this point in the history
refactor: Improve readability and use best practices for optimisation.
  • Loading branch information
Arctos2win authored Dec 24, 2024
2 parents 270e54b + 301e1ca commit efa1595
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 145 deletions.
183 changes: 82 additions & 101 deletions client/main.lua
Original file line number Diff line number Diff line change
@@ -1,131 +1,112 @@
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
setPlayerNeeds(500000, 500000)
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', 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', function(propName)
warnDeprecated('esx_basicneeds:onEat', 'food', propName or 'prop_cs_burger_01')
end)

AddEventHandler('esx_basicneeds:onDrink', function(propName)
warnDeprecated('esx_basicneeds:onDrink', 'drink', propName or 'prop_ld_flow_bottle')
end)
33 changes: 18 additions & 15 deletions config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
73 changes: 44 additions & 29 deletions server/main.lua
Original file line number Diff line number Diff line change
@@ -1,36 +1,51 @@
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 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,
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)

0 comments on commit efa1595

Please sign in to comment.