├── fxmanifest.lua ├── server ├── server.lua └── updater.lua ├── README.md ├── config.lua └── client └── client.lua /fxmanifest.lua: -------------------------------------------------------------------------------- 1 | -----------------For support, scripts, and more---------------- 2 | --------------- https://discord.gg/wasabiscripts ------------- 3 | --------------------------------------------------------------- 4 | 5 | fx_version 'cerulean' 6 | game 'gta5' 7 | lua54 'yes' 8 | 9 | description 'Wasabi Sell Shop' 10 | version '1.0.1' 11 | 12 | client_scripts { 13 | 'client/**.lua' 14 | } 15 | 16 | server_scripts { 17 | 'server/**.lua' 18 | } 19 | 20 | shared_scripts { 21 | '@ox_lib/init.lua', 22 | 'config.lua' 23 | } 24 | 25 | dependencies { 26 | 'es_extended', 27 | 'qtarget', 28 | 'ox_lib' 29 | } 30 | -------------------------------------------------------------------------------- /server/server.lua: -------------------------------------------------------------------------------- 1 | -----------------For support, scripts, and more---------------- 2 | --------------- https://discord.gg/wasabiscripts ------------- 3 | --------------------------------------------------------------- 4 | 5 | ESX = exports["es_extended"]:getSharedObject() 6 | 7 | lib.callback.register('ws_sellshop:sellItem', function(source, data) 8 | local xPlayer = ESX.GetPlayerFromId(source) 9 | local xItem = xPlayer.getInventoryItem(data.item) 10 | if xItem.count < data.quantity then 11 | return false 12 | else 13 | local profit = math.floor(data.price * data.quantity) 14 | xPlayer.removeInventoryItem(data.item, data.quantity) 15 | xPlayer.addAccountMoney(data.currency, profit) 16 | return profit 17 | end 18 | end) 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # wasabi_sellshop 2 | 3 | ## Wasabi's Sell Shop 4 | 5 | **Pretty self-explanatory in the `config.lua`** 6 | 7 | ### Dependencies 8 | - ox_lib - https://github.com/overextended/ox_lib/releases 9 | - qtarget- https://github.com/overextended/qtarget/releases 10 | - es_extended 11 | 12 | ## Features 13 | - Multiple sell shops 14 | - ox_lib utilized for cached player ped, context menu, input dialog, notifications, and callbacks 15 | - Configurable shop ped 16 | - Configurable / optional blips 17 | - Configurable payment currency per item 18 | - 0.00ms usage 19 | 20 | ### Previews 21 | https://media.discordapp.net/attachments/894737355418771506/1019657341601329222/unknown.png 22 | https://media.discordapp.net/attachments/894737355418771506/1019657425030230066/unknown.png 23 | 24 | 25 | # Support 26 | ![Discord Banner 2](https://discordapp.com/api/guilds/1025493337031049358/widget.png?style=banner2) 27 | -------------------------------------------------------------------------------- /server/updater.lua: -------------------------------------------------------------------------------- 1 | -----------------For support, scripts, and more---------------- 2 | --------------- https://discord.gg/wasabiscripts ------------- 3 | --------------------------------------------------------------- 4 | 5 | local curVersion = GetResourceMetadata(GetCurrentResourceName(), "version") 6 | local resourceName = "wasabi_sellshop" 7 | 8 | if Config.checkForUpdates then 9 | CreateThread(function() 10 | if GetCurrentResourceName() ~= "wasabi_sellshop" then 11 | resourceName = "wasabi_sellshop (" .. GetCurrentResourceName() .. ")" 12 | end 13 | end) 14 | 15 | CreateThread(function() 16 | while true do 17 | PerformHttpRequest("https://api.github.com/repos/wasabirobby/wasabi_sellshop/releases/latest", CheckVersion, "GET") 18 | Wait(3600000) 19 | end 20 | end) 21 | 22 | CheckVersion = function(err, responseText, headers) 23 | local repoVersion, repoURL, repoBody = GetRepoInformations() 24 | 25 | CreateThread(function() 26 | if curVersion ~= repoVersion then 27 | Wait(4000) 28 | print("^0[^3WARNING^0] " .. resourceName .. " is ^1NOT ^0up to date!") 29 | print("^0[^3WARNING^0] Your Version: ^2" .. curVersion .. "^0") 30 | print("^0[^3WARNING^0] Latest Version: ^2" .. repoVersion .. "^0") 31 | print("^0[^3WARNING^0] Get the latest Version from: ^2" .. repoURL .. "^0") 32 | print("^0[^3WARNING^0] Changelog:^0") 33 | print("^1" .. repoBody .. "^0") 34 | else 35 | Wait(4000) 36 | print("^0[^2INFO^0] " .. resourceName .. " is up to date! (^2" .. curVersion .. "^0)") 37 | end 38 | end) 39 | end 40 | 41 | GetRepoInformations = function() 42 | local repoVersion, repoURL, repoBody = nil, nil, nil 43 | 44 | PerformHttpRequest("https://api.github.com/repos/wasabirobby/wasabi_sellshop/releases/latest", function(err, response, headers) 45 | if err == 200 then 46 | local data = json.decode(response) 47 | 48 | repoVersion = data.tag_name 49 | repoURL = data.html_url 50 | repoBody = data.body 51 | else 52 | repoVersion = curVersion 53 | repoURL = "https://github.com/wasabirobby/wasabi_sellshop" 54 | end 55 | end, "GET") 56 | 57 | repeat 58 | Wait(50) 59 | until (repoVersion and repoURL and repoBody) 60 | 61 | return repoVersion, repoURL, repoBody 62 | end 63 | end 64 | -------------------------------------------------------------------------------- /config.lua: -------------------------------------------------------------------------------- 1 | -----------------For support, scripts, and more---------------- 2 | --------------- https://discord.gg/wasabiscripts ------------- 3 | --------------------------------------------------------------- 4 | 5 | Config = {} 6 | 7 | Config.checkForUpdates = true -- Check for Updates? 8 | 9 | Config.SellShops = { 10 | --[[{ --EXAMPLE 11 | coords = vec3(123.22, 222.22, 12.22), -- Coords of sell shop 12 | heading = 123.2, -- Heading of ped in pawn shop 13 | ped = 'a_m_m_og_boss_01', -- Ped model name 14 | label = 'Sell Shop', -- Label at top of context menu/blip if enabled 15 | blip = { 16 | enabled = false, -- Enable blip? 17 | sprite = 11, -- https://docs.fivem.net/docs/game-references/blips/ 18 | color = 11, -- https://docs.fivem.net/docs/game-references/blips/ 19 | scale = 0.75 -- Scale/size of blip (0.75 default) 20 | }, 21 | items = { 22 | { item = 'water', label = 'Water', price = 12, currency = 'black_money' }, -- Self explanatory I would hope 23 | { item = 'lockpick', label = 'Lockpick', price = 12, currency = 'black_money' }, -- Self explanatory I would hope 24 | { item = 'burger', label = 'Burger', price = 12, currency = 'black_money' }, -- Self explanatory I would hope 25 | { item = 'water', label = 'Water', price = 12, currency = 'black_money' }, -- Self explanatory I would hope 26 | } 27 | },]]-- 28 | { 29 | coords = vec3(411.44, 313.27, 103.01-0.9), -- Coords of sell shop 30 | heading = 201.2, -- Heading of ped in pawn shop 31 | ped = 'a_m_m_og_boss_01', -- Ped model name 32 | label = 'Sell Shop', -- Label at top of context menu/blip if enabled 33 | blip = { 34 | enabled = false, -- Enable blip? 35 | sprite = 11, -- https://docs.fivem.net/docs/game-references/blips/ 36 | color = 11, -- https://docs.fivem.net/docs/game-references/blips/ 37 | scale = 0.75 -- Scale/size of blip (0.75 default) 38 | }, 39 | items = { 40 | { item = 'water', label = 'Water', price = 12, currency = 'black_money' }, -- Self explanatory I would hope 41 | { item = 'lockpick', label = 'Lockpick', price = 12, currency = 'black_money' }, -- Self explanatory I would hope 42 | { item = 'burger', label = 'Burger', price = 12, currency = 'black_money' }, -- Self explanatory I would hope 43 | { item = 'water', label = 'Water', price = 12, currency = 'black_money' }, -- Self explanatory I would hope 44 | } 45 | }, 46 | } -------------------------------------------------------------------------------- /client/client.lua: -------------------------------------------------------------------------------- 1 | -----------------For support, scripts, and more---------------- 2 | --------------- https://discord.gg/wasabiscripts ------------- 3 | --------------------------------------------------------------- 4 | 5 | ESX = exports["es_extended"]:getSharedObject() 6 | 7 | addCommas = function(n) 8 | return tostring(math.floor(n)):reverse():gsub("(%d%d%d)","%1,") 9 | :gsub(",(%-?)$","%1"):reverse() 10 | end 11 | 12 | CreateBlip = function(coords, sprite, colour, text, scale) 13 | local blip = AddBlipForCoord(coords) 14 | SetBlipSprite(blip, sprite) 15 | SetBlipColour(blip, colour) 16 | SetBlipAsShortRange(blip, true) 17 | SetBlipScale(blip, scale) 18 | BeginTextCommandSetBlipName("STRING") 19 | AddTextComponentString(text) 20 | EndTextCommandSetBlipName(blip) 21 | end 22 | 23 | AddEventHandler('ws_sellshop:sellItem', function(data) 24 | local data = data 25 | local input = lib.inputDialog('How many would you like to sell?', {'Quantity'}) 26 | if input then 27 | data.quantity = math.floor(tonumber(input[1])) 28 | if data.quantity < 1 then 29 | lib.notify({ 30 | title = 'Error', 31 | description = 'Please enter a valid amount!', 32 | type = 'error' 33 | }) 34 | else 35 | local done = lib.callback.await('ws_sellshop:sellItem', 100, data) 36 | if not done then 37 | lib.notify({ 38 | title = 'Error', 39 | description = 'You lacked the requested items to sell!', 40 | type = 'error' 41 | }) 42 | else 43 | lib.notify({ 44 | title = 'Success', 45 | description = 'You sold your goods for and profited $'..addCommas(done), 46 | type = 'success' 47 | }) 48 | end 49 | end 50 | else 51 | lib.notify({ 52 | title = 'Error', 53 | description = 'Please enter a valid amount!', 54 | type = 'error' 55 | }) 56 | end 57 | end) 58 | 59 | AddEventHandler('ws_sellshop:interact', function(data) 60 | local storeData = data.store 61 | local items = storeData.items 62 | local Options = {} 63 | for i=1, #items do 64 | table.insert(Options, { 65 | title = items[i].label, 66 | description = 'Sell Price: $'..items[i].price, 67 | event = 'ws_sellshop:sellItem', 68 | args = { item = items[i].item, price = items[i].price, currency = items[i].currency } 69 | }) 70 | end 71 | lib.registerContext({ 72 | id = 'storeInteract', 73 | title = storeData.label, 74 | options = Options 75 | }) 76 | lib.showContext('storeInteract') 77 | end) 78 | 79 | -- Blips/Targets 80 | CreateThread(function() 81 | for i=1, #Config.SellShops do 82 | exports.qtarget:AddBoxZone(i.."_sell_shop", Config.SellShops[i].coords, 1.0, 1.0, { 83 | name=i.."_sell_shop", 84 | heading=Config.SellShops[i].blip.heading, 85 | debugPoly=false, 86 | minZ=Config.SellShops[i].coords.z-1.5, 87 | maxZ=Config.SellShops[i].coords.z+1.5 88 | }, { 89 | options = { 90 | { 91 | event = 'ws_sellshop:interact', 92 | icon = 'fas fa-hand-paper', 93 | label = 'Interact', 94 | store = Config.SellShops[i] 95 | } 96 | }, 97 | job = 'all', 98 | distance = 1.5 99 | }) 100 | if Config.SellShops[i].blip.enabled then 101 | CreateBlip(Config.SellShops[i].coords, Config.SellShops[i].blip.sprite, Config.SellShops[i].blip.color, Config.SellShops[i].label, Config.SellShops[i].blip.scale) 102 | end 103 | end 104 | end) 105 | 106 | -- Ped spawn thread 107 | local pedSpawned = {} 108 | local pedPool = {} 109 | CreateThread(function() 110 | while true do 111 | local sleep = 1500 112 | local playerPed = cache.ped 113 | local pos = GetEntityCoords(playerPed) 114 | for i=1, #Config.SellShops do 115 | local dist = #(pos - Config.SellShops[i].coords) 116 | if dist <= 20 and not pedSpawned[i] then 117 | pedSpawned[i] = true 118 | lib.requestModel(Config.SellShops[i].ped, 100) 119 | lib.requestAnimDict('mini@strip_club@idles@bouncer@base', 100) 120 | pedPool[i] = CreatePed(28, Config.SellShops[i].ped, Config.SellShops[i].coords.x, Config.SellShops[i].coords.y, Config.SellShops[i].coords.z, Config.SellShops[i].heading, false, false) 121 | FreezeEntityPosition(pedPool[i], true) 122 | SetEntityInvincible(pedPool[i], true) 123 | SetBlockingOfNonTemporaryEvents(pedPool[i], true) 124 | TaskPlayAnim(pedPool[i], 'mini@strip_club@idles@bouncer@base','base', 8.0, 0.0, -1, 1, 0, 0, 0, 0) 125 | elseif dist >= 21 and pedSpawned[i] then 126 | local model = GetEntityModel(pedPool[i]) 127 | SetModelAsNoLongerNeeded(model) 128 | DeletePed(pedPool[i]) 129 | SetPedAsNoLongerNeeded(pedPool[i]) 130 | pedPool[i] = nil 131 | pedSpawned[i] = false 132 | end 133 | end 134 | Wait(sleep) 135 | end 136 | end) 137 | --------------------------------------------------------------------------------