local target, ox_target local locations = {} local pedBlips = {} local clothingComponents = { face = 0, mask = 1, hair = 2, torso = 3, leg = 4, bag = 5, shoes = 6, accessory = 7, undershirt = 8, kevlar = 9, badge = 10, torso2 = 11 } local clothingProps = { hat = 0, glasses = 1, ears = 2, watch = 6, bracelets = 7 } NDCore.isResourceStarted("ox_target", function(started) target = started if not target then return end ox_target = exports.ox_target end) local function configPed(ped) SetPedCanBeTargetted(ped, false) SetEntityCanBeDamaged(ped, false) SetBlockingOfNonTemporaryEvents(ped, true) SetPedCanRagdollFromPlayerImpact(ped, false) SetPedResetFlag(ped, 249, true) SetPedConfigFlag(ped, 185, true) SetPedConfigFlag(ped, 108, true) SetPedConfigFlag(ped, 208, true) SetPedCanRagdoll(ped, false) end local function setClothing(ped, clothing) if not clothing then return end for component, clothingInfo in pairs(clothing) do if clothingComponents[component] then SetPedComponentVariation(ped, clothingComponents[component], clothingInfo.drawable, clothingInfo.texture, 0) elseif clothingProps[component] then SetPedPropIndex(ped, clothingProps[component], clothingInfo.drawable, clothingInfo.texture, true) end end end local function groupCheck(groups, playerGroups) if not groups or #groups == 0 then return true end for i=1, #groups do if playerGroups and playerGroups[groups[i]] then return true end end end local function createBlip(coords, info, i) if not info then return end local groups = info.groups local playerGroups = NDCore.player?.groups local key = i or #pedBlips+1 pedBlips[key] = { groups = groups, info = info, coords = coords } if not groupCheck(groups, playerGroups) then return end local blip = AddBlipForCoord(coords.x, coords.y, coords.z) SetBlipSprite(blip, info.sprite or 280) SetBlipScale(blip, info.scale or 0.8) SetBlipColour(blip, info.color or 3) SetBlipAsShortRange(blip, true) if info.label then BeginTextCommandSetBlipName("STRING") AddTextComponentString(info.label) EndTextCommandSetBlipName(blip) end pedBlips[key].blip = blip return blip end local function updateBlips(playerGroups) for i=1, #pedBlips do local blipInfo = pedBlips[i] local access = groupCheck(blipInfo.groups, playerGroups) if access and not blipInfo.blip or not DoesBlipExist(blipInfo.blip) then createBlip(blipInfo.coords, blipInfo.info, i) elseif not access and blipInfo.blip and DoesBlipExist(blipInfo.blip) then RemoveBlip(blipInfo.blip) end end end local function disableCollisionWithModels(ped, models) if not models then return end local coords = GetEntityCoords(ped) for i=1, #models do local m = models[i] local model = type(m) == "number" and m or GetHashKey(m) local obj = GetClosestObjectOfType(coords.x, coords.y, coords.z, 5.0, model, false, false, false) SetEntityNoCollisionEntity(ped, obj, false) end end function NDCore.createAiPed(info) local ped local model = type(info.model) == "string" and GetHashKey(info.model) or info.model local blipInfo = info.blip local anim = info.anim local clothing = info.clothing local coords = info.coords local options = info.options local blip = createBlip(coords, blipInfo) local point = lib.points.new({ coords = coords.xyz, distance = info.distance or 25.0 }) local id = #locations+1 locations[id] = { point = point, blip = blip, options = info.options, resource = info.resource or GetInvokingResource() } if blip and blipInfo and blipInfo.showWhenNear and DoesBlipExist(blip) and #(GetEntityCoords(cache.ped)-coords.xyz) > point.distance then SetBlipAlpha(blip, 0) end function point:onEnter() local found, ground = GetGroundZFor_3dCoord(coords.x, coords.y, coords.z, true) lib.requestModel(model) ped = CreatePed(4, model, coords.x, coords.y, found and ground or coords.z, coords.w or coords.h or info.heading, false, false) local time = GetCloudTimeAsInt() while not DoesEntityExist(ped) and time-GetCloudTimeAsInt() < 5 do Wait(100) end disableCollisionWithModels(ped, info.disableCollisionWithModels) configPed(ped) setClothing(ped, clothing) locations[id].ped = ped if anim and anim.dict and anim.clip then lib.requestAnimDict(anim.dict) TaskPlayAnim(ped, anim.dict, anim.clip, 2.0, 8.0, -1, 1, 0, 0, 0, 0) end if target and options then Wait(500) ox_target:addLocalEntity({ped}, options) end if blip and blipInfo and blipInfo.showWhenNear and DoesBlipExist(blip) then SetBlipAlpha(blip, 255) end end function point:onExit() if blip and blipInfo and blipInfo.showWhenNear and DoesBlipExist(blip) then SetBlipAlpha(blip, 0) end if ped and DoesEntityExist(ped) then if target and options then ox_target:removeLocalEntity({ped}) end Wait(500) DeleteEntity(ped) end end return id end function NDCore.removeAiPed(id) local info = locations[id] if not info then return end local ped = info.ped local blip = info.blip info.point:remove() locations[id] = nil if blip and DoesBlipExist(blip) then RemoveBlip(blip) end if ped and DoesEntityExist(ped) then if info.options then ox_target:removeLocalEntity({ped}) end DeleteEntity(ped) end end RegisterNetEvent("ND:updateCharacter", function(character) Wait(3000) if character.id ~= NDCore.player?.id then return end updateBlips(character.groups) end) RegisterNetEvent("ND:characterLoaded", function(character) Wait(3000) if character.id ~= NDCore.player?.id then return end updateBlips(character.groups) end) AddEventHandler("onResourceStop", function(name) if name == GetCurrentResourceName() then for i, _ in ipairs(locations) do NDCore.removeAiPed(i) end else for i, v in ipairs(locations) do if v.resource == name then NDCore.removeAiPed(i) end end end end) RegisterCommand("getclothing", function(source, args, rawCommand) local info = "" for k, v in pairs(clothingComponents) do info = ("%s\n%s = { drawable = %s, texture = %s },"):format(info, k, GetPedDrawableVariation(cache.ped, v), GetPedTextureVariation(cache.ped, v)) end for k, v in pairs(clothingProps) do info = ("%s\n%s = { drawable = %s, texture = %s },"):format(info, k, GetPedPropIndex(cache.ped, v), GetPedPropTextureIndex(cache.ped, v)) end lib.setClipboard(info) end, false)