Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: added qbx_garages support #43

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 78 additions & 3 deletions client/realtor.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,24 @@ for k in pairs(sharedConfig.interiors) do
values[#values + 1] = k
end

local car = 0
local shell = 0
local playerCoords = vec3(0, 0, 0)
local garageCoords = nil
local garageHeading = 0.0
local isPreviewing = false

local function showText()
lib.showTextUI('BACKSPACE - Exit \n ARROW LEFT - Turn left \n ARROW RIGHT - Turn right \n ENTER - Confirm Placement')
end

local function spawnCar()
local model = lib.requestModel('sultanrs', 2500)
car = CreateVehicle(model, 0.0, 0.0, 0.0, 0.0, false, false)
SetEntityCompletelyDisableCollision(car, false, false)
Frowmza marked this conversation as resolved.
Show resolved Hide resolved
SetModelAsNoLongerNeeded(model)
end

local function previewProperty(propertyIndex)
if DoesEntityExist(shell) then DeleteEntity(shell) end
if type(propertyIndex) == 'number' then
Expand Down Expand Up @@ -35,6 +49,63 @@ local function stopPreview()
end
end

local function addGaragePoint()
local isAddingGarage = true
garageCoords = nil

showText()
spawnCar()

while isAddingGarage do
Wait(0)

local hit, _, endCoords = lib.raycast.fromCamera(511, 4, 25.0)

if not hit then
SetEntityCoords(car, 0.0, 0.0, 0.0, false, false, false, false)
else
SetEntityCoords(car, endCoords.x, endCoords.y, endCoords.z + 1.0, false, false, false, false)
SetVehicleOnGroundProperly(car)
end

if IsControlJustPressed(0, 202) then
if DoesEntityExist(car) then
DeleteEntity(car)
end
isAddingGarage = false
end

if IsControlPressed(0, 190) then
garageHeading = (garageHeading + 2.5) % 360.0
SetEntityHeading(car, garageHeading)
Wait(100)
end

if IsControlPressed(0, 189) then
garageHeading = (garageHeading - 2.5) % 360.0
SetEntityHeading(car, garageHeading)
Wait(100)
end

if IsControlJustPressed(0, 18) then
if hit then
garageCoords = endCoords
garageHeading = GetEntityHeading(car)
if DoesEntityExist(car) then
DeleteEntity(car)
end
isAddingGarage = false
else
lib.notify({type = 'error', title = 'Error', description = 'Invalid garage location.'})
end
end

SetEntityHeading(car, garageHeading) -- Prevent the car from rotating
end

lib.hideTextUI()
end

lib.registerMenu({
id = 'qbx_properties_realtor_menu',
title = locale('menu.interior_preview'),
Expand All @@ -54,10 +125,14 @@ lib.registerMenu({
{type = 'input', label = locale('alert.property_name'), description = locale('alert.property_name_description'), required = true, min = 4, max = 32, icon = 'home'},
{type = 'number', label = locale('alert.price'), description = locale('alert.price_description'), icon = 'dollar-sign', required = true, min = 1},
{type = 'number', label = locale('alert.rent_interval'), description = locale('alert.rent_interval_description'), icon = 'clock', min = 1, max = 24, step = 1},
{type = 'checkbox', label = locale('alert.add_garage')},
})
if input then
TriggerServerEvent('qbx_properties:server:createProperty', args[scrollIndex], input, playerCoords)
if not input then return end

if input[4] then
addGaragePoint()
end
TriggerServerEvent('qbx_properties:server:createProperty', args[scrollIndex], input, playerCoords, vec4(garageCoords.x, garageCoords.y, garageCoords.z + 1.0, garageHeading))
end)

RegisterNetEvent('qbx_properties:client:createProperty', function()
Expand All @@ -74,4 +149,4 @@ RegisterNetEvent('qbx_properties:client:createProperty', function()
end
Wait(3000)
end
end)
end)
3 changes: 2 additions & 1 deletion locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"price": "Price",
"price_description": "The purchasing price or the price deducted for rent",
"rent_interval": "Rent interval",
"rent_interval_description": "The interval in which the rent will be deducted in hours (makes the property rentable instead of purchasable)"
"rent_interval_description": "The interval in which the rent will be deducted in hours (makes the property rentable instead of purchasable)",
"add_garage": "Add Garage"
},
"menu": {
"add_keyholder": "Add Keyholder",
Expand Down
1 change: 1 addition & 0 deletions property_garages.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE `properties` ADD COLUMN IF NOT EXISTS `garage` JSON DEFAULT NULL AFTER `stash_options`;
53 changes: 50 additions & 3 deletions server/property.lua
Original file line number Diff line number Diff line change
Expand Up @@ -337,11 +337,45 @@ AddEventHandler('playerDropped', function ()
MySQL.update('UPDATE players SET position = ? WHERE citizenid = ?', { json.encode(vec4(coords.x, coords.y, coords.z, 0.0)), citizenid[playerSource] })
end)

local function canAccess(source, owner, keyholders)
local player = exports.qbx_core:GetPlayer(source)
if player.PlayerData.citizenid == owner then return true end
for i = 1, #keyholders do
if player.PlayerData.citizenid == keyholders[i] then return true end
end
return false
end

local function registerGarage(name, owner, keyholders, garage)
local garageName = 'property_' .. string.gsub(string.lower(name), ' ', '_')
exports.qbx_garages:RegisterGarage(garageName, {
label = name,
vehicleType = 'car',
accessPoints = {
{
coords = vec4(garage.x, garage.y, garage.z, garage.w),
}
},
canAccess = function(source)
return canAccess(source, owner, keyholders)
end
})
end

local function registerGarages()
local properties = MySQL.query.await('SELECT property_name, owner, keyholders, garage FROM properties WHERE owner IS NOT NULL AND garage IS NOT NULL')
if not properties then return end
for i = 1, #properties do
local property = properties[i]
registerGarage(property.property_name, property.owner, json.decode(property.keyholders), json.decode(property.garage))
end
end

local function startRentThread(propertyId)
CreateThread(function()
while true do
local property = MySQL.single.await('SELECT owner, price, rent_interval, property_name FROM properties WHERE id = ?', {propertyId})
if not property or not property.owner then break end
if not property or not property.owner then break end

local player = exports.qbx_core:GetPlayerByCitizenId(property.owner) or exports.qbx_core:GetOfflinePlayer(property.owner)
if not player then print(string.format('%s does not exist anymore, consider checking property id %s', property.owner, propertyId)) break end
Expand All @@ -368,7 +402,7 @@ RegisterNetEvent('qbx_properties:server:rentProperty', function(propertyId)
local playerSource = source --[[@as number]]
local player = exports.qbx_core:GetPlayer(playerSource)
local playerCoords = GetEntityCoords(GetPlayerPed(playerSource))
local property = MySQL.single.await('SELECT owner, price, property_name, coords, rent_interval FROM properties WHERE id = ?', {propertyId})
local property = MySQL.single.await('SELECT owner, price, property_name, coords, rent_interval, keyholders, garage FROM properties WHERE id = ?', {propertyId})
local propertyCoords = json.decode(property.coords)
if #(playerCoords - vec3(propertyCoords.x, propertyCoords.y, propertyCoords.z)) > 8.0 then return end
if property.owner then return end
Expand All @@ -379,6 +413,10 @@ RegisterNetEvent('qbx_properties:server:rentProperty', function(propertyId)
return
end

if property.garage then
registerGarage(property.property_name, player.PlayerData.citizenid, json.decode(property.keyholders), json.decode(property.garage))
end

exports.qbx_core:Notify(playerSource, string.format('Successfully started renting %s', property.property_name), 'success')
MySQL.update('UPDATE properties SET owner = ? WHERE id = ?', {player.PlayerData.citizenid, propertyId})
startRentThread()
Expand All @@ -388,7 +426,7 @@ RegisterNetEvent('qbx_properties:server:buyProperty', function(propertyId)
local playerSource = source --[[@as number]]
local player = exports.qbx_core:GetPlayer(playerSource)
local playerCoords = GetEntityCoords(GetPlayerPed(playerSource))
local property = MySQL.single.await('SELECT owner, price, property_name, coords FROM properties WHERE id = ?', {propertyId})
local property = MySQL.single.await('SELECT owner, price, property_name, coords, keyholders, garage FROM properties WHERE id = ?', {propertyId})
local propertyCoords = json.decode(property.coords)

if #(playerCoords - vec3(propertyCoords.x, propertyCoords.y, propertyCoords.z)) > 8.0 or property.owner then return end
Expand All @@ -398,20 +436,29 @@ RegisterNetEvent('qbx_properties:server:buyProperty', function(propertyId)
return
end

if property.garage then
registerGarage(property.property_name, player.PlayerData.citizenid, json.decode(property.keyholders), json.decode(property.garage))
end

MySQL.update('UPDATE properties SET owner = ? WHERE id = ?', {player.PlayerData.citizenid, propertyId})
exports.qbx_core:Notify(playerSource, string.format('Successfully purchased %s for $%s', property.property_name, property.price))
end)

Citizen.CreateThreadNow(function()
local sql1 = LoadResourceFile(cache.resource, 'property.sql')
local sql2 = LoadResourceFile(cache.resource, 'decorations.sql')
local sql3 = LoadResourceFile(cache.resource, 'property_garages.sql')

MySQL.query.await(sql1)
MySQL.query.await(sql2)
MySQL.query.await(sql3)

local properties = MySQL.query.await('SELECT id FROM properties WHERE owner IS NOT NULL AND rent_interval IS NOT NULL')
for i = 1, #properties do
startRentThread(properties[i].id)
end

registerGarages()
end)

RegisterNetEvent('qbx_properties:server:stopRenting', function()
Expand Down
18 changes: 12 additions & 6 deletions server/realtor.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ lib.addCommand('createproperty', {
TriggerClientEvent('qbx_properties:client:createProperty', source)
end)

RegisterNetEvent('qbx_properties:server:createProperty', function(interiorIndex, data, propertyCoords)
RegisterNetEvent('qbx_properties:server:createProperty', function(interiorIndex, data, propertyCoords, garageCoords)
local playerSource = source --[[@as number]]
local player = exports.qbx_core:GetPlayer(playerSource)
local playerCoords = GetEntityCoords(GetPlayerPed(playerSource))

if player.PlayerData.job.name ~= 'realestate' then return end
if #(playerCoords - propertyCoords) > 5.0 then return end
if not garageCoords and #(playerCoords - propertyCoords) > 5.0 then return end
if garageCoords and #(playerCoords - vec3(garageCoords.xyz)) > 5.0 then return end
Frowmza marked this conversation as resolved.
Show resolved Hide resolved

local interactData = {
{
Expand All @@ -33,23 +34,28 @@ RegisterNetEvent('qbx_properties:server:createProperty', function(interiorIndex,
coords = sharedConfig.interiors[interiorIndex].exit
}
}

local stashData = {
{
coords = sharedConfig.interiors[interiorIndex].stash,
slots = config.apartmentStash.slots,
maxWeight = config.apartmentStash.maxWeight,
}
}

local result = MySQL.single.await('SELECT id FROM properties ORDER BY id DESC', {})
local propertNumber = result?.id or 0
MySQL.insert('INSERT INTO `properties` (`coords`, `property_name`, `price`, `interior`, `interact_options`, `stash_options`, `rent_interval`) VALUES (?, ?, ?, ?, ?, ?, ?)', {
local propertyNumber = result?.id or 0
local propertyName = string.format('%s %s', data[1], propertyNumber)

MySQL.insert('INSERT INTO `properties` (`coords`, `property_name`, `price`, `interior`, `interact_options`, `stash_options`, `rent_interval`, `garage`) VALUES (?, ?, ?, ?, ?, ?, ?, ?)', {
json.encode(propertyCoords),
string.format('%s %s', data[1], propertNumber),
propertyName,
data[2],
interiorIndex,
json.encode(interactData),
json.encode(stashData),
data[3]
data[3],
garageCoords and json.encode(garageCoords) or nil,
})
TriggerClientEvent('qbx_properties:client:addProperty', -1, propertyCoords)
end)
Loading