ed
This commit is contained in:
		
							parent
							
								
									19fb68f805
								
							
						
					
					
						commit
						01d047b3cc
					
				
					 53 changed files with 3222 additions and 5 deletions
				
			
		
							
								
								
									
										349
									
								
								resources/[housing]/ox_doorlock/client/main.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										349
									
								
								resources/[housing]/ox_doorlock/client/main.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,349 @@ | |||
| if not LoadResourceFile(cache.resource, 'web/build/index.html') then | ||||
| 	error('Unable to load UI. Build ox_doorlock or download the latest release.\n	^3https://github.com/overextended/ox_doorlock/releases/latest/download/ox_doorlock.zip^0') | ||||
| end | ||||
|  | ||||
| if not lib.checkDependency('ox_lib', '3.14.0', true) then return end | ||||
|  | ||||
| local function createDoor(door) | ||||
| 	local double = door.doors | ||||
| 	door.zone = GetLabelText(GetNameOfZone(door.coords.x, door.coords.y, door.coords.z)) | ||||
|  | ||||
| 	if double then | ||||
| 		for i = 1, 2 do | ||||
| 			AddDoorToSystem(double[i].hash, double[i].model, double[i].coords.x, double[i].coords.y, double[i].coords.z, false, false, false) | ||||
| 			DoorSystemSetDoorState(double[i].hash, 4, false, false) | ||||
| 			DoorSystemSetDoorState(double[i].hash, door.state, false, false) | ||||
|  | ||||
| 			if door.doorRate or not door.auto then | ||||
| 				DoorSystemSetAutomaticRate(double[i].hash, door.doorRate or 10.0, false, false) | ||||
| 			end | ||||
| 		end | ||||
| 	else | ||||
| 		AddDoorToSystem(door.hash, door.model, door.coords.x, door.coords.y, door.coords.z, false, false, false) | ||||
| 		DoorSystemSetDoorState(door.hash, 4, false, false) | ||||
| 		DoorSystemSetDoorState(door.hash, door.state, false, false) | ||||
|  | ||||
| 		if door.doorRate or not door.auto then | ||||
| 			DoorSystemSetAutomaticRate(door.hash, door.doorRate or 10.0, false, false) | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| local nearbyDoors = {} | ||||
| local Entity = Entity | ||||
|  | ||||
| lib.callback('ox_doorlock:getDoors', false, function(data) | ||||
| 	doors = data | ||||
|  | ||||
| 	for _, door in pairs(data) do | ||||
| 		createDoor(door) | ||||
| 	end | ||||
|  | ||||
| 	while true do | ||||
| 		table.wipe(nearbyDoors) | ||||
| 		local coords = GetEntityCoords(cache.ped) | ||||
|  | ||||
| 		for _, door in pairs(doors) do | ||||
| 			local double = door.doors | ||||
| 			door.distance = #(coords - door.coords) | ||||
|  | ||||
| 			if double then | ||||
| 				if door.distance < 80 then | ||||
| 					for i = 1, 2 do | ||||
| 						if not double[i].entity and IsModelValid(double[i].model) then | ||||
| 							local entity = GetClosestObjectOfType(double[i].coords.x, double[i].coords.y, double[i].coords.z, 1.0, double[i].model, false, false, false) | ||||
|  | ||||
| 							if entity ~= 0 then | ||||
| 								double[i].entity = entity | ||||
| 								Entity(entity).state.doorId = door.id | ||||
| 							end | ||||
| 						end | ||||
| 					end | ||||
|  | ||||
| 					if door.distance < 20 then | ||||
| 						nearbyDoors[#nearbyDoors + 1] = door | ||||
| 					end | ||||
| 				else | ||||
| 					for i = 1, 2 do | ||||
| 						double[i].entity = nil | ||||
| 					end | ||||
| 				end | ||||
| 			elseif door.distance < 80 then | ||||
| 				if not door.entity and IsModelValid(door.model) then | ||||
| 					local entity = GetClosestObjectOfType(door.coords.x, door.coords.y, door.coords.z, 1.0, door.model, false, false, false) | ||||
|  | ||||
| 					if entity ~= 0 then | ||||
| 						local min, max = GetModelDimensions(door.model) | ||||
| 						local points = { | ||||
| 							GetOffsetFromEntityInWorldCoords(entity, min.x, min.y, min.z).xy, | ||||
| 							GetOffsetFromEntityInWorldCoords(entity, min.x, min.y, max.z).xy, | ||||
| 							GetOffsetFromEntityInWorldCoords(entity, min.x, max.y, max.z).xy, | ||||
| 							GetOffsetFromEntityInWorldCoords(entity, min.x, max.y, min.z).xy, | ||||
| 							GetOffsetFromEntityInWorldCoords(entity, max.x, min.y, min.z).xy, | ||||
| 							GetOffsetFromEntityInWorldCoords(entity, max.x, min.y, max.z).xy, | ||||
| 							GetOffsetFromEntityInWorldCoords(entity, max.x, max.y, max.z).xy, | ||||
| 							GetOffsetFromEntityInWorldCoords(entity, max.x, max.y, min.z).xy | ||||
| 						} | ||||
|  | ||||
| 						local centroid = vec2(0, 0) | ||||
|  | ||||
| 						for i = 1, 8 do | ||||
| 							centroid += points[i] | ||||
| 						end | ||||
|  | ||||
| 						centroid = centroid / 8 | ||||
| 						door.coords = vec3(centroid.x, centroid.y, door.coords.z) | ||||
| 						door.entity = entity | ||||
| 						Entity(entity).state.doorId = door.id | ||||
| 					end | ||||
| 				end | ||||
|  | ||||
| 				if door.distance < 20 then | ||||
| 					nearbyDoors[#nearbyDoors + 1] = door | ||||
| 				end | ||||
| 			elseif door.entity then | ||||
| 				door.entity = nil | ||||
| 			end | ||||
| 		end | ||||
|  | ||||
| 		Wait(500) | ||||
| 	end | ||||
| end) | ||||
|  | ||||
| RegisterNetEvent('ox_doorlock:setState', function(id, state, source, data) | ||||
| 	if not doors then return end | ||||
|  | ||||
| 	if data then | ||||
| 		doors[id] = data | ||||
| 		createDoor(data) | ||||
|  | ||||
| 		if NuiHasLoaded then | ||||
| 			SendNuiMessage(json.encode({ | ||||
| 				action = 'updateDoorData', | ||||
| 				data = data | ||||
| 			})) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	if Config.Notify and source == cache.serverId then | ||||
| 		if state == 0 then | ||||
| 			lib.notify({ | ||||
| 				type = 'success', | ||||
| 				icon = 'unlock', | ||||
| 				description = locale('unlocked_door') | ||||
| 			}) | ||||
| 		else | ||||
| 			lib.notify({ | ||||
| 				type = 'success', | ||||
| 				icon = 'lock', | ||||
| 				description = locale('locked_door') | ||||
| 			}) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	local door = data or doors[id] | ||||
| 	local double = door.doors | ||||
| 	door.state = state | ||||
|  | ||||
| 	if double then | ||||
| 		DoorSystemSetDoorState(double[1].hash, door.state, false, false) | ||||
| 		DoorSystemSetDoorState(double[2].hash, door.state, false, false) | ||||
|  | ||||
| 		if door.holdOpen then | ||||
| 			DoorSystemSetHoldOpen(double[1].hash, door.state == 0) | ||||
| 			DoorSystemSetHoldOpen(double[2].hash, door.state == 0) | ||||
| 		end | ||||
|  | ||||
| 		while door.state == 1 and (not IsDoorClosed(double[1].hash) or not IsDoorClosed(double[2].hash)) do Wait(0) end | ||||
| 	else | ||||
| 		DoorSystemSetDoorState(door.hash, door.state, false, false) | ||||
|  | ||||
| 		if door.holdOpen then DoorSystemSetHoldOpen(door.hash, door.state == 0) end | ||||
| 		while door.state == 1 and not IsDoorClosed(door.hash) do Wait(0) end | ||||
| 	end | ||||
|  | ||||
| 	if door.state == state and door.distance and door.distance < 20 then | ||||
| 		if Config.NativeAudio then | ||||
| 			RequestScriptAudioBank('dlc_oxdoorlock/oxdoorlock', false) | ||||
| 			local sound = state == 0 and door.unlockSound or door.lockSound or 'door_bolt' | ||||
| 			local soundId = GetSoundId() | ||||
|  | ||||
| 			PlaySoundFromCoord(soundId, sound, door.coords.x, door.coords.y, door.coords.z, 'DLC_OXDOORLOCK_SET', false, 0, false) | ||||
| 			ReleaseSoundId(soundId) | ||||
| 			ReleaseNamedScriptAudioBank('dlc_oxdoorlock/oxdoorlock') | ||||
| 		else | ||||
| 			local volume = (0.01 * GetProfileSetting(300)) / (door.distance / 2) | ||||
| 			if volume > 1 then volume = 1 end | ||||
| 			local sound = state == 0 and door.unlockSound or door.lockSound or 'door-bolt-4' | ||||
|  | ||||
| 			SendNUIMessage({ | ||||
| 				action = 'playSound', | ||||
| 				data = { | ||||
| 					sound = sound, | ||||
| 					volume = volume | ||||
| 				} | ||||
| 			}) | ||||
| 		end | ||||
| 	end | ||||
| end) | ||||
|  | ||||
| RegisterNetEvent('ox_doorlock:editDoorlock', function(id, data) | ||||
| 	if source == '' then return end | ||||
|  | ||||
| 	local door = doors[id] | ||||
| 	local double = door.doors | ||||
| 	local doorState = data and data.state or 0 | ||||
|  | ||||
| 	if data then | ||||
| 		data.zone = door.zone or GetLabelText(GetNameOfZone(door.coords.x, door.coords.y, door.coords.z)) | ||||
|  | ||||
| 		-- hacky method to resolve a bug with "closest door" by forcing a distance recalculation | ||||
| 		if door.distance < 20 then door.distance = 80 end | ||||
| 	elseif ClosestDoor?.id == id then | ||||
| 		ClosestDoor = nil | ||||
| 	end | ||||
|  | ||||
| 	if double then | ||||
| 		for i = 1, 2 do | ||||
| 			local doorHash = double[i].hash | ||||
|  | ||||
| 			if data then | ||||
| 				if data.doorRate or door.doorRate or not data.auto then | ||||
| 					DoorSystemSetAutomaticRate(doorHash, data.doorRate or door.doorRate and 0.0 or 10.0, false, false) | ||||
| 				end | ||||
|  | ||||
| 				DoorSystemSetDoorState(doorHash, doorState, false, false) | ||||
|  | ||||
| 				if data.holdOpen then DoorSystemSetHoldOpen(doorHash, doorState == 0) end | ||||
| 			else | ||||
| 				DoorSystemSetDoorState(doorHash, 4, false, false) | ||||
| 				DoorSystemSetDoorState(doorHash, 0, false, false) | ||||
|  | ||||
| 				if double[i].entity then | ||||
| 					Entity(double[i].entity).state.doorId = nil | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 	else | ||||
| 		if data then | ||||
| 			if data.doorRate or door.doorRate or not data.auto then | ||||
| 				DoorSystemSetAutomaticRate(door.hash, data.doorRate or door.doorRate and 0.0 or 10.0, false, false) | ||||
| 			end | ||||
|  | ||||
| 			DoorSystemSetDoorState(door.hash, doorState, false, false) | ||||
|  | ||||
| 			if data.holdOpen then DoorSystemSetHoldOpen(door.hash, doorState == 0) end | ||||
| 		else | ||||
| 			DoorSystemSetDoorState(door.hash, 4, false, false) | ||||
| 			DoorSystemSetDoorState(door.hash, 0, false, false) | ||||
|  | ||||
| 			if door.entity then | ||||
| 				Entity(door.entity).state.doorId = nil | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	doors[id] = data | ||||
|  | ||||
| 	if NuiHasLoaded then | ||||
| 		SendNuiMessage(json.encode({ | ||||
| 			action = 'updateDoorData', | ||||
| 			data = data or id | ||||
| 		})) | ||||
| 	end | ||||
| end) | ||||
|  | ||||
| ClosestDoor = nil | ||||
|  | ||||
| lib.callback.register('ox_doorlock:inputPassCode', function() | ||||
| 	return ClosestDoor?.passcode and lib.inputDialog(locale('door_lock'), { | ||||
| 		{ | ||||
| 			type = 'input', | ||||
| 			label = locale('passcode'), | ||||
| 			password = true, | ||||
| 			icon = 'lock' | ||||
| 		}, | ||||
| 	})?[1] | ||||
| end) | ||||
|  | ||||
| local lastTriggered = 0 | ||||
|  | ||||
| local function useClosestDoor() | ||||
| 	if not ClosestDoor then return false end | ||||
|  | ||||
| 	local gameTimer = GetGameTimer() | ||||
|  | ||||
| 	if gameTimer - lastTriggered > 500 then | ||||
| 		lastTriggered = gameTimer | ||||
| 		TriggerServerEvent('ox_doorlock:setState', ClosestDoor.id, ClosestDoor.state == 1 and 0 or 1) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| exports('useClosestDoor', useClosestDoor) | ||||
|  | ||||
| CreateThread(function() | ||||
| 	local lockDoor = locale('lock_door') | ||||
| 	local unlockDoor = locale('unlock_door') | ||||
| 	local showUI | ||||
| 	local drawSprite = Config.DrawSprite | ||||
|  | ||||
| 	if drawSprite then | ||||
| 		local sprite1 = drawSprite[0]?[1] | ||||
| 		local sprite2 = drawSprite[1]?[1] | ||||
|  | ||||
| 		if sprite1 then | ||||
| 			RequestStreamedTextureDict(sprite1, true) | ||||
| 		end | ||||
|  | ||||
| 		if sprite2 then | ||||
| 			RequestStreamedTextureDict(sprite2, true) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	local SetDrawOrigin = SetDrawOrigin | ||||
| 	local ClearDrawOrigin = ClearDrawOrigin | ||||
| 	local DrawSprite = drawSprite and DrawSprite | ||||
|  | ||||
| 	while true do | ||||
| 		local num = #nearbyDoors | ||||
|  | ||||
| 		if num > 0 then | ||||
| 			local ratio = drawSprite and GetAspectRatio(true) | ||||
| 			for i = 1, num do | ||||
| 				local door = nearbyDoors[i] | ||||
|  | ||||
| 				if door.distance < door.maxDistance then | ||||
| 					if door.distance < (ClosestDoor?.distance or 10) then | ||||
| 						ClosestDoor = door | ||||
| 					end | ||||
|  | ||||
| 					if drawSprite and not door.hideUi then | ||||
| 						local sprite = drawSprite[door.state] | ||||
|  | ||||
| 						if sprite then | ||||
| 							SetDrawOrigin(door.coords.x, door.coords.y, door.coords.z) | ||||
| 							DrawSprite(sprite[1], sprite[2], sprite[3], sprite[4], sprite[5], sprite[6] * ratio, sprite[7], sprite[8], sprite[9], sprite[10], sprite[11]) | ||||
| 							ClearDrawOrigin() | ||||
| 						end | ||||
| 					end | ||||
| 				end | ||||
| 			end | ||||
| 		else ClosestDoor = nil end | ||||
|  | ||||
| 		if ClosestDoor and ClosestDoor.distance < ClosestDoor.maxDistance then | ||||
| 			if Config.DrawTextUI and not ClosestDoor.hideUi and ClosestDoor.state ~= showUI then | ||||
| 				lib.showTextUI(ClosestDoor.state == 0 and lockDoor or unlockDoor) | ||||
| 				showUI = ClosestDoor.state | ||||
| 			end | ||||
|  | ||||
| 			if not PickingLock and IsDisabledControlJustReleased(0, 38) then | ||||
| 				useClosestDoor() | ||||
| 			end | ||||
| 		elseif showUI then | ||||
| 			lib.hideTextUI() | ||||
| 			showUI = nil | ||||
| 		end | ||||
|  | ||||
| 		Wait(num > 0 and 0 or 500) | ||||
| 	end | ||||
| end) | ||||
							
								
								
									
										410
									
								
								resources/[housing]/ox_doorlock/client/utils.lua
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										410
									
								
								resources/[housing]/ox_doorlock/client/utils.lua
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,410 @@ | |||
| local Entity = Entity | ||||
|  | ||||
| local function getDoorFromEntity(data) | ||||
| 	local entity = type(data) == 'table' and data.entity or data | ||||
|  | ||||
| 	if not entity then return end | ||||
|  | ||||
| 	local state = Entity(entity)?.state | ||||
| 	local doorId = state?.doorId | ||||
|  | ||||
| 	if not doorId then return end | ||||
|  | ||||
| 	local door = doors[doorId] | ||||
|  | ||||
| 	if not door then | ||||
| 		state.doorId = nil | ||||
| 	end | ||||
|  | ||||
| 	return door | ||||
| end | ||||
|  | ||||
| exports('getClosestDoorId', function() return ClosestDoor?.id end) | ||||
| exports('getDoorIdFromEntity', function(entityId) return getDoorFromEntity(entityId)?.id end) -- same as Entity(entityId).state.doorId | ||||
|  | ||||
| local function entityIsNotDoor(data) | ||||
| 	local entity = type(data) == 'number' and data or data.entity | ||||
| 	return not getDoorFromEntity(entity) | ||||
| end | ||||
|  | ||||
| PickingLock = false | ||||
|  | ||||
| local function canPickLock(entity) | ||||
| 	if PickingLock then return false end | ||||
|  | ||||
| 	local door = getDoorFromEntity(entity) | ||||
|  | ||||
| 	return door and door.lockpick and (Config.CanPickUnlockedDoors or door.state == 1) | ||||
| end | ||||
|  | ||||
| ---@param entity number | ||||
| local function pickLock(entity) | ||||
| 	local door = getDoorFromEntity(entity) | ||||
|  | ||||
| 	if not door or PickingLock or not door.lockpick or (not Config.CanPickUnlockedDoors and door.state == 0) then return end | ||||
|  | ||||
| 	PickingLock = true | ||||
|  | ||||
| 	TaskTurnPedToFaceCoord(cache.ped, door.coords.x, door.coords.y, door.coords.z, 4000) | ||||
| 	Wait(500) | ||||
|  | ||||
| 	local animDict = lib.requestAnimDict('mp_common_heist') | ||||
|  | ||||
| 	TaskPlayAnim(cache.ped, animDict, 'pick_door', 3.0, 1.0, -1, 49, 0, true, true, true) | ||||
|  | ||||
| 	local success = lib.skillCheck(door.lockpickDifficulty or Config.LockDifficulty) | ||||
| 	local rand = math.random(1, success and 100 or 5) | ||||
|  | ||||
| 	if success then | ||||
| 		TriggerServerEvent('ox_doorlock:setState', door.id, door.state == 1 and 0 or 1, true) | ||||
| 	end | ||||
|  | ||||
| 	if rand == 1 then | ||||
| 		TriggerServerEvent('ox_doorlock:breakLockpick') | ||||
| 		lib.notify({ type = 'error', description = locale('lockpick_broke') }) | ||||
| 	end | ||||
|  | ||||
| 	StopEntityAnim(cache.ped, 'pick_door', animDict, 0) | ||||
| 	RemoveAnimDict(animDict) | ||||
|  | ||||
| 	PickingLock = false | ||||
| end | ||||
|  | ||||
| exports('pickClosestDoor', function() | ||||
| 	if not ClosestDoor then return end | ||||
|  | ||||
| 	pickLock(ClosestDoor.entity) | ||||
| end) | ||||
|  | ||||
| local tempData = {} | ||||
|  | ||||
| local function addDoorlock(data) | ||||
| 	local entity = type(data) == 'number' and data or data.entity | ||||
| 	local model = GetEntityModel(entity) | ||||
| 	local coords = GetEntityCoords(entity) | ||||
|  | ||||
| 	AddDoorToSystem(`temp`, model, coords.x, coords.y, coords.z, false, false, false) | ||||
| 	DoorSystemSetDoorState(`temp`, 4, false, false) | ||||
|  | ||||
| 	coords = GetEntityCoords(entity) | ||||
| 	tempData[#tempData + 1] = { | ||||
| 		entity = entity, | ||||
| 		model = model, | ||||
| 		coords = coords, | ||||
| 		heading = math.floor(GetEntityHeading(entity) + 0.5) | ||||
| 	} | ||||
|  | ||||
| 	RemoveDoorFromSystem(`temp`) | ||||
| end | ||||
|  | ||||
| local isAddingDoorlock = false | ||||
|  | ||||
| RegisterNUICallback('notify', function(data, cb) | ||||
| 	cb(1) | ||||
| 	lib.notify({ title = data }) | ||||
| end) | ||||
|  | ||||
| RegisterNUICallback('createDoor', function(data, cb) | ||||
| 	cb(1) | ||||
| 	SetNuiFocus(false, false) | ||||
|  | ||||
| 	data.state = data.state and 1 or 0 | ||||
|  | ||||
| 	if data.items and not next(data.items) then | ||||
| 		data.items = nil | ||||
| 	end | ||||
|  | ||||
| 	if data.characters and not next(data.characters) then | ||||
| 		data.characters = nil | ||||
| 	end | ||||
|  | ||||
| 	if data.lockpickDifficulty and not next(data.lockpickDifficulty) then | ||||
| 		data.lockpickDifficulty = nil | ||||
| 	end | ||||
|  | ||||
| 	if data.groups and not next(data.groups) then | ||||
| 		data.groups = nil | ||||
| 	end | ||||
|  | ||||
| 	if not data.id then | ||||
| 		isAddingDoorlock = true | ||||
| 		local doorCount = data.doors and 2 or 1 | ||||
| 		local lastEntity = 0 | ||||
|  | ||||
| 		lib.showTextUI(locale('add_door_textui')) | ||||
|  | ||||
| 		repeat | ||||
| 			DisablePlayerFiring(cache.playerId, true) | ||||
| 			DisableControlAction(0, 25, true) | ||||
|  | ||||
| 			local hit, entity, coords = lib.raycast.cam(1|16) | ||||
| 			local changedEntity = lastEntity ~= entity | ||||
| 			local doorA = tempData[1]?.entity | ||||
|  | ||||
| 			if changedEntity and lastEntity ~= doorA then | ||||
| 				SetEntityDrawOutline(lastEntity, false) | ||||
| 			end | ||||
|  | ||||
| 			lastEntity = entity | ||||
|  | ||||
| 			if hit then | ||||
| 				---@diagnostic disable-next-line: param-type-mismatch | ||||
| 				DrawMarker(28, coords.x, coords.y, coords.z, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.2, 0.2, 0.2, 255, 42, 24, | ||||
| 					100, false, false, 0, true, false, false, false) | ||||
| 			end | ||||
|  | ||||
| 			if hit and entity > 0 and GetEntityType(entity) == 3 and (doorCount == 1 or doorA ~= entity) and entityIsNotDoor(entity) then | ||||
| 				if changedEntity then | ||||
| 					SetEntityDrawOutline(entity, true) | ||||
| 				end | ||||
|  | ||||
| 				if IsDisabledControlJustPressed(0, 24) then | ||||
| 					addDoorlock(entity) | ||||
| 				end | ||||
| 			end | ||||
|  | ||||
| 			if IsDisabledControlJustPressed(0, 25) then | ||||
| 				SetEntityDrawOutline(entity, false) | ||||
|  | ||||
| 				if not doorA then | ||||
| 					isAddingDoorlock = false | ||||
| 					return lib.hideTextUI() | ||||
| 				end | ||||
|  | ||||
| 				SetEntityDrawOutline(doorA, false) | ||||
| 				table.wipe(tempData) | ||||
| 			end | ||||
| 		until tempData[doorCount] | ||||
|  | ||||
| 		lib.hideTextUI() | ||||
| 		SetEntityDrawOutline(tempData[1].entity, false) | ||||
|  | ||||
| 		if data.doors then | ||||
| 			SetEntityDrawOutline(tempData[2].entity, false) | ||||
| 			tempData[1].entity = nil | ||||
| 			tempData[2].entity = nil | ||||
| 			data.doors = tempData | ||||
| 		else | ||||
| 			data.model = tempData[1].model | ||||
| 			data.coords = tempData[1].coords | ||||
| 			data.heading = tempData[1].heading | ||||
| 		end | ||||
| 	else | ||||
| 		if data.doors then | ||||
| 			for i = 1, 2 do | ||||
| 				local coords = data.doors[i].coords | ||||
| 				data.doors[i].coords = vector3(coords.x, coords.y, coords.z) | ||||
| 				data.doors[i].entity = nil | ||||
| 			end | ||||
| 		else | ||||
| 			data.entity = nil | ||||
| 		end | ||||
|  | ||||
| 		data.coords = vector3(data.coords.x, data.coords.y, data.coords.z) | ||||
| 		data.distance = nil | ||||
| 		data.zone = nil | ||||
| 	end | ||||
|  | ||||
| 	isAddingDoorlock = false | ||||
|  | ||||
| 	------------------------------------ | ||||
| 	------- Brutal Housing Editing ----- | ||||
| 	------------------------------------ | ||||
| 	if PropertyID ~= nil then | ||||
| 		if data.name:match("^(.-)_") == nil or data.name:match("^(.-)_") ~= PropertyID then | ||||
| 			data.name = PropertyID.."_"..data.name | ||||
| 		end | ||||
|  | ||||
| 		local coords = data.coords or data.doors[1].coords | ||||
| 		if coords ~= nil then | ||||
| 			if #(coords - vector3(PropertyCoords.x, PropertyCoords.y, PropertyCoords.z)) > MaxDoorlockDistance then | ||||
| 				TriggerEvent('brutal_housing:client:SendNotifyNumber', 75) | ||||
| 				return | ||||
| 			end | ||||
| 		else | ||||
| 			return | ||||
| 		end | ||||
|  | ||||
| 		PropertyID = nil | ||||
| 		PropertyCoords = nil | ||||
| 	end | ||||
| 	------------------------------------ | ||||
| 	------- Brutal Housing Editing ----- | ||||
| 	------------------------------------ | ||||
|  | ||||
| 	TriggerServerEvent('ox_doorlock:editDoorlock', data.id or false, data) | ||||
| 	table.wipe(tempData) | ||||
| end) | ||||
|  | ||||
| RegisterNUICallback('deleteDoor', function(id, cb) | ||||
| 	cb(1) | ||||
| 	TriggerServerEvent('ox_doorlock:editDoorlock', id) | ||||
| end) | ||||
|  | ||||
| RegisterNUICallback('teleportToDoor', function(id, cb) | ||||
| 	cb(1) | ||||
| 	SetNuiFocus(false, false) | ||||
| 	local doorCoords = doors[id].coords | ||||
| 	if not doorCoords then return end | ||||
| 	SetEntityCoords(cache.ped, doorCoords.x, doorCoords.y, doorCoords.z, false, false, false, false) | ||||
| end) | ||||
|  | ||||
| RegisterNUICallback('exit', function(_, cb) | ||||
| 	cb(1) | ||||
| 	SetNuiFocus(false, false) | ||||
| end) | ||||
|  | ||||
| ------------------------------------ | ||||
| ------- Brutal Housing Editing ----- | ||||
| ------------------------------------ | ||||
|  | ||||
| PropertyID = nil | ||||
| PropertyCoords = nil | ||||
| MaxDoorlockDistance = 50.0 | ||||
|  | ||||
| RegisterNetEvent("ox_doorlock:dataFromHousing") | ||||
| AddEventHandler("ox_doorlock:dataFromHousing", function(propertyID, coords, maxdoorlockdistance) | ||||
| 	PropertyID = propertyID | ||||
| 	PropertyCoords = coords | ||||
| 	MaxDoorlockDistance = maxdoorlockdistance | ||||
|  | ||||
| 	if isAddingDoorlock then return end | ||||
|  | ||||
| 	NuiHasLoaded = true | ||||
|  | ||||
| 	local allowedDoors = {} | ||||
| 	for k,v in pairs(doors) do | ||||
| 		print(v.name:match("^(.-)_"), PropertyID) | ||||
| 		if v.name:match("^(.-)_") == PropertyID then | ||||
| 			table.insert(allowedDoors, v) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	SendNuiMessage(json.encode({ | ||||
| 		action = 'updateDoorData', | ||||
| 		data = allowedDoors | ||||
| 	}, { with_hole = false })) | ||||
| 	Wait(100) | ||||
|  | ||||
| 	SendNUIMessage({ | ||||
| 		action = 'setSoundFiles', | ||||
| 		data = lib.callback.await('ox_doorlock:getSounds', false) | ||||
| 	}) | ||||
|  | ||||
| 	SetNuiFocus(true, true) | ||||
| 	SendNuiMessage(json.encode({ | ||||
| 		action = 'setVisible', | ||||
| 		data = id | ||||
| 	})) | ||||
| end) | ||||
|  | ||||
| ------------------------------------ | ||||
| ------- Brutal Housing Editing ----- | ||||
| ------------------------------------ | ||||
|  | ||||
| local function openUi(id) | ||||
| 	if source == '' or isAddingDoorlock then return end | ||||
|  | ||||
| 	------------------------------------ | ||||
| 	------- Brutal Housing Editing ----- | ||||
| 	------------------------------------ | ||||
| 	PropertyID = nil | ||||
| 	PropertyCoords = nil | ||||
| 	------------------------------------ | ||||
| 	------- Brutal Housing Editing ----- | ||||
| 	------------------------------------ | ||||
|  | ||||
| 	NuiHasLoaded = true | ||||
|  | ||||
| 	SendNuiMessage(json.encode({ | ||||
| 		action = 'updateDoorData', | ||||
| 		data = doors | ||||
| 	}, { with_hole = false })) | ||||
| 	Wait(100) | ||||
|  | ||||
| 	SendNUIMessage({ | ||||
| 		action = 'setSoundFiles', | ||||
| 		data = lib.callback.await('ox_doorlock:getSounds', false) | ||||
| 	}) | ||||
|  | ||||
| 	SetNuiFocus(true, true) | ||||
| 	SendNuiMessage(json.encode({ | ||||
| 		action = 'setVisible', | ||||
| 		data = id | ||||
| 	})) | ||||
| end | ||||
|  | ||||
| RegisterNetEvent('ox_doorlock:triggeredCommand', function(closest) | ||||
| 	openUi(closest and ClosestDoor?.id or nil) | ||||
| end) | ||||
|  | ||||
| CreateThread(function() | ||||
| 	local target | ||||
|  | ||||
| 	if GetResourceState('ox_target'):find('start') then | ||||
| 		target = { | ||||
| 			ox = true, | ||||
| 			exp = exports.ox_target | ||||
| 		} | ||||
| 	elseif GetResourceState('qb-target'):find('start') then | ||||
| 		target = { | ||||
| 			qb = true, | ||||
| 			exp = exports['qb-target'] | ||||
| 		} | ||||
| 	elseif GetResourceState('qtarget'):find('start') then | ||||
| 		target = { | ||||
| 			qt = true, | ||||
| 			exp = exports.qtarget | ||||
| 		} | ||||
| 	end | ||||
|  | ||||
| 	if not target then return end | ||||
|  | ||||
| 	if target.ox then | ||||
| 		target.exp:addGlobalObject({ | ||||
| 			{ | ||||
| 				name = 'pickDoorlock', | ||||
| 				label = locale('pick_lock'), | ||||
| 				icon = 'fas fa-user-lock', | ||||
| 				onSelect = pickLock, | ||||
| 				canInteract = canPickLock, | ||||
| 				items = Config.LockpickItems, | ||||
| 				anyItem = true, | ||||
| 				distance = 1 | ||||
| 			} | ||||
| 		}) | ||||
| 	else | ||||
| 		local options = { | ||||
| 			{ | ||||
| 				label = locale('pick_lock'), | ||||
| 				icon = 'fas fa-user-lock', | ||||
| 				action = pickLock, | ||||
| 				canInteract = canPickLock, | ||||
| 				item = Config.LockpickItems[1], | ||||
| 				distance = 1 | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		---@cast target table | ||||
|  | ||||
| 		if target.qt then | ||||
| 			target.exp:Object({ options = options }) | ||||
| 		elseif target.qb then | ||||
| 			target.exp:AddGlobalObject({ options = options }) | ||||
| 		end | ||||
|  | ||||
| 		options = { locale('pick_lock') } | ||||
|  | ||||
| 		AddEventHandler('onResourceStop', function(resource) | ||||
| 			if resource == cache.resource then | ||||
| 				if target.qt then | ||||
| 					return target.exp:RemoveObject(options) | ||||
| 				end | ||||
|  | ||||
| 				if target.qb then | ||||
| 					return target.exp:RemoveGlobalObject(options) | ||||
| 				end | ||||
| 			end | ||||
| 		end) | ||||
| 	end | ||||
| end) | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Nordi98
						Nordi98