-----------------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)