994 lines
30 KiB
Lua
994 lines
30 KiB
Lua
|
local kvpname = GetCurrentServerEndpoint()..'_inshells'
|
||
|
local blips = {}
|
||
|
|
||
|
local function createBlip(blip, label, motel, owned, owner)
|
||
|
exports['blip_info']:SetBlipInfoTitle(blip, label, 0)
|
||
|
exports['blip_info']:SetBlipInfoImage(blip, "motels", motel)
|
||
|
if owned then
|
||
|
exports['blip_info']:AddBlipInfoName(blip, "Ejet af", owner)
|
||
|
else
|
||
|
exports['blip_info']:AddBlipInfoName(blip, " ", "Til salg")
|
||
|
end
|
||
|
exports['blip_info']:AddBlipInfoName(blip, "Type", "Beboelse")
|
||
|
exports['blip_info']:AddBlipInfoHeader(blip, "")
|
||
|
exports['blip_info']:AddBlipInfoHeader(blip, "")
|
||
|
exports['blip_info']:AddBlipInfoText(blip, "Hvis du mangler et sted at overnatte.")
|
||
|
end
|
||
|
|
||
|
CreateBlips = function()
|
||
|
for k,v in pairs(config.motels) do
|
||
|
local motel = GlobalState.Motels[v.motel]
|
||
|
local blip = AddBlipForCoord(v.rentcoord.x,v.rentcoord.y,v.rentcoord.z)
|
||
|
|
||
|
if not blips[v.motel] then
|
||
|
blips[v.motel] = {}
|
||
|
end
|
||
|
|
||
|
blips[v.motel].blip = blip
|
||
|
blips[v.motel].label = v.label
|
||
|
blips[v.motel].motel = v.motel
|
||
|
blips[v.motel].owned = motel.owned or false
|
||
|
blips[v.motel].ownerName = motel.ownerName
|
||
|
SetBlipSprite(blip,475)
|
||
|
SetBlipColour(blip,2)
|
||
|
SetBlipAsShortRange(blip,true)
|
||
|
SetBlipScale(blip,0.6)
|
||
|
BeginTextCommandSetBlipName("STRING")
|
||
|
AddTextComponentString(v.label)
|
||
|
EndTextCommandSetBlipName(blip)
|
||
|
|
||
|
createBlip(blips[v.motel].blip, blips[v.motel].label, blips[v.motel].motel, blips[v.motel].owned, blips[v.motel].ownerName)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
RegisterNetEvent('renzu_motels:UpdateBlip')
|
||
|
AddEventHandler('renzu_motels:UpdateBlip', function(motelName, owned, ownerName)
|
||
|
if owned then
|
||
|
blips[motelName].owned = owned
|
||
|
blips[motelName].ownerName = ownerName
|
||
|
end
|
||
|
exports['blip_info']:ResetBlipInfo(blips[motelName].blip)
|
||
|
createBlip(blips[motelName].blip, blips[motelName].label, blips[motelName].motel, owned, ownerName)
|
||
|
end)
|
||
|
|
||
|
RegisterNetEvent('renzu_motels:invoice')
|
||
|
AddEventHandler('renzu_motels:invoice', function(data)
|
||
|
local motels = GlobalState.Motels
|
||
|
local buy = lib.alertDialog({
|
||
|
header = 'Regning',
|
||
|
content = ' \n ## INFO \n **Beskrivelse:** '..data.description..' \n **Beløb:** '..data.amount..',- \n **Betalingsmetode:** '..data.payment,
|
||
|
centered = true,
|
||
|
labels = {
|
||
|
cancel = 'Luk',
|
||
|
confirm = 'Betal'
|
||
|
},
|
||
|
cancel = true
|
||
|
})
|
||
|
if buy ~= 'cancel' then
|
||
|
local success = lib.callback.await('renzu_motels:payinvoice',false,data)
|
||
|
if success then
|
||
|
Notify('Du betalte din regning!','success')
|
||
|
else
|
||
|
Notify('Du betalte ikke regningen','error')
|
||
|
end
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
DoesPlayerHaveAccess = function(data)
|
||
|
for identifier, _ in pairs(data) do
|
||
|
if identifier == PlayerData?.identifier then return true end
|
||
|
end
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
DoesPlayerHaveKey = function(data,room)
|
||
|
local items = GetInventoryItems('keya')
|
||
|
if not items then return false end
|
||
|
for k,v in pairs(items) do
|
||
|
if v.metadata?.type == data.motel and v.metadata?.serial == data.index then
|
||
|
return v.metadata?.owner and room?.players[v.metadata?.owner] or false
|
||
|
end
|
||
|
end
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
GetPlayerKeys = function(data,room)
|
||
|
local items = GetInventoryItems('keya')
|
||
|
if not items then return false end
|
||
|
local keys = {}
|
||
|
for k,v in pairs(items) do
|
||
|
if v.metadata?.type == data.motel and v.metadata?.serial == data.index then
|
||
|
local key = v.metadata?.owner and room?.players[v.metadata?.owner]
|
||
|
if key then
|
||
|
keys[v.metadata.owner] = key.name
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
return keys
|
||
|
end
|
||
|
|
||
|
SetDoorState = function(data)
|
||
|
local motels = GlobalState.Motels or {}
|
||
|
local doorindex = data.index + (joaat(data.motel))
|
||
|
DoorSystemSetDoorState(doorindex, 1)
|
||
|
end
|
||
|
|
||
|
RegisterNetEvent('renzu_motels:Door', function(data)
|
||
|
if not data.Mlo then return end
|
||
|
local doorindex = data.index + (joaat(data.motel))
|
||
|
DoorSystemSetDoorState(doorindex, DoorSystemGetDoorState(doorindex) == 0 and 1 or 0, false, false)
|
||
|
end)
|
||
|
|
||
|
Door = function(data)
|
||
|
local dist = #(data.coord - GetEntityCoords(cache.ped)) < 2
|
||
|
local motel = GlobalState.Motels[data.motel]
|
||
|
local moteldoor = motel and motel.rooms[data.index]
|
||
|
if moteldoor and DoesPlayerHaveAccess(motel.rooms[data.index].players)
|
||
|
or moteldoor and DoesPlayerHaveKey(data,moteldoor) or IsOwnerOrEmployee(data.motel) then
|
||
|
lib.RequestAnimDict('mp_doorbell')
|
||
|
TaskPlayAnim(PlayerPedId(), "mp_doorbell", "open_door", 1.0, 1.0, 1000, 1, 1, 0, 0, 0)
|
||
|
TriggerServerEvent('renzu_motels:Door', {
|
||
|
motel = data.motel,
|
||
|
index = data.index,
|
||
|
coord = data.coord,
|
||
|
Mlo = data.Mlo,
|
||
|
})
|
||
|
local text
|
||
|
if data.Mlo then
|
||
|
local doorindex = data.index + (joaat(data.motel))
|
||
|
text = DoorSystemGetDoorState(doorindex) == 0 and 'Du låste døren' or 'Du låste døren op'
|
||
|
else
|
||
|
text = not moteldoor?.lock and 'Du låste døren' or 'Du låste døren op'
|
||
|
end
|
||
|
Wait(1000)
|
||
|
--PlaySoundFromEntity(-1, "Hood_Open", cache.ped , 'Lowrider_Super_Mod_Garage_Sounds', 0, 0)
|
||
|
local data = {
|
||
|
file = 'door',
|
||
|
volume = 0.5
|
||
|
}
|
||
|
SendNUIMessage({
|
||
|
type = "playsound",
|
||
|
content = data
|
||
|
})
|
||
|
Notify(text, 'info')
|
||
|
else
|
||
|
Notify('Du har ikke adgang', 'error')
|
||
|
end
|
||
|
end
|
||
|
|
||
|
isRentExpired = function(data)
|
||
|
local motels = GlobalState.Motels[data.motel]
|
||
|
local room = motels?.rooms[data.index] or {}
|
||
|
local player = room?.players[PlayerData.identifier] or {}
|
||
|
return player?.duration and player?.duration < GlobalState.MotelTimer
|
||
|
end
|
||
|
|
||
|
RoomFunction = function(data,identifier)
|
||
|
if isRentExpired(data) then
|
||
|
return Notify('Du skal betale husleje. \n Betal venligst for at komme ind')
|
||
|
end
|
||
|
if data.type == 'door' then
|
||
|
return Door(data)
|
||
|
elseif data.type == 'stash' then
|
||
|
local stashid = identifier or data.uniquestash and PlayerData.identifier or 'room'
|
||
|
return OpenStash(data,stashid)
|
||
|
elseif data.type == 'wardrobe' then
|
||
|
return config.wardrobes[config.wardrobe]()
|
||
|
elseif config.extrafunction[data.type] then
|
||
|
local stashid = identifier or data.uniquestash and PlayerData.identifier or 'room'
|
||
|
return config.extrafunction[data.type](data,stashid)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
LockPick = function(data)
|
||
|
local success = nil
|
||
|
SetTimeout(1000,function()
|
||
|
repeat
|
||
|
local lockpick = lib.progressBar({
|
||
|
duration = 10000,
|
||
|
label = 'Bryder ind..',
|
||
|
useWhileDead = false,
|
||
|
canCancel = true,
|
||
|
anim = {
|
||
|
dict = 'veh@break_in@0h@p_m_one@',
|
||
|
clip = 'low_force_entry_ds'
|
||
|
},
|
||
|
})
|
||
|
Wait(0)
|
||
|
until success ~= nil
|
||
|
end)
|
||
|
success = lib.skillCheck({'easy', 'easy', {areaSize = 60, speedMultiplier = 2}, 'easy'})
|
||
|
if lib.progressActive() then
|
||
|
lib.cancelProgress()
|
||
|
end
|
||
|
if success then
|
||
|
TriggerServerEvent('renzu_motels:Door', {
|
||
|
motel = data.motel,
|
||
|
index = data.index,
|
||
|
coord = data.coord,
|
||
|
Mlo = data.Mlo
|
||
|
})
|
||
|
local doorindex = data.index + (joaat(data.motel))
|
||
|
Notify(DoorSystemGetDoorState(doorindex) == 0 and 'Du låste døren' or 'Du låste døren op', 'info')
|
||
|
end
|
||
|
end
|
||
|
|
||
|
Notify = function(msg,type)
|
||
|
lib.notify({
|
||
|
description = msg,
|
||
|
type = type or 'info'
|
||
|
})
|
||
|
end
|
||
|
|
||
|
MyRoomMenu = function(data)
|
||
|
local motels = GlobalState.Motels
|
||
|
local rate = motels[data.motel].hour_rate or data.rate
|
||
|
|
||
|
local options = {
|
||
|
{
|
||
|
title = 'Mit værelse ['..data.index..'] - Betal leje',
|
||
|
description = 'Betal leje eller fortsæt til '..data.index..' \n Lejeperiode: '..data.duration..' \n '..rate..',- per '..data.rental_period,
|
||
|
icon = 'money-bill-wave-alt',
|
||
|
onSelect = function()
|
||
|
local input = lib.inputDialog('Betal eller indsæt til motel', {
|
||
|
{type = 'number', label = 'Beløb du vil indsætte', description = rate..',- per '..data.rental_period..' \n Betalingsmetode: '..data.payment, icon = 'money', default = rate},
|
||
|
})
|
||
|
if not input then return end
|
||
|
local success = lib.callback.await('renzu_motels:payrent',false,{
|
||
|
payment = data.payment,
|
||
|
index = data.index,
|
||
|
motel = data.motel,
|
||
|
amount = input[1],
|
||
|
rate = rate,
|
||
|
rental_period = data.rental_period
|
||
|
})
|
||
|
if success then
|
||
|
Notify('Du betalte leje', 'success')
|
||
|
else
|
||
|
Notify('Du betalte ikke leje', 'error')
|
||
|
end
|
||
|
end,
|
||
|
arrow = true,
|
||
|
},
|
||
|
{
|
||
|
title = 'Lav nøgle',
|
||
|
description = 'Anmod om nøgle',
|
||
|
icon = 'key',
|
||
|
onSelect = function()
|
||
|
local success = lib.callback.await('renzu_motels:motelkey',false,{
|
||
|
index = data.index,
|
||
|
motel = data.motel,
|
||
|
})
|
||
|
if success then
|
||
|
Notify('Du anmodede om en dele-nøgle', 'success')
|
||
|
else
|
||
|
Notify('Du blev afvist', 'error')
|
||
|
end
|
||
|
end,
|
||
|
arrow = true,
|
||
|
},
|
||
|
{
|
||
|
title = 'Terminer leje-aftale',
|
||
|
description = 'Terminer leje-aftale med motellet',
|
||
|
icon = 'ban',
|
||
|
onSelect = function()
|
||
|
if isRentExpired(data) then
|
||
|
Notify('Leje-aftale på '..data.index..' kunne ikke termineres. \n Årsag: Du mangler at betale leje','error')
|
||
|
return
|
||
|
end
|
||
|
local End = lib.alertDialog({
|
||
|
header = '## ADVARSEL',
|
||
|
content = ' Du vil ikke længere have adgang til dør eller skab.',
|
||
|
centered = true,
|
||
|
labels = {
|
||
|
cancel = 'Luk',
|
||
|
confirm = 'Okay',
|
||
|
},
|
||
|
cancel = true
|
||
|
})
|
||
|
if End == 'cancel' then return end
|
||
|
local success = lib.callback.await('renzu_motels:removeoccupant',false,data,data.index,PlayerData.identifier)
|
||
|
if success then
|
||
|
Notify('Leje blev sluttet for '..data.index,'success')
|
||
|
else
|
||
|
Notify('Fejlede at afslutte leje for '..data.index,'error')
|
||
|
end
|
||
|
end,
|
||
|
arrow = true,
|
||
|
},
|
||
|
}
|
||
|
lib.registerContext({
|
||
|
id = 'myroom',
|
||
|
menu = 'roomlist',
|
||
|
title = 'Mine Motel muligheder',
|
||
|
options = options
|
||
|
})
|
||
|
lib.showContext('myroom')
|
||
|
end
|
||
|
|
||
|
CountOccupants = function(players)
|
||
|
local count = 0
|
||
|
for k,v in pairs(players or {}) do
|
||
|
count += 1
|
||
|
end
|
||
|
return count
|
||
|
end
|
||
|
|
||
|
RoomList = function(data)
|
||
|
local motels , time = lib.callback.await('renzu_motels:getMotels',false)
|
||
|
local rate = motels[data.motel].hour_rate or data.rate
|
||
|
local options = {}
|
||
|
--local motels = GlobalState.Motels
|
||
|
for doorindex,v in ipairs(data.doors) do
|
||
|
local playerroom = motels[data.motel].rooms[doorindex].players[PlayerData.identifier]
|
||
|
local duration = playerroom?.duration
|
||
|
local occupants = CountOccupants(motels[data.motel].rooms[doorindex].players)
|
||
|
if occupants < data.maxoccupants and not duration then
|
||
|
table.insert(options,{
|
||
|
title = 'Lej motel-værelse #'..doorindex,
|
||
|
description = 'Vælg rum #'..doorindex..' \n Pladser: '..occupants..'/'..data.maxoccupants,
|
||
|
icon = 'door-closed',
|
||
|
onSelect = function()
|
||
|
local input = lib.inputDialog('Leje-periode', {
|
||
|
{type = 'number', label = 'Vælg leje-periode i '..data.rental_period, description = rate..',- per '..data.rental_period..' \n Betalingsmetode: '..data.payment, icon = 'clock', default = 1},
|
||
|
})
|
||
|
if not input then return end
|
||
|
local success = lib.callback.await('renzu_motels:rentaroom',false,{
|
||
|
index = doorindex,
|
||
|
motel = data.motel,
|
||
|
duration = input[1],
|
||
|
rate = rate,
|
||
|
rental_period = data.rental_period,
|
||
|
payment = data.payment,
|
||
|
uniquestash = data.uniquestash
|
||
|
})
|
||
|
if success then
|
||
|
Notify('Du lejede et værelse!', 'success')
|
||
|
else
|
||
|
Notify('Du kunne ikke leje et værelse', 'error')
|
||
|
end
|
||
|
end,
|
||
|
arrow = true,
|
||
|
})
|
||
|
elseif duration then
|
||
|
local hour = math.floor((duration - time) / 3600)
|
||
|
local duration_left = hour .. ' Timer: '..math.floor(((duration - time) / 60) - (60 * hour))..' minutter'
|
||
|
table.insert(options,{
|
||
|
title = 'Min dør #'..doorindex..' muligheder',
|
||
|
description = 'Betal leje eller anmod om en nøgle',
|
||
|
icon = 'cog',
|
||
|
onSelect = function()
|
||
|
return MyRoomMenu({
|
||
|
payment = data.payment,
|
||
|
index = doorindex,
|
||
|
motel = data.motel,
|
||
|
duration = duration_left,
|
||
|
rate = rate,
|
||
|
rental_period = data.rental_period
|
||
|
})
|
||
|
end,
|
||
|
arrow = true,
|
||
|
})
|
||
|
end
|
||
|
end
|
||
|
lib.registerContext({
|
||
|
id = 'roomlist',
|
||
|
menu = 'rentmenu',
|
||
|
title = 'Vælg rum',
|
||
|
options = options
|
||
|
})
|
||
|
lib.showContext('roomlist')
|
||
|
end
|
||
|
|
||
|
IsOwnerOrEmployee = function(motel)
|
||
|
local motels = GlobalState.Motels
|
||
|
motels[motel].ownerName = PlayerData.charinfo.firstname.. ' '..PlayerData.charinfo.lastname
|
||
|
return motels[motel].owned == PlayerData.identifier or motels[motel].employees[PlayerData.identifier]
|
||
|
end
|
||
|
|
||
|
MotelRentalMenu = function(data)
|
||
|
local motels = GlobalState.Motels
|
||
|
local rate = motels[data.motel].hour_rate or data.rate
|
||
|
local options = {}
|
||
|
if not data.manual then
|
||
|
table.insert(options,{
|
||
|
title = 'Lej nyt motelværelse',
|
||
|
description = ' \n Vælg et værelse \n '..data.rental_period..' Rate: '..rate..',-',
|
||
|
icon = 'hotel',
|
||
|
onSelect = function()
|
||
|
return RoomList(data)
|
||
|
end,
|
||
|
arrow = true,
|
||
|
})
|
||
|
end
|
||
|
if not motels[data.motel].owned and config.business or IsOwnerOrEmployee(data.motel) and config.business then
|
||
|
local title = not motels[data.motel].owned and 'Køb motel' or 'Motel-menu'
|
||
|
local description = not motels[data.motel].owned and 'Pris: '..data.businessprice or 'Håndter ansatte, lejere og økonomi.'
|
||
|
table.insert(options,{
|
||
|
title = title,
|
||
|
description = description,
|
||
|
icon = 'hotel',
|
||
|
onSelect = function()
|
||
|
return MotelOwner(data)
|
||
|
end,
|
||
|
arrow = true,
|
||
|
})
|
||
|
end
|
||
|
|
||
|
if #options == 0 then
|
||
|
Notify('This Motels Manually Accept Occupants \n Contact the Owner')
|
||
|
Wait(1500)
|
||
|
return SendMessageApi(data.motel)
|
||
|
end
|
||
|
|
||
|
lib.registerContext({
|
||
|
id = 'rentmenu',
|
||
|
title = data.label,
|
||
|
options = options
|
||
|
})
|
||
|
lib.showContext('rentmenu')
|
||
|
end
|
||
|
|
||
|
SendMessageApi = function(motel)
|
||
|
local message = lib.alertDialog({
|
||
|
header = 'Vil du kontakte ejeren?',
|
||
|
content = '## Besked til motel-ejeren',
|
||
|
centered = true,
|
||
|
labels = {
|
||
|
cancel = 'Luk',
|
||
|
confirm = 'Send',
|
||
|
},
|
||
|
cancel = true
|
||
|
})
|
||
|
if message == 'cancel' then return end
|
||
|
local input = lib.inputDialog('Message', {
|
||
|
{type = 'input', label = 'Titel', description = 'Titel på din besked', icon = 'hash', required = true},
|
||
|
{type = 'textarea', label = 'Besked', description = 'Din besked', icon = 'mail', required = true},
|
||
|
{type = 'number', label = 'Kontaktnummer', icon = 'phone', required = false},
|
||
|
})
|
||
|
|
||
|
config.messageApi({title = input[1], message = input[2], motel = motel})
|
||
|
end
|
||
|
|
||
|
Owner = {}
|
||
|
Owner.Rooms = {}
|
||
|
Owner.Rooms.Occupants = function(data,index)
|
||
|
local motels , time = lib.callback.await('renzu_motels:getMotels',false)
|
||
|
local motel = motels[data.motel]
|
||
|
local players = motel.rooms[index] and motel.rooms[index].players or {}
|
||
|
local options = {}
|
||
|
for player,char in pairs(players) do
|
||
|
local hour = math.floor((char.duration - time) / 3600)
|
||
|
local name = char.name or 'Intet navn'
|
||
|
local duration_left = hour .. ' Timer: '..math.floor(((char.duration - time) / 60) - (60 * hour))..' minutter'
|
||
|
table.insert(options,{
|
||
|
title = 'Lejer '..name,
|
||
|
description = 'Leje-periode: '..duration_left,
|
||
|
icon = 'hotel',
|
||
|
onSelect = function()
|
||
|
local kick = lib.alertDialog({
|
||
|
header = 'Bekræft',
|
||
|
content = '## Bortvis lejer \n **Navn:** '..name,
|
||
|
centered = true,
|
||
|
labels = {
|
||
|
cancel = 'Luk',
|
||
|
confirm = 'Bortvis',
|
||
|
waw = 'waw'
|
||
|
},
|
||
|
cancel = true
|
||
|
})
|
||
|
if kick == 'cancel' then return end
|
||
|
local success = lib.callback.await('renzu_motels:removeoccupant',false,data,index,player)
|
||
|
if success then
|
||
|
Notify('Du bortviste '..name..' fra værelse #'..index,'success')
|
||
|
else
|
||
|
Notify('Du kunne ikke bortvise '..name..' fra værelse #'..index,'error')
|
||
|
end
|
||
|
end,
|
||
|
arrow = true,
|
||
|
})
|
||
|
end
|
||
|
if data.maxoccupants > #options then
|
||
|
for i = 1, data.maxoccupants-#options do
|
||
|
table.insert(options,{
|
||
|
title = 'Tomme pladser ',
|
||
|
icon = 'hotel',
|
||
|
onSelect = function()
|
||
|
local input = lib.inputDialog('Ny lejer', {
|
||
|
{type = 'number', label = 'Borger ID', description = 'ID på borgeren du vil tilføje', icon = 'id-card', required = true},
|
||
|
{type = 'number', label = 'Vælg en leje-periode i '..data.rental_period, description = 'Hvor mange '..data.rental_period, icon = 'clock', default = 1},
|
||
|
})
|
||
|
if not input then return end
|
||
|
local success = lib.callback.await('renzu_motels:addoccupant',false,data,index,input)
|
||
|
if success == 'exist' then
|
||
|
Notify('Eksisterer allerede i '..index,'error')
|
||
|
elseif success then
|
||
|
Notify('Du tilføjede '..input[1]..' fra '..index,'success')
|
||
|
else
|
||
|
Notify('Fejlede i at tilføje '..input[1]..' fra '..index,'error')
|
||
|
end
|
||
|
end,
|
||
|
arrow = true,
|
||
|
})
|
||
|
end
|
||
|
end
|
||
|
lib.registerContext({
|
||
|
menu = 'owner_rooms',
|
||
|
id = 'occupants_lists',
|
||
|
title = 'Rum #'..index..' lejere',
|
||
|
options = options
|
||
|
})
|
||
|
lib.showContext('occupants_lists')
|
||
|
end
|
||
|
|
||
|
Owner.Rooms.List = function(data)
|
||
|
local motels = GlobalState.Motels
|
||
|
local options = {}
|
||
|
for doorindex,v in ipairs(data.doors) do
|
||
|
local occupants = CountOccupants(motels[data.motel].rooms[doorindex].players)
|
||
|
table.insert(options,{
|
||
|
title = 'Rum #'..doorindex,
|
||
|
description = 'Tilføj er eller bortvise lejere fra #'..doorindex..' \n ***Lejere:*** '..occupants,
|
||
|
icon = 'hotel',
|
||
|
onSelect = function()
|
||
|
return Owner.Rooms.Occupants(data,doorindex)
|
||
|
end,
|
||
|
arrow = true,
|
||
|
})
|
||
|
end
|
||
|
lib.registerContext({
|
||
|
menu = 'motelmenu',
|
||
|
id = 'owner_rooms',
|
||
|
title = data.label,
|
||
|
options = options
|
||
|
})
|
||
|
lib.showContext('owner_rooms')
|
||
|
end
|
||
|
|
||
|
Owner.Employee = {}
|
||
|
Owner.Employee.Manage = function(data)
|
||
|
local motel = GlobalState.Motels[data.motel]
|
||
|
local options = {
|
||
|
{
|
||
|
title = 'Ansæt spiller',
|
||
|
description = 'Ansæt nærmeste spiller',
|
||
|
icon = 'hotel',
|
||
|
onSelect = function()
|
||
|
local input = lib.inputDialog('Ansæt spiller', {
|
||
|
{type = 'number', label = 'Spiller ID', description = 'ID på spilleren', icon = 'id-card', required = true},
|
||
|
})
|
||
|
if not input then return end
|
||
|
local success = lib.callback.await('renzu_motels:addemployee',false,data.motel,input[1])
|
||
|
if success then
|
||
|
Notify('Du ansatte personen!','success')
|
||
|
else
|
||
|
Notify('Du kunne ikke ansætte personen.','error')
|
||
|
end
|
||
|
end,
|
||
|
arrow = true,
|
||
|
}
|
||
|
}
|
||
|
if motel and motel.employees then
|
||
|
for identifier,name in pairs(motel.employees) do
|
||
|
table.insert(options,{
|
||
|
title = name,
|
||
|
description = 'Fyr '..name,
|
||
|
icon = 'hotel',
|
||
|
onSelect = function()
|
||
|
local success = lib.callback.await('renzu_motels:removeemployee',false,data.motel,identifier)
|
||
|
if success then
|
||
|
Notify('Du fyrede personen','success')
|
||
|
else
|
||
|
Notify('Du kunne ikke fyre personen','error')
|
||
|
end
|
||
|
end,
|
||
|
arrow = true,
|
||
|
})
|
||
|
end
|
||
|
end
|
||
|
lib.registerContext({
|
||
|
id = 'employee_manage',
|
||
|
title = 'Håndter ansatte',
|
||
|
options = options
|
||
|
})
|
||
|
lib.showContext('employee_manage')
|
||
|
end
|
||
|
|
||
|
MotelOwner = function(data)
|
||
|
local motels = GlobalState.Motels
|
||
|
if not motels[data.motel].owned then
|
||
|
local buy = lib.alertDialog({
|
||
|
header = data.label,
|
||
|
content = ' \n ## INFO \n **Værelser:** '..#data.doors..' \n **Maks lejere:** '..#data.doors * data.maxoccupants..' \n **Pris:** '..data.businessprice..',-',
|
||
|
centered = true,
|
||
|
labels = {
|
||
|
cancel = 'Luk',
|
||
|
confirm = 'Køb'
|
||
|
},
|
||
|
cancel = true
|
||
|
})
|
||
|
if buy ~= 'cancel' then
|
||
|
local success = lib.callback.await('renzu_motels:buymotel',false,data)
|
||
|
if success then
|
||
|
Notify('Du købte motellet','success')
|
||
|
else
|
||
|
Notify('Du kunne ikke købe motellet','error')
|
||
|
end
|
||
|
end
|
||
|
elseif IsOwnerOrEmployee(data.motel) then
|
||
|
local revenue = motels[data.motel].revenue or 0
|
||
|
local rate = motels[data.motel].hour_rate or data.rate
|
||
|
local options = {
|
||
|
{
|
||
|
title = 'Motel værelser',
|
||
|
description = 'Tilføj eller fjern lejer',
|
||
|
icon = 'hotel',
|
||
|
onSelect = function()
|
||
|
return Owner.Rooms.List(data)
|
||
|
end,
|
||
|
arrow = true,
|
||
|
},
|
||
|
{
|
||
|
title = 'Send regning',
|
||
|
description = 'Send regning til nærmeste spiller',
|
||
|
icon = 'hotel',
|
||
|
onSelect = function()
|
||
|
local input = lib.inputDialog('Send regning', {
|
||
|
{type = 'number', label = 'Spiller ID', description = 'ID på spilleren', icon = 'money', required = true},
|
||
|
{type = 'number', label = 'Mængde', description = 'Beløbet på regningen', icon = 'money', required = true},
|
||
|
{type = 'input', label = 'Besked', description = 'Besked på regningen', icon = 'info'},
|
||
|
{type = 'checkbox', label = 'Bank-overførse'},
|
||
|
})
|
||
|
if not input then return end
|
||
|
Notify('Du sendte en regning til '..input[1],'success')
|
||
|
local success = lib.callback.await('renzu_motels:sendinvoice',false,data.motel,input)
|
||
|
if success then
|
||
|
Notify('Regning betalt','success')
|
||
|
else
|
||
|
Notify('Regningen blev ikke betalt','error')
|
||
|
end
|
||
|
end,
|
||
|
arrow = true,
|
||
|
}
|
||
|
}
|
||
|
if motels[data.motel].owned == PlayerData.identifier then
|
||
|
table.insert(options,{
|
||
|
title = 'Skift tids-rate',
|
||
|
description = 'Skift '..data.rental_period..' rater. \n '..data.rental_period..' Rater: '..rate,
|
||
|
icon = 'hotel',
|
||
|
onSelect = function()
|
||
|
local input = lib.inputDialog('Skift '..data.rental_period..' rate', {
|
||
|
{type = 'number', label = 'Rate', description = 'Rate per '..data.rental_period..'', icon = 'money', required = true},
|
||
|
})
|
||
|
if not input then return end
|
||
|
local success = lib.callback.await('renzu_motels:editrate',false,data.motel,input[1])
|
||
|
if success then
|
||
|
Notify('Du ændrede '..data.rental_period..' raten','success')
|
||
|
else
|
||
|
Notify('Modificering fejlede','error')
|
||
|
end
|
||
|
end,
|
||
|
arrow = true,
|
||
|
})
|
||
|
table.insert(options,{
|
||
|
title = 'Motel omsætning',
|
||
|
description = 'Total: '..revenue,
|
||
|
icon = 'hotel',
|
||
|
onSelect = function()
|
||
|
local input = lib.inputDialog('Hæv penge fra motel', {
|
||
|
{type = 'number', label = 'Mængde', icon = 'money', required = true},
|
||
|
})
|
||
|
if not input then return end
|
||
|
local success = lib.callback.await('renzu_motels:withdrawfund',false,data.motel,input[1])
|
||
|
if success then
|
||
|
Notify('Du hævede penge fra motel','success')
|
||
|
else
|
||
|
Notify('Kunne ikke hæve penge','error')
|
||
|
end
|
||
|
end,
|
||
|
arrow = true,
|
||
|
})
|
||
|
table.insert(options,{
|
||
|
title = 'Medarbejder menu',
|
||
|
description = 'Ansæt / Fyr ansat',
|
||
|
icon = 'hotel',
|
||
|
onSelect = function()
|
||
|
return Owner.Employee.Manage(data)
|
||
|
end,
|
||
|
arrow = true,
|
||
|
})
|
||
|
table.insert(options,{
|
||
|
title = 'Overfør ejerskab',
|
||
|
description = 'Overfør ejerskab til nærmeste spiller',
|
||
|
icon = 'hotel',
|
||
|
onSelect = function()
|
||
|
local input = lib.inputDialog('Overfør ejerskab af motel', {
|
||
|
{type = 'number', label = 'ID', description = 'ID på borgeren som vil modtage dit motel', icon = 'id-card', required = true},
|
||
|
})
|
||
|
if not input then return end
|
||
|
local success = lib.callback.await('renzu_motels:transfermotel',false,data.motel,input[1])
|
||
|
if success then
|
||
|
Notify('Motel-ejerskab overført','success')
|
||
|
else
|
||
|
Notify('Kunne ikke overføre ejerskab','error')
|
||
|
end
|
||
|
end,
|
||
|
arrow = true,
|
||
|
})
|
||
|
table.insert(options,{
|
||
|
title = 'Sælg motel',
|
||
|
description = 'Sælg dit motel for halv pris',
|
||
|
icon = 'hotel',
|
||
|
onSelect = function()
|
||
|
local sell = lib.alertDialog({
|
||
|
header = data.label,
|
||
|
content = ' \n ## INFO \n **Salgsværdi:** '..(data.businessprice / 2)..',-',
|
||
|
centered = true,
|
||
|
labels = {
|
||
|
cancel = 'Luk',
|
||
|
confirm = 'Sælg'
|
||
|
},
|
||
|
cancel = true
|
||
|
})
|
||
|
if sell ~= 'cancel' then
|
||
|
local success = lib.callback.await('renzu_motels:sellmotel',false,data)
|
||
|
if success then
|
||
|
Notify('Du solgte dit motel','success')
|
||
|
else
|
||
|
Notify('Dit motel blev ikke solgt','error')
|
||
|
end
|
||
|
end
|
||
|
end,
|
||
|
arrow = true,
|
||
|
})
|
||
|
end
|
||
|
lib.registerContext({
|
||
|
id = 'motelmenu',
|
||
|
menu = 'rentmenu',
|
||
|
title = data.label,
|
||
|
options = options
|
||
|
})
|
||
|
lib.showContext('motelmenu')
|
||
|
end
|
||
|
end
|
||
|
|
||
|
MotelRentalPoints = function(data)
|
||
|
local point = lib.points.new(data.rentcoord, 5, data)
|
||
|
|
||
|
function point:onEnter()
|
||
|
lib.showTextUI('[E] - Motel leje', {
|
||
|
position = "top-center",
|
||
|
icon = 'hotel',
|
||
|
style = {
|
||
|
borderRadius = 0,
|
||
|
backgroundColor = '#48BB78',
|
||
|
color = 'white'
|
||
|
}
|
||
|
})
|
||
|
end
|
||
|
|
||
|
function point:onExit()
|
||
|
lib.hideTextUI()
|
||
|
end
|
||
|
|
||
|
function point:nearby()
|
||
|
DrawMarker(2, self.coords.x, self.coords.y, self.coords.z, 0.0, 0.0,0.0, 0.0, 180.0, 0.0, 0.7, 0.7, 0.7, 225, 225, 211, 50, false,true, 2, nil, nil, false)
|
||
|
if self.currentDistance < 1 and IsControlJustReleased(0, 38) then
|
||
|
MotelRentalMenu(data)
|
||
|
end
|
||
|
end
|
||
|
return point
|
||
|
end
|
||
|
|
||
|
local inMotelZone = false
|
||
|
MotelZone = function(data)
|
||
|
local point = nil
|
||
|
function onEnter(self)
|
||
|
inMotelZone = true
|
||
|
Citizen.CreateThreadNow(function()
|
||
|
for index, doors in pairs(data.doors) do
|
||
|
for type, coord in pairs(doors) do
|
||
|
MotelFunction({
|
||
|
payment = data.payment or 'money',
|
||
|
uniquestash = data.uniquestash,
|
||
|
shell = data.shell,
|
||
|
Mlo = data.Mlo,
|
||
|
type = type,
|
||
|
index = index,
|
||
|
coord = coord,
|
||
|
label = config.Text[type],
|
||
|
motel = data.motel,
|
||
|
door = data.door
|
||
|
})
|
||
|
end
|
||
|
end
|
||
|
point = MotelRentalPoints(data)
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
function onExit(self)
|
||
|
inMotelZone = false
|
||
|
point:remove()
|
||
|
for k,id in pairs(zones) do
|
||
|
removeTargetZone(id)
|
||
|
end
|
||
|
for k,id in pairs(blips) do
|
||
|
if DoesBlipExist(id) then
|
||
|
RemoveBlip(id)
|
||
|
end
|
||
|
end
|
||
|
zones = {}
|
||
|
end
|
||
|
|
||
|
local sphere = lib.zones.sphere({
|
||
|
coords = data.coord,
|
||
|
radius = data.radius,
|
||
|
debug = false,
|
||
|
inside = inside,
|
||
|
onEnter = onEnter,
|
||
|
onExit = onExit
|
||
|
})
|
||
|
end
|
||
|
|
||
|
--qb-interior func
|
||
|
local house
|
||
|
local inhouse = false
|
||
|
function Teleport(x, y, z, h ,exit)
|
||
|
CreateThread(function()
|
||
|
SetEntityCoords(cache.ped, x, y, z, 0, 0, 0, false)
|
||
|
SetEntityHeading(cache.ped, h or 0.0)
|
||
|
Wait(1001)
|
||
|
DoScreenFadeIn(1000)
|
||
|
end)
|
||
|
if exit then
|
||
|
inhouse = false
|
||
|
TriggerEvent('qb-weathersync:client:EnableSync')
|
||
|
for k,id in pairs(shelzones) do
|
||
|
removeTargetZone(id)
|
||
|
end
|
||
|
DeleteEntity(house)
|
||
|
lib.callback.await('renzu_motels:SetRouting',false,data,'exit')
|
||
|
shelzones = {}
|
||
|
DeleteResourceKvp(kvpname)
|
||
|
LocalPlayer.state:set('inshell',false,true)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
EnterShell = function(data,login)
|
||
|
local motels = GlobalState.Motels
|
||
|
if motels[data.motel].rooms[data.index].lock and not login then
|
||
|
Notify('Døren er låst', 'error')
|
||
|
return false
|
||
|
end
|
||
|
local shelldata = config.shells[data.shell or data.motel]
|
||
|
if not shelldata then
|
||
|
warn('Interiør er ikke konfigureret')
|
||
|
return
|
||
|
end
|
||
|
lib.callback.await('renzu_motels:SetRouting',false,data,'enter')
|
||
|
inhouse = true
|
||
|
Wait(1000)
|
||
|
local spawn = vec3(data.coord.x,data.coord.y,data.coord.z)+vec3(0.0,0.0,1500.0)
|
||
|
local offsets = shelldata.offsets
|
||
|
local model = shelldata.shell
|
||
|
DoScreenFadeOut(500)
|
||
|
while not IsScreenFadedOut() do
|
||
|
Wait(10)
|
||
|
end
|
||
|
inhouse = true
|
||
|
TriggerEvent('qb-weathersync:client:DisableSync')
|
||
|
RequestModel(model)
|
||
|
while not HasModelLoaded(model) do
|
||
|
Wait(1000)
|
||
|
end
|
||
|
local lastloc = GetEntityCoords(cache.ped)
|
||
|
house = CreateObject(model, spawn.x, spawn.y, spawn.z, false, false, false)
|
||
|
FreezeEntityPosition(house, true)
|
||
|
LocalPlayer.state:set('lastloc',data.lastloc or lastloc,false)
|
||
|
data.lastloc = data.lastloc or lastloc
|
||
|
if not login then
|
||
|
SendNUIMessage({
|
||
|
type = 'door'
|
||
|
})
|
||
|
end
|
||
|
Teleport(spawn.x + offsets.exit.x, spawn.y + offsets.exit.y, spawn.z+0.1, offsets.exit.h)
|
||
|
SetResourceKvp(kvpname,json.encode(data))
|
||
|
|
||
|
Citizen.CreateThreadNow(function()
|
||
|
ShellTargets(data,offsets,spawn,house)
|
||
|
while inhouse do
|
||
|
--SetRainLevel(0.0)
|
||
|
SetWeatherTypePersist('CLEAR')
|
||
|
SetWeatherTypeNow('CLEAR')
|
||
|
SetWeatherTypeNowPersist('CLEAR')
|
||
|
NetworkOverrideClockTime(18, 0, 0)
|
||
|
Wait(1)
|
||
|
end
|
||
|
end)
|
||
|
return house
|
||
|
end
|
||
|
|
||
|
function RotationToDirection(rotation)
|
||
|
local adjustedRotation =
|
||
|
{
|
||
|
x = (math.pi / 180) * rotation.x,
|
||
|
y = (math.pi / 180) * rotation.y,
|
||
|
z = (math.pi / 180) * rotation.z
|
||
|
}
|
||
|
local direction =
|
||
|
{
|
||
|
x = -math.sin(adjustedRotation.z) * math.abs(math.cos(adjustedRotation.x)),
|
||
|
y = math.cos(adjustedRotation.z) * math.abs(math.cos(adjustedRotation.x)),
|
||
|
z = math.sin(adjustedRotation.x)
|
||
|
}
|
||
|
return direction
|
||
|
end
|
||
|
|
||
|
function RayCastGamePlayCamera(distance,flag)
|
||
|
local cameraRotation = GetGameplayCamRot()
|
||
|
local cameraCoord = GetGameplayCamCoord()
|
||
|
local direction = RotationToDirection(cameraRotation)
|
||
|
local destination = vector3(cameraCoord.x + direction.x * distance,
|
||
|
cameraCoord.y + direction.y * distance,
|
||
|
cameraCoord.z + direction.z * distance
|
||
|
)
|
||
|
if not flag then
|
||
|
flag = 1
|
||
|
end
|
||
|
|
||
|
local a, b, c, d, e = GetShapeTestResultIncludingMaterial(StartShapeTestRay(cameraCoord.x, cameraCoord.y, cameraCoord.z, destination.x, destination.y, destination.z, flag, -1, 1))
|
||
|
return b, c, e, destination
|
||
|
end
|
||
|
|
||
|
local lastweapon = nil
|
||
|
lib.onCache('weapon', function(weapon)
|
||
|
if not inMotelZone then return end
|
||
|
if not PlayerData.job then return end
|
||
|
if not config.breakinJobs[PlayerData.job.name] then return end
|
||
|
local motels = GlobalState.Motels
|
||
|
lastweapon = weapon
|
||
|
while weapon and weapon == lastweapon do
|
||
|
Wait(33)
|
||
|
if IsPedShooting(cache.ped) then
|
||
|
local _, bullet, _ = RayCastGamePlayCamera(200.0,1)
|
||
|
for k,data in pairs(config.motels) do
|
||
|
for k,v in pairs(data.doors) do
|
||
|
if #(vec3(bullet.x,bullet.y,bullet.z) - vec3(v.door.x,v.door.y,v.door.z)) < 2 and motels[data.motel].rooms[k].lock then
|
||
|
TriggerServerEvent('renzu_motels:Door', {
|
||
|
motel = data.motel,
|
||
|
index = k,
|
||
|
coord = v.door,
|
||
|
Mlo = data.Mlo,
|
||
|
})
|
||
|
local text
|
||
|
if data.Mlo then
|
||
|
local doorindex = k + (joaat(data.motel))
|
||
|
text = DoorSystemGetDoorState(doorindex) == 0 and 'Du ødelagde motel-døren'
|
||
|
else
|
||
|
text = 'Du ødelagde motel-døren'
|
||
|
end
|
||
|
Notify(text,'warning')
|
||
|
end
|
||
|
end
|
||
|
Wait(1000)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end)
|
||
|
|
||
|
RegisterNetEvent('renzu_motels:MessageOwner', function(data)
|
||
|
AddTextEntry('esxAdvancedNotification', data.message)
|
||
|
BeginTextCommandThefeedPost('esxAdvancedNotification')
|
||
|
ThefeedSetNextPostBackgroundColor(1)
|
||
|
AddTextComponentSubstringPlayerName(data.message)
|
||
|
EndTextCommandThefeedPostMessagetext('CHAR_FACEBOOK', 'CHAR_FACEBOOK', false, 1, data.motel, data.title)
|
||
|
EndTextCommandThefeedPostTicker(flash or false, true)
|
||
|
end)
|
||
|
|
||
|
Citizen.CreateThread(function()
|
||
|
while GlobalState.Motels == nil do Wait(1) end
|
||
|
for motel, data in pairs(config.motels) do
|
||
|
MotelZone(data)
|
||
|
end
|
||
|
CreateBlips()
|
||
|
end)
|