From 75db08b9a1af8898f03aab8750992d6322736385 Mon Sep 17 00:00:00 2001 From: Nordi98 Date: Tue, 1 Jul 2025 12:45:49 +0200 Subject: [PATCH] ed --- .../[civ]/wasabi_fishing/client/client.lua | 71 +--- .../wasabi_fishing/configuration/config.lua | 38 +- .../[civ]/wasabi_fishing/server/server.lua | 333 +++++++++--------- 3 files changed, 204 insertions(+), 238 deletions(-) diff --git a/resources/[jobs]/[civ]/wasabi_fishing/client/client.lua b/resources/[jobs]/[civ]/wasabi_fishing/client/client.lua index ddccb7a3d..bf6dc2db5 100644 --- a/resources/[jobs]/[civ]/wasabi_fishing/client/client.lua +++ b/resources/[jobs]/[civ]/wasabi_fishing/client/client.lua @@ -6,7 +6,7 @@ local fishing = false if Config.sellShop.enabled then CreateThread(function() local ped, textUI - --CreateBlip(Config.sellShop.coords, 356, 1, Strings.sell_shop_blip, 0.80) + CreateBlip(Config.sellShop.coords, 356, 1, Strings.sell_shop_blip, 0.80) local point = lib.points.new({ coords = Config.sellShop.coords, distance = 30 @@ -51,9 +51,8 @@ if Config.sellShop.enabled then end) end --- Function to select bait from available options --- Function to select bait from available options -local function SelectBait() +-- Function to check for available baits and select the best one +local function GetBestAvailableBait() local availableBaits = {} -- Check all bait types @@ -68,31 +67,15 @@ local function SelectBait() return nil end - -- If only one bait type is available, use it directly - if #availableBaits == 1 then - return availableBaits[1] - end - - -- Create a notification about available baits - local baitNames = "" - for i, bait in ipairs(availableBaits) do - if i > 1 then baitNames = baitNames .. ", " end - baitNames = baitNames .. bait.label - end - - TriggerEvent('wasabi_fishing:notify', 'Available Baits', 'You have: ' .. baitNames, 'inform') - - -- Just use the best bait available (highest catch bonus) + -- Sort baits by catch bonus (highest first) table.sort(availableBaits, function(a, b) - return a.catchBonus > b.catchBonus + return (a.catchBonus or 0) > (b.catchBonus or 0) end) - TriggerEvent('wasabi_fishing:notify', 'Selected Bait', 'Using ' .. availableBaits[1].label .. ' (best available)', 'inform') + -- Return the best bait return availableBaits[1] end - - -- Function to handle the fishing process local function StartFishingProcess(selectedBait, waterLoc) fishing = true @@ -154,16 +137,14 @@ local function StartFishingProcess(selectedBait, waterLoc) TriggerServerEvent('wasabi_fishing:loseBait', selectedBait.itemName) TriggerEvent('wasabi_fishing:notify', Strings.bait_lost, Strings.bait_lost_desc, 'error') - -- Check if we still have bait + -- Check if we still have this bait local hasBait = lib.callback.await('wasabi_fishing:checkItem', 100, selectedBait.itemName) if not hasBait then - TriggerEvent('wasabi_fishing:notify', Strings.no_more_bait, Strings.no_more_bait_desc, 'error') - - -- Try to select a new bait - local newBait = SelectBait() + -- Try to get a new bait + local newBait = GetBestAvailableBait() if newBait then selectedBait = newBait - TriggerEvent('wasabi_fishing:notify', Strings.new_bait, string.format(Strings.new_bait_desc, selectedBait.label), 'inform') + TriggerEvent('wasabi_fishing:notify', 'New Bait', 'Using ' .. selectedBait.label .. ' as bait', 'inform') else TriggerEvent('wasabi_fishing:notify', Strings.no_bait, Strings.no_bait_desc, 'error') fishing = false @@ -186,11 +167,11 @@ local function StartFishingProcess(selectedBait, waterLoc) elseif IsControlJustReleased(0, 194) then -- Cancel fishing with backspace ClearPedTasks(cache.ped) - TriggerEvent('wasabi_fishing:notify', Strings.fishing_canceled, Strings.fishing_canceled_desc, 'inform') + TriggerEvent('wasabi_fishing:notify', 'Fishing Canceled', 'You stopped fishing', 'inform') break elseif #(GetEntityCoords(cache.ped) - waterLoc) > 30 then -- Too far from water - TriggerEvent('wasabi_fishing:notify', Strings.too_far, Strings.too_far_desc, 'error') + TriggerEvent('wasabi_fishing:notify', 'Too Far', 'You moved too far from the water', 'error') break end end @@ -211,7 +192,7 @@ RegisterNetEvent('wasabi_fishing:startFishing', function() -- Check if already fishing if fishing then - TriggerEvent('wasabi_fishing:notify', Strings.already_fishing, Strings.already_fishing_desc, 'error') + TriggerEvent('wasabi_fishing:notify', 'Already Fishing', 'You are already fishing', 'error') return end @@ -223,14 +204,14 @@ RegisterNetEvent('wasabi_fishing:startFishing', function() end -- Select bait - local selectedBait = SelectBait() + local selectedBait = GetBestAvailableBait() if not selectedBait then TriggerEvent('wasabi_fishing:notify', Strings.no_bait, Strings.no_bait_desc, 'error') return end -- Start fishing process - TriggerEvent('wasabi_fishing:notify', Strings.bait_selected, string.format(Strings.bait_selected_desc, selectedBait.label), 'inform') + TriggerEvent('wasabi_fishing:notify', 'Bait Selected', 'Using ' .. selectedBait.label .. ' as bait', 'inform') StartFishingProcess(selectedBait, waterLoc) end) @@ -239,27 +220,12 @@ RegisterNetEvent('wasabi_fishing:processFish', function(fishItem) -- Check if player has knife local hasKnife = lib.callback.await('wasabi_fishing:checkItem', 100, Config.processing.knifeItem) if not hasKnife then - TriggerEvent('wasabi_fishing:notify', Strings.no_knife, Strings.no_knife_desc, 'error') - return - end - - -- Find processing data for this fish - local processData = nil - for _, data in pairs(Config.processing.products) do - if data.sourceItem == fishItem then - processData = data - break - end - end - - if not processData then - TriggerEvent('wasabi_fishing:notify', Strings.cannot_process, Strings.cannot_process_desc, 'error') + TriggerEvent('wasabi_fishing:notify', 'No Knife', 'You need a knife to process fish', 'error') return end -- Start processing animation local playerPed = cache.ped - local coords = GetEntityCoords(playerPed) lib.requestAnimDict('anim@amb@business@coc@coc_unpack_cut@', 100) TaskPlayAnim(playerPed, 'anim@amb@business@coc@coc_unpack_cut@', 'fullcut_cycle_v6_cokecutter', 8.0, -8.0, -1, 1, 0, false, false, false) @@ -267,7 +233,7 @@ RegisterNetEvent('wasabi_fishing:processFish', function(fishItem) -- Processing progress bar if lib.progressBar({ duration = 5000, - label = Strings.processing_fish, + label = 'Processing Fish', useWhileDead = false, canCancel = true, disable = { @@ -284,7 +250,7 @@ RegisterNetEvent('wasabi_fishing:processFish', function(fishItem) TriggerServerEvent('wasabi_fishing:processItem', fishItem) else -- Cancelled - TriggerEvent('wasabi_fishing:notify', Strings.canceled, Strings.canceled_desc, 'error') + TriggerEvent('wasabi_fishing:notify', 'Canceled', 'Fish processing canceled', 'error') end ClearPedTasks(playerPed) @@ -295,4 +261,3 @@ RegisterNetEvent('wasabi_fishing:interupt', function() fishing = false ClearPedTasks(cache.ped) end) - diff --git a/resources/[jobs]/[civ]/wasabi_fishing/configuration/config.lua b/resources/[jobs]/[civ]/wasabi_fishing/configuration/config.lua index f055dc89b..3d4f3445a 100644 --- a/resources/[jobs]/[civ]/wasabi_fishing/configuration/config.lua +++ b/resources/[jobs]/[civ]/wasabi_fishing/configuration/config.lua @@ -10,8 +10,8 @@ Config.oldESX = false -- Nothing to do with qb / Essentially when set to true it Config.sellShop = { enabled = true, - coords = vec3(-1597.1718, 5201.9839, 3.3590), -- X, Y, Z Coords of where fish buyer will spawn - heading = 234.6800, -- Heading of fish buyer ped + coords = vec3(-1612.19, -989.18, 13.01-0.9), -- X, Y, Z Coords of where fish buyer will spawn + heading = 45.3, -- Heading of fish buyer ped ped = 'cs_old_man2' -- Ped name here } @@ -44,16 +44,34 @@ Config.bait = { { itemName = 'young_salmon', label = 'Young Salmon', + loseChance = 80, -- easy to lose + catchBonus = 25 -- 25% better catch chance + }, + { + itemName = 'illegal_bait', + label = 'Illegal Bait', loseChance = 60, catchBonus = 20, -- 20% better catch chance exclusive = {'pufferfish'} -- can only catch pufferfish with this } }, - defaultBait = 'fishbait' -- Default bait item name + defaultBait = 'fishbait', -- Default bait item name + itemName = 'fishbait', -- For backwards compatibility + loseChance = 65 -- For backwards compatibility +} + +Config.fishingRod = { + itemName = 'fishingrod', -- Item name of fishing rod + breakChance = 25 --Chance of breaking pole when failing skillbar (Setting to 0 means never break) +} + +Config.timeForBite = { -- Set min and max random range of time it takes for fish to be on the line. + min = 2 * seconds, + max = 20 * seconds } Config.processing = { - knifeItem = 'weapon_knife', + knifeItem = 'knife', products = { { sourceItem = 'tuna', @@ -115,18 +133,6 @@ Config.processedItems = { { item = 'caviar', label = 'Caviar', price = {300, 500} }, } - -Config.fishingRod = { - itemName = 'fishingrod', -- Item name of fishing rod - breakChance = 25 --Chance of breaking pole when failing skillbar (Setting to 0 means never break) -} - -Config.timeForBite = { -- Set min and max random range of time it takes for fish to be on the line. - min = 2 * seconds, - max = 20 * seconds -} - - RegisterNetEvent('wasabi_fishing:notify') AddEventHandler('wasabi_fishing:notify', function(title, message, msgType) -- Place notification system info here, ex: exports['mythic_notify']:SendAlert('inform', message) diff --git a/resources/[jobs]/[civ]/wasabi_fishing/server/server.lua b/resources/[jobs]/[civ]/wasabi_fishing/server/server.lua index 8640b63b8..38e211d39 100644 --- a/resources/[jobs]/[civ]/wasabi_fishing/server/server.lua +++ b/resources/[jobs]/[civ]/wasabi_fishing/server/server.lua @@ -15,177 +15,9 @@ lib.callback.register('wasabi_fishing:checkItem', function(source, itemname) end end) -lib.callback.register('wasabi_fishing:getFishData', function(source) - local data = Config.fish[math.random(#Config.fish)] - return data -end) - -RegisterNetEvent('wasabi_fishing:rodBroke', function() - RemoveItem(source, Config.fishingRod.itemName, 1) - TriggerClientEvent('wasabi_fishing:interupt', source) -end) - -RegisterNetEvent('wasabi_fishing:tryFish', function(data) - local xPole = HasItem(source, Config.fishingRod.itemName) - local xBait = HasItem(source, Config.bait.itemName) - if xPole > 0 and xBait > 0 then - local chance = math.random(1,100) - if chance <= Config.bait.loseChance then - RemoveItem(source, Config.bait.itemName, 1) - TriggerClientEvent('wasabi_fishing:notify', source, Strings.bait_lost, Strings.bait_lost_desc, 'error') - end - if Framework == 'esx' and not Config.oldESX then - local player = GetPlayer(source) - if player.canCarryItem(data.item, 1) then - AddItem(source, data.item, 1) - TriggerClientEvent('wasabi_fishing:notify', source, Strings.fish_success, string.format(Strings.fish_success_desc, data.label), 'success') - else - TriggerClientEvent('wasabi_fishing:notify', source, Strings.cannot_carry, Strings.cannot_carry_desc, 'error') - end - else - AddItem(source, data.item, 1) - TriggerClientEvent('wasabi_fishing:notify', source, Strings.fish_success, string.format(Strings.fish_success_desc, data.label), 'success') - end - elseif xPole > 0 and xBait < 1 then - TriggerClientEvent('wasabi_fishing:interupt', source) - TriggerClientEvent('wasabi_fishing:notify', source, Strings.no_bait, Strings.no_bait_desc, 'error') - elseif xPole < 1 then - KickPlayer(source, Strings.kicked) - end -end) - -RegisterNetEvent('wasabi_fishing:sellFish', function() - local playerPed = GetPlayerPed(source) - local playerCoord = GetEntityCoords(playerPed) - local distance = #(playerCoord - Config.sellShop.coords) - if distance == nil then - KickPlayer(source, Strings.kicked) - return - end - if distance > 3 then - KickPlayer(source, Strings.kicked) - return - end - for i=1, #Config.fish do - if HasItem(source, Config.fish[i].item) > 0 then - local rewardAmount = 0 - for j=1, HasItem(source, Config.fish[i].item) do - rewardAmount = rewardAmount + math.random(Config.fish[i].price[1], Config.fish[i].price[2]) - end - if rewardAmount > 0 then - AddMoney(source, 'money', rewardAmount) - TriggerClientEvent('wasabi_fishing:notify', source, Strings.sold_for, (Strings.sold_for_desc):format(HasItem(source, Config.fish[i].item), Config.fish[i].label, addCommas(rewardAmount)), 'success') - RemoveItem(source, Config.fish[i].item, HasItem(source, Config.fish[i].item)) - end - end - end -end) - -RegisterUsableItem(Config.fishingRod.itemName, function(source) - TriggerClientEvent('wasabi_fishing:startFishing', source) -end) --- Register usable items for all fish types for processing -for _, fish in pairs(Config.processing.products) do - RegisterUsableItem(fish.sourceItem, function(source) - local hasKnife = HasItem(source, Config.processing.knifeItem) - if hasKnife > 0 then - ProcessFish(source, fish) - else - TriggerClientEvent('wasabi_fishing:notify', source, Strings.no_knife, Strings.no_knife_desc, 'error') - end - end) -end - --- Function to process fish -function ProcessFish(source, fishData) - -- Remove the fish - RemoveItem(source, fishData.sourceItem, 1) - - -- Add fish fillets - local filletYield = fishData.yield[1] - local filletAmount = math.random(filletYield.amount[1], filletYield.amount[2]) - - if Framework == 'esx' and not Config.oldESX then - local player = GetPlayer(source) - if player.canCarryItem(filletYield.item, filletAmount) then - AddItem(source, filletYield.item, filletAmount) - TriggerClientEvent('wasabi_fishing:notify', source, Strings.processing_success, - string.format(Strings.processing_success_desc, filletAmount, GetItemLabel(filletYield.item)), 'success') - else - TriggerClientEvent('wasabi_fishing:notify', source, Strings.cannot_carry, Strings.cannot_carry_desc, 'error') - -- Give back the fish if they can't carry the fillets - AddItem(source, fishData.sourceItem, 1) - return - end - else - AddItem(source, filletYield.item, filletAmount) - TriggerClientEvent('wasabi_fishing:notify', source, Strings.processing_success, - string.format(Strings.processing_success_desc, filletAmount, GetItemLabel(filletYield.item)), 'success') - end - - -- Check for caviar - for i=2, #fishData.yield do - local extraYield = fishData.yield[i] - if extraYield.item == 'caviar' and extraYield.chance then - local chance = math.random(1, 100) - if chance <= extraYield.chance then - if Framework == 'esx' and not Config.oldESX then - local player = GetPlayer(source) - if player.canCarryItem(extraYield.item, 1) then - AddItem(source, extraYield.item, 1) - TriggerClientEvent('wasabi_fishing:notify', source, Strings.caviar_found, Strings.caviar_found_desc, 'success') - end - else - AddItem(source, extraYield.item, 1) - TriggerClientEvent('wasabi_fishing:notify', source, Strings.caviar_found, Strings.caviar_found_desc, 'success') - end - end - end - end -end - --- Modify the sellFish event to include processed items -RegisterNetEvent('wasabi_fishing:sellFish', function() - local playerPed = GetPlayerPed(source) - local playerCoord = GetEntityCoords(playerPed) - local distance = #(playerCoord - Config.sellShop.coords) - if distance == nil or distance > 3 then - KickPlayer(source, Strings.kicked) - return - end - - -- Sell fish - for i=1, #Config.fish do - SellItem(source, Config.fish[i]) - end - - -- Sell processed items - for i=1, #Config.processedItems do - SellItem(source, Config.processedItems[i]) - end -end) - --- Helper function to sell items -function SellItem(source, itemData) - if HasItem(source, itemData.item) > 0 then - local rewardAmount = 0 - for j=1, HasItem(source, itemData.item) do - rewardAmount = rewardAmount + math.random(itemData.price[1], itemData.price[2]) - end - if rewardAmount > 0 then - AddMoney(source, 'money', rewardAmount) - TriggerClientEvent('wasabi_fishing:notify', source, Strings.sold_for, - (Strings.sold_for_desc):format(HasItem(source, itemData.item), itemData.label, addCommas(rewardAmount)), 'success') - RemoveItem(source, itemData.item, HasItem(source, itemData.item)) - end - end -end - --- Modify the getFishData callback to handle bait types lib.callback.register('wasabi_fishing:getFishData', function(source, baitType) - local baitData = nil - -- Find the bait data + local baitData = nil for _, bait in pairs(Config.bait.types) do if bait.itemName == baitType then baitData = bait @@ -239,3 +71,166 @@ lib.callback.register('wasabi_fishing:getFishData', function(source, baitType) -- Apply catch bonus logic here if needed return availableFish[math.random(#availableFish)] end) + +RegisterNetEvent('wasabi_fishing:rodBroke', function() + RemoveItem(source, Config.fishingRod.itemName, 1) + TriggerClientEvent('wasabi_fishing:interupt', source) +end) + +RegisterNetEvent('wasabi_fishing:loseBait', function(baitType) + RemoveItem(source, baitType, 1) +end) + +RegisterNetEvent('wasabi_fishing:tryFish', function(data) + local xPole = HasItem(source, Config.fishingRod.itemName) + local xBait = false + + -- Check if player has any type of bait + for _, bait in pairs(Config.bait.types) do + if HasItem(source, bait.itemName) > 0 then + xBait = true + break + end + end + + if xPole > 0 and xBait then + if Framework == 'esx' and not Config.oldESX then + local player = GetPlayer(source) + if player.canCarryItem(data.item, 1) then + AddItem(source, data.item, 1) + TriggerClientEvent('wasabi_fishing:notify', source, Strings.fish_success, string.format(Strings.fish_success_desc, data.label), 'success') + else + TriggerClientEvent('wasabi_fishing:notify', source, Strings.cannot_carry, Strings.cannot_carry_desc, 'error') + end + else + AddItem(source, data.item, 1) + TriggerClientEvent('wasabi_fishing:notify', source, Strings.fish_success, string.format(Strings.fish_success_desc, data.label), 'success') + end + elseif xPole > 0 and not xBait then + TriggerClientEvent('wasabi_fishing:interupt', source) + TriggerClientEvent('wasabi_fishing:notify', source, Strings.no_bait, Strings.no_bait_desc, 'error') + elseif xPole < 1 then + KickPlayer(source, Strings.kicked) + end +end) + +RegisterNetEvent('wasabi_fishing:processItem', function(fishItem) + -- Find processing data for this fish + local processData = nil + for _, data in pairs(Config.processing.products) do + if data.sourceItem == fishItem then + processData = data + break + end + end + + if not processData then + TriggerClientEvent('wasabi_fishing:notify', source, 'Cannot Process', 'This fish cannot be processed', 'error') + return + end + + -- Check if player has the fish and knife + local hasFish = HasItem(source, fishItem) + local hasKnife = HasItem(source, Config.processing.knifeItem) + + if hasFish < 1 or hasKnife < 1 then + TriggerClientEvent('wasabi_fishing:notify', source, 'Missing Items', 'You need both the fish and a knife', 'error') + return + end + + -- Remove the fish + RemoveItem(source, fishItem, 1) + + -- Add fish fillets + local filletYield = processData.yield[1] + local filletAmount = math.random(filletYield.amount[1], filletYield.amount[2]) + + if Framework == 'esx' and not Config.oldESX then + local player = GetPlayer(source) + if player.canCarryItem(filletYield.item, filletAmount) then + AddItem(source, filletYield.item, filletAmount) + TriggerClientEvent('wasabi_fishing:notify', source, 'Processing Success', + 'You obtained ' .. filletAmount .. ' fish fillets', 'success') + else + TriggerClientEvent('wasabi_fishing:notify', source, Strings.cannot_carry, Strings.cannot_carry_desc, 'error') + -- Give back the fish if they can't carry the fillets + AddItem(source, fishItem, 1) + return + end + else + AddItem(source, filletYield.item, filletAmount) + TriggerClientEvent('wasabi_fishing:notify', source, 'Processing Success', + 'You obtained ' .. filletAmount .. ' fish fillets', 'success') + end + + -- Check for caviar + for i=2, #processData.yield do + local extraYield = processData.yield[i] + if extraYield.item == 'caviar' and extraYield.chance then + local chance = math.random(1, 100) + if chance <= extraYield.chance then + if Framework == 'esx' and not Config.oldESX then + local player = GetPlayer(source) + if player.canCarryItem(extraYield.item, 1) then + AddItem(source, extraYield.item, 1) + TriggerClientEvent('wasabi_fishing:notify', source, 'Caviar Found', 'You found some valuable caviar!', 'success') + end + else + AddItem(source, extraYield.item, 1) + TriggerClientEvent('wasabi_fishing:notify', source, 'Caviar Found', 'You found some valuable caviar!', 'success') + end + end + end + end +end) + +RegisterNetEvent('wasabi_fishing:sellFish', function() + local playerPed = GetPlayerPed(source) + local playerCoord = GetEntityCoords(playerPed) + local distance = #(playerCoord - Config.sellShop.coords) + if distance == nil then + KickPlayer(source, Strings.kicked) + return + end + if distance > 3 then + KickPlayer(source, Strings.kicked) + return + end + + -- Sell fish + for i=1, #Config.fish do + SellItem(source, Config.fish[i]) + end + + -- Sell processed items + for i=1, #Config.processedItems do + SellItem(source, Config.processedItems[i]) + end +end) + +-- Helper function to sell items +function SellItem(source, itemData) + if HasItem(source, itemData.item) > 0 then + local rewardAmount = 0 + for j=1, HasItem(source, itemData.item) do + rewardAmount = rewardAmount + math.random(itemData.price[1], itemData.price[2]) + end + if rewardAmount > 0 then + AddMoney(source, 'money', rewardAmount) + TriggerClientEvent('wasabi_fishing:notify', source, Strings.sold_for, + (Strings.sold_for_desc):format(HasItem(source, itemData.item), itemData.label, addCommas(rewardAmount)), 'success') + RemoveItem(source, itemData.item, HasItem(source, itemData.item)) + end + end +end + +-- Register usable items for all fish types for processing +for _, fish in pairs(Config.fish) do + RegisterUsableItem(fish.item, function(source) + TriggerClientEvent('wasabi_fishing:processFish', source, fish.item) + end) +end + +RegisterUsableItem(Config.fishingRod.itemName, function(source) + TriggerClientEvent('wasabi_fishing:startFishing', source) +end)