Main/resources/[jobs]/[civ]/wasabi_fishing/client/client.lua
2025-07-01 12:59:20 +02:00

298 lines
11 KiB
Lua

-----------------For support, scripts, and more----------------
--------------- https://discord.gg/wasabiscripts -------------
---------------------------------------------------------------
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)
local point = lib.points.new({
coords = Config.sellShop.coords,
distance = 30
})
function point:nearby()
if self.currentDistance < self.distance then
if not ped then
lib.requestAnimDict('mini@strip_club@idles@bouncer@base', 100)
lib.requestModel(Config.sellShop.ped, 100)
ped = CreatePed(28, Config.sellShop.ped, Config.sellShop.coords.x, Config.sellShop.coords.y, Config.sellShop.coords.z, Config.sellShop.heading, false, false)
FreezeEntityPosition(ped, true)
SetEntityInvincible(ped, true)
SetBlockingOfNonTemporaryEvents(ped, true)
TaskPlayAnim(ped, 'mini@strip_club@idles@bouncer@base', 'base', 8.0, 0.0, -1, 1, 0, 0, 0, 0)
end
if self.currentDistance <= 1.8 then
if not textUI then
lib.showTextUI(Strings.sell_fish)
textUI = true
end
if IsControlJustReleased(0, 38) then
FishingSellItems()
end
elseif self.currentDistance >= 1.9 and textUI then
lib.hideTextUI()
textUI = nil
end
end
end
function point:onExit()
if ped then
local model = GetEntityModel(ped)
SetModelAsNoLongerNeeded(model)
DeletePed(ped)
SetPedAsNoLongerNeeded(ped)
RemoveAnimDict('mini@strip_club@idles@bouncer@base')
ped = nil
end
end
end)
end
-- Function to select bait using ox_lib menu
local function SelectBait()
local availableBaits = {}
-- Check all bait types
for _, bait in pairs(Config.bait.types) do
local hasItem = lib.callback.await('wasabi_fishing:checkItem', 100, bait.itemName)
if hasItem then
table.insert(availableBaits, bait)
end
end
if #availableBaits == 0 then
return nil
end
-- If only one bait type is available, use it directly
if #availableBaits == 1 then
return availableBaits[1]
end
-- Create menu options for bait selection
local options = {}
for i, bait in ipairs(availableBaits) do
table.insert(options, {
title = bait.label,
description = 'Catch Bonus: +' .. bait.catchBonus .. '% | Loss Chance: ' .. bait.loseChance .. '%',
icon = 'fish',
onSelect = function()
-- This will be handled by the menu's onClose callback
end
})
end
-- Create a variable to store the selected bait
local selectedIndex = 1
-- Register the menu
lib.registerMenu({
id = 'bait_selection_menu',
title = 'Select Fishing Bait',
position = 'top-right',
options = options,
onClose = function(selected)
selectedIndex = selected or 1
end
})
-- Show the menu
lib.showMenu('bait_selection_menu')
-- Wait for menu to close
while lib.getOpenMenu() == 'bait_selection_menu' do
Wait(100)
end
-- Return the selected bait
return availableBaits[selectedIndex]
end
-- Function to handle the fishing process
local function StartFishingProcess(selectedBait, waterLoc)
fishing = true
-- Create fishing rod prop
local model = `prop_fishing_rod_01`
lib.requestModel(model, 100)
local pole = CreateObject(model, GetEntityCoords(cache.ped), true, false, false)
AttachEntityToEntity(pole, cache.ped, GetPedBoneIndex(cache.ped, 18905), 0.1, 0.05, 0, 80.0, 120.0, 160.0, true, true, false, true, 1, true)
SetModelAsNoLongerNeeded(model)
-- Load animations
lib.requestAnimDict('mini@tennis', 100)
lib.requestAnimDict('amb@world_human_stand_fishing@idle_a', 100)
-- Initial casting animation
TaskPlayAnim(cache.ped, 'mini@tennis', 'forehand_ts_md_far', 1.0, -1.0, 1.0, 48, 0, 0, 0, 0)
Wait(3000)
TaskPlayAnim(cache.ped, 'amb@world_human_stand_fishing@idle_a', 'idle_c', 1.0, -1.0, 1.0, 11, 0, 0, 0, 0)
-- Main fishing loop
while fishing do
Wait(0)
local unarmed = `WEAPON_UNARMED`
SetCurrentPedWeapon(cache.ped, unarmed)
ShowHelp(Strings.intro_instruction)
DisableControlAction(0, 24, true)
-- Cast line
if IsDisabledControlJustReleased(0, 24) then
-- Casting animation
TaskPlayAnim(cache.ped, 'mini@tennis', 'forehand_ts_md_far', 1.0, -1.0, 1.0, 48, 0, 0, 0, 0)
TriggerEvent('wasabi_fishing:notify', Strings.waiting_bite, Strings.waiting_bite_desc, 'inform')
-- Wait for fish to bite
local waitTime = math.random(Config.timeForBite.min, Config.timeForBite.max)
Wait(waitTime)
-- Check if player is still fishing
if not fishing then
break
end
TriggerEvent('wasabi_fishing:notify', Strings.got_bite, Strings.got_bite_desc, 'inform')
Wait(1000)
-- Get fish data based on selected bait
local fishData = lib.callback.await('wasabi_fishing:getFishData', 100, selectedBait.itemName)
-- Skill check to catch fish
if lib.skillCheck(fishData.difficulty) then
ClearPedTasks(cache.ped)
TryFish(fishData)
TaskPlayAnim(cache.ped, 'amb@world_human_stand_fishing@idle_a', 'idle_c', 1.0, -1.0, 1.0, 11, 0, 0, 0, 0)
-- Check for bait loss
local loseChance = math.random(1,100)
if loseChance <= selectedBait.loseChance then
TriggerServerEvent('wasabi_fishing:loseBait', selectedBait.itemName)
TriggerEvent('wasabi_fishing:notify', Strings.bait_lost, Strings.bait_lost_desc, 'error')
-- Check if we still have this bait
local hasBait = lib.callback.await('wasabi_fishing:checkItem', 100, selectedBait.itemName)
if not hasBait then
-- Try to select a new bait
local newBait = SelectBait()
if newBait then
selectedBait = newBait
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
break
end
end
end
else
-- Failed to catch fish
local breakChance = math.random(1,100)
if breakChance < Config.fishingRod.breakChance then
TriggerServerEvent('wasabi_fishing:rodBroke')
TriggerEvent('wasabi_fishing:notify', Strings.rod_broke, Strings.rod_broke_desc, 'error')
ClearPedTasks(cache.ped)
fishing = false
break
end
TriggerEvent('wasabi_fishing:notify', Strings.failed_fish, Strings.failed_fish_desc, 'error')
end
elseif IsControlJustReleased(0, 194) then
-- Cancel fishing with backspace
ClearPedTasks(cache.ped)
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', 'Too Far', 'You moved too far from the water', 'error')
break
end
end
-- Clean up
fishing = false
DeleteObject(pole)
RemoveAnimDict('mini@tennis')
RemoveAnimDict('amb@world_human_stand_fishing@idle_a')
end
RegisterNetEvent('wasabi_fishing:startFishing', function()
-- Check if player is in a valid state to fish
if IsPedInAnyVehicle(cache.ped) or IsPedSwimming(cache.ped) then
TriggerEvent('wasabi_fishing:notify', Strings.cannot_perform, Strings.cannot_perform_desc, 'error')
return
end
-- Check if already fishing
if fishing then
TriggerEvent('wasabi_fishing:notify', 'Already Fishing', 'You are already fishing', 'error')
return
end
-- Check for water
local water, waterLoc = WaterCheck()
if not water then
TriggerEvent('wasabi_fishing:notify', Strings.no_water, Strings.no_water_desc, 'error')
return
end
-- Select bait
local selectedBait = SelectBait()
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', 'Bait Selected', 'Using ' .. selectedBait.label .. ' as bait', 'inform')
StartFishingProcess(selectedBait, waterLoc)
end)
-- Process fish with knife
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', 'No Knife', 'You need a knife to process fish', 'error')
return
end
-- Start processing animation
local playerPed = cache.ped
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)
-- Processing progress bar
if lib.progressBar({
duration = 5000,
label = 'Processing Fish',
useWhileDead = false,
canCancel = true,
disable = {
car = true,
move = true,
combat = true
},
anim = {
dict = 'anim@amb@business@coc@coc_unpack_cut@',
clip = 'fullcut_cycle_v6_cokecutter'
},
}) then
-- Success - server handles the actual item processing
TriggerServerEvent('wasabi_fishing:processItem', fishItem)
else
-- Cancelled
TriggerEvent('wasabi_fishing:notify', 'Canceled', 'Fish processing canceled', 'error')
end
ClearPedTasks(playerPed)
RemoveAnimDict('anim@amb@business@coc@coc_unpack_cut@')
end)
RegisterNetEvent('wasabi_fishing:interupt', function()
fishing = false
ClearPedTasks(cache.ped)
end)