├── README.md
└── s_fishing
├── fishes.sql
├── fxmanifest.lua
├── html
├── index.html
├── reset.css
├── index.css
└── index.js
├── config
└── config.lua
├── cl
├── skillcheck.lua
├── cl.lua
└── shops.lua
└── sv
└── sv.lua
/README.md:
--------------------------------------------------------------------------------
1 | # s_fishing
2 | Fishing script for FiveM
3 |
4 | Probably better than most paid ones out there, definitely better than most free releases.
5 |
--------------------------------------------------------------------------------
/s_fishing/fishes.sql:
--------------------------------------------------------------------------------
1 | INSERT INTO `items` (`name`, `label`, `weight`) VALUES
2 | ('pike', 'Pike', 1),
3 | ('bream', 'Bream', 1),
4 | ('pike_berch', 'pike_perch', 1),
5 | ('salmon', 'Salmon', 1),
6 | ('trout', 'Trout', 1),
7 | ('herring', 'Herring', 1),
8 | ('cod', 'Cod', 1),
9 | ('tuna', 'Tuna', 1),
10 | ('rod', 'Fishing rod', 1)
11 | ;
--------------------------------------------------------------------------------
/s_fishing/fxmanifest.lua:
--------------------------------------------------------------------------------
1 | fx_version 'adamant'
2 |
3 | game 'gta5'
4 |
5 | description 's_fishing' --Made by Slerbamonsteri#5636
6 |
7 | version '1.0.0'
8 |
9 | ui_page 'html/index.html'
10 |
11 | files {
12 | 'html/index.html',
13 | 'html/index.js',
14 | 'html/index.css',
15 | 'html/reset.css'
16 | }
17 |
18 | client_scripts {
19 | 'cl/cl.lua',
20 | 'cl/skillcheck.lua',
21 | 'cl/shops.lua',
22 | 'config/config.lua'
23 | }
24 |
25 | server_scripts {
26 | 'sv/sv.lua',
27 | 'sv/config.lua',
28 | 'config/config.lua'
29 | }
--------------------------------------------------------------------------------
/s_fishing/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/s_fishing/html/reset.css:
--------------------------------------------------------------------------------
1 | /* http://meyerweb.com/eric/tools/css/reset/
2 | v2.0 | 20110126
3 | License: none (public domain)
4 | */
5 |
6 | html, body, div, span, applet, object, iframe,
7 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
8 | a, abbr, acronym, address, big, cite, code,
9 | del, dfn, em, img, ins, kbd, q, s, samp,
10 | small, strike, strong, sub, sup, tt, var,
11 | b, u, i, center,
12 | dl, dt, dd, ol, ul, li,
13 | fieldset, form, label, legend,
14 | table, caption, tbody, tfoot, thead, tr, th, td,
15 | article, aside, canvas, details, embed,
16 | figure, figcaption, footer, header, hgroup,
17 | menu, nav, output, ruby, section, summary,
18 | time, mark, audio, video {
19 | margin: 0;
20 | padding: 0;
21 | border: 0;
22 | font-size: 100%;
23 | font: inherit;
24 | vertical-align: baseline;
25 | }
26 | /* HTML5 display-role reset for older browsers */
27 | article, aside, details, figcaption, figure,
28 | footer, header, hgroup, menu, nav, section {
29 | display: block;
30 | }
31 | body {
32 | line-height: 1;
33 | }
34 | ol, ul {
35 | list-style: none;
36 | }
37 | blockquote, q {
38 | quotes: none;
39 | }
40 | blockquote:before, blockquote:after,
41 | q:before, q:after {
42 | content: '';
43 | content: none;
44 | }
45 | table {
46 | border-collapse: collapse;
47 | border-spacing: 0;
48 | }
--------------------------------------------------------------------------------
/s_fishing/config/config.lua:
--------------------------------------------------------------------------------
1 | Config = {}
2 |
3 | Config.fishwebhook = 'WEBHOOK HERE' --Caught fishes -log
4 | Config.sellwebhook = 'WEBHOOK HERE' --Shopselling -log
5 | Config.licenses = true --Set to false if you do not use esx_license, this is used to add fishing licenses(permits) for players.
6 |
7 | Config.sellitemprices = { --You can add here other stuff too if you i.e add more variety of fishes
8 | pike = 12,
9 | bream = 8,
10 | pike_berch = 20,
11 | salmon = 19,
12 | trout = 17,
13 | cod = 10,
14 | herring = 7,
15 | }
16 |
17 | Config.fishes = {
18 | --Here are some examples, you can add unlimited brackets
19 | [1] = {
20 | { itemName = 'pike', howmany = 1, type = 'item'},
21 | },
22 |
23 | [2] = {
24 | { itemName = 'bream', howmany = 1, type = 'item'},
25 | },
26 |
27 | [3] = {
28 | { itemName = 'pike_berch', howmany = 1, type = 'item'},
29 | },
30 |
31 | [4] = {
32 | { itemName = 'salmon', howmany = 1, type = 'item'},
33 | },
34 |
35 | [5] = {
36 | { itemName = 'trout', howmany = 1, type = 'item'},
37 | },
38 |
39 | [6] = {
40 | { itemName = 'cod', howmany = 1, type = 'item'},
41 | },
42 |
43 | [7] = {
44 | { itemName = 'herring', howmany = 1, type = 'item'},
45 | },
46 |
47 | [8] = {
48 | { itemName = 'tuna', howmany = 1, type = 'item'},
49 | },
50 | }
--------------------------------------------------------------------------------
/s_fishing/html/index.css:
--------------------------------------------------------------------------------
1 |
2 | body {
3 | background: none !important;
4 | }
5 |
6 | #container {
7 | font-size: 20px;
8 | padding: 25px;
9 | color: white;
10 | position: relative;
11 | top: 50%;
12 | left: 50%;
13 | transform: translate(-50%, -50%);
14 | background-color: rgba(44, 44, 44, 0);
15 | }
16 |
17 |
18 |
19 | .Buttons {
20 | width: 75px;
21 | height: 75px;
22 | background-color: rgba(79, 79, 79, 150);
23 | border-radius: 10px 10px;
24 | border: 1px solid rgb(163, 163, 163);
25 | box-shadow: 5px;
26 | padding: 1px;
27 | font-size: 30px;
28 | font-weight: bold;
29 | color: white;
30 | -webkit-box-shadow: inset 0 0px 0 #000000, 4px 8px 0 #000000;
31 | margin-left: 60%;
32 | }
33 |
34 | .timer1 {
35 | margin-top: 30px;
36 | height: 5px;
37 | width: 500px;
38 | position: absolute;
39 | z-index: 2;
40 | background-color: rgb(143, 98, 0);
41 | margin-left: 36.9791666667%;
42 | margin-top: 25%;
43 | border-radius: 10px 10px;
44 | }
45 |
46 | .timer2 {
47 | margin-top: 30px;
48 | height: 5px;
49 | width: 100px;
50 | position: absolute;
51 | z-index: 3;
52 | background-color: rgb(255, 174, 0);
53 | margin-left: 36.9791666667%;
54 | margin-top: 25%;
55 | border-radius: 10px 10px;
56 | }
--------------------------------------------------------------------------------
/s_fishing/cl/skillcheck.lua:
--------------------------------------------------------------------------------
1 |
2 | --skillcheck stuff
3 |
4 | local display = false
5 | local notComplete = false
6 | local failure = false
7 | local Callback = {}
8 |
9 |
10 | RegisterNUICallback("exit", function(data)
11 | chat("Failed!", {0,255,0})
12 | SetDisplay(false)
13 | end)
14 |
15 |
16 | RegisterNUICallback("error", function(data)
17 | if data.error == 'Complete!' then
18 | SetDisplay(false)
19 | notComplete = false
20 | else
21 | SetDisplay(false)
22 | notComplete = false
23 | failure = true
24 | end
25 | end)
26 |
27 | function SetDisplay(bool)
28 | SetNuiFocus(bool, false)
29 | SendNUIMessage({
30 | type = "ui",
31 | status = bool,
32 | })
33 | end
34 |
35 | RegisterNetEvent('s_fishing:minigame')
36 | AddEventHandler('s_fishing:minigame', function(func)
37 | Callback = func
38 | SetDisplay(not display)
39 | notComplete = true
40 | failure = false
41 | while notComplete do
42 | Citizen.Wait(100)
43 | end
44 | if failure then
45 | Callback(false)
46 | else
47 | Callback(true)
48 | end
49 | end)
50 |
51 | Citizen.CreateThread(function()
52 | while display do
53 | Citizen.Wait(0)
54 | -- https://runtime.fivem.net/doc/natives/#_0xFE99B66D079CF6BC
55 | --[[
56 | inputGroup -- integer ,
57 | control --integer ,
58 | disable -- boolean
59 | ]]
60 | DisableControlAction(0, 1, display) -- LookLeftRight
61 | DisableControlAction(0, 2, display) -- LookUpDown
62 | DisableControlAction(0, 142, display) -- MeleeAttackAlternate
63 | DisableControlAction(0, 18, display) -- Enter
64 | DisableControlAction(0, 322, display) -- ESC
65 | DisableControlAction(0, 106, display) -- VehicleMouseControlOverride
66 | end
67 | end)
68 |
69 | function chat(str, color)
70 | TriggerEvent(
71 | 'chat:addMessage',
72 | {
73 | color = color,
74 | multiline = true,
75 | args = {str}
76 | }
77 | )
78 | end
--------------------------------------------------------------------------------
/s_fishing/html/index.js:
--------------------------------------------------------------------------------
1 | $(function () {
2 | function display(bool) {
3 | if (bool) {
4 | $("#container").show();
5 | } else {
6 | $("#container").hide();
7 | }
8 | }
9 | function sleep(ms) {
10 | return new Promise(resolve => setTimeout(resolve, ms));
11 | }
12 |
13 | let progress = 0;
14 | let divide = 0;
15 | let doTimer = false;
16 |
17 |
18 |
19 | async function countdown() {
20 | //document.getElementById('timer').style.width = '480px';
21 | let timerWidth = '500';
22 | for (i = 0; i < 500; i++) {
23 | if (doTimer) {
24 | timerWidth = timerWidth - 1
25 | document.getElementById('timer').style.width = timerWidth + 'px';
26 | await sleep(8)
27 | if (timerWidth === 0) {
28 | playingGame = false;
29 | timerStarted = false;
30 | $.post("https://s_fishing/error", JSON.stringify({
31 | error: "You took too long!"
32 | }))
33 | document.getElementById('1').style.backgroundColor = '';
34 | }
35 | } else {
36 | break;
37 | }
38 | }
39 | }
40 |
41 | display(false)
42 |
43 | window.addEventListener('message', function(event) {
44 | var item = event.data;
45 | if (item.type === "ui") {
46 | if (item.status == true) {
47 | display(true)
48 | progress = 0;
49 | divide = Math.floor(Math.random()*5)*5 + 5
50 | if (divide < 10) {
51 | divide = 10
52 | }
53 | document.getElementById('timer').style.width = '500px';
54 | doTimer = true;
55 | countdown()
56 | } else {
57 | display(false)
58 | }
59 | }
60 | })
61 |
62 |
63 | // if the person uses the escape key, it will exit the resource
64 | document.onkeyup = function (data) {
65 | if (data.which == 27) {
66 | doTimer = false;
67 | $.post('https://s_fishing/exit', JSON.stringify({}));
68 | return
69 | } else if (data.which == 69) {
70 | progress = progress + divide;
71 | $("button").css("-webkit-box-shadow", "inset 4px 4px 0 #000000, 2px 4px 0 #000000");
72 | setTimeout(function(){
73 | $("button").css("-webkit-box-shadow", "");
74 | }, 30);
75 | if (progress > 255) {
76 | doTimer = false;
77 | $("button").css("background-color", "");
78 | $.post("https://s_fishing/error", JSON.stringify({
79 | error: "Complete!"
80 | }))
81 | } else {
82 | $("button").css("background-color", "rgb(" + progress + "," + progress+ "," + progress + ")");
83 | }
84 | }
85 | };
86 |
87 | })
--------------------------------------------------------------------------------
/s_fishing/sv/sv.lua:
--------------------------------------------------------------------------------
1 | ESX = nil
2 |
3 | TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
4 |
5 | ESX.RegisterUsableItem('rod', function(source)
6 | TriggerClientEvent('s_fishing:start', source)
7 | end)
8 |
9 | AddEventHandler('esx:playerLoaded', function(source)
10 | print('playerloaded')
11 | TriggerEvent('pkrp_license:getLicenses', source, function(licenses)
12 | TriggerClientEvent('s_fishing:loadLicenses', source, licenses)
13 | end)
14 | end)
15 |
16 |
17 | --Fishing stuff
18 | RegisterServerEvent('s_fishing:caught')
19 | AddEventHandler('s_fishing:caught', function()
20 | local _source = source
21 | local xPlayer = ESX.GetPlayerFromId(_source)
22 | local RBrackets = math.random(1, #Config.fishes)
23 | local name = GetPlayerName(source)
24 | if xPlayer ~=nil then
25 | for k,v in pairs(Config.fishes[RBrackets]) do
26 | if v.type == 'item' then
27 | xPlayer.addInventoryItem(v.itemName, v.howmany)
28 | sendToDiscord(66666, "Fishing", name .. " Caught: " ..v.itemName.. 'x ' ..v.howmany..'.', "s_fishingLOG")
29 | elseif v.type == 'weapon' then
30 | for i=1, v.howmany, 1 do
31 | xPlayer.addWeapon(v.itemName, v.ammo)
32 | sendToDiscord(66666, "Fishing", name .. " Caught: " ..v.itemName.. 'x ' ..v.ammo..'.', "s_fishingLOG")
33 | end
34 | elseif v.type == 'money' then
35 | xPlayer.addMoney(v.howmany)
36 | sendToDiscord(66666, "Fishing", name .. " Caught some money: "..v.howmany..'.', "s_fishingLOG")
37 | end
38 | end
39 | end
40 | end)
41 |
42 | --Selling stuff
43 | RegisterServerEvent('s_fishing:sell')
44 | AddEventHandler('s_fishing:sell', function()
45 | local _source = source
46 | local xPlayer = ESX.GetPlayerFromId(_source)
47 | local name = GetPlayerName(_source)
48 | for q,p in pairs(Config.sellitemprices) do
49 | local item = xPlayer.getInventoryItem(q)
50 | if item.count >= 1 then
51 | xPlayer.addMoney(item.count * p)
52 | xPlayer.removeInventoryItem(q, item.count)
53 | xPlayer.showNotification('Sold fish ~b~' ..item.label.. '~s~ for ~g~'..item.count * p ..'$')
54 | sendToDiscord2(56222, 'Fish market', '**'..name.. '** | **Sold:** [*' ..item.label.. '*]** for:** [' ..item.count * p.. '$]', 's_fishingLOG')
55 | end
56 | end
57 | end)
58 |
59 | --Purcahse fishing rod
60 | RegisterServerEvent("s_fishing:buyrod")
61 | AddEventHandler("s_fishing:buyrod", function()
62 | local xPlayer = ESX.GetPlayerFromId(source)
63 | if xPlayer.getAccount('bank').money >= 200 then
64 | xPlayer.removeAccountMoney('bank', 200)
65 | xPlayer.addInventoryItem('rod', 1)
66 | else
67 | xPlayer.showNotification('Not enough money (200$)')
68 | end
69 | end)
70 |
71 | --License stuff
72 | ESX.RegisterServerCallback('s_fishing:buyLicense', function(source, cb)
73 | local xPlayer = ESX.GetPlayerFromId(source)
74 |
75 | if xPlayer.getAccount('bank').money >= 250 then
76 | xPlayer.removeAccountMoney('bank', 250)
77 |
78 | TriggerEvent('pkrp_license:addLicense', source, 'fishing', function()
79 | xPlayer.showNotification('You now own fishing permits')
80 | cb(true)
81 | end)
82 | else
83 | xPlayer.showNotification('Not enough money')
84 | cb(false)
85 | end
86 | end)
87 |
88 | function sendToDiscord(color, name, message, footer)
89 | local embed = {
90 | {
91 | ["color"] = color,
92 | ["title"] = "**".. name .."**",
93 | ["description"] = message,
94 | ["footer"] = {
95 | ["text"] = footer,
96 | },
97 | }
98 | }
99 | PerformHttpRequest(Config.fishwebhook, function(err, text, headers) end, 'POST', json.encode({username = name, embeds = embed}), { ['Content-Type'] = 'application/json' })
100 | end
101 |
102 | function sendToDiscord2(color, name, message, footer)
103 | local embed = {
104 | {
105 | ["color"] = color,
106 | ["title"] = "**".. name .."**",
107 | ["description"] = message,
108 | ["footer"] = {
109 | ["text"] = footer,
110 | },
111 | }
112 | }
113 | PerformHttpRequest(Config.sellwebhook, function(err, text, headers) end, 'POST', json.encode({username = name, embeds = embed}), { ['Content-Type'] = 'application/json' })
114 | end
115 |
116 |
--------------------------------------------------------------------------------
/s_fishing/cl/cl.lua:
--------------------------------------------------------------------------------
1 | ESX = nil
2 |
3 | Citizen.CreateThread(function()
4 | while ESX == nil do
5 | TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
6 | Citizen.Wait(0)
7 | end
8 | end)
9 |
10 | --Some code i found in vrP_fishing
11 | function AttachEntityToPed(prop,bone_ID,x,y,z,RotX,RotY,RotZ)
12 | BoneID = GetPedBoneIndex(PlayerPedId(), bone_ID)
13 | obj = CreateObject(GetHashKey(prop), 1729.73, 6403.90, 34.56, true, true, true)
14 | vX,vY,vZ = table.unpack(GetEntityCoords(PlayerPedId()))
15 | xRot, yRot, zRot = table.unpack(GetEntityRotation(PlayerPedId(),2))
16 | AttachEntityToEntity(obj, PlayerPedId(), BoneID, x,y,z, RotX,RotY,RotZ, false, false, false, false, 2, true)
17 | return obj
18 | end
19 |
20 | local draw = false
21 | local rng22 = false
22 |
23 | --starting up
24 | RegisterNetEvent('s_fishing:start')
25 | AddEventHandler('s_fishing:start', function()
26 | local pedc = GetEntityCoords(PlayerPedId())
27 | local boat = GetClosestVehicle(pedc.x, pedc.y, pedc.z, 5.0, 0, 12294)
28 | if IsEntityInWater(PlayerPedId()) or IsEntityInWater(boat) then
29 | if not IsPedInAnyVehicle(PlayerPedId(), false) then
30 | if not IsPedSwimming(PlayerPedId()) then
31 | ESX.UI.Menu.CloseAll()
32 | draw = true
33 | rng22 = true
34 | ESX.ShowNotification('Fishing...')
35 | TriggerEvent('s_fishing:rng')
36 | fishing()
37 | else
38 | ESX.ShowNotification('You have to decide, whether you want to swim or fish')
39 | end
40 | end
41 | else
42 | ESX.ShowNotification('I can´t fish here...')
43 | end
44 | end)
45 |
46 | --Anim & Prop & Triggering them fishy fishes
47 | function fishing()
48 | RequestAnimDict('amb@world_human_stand_fishing@idle_a')
49 | while not HasAnimDictLoaded('amb@world_human_stand_fishing@idle_a') do
50 | Citizen.Wait(1)
51 | end
52 | rod = AttachEntityToPed('prop_fishing_rod_01',60309, 0,0,0, 0,0,0)
53 | TaskPlayAnim(PlayerPedId(), 'amb@world_human_stand_fishing@idle_a', 'idle_b', 8.0, 8.0, -1, 1, 1, 0, 0, 0)
54 | drawtext()
55 | end
56 |
57 | --Drawing function, added as an extra spice inventory disabling.. Just to make sure players wont fuck anything up or exploit anything
58 | function drawtext()
59 | local pedcoords = GetEntityCoords(PlayerPedId())
60 | while draw do
61 | w = 5
62 | DisableControlAction(0, 288, true) -- F1
63 | DisableControlAction(0, 289, true) -- F2
64 | Draw3DText(pedcoords.x - 1, pedcoords.y, pedcoords.z + 1,'Press [~r~X~s~] to stop fishing')
65 | if IsControlJustPressed(0, 73) then
66 | ESX.ShowNotification('Stopped fishing')
67 | DeleteEntity(rod)
68 | DeleteObject(rod)
69 | rng22 = false
70 | TriggerEvent('s_fishing:rng')
71 | cancel()
72 | ClearPedTasks(PlayerPedId())
73 | break
74 | end
75 | Citizen.Wait(w)
76 | end
77 | while not draw do
78 | break
79 | end
80 | end
81 |
82 | AddEventHandler('s_fishing:rng', function()
83 | while rng22 do
84 | Wait(math.random(13000, 32000))
85 | catchfish()
86 | ClearPedTasks(PlayerPedId())
87 | DeleteObject(rod)
88 | DeleteEntity(rod)
89 | break
90 | end
91 | while not rng22 do
92 | catchfish()
93 | break
94 | end
95 | end)
96 |
97 | function catchfish()
98 | if rng22 then
99 | TriggerEvent('s_fishing:minigame', function(success)
100 | if success then
101 | TriggerServerEvent('s_fishing:caught')
102 | cancel()
103 | Citizen.Wait(10)
104 | TriggerEvent('s_fishing:start')
105 | else
106 | rng22 = false
107 | cancel()
108 | ClearPedTasks(PlayerPedId())
109 | TriggerEvent('s_fishing:rng')
110 | ESX.ShowNotification("You didn't catch anything, try again")
111 | end
112 | end)
113 | end
114 | end
115 |
116 | function cancel()
117 | draw = false
118 | DeleteObject(rod)
119 | DeleteEntity(rod)
120 | drawtext()
121 | ClearPedTasks(PlayerPedId())
122 | end
123 |
124 | --Drawtext
125 | function Draw3DText(x,y,z, text)
126 | local onScreen,_x,_y=World3dToScreen2d(x,y,z)
127 | local px,py,pz=table.unpack(GetGameplayCamCoords())
128 |
129 | SetTextScale(0.35, 0.35)
130 | SetTextFont(8)
131 | SetTextProportional(1)
132 | SetTextColour(255, 255, 255, 215)
133 | SetTextEntry("STRING")
134 | SetTextCentre(1)
135 | SetTextOutline()
136 | AddTextComponentString(text)
137 | DrawText(_x,_y)
138 | end
139 |
--------------------------------------------------------------------------------
/s_fishing/cl/shops.lua:
--------------------------------------------------------------------------------
1 | ESX = nil
2 | local Licenses = {}
3 | --Make peds face playerped
4 | Citizen.CreateThread(function()
5 | while ESX == nil do
6 | TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end)
7 | Citizen.Wait(0)
8 | end
9 | ESX.Game.MakeEntityFaceEntity = function(entity1, entity2)
10 | local p1 = GetEntityCoords(entity1, true)
11 | local p2 = GetEntityCoords(entity2, true)
12 |
13 | local dx = p2.x - p1.x
14 | local dy = p2.y - p1.y
15 |
16 | local heading = GetHeadingFromVector_2d(dx, dy)
17 | SetEntityHeading( entity1, heading )
18 | end
19 | end)
20 |
21 |
22 | --Add as many sellpoints as you wish
23 | local shopnpc = {
24 | {x =-1845.49, y = -1196.50, z = 18.18},
25 | --{x =-1845.49, y = -1196.50, z = 18.18},
26 | --{x =-1845.49, y = -1196.50, z = 18.18}
27 | }
28 |
29 | --Function to spawn shopnpc
30 | function spawnshopnpc()
31 | Citizen.CreateThread(function()
32 | local sleep = 1000
33 | local ped = GetHashKey("s_m_m_linecook")
34 | RequestModel(ped)
35 | while not HasModelLoaded(ped) do
36 | Citizen.Wait(1)
37 | end
38 | for k,v in pairs(shopnpc) do
39 | shop = CreatePed(4, ped, v.x, v.y, v.z, 78.20, false, true)
40 | local npc = GetEntityCoords(shop)
41 | local playerped = GetEntityCoords(PlayerPedId())
42 | local dist = #(npc - playerped)
43 | SetEntityInvincible(shop, true)
44 | PlaceObjectOnGroundProperly(shop)
45 | TaskSetBlockingOfNonTemporaryEvents(shop, true)
46 | Citizen.Wait(1000)
47 | FreezeEntityPosition(shop, true)
48 | while true do
49 | Citizen.Wait(50)
50 | playerped = GetEntityCoords(PlayerPedId())
51 | dist = #(npc - playerped)
52 | if dist < 5 then
53 | ESX.Game.MakeEntityFaceEntity(shop, PlayerPedId())
54 | else
55 | Citizen.Wait(sleep)
56 | end
57 | end
58 | end
59 | end)
60 | end
61 |
62 | --Shop purchase
63 | function fishshop()
64 | local ownedLicenses = {}
65 | for i=1, #Licenses, 1 do
66 | ownedLicenses[Licenses[i].type] = true
67 | end
68 | ESX.UI.Menu.CloseAll()
69 | FreezeEntityPosition(PlayerPedId(),true)
70 | local elements = {}
71 | table.insert(elements, {label = 'Purchase fishing rod - 200$', value = 'buyrod'})
72 | if Config.licenses then
73 | if not ownedLicenses['fishing'] then
74 | table.insert(elements, {label = 'Purchase Fishing Permit - 250$', value = 'buylice'})
75 | else
76 | table.insert(elements, {label = 'You already own Fishing permits', value = 'exit'})
77 | end
78 | end
79 | table.insert(elements, {label = 'Exit', value = 'exit'})
80 | ESX.UI.Menu.Open(
81 | 'default', GetCurrentResourceName(), 'fishingshop',
82 | {
83 | title = 'Fish shop',
84 | align = 'center',
85 | elements = elements
86 | },
87 | function(data, menu)
88 | if data.current.value == 'buyrod' then
89 | TriggerServerEvent("s_fishing:buyrod")
90 | elseif data.current.value == 'buylice' then
91 | ESX.TriggerServerCallback('s_fishing:buyLicense', function(bought)
92 | if bought then
93 | menu.close()
94 | end
95 | end)
96 | elseif data.current.value == 'exit' then
97 | ESX.UI.Menu.CloseAll()
98 | end
99 | FreezeEntityPosition(PlayerPedId(),false)
100 | ESX.UI.Menu.CloseAll()
101 | end)
102 | end
103 |
104 | --Shop sell
105 | function shopsell()
106 | ESX.UI.Menu.CloseAll()
107 | FreezeEntityPosition(PlayerPedId(),true)
108 | ESX.UI.Menu.Open(
109 | 'default', GetCurrentResourceName(), 'fshop',
110 | {
111 | title = 'Fish market',
112 | align = 'center',
113 | elements = {
114 | {label = 'Sell fish', value = 'sell'},
115 | {label = 'Exit', value = 'exit'},
116 | },
117 | },
118 | function(data, menu)
119 | if data.current.value == 'sell' then
120 | TriggerServerEvent("s_fishing:sell", source)
121 | ESX.UI.Menu.CloseAll()
122 | elseif data.current.value == 'exit' then
123 | ESX.UI.Menu.CloseAll()
124 | end
125 | FreezeEntityPosition(PlayerPedId(),false)
126 | ESX.UI.Menu.CloseAll()
127 | end)
128 | end
129 |
130 | --Store stuff
131 | Citizen.CreateThread(function()
132 | while true do
133 | Citizen.Wait(5)
134 | local playerped = GetEntityCoords(PlayerPedId())
135 | for k,v in pairs(shopnpc) do
136 | local dist = #(vector3(v.x, v.y, v.z) - playerped)
137 | local ClockTime = GetClockHours()
138 | local w = 1000
139 | if dist < 5 then
140 | Draw3DText2(v.x, v.y, v.z + 0.5, "[~r~E~w~] Open shop | [~g~G~w~] Sell your fishes")
141 | if IsControlJustReleased(0, 38) then
142 | if ClockTime >= 6 -1 and ClockTime < 22 then
143 | fishshop()
144 | else
145 | TriggerEvent('mythic_notify:client:slerba', { type = 'error', length = 7000, text = 'Shop is currently unavailable' })
146 | end
147 | elseif IsControlJustPressed(0, 47) then
148 | shopsell()
149 | end
150 | else
151 | Citizen.Wait(w)
152 | end
153 | end
154 | end
155 | end)
156 |
157 | --License stuff from copied from esx_dmvschool
158 | RegisterNetEvent('s_fishing:loadLicenses')
159 | AddEventHandler('s_fishing:loadLicenses', function(licenses)
160 | Licenses = licenses
161 | end)
162 |
163 | --Blip and npc stuff
164 | Citizen.CreateThread(function()
165 | spawnshopnpc()
166 | Wait(300)
167 | for k,v in pairs(shopnpc) do
168 | sellblip = AddBlipForCoord(v.x, v.y, v.z)
169 | SetBlipSprite(sellblip, 356)
170 | SetBlipColour(sellblip, 83)
171 | SetBlipScale(sellblip, 0.8)
172 | SetBlipAsShortRange(sellblip, true)
173 | BeginTextCommandSetBlipName('STRING')
174 | AddTextComponentString('Fish market') -- set blip's "name"
175 | EndTextCommandSetBlipName(sellblip)
176 | end
177 | end)
178 |
179 | --3D text stuff
180 | function Draw3DText2(x,y,z, text)
181 | local onScreen,_x,_y=World3dToScreen2d(x,y,z)
182 | local px,py,pz=table.unpack(GetGameplayCamCoords())
183 |
184 | SetTextScale(0.35, 0.35)
185 | SetTextFont(4)
186 | SetTextProportional(1)
187 | SetTextColour(255, 255, 255, 215)
188 | SetTextEntry("STRING")
189 | SetTextCentre(1)
190 | AddTextComponentString(text)
191 | DrawText(_x,_y)
192 | local factor = (string.len(text)) / 370
193 | DrawRect(_x,_y+0.0125, 0.015+ factor, 0.03, 0, 0, 0, 68)
194 | end
195 |
--------------------------------------------------------------------------------