--[[ Variables ]]-- -- DO NOT CHANGE -- local just_started = true local k9_name = "Default" local spawned_ped = nil local following = false local attacking = false local attacked_player = 0 local searching = false local playing_animation = false local animations = { ['Normal'] = { sit = { dict = "creatures@rottweiler@amb@world_dog_sitting@idle_a", anim = "idle_b" }, laydown = { dict = "creatures@rottweiler@amb@sleep_in_kennel@", anim = "sleep_in_kennel" }, searchhit = { dict = "creatures@rottweiler@indication@", anim = "indicate_high" } } } --]] --[[ Tables ]]-- local language = {} --]] --[[ NUI Messages ]]-- -- Open Menu -- function EnableMenu() SetNuiFocus(true, true) SendNUIMessage({ type = "open_k9_menu" }) end --]] --[[ NUI Callbacks ]]-- RegisterNUICallback("closemenu", function(data) SetNuiFocus(false, false) end) RegisterNUICallback("updatename", function(data) k9_name = data.name end) RegisterNUICallback("spawnk9", function(data) TriggerEvent("K9:ToggleK9", data.model) end) RegisterNUICallback("vehicletoggle", function(data) if spawned_ped ~= nil then TriggerServerEvent("K9:RequestVehicleToggle") end end) RegisterNUICallback("vehiclesearch", function(data) if spawned_ped ~= nil then TriggerServerEvent("K9:RequestItems") end end) RegisterNUICallback("sit", function(data) if spawned_ped ~= nil then PlayAnimation(animations['Normal'].sit.dict, animations['Normal'].sit.anim) end end) RegisterNUICallback("laydown", function(data) if spawned_ped ~= nil then PlayAnimation(animations['Normal'].laydown.dict, animations['Normal'].laydown.anim) end end) --]] --[[ Main Event Handlers ]]-- -- Updates Language Settings RegisterNetEvent("K9:UpdateLanguage") AddEventHandler("K9:UpdateLanguage", function(commands) language = commands Citizen.Trace(tostring(json.encode(language))) end) -- Opens K9 Menu RegisterNetEvent("K9:OpenMenu") AddEventHandler("K9:OpenMenu", function(pedRestriction, pedList) if pedRestriction then if CheckPedRestriction(GetLocalPed(), pedList) then EnableMenu() else Notification(tostring("~r~You do not have the right PED to use the K9.")) end else EnableMenu() end end) -- Error for Identifier Whitelist RegisterNetEvent("K9:IdentifierRestricted") AddEventHandler("K9:IdentifierRestricted", function() Notification(tostring("~r~You do not match any identifiers in the whitelist.")) end) -- Spawns and Deletes K9 RegisterNetEvent("K9:ToggleK9") AddEventHandler("K9:ToggleK9", function(model) if spawned_ped == nil then local ped = GetHashKey(model) RequestModel(ped) while not HasModelLoaded(ped) do Citizen.Wait(1) RequestModel(ped) end local plyCoords = GetOffsetFromEntityInWorldCoords(GetLocalPed(), 0.0, 2.0, 0.0) local dog = CreatePed(28, ped, plyCoords.x, plyCoords.y, plyCoords.z, GetEntityHeading(GetLocalPed()), 0, 1) spawned_ped = dog SetBlockingOfNonTemporaryEvents(spawned_ped, true) SetPedFleeAttributes(spawned_ped, 0, 0) SetPedRelationshipGroupHash(spawned_ped, GetHashKey("k9")) local blip = AddBlipForEntity(spawned_ped) SetBlipAsFriendly(blip, true) SetBlipSprite(blip, 442) BeginTextCommandSetBlipName("STRING") AddTextComponentString(tostring("K9: ".. k9_name)) EndTextCommandSetBlipName(blip) NetworkRegisterEntityAsNetworked(spawned_ped) GiveWeaponToPed(spawned_ped, GetHashKey("WEAPON_ANIMAL"), 200, true, true); while not NetworkGetEntityIsNetworked(spawned_ped) do NetworkRegisterEntityAsNetworked(spawned_ped) Citizen.Wait(1) end else local has_control = false RequestNetworkControl(function(cb) has_control = cb end) if has_control then SetEntityAsMissionEntity(spawned_ped, true, true) DeleteEntity(spawned_ped) spawned_ped = nil if attacking then SetPedRelationshipGroupDefaultHash(target_ped, GetHashKey("CIVMALE")) target_ped = nil attacking = false end following = false searching = false playing_animation = false end end end) -- Toggles K9 to Follow / Heel RegisterNetEvent("K9:ToggleFollow") AddEventHandler("K9:ToggleFollow", function() if spawned_ped ~= nil then if not following then local has_control = false RequestNetworkControl(function(cb) has_control = cb end) if has_control then TaskFollowToOffsetOfEntity(spawned_ped, GetLocalPed(), 0.5, 0.0, 0.0, 5.0, -1, 0.0, 1) SetPedKeepTask(spawned_ped, true) following = true attacking = false Notification(tostring(k9_name .. " " .. language.follow)) end else local has_control = false RequestNetworkControl(function(cb) has_control = cb end) if has_control then SetPedKeepTask(spawned_ped, false) ClearPedTasks(spawned_ped) following = false attacking = false Notification(tostring(k9_name .. " " .. language.stop)) end end end end) -- Toggles K9 In and Out of Vehicles RegisterNetEvent("K9:ToggleVehicle") AddEventHandler("K9:ToggleVehicle", function(isRestricted, vehList) if not searching then if IsPedInAnyVehicle(spawned_ped, false) then SetEntityInvincible(spawned_ped, true) SetPedCanRagdoll(spawned_ped, false) TaskLeaveVehicle(spawned_ped, GetVehiclePedIsIn(spawned_ped, false), 256) Notification(tostring(k9_name .. " " .. language.exit)) Wait(2000) SetPedCanRagdoll(spawned_ped, true) SetEntityInvincible(spawned_ped, false) else if not IsPedInAnyVehicle(GetLocalPed(), false) then local plyCoords = GetEntityCoords(GetLocalPed(), false) local vehicle = GetVehicleAheadOfPlayer() local door = GetClosestVehicleDoor(vehicle) if door ~= false then if isRestricted then if CheckVehicleRestriction(vehicle, vehList) then TaskEnterVehicle(spawned_ped, vehicle, -1, door, 2.0, 1, 0) Notification(tostring(k9_name .. " " .. language.enter)) end else TaskEnterVehicle(spawned_ped, vehicle, -1, door, 2.0, 1, 0) Notification(tostring(k9_name .. " " .. language.enter)) end end else local vehicle = GetVehiclePedIsIn(GetLocalPed(), false) local door = 1 if isRestricted then if CheckVehicleRestriction(vehicle, vehList) then TaskEnterVehicle(spawned_ped, vehicle, -1, door, 2.0, 1, 0) Notification(tostring(k9_name .. " " .. language.enter)) end else TaskEnterVehicle(spawned_ped, vehicle, -1, door, 2.0, 1, 0) Notification(tostring(k9_name .. " " .. language.enter)) end end end end end) -- Triggers K9 to Attack RegisterNetEvent("K9:ToggleAttack") AddEventHandler("K9:ToggleAttack", function(target) if not attacking and not searching then if IsPedAPlayer(target) then local has_control = false RequestNetworkControl(function(cb) has_control = cb end) if has_control then local player = GetPlayerFromServerId(GetPlayerId(target)) SetCanAttackFriendly(spawned_ped, true, true) TaskPutPedDirectlyIntoMelee(spawned_ped, target, 0.0, -1.0, 0.0, 0) attacked_player = player end else local has_control = false RequestNetworkControl(function(cb) has_control = cb end) if has_control then SetCanAttackFriendly(spawned_ped, true, true) TaskPutPedDirectlyIntoMelee(spawned_ped, target, 0.0, -1.0, 0.0, 0) attacked_player = 0 end end attacking = true following = false Notification(tostring(k9_name .. " " .. language.attack)) end end) -- Triggers K9 to Search Vehicle RegisterNetEvent("K9:SearchVehicle") AddEventHandler("K9:SearchVehicle", function(items, openDoors) local vehicle = GetVehicleAheadOfPlayer() Citizen.Trace(tostring(vehicle)) Citizen.Trace(tostring(json.encode(items))) if vehicle ~= 0 and not searching then searching = true local found_table = {} Notification(tostring(k9_name .. " has began searching...")) if openDoors then SetVehicleDoorOpen(vehicle, 0, 0, 0) SetVehicleDoorOpen(vehicle, 1, 0, 0) SetVehicleDoorOpen(vehicle, 2, 0, 0) SetVehicleDoorOpen(vehicle, 3, 0, 0) SetVehicleDoorOpen(vehicle, 4, 0, 0) SetVehicleDoorOpen(vehicle, 5, 0, 0) SetVehicleDoorOpen(vehicle, 6, 0, 0) SetVehicleDoorOpen(vehicle, 7, 0, 0) end -- Back Right local offsetOne = GetOffsetFromEntityInWorldCoords(vehicle, 2.0, -2.0, 0.0) TaskGoToCoordAnyMeans(spawned_ped, offsetOne.x, offsetOne.y, offsetOne.z, 5.0, 0, 0, 1, 10.0) local oneItem = ChooseItem(items) if oneItem ~= false then table.insert(found_table, oneItem) end Citizen.Wait(7000) -- Front Right local offsetTwo = GetOffsetFromEntityInWorldCoords(vehicle, 2.0, 2.0, 0.0) TaskGoToCoordAnyMeans(spawned_ped, offsetTwo.x, offsetTwo.y, offsetTwo.z, 5.0, 0, 0, 1, 10.0) local twoItem = ChooseItem(items) if twoItem ~= false then table.insert(found_table, twoItem) end Citizen.Wait(7000) -- Front Left local offsetThree = GetOffsetFromEntityInWorldCoords(vehicle, -2.0, 2.0, 0.0) TaskGoToCoordAnyMeans(spawned_ped, offsetThree.x, offsetThree.y, offsetThree.z, 5.0, 0, 0, 1, 10.0) local threeItem = ChooseItem(items) if threeItem ~= false then table.insert(found_table, threeItem) end Citizen.Wait(7000) -- Front Right local offsetFour = GetOffsetFromEntityInWorldCoords(vehicle, -2.0, -2.0, 0.0) TaskGoToCoordAnyMeans(spawned_ped, offsetFour.x, offsetFour.y, offsetFour.z, 5.0, 0, 0, 1, 10.0) local fourItem = ChooseItem(items) if fourItem ~= false then table.insert(found_table, fourItem) end Citizen.Wait(7000) if openDoors then SetVehicleDoorsShut(vehicle, 0) end local stringified_table = {} local found_illegal_item = false for a = 1, #found_table do table.insert(stringified_table, found_table[a].item) if found_table[a].illegal then found_illegal_item = true end end if found_illegal_item then PlayAnimation(animations['Normal'].searchhit.dict, animations['Normal'].searchhit.anim) Citizen.Wait(3000) PlayAnimation(animations['Normal'].sit.dict, animations['Normal'].sit.anim) end Notification(tostring(k9_name .. " has found [ " .. tostring(table.concat(stringified_table, ", ")) .. " ].")) searching = false end end) --]] --[[ Threads ]] -- Controls Menu Citizen.CreateThread(function() while true do Citizen.Wait(0) -- Trigger Attack if IsControlJustPressed(1, 288) and IsPlayerFreeAiming(PlayerId()) then local bool, target = GetEntityPlayerIsFreeAimingAt(PlayerId()) if bool then if IsEntityAPed(target) then TriggerEvent("K9:ToggleAttack", target) end end end -- Trigger Follow if IsControlJustPressed(1, 288) and not IsPlayerFreeAiming(PlayerId()) then TriggerEvent("K9:ToggleFollow") end if IsControlJustPressed(1, 178) then if spawned_ped ~= nil then TriggerServerEvent("K9:RequestVehicleToggle") end end end end) -- DO NOT TOUCH (CLEANER) Citizen.CreateThread(function() while true do Citizen.Wait(0) -- Setting K9 Settings if just_started then Citizen.Wait(1000) local resource = GetCurrentResourceName() SendNUIMessage({ type = "update_resource_name", name = resource }) just_started = false TriggerServerEvent("K9:SendLanguage") end -- Deletes K9 when you die if spawned_ped ~= nil and IsEntityDead(GetLocalPed()) then TriggerEvent("K9:ToggleK9") end end end) --]] --[[ EXTRA FUNCTIONS ]]-- -- Gets Local Ped function GetLocalPed() return GetPlayerPed(PlayerId()) end -- Gets Control Of Ped function RequestNetworkControl(callback) local netId = NetworkGetNetworkIdFromEntity(spawned_ped) local timer = 0 NetworkRequestControlOfNetworkId(netId) while not NetworkHasControlOfNetworkId(netId) do Citizen.Wait(1) NetworkRequestControlOfNetworkId(netId) timer = timer + 1 if timer == 5000 then Citizen.Trace("Control failed") callback(false) break end end callback(true) end -- Gets Players function GetPlayers() local players = {} for i = 0, 32 do if NetworkIsPlayerActive(i) then table.insert(players, i) end end return players end -- Get Searching item function ChooseItem(items) local number = math.random(1, 100) if number > 70 and number < 95 then -- 70 | 95 local randomItem = math.random(1, #items) return items[randomItem] else return false end end -- Set K9 Animation (Sit / Laydown) function PlayAnimation(dict, anim) RequestAnimDict(dict) while not HasAnimDictLoaded(dict) do Citizen.Wait(0) end TaskPlayAnim(spawned_ped, dict, anim, 8.0, -8.0, -1, 2, 0.0, 0, 0, 0) end -- Gets Player ID function GetPlayerId(target_ped) local players = GetPlayers() for a = 1, #players do local ped = GetPlayerPed(players[a]) local server_id = GetPlayerServerId(players[a]) if target_ped == ped then return server_id end end return 0 end -- Checks Ped Restriction function CheckPedRestriction(ped, PedList) for i = 1, #PedList do if GetHashKey(PedList[i]) == GetEntityModel(ped) then return true end end return false end -- Checks Vehicle Restriction function CheckVehicleRestriction(vehicle, VehicleList) for i = 1, #VehicleList do if GetHashKey(VehicleList[i]) == GetEntityModel(vehicle) then return true end end return false end -- Gets Vehicle Ahead Of Player function GetVehicleAheadOfPlayer() local lPed = GetLocalPed() local lPedCoords = GetEntityCoords(lPed, alive) local lPedOffset = GetOffsetFromEntityInWorldCoords(lPed, 0.0, 3.0, 0.0) local rayHandle = StartShapeTestCapsule(lPedCoords.x, lPedCoords.y, lPedCoords.z, lPedOffset.x, lPedOffset.y, lPedOffset.z, 1.2, 10, lPed, 7) local returnValue, hit, endcoords, surface, vehicle = GetShapeTestResult(rayHandle) if hit then return vehicle else return false end end RegisterCommand('k9', function(source, args) TriggerServerEvent("K9:RequestOpenMenu") end, false) -- Gets Closest Door To Player function GetClosestVehicleDoor(vehicle) local plyCoords = GetEntityCoords(GetLocalPed(), false) local backleft = GetWorldPositionOfEntityBone(vehicle, GetEntityBoneIndexByName(vehicle, "door_dside_r")) local backright = GetWorldPositionOfEntityBone(vehicle, GetEntityBoneIndexByName(vehicle, "door_pside_r")) local bldistance = GetDistanceBetweenCoords(backleft['x'], backleft['y'], backleft['z'], plyCoords.x, plyCoords.y, plyCoords.z, 1) local brdistance = GetDistanceBetweenCoords(backright['x'], backright['y'], backright['z'], plyCoords.x, plyCoords.y, plyCoords.z, 1) local found_door = false if (bldistance < brdistance) then found_door = 1 elseif(brdistance < bldistance) then found_door = 2 end return found_door end -- Displays Notification function Notification(message) SetNotificationTextEntry("STRING") AddTextComponentString(message) DrawNotification(0, 1) end --]]