1520 lines
71 KiB
Lua
1520 lines
71 KiB
Lua
--[[
|
|
ESX Property - Properties Made Right!
|
|
Copyright (C) 2025 ESX-Framework
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
]] local GameBuild = GetGameBuildNumber()
|
|
Properties = {}
|
|
CurrentId = 0
|
|
local CurrentDrawing = {}
|
|
InProperty = false
|
|
PlayerKeys = {}
|
|
InCCTV = false
|
|
local Blips = {}
|
|
local Shell = nil
|
|
local PM = Config.PlayerManagement
|
|
local CreateThread = CreateThread
|
|
local Wait = Wait
|
|
local ShowingUIs = {Exit = false, Wardrobe = false, Storage = false, ExitShell = false}
|
|
local ox_inventory = exports.ox_inventory
|
|
local DoScreenFadeIn = DoScreenFadeIn
|
|
local PlayerPedId = PlayerPedId
|
|
local GetEntityCoords = GetEntityCoords
|
|
local GetEntityHeading = GetEntityHeading
|
|
local IsControlJustPressed = IsControlJustPressed
|
|
local IsControlPressed = IsControlPressed
|
|
local DoScreenFadeOut = DoScreenFadeOut
|
|
function RefreshBlips()
|
|
for i = 1, #Blips, 1 do
|
|
RemoveBlip(Blips[i])
|
|
Blips[i] = nil
|
|
end
|
|
|
|
for k, v in pairs(Properties) do
|
|
if v.Owned and Config.OwnedBlips then
|
|
if v.Owner == ESX.PlayerData.identifier then
|
|
local Blip = AddBlipForCoord(v.Entrance.x, v.Entrance.y, v.Entrance.z)
|
|
SetBlipSprite(Blip, 40)
|
|
SetBlipAsShortRange(Blip, true)
|
|
SetBlipScale(Blip, 0.8)
|
|
SetBlipColour(Blip, 0)
|
|
BeginTextCommandSetBlipName("STRING")
|
|
AddTextComponentString(v.Name)
|
|
EndTextCommandSetBlipName(Blip)
|
|
SetBlipCategory(Blip, 11)
|
|
Blips[#Blips + 1] = Blip
|
|
elseif PlayerKeys[k] then
|
|
local Blip = AddBlipForCoord(v.Entrance.x, v.Entrance.y, v.Entrance.z)
|
|
SetBlipSprite(Blip, GameBuild >= 2699 and 811 or 134)
|
|
SetBlipAsShortRange(Blip, true)
|
|
SetBlipScale(Blip, 0.9)
|
|
SetBlipColour(Blip, 26)
|
|
BeginTextCommandSetBlipName("STRING")
|
|
AddTextComponentString(v.Name)
|
|
EndTextCommandSetBlipName(Blip)
|
|
SetBlipCategory(Blip, 11)
|
|
Blips[#Blips + 1] = Blip
|
|
end
|
|
elseif not v.Owned and Config.ForSaleBlips then
|
|
local Blip = AddBlipForCoord(v.Entrance.x, v.Entrance.y, v.Entrance.z)
|
|
SetBlipSprite(Blip, 350)
|
|
SetBlipAsShortRange(Blip, true)
|
|
SetBlipScale(Blip, 0.7)
|
|
BeginTextCommandSetBlipName("STRING")
|
|
AddTextComponentString(v.Name)
|
|
EndTextCommandSetBlipName(Blip)
|
|
SetBlipCategory(Blip, 10)
|
|
Blips[#Blips + 1] = Blip
|
|
end
|
|
end
|
|
|
|
if PM.Enabled then
|
|
local Blip = AddBlipForCoord(PM.Locations.Entrance)
|
|
SetBlipSprite(Blip, 374)
|
|
SetBlipColour(Blip, 45)
|
|
SetBlipAsShortRange(Blip, true)
|
|
SetBlipScale(Blip, 0.7)
|
|
BeginTextCommandSetBlipName("STRING")
|
|
AddTextComponentString(TranslateCap("office_blip",PM.joblabel))
|
|
EndTextCommandSetBlipName(Blip)
|
|
Blips[#Blips + 1] = Blip
|
|
end
|
|
end
|
|
|
|
RegisterNetEvent("esx_property:syncProperties", function(properties, lastProperty)
|
|
while not ESX.PlayerLoaded and not ESX.PlayerData.identifier do
|
|
Wait(0)
|
|
end
|
|
Properties = properties
|
|
for house, data in pairs(Properties) do
|
|
if data.Keys then
|
|
for ident, vaues in pairs(data.Keys) do
|
|
if vaues and ident == ESX.PlayerData.identifier then
|
|
PlayerKeys[house] = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if lastProperty then
|
|
if Properties[lastProperty.id] and (Properties[lastProperty.id].Owner == ESX.PlayerData.identifier or PlayerKeys[lastProperty.id]) then
|
|
AttemptHouseEntry(lastProperty.id)
|
|
else
|
|
ESX.TriggerServerCallback('esx_property:RemoveLastProperty', function()
|
|
SetEntityCoords(ESX.PlayerData.ped, vector3(lastProperty.coords.x, lastProperty.coords.y, lastProperty.coords.z))
|
|
end)
|
|
end
|
|
end
|
|
RefreshBlips()
|
|
end)
|
|
|
|
RegisterNetEvent("esx_property:giveKeyAccess", function(Property)
|
|
ESX.TriggerServerCallback("esx_property:ShouldHaveKey", function(Should)
|
|
if Should then
|
|
PlayerKeys[Property] = true
|
|
end
|
|
end, Property)
|
|
end)
|
|
|
|
RegisterNetEvent("esx_property:RemoveKey", function(Property)
|
|
PlayerKeys[Property] = false
|
|
end)
|
|
|
|
RegisterNetEvent('esx:setJob')
|
|
AddEventHandler('esx:setJob', function(job)
|
|
RefreshBlips()
|
|
end)
|
|
|
|
exports("GetProperties", function()
|
|
return Properties
|
|
end)
|
|
|
|
function OpenInteractionMenu(PropertyId, Interaction)
|
|
local Property = Properties[PropertyId]
|
|
if Property.Owned then
|
|
if Interaction == "Wardrobe" then
|
|
Config.WardrobeInteraction(PropertyId, Interaction)
|
|
elseif Interaction == "Storage" then
|
|
if Config.OxInventory then
|
|
exports.ox_inventory:openInventory('stash', {id = 'property-' .. PropertyId, owner = Property.Owner})
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function GiveKeysMenu(Property)
|
|
ESX.TriggerServerCallback("esx_property:GetInsidePlayers", function(Players)
|
|
local Elements = {{unselectable = true, title = TranslateCap("nearby"), icon = "fas fa-user-plus"},
|
|
{title = TranslateCap("back"), icon = "fas fa-arrow-left", value = "go_back"}}
|
|
for i = 1, #Players, 1 do
|
|
Elements[#Elements + 1] = {title = Players[i].Name, icon = "far fa-user", index = Players[i].Id, value = "user"}
|
|
end
|
|
ESX.OpenContext("right", Elements, function(menu, element)
|
|
if element.value == "go_back" then
|
|
ManageKeys(Property)
|
|
elseif element.value == "user" then
|
|
ESX.TriggerServerCallback("esx_property:GiveKey", function(KeyGiven)
|
|
if KeyGiven then
|
|
ESX.ShowNotification(TranslateCap("gave_key",element.title), "success")
|
|
ESX.CloseContext()
|
|
else
|
|
ESX.ShowNotification(TranslateCap("key_cannot_give"), "error")
|
|
end
|
|
end, Property, element.index)
|
|
end
|
|
end)
|
|
end, Property)
|
|
end
|
|
|
|
function RemoveKeysMenu(Property)
|
|
ESX.TriggerServerCallback("esx_property:GetPlayersWithKeys", function(Players)
|
|
local Elements = {{unselectable = true, title = TranslateCap("remove_title"), icon = "fas fa-user-plus"},
|
|
{title = TranslateCap("back"), icon = "fas fa-arrow-left", value = "go_back"}}
|
|
for k, v in pairs(Players) do
|
|
local name = v.name
|
|
local Id = k
|
|
Elements[#Elements + 1] = {title = name, icon = "far fa-user", value = "user", id = Id}
|
|
end
|
|
ESX.OpenContext("right", Elements, function(menu, element)
|
|
if element.value == "go_back" then
|
|
ManageKeys(Property)
|
|
elseif element.value == "user" then
|
|
ESX.TriggerServerCallback("esx_property:RemoveKey", function(KeyGiven)
|
|
if KeyGiven then
|
|
ESX.ShowNotification(TranslateCap("key_revoke_success", element.title), "success")
|
|
ESX.CloseContext()
|
|
else
|
|
ESX.ShowNotification(TranslateCap("key_revoke_error"), "error")
|
|
end
|
|
end, Property, element.id)
|
|
end
|
|
end)
|
|
end, Property)
|
|
end
|
|
|
|
function ManageKeys(Property)
|
|
ESX.HideUI()
|
|
local Elements = {{unselectable = true, title = TranslateCap("key_management"), icon = "fas fa-key"},
|
|
{title = TranslateCap("back"), icon = "fas fa-arrow-left", value = "go_back"},
|
|
{title = TranslateCap("give_keys"), icon = "fas fa-plus", value = "give_keys"},
|
|
{title = TranslateCap("remove_keys"), icon = "fas fa-minus", value = "remove_keys"}}
|
|
|
|
ESX.OpenContext("right", Elements, function(menu, element)
|
|
if element.value == "go_back" then
|
|
OpenPropertyMenu(Property)
|
|
end
|
|
if element.value == "give_keys" then
|
|
GiveKeysMenu(Property)
|
|
end
|
|
if element.value == "remove_keys" then
|
|
RemoveKeysMenu(Property)
|
|
end
|
|
end)
|
|
end
|
|
|
|
function SetPropertyName(Property)
|
|
local Name = Properties[Property].setName ~= "" and Properties[Property].setName or Properties[Property].Name
|
|
local Elements = {{unselectable = true, title = TranslateCap("name_edit"), icon = "fa-solid fa-signature"},
|
|
{icon = "", title = TranslateCap("name"), input = true, inputType = "text", inputValue = Name, inputPlaceholder = Properties[Property].Name,
|
|
name = "setName"}, {icon = "fa-solid fa-check", title = TranslateCap("confirm"), name = "confirm"}}
|
|
|
|
ESX.OpenContext("right", Elements, function(menu, element)
|
|
if element.name == "confirm" then
|
|
ESX.TriggerServerCallback("esx_property:SetPropertyName", function(Set)
|
|
if Set then
|
|
ESX.ShowNotification(TranslateCap("name_edit_success",menu.eles[2].inputValue), "success")
|
|
ESX.CloseContext()
|
|
else
|
|
ESX.ShowNotification(TranslateCap("name_edit_error",menu.eles[2].inputValue), "error")
|
|
end
|
|
end, Property, menu.eles[2].inputValue)
|
|
end
|
|
end)
|
|
end
|
|
|
|
local SettingValue = ""
|
|
|
|
function PropertyMenuElements(PropertyId)
|
|
local Property = Properties[PropertyId]
|
|
local elements = {{unselectable = true, title = Property.setName ~= "" and Property.setName or Property.Name, icon = "fas fa-home"}}
|
|
if Property.Owned then
|
|
if Property.Locked then
|
|
table.insert(elements, {title = TranslateCap("door_locked"), icon = "fas fa-lock", value = 'property_unlock'})
|
|
else
|
|
table.insert(elements, {title = TranslateCap("door_unlocked"), icon = "fas fa-unlock", value = 'property_lock'})
|
|
end
|
|
if ESX.PlayerData.identifier == Property.Owner then
|
|
table.insert(elements,
|
|
{title = TranslateCap("name_manage"), description = TranslateCap("name_manage_desc"), icon = "fa-solid fa-signature", value = 'property_name'})
|
|
end
|
|
if not InProperty then
|
|
if ESX.PlayerData.identifier == Property.Owner then
|
|
table.insert(elements, {title = TranslateCap("key_management"), description = TranslateCap("key_management_desc"), icon = "fas fa-key", value = 'property_keys'})
|
|
table.insert(elements,
|
|
{title = TranslateCap("sell_title"), description = TranslateCap("sell_desc", ESX.Math.GroupDigits(ESX.Round(Property.Price * 0.6))),
|
|
icon = "fas fa-dollar-sign", value = 'property_sell'})
|
|
end
|
|
if Config.Raiding.Enabled and Property.Locked and ESX.PlayerData.job and ESX.GetPlayerData().job.name == "police" then
|
|
table.insert(elements, {title = TranslateCap("raid_title"), description = TranslateCap("raid_desc"), icon = "fas fa-bomb", value = 'property_raid'})
|
|
end
|
|
else
|
|
if (Config.CCTV.Enabled and Properties[PropertyId].cctv.enabled) and (ESX.PlayerData.identifier == Property.Owner or PlayerKeys[PropertyId]) then
|
|
table.insert(elements, {title = TranslateCap("cctv_title"), description = TranslateCap("cctv_desc"), icon = "fas fa-video", value = 'property_cctv'})
|
|
end
|
|
if (ESX.PlayerData.identifier == Property.Owner or PlayerKeys[PropertyId]) then
|
|
if Config.CanCustomiseInventoryAndWardrobePositions then
|
|
if Config.OxInventory then
|
|
table.insert(elements, {title = TranslateCap("inventory_title"), description = TranslateCap("inventory_desc"),
|
|
icon = "fa-solid fa-up-down-left-right", value = 'property_inventory'})
|
|
end
|
|
table.insert(elements, {title = TranslateCap("wardrobe_title"), description = TranslateCap("wardrobe_desc"), icon = "fa-solid fa-up-down-left-right",
|
|
value = 'property_wardrobe'})
|
|
end
|
|
table.insert(elements,
|
|
{title = TranslateCap("furniture_title"), description = TranslateCap("furniture_desc"), icon = "fas fa-boxes-stacked", value = 'property_furniture'})
|
|
end
|
|
end
|
|
if (not Property.Locked or Config.OwnerCanAlwaysEnter and ESX.PlayerData.identifier == Property.Owner) and not InProperty then
|
|
table.insert(elements, {title = TranslateCap("enter_title"), icon = "fas fa-door-open", value = 'property_enter'})
|
|
end
|
|
if Property.Locked and not InProperty and
|
|
not (Config.OwnerCanAlwaysEnter and ESX.PlayerData.identifier == Property.Owner or PlayerKeys[PropertyId]) then
|
|
table.insert(elements, {title = TranslateCap("knock_title"), icon = "fa-solid fa-hand-sparkles", value = 'property_knock'})
|
|
end
|
|
else
|
|
if not PM.Enabled then
|
|
table.insert(elements,
|
|
{title = TranslateCap("buy_title"), description = TranslateCap("buy_desc", ESX.Math.GroupDigits(ESX.Round(Property.Price))), icon = "fas fa-shopping-cart",
|
|
value = 'property_buy'})
|
|
else
|
|
if ESX.PlayerData.job.name == PM.job and ESX.PlayerData.job.grade >= PM.Permissions.SellProperty then
|
|
table.insert(elements, {title = TranslateCap("sellplayer_title"), description = TranslateCap("sellplayer_desc", ESX.Math.GroupDigits(ESX.Round(Property.Price))),
|
|
icon = "fas fa-shopping-cart", value = 'property_sell_re'})
|
|
end
|
|
end
|
|
if not Property.Locked and not InProperty then
|
|
table.insert(elements, {title = TranslateCap("view_title"), icon = "fas fa-door-open", value = 'property_enter'})
|
|
end
|
|
end
|
|
|
|
if InProperty and (not Property.Locked or Config.CanAlwaysExit) then
|
|
table.insert(elements, {title = TranslateCap("exit_title"), icon = "fas fa-sign-out-alt", value = 'property_exit'})
|
|
end
|
|
|
|
return elements
|
|
end
|
|
|
|
function OpenPropertyMenu(PropertyId)
|
|
if SettingValue ~= "" then
|
|
ESX.ShowNotification(TranslateCap("property_editing_error"))
|
|
return
|
|
end
|
|
ESX.HideUI()
|
|
local Property = Properties[PropertyId]
|
|
local elements = PropertyMenuElements(PropertyId)
|
|
|
|
ESX.OpenContext("right", elements, function(menu, element)
|
|
if element.value == "property_unlock" then
|
|
ESX.TriggerServerCallback("esx_property:toggleLock", function(IsUnlocked)
|
|
if IsUnlocked then
|
|
local eles = PropertyMenuElements(PropertyId)
|
|
exports["esx_context"]:Refresh(eles)
|
|
else
|
|
ESX.ShowNotification(TranslateCap("unlock_error"), "error")
|
|
end
|
|
end, PropertyId)
|
|
end
|
|
if element.value == "property_lock" then
|
|
ESX.TriggerServerCallback("esx_property:toggleLock", function(IsUnlocked)
|
|
if IsUnlocked then
|
|
local eles = PropertyMenuElements(PropertyId)
|
|
exports["esx_context"]:Refresh(eles)
|
|
else
|
|
ESX.ShowNotification(TranslateCap("lock_error"), "error")
|
|
end
|
|
end, PropertyId)
|
|
end
|
|
if element.value == "property_cctv" then
|
|
CCTV(PropertyId)
|
|
end
|
|
if element.value == "property_raid" then
|
|
ESX.TriggerServerCallback("esx_property:CanRaid", function(CanRaid)
|
|
if CanRaid then
|
|
ESX.Progressbar(TranslateCap("prep_raid"), 15000, {FreezePlayer = true, animation = Config.Raiding.Animation, onFinish = function()
|
|
ESX.ShowNotification(TranslateCap("raiding"), "success")
|
|
AttemptHouseEntry(PropertyId)
|
|
end, onCancel = function()
|
|
ESX.ShowNotification(TranslateCap("cancel_raiding"), "error")
|
|
end})
|
|
else
|
|
ESX.ShowNotification(TranslateCap("cannot_raid"), "error")
|
|
end
|
|
end, PropertyId)
|
|
end
|
|
if element.value == "property_enter" then
|
|
ESX.CloseContext()
|
|
AttemptHouseEntry(PropertyId)
|
|
end
|
|
if element.value == "property_keys" then
|
|
ESX.CloseContext()
|
|
ManageKeys(PropertyId)
|
|
end
|
|
if element.value == "property_name" then
|
|
ESX.CloseContext()
|
|
SetPropertyName(PropertyId)
|
|
end
|
|
if element.value == "property_furniture" then
|
|
ESX.CloseContext()
|
|
FurnitureMenu(PropertyId)
|
|
end
|
|
if element.value == "property_inventory" then
|
|
ESX.CloseContext()
|
|
ShowingUIs.Exit = false
|
|
SettingValue = "Storage"
|
|
Wait(20)
|
|
ESX.TextUI(TranslateCap("storage_pos_textui"))
|
|
while SettingValue ~= "" do
|
|
Wait(1)
|
|
if IsControlJustPressed(0, 47) then
|
|
SettingValue = ""
|
|
ESX.HideUI()
|
|
ESX.TriggerServerCallback("esx_property:SetInventoryPosition", function(Success)
|
|
if Success then
|
|
ESX.ShowNotification(TranslateCap("storage_pos_success"), "success")
|
|
else
|
|
ESX.ShowNotification(TranslateCap("storage_pos_error"), "error")
|
|
end
|
|
end, PropertyId, GetEntityCoords(ESX.PlayerData.ped))
|
|
break
|
|
end
|
|
end
|
|
end
|
|
if element.value == "property_wardrobe" then
|
|
ESX.CloseContext()
|
|
ShowingUIs.Exit = false
|
|
SettingValue = "Wardrobe"
|
|
Wait(20)
|
|
ESX.TextUI(TranslateCap("wardrobe_pos_textui"))
|
|
while SettingValue ~= "" do
|
|
Wait(1)
|
|
if IsControlJustPressed(0, 47) then
|
|
SettingValue = ""
|
|
ESX.HideUI()
|
|
ESX.TriggerServerCallback("esx_property:SetWardrobePosition", function(Success)
|
|
if Success then
|
|
ESX.ShowNotification(TranslateCap("wardrobe_pos_success"), "success")
|
|
else
|
|
ESX.ShowNotification(TranslateCap("wardrobe_pos_error"), "error")
|
|
end
|
|
end, PropertyId, GetEntityCoords(ESX.PlayerData.ped))
|
|
break
|
|
end
|
|
end
|
|
end
|
|
if element.value == "property_exit" then
|
|
ESX.CloseContext()
|
|
if SettingValue == "" then
|
|
AttemptHouseExit(PropertyId)
|
|
else
|
|
ESX.ShowNotification(TranslateCap("please_finish", SettingValue))
|
|
end
|
|
end
|
|
if element.value == "property_buy" then
|
|
ESX.TriggerServerCallback("esx_property:buyProperty", function(IsBought)
|
|
if IsBought then
|
|
local eles = PropertyMenuElements(PropertyId)
|
|
exports["esx_context"]:Refresh(eles)
|
|
else
|
|
ESX.ShowNotification(TranslateCap("cannot_afford"), "error")
|
|
end
|
|
end, PropertyId)
|
|
end
|
|
if element.value == "property_sell_re" then
|
|
local Elements = {{unselectable = true, title = TranslateCap("select_player")}}
|
|
ESX.TriggerServerCallback("esx_property:GetNearbyPlayers", function(Players)
|
|
if Players then
|
|
for i = 1, #Players do
|
|
Elements[#Elements + 1] = {title = Players[i].name, value = Players[i].source}
|
|
end
|
|
|
|
ESX.OpenContext("right", Elements, function(menu, element)
|
|
if element.value then
|
|
ESX.TriggerServerCallback("esx_property:attemptSellToPlayer", function(IsBought)
|
|
if IsBought then
|
|
local eles = PropertyMenuElements(PropertyId)
|
|
exports["esx_context"]:Refresh(eles)
|
|
else
|
|
ESX.ShowNotification(TranslateCap("cannot_sell"), "error")
|
|
end
|
|
end, PropertyId, element.value)
|
|
end
|
|
end)
|
|
end
|
|
end, PropertyId)
|
|
end
|
|
if element.value == "property_knock" then
|
|
ESX.ShowNotification(TranslateCap("knock_on_door"), "success")
|
|
ESX.TriggerServerCallback("esx_property:KnockOnDoor", function(HasKnocked)
|
|
if not HasKnocked then
|
|
ESX.ShowNotification(TranslateCap("nobody_home"), "error")
|
|
end
|
|
end, PropertyId)
|
|
end
|
|
if element.value == "property_sell" then
|
|
ESX.TriggerServerCallback("esx_property:sellProperty", function(IsSold)
|
|
if IsSold then
|
|
local eles = PropertyMenuElements(PropertyId)
|
|
exports["esx_context"]:Refresh(eles)
|
|
else
|
|
ESX.ShowNotification(TranslateCap("cannot_sell"), "error")
|
|
end
|
|
end, PropertyId)
|
|
end
|
|
end, function(menu)
|
|
CurrentDrawing.Showing = false
|
|
end)
|
|
end
|
|
|
|
function AttemptHouseExit(PropertyId)
|
|
local Property = Properties[PropertyId]
|
|
|
|
ESX.ShowNotification(TranslateCap("exiting"), "success")
|
|
FreezeEntityPosition(ESX.PlayerData.ped, true)
|
|
InProperty = false
|
|
CurrentId = 0
|
|
SettingValue = ""
|
|
ESX.HideUI()
|
|
ESX.UI.Menu.CloseAll()
|
|
SetRainLevel(-1)
|
|
DoScreenFadeOut(1500)
|
|
Wait(1500)
|
|
TriggerServerEvent("esx_property:leave", PropertyId)
|
|
if Shell then
|
|
DeleteObject(Shell)
|
|
Shell = nil
|
|
end
|
|
if Config.Furniture.Enabled then
|
|
for k, v in pairs(SpawnedFurniture) do
|
|
DeleteObject(v.obj)
|
|
end
|
|
SpawnedFurniture = {}
|
|
end
|
|
Wait(1500)
|
|
FreezeEntityPosition(ESX.PlayerData.ped, false)
|
|
DoScreenFadeIn(1500)
|
|
end
|
|
|
|
RegisterCommand("getoffset", function(source)
|
|
if InProperty then
|
|
local PlayerPed = ESX.PlayerData.ped
|
|
local Pcoords = GetEntityCoords(PlayerPed)
|
|
local Property = Properties[CurrentId]
|
|
local Interior = GetInteriorValues(Property.Interior)
|
|
print(vector3(Property.Entrance.x, Property.Entrance.y, 2000) - Pcoords)
|
|
SendNUIMessage({
|
|
link = tostring(vector3(Property.Entrance.x, Property.Entrance.y, 2000) - Pcoords)
|
|
})
|
|
end
|
|
end)
|
|
|
|
function AttemptHouseEntry(PropertyId)
|
|
local Property = Properties[PropertyId]
|
|
local Interior = GetInteriorValues(Property.Interior)
|
|
if Interior.type == "shell" and not Config.Shells then
|
|
ESX.ShowNotification(TranslateCap("shell_disabled"), "error")
|
|
return
|
|
end
|
|
ESX.ShowNotification(TranslateCap("entering"), "success")
|
|
CurrentId = PropertyId
|
|
ESX.UI.Menu.CloseAll()
|
|
local Property = Properties[CurrentId]
|
|
FreezeEntityPosition(ESX.PlayerData.ped, true)
|
|
DoScreenFadeOut(1500)
|
|
Wait(1500)
|
|
if Interior.type == "shell" then
|
|
ESX.Streaming.RequestModel(joaat(Property.Interior), function()
|
|
if Shell then
|
|
DeleteObject(Shell)
|
|
Shell = nil
|
|
end
|
|
local Pos = vector3(Property.Entrance.x, Property.Entrance.y, 2000)
|
|
Shell = CreateObjectNoOffset(joaat(Property.Interior), Pos + Interior.pos, false, false, false)
|
|
SetEntityHeading(Shell, 0.0)
|
|
while not DoesEntityExist(Shell) do
|
|
Wait(1)
|
|
end
|
|
FreezeEntityPosition(Shell, true)
|
|
end)
|
|
end
|
|
if Properties[PropertyId].furniture then
|
|
for k, v in pairs(Properties[PropertyId].furniture) do
|
|
ESX.Game.SpawnLocalObject(v.Name, v.Pos, function(object)
|
|
SetEntityCoordsNoOffset(object, v.Pos.x, v.Pos.y, v.Pos.z)
|
|
SetEntityHeading(object, v.Heading)
|
|
SetEntityAsMissionEntity(object, true, true)
|
|
FreezeEntityPosition(object, true)
|
|
SpawnedFurniture[k] = {obj = object, data = v}
|
|
end)
|
|
end
|
|
end
|
|
local ShowingTextUI2 = false
|
|
FreezeEntityPosition(ESX.PlayerData.ped, false)
|
|
TriggerServerEvent("esx_property:enter", PropertyId)
|
|
Wait(1500)
|
|
DoScreenFadeIn(1800)
|
|
InProperty = true
|
|
if not Config.OxInventory then
|
|
Interior.positions.Storage = nil
|
|
Properties[CurrentId].positions.Storage = nil
|
|
end
|
|
|
|
CreateThread(function()
|
|
while InProperty do
|
|
local Property = Properties[CurrentId]
|
|
local Sleep = 1000
|
|
local Near = false
|
|
SetRainLevel(0.0)
|
|
local PlayerPed = ESX.PlayerData.ped
|
|
local PlayerCoords = GetEntityCoords(PlayerPed)
|
|
if Interior.type == "shell" then
|
|
if #(PlayerCoords - vector3(Property.Entrance.x, Property.Entrance.y, 1999)) < 5.0 then
|
|
Sleep = 0
|
|
DrawMarker(27, vector3(Property.Entrance.x, Property.Entrance.y, 2000.2), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 50, 50, 200, 200,
|
|
false, false, 2, true, nil, nil, false)
|
|
if #(PlayerCoords.xy - vector2(Property.Entrance.x, Property.Entrance.y)) <= 2.5 then
|
|
Near = true
|
|
if not ShowingUIs.Exit then
|
|
|
|
local Pname = Properties[CurrentId].setName ~= "" and Properties[CurrentId].setName or Properties[CurrentId].Name
|
|
ESX.TextUI(TranslateCap("access_textui", Pname))
|
|
ShowingUIs.Exit = true
|
|
end
|
|
if IsControlJustPressed(0, 38) then
|
|
OpenPropertyMenu(CurrentId)
|
|
end
|
|
else
|
|
if not Near and ShowingUIs.Exit and SettingValue == "" then
|
|
ShowingUIs.Exit = false
|
|
ESX.HideUI()
|
|
ESX.CloseContext()
|
|
end
|
|
end
|
|
end
|
|
|
|
if Property.Owned then
|
|
for k, v in pairs(Properties[CurrentId].positions) do
|
|
local v = vector3(v.x, v.y, v.z)
|
|
local CanDo = true
|
|
if CanDo then
|
|
local Poss = vector3(Property.Entrance.x, Property.Entrance.y, 1999) - v
|
|
if #(PlayerCoords - Poss) < 5.0 then
|
|
Sleep = 0
|
|
DrawMarker(27, Poss, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 200, 50, 50, 200, false, false, 2, true, nil, nil, false)
|
|
if #(PlayerCoords - Poss) < 2.0 and SettingValue == "" then
|
|
Near = true
|
|
if not ShowingUIs[k] then
|
|
ShowingUIs[k] = true
|
|
|
|
ESX.TextUI(TranslateCap("access_textui", k))
|
|
end
|
|
if IsControlJustPressed(0, 38) then
|
|
OpenInteractionMenu(CurrentId, k)
|
|
end
|
|
else
|
|
if not Near and ShowingUIs[k] and SettingValue == "" then
|
|
ShowingUIs[k] = false
|
|
ESX.HideUI()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if not Near and ShowingUIs and SettingValue == "" then
|
|
ShowingTextUI2 = false
|
|
ESX.HideUI()
|
|
end
|
|
end
|
|
else
|
|
if #(PlayerCoords - Interior.pos) < 5.0 then
|
|
Sleep = 0
|
|
DrawMarker(27, vector3(Interior.pos.xy, Interior.pos.z - 0.98), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 50, 50, 200, 200, false, false,
|
|
2, true, nil, nil, false)
|
|
if #(PlayerCoords - Interior.pos) < 2.0 then
|
|
if not ShowingUIs.Exit then
|
|
ShowingUIs.Exit = true
|
|
local Pname = Properties[CurrentId].setName ~= "" and Properties[CurrentId].setName or Properties[CurrentId].Name
|
|
ESX.TextUI(TranslateCap("access_textui", Pname))
|
|
end
|
|
if IsControlJustPressed(0, 38) then
|
|
OpenPropertyMenu(CurrentId)
|
|
end
|
|
else
|
|
if ShowingUIs.Exit and SettingValue == "" then
|
|
ShowingUIs.Exit = false
|
|
ESX.HideUI()
|
|
ESX.CloseContext()
|
|
end
|
|
end
|
|
end
|
|
|
|
if Property.Owned then
|
|
for k, v in pairs(Properties[CurrentId].positions) do
|
|
v = vector3(v.x, v.y, v.z)
|
|
local CanDo = true
|
|
|
|
if CanDo then
|
|
if #(PlayerCoords - v) < 5.0 then
|
|
Sleep = 0
|
|
DrawMarker(27, vector3(v.xy, v.z - 0.98), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 200, 50, 50, 200, false, false, 2, true, nil,
|
|
nil, false)
|
|
if #(PlayerCoords - v) < 2.0 then
|
|
if not ShowingUIs[k] then
|
|
ShowingUIs[k] = true
|
|
ESX.TextUI(TranslateCap("access_textui", k))
|
|
end
|
|
if IsControlJustPressed(0, 38) then
|
|
OpenInteractionMenu(CurrentId, k)
|
|
end
|
|
else
|
|
if ShowingUIs[k] and SettingValue == "" then
|
|
ShowingUIs[k] = false
|
|
ESX.HideUI()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
Wait(Sleep)
|
|
end
|
|
end)
|
|
end
|
|
|
|
function StoreVehicle(PropertyId)
|
|
local Vehicle = GetVehiclePedIsIn(ESX.PlayerData.ped, false)
|
|
if Vehicle then
|
|
local VehProperties = ESX.Game.GetVehicleProperties(Vehicle)
|
|
VehProperties.DisplayName = GetLabelText(GetDisplayNameFromVehicleModel(VehProperties.model))
|
|
ESX.TriggerServerCallback("esx_property:StoreVehicle", function(result)
|
|
if result then
|
|
SetEntityAsMissionEntity(Vehicle, true, true)
|
|
DeleteVehicle(Vehicle)
|
|
ESX.ShowNotification(TranslateCap("store_success"), "success")
|
|
return
|
|
else
|
|
ESX.ShowNotification(TranslateCap("store_error"), "error")
|
|
return
|
|
end
|
|
end, PropertyId, VehProperties)
|
|
end
|
|
end
|
|
|
|
function AccessGarage(PropertyId)
|
|
ESX.TriggerServerCallback("esx_property:AccessGarage", function(Vehicles)
|
|
if Vehicles then
|
|
local elements = {{unselectable = true, icon = "fas fa-warehouse", title = TranslateCap("property_garage")}}
|
|
for k, v in pairs(Vehicles) do
|
|
elements[#elements + 1] = {title = v.vehicle.DisplayName .. " | " .. v.vehicle.plate, Properties = v.vehicle, index = k}
|
|
end
|
|
ESX.OpenContext("right", elements, function(menu, element)
|
|
if element.Properties then
|
|
ESX.CloseContext()
|
|
ESX.ShowNotification(TranslateCap("retriving_notify",element.Properties.DisplayName))
|
|
if ESX.Game.IsSpawnPointClear(vector3(Properties[PropertyId].garage.pos.x, Properties[PropertyId].garage.pos.y,
|
|
Properties[PropertyId].garage.pos.z), 3.0) then
|
|
ESX.Game.SpawnVehicle(element.Properties.model, Properties[PropertyId].garage.pos, Properties[PropertyId].garage.Heading,
|
|
function(vehicle)
|
|
SetEntityAsMissionEntity(vehicle, true, true)
|
|
ESX.Game.SetVehicleProperties(vehicle, element.Properties)
|
|
TaskWarpPedIntoVehicle(ESX.PlayerData.ped, vehicle, -1)
|
|
SetModelAsNoLongerNeeded(element.Properties.model)
|
|
TriggerServerEvent("esx_property:SetVehicleOut", PropertyId, element.index)
|
|
end)
|
|
end
|
|
end
|
|
end)
|
|
else
|
|
ESX.ShowNotification(TranslateCap("cannot_access"), "error")
|
|
return
|
|
end
|
|
end, PropertyId)
|
|
end
|
|
|
|
CreateThread(function()
|
|
local ShowingTextUI = false
|
|
while true do
|
|
local Sleep = 2000
|
|
|
|
if #(Properties) > 0 then
|
|
Sleep = 800
|
|
local nearby = false
|
|
for i = 1, #(Properties) do
|
|
if Properties[i].Entrance then
|
|
local GetEntityCoords = GetEntityCoords
|
|
local IsControlJustPressed = IsControlJustPressed
|
|
local DrawMarker = DrawMarker
|
|
local Coords = GetEntityCoords(ESX.PlayerData.ped)
|
|
local Entrance = vector3(Properties[i].Entrance.x, Properties[i].Entrance.y, Properties[i].Entrance.z)
|
|
if not InCCTV then
|
|
if #(Coords - Entrance) < 10.0 then
|
|
Sleep = 0
|
|
DrawMarker(27, Entrance, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 50, 200, 50, 200, false, false, 2, true, nil, nil, false)
|
|
if #(Coords - Entrance) < 1.5 then
|
|
nearby = true
|
|
local PropertyName = Properties[i].setName ~= "" and Properties[i].setName or Properties[i].Name
|
|
if not CurrentDrawing.Showing or CurrentDrawing.Name ~= PropertyName then
|
|
CurrentDrawing.Name = PropertyName
|
|
CurrentDrawing.Showing = true
|
|
ESX.TextUI(TranslateCap("access_textui", PropertyName))
|
|
end
|
|
if IsControlJustPressed(0, 38) then
|
|
OpenPropertyMenu(i)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if Properties[i].garage.enabled and Properties[i].garage.pos and (ESX.PlayerData.identifier == Properties[i].Owner or PlayerKeys[i]) then
|
|
local Garage = vector3(Properties[i].garage.pos.x, Properties[i].garage.pos.y, Properties[i].garage.pos.z)
|
|
if #(Coords - Garage) < 10.0 then
|
|
Sleep = 0
|
|
DrawMarker(36, Garage, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.5, 1.5, 1.5, 50, 200, 50, 200, false, false, 2, true, nil, nil, false)
|
|
if #(Coords - Garage) < 3.0 then
|
|
nearby = true
|
|
if GetVehiclePedIsUsing(ESX.PlayerData.ped) ~= 0 then
|
|
local veh = GetVehiclePedIsIn(ESX.PlayerData.ped, false)
|
|
local vehmodel = GetEntityModel(veh)
|
|
local DisplayName = GetLabelText(GetDisplayNameFromVehicleModel(vehmodel))
|
|
if not CurrentDrawing.Showing or CurrentDrawing.Name ~= DisplayName then
|
|
CurrentDrawing.Name = DisplayName
|
|
CurrentDrawing.Showing = true
|
|
ESX.TextUI(TranslateCap("store_textui", DisplayName))
|
|
end
|
|
else
|
|
if not CurrentDrawing.Showing or CurrentDrawing.Name ~= "Garage" then
|
|
CurrentDrawing.Name = "Garage"
|
|
CurrentDrawing.Showing = true
|
|
ESX.TextUI(TranslateCap("access_textui", "garage"))
|
|
end
|
|
end
|
|
if IsControlJustPressed(0, 38) then
|
|
if GetVehiclePedIsUsing(ESX.PlayerData.ped) ~= 0 then
|
|
StoreVehicle(i)
|
|
else
|
|
AccessGarage(i)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if not nearby and CurrentDrawing.Showing and SettingValue == "" then
|
|
ESX.HideUI()
|
|
CurrentDrawing.Showing = false
|
|
ESX.CloseContext()
|
|
end
|
|
end
|
|
Wait(Sleep)
|
|
end
|
|
end)
|
|
|
|
function OpenPMQuickMenu(Action)
|
|
if Action == "Entrance" then
|
|
DoScreenFadeOut(1500)
|
|
Wait(1500)
|
|
ESX.TriggerServerCallback("esx_property:PMenterOffice", function(HasEntered)
|
|
if HasEntered then
|
|
ESX.ShowNotification(TranslateCap("enter_office"), "success")
|
|
else
|
|
ESX.ShowNotification(TranslateCap("enter_office_error"), "error")
|
|
end
|
|
Wait(1500)
|
|
DoScreenFadeIn(1500)
|
|
end)
|
|
elseif Action == "Exit" then
|
|
DoScreenFadeOut(1500)
|
|
Wait(1500)
|
|
ESX.TriggerServerCallback("esx_property:PMexitOffice", function(HasExited)
|
|
if HasExited then
|
|
ESX.ShowNotification(TranslateCap("exit_office"), "success")
|
|
else
|
|
ESX.ShowNotification(TranslateCap("exit_office_error"), "error")
|
|
end
|
|
Wait(1500)
|
|
DoScreenFadeIn(1500)
|
|
end)
|
|
elseif Action == "Properties" then
|
|
TriggerEvent("esx_property:AdminMenu")
|
|
|
|
elseif Action == "ActionsMenu" then
|
|
local elements = {{unselectable = true, title = TranslateCap("actions"), value = "RealEstateActions"}}
|
|
|
|
if ESX.PlayerData.job.name == PM.job then
|
|
if ESX.PlayerData.job.grade >= PM.Permissions.CreateProperty then
|
|
elements[#elements + 1] = {title = TranslateCap("property_create"), value = "CreateProperty"}
|
|
end
|
|
if ESX.PlayerData.job.grade >= PM.Permissions.ManagePropertiesFromQuickActions then
|
|
elements[#elements + 1] = {title = TranslateCap("property_manage"), value = "manage"}
|
|
end
|
|
end
|
|
ESX.OpenContext("right", elements, function(menu, element)
|
|
if element.value == "CreateProperty" then
|
|
TriggerEvent("esx_property:CreateProperty")
|
|
end
|
|
if element.value == "manage" then
|
|
TriggerEvent("esx_property:AdminMenu")
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
|
|
ESX.RegisterInput(TranslateCap("realestate_command"), TranslateCap("realestate_command_desc"), "keyboard", "F5", function()
|
|
ESX.TriggerServerCallback('esx_property:CanAccessRealEstateMenu', function(Access)
|
|
if Access then
|
|
OpenPMQuickMenu("ActionsMenu")
|
|
end
|
|
end)
|
|
end)
|
|
|
|
local PMdrawing = {Entrance = false, Exit = false}
|
|
CreateThread(function()
|
|
while PM.Enabled do
|
|
local Sleep = 2500
|
|
local DrawMarker = DrawMarker
|
|
if ESX.IsPlayerLoaded() then
|
|
if ESX.PlayerData.job and ESX.PlayerData.job.name == PM.job then
|
|
Sleep = 1500
|
|
|
|
local Coords = GetEntityCoords(ESX.PlayerData.ped)
|
|
local nearby = false
|
|
|
|
for k, v in pairs(PM.Locations) do
|
|
local Dist = #(Coords - v)
|
|
if Dist <= 10.0 then
|
|
nearby = true
|
|
Sleep = 0
|
|
DrawMarker(27, v, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 50, 200, 50, 200, false, false, 2, true, nil, nil, false)
|
|
if Dist <= 1.5 then
|
|
if not PMdrawing[k] then
|
|
PMdrawing[k] = true
|
|
ESX.TextUI(TranslateCap("realestate_textui", k))
|
|
end
|
|
if IsControlJustPressed(0, 38) then
|
|
OpenPMQuickMenu(k)
|
|
end
|
|
end
|
|
else
|
|
if not nearby and PMdrawing[k] then
|
|
ESX.HideUI()
|
|
PMdrawing[k] = false
|
|
ESX.CloseContext()
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
Wait(Sleep)
|
|
end
|
|
end)
|
|
|
|
local HouseData = {}
|
|
|
|
RegisterNetEvent("esx_property:CreateProperty", function()
|
|
ESX.TriggerServerCallback('esx_property:CanCreateProperty', function(data)
|
|
if data then
|
|
local GetEntityCoords = GetEntityCoords
|
|
local GetStreetNameAtCoord = GetStreetNameAtCoord
|
|
local GetStreetNameFromHashKey = GetStreetNameFromHashKey
|
|
local Pcoords = GetEntityCoords(ESX.PlayerData.ped)
|
|
local StreetHash = GetStreetNameAtCoord(Pcoords.x, Pcoords.y, Pcoords.z)
|
|
local StreetName = GetStreetNameFromHashKey(StreetHash)
|
|
local Zone = GetZoneAtCoords(Pcoords.x, Pcoords.y, Pcoords.z)
|
|
local ZoneScum = GetZoneScumminess(Zone)
|
|
local SuggestedPrice = Config.ZonePriceOptions.Enabled and Config.ZonePriceOptions.Default * Config.ZonePrices[ZoneScum] or nil
|
|
HouseData = {}
|
|
local Property = {{unselectable = true, icon = "fas fa-plus", title = TranslateCap("menu_title")},
|
|
{value = 0, title = TranslateCap("element_title1"), icon = "fas fa-list-ol", description = TranslateCap("element_description1"), input = true,
|
|
inputType = "number", inputPlaceholder = "Number...", inputValue = nil, inputMin = 1, inputMax = 90000, index = "hnumber"},
|
|
{title = TranslateCap("element_title2"), icon = "fas fa-dollar-sign", input = true, inputType = "number",description = TranslateCap("element_description2"),
|
|
inputPlaceholder = "Price...", inputValue = SuggestedPrice, inputMin = 1, inputMax = 900000000, index = "price"},
|
|
{title = TranslateCap("element_title3"), description = TranslateCap("element_description3"), icon = "fas fa-home", index = "interior"},
|
|
{title = TranslateCap("element_title4"), description = TranslateCap("element_description4"), icon = "fas fa-warehouse", value = {enabled = false},
|
|
index = "garage", disabled = not (Config.Garage.Enabled)},
|
|
{title = TranslateCap("element_title5"), description = TranslateCap("element_description5"), icon = "fas fa-video",
|
|
value = {enabled = false, rot = GetGameplayCamRot(2), maxleft = 80, maxright = -20}, index = "cctv",
|
|
disabled = not (Config.CCTV.Enabled)},
|
|
{title = TranslateCap("element_title6"),description = TranslateCap("element_description6"), icon = "fas fa-map-marker-alt", index = "entrance"},
|
|
{title = TranslateCap("element_create_title"), icon = "fas fa-check", description = TranslateCap("element_create_desc_1"), index = "creation"}}
|
|
local function OpenCreate()
|
|
local opos = {}
|
|
ESX.OpenContext("right", Property, function(menu, element)
|
|
if menu.eles[2] and menu.eles[2].inputValue and menu.eles[1].title == TranslateCap("menu_title") then
|
|
Property[2].inputValue = menu.eles[2].inputValue
|
|
HouseData.name = menu.eles[2].inputValue .. " " .. StreetName
|
|
end
|
|
if menu.eles[3] and menu.eles[3].inputValue and menu.eles[1].title == TranslateCap("menu_title") then
|
|
Property[3].inputValue = menu.eles[3].inputValue
|
|
HouseData.price = menu.eles[3].inputValue
|
|
end
|
|
if element.index then
|
|
if element.index == "entrance" then
|
|
local PlayerPos = GetEntityCoords(ESX.PlayerData.ped)
|
|
HouseData.entrance = {x = ESX.Math.Round(PlayerPos.x, 2), y = ESX.Math.Round(PlayerPos.y, 2), z = ESX.Math.Round(PlayerPos.z, 2) - 0.98}
|
|
Property[7].title = TranslateCap("entrance_set_title")
|
|
Property[7].description = TranslateCap("entrance_set_description",HouseData.entrance.x, HouseData.entrance.y, HouseData.entrance.z)
|
|
OpenCreate()
|
|
end
|
|
if element.index == "selectedinterior" then
|
|
HouseData.interior = element.value
|
|
Property[4].title = TranslateCap("interior_set_title")
|
|
Property[4].description = TranslateCap("interior_set_description",element.title)
|
|
OpenCreate()
|
|
end
|
|
if element.index == "IPL" then
|
|
local ints = {{unselectable = true, icon = "fas fa-warehouse", title = TranslateCap("ipl_title")}}
|
|
for i = 1, #(Config.Interiors.IPL) do
|
|
ints[#ints + 1] = {title = Config.Interiors.IPL[i].label, index = "selectedinterior", value = Config.Interiors.IPL[i].value}
|
|
exports["esx_context"]:Refresh(ints, "right")
|
|
end
|
|
end
|
|
if element.index == "Shells" then
|
|
local ints = {{unselectable = true, icon = "fas fa-warehouse", title = TranslateCap("shell_title")}}
|
|
for i = 1, #(Config.Interiors.Shells) do
|
|
ints[#ints + 1] = {title = Config.Interiors.Shells[i].label, index = "selectedinterior", value = Config.Interiors.Shells[i].value}
|
|
exports["esx_context"]:Refresh(ints, "right")
|
|
end
|
|
end
|
|
if element.index == "interior" then
|
|
local catsa = {{unselectable = true, icon = "fas fa-warehouse", title = TranslateCap("types_title")},
|
|
{title = TranslateCap("ipl_title"), description = TranslateCap("ipl_description"), index = "IPL"}}
|
|
if Config.Shells then
|
|
catsa[3] = {title = TranslateCap("shell_title"), description = TranslateCap("shell_description"), index = "Shells"}
|
|
end
|
|
exports["esx_context"]:Refresh(catsa, "right")
|
|
end
|
|
if element.index == "return" then
|
|
OpenCreate()
|
|
end
|
|
if element.index == "cctv" then
|
|
local status = Property[6].value.enabled and TranslateCap("enabled") or TranslateCap("disabled")
|
|
opos = {{unselectable = true, icon = "fas fa-video", title = TranslateCap("cctv_settings")},
|
|
{title = TranslateCap("toggle_title"), icon = status == TranslateCap("enabled") and "fas fa-eye" or "fas fa-eye-slash",
|
|
description = TranslateCap("toggle_description",status), index = "ToggleCCTV"},
|
|
{title = TranslateCap("cctv_set_title"), icon = "fas fa-rotate", disabled = not Property[6].value.enabled,
|
|
description = TranslateCap("cctv_set_description"), index = "SetCCTVangle"},
|
|
{title = TranslateCap("back"), icon = "fas fa-arrow-left", description = TranslateCap("back_description"), index = "return"}}
|
|
exports["esx_context"]:Refresh(opos, "right")
|
|
end
|
|
if element.index == "ToggleCCTV" then
|
|
Property[6].value.enabled = not Property[6].value.enabled
|
|
local status = Property[6].value.enabled and TranslateCap("enabled") or TranslateCap("disabled")
|
|
opos = {{unselectable = true, icon = "fas fa-video", title = TranslateCap("cctv_settings")},
|
|
{title = TranslateCap("toggle_title"), icon = status == TranslateCap("enabled") and "fas fa-eye" or "fas fa-eye-slash",
|
|
description = TranslateCap("toggle_description",status), index = "ToggleCCTV"},
|
|
{title = TranslateCap("cctv_set_title"), icon = "fas fa-rotate", disabled = not Property[6].value.enabled,
|
|
description = TranslateCap("cctv_set_description"), index = "SetCCTVangle"},
|
|
{title = TranslateCap("back"), icon = "fas fa-arrow-left", description = TranslateCap("back_description"), index = "return"}}
|
|
exports["esx_context"]:Refresh(opos, "right")
|
|
end
|
|
if Config.Garage.Enabled and element.index == "garage" then
|
|
local status = Property[5].value.enabled and TranslateCap("enabled") or TranslateCap("disabled")
|
|
opos = {{unselectable = true, icon = "fas fa-warehouse", title = TranslateCap("garage_settings")},
|
|
{title = TranslateCap("toggle_title"), icon = status == TranslateCap("enabled") and "fa-solid fa-toggle-on" or "fa-solid fa-toggle-off",
|
|
description = TranslateCap("toggle_description",status), index = "ToggleGarage"}}
|
|
if Property[5].value.enabled then
|
|
opos[#opos + 1] = {title = TranslateCap("garage_set_title"), icon = "fas fa-map-marker-alt", disabled = not Property[5].value.enabled,
|
|
description = TranslateCap("garage_set_description"), index = "SetGaragePos"}
|
|
if Property[5].value.pos then
|
|
opos[#opos + 1] = {title = TranslateCap("back"), icon = "fas fa-arrow-left", description = TranslateCap("back_description"), index = "return"}
|
|
end
|
|
else
|
|
opos[#opos + 1] = {title = TranslateCap("back"), icon = "fas fa-arrow-left", description = TranslateCap("back_description"), index = "return"}
|
|
end
|
|
exports["esx_context"]:Refresh(opos, "right")
|
|
end
|
|
if element.index == "ToggleGarage" then
|
|
Property[5].value.enabled = not Property[5].value.enabled
|
|
local status = Property[5].value.enabled and TranslateCap("enabled") or TranslateCap("disabled")
|
|
opos = {{unselectable = true, icon = "fas fa-warehouse", title = TranslateCap("garage_settings")},
|
|
{title = TranslateCap("toggle_title"), icon = status == TranslateCap("enabled") and "fa-solid fa-toggle-on" or "fa-solid fa-toggle-off",
|
|
description = TranslateCap("toggle_description",status), index = "ToggleGarage"}}
|
|
if Property[5].value.enabled then
|
|
opos[#opos + 1] = {title = TranslateCap("garage_set_title"), icon = "fas fa-map-marker-alt", disabled = not Property[5].value.enabled,
|
|
description = TranslateCap("garage_set_description"), index = "SetGaragePos"}
|
|
else
|
|
opos[#opos + 1] = {title = TranslateCap("back"), icon = "fas fa-arrow-left", description = TranslateCap("back_description"), index = "return"}
|
|
end
|
|
exports["esx_context"]:Refresh(opos, "right")
|
|
end
|
|
if element.index == "SetGaragePos" then
|
|
ESX.CloseContext()
|
|
ESX.TextUI(TranslateCap("garage_textui"))
|
|
while true do
|
|
Wait(0)
|
|
if IsControlJustPressed(0, 38) then
|
|
local PlayerPos = GetEntityCoords(ESX.PlayerData.ped)
|
|
Property[5].value.pos = GetEntityCoords(ESX.PlayerData.ped)
|
|
Property[5].value.heading = GetEntityHeading(ESX.PlayerData.ped)
|
|
ESX.HideUI()
|
|
OpenCreate()
|
|
break
|
|
end
|
|
end
|
|
end
|
|
if element.index == "SetCCTVangle" then
|
|
ESX.CloseContext()
|
|
ESX.TextUI(TranslateCap("cctv_textui_1"))
|
|
local stage = "angle"
|
|
while true do
|
|
Wait(0)
|
|
if IsControlJustPressed(0, 38) then
|
|
if stage == "angle" then
|
|
Property[6].value.rot = GetGameplayCamRot(2)
|
|
ESX.TextUI(TranslateCap("cctv_textui_2"))
|
|
stage = "maxright"
|
|
elseif stage == "maxright" then
|
|
Property[6].value.maxright = GetGameplayCamRot(2).z
|
|
ESX.TextUI(TranslateCap("cctv_textui_3"))
|
|
stage = "maxleft"
|
|
elseif stage == "maxleft" then
|
|
Property[6].value.maxleft = GetGameplayCamRot(2).z
|
|
ESX.HideUI()
|
|
OpenCreate()
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if element.index == "creation" then
|
|
if HouseData.price and HouseData.name and HouseData.entrance and HouseData.interior then
|
|
local newProperty = {name = HouseData.name, price = HouseData.price, interior = HouseData.interior, entrance = HouseData.entrance,
|
|
cctv = Property[6].value, garage = Property[5].value}
|
|
TriggerServerEvent("esx_property:server:createProperty", newProperty)
|
|
ESX.ShowNotification(TranslateCap("create_success"), "success")
|
|
ESX.CloseContext()
|
|
HouseData = {}
|
|
else
|
|
ESX.ShowNotification(TranslateCap("missing_data"), "error")
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
OpenCreate()
|
|
end
|
|
end)
|
|
end)
|
|
|
|
RegisterNetEvent("esx_property:AdminMenu", function()
|
|
ESX.TriggerServerCallback('esx_property:IsAdmin', function(data)
|
|
if data then
|
|
|
|
function ManageProperty(currentProperty)
|
|
local Interior = GetInteriorValues(Properties[currentProperty].Interior)
|
|
ESX.TriggerServerCallback('esx_property:IsAdmin', function(data)
|
|
if data then
|
|
local opos = {}
|
|
local function GetData()
|
|
local elements = {{unselectable = true, icon = "fas fa-cogs", title = "Property Management"},
|
|
{title = TranslateCap("back"), icon = "fas fa-arrow-left", value = "back"},
|
|
{title = "Toggle Lock", icon = (Properties[currentProperty].Locked and "fas fa-lock") or "fas fa-unlock",
|
|
description = "Lock/Unlock The Property.", value = "lock"},
|
|
{title = "Enter", description = "Force Entry Into The Property.", icon = "fas fa-door-open", value = "enter"},
|
|
{title = "Price", icon = "fas fa-dollar-sign", description = "Alter The Price Of The Property.", value = "price"},
|
|
{title = "Set Interior", description = "Renovate The Property`s Interior.", icon = "fas fa-home", value = "interior"},
|
|
{title = "Entrance", description = "Set The Entrance As Your Position.", icon = "fas fa-map-marker-alt",
|
|
value = "entrance"}}
|
|
if Properties[currentProperty].setName ~= "" then
|
|
elements[#elements + 1] = {title = "Clear Custom Name", icon = "fa-solid fa-ban",
|
|
description = "Current Name: " .. Properties[currentProperty].setName, value = "remove_custom_name"}
|
|
end
|
|
if Config.Furniture.Enabled and #(Properties[currentProperty].furniture) > 0 then
|
|
elements[#elements + 1] = {title = "Reset Furniture", description = "Delete All Property Furniture", icon = "fas fa-eraser",
|
|
value = "refurni"}
|
|
end
|
|
if Config.Garage.Enabled then
|
|
elements[#elements + 1] = {title = "Garage", description = "Change Garage Settings", icon = "fa-solid fa-warehouse", value = "garage"}
|
|
end
|
|
if Config.CCTV.Enabled then
|
|
elements[#elements + 1] = {title = "CCTV", description = "Change CCTV Settings", icon = "fa-solid fa-camera", value = "cctv"}
|
|
end
|
|
if (Config.OxInventory) and Properties[currentProperty].positions.Storage and
|
|
(ESX.Round(Interior.positions.Storage.x, 2) ~= Properties[currentProperty].positions.Storage.x or
|
|
ESX.Round(Interior.positions.Storage.y, 2) ~= Properties[currentProperty].positions.Storage.y) then
|
|
elements[#elements + 1] = {title = "Reset Storage Position", description = "Set Storage Position To Interior Default.",
|
|
icon = "fas fa-eraser", value = "restorage"}
|
|
end
|
|
if Interior.positions.Wardrobe then
|
|
if ESX.Round(Interior.positions.Wardrobe.x, 2) ~= ESX.Round(Properties[currentProperty].positions.Wardrobe.x, 2) or
|
|
ESX.Round(Interior.positions.Wardrobe.y, 2) ~= ESX.Round(Properties[currentProperty].positions.Wardrobe.y, 2) then
|
|
elements[#elements + 1] = {title = "Reset Wardrobe Position", description = "Set Wardrobe Position To Interior Default.",
|
|
icon = "fas fa-eraser", value = "rewardrobe"}
|
|
end
|
|
end
|
|
if Properties[currentProperty].Owned then
|
|
elements[#elements + 1] = {title = "Remove Owner", icon = "fas fa-user-times", description = "Evict The Owner Of The Property.",
|
|
value = "removeowner"}
|
|
end
|
|
return elements
|
|
end
|
|
ESX.OpenContext("right", GetData(), function(menu, element)
|
|
if element.value then
|
|
if element.value == "lock" then
|
|
ESX.TriggerServerCallback("esx_property:toggleLock", function(IsUnlocked)
|
|
if IsUnlocked then
|
|
ESX.ShowNotification("Lock Toggled!", "success")
|
|
exports["esx_context"]:Refresh(GetData())
|
|
else
|
|
ESX.ShowNotification("You Cannot Lock This Property", "error")
|
|
end
|
|
end, currentProperty)
|
|
end
|
|
if element.value == "enter" then
|
|
AttemptHouseEntry(currentProperty)
|
|
end
|
|
if element.value == "removeowner" then
|
|
ESX.TriggerServerCallback("esx_property:evictOwner", function(Evicted)
|
|
if Evicted then
|
|
ESX.ShowNotification("Owner Evicted!", "success")
|
|
exports["esx_context"]:Refresh(GetData())
|
|
else
|
|
ESX.ShowNotification("You Cannot Evict This Owner!", "error")
|
|
end
|
|
end, currentProperty)
|
|
end
|
|
if element.value == "garage" then
|
|
local status = Properties[currentProperty].garage.enabled and TranslateCap("enabled") or TranslateCap("disabled")
|
|
opos = {{unselectable = true, icon = "fas fa-warehouse", title = TranslateCap("garage_settings")},
|
|
{title = "Toggle Usage", icon = status == TranslateCap("enabled") and "fa-solid fa-toggle-on" or "fa-solid fa-toggle-off",
|
|
description = "Current Status: " .. status, value = "ToggleGarage"}}
|
|
if Properties[currentProperty].garage.enabled then
|
|
opos[#opos + 1] = {title = "Set Position", icon = "fas fa-map-marker-alt",
|
|
disabled = not Properties[currentProperty].garage.enabled,
|
|
description = "Sets the Garage Position to your Players Position", value = "SetGaragePos"}
|
|
if Properties[currentProperty].garage.pos then
|
|
opos[#opos + 1] = {title = TranslateCap("back"), icon = "fas fa-arrow-left", description = "return to Property Management.",
|
|
value = "return"}
|
|
end
|
|
else
|
|
opos[#opos + 1] = {title = TranslateCap("back"), icon = "fas fa-arrow-left", description = "return to Property Management", value = "return"}
|
|
end
|
|
exports["esx_context"]:Refresh(opos, "right")
|
|
end
|
|
if element.value == "cctv" then
|
|
local status = Properties[currentProperty].cctv.enabled and TranslateCap("enabled") or TranslateCap("disabled")
|
|
opos = {{unselectable = true, icon = "fas fa-warehouse", title = TranslateCap("cctv_settings")},
|
|
{title = "Toggle Usage", icon = status == TranslateCap("enabled") and "fa-solid fa-toggle-on" or "fa-solid fa-toggle-off",
|
|
description = "Current Status: " .. status, value = "ToggleCCTV"}}
|
|
if Properties[currentProperty].cctv.enabled then
|
|
opos[#opos + 1] = {title = "Set Angle", icon = "fas fa-map-marker-alt", disabled = not Properties[currentProperty].cctv.enabled,
|
|
description = "Sets the Angle of the Camera.", value = "SetCCTVangle"}
|
|
if Properties[currentProperty].cctv.rot then
|
|
opos[#opos + 1] = {title = TranslateCap("back"), icon = "fas fa-arrow-left", description = "return to Property Management.",
|
|
value = "return"}
|
|
end
|
|
else
|
|
opos[#opos + 1] = {title = TranslateCap("back"), icon = "fas fa-arrow-left", description = "return to Property Management", value = "return"}
|
|
end
|
|
exports["esx_context"]:Refresh(opos, "right")
|
|
end
|
|
if element.value == "ToggleGarage" then
|
|
ESX.TriggerServerCallback("esx_property:toggleGarage", function(IsUnlocked, enabled)
|
|
if IsUnlocked then
|
|
ESX.ShowNotification("Garage Toggled!", "success")
|
|
local status = enabled and TranslateCap("enabled") or TranslateCap("disabled")
|
|
opos = {{unselectable = true, icon = "fas fa-warehouse", title = TranslateCap("garage_settings")},
|
|
{title = "Toggle Usage", icon = status == TranslateCap("enabled") and "fa-solid fa-toggle-on" or "fa-solid fa-toggle-off",
|
|
description = "Current Status: " .. status, value = "ToggleGarage"}}
|
|
if enabled then
|
|
opos[#opos + 1] = {title = "Set Position", icon = "fas fa-map-marker-alt", disabled = not enabled,
|
|
description = "Sets the Garage Position to your Players Position", value = "SetGaragePos"}
|
|
if Properties[currentProperty].garage.pos then
|
|
opos[#opos + 1] = {title = TranslateCap("back"), icon = "fas fa-arrow-left", description = "return to Property Management.",
|
|
value = "return"}
|
|
end
|
|
else
|
|
opos[#opos + 1] = {title = TranslateCap("back"), icon = "fas fa-arrow-left", description = "return to Property Management",
|
|
value = "return"}
|
|
end
|
|
exports["esx_context"]:Refresh(opos, "right")
|
|
else
|
|
ESX.ShowNotification("You ~r~Cannot~s~ Toggle This Option!", "error")
|
|
end
|
|
end, currentProperty)
|
|
end
|
|
if element.value == "ToggleCCTV" then
|
|
ESX.TriggerServerCallback("esx_property:toggleCCTV", function(IsUnlocked, enabled)
|
|
if IsUnlocked then
|
|
ESX.ShowNotification("CCTV Toggled!", "success")
|
|
local status = enabled and TranslateCap("enabled") or TranslateCap("disabled")
|
|
opos = {{unselectable = true, icon = "fas fa-warehouse", title = TranslateCap("cctv_settings")},
|
|
{title = "Toggle Usage", icon = status == TranslateCap("enabled") and "fa-solid fa-toggle-on" or "fa-solid fa-toggle-off",
|
|
description = "Current Status: " .. status, value = "ToggleCCTV"}}
|
|
if enabled then
|
|
opos[#opos + 1] = {title = "Set Angle", icon = "fas fa-map-marker-alt", disabled = not enabled,
|
|
description = "Sets the Angle of the Camera.", value = "SetCCTVangle"}
|
|
if Properties[currentProperty].cctv.rot then
|
|
opos[#opos + 1] = {title = TranslateCap("back"), icon = "fas fa-arrow-left", description = "return to Property Management.",
|
|
value = "return"}
|
|
end
|
|
else
|
|
opos[#opos + 1] = {title = TranslateCap("back"), icon = "fas fa-arrow-left", description = "return to Property Management",
|
|
value = "return"}
|
|
end
|
|
exports["esx_context"]:Refresh(opos, "right")
|
|
else
|
|
ESX.ShowNotification("You ~r~Cannot~s~ Toggle This Option!", "error")
|
|
end
|
|
end, currentProperty)
|
|
end
|
|
if element.value == "SetGaragePos" then
|
|
ESX.CloseContext()
|
|
ESX.TextUI("Press ~b~[E]~s~ to Set Position")
|
|
SettingValue = "Garage"
|
|
while SettingValue ~= "" do
|
|
Wait(0)
|
|
if IsControlJustPressed(0, 38) then
|
|
ESX.TriggerServerCallback("esx_property:SetGaragePos", function(IsChanged)
|
|
if IsChanged then
|
|
ESX.HideUI()
|
|
SettingValue = ""
|
|
ESX.ShowNotification("Position Changed!", "success")
|
|
ManageProperty(currentProperty)
|
|
else
|
|
ESX.ShowNotification("You ~r~Cannot~s~ Change This Option!", "error")
|
|
end
|
|
end, currentProperty, GetEntityHeading(ESX.PlayerData.ped))
|
|
break
|
|
end
|
|
end
|
|
end
|
|
if element.value == "SetCCTVangle" then
|
|
ESX.CloseContext()
|
|
ESX.TextUI("Press ~b~[E]~s~ to Set Angle")
|
|
local stage = "angle"
|
|
SettingValue = "cctv"
|
|
local Angles = {}
|
|
while stage do
|
|
Wait(0)
|
|
if IsControlJustPressed(0, 38) then
|
|
if stage == "angle" then
|
|
Angles.rot = GetGameplayCamRot(2)
|
|
ESX.TextUI("Press ~b~[E]~s~ to Set Max Right Roation")
|
|
stage = "maxright"
|
|
elseif stage == "maxright" then
|
|
Angles.maxright = GetGameplayCamRot(2).z
|
|
ESX.TextUI("Press ~b~[E]~s~ to Set Max Left Roation")
|
|
stage = "maxleft"
|
|
elseif stage == "maxleft" then
|
|
Angles.maxleft = GetGameplayCamRot(2).z
|
|
ESX.TriggerServerCallback("esx_property:SetCCTVangle", function(IsChanged)
|
|
if IsChanged then
|
|
SettingValue = ""
|
|
stage = nil
|
|
ESX.HideUI()
|
|
ESX.ShowNotification("Angle Changed!", "success")
|
|
ManageProperty(currentProperty)
|
|
else
|
|
ESX.ShowNotification("You ~r~Cannot~s~ Change This Option!", "error")
|
|
end
|
|
end, currentProperty, Angles)
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if element.value == "remove_custom_name" then
|
|
ESX.TriggerServerCallback("esx_property:RemoveCustomName", function(Cleared)
|
|
if Cleared then
|
|
ESX.ShowNotification("Property Name Reset!", "success")
|
|
exports["esx_context"]:Refresh(GetData())
|
|
else
|
|
ESX.ShowNotification("You Cannot Reset This Property`s Name!", "error")
|
|
end
|
|
end, currentProperty)
|
|
end
|
|
if element.value == "refurni" then
|
|
ESX.TriggerServerCallback("esx_property:RemoveAllfurniture", function(Removed)
|
|
if Removed then
|
|
ESX.ShowNotification("Furniture Reset!", "success")
|
|
exports["esx_context"]:Refresh(GetData())
|
|
else
|
|
ESX.ShowNotification("You Cannot Reset This Property!", "error")
|
|
end
|
|
end, currentProperty)
|
|
end
|
|
if element.value == "restorage" then
|
|
ESX.TriggerServerCallback("esx_property:SetInventoryPosition", function(Reset)
|
|
if Reset then
|
|
ESX.ShowNotification("~b~Storage~s~ Position Reset!", "success")
|
|
exports["esx_context"]:Refresh(GetData())
|
|
else
|
|
ESX.ShowNotification("You Cannot Reset This Property!", "error")
|
|
end
|
|
end, currentProperty, Interior.positions.Storage, true)
|
|
end
|
|
if element.value == "rewardrobe" then
|
|
ESX.TriggerServerCallback("esx_property:SetWardrobePosition", function(Reset)
|
|
if Reset then
|
|
ESX.ShowNotification("~b~Wardrobe~s~ Position Reset!", "success")
|
|
exports["esx_context"]:Refresh(GetData())
|
|
else
|
|
ESX.ShowNotification("You Cannot Reset This Property!", "error")
|
|
end
|
|
end, currentProperty, Interior.positions.Wardrobe, true)
|
|
end
|
|
if element.value == "back" then
|
|
AdminOptions(currentProperty)
|
|
end
|
|
if element.value == "return" then
|
|
exports["esx_context"]:Refresh(GetData())
|
|
end
|
|
if element.value == "price" then
|
|
ESX.UI.Menu.Open('dialog', GetCurrentResourceName(), 'PropertyPrice', {title = "Property Price"}, function(data4, menu4)
|
|
if data4.value then
|
|
ESX.TriggerServerCallback("esx_property:ChangePrice", function(IsChanged)
|
|
if IsChanged then
|
|
ESX.ShowNotification("Price Changed!", "success")
|
|
menu4.close()
|
|
else
|
|
ESX.ShowNotification("You Cannot Change this property!", "error")
|
|
end
|
|
end, currentProperty, tonumber(data4.value))
|
|
end
|
|
end, function(data4, menu4)
|
|
menu4.close()
|
|
end)
|
|
end
|
|
if element.value == "interior" then
|
|
local elements = {{unselectable = true, icon = "fas fa-warehouse", title = "Interior Types"},
|
|
{title = "IPL Interiors", description = "Native GTA Interiors, Made by R*", value = "IPL"}}
|
|
if Config.Shells then
|
|
elements[3] = {title = "Custom Interiors", description = "Custom Interiors, Made by You", value = "Shells"}
|
|
end
|
|
ESX.OpenContext("right", elements, function(menu, element)
|
|
if element.value then
|
|
local elements = {{unselectable = true, icon = "fas fa-warehouse", title = "Interiors"}}
|
|
for i = 1, #(Config.Interiors[element.value]) do
|
|
elements[#elements + 1] = {title = Config.Interiors[element.value][i].label, value = Config.Interiors[element.value][i].value}
|
|
end
|
|
ESX.OpenContext("right", elements, function(menu, element)
|
|
if element.value then
|
|
ESX.TriggerServerCallback("esx_property:ChangeInterior", function(IsChanged)
|
|
if IsChanged then
|
|
ESX.ShowNotification("Interior Changed!", "success")
|
|
ESX.CloseContext()
|
|
else
|
|
ESX.ShowNotification("You Cannot Change this property!", "error")
|
|
end
|
|
end, currentProperty, element.value)
|
|
end
|
|
end)
|
|
end
|
|
end, function()
|
|
ManageProperty(currentProperty)
|
|
end)
|
|
end
|
|
if element.value == "entrance" then
|
|
ESX.TriggerServerCallback("esx_property:ChangeEntrance", function(IsChanged)
|
|
if IsChanged then
|
|
ESX.ShowNotification("Entrance Changed!", "success")
|
|
else
|
|
ESX.ShowNotification("You Cannot Change this property!", "error")
|
|
end
|
|
end, currentProperty, GetEntityCoords(ESX.PlayerData.ped))
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
end)
|
|
end
|
|
|
|
function AdminOptions(currentProperty)
|
|
ESX.TriggerServerCallback('esx_property:IsAdmin', function(data)
|
|
if data then
|
|
local elements = {{unselectable = true, icon = "fas fa-home", title = "Property Options"},
|
|
{title = TranslateCap("back"), icon = "fas fa-arrow-left", value = "back"},
|
|
{title = "Manage", icon = "fas fa-cogs", description = "Alter This Property's Settings.", value = "manage"},
|
|
{title = "Teleport", description = "Teleport To This Property.", icon = "fas fa-map-marker-alt", value = "goto"},
|
|
{title = "Set GPS", description = "Set GPS position To Property.", icon = "fa-solid fa-location-dot", value = "gps"},
|
|
{title = "Delete", icon = "fas fa-trash-alt", description = "Remove Current Property.", value = "delete"}}
|
|
|
|
ESX.OpenContext("right", elements, function(menu, element)
|
|
if element.value then
|
|
if element.value == "goto" then
|
|
SetEntityCoords(ESX.PlayerData.ped, Properties[currentProperty].Entrance.x, Properties[currentProperty].Entrance.y,
|
|
Properties[currentProperty].Entrance.z)
|
|
ESX.ShowNotification("Teleported to Property!")
|
|
end
|
|
if element.value == "gps" then
|
|
SetNewWaypoint(Properties[currentProperty].Entrance.x, Properties[currentProperty].Entrance.y)
|
|
ESX.ShowNotification("GPS Set!")
|
|
end
|
|
if element.value == "back" then
|
|
AdminMenu()
|
|
end
|
|
if element.value == "delete" then
|
|
ESX.TriggerServerCallback("esx_property:deleteProperty", function(response)
|
|
if response then
|
|
ESX.ShowNotification("Property Deleted!", "success")
|
|
ESX.CloseContext()
|
|
else
|
|
ESX.ShowNotification("You Cannot Delete This Property", "error")
|
|
end
|
|
end, currentProperty)
|
|
end
|
|
|
|
if element.value == "manage" then
|
|
ManageProperty(currentProperty)
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
end)
|
|
end
|
|
|
|
function AdminMenu()
|
|
ESX.TriggerServerCallback('esx_property:IsAdmin', function(data)
|
|
if data then
|
|
local elements = {{unselectable = true, icon = "fas fa-home", title = "Properties Management"}}
|
|
for i = 1, #(Properties) do
|
|
if Properties[i].Entrance then
|
|
local description = ""
|
|
if Properties[i].setName ~= "" then
|
|
description = description .. "\nName: " .. Properties[i].setName
|
|
end
|
|
if Properties[i].Owned then
|
|
description = description .. "\nOwner: " .. Properties[i].OwnerName
|
|
end
|
|
table.insert(elements, {title = Properties[i].Name, value = i, description = description, icon = "fas fa-home"})
|
|
end
|
|
end
|
|
ESX.OpenContext("right", elements, function(menu, element)
|
|
if element.value then
|
|
ESX.CloseContext()
|
|
AdminOptions(element.value)
|
|
end
|
|
end)
|
|
end
|
|
end)
|
|
end
|
|
|
|
AdminMenu()
|
|
else
|
|
ESX.ShowNotification("You ~r~Cannot~s~ Access This Menu!", 5000, "error")
|
|
end
|
|
end)
|
|
end)
|
|
|