diff --git a/client/main.lua b/client/main.lua
index c7d66277..41e38d0f 100644
--- a/client/main.lua
+++ b/client/main.lua
@@ -20,8 +20,7 @@ Citizen.CreateThread(function()
Citizen.Wait(0)
end
- while ESX.GetPlayerData() == nil do
- print('playerdata nil!! (boat)')
+ while ESX.GetPlayerData().job == nil do
Citizen.Wait(10)
end
@@ -41,7 +40,7 @@ function OpenBoatShop(shop)
label = (string.format ('%s - $%i', Config.Vehicles[i].label, Config.Vehicles[i].price)),
name = Config.Vehicles[i].label,
model = Config.Vehicles[i].model,
- price = Config.Vehicles[i].price,
+ price = Config.Vehicles[i].price
})
end
@@ -64,11 +63,11 @@ function OpenBoatShop(shop)
if data2.current.value == 'yes' then
- local plate = exports['esx_vehicleshop']:GeneratePlate()
- local vehicle = GetVehiclePedIsIn(playerPed, false)
- local props = ESX.Game.GetVehicleProperties(vehicle)
- props.plate = plate
- print(props.model)
+ local plate = exports['esx_vehicleshop']:GeneratePlate()
+ local vehicle = GetVehiclePedIsIn(playerPed, false)
+ local props = ESX.Game.GetVehicleProperties(vehicle)
+ props.plate = plate
+ props.modelAlt = data.current.model
ESX.TriggerServerCallback('esx_boat:buyBoat', function (bought)
@@ -89,7 +88,7 @@ function OpenBoatShop(shop)
menu2.close()
end
- end, props, data.current.model)
+ end, props)
else
menu2.close()
@@ -99,10 +98,7 @@ function OpenBoatShop(shop)
menu2.close()
end)
-
-
end, function (data, menu)
- -- exit menu
menu.close()
DeleteSpawnedVehicles()
@@ -122,8 +118,6 @@ function OpenBoatShop(shop)
TaskWarpPedIntoVehicle(playerPed, vehicle, -1)
FreezeEntityPosition(vehicle, true)
end)
- end, function (data, menu)
-
end)
-- spawn first vehicle
@@ -135,6 +129,66 @@ function OpenBoatShop(shop)
end)
end
+function OpenBoatGarage(garage)
+
+ ESX.TriggerServerCallback('esx_boat:getGarage', function (ownedBoats)
+
+ if #ownedBoats == 0 then
+ ESX.ShowNotification(_U('garage_noboats'))
+ else
+
+ -- get all available boats
+ local elements = {}
+ for i=1, #ownedBoats, 1 do
+ table.insert(elements, {
+ label = getVehicleModelFromHash(ownedBoats[i].model),
+ vehicleProps = ownedBoats[i]
+ })
+ end
+
+ ESX.UI.Menu.Open('default', GetCurrentResourceName(), 'boat_garage',
+ {
+ title = _U('garage'),
+ align = 'top-left',
+ elements = elements
+ }, function (data, menu)
+
+ -- make sure the spawn point isn't blocked
+ local closestVehicle = GetClosestVehicle(garage.SpawnPoint.x, garage.SpawnPoint.y, garage.SpawnPoint.z, 3.0, 0, 71)
+ local playerPed = PlayerPedId()
+ local vehicleProps = data.current.vehicleProps
+
+ if not DoesEntityExist(closestVehicle) then
+ TriggerServerEvent('esx_boat:takeOutVehicle', vehicleProps.plate)
+ ESX.ShowNotification(_U('garage_taken'))
+
+ ESX.Game.SpawnVehicle(vehicleProps.model, garage.SpawnPoint, 20, function(vehicle)
+ TaskWarpPedIntoVehicle(playerPed, vehicle, -1)
+ ESX.Game.SetVehicleProperties(vehicle, vehicleProps)
+ end)
+
+ menu.close()
+ else
+ ESX.ShowNotification(_U('garage_blocked'))
+ end
+
+
+ end, function (data, menu)
+ menu.close()
+
+ CurrentAction = 'garage_out'
+ CurrentActionMsg = _U('garage_open')
+ end)
+ end
+
+ end)
+end
+
+function StoreBoatInGarage(vehicle)
+
+end
+
+
-- Key controls
Citizen.CreateThread(function()
while true do
@@ -150,20 +204,19 @@ Citizen.CreateThread(function()
end)
function DeleteSpawnedVehicles()
-
while #spawnedVehicles > 0 do
-
local vehicle = spawnedVehicles[1]
ESX.Game.DeleteVehicle(vehicle)
table.remove(spawnedVehicles, 1)
-
end
end
+function getVehicleModelFromHash(hash)
+ for i=1, #Config.Vehicles, 1 do
+ if Config.Vehicles[i].hash == hash then
+ return Config.Vehicles[i].model
+ end
+ end
-
-AddEventHandler('onResourceStop', function(resource)
- --if resource == GetCurrentResourceName() and ESX.UI.Menu.IsOpen('default', GetCurrentResourceName(), 'boat_shop') then
- ESX.UI.Menu.CloseAll()
--- end
-end)
+ return 'Unknown hash [' .. hash .. ']'
+end
\ No newline at end of file
diff --git a/client/marker.lua b/client/marker.lua
index 5a4f7ff2..96c7bc6e 100644
--- a/client/marker.lua
+++ b/client/marker.lua
@@ -10,9 +10,7 @@ Citizen.CreateThread(function()
while true do
Citizen.Wait(10)
- if CurrentAction == nil then
- Citizen.Wait(200)
- else
+ if CurrentAction ~= nil then
ESX.ShowHelpNotification(CurrentActionMsg)
@@ -20,10 +18,17 @@ Citizen.CreateThread(function()
if CurrentAction == 'boat_shop' then
OpenBoatShop(Config.Zones.BoatShops[CurrentActionData.zoneNum])
+ elseif CurentAction == 'garage_out' then
+ OpenBoatGarage(Config.Zones.Garages[CurrentActionData.zoneNum])
+ elseif CrurentAction == 'garage_in' then
+ StoreBoatInGarage(CurrentActionData.vehicle)
end
CurrentAction = nil
+
end
+ else
+ Citizen.Wait(200)
end
end
end)
@@ -36,6 +41,24 @@ AddEventHandler('esx_boat:hasEnteredMarker', function(zone, zoneNum)
CurrentAction = 'boat_shop'
CurrentActionMsg = _U('boat_shop_open')
CurrentActionData = { zoneNum = zoneNum }
+ elseif zone == 'garage_out' then
+ CurrentAction = 'garage_out'
+ CurrentActionMsg = _U('garage_open')
+ CurrentActionData = { zoneNum = zoneNum }
+ elseif zone == 'garage_in' then
+ local playerPed = PlayerPedId()
+ local coords = GetEntityCoords(playerPed)
+
+ if IsPedInAnyVehicle(playerPed, false) then
+ local vehicle = GetVehiclePedIsIn(playerPed, false)
+
+ if DoesEntityExist(vehicle) then
+ CurrentAction = 'garage_in'
+ CurrentActionMsg = _U('garage_store')
+ CurrentActionData = {vehicle = vehicle}
+ end
+
+ end
end
end)
@@ -59,7 +82,21 @@ Citizen.CreateThread(function()
for i=1, #Config.Zones.BoatShops, 1 do
local zone = Config.Zones.BoatShops[i].Outside
if GetDistanceBetweenCoords(coords, zone.x, zone.y, zone.z, true) < Config.DrawDistance then
- DrawMarker(Config.MarkerType, zone.x, zone.y, zone.z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, Config.MarkerSize.x, Config.MarkerSize.y, Config.MarkerSize.z, Config.MarkerColor.r, Config.MarkerColor.g, Config.MarkerColor.b, 100, false, true, 2, false, false, false, false)
+ DrawMarker(Config.MarkerType, zone.x, zone.y, zone.z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, Config.Marker.x, Config.Marker.y, Config.Marker.z, Config.Marker.r, Config.Marker.g, Config.Marker.b, 100, false, true, 2, false, false, false, false)
+ end
+ end
+
+ for i=1, #Config.Zones.Garages, 1 do
+ local zoneOut = Config.Zones.Garages[i].GaragePos
+ if GetDistanceBetweenCoords(coords, zoneOut.x, zoneOut.y, zoneOut.z, true) < Config.DrawDistance then
+ DrawMarker(Config.MarkerType, zoneOut.x, zoneOut.y, zoneOut.z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, Config.Marker.x, Config.Marker.y, Config.Marker.z, Config.Marker.r, Config.Marker.g, Config.Marker.b, 100, false, true, 2, false, false, false, false)
+ end
+ end
+
+ for i=1, #Config.Zones.Garages, 1 do
+ local zoneIn = Config.Zones.Garages[i].StorePos
+ if GetDistanceBetweenCoords(coords, zoneIn.x, zoneIn.y, zoneIn.z, true) < Config.DrawDistance then
+ DrawMarker(Config.MarkerType, zoneIn.x, zoneIn.y, zoneIn.z, 0.0, 0.0, 0.0, 0, 0.0, 0.0, Config.StoreMarker.x, Config.StoreMarker.y, Config.StoreMarker.z, Config.StoreMarker.r, Config.StoreMarker.g, Config.StoreMarker.b, 100, false, true, 2, false, false, false, false)
end
end
@@ -79,27 +116,32 @@ Citizen.CreateThread(function()
local currentZone = nil
local currentZoneNum = nil
- for i=1, #Config.Zones.BoatShops, 1 do
-
- if GetDistanceBetweenCoords(coords, Config.Zones.BoatShops[i].Outside.x, Config.Zones.BoatShops[i].Outside.y, Config.Zones.BoatShops[i].Outside.z, true) < Config.MarkerSize.x then
- isInMarker = true
- currentZone = 'boat_shop'
- currentZoneNum = i
- end
-
---[[
- if GetDistanceBetweenCoords(coords, v.Helicopters[i].SpawnPoint.x, v.Helicopters[i].SpawnPoint.y, v.Helicopters[i].SpawnPoint.z, true) < Config.MarkerSize.x then
- isInMarker = true
- currentZone = 'HelicopterSpawnPoint'
- currentZoneNum = i
- end
- extra för garage
-]]
-
-
+ for i=1, #Config.Zones.BoatShops, 1 do
+ if GetDistanceBetweenCoords(coords, Config.Zones.BoatShops[i].Outside.x, Config.Zones.BoatShops[i].Outside.y, Config.Zones.BoatShops[i].Outside.z, true) < Config.Marker.x then
+ isInMarker = true
+ currentZone = 'boat_shop'
+ currentZoneNum = i
end
+ end
+
+ for i=1, #Config.Zones.Garages, 1 do
+
+ if GetDistanceBetweenCoords(coords, Config.Zones.Garages[i].GaragePos.x, Config.Zones.Garages[i].GaragePos.y, Config.Zones.Garages[i].GaragePos.z, true) < Config.Marker.x then
+ isInMarker = true
+ currentZone = 'garage_out'
+ currentZoneNum = i
+ end
+
+ if GetDistanceBetweenCoords(coords, Config.Zones.Garages[i].StorePos.x, Config.Zones.Garages[i].StorePos.y, Config.Zones.Garages[i].StorePos.z, true) < Config.StoreMarker.x then
+ isInMarker = true
+ currentZone = 'garage_in'
+ currentZoneNum = i
+ end
+
+ end
+
local hasExited = false
if isInMarker and not HasAlreadyEnteredMarker or (isInMarker and (LastZone ~= currentZone or LastZoneNum ~= currentZoneNum) ) then
@@ -127,3 +169,48 @@ Citizen.CreateThread(function()
end
end)
+
+-- Blips
+Citizen.CreateThread(function()
+
+ local blipList = {}
+
+ for i=1, #Config.Zones.Garages, 1 do
+ table.insert(blipList, {
+ coords = { Config.Zones.Garages[i].GaragePos.x, Config.Zones.Garages[i].GaragePos.y },
+ text = _U('blip_garage'),
+ sprite = 356,
+ color = 3,
+ scale = 1.0
+ })
+ end
+
+ for i=1, #Config.Zones.BoatShops, 1 do
+ table.insert(blipList, {
+ coords = { Config.Zones.BoatShops[i].Outside.x, Config.Zones.BoatShops[i].Outside.y },
+ text = _U('blip_shop'),
+ sprite = 427,
+ color = 3,
+ scale = 1.0
+ })
+ end
+
+ for i=1, #blipList, 1 do
+ CreateBlip(blipList[i].coords, blipList[i].text, blipList[i].sprite, blipList[i].color, blipList[i].scale)
+ end
+
+end)
+
+function CreateBlip(coords, text, sprite, color, scale)
+ local blip = AddBlipForCoord( table.unpack(coords) )
+
+ SetBlipSprite(blip, sprite)
+ SetBlipScale(blip, scale)
+ SetBlipColour(blip, color)
+
+ SetBlipAsShortRange(blip, true)
+
+ BeginTextCommandSetBlipName('STRING')
+ AddTextComponentSubstringPlayerName(text)
+ EndTextCommandSetBlipName(blip)
+end
\ No newline at end of file
diff --git a/config.lua b/config.lua
index 62f2dbd3..a5a1f16d 100644
--- a/config.lua
+++ b/config.lua
@@ -4,17 +4,25 @@ Config.Locale = 'en'
Config.MarkerType = 1
Config.DrawDistance = 100.0
-Config.ZoneSize = {x = 5.0, y = 5.0, z = 3.0}
-Config.MarkerColor = {r = 100, g = 204, b = 100}
-Config.MarkerSize = { x = 1.5, y = 1.5, z = 1.0 }
+
+Config.Marker = {
+ r = 100, g = 204, b = 100, -- blue-ish color, standard size circle
+ x = 1.5, y = 1.5, z = 1.0
+}
+
+Config.StoreMarker = {
+ r = 255, g = 0, b = 0,
+ x = 5.0, y = 5.0, z = 1.0 -- big circle for storing boat
+}
+
Config.Zones = {
Garages = {
{
- GaragePos = { x = -772.42, y = -1430.90, z = 1.59 },
+ GaragePos = { x = -772.42, y = -1430.90, z = 0.55 },
SpawnPoint = { x = -785.39, y = -1426.30, z = -0.47 },
- RemovePos = { x = -798.45, y = -1456.03, z = -0.47 },
+ StorePos = { x = -798.45, y = -1456.03, z = -0.47 },
Heading = 150.0
}
@@ -30,8 +38,6 @@ Config.Zones = {
}
-
-
}
Config.Vehicles = {
@@ -39,12 +45,14 @@ Config.Vehicles = {
{
model = 'seashark',
label = 'Seashark',
+ hash = -1030275036,
price = 15000
},
{
model = 'speeder',
label = 'Speeder',
+ hash = 231083307,
price = 10000
}
diff --git a/locales/en.lua b/locales/en.lua
index 9f621d14..1f7372a3 100644
--- a/locales/en.lua
+++ b/locales/en.lua
@@ -1,10 +1,23 @@
Locales['en'] = {
-- shop
['boat_shop'] = 'boat shop',
- ['boat_shop_open'] = 'press ~INPUT_CONTEXT~ to open the boat shop.',
+ ['boat_shop_open'] = 'press ~INPUT_CONTEXT~ to access the ~y~boat shop~s~.',
['boat_shop_confirm'] = 'buy a %s for $%s?',
['boat_shop_bought'] = 'you have ~y~bought~s~ a ~b~%s~s~ for ~g~$%s~s~',
['boat_shop_nomoney'] = 'you cannot afford this boat!',
['confirm_no'] = 'no',
['confirm_yes'] = 'yes',
+
+ -- garage
+ ['garage'] = 'boat garage',
+ ['garage_open'] = 'press ~INPUT_CONTEXT~ to access your ~y~boat garage~s~.',
+ ['garage_store'] = 'press ~INPUT_CONTEXT~ to ~y~store~s~ the boat in your garage.',
+ ['garage_taken'] = 'the boat has been taken out!',
+ ['garage_stored'] = 'the boat has been safely stored in your garage!',
+ ['garage_noboats'] = 'you don\'t have any stored boats! Visit the ~y~boat shop~s~ to buy one.',
+ ['garage_blocked'] = 'the boat cannot be taken out because another vehicle is blocking the spawn point!',
+
+ -- blips
+ ['blip_garage'] = 'boat Garage',
+ ['blip_shop'] = 'boat Shop',
}
\ No newline at end of file
diff --git a/server/main.lua b/server/main.lua
index fe9dde8b..a32a4f9d 100644
--- a/server/main.lua
+++ b/server/main.lua
@@ -2,9 +2,22 @@ ESX = nil
TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
-ESX.RegisterServerCallback('esx_boat:buyBoat', function (source, cb, vehicleProps, model)
+
+--[[
+AddEventHandler('onMySQLReady', function()
+ MySQL.Async.execute('UPDATE owned_vehicles SET stored = true WHERE stored = false', {}, function (rowsChanged)
+ if rowsChanged > 0 then
+ print('esx_boat: all boats have been stored!')
+ end
+ end)
+end)
+]]
+
+ESX.RegisterServerCallback('esx_boat:buyBoat', function (source, cb, vehicleProps)
local xPlayer = ESX.GetPlayerFromId(source)
- local price = getPriceFromModel(model)
+ local price = getPriceFromModel(vehicleProps.modelAlt)
+
+ vehicleProps.modelAlt = nil
-- vehicle model not found
if price == 0 then
@@ -29,17 +42,32 @@ ESX.RegisterServerCallback('esx_boat:buyBoat', function (source, cb, vehicleProp
end
end)
+RegisterServerEvent('esx_boat:takeOutVehicle')
+AddEventHandler('esx_boat:takeOutVehicle', function(plate)
+ MySQL.Async.execute('UPDATE owned_vehicles SET stored = @stored WHERE owner = @owner AND plate = @plate',
+ {
+ ['@stored'] = false,
+ ['@owner'] = GetPlayerIdentifiers(source)[1],
+ ['@plate'] = plate
+ }, function (rowsChanged)
+ print(rowsChanged)
+ end)
+
+end)
+
ESX.RegisterServerCallback('esx_boat:getGarage', function (source, cb)
- MySQL.Async.fetchAll('SELECT * FROM owned_vehicles WHERE owner = @owner, vehicleType = @vehicleType, stored = 1',
+ MySQL.Async.fetchAll('SELECT * FROM owned_vehicles WHERE owner = @owner AND vehicleType = @vehicleType AND stored = @stored',
{
- ['@owner'] = GetPlayerIdentifiers(source)[1],
- ['vehicleType'] = 'boat'
+ ['@owner'] = GetPlayerIdentifiers(source)[1],
+ ['@vehicleType'] = 'boat',
+ ['@stored'] = true
}, function (result)
local vehicles = {}
for i=1, #result, 1 do
- table.insert(vehicles, json.decode(result[i].vehicle))
+ local vehicleProps = json.decode(result[i].vehicle)
+ table.insert(vehicles, vehicleProps)
end
cb(vehicles)