Files
2025-01-24 14:59:44 -08:00

504 lines
17 KiB
Lua

-- CONFIG --
local config_select = true -- true = select the target, false = auto target the player in front
-- END OF CONFIG --
local dogBreeds = { 'Rottweiler', 'Husky', 'Retriever', 'Shepherd' }
local dogBHash = { 'a_c_rottweiler', 'a_c_husky', 'a_c_retriever', 'a_c_shepherd' }
local k9 = nil
local k9Name = nil
local blipk9 = nil
local selectedDogIndex = 1
local currentDogIndex = 1
local open = false
local main = RageUI.CreateMenu("K9 Manager", "Actions")
main.Closed = function()
open = false
end
function openK9Menu()
if open then
open = false
RageUI.Visible(main, false)
return
else
open = true
RageUI.Visible(main, true)
Citizen.CreateThread(function()
while open do
RageUI.IsVisible(main, function()
if k9 == nil then
-- create a button to rename the dog
RageUI.Button("Dog's name", nil, { RightLabel = k9Name }, true, {
onSelected = function()
local result = KeyboardInput("Dog's name")
if result ~= nil then
k9Name = result
end
end,
})
-- create a button to select the dog breed
RageUI.List("Dog breed", dogBreeds, selectedDogIndex, nil, {}, true, {
onListChange = function(Index)
selectedDogIndex = Index
currentDogIndex = Index
end,
})
RageUI.Button("Spawn the dog", nil, { RightLabel = "→" }, true, {
onSelected = function()
if k9Name == nil then
ShowNotification("You have to name your dog first!")
else
-- Spawning
RequestModel(GetHashKey(dogBHash[currentDogIndex]))
while not HasModelLoaded(GetHashKey(dogBHash[currentDogIndex])) do
Citizen.Wait(1)
end
local pos = GetOffsetFromEntityInWorldCoords(PlayerPedId(), 0.0, 2.0, 0.0)
local heading = GetEntityHeading(GetPlayerPed(-1))
local _, groundZ = GetGroundZFor_3dCoord(pos.x, pos.y, pos.z, false);
k9 = CreatePed(28, GetHashKey(dogBHash[currentDogIndex]), pos.x, pos.y, groundZ + 1, heading, true, true)
GiveWeaponToPed(k9, GetHashKey('WEAPON_ANIMAL'), true, true)
TaskSetBlockingOfNonTemporaryEvents(k9, true)
SetPedFleeAttributes(k9, 0, false)
SetPedCombatAttributes(k9, 3, true)
SetPedCombatAttributes(k9, 5, true)
SetPedCombatAttributes(k9, 46, true)
-- make it not attack the owner in any condition
SetPedAsGroupLeader(k9, GetPedGroupIndex(PlayerPedId()))
SetPedAsGroupMember(k9, GetPedGroupIndex(PlayerPedId()))
SetPedNeverLeavesGroup(k9, true)
blipk9 = AddBlipForEntity(k9)
SetBlipAsFriendly(blipk9, true)
SetBlipDisplay(blipk9, 2)
SetBlipShowCone(blipk9, true)
SetBlipAsShortRange(blipk9, false)
BeginTextCommandSetBlipName("STRING")
AddTextComponentString(k9Name)
EndTextCommandSetBlipName(blipk9)
Command_Follow(k9)
end
end,
})
else
if IsPedDeadOrDying(k9, true) then
ShowNotification(k9Name .. " was killed!")
k9 = nil
k9Name = nil
RemoveBlip(blipk9)
blipk9 = nil
end
RageUI.Button("Sit", nil, { RightLabel = "→" }, true, {
onSelected = function()
Command_Sit(k9)
end,
})
RageUI.Button("Follow / Call", nil, { RightLabel = "→" }, true, {
onSelected = function()
Command_Follow(k9)
end,
})
RageUI.Button("Don't move", nil, { RightLabel = "→" }, true, {
onSelected = function()
Command_Stay(k9)
end,
})
RageUI.Button("Bark", nil, { RightLabel = "→" }, true, {
onSelected = function()
Command_Bark(k9)
end,
})
RageUI.Button("Lay down", nil, { RightLabel = "→" }, true, {
onSelected = function()
Command_Lay(k9)
end,
})
RageUI.Button("Beg", nil, { RightLabel = "→" }, true, {
onSelected = function()
Command_beg(k9)
end,
})
RageUI.Button("Give paw", nil, { RightLabel = "→" }, true, {
onSelected = function()
Command_paw(k9)
end,
})
RageUI.Button("Attack", nil, { RightLabel = "→" }, true, {
onSelected = function()
if isAttacking then
isAttacking = false
ClearPedTasksImmediately(k9)
else
if config_select then
select_and_attackK9(k9)
else
attackK9(k9)
end
end
end,
})
RageUI.Button("Enter the car", nil, { RightLabel = "→" }, true, {
onSelected = function()
EnterVehicle(k9)
end,
})
RageUI.Button("Exit the car", nil, { RightLabel = "→" }, true, {
onSelected = function()
ExitVehicle(k9)
end,
})
RageUI.Button("Dismiss the dog", nil, { RightLabel = "→" }, true, {
onSelected = function()
DismissDog(k9)
end,
})
end
end)
Wait(1)
end
end)
end
end
Keys.Register('K', 'K', 'Menu K9', function()
openK9Menu()
end)
local isAttacking = false
function attackK9(ped)
DetachEntity(ped)
if IsPlayerFreeAiming(PlayerId()) then
local _, target = GetEntityPlayerIsFreeAimingAt(PlayerId())
ClearPedTasks(ped)
if IsEntityAPed(target) and target ~= PlayerPedId() then
isAttacking = true
TaskCombatPed(ped, target, 0, 16)
CreateThread(function()
while isAttacking and not IsPedDeadOrDying(target, true) do
SetPedMoveRateOverride(ped, 1.25)
Citizen.Wait(0)
end
end)
end
else
local target = GetPedInFront()
ClearPedTasks(ped)
if IsEntityAPed(target) and target ~= PlayerPedId() then
isAttacking = true
TaskCombatPed(ped, target, 0, 16)
CreateThread(function()
while isAttacking and not IsPedDeadOrDying(target, true) do
SetPedMoveRateOverride(ped, 1.25)
Citizen.Wait(0)
end
end)
end
end
end
function select_and_attackK9(ped)
DetachEntity(ped)
local target = nil
local player = GetAllPlayersInArea(GetEntityCoords(ped), 5.0)
for k, v in pairs(player) do
if v == PlayerId() then
table.remove(player, k)
end
end
if player ~= nil then
if next(player) then
inChoice = true
StartChoicePlayerK9(player)
if selectedPlayer ~= nil then
target = GetPlayerPed(selectedPlayer)
end
end
else
ShowNotification("No player nearby")
end
if target == nil then
ShowNotification("No player selected")
return
end
ClearPedTasks(ped)
if IsEntityAPed(target) and target ~= PlayerPedId() then
isAttacking = true
TaskCombatPed(ped, target, 0, 16)
CreateThread(function()
while isAttacking and not IsPedDeadOrDying(target, true) do
SetPedMoveRateOverride(ped, 1.25)
Citizen.Wait(0)
end
end)
end
end
function Command_Sit(ped)
ClearPedTasks(ped)
RequestAnimDict("creatures@rottweiler@amb@world_dog_sitting@idle_a")
while not HasAnimDictLoaded("creatures@rottweiler@amb@world_dog_sitting@idle_a") do
Citizen.Wait(1)
end
TaskPlayAnim(ped, "creatures@rottweiler@amb@world_dog_sitting@idle_a", "idle_b", 8.0, -4.0, -1, 1, 0.0)
end
function Command_Stay(ped)
ClearPedTasks(ped)
RequestAnimDict("amb@lo_res_idles@")
while not HasAnimDictLoaded("amb@lo_res_idles@") do
Citizen.Wait(1)
end
TaskPlayAnim(ped, "amb@lo_res_idles@", "creatures_world_rottweiler_standing_lo_res_base", 8.0, -4.0, -1, 1, 0.0)
end
function Command_paw(ped)
ClearPedTasks(ped)
RequestAnimDict("creatures@rottweiler@tricks@")
while not HasAnimDictLoaded("creatures@rottweiler@tricks@") do
Citizen.Wait(1)
end
TaskPlayAnim(ped, "creatures@rottweiler@tricks@", "paw_right_loop", 8.0, -4.0, -1, 1, 0.0)
end
function Command_beg(ped)
ClearPedTasks(ped)
RequestAnimDict("creatures@rottweiler@tricks@")
while not HasAnimDictLoaded("creatures@rottweiler@tricks@") do
Citizen.Wait(1)
end
TaskPlayAnim(ped, "creatures@rottweiler@tricks@", "beg_loop", 8.0, -4.0, -1, 1, 0.0)
end
function Command_Follow(ped)
ClearPedTasks(ped)
DetachEntity(ped)
TaskFollowToOffsetOfEntity(ped, GetPlayerPed(-1), 0.5, 0.0, 0.0, 7.0, -1, 0.2, true)
end
function Command_Bark(ped)
ClearPedTasks(ped)
RequestAnimDict("creatures@rottweiler@amb@world_dog_barking@idle_a")
while not HasAnimDictLoaded("creatures@rottweiler@amb@world_dog_barking@idle_a") do
Citizen.Wait(1)
end
TaskPlayAnim(ped, "creatures@rottweiler@amb@world_dog_barking@idle_a", "idle_a", 8.0, -4.0, -1, 1, 0.0)
end
function Command_Lay(ped)
ClearPedTasks(ped)
RequestAnimDict("creatures@rottweiler@amb@sleep_in_kennel@")
while not HasAnimDictLoaded("creatures@rottweiler@amb@sleep_in_kennel@") do
Citizen.Wait(1)
end
TaskPlayAnim(ped, "creatures@rottweiler@amb@sleep_in_kennel@", "sleep_in_kennel", 8.0, -4.0, -1, 1, 0.0)
end
function Command_StartTrack(dog, player)
local target = GetPlayerPed(GetPlayerFromServerId(tonumber(player)))
TaskFollowToOffsetOfEntity(dog, target, 0.5, 0.0, 0.0, 6.0, -1, 0.2, true)
end
function EnterVehicle(ped)
if IsPedInAnyVehicle(PlayerPedId(), false) then
ClearPedTasks(ped)
local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
local vehHeading = GetEntityHeading(vehicle)
TaskGoToEntity(ped, vehicle, -1, 0.5, 100, 1073741824, 0)
TaskAchieveHeading(ped, vehHeading, -1)
RequestAnimDict("creatures@rottweiler@in_vehicle@van")
RequestAnimDict("creatures@rottweiler@amb@world_dog_sitting@base")
while not HasAnimDictLoaded("creatures@rottweiler@in_vehicle@van") or
not HasAnimDictLoaded("creatures@rottweiler@amb@world_dog_sitting@base") do
Citizen.Wait(1)
end
TaskPlayAnim(ped, "creatures@rottweiler@in_vehicle@van", "get_in", 8.0, -4.0, -1, 2, 0.0)
Citizen.Wait(700)
ClearPedTasks(ped)
AttachEntityToEntity(ped, vehicle, GetEntityBoneIndexByName(vehicle, "seat_pside_r"), 0.0, 0.0, 0.25)
TaskPlayAnim(ped, "creatures@rottweiler@amb@world_dog_sitting@base", "base", 8.0, -4.0, -1, 2, 0.0)
else
ShowNotification("You have to be in a vehicle to do that!")
end
end
function ExitVehicle(ped)
local vehicle = GetEntityAttachedTo(ped)
local vehPos = GetEntityCoords(vehicle)
local forwardX = GetEntityForwardVector(vehicle).x * 3.7
local forwardY = GetEntityForwardVector(vehicle).y * 3.7
local _, groundZ = GetGroundZFor_3dCoord(vehPos.x, vehPos.y, vehPos.z, 0)
ClearPedTasks(ped)
DetachEntity(ped)
SetEntityCoords(ped, vehPos.x - forwardX, vehPos.y - forwardY, groundZ)
Command_Follow(ped)
end
function DismissDog(ped)
ClearPedTasks(ped)
DeletePed(ped)
blipk9 = nil
k9 = nil
k9Name = nil
RemoveBlip(blipk9)
end
function GetPedInFront()
local player = PlayerId()
local plyPed = GetPlayerPed(player)
local plyPos = GetEntityCoords(plyPed, false)
local plyOffset = GetOffsetFromEntityInWorldCoords(plyPed, 0.0, 5.0, 0.0)
local rayHandle = StartShapeTestCapsule(plyPos.x, plyPos.y, plyPos.z, plyOffset.x, plyOffset.y, plyOffset.z, 1.0, 12
, plyPed, 7)
local _, _, _, _, ped = GetShapeTestResult(rayHandle)
return ped
end
function StartChoicePlayerK9(players)
selectedPlayer = nil
ShowNotification("Press ~g~E~s~ to confirm\nPress ~b~L~s~ to change target\nPress ~r~X~s~ to cancel")
local timer = GetGameTimer() + 10000
while inChoice do
if next(players) then
local mCoors = GetEntityCoords(GetPlayerPed(players[1]))
DrawMarker(20, mCoors.x, mCoors.y, mCoors.z + 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.3, 0.3, 0.3, 255, 255,
255, 120, 0, 1, 2, 0, nil, nil, 0)
if GetGameTimer() > timer then
ShowNotification("~r~Timeout was reached")
inChoice = false
return
elseif IsControlJustPressed(0, 51) then -- E
selectedPlayer = players[1]
inChoice = false
return
elseif IsControlJustPressed(0, 182) then -- L
table.remove(players, 1)
if next(players) then
timer = GetGameTimer() + 10000
end
elseif IsControlJustPressed(0, 73) then -- X
ShowNotification("~r~You canceled the choice")
selectedPlayer = nil
inChoice = false
return
end
else
ShowNotification("~r~No players found")
selectedPlayer = nil
inChoice = false
return
end
Wait(0)
end
end
function KeyboardInput(text)
local result = nil
AddTextEntry("CUSTOM_AMOUNT", text)
DisplayOnscreenKeyboard(1, "CUSTOM_AMOUNT", '', "", '', '', '', 255)
while UpdateOnscreenKeyboard() ~= 1 and UpdateOnscreenKeyboard() ~= 2 do
Wait(1)
end
if UpdateOnscreenKeyboard() ~= 2 then
result = GetOnscreenKeyboardResult()
Citizen.Wait(1)
else
Citizen.Wait(1)
end
return result
end
function ShowNotification(text)
AddTextEntry('core:notif', text)
BeginTextCommandThefeedPost('core:notif')
AddTextComponentSubstringPlayerName(text)
EndTextCommandThefeedPostTicker(true, true)
end
function GetAllPlayersInArea(coords, zone)
local playersInArea = {}
if zone == nil then
zone = 150.0
end
for k, v in pairs(GetActivePlayers()) do
local pPed = GetPlayerPed(v)
local pCoords = GetEntityCoords(pPed)
if GetDistanceBetweenCoords(pCoords, coords, false) <= zone then
table.insert(playersInArea, v)
end
end
return playersInArea
end