Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add better multiple hospital support + some refactors #299

Merged
merged 12 commits into from
Mar 18, 2024
240 changes: 121 additions & 119 deletions client/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ local canLeaveBed = true
local bedOccupying = nil
local bedObject = nil
local bedOccupyingData = nil
local closestBed = nil
local doctorCount = 0
local CurrentDamageList = {}
local cam = nil
local playerArmor = nil
local hospitalLocation = 1
inBedDict = 'anim@gangops@morgue@table@'
inBedAnim = 'body_search'
isInHospitalBed = false
Expand Down Expand Up @@ -49,25 +49,20 @@ BodyParts = {

-- Functions

local function GetAvailableBed(bedId)
local pos = GetEntityCoords(PlayerPedId())
local retval = nil
if bedId == nil then
for k, _ in pairs(Config.Locations['beds']) do
if not Config.Locations['beds'][k].taken then
if #(pos - vector3(Config.Locations['beds'][k].coords.x, Config.Locations['beds'][k].coords.y, Config.Locations['beds'][k].coords.z)) < 500 then
retval = k
end
end
end
else
if not Config.Locations['beds'][bedId].taken then
if #(pos - vector3(Config.Locations['beds'][bedId].coords.x, Config.Locations['beds'][bedId].coords.y, Config.Locations['beds'][bedId].coords.z)) < 500 then
retval = bedId
end
-- Gets a bed at the given hospital that is not taken.
-- If all beds are taken it will just place them in the first bed
local function getClosestAvailableBed(hospitalIndex)
local hospital = Config.Locations['hospital'][hospitalIndex]

-- Loop through beds at this hospital and find the first non taken bed
for bedId, bed in pairs(hospital.beds) do
local isBedTaken = bed.taken
if not isBedTaken then
return bedId
end
end
return retval

return 1 -- default to the first bed
end

local function GetDamagingWeapon(ped)
Expand Down Expand Up @@ -123,27 +118,6 @@ local function ApplyBleed(level)
end
end

local function SetClosestBed()
local pos = GetEntityCoords(PlayerPedId(), true)
local current = nil
local dist = nil
for k, _ in pairs(Config.Locations['beds']) do
local dist2 = #(pos - vector3(Config.Locations['beds'][k].coords.x, Config.Locations['beds'][k].coords.y, Config.Locations['beds'][k].coords.z))
if current then
if dist2 < dist then
current = k
dist = dist2
end
else
dist = dist2
current = k
end
end
if current ~= closestBed and not isInHospitalBed then
closestBed = current
end
end

local function IsInjuryCausingLimp()
for _, v in pairs(BodyParts) do
if v.causeLimp and v.isDamaged then
Expand Down Expand Up @@ -265,7 +239,7 @@ local function SetBedCam()
FreezeEntityPosition(bedObject, true)

SetEntityCoords(player, bedOccupyingData.coords.x, bedOccupyingData.coords.y, bedOccupyingData.coords.z + 0.02)
--SetEntityInvincible(PlayerPedId(), true)

Wait(500)
FreezeEntityPosition(player, true)

Expand Down Expand Up @@ -303,7 +277,7 @@ local function LeaveBed()
TaskPlayAnim(player, getOutDict, getOutAnim, 100.0, 1.0, -1, 8, -1, 0, 0, 0)
Wait(4000)
ClearPedTasks(player)
TriggerServerEvent('hospital:server:LeaveBed', bedOccupying)
TriggerServerEvent('hospital:server:LeaveBed', bedOccupying, hospitalLocation)
FreezeEntityPosition(bedObject, true)
RenderScriptCams(0, true, 200, true, true)
DestroyCam(cam, false)
Expand Down Expand Up @@ -653,31 +627,33 @@ RegisterNetEvent('hospital:client:SendToBed', function(id, data, isRevive)
end)
end)

RegisterNetEvent('hospital:client:SetBed', function(id, isTaken)
Config.Locations['beds'][id].taken = isTaken
RegisterNetEvent('hospital:client:SetBed', function(id, isTaken, hospitalIndex)
Config.Locations['hospital'][hospitalIndex]['beds'][id].taken = isTaken
hospitalLocation = hospitalIndex
end)

RegisterNetEvent('hospital:client:SetBed2', function(id, isTaken)
Config.Locations['jailbeds'][id].taken = isTaken
end)

RegisterNetEvent('hospital:client:RespawnAtHospital', function()
TriggerServerEvent('hospital:server:RespawnAtHospital')
local hospitalIndex = 1 -- Default hospital to respawn at
TriggerServerEvent('hospital:server:RespawnAtHospital', hospitalIndex)
if exports['qb-policejob']:IsHandcuffed() then
TriggerEvent('police:client:GetCuffed', -1)
end
TriggerEvent('police:client:DeEscort')
end)

RegisterNetEvent('hospital:client:SendBillEmail', function(amount)
RegisterNetEvent('hospital:client:SendBillEmail', function(amount, hospitalName)
SetTimeout(math.random(2500, 4000), function()
local gender = Lang:t('info.mr')
if QBCore.Functions.GetPlayerData().charinfo.gender == 1 then
gender = Lang:t('info.mrs')
end
local charinfo = QBCore.Functions.GetPlayerData().charinfo
TriggerServerEvent('qb-phone:server:sendNewMail', {
sender = Lang:t('mail.sender'),
sender = hospitalName,
subject = Lang:t('mail.subject'),
message = Lang:t('mail.message', { gender = gender, lastname = charinfo.lastname, costs = amount }),
button = {}
Expand All @@ -701,7 +677,7 @@ RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
TriggerServerEvent('hospital:server:SetLaststandStatus', false)
TriggerServerEvent('hospital:server:SetArmor', GetPedArmour(ped))
if bedOccupying then
TriggerServerEvent('hospital:server:LeaveBed', bedOccupying)
TriggerServerEvent('hospital:server:LeaveBed', bedOccupying, hospitalLocation)
end
isDead = false
deathTime = 0
Expand Down Expand Up @@ -751,7 +727,6 @@ end)
CreateThread(function()
while true do
Wait(1000)
SetClosestBed()
if isStatusChecking then
statusCheckTime = statusCheckTime - 1
if statusCheckTime <= 0 then
Expand Down Expand Up @@ -827,7 +802,9 @@ CreateThread(function()
end)

local listen = false
local function CheckInControls(variable)
-- variable - 'checkin' or 'beds'
-- hospitalIndex - index referring to the key of the hospital key/value pairs
local function CheckInControls(variable, hospitalIndex, bedId)
CreateThread(function()
listen = true
while listen do
Expand All @@ -837,7 +814,7 @@ local function CheckInControls(variable)
TriggerEvent('qb-ambulancejob:checkin')
listen = false
elseif variable == 'beds' then
TriggerEvent('qb-ambulancejob:beds')
TriggerEvent('qb-ambulancejob:beds', hospitalIndex, bedId)
listen = false
end
end
Expand All @@ -847,44 +824,61 @@ local function CheckInControls(variable)
end

RegisterNetEvent('qb-ambulancejob:checkin', function()
if doctorCount >= Config.MinimalDoctors then
TriggerServerEvent('hospital:server:SendDoctorAlert')
else
QBCore.Functions.Progressbar('hospital_checkin', Lang:t('progress.checking_in'), 2000, false, true, {
disableMovement = true,
disableCarMovement = true,
disableMouse = false,
disableCombat = true,
}, {
animDict = 'missheistdockssetup1clipboard@base',
anim = 'base',
flags = 33,
}, {
model = 'prop_notepad_01',
bone = 18905,
coords = { x = 0.1, y = 0.02, z = 0.05 },
rotation = { x = 10.0, y = 0.0, z = 0.0 },
}, {
model = 'prop_pencil_01',
bone = 58866,
coords = { x = 0.11, y = -0.02, z = 0.001 },
rotation = { x = -120.0, y = 0.0, z = 0.0 },
}, function() -- Done
local bedId = GetAvailableBed()
if bedId then
TriggerServerEvent('hospital:server:SendToBed', bedId, true)
local coords = GetEntityCoords(PlayerPedId())

-- Support for figuring out which hospital to check the player into
for k,_ in pairs(Config.Locations['hospital']) do
local hospital = vector3(Config.Locations['hospital'][k]['location'].x, Config.Locations['hospital'][k]['location'].y, Config.Locations['hospital'][k]['location'].z)
local distance = #(coords - hospital)
-- Check if the player is close enough to hospital checkin location
if distance < 3 then
if doctorCount >= Config.MinimalDoctors then
TriggerServerEvent('hospital:server:SendDoctorAlert', Config.Locations['hospital'][k]['name'])
QBCore.Functions.Notify('Called a Doctor', 'primary')
else
QBCore.Functions.Notify(Lang:t('error.beds_taken'), 'error')
TriggerEvent('animations:client:EmoteCommandStart', {'notepad'})
QBCore.Functions.Progressbar('hospital_checkin', Lang:t('progress.checking_in'), 2000, false, true, {
disableMovement = true,
disableCarMovement = true,
disableMouse = false,
disableCombat = true,
}, {
animDict = 'missheistdockssetup1clipboard@base',
anim = 'base',
flags = 33,
}, {
model = 'prop_notepad_01',
bone = 18905,
coords = { x = 0.1, y = 0.02, z = 0.05 },
rotation = { x = 10.0, y = 0.0, z = 0.0 },
}, {
model = 'prop_pencil_01',
bone = 58866,
coords = { x = 0.11, y = -0.02, z = 0.001 },
rotation = { x = -120.0, y = 0.0, z = 0.0 },
}, function() -- Done
TriggerEvent('animations:client:EmoteCommandStart', {'c'})

local bedId = getClosestAvailableBed(k)
if bedId then
TriggerServerEvent('hospital:server:SendToBed', bedId, true, k)
hospitalLocation = k
else
QBCore.Functions.Notify(Lang:t('error.beds_taken'), 'error')
end
end, function() -- Cancel
TriggerEvent('animations:client:EmoteCommandStart', {'c'})
QBCore.Functions.Notify(Lang:t('error.canceled'), 'error')
end)
end
end, function() -- Cancel
QBCore.Functions.Notify(Lang:t('error.canceled'), 'error')
end)
end
end
end)

RegisterNetEvent('qb-ambulancejob:beds', function()
if GetAvailableBed(closestBed) then
TriggerServerEvent('hospital:server:SendToBed', closestBed, false)
RegisterNetEvent('qb-ambulancejob:beds', function(hospitalIndex, bedId)
if bedId then
TriggerServerEvent('hospital:server:SendToBed', bedId, false, hospitalIndex)
hospitalLocation = hospitalIndex
else
QBCore.Functions.Notify(Lang:t('error.beds_taken'), 'error')
end
Expand Down Expand Up @@ -913,24 +907,26 @@ if Config.UseTarget then
})
end

for k, v in pairs(Config.Locations['beds']) do
exports['qb-target']:AddBoxZone('beds' .. k, v.coords, 2.5, 2.3, {
name = 'beds' .. k,
heading = -20,
debugPoly = false,
minZ = v.coords.z - 1,
maxZ = v.coords.z + 1,
}, {
options = {
{
type = 'client',
event = 'qb-ambulancejob:beds',
icon = 'fas fa-bed',
label = 'Lay in Bed',
}
},
distance = 1.5
})
for hospitalKey, _ in pairs(Config.Locations['hospital']) do
for k, v in pairs(Config.Locations['hospital'][hospitalKey]['beds']) do
exports['qb-target']:AddBoxZone('beds'..k, v.coords, 2.5, 2.3, {
name = 'beds'..k..Config.Locations['hospital'][hospitalKey]['name'],
heading = -20,
debugPoly = false,
minZ = v.coords.z - 1,
maxZ = v.coords.z + 1,
}, {
options = {
{
type = 'client',
event = 'qb-ambulancejob:beds',
icon = 'fas fa-bed',
label = 'Layin Bed',
}
},
distance = 1.5
})
end
end
end)
else
Expand Down Expand Up @@ -961,24 +957,30 @@ else
end)
end
local bedPoly = {}
for k, v in pairs(Config.Locations['beds']) do
bedPoly[#bedPoly + 1] = BoxZone:Create(v.coords, 2.5, 2.3, {
name = 'beds' .. k,
heading = -20,
debugPoly = false,
minZ = v.coords.z - 1,
maxZ = v.coords.z + 1,
})
local bedCombo = ComboZone:Create(bedPoly, { name = 'bedCombo', debugPoly = false })
bedCombo:onPlayerInOut(function(isPointInside)
if isPointInside then
exports['qb-core']:DrawText(Lang:t('text.lie_bed'), 'left')
CheckInControls('beds')
else
listen = false
exports['qb-core']:HideText()
end
end)
for hospitalKey, _ in pairs(Config.Locations['hospital']) do
for k, v in pairs(Config.Locations['hospital'][hospitalKey]['beds']) do
bedPoly[#bedPoly+1] = BoxZone:Create(v.coords, 2.5, 2.3, {
name = 'beds'..k..Config.Locations['hospital'][hospitalKey]['name'],
heading = -20,
debugPoly = false,
minZ = v.coords.z - 1,
maxZ = v.coords.z + 1,
data = {
bedId = k
},
})
local bedCombo = ComboZone:Create(bedPoly, {name = 'bedCombo', debugPoly = false})
bedCombo:onPlayerInOut(function(isPointInside, _, zone)
if isPointInside and not isInHospitalBed then
exports['qb-core']:DrawText(Lang:t('text.lie_bed'), 'left')
local bedId = zone.data.bedId
CheckInControls('beds', hospitalKey, bedId)
else
listen = false
exports['qb-core']:HideText()
end
end)
end
end
end)
end
25 changes: 25 additions & 0 deletions config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,31 @@ Config.Locations = { -- Edit the various interaction points for p
{ coords = vector4(1771.8, 2598.02, 45.66, 89.05), taken = false, model = 2117668672 },
{ coords = vector4(1771.85, 2591.85, 45.66, 91.51), taken = false, model = 2117668672 },
},
['hospital'] = { -- Define hospitals and beds here
[1] = {
['name'] = Lang:t('info.pb_hospital'),
['location'] = vector3(308.36, -595.25, 43.28),
['beds'] = {
[1] = {coords = vector4(353.1, -584.6, 43.11, 152.08), taken = false, model = 1631638868},
[2] = {coords = vector4(356.79, -585.86, 43.11, 152.08), taken = false, model = 1631638868},
[3] = {coords = vector4(354.12, -593.12, 43.1, 336.32), taken = false, model = 2117668672},
[4] = {coords = vector4(350.79, -591.8, 43.1, 336.32), taken = false, model = 2117668672},
[5] = {coords = vector4(346.99, -590.48, 43.1, 336.32), taken = false, model = 2117668672},
[6] = {coords = vector4(360.32, -587.19, 43.02, 152.08), taken = false, model = -1091386327},
[7] = {coords = vector4(349.82, -583.33, 43.02, 152.08), taken = false, model = -1091386327},
[8] = {coords = vector4(326.98, -576.17, 43.02, 152.08), taken = false, model = -1091386327},
},
},
[2] = {
['name'] = Lang:t('info.paleto_hospital'),
['location'] = vector3(-254.54, 6331.78, 32.43),
['beds'] = {
[1] = {coords = vector4(-252.43, 6312.25, 32.34, 313.48), taken = false, model = 2117668672},
[2] = {coords = vector4(-247.04, 6317.95, 32.34, 134.64), taken = false, model = 2117668672},
[3] = {coords = vector4(-255.98, 6315.67, 32.34, 313.91), taken = false, model = 2117668672},
},
},
},
['stations'] = {
{ label = Lang:t('info.pb_hospital'), coords = vector3(304.27, -600.33, 43.28) }
}
Expand Down
Loading
Loading