298 lines
		
	
	
		
			No EOL
		
	
	
		
			10 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			298 lines
		
	
	
		
			No EOL
		
	
	
		
			10 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
| if not Config.GUI.Enabled then return end
 | |
| 
 | |
| local Sounds = { -- In case you wanna change out the sounds they are located here.
 | |
| 	["Close"] = {"TOGGLE_ON", "HUD_FRONTEND_DEFAULT_SOUNDSET"},
 | |
| 	["Open"] = {"NAV_LEFT_RIGHT", "HUD_FRONTEND_DEFAULT_SOUNDSET"},
 | |
| 	["Select"] = {"SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET"}
 | |
| }
 | |
| function SoundPlay(which)
 | |
| 	if not Config.GUI.Sound then return end
 | |
| 	local Sound = Sounds[which]
 | |
| 	PlaySoundFrontend(-1, Sound[1], Sound[2])
 | |
| end
 | |
| 
 | |
| local function Distance(x1, y1, x2, y2)
 | |
| 	local dx = x1 - x2
 | |
| 	local dy = y1 - y2
 | |
| 	return math.sqrt(dx * dx + dy * dy)
 | |
| end
 | |
| 
 | |
| local function DisableControl()
 | |
| 	DisableControlAction(1, 1, true)
 | |
| 	DisableControlAction(1, 2, true)
 | |
| 	DisableControlAction(1, 18, true)
 | |
| 	DisableControlAction(1, 68, true)
 | |
| 	DisableControlAction(1, 69, true)
 | |
| 	DisableControlAction(1, 70, true)
 | |
| 	DisableControlAction(1, 91, true)
 | |
| 	DisableControlAction(1, 92, true)
 | |
| 	DisableControlAction(1, 24, true)
 | |
| 	DisableControlAction(1, 25, true)
 | |
| 	DisableControlAction(1, 14, true)
 | |
| 	DisableControlAction(1, 15, true)
 | |
| 	DisableControlAction(1, 16, true)
 | |
| 	DisableControlAction(1, 17, true)
 | |
| 	DisablePlayerFiring(PlayerId(), true)	-- We wouldnt want the player punching by accident.
 | |
| 	ShowCursorThisFrame()
 | |
| end
 | |
| 
 | |
| local function GetCursor() -- This might break for people with weird resolutions? Im really not sure.
 | |
| 	local sx, sy = GetActiveScreenResolution()
 | |
| 	local cx, cy = GetNuiCursorPosition()
 | |
| 	local cx, cy = (cx / sx) + 0.008, (cy / sy) + 0.027
 | |
| 	return cx, cy
 | |
| end
 | |
| 
 | |
| local function DrawButton(b)
 | |
| 	local B = Config.GUI.ButtonColor
 | |
| 	local Rot = b.Rotate or 0.0
 | |
| 	if b.Shadow then
 | |
| 		DrawSprite("dp_clothing", "circle", b.x, b.y, b.Size.Circle.x/0.80, b.Size.Circle.y/0.80, Rot, b.Colour.r, b.Colour.g, b.Colour.b, b.Alpha)
 | |
| 	end
 | |
| 	DrawSprite("dp_clothing", b.Sprite, b.x, b.y, b.Size.Sprite.x/0.68, b.Size.Sprite.y/0.68, b.Rotation, 255, 255, 255, b.Alpha)
 | |
| 	if IsDisabledControlJustPressed(1, 24) then
 | |
| 		local x,y = GetCursor()
 | |
| 		local Distance = Distance(b.x+0.005, b.y+0.025, x, y)
 | |
| 		if Distance < 0.025 then return true end
 | |
| 	elseif IsDisabledControlJustPressed(1, 25) and Config.Debug then
 | |
| 		local x,y = GetCursor()
 | |
| 		local Distance = Distance(b.x+0.005, b.y+0.025, x, y)
 | |
| 		if Distance < 0.025 then
 | |
| 			DevTestVariants(FirstUpper(b.Sprite))
 | |
| 		end
 | |
| 	end
 | |
| 	return false
 | |
| end
 | |
| 
 | |
| local function Check(ped) -- We check if the player should be able to open the menu.
 | |
| 	if IsPedInAnyVehicle(ped) and not Config.GUI.AllowInCars then
 | |
| 		return false
 | |
| 	elseif IsPedSwimmingUnderWater(ped) then
 | |
| 		return false
 | |
| 	elseif IsPedRagdoll(ped) and not Config.GUI.AllowWhenRagdolled then
 | |
| 		return false
 | |
| 	elseif IsHudComponentActive(19) then -- If the weapon wheel is open, we close!
 | |
| 		return false
 | |
| 	end
 | |
| 	return true
 | |
| end
 | |
| 
 | |
| local DefaultButton = {x = 0.0254, y = 0.0445}
 | |
| local DefaultCircle = {x = 0.0345 / 1.2, y = 0.06 / 1.2}
 | |
| local Buttons = {}
 | |
| local ExtraButtons = {}
 | |
| local InfoButtonRot = 0.0
 | |
| MenuOpened = false
 | |
| 
 | |
| local function GenerateTheButtons() -- We generate the buttons here to save on a little bit of performance.
 | |
| 	local x, y, rx, ry = Config.GUI.Position.x, Config.GUI.Position.y, 0.1, 0.175
 | |
| 	for k,v in pairs(Config.Commands) do
 | |
| 		local i = v.Button
 | |
| 		local Angle = i * math.pi / 7 local Ptx, Pty = x + rx * math.cos(Angle), y + ry * math.sin(Angle)
 | |
| 		Buttons[i] = {
 | |
| 			Command = k,
 | |
| 			Desc = v.Desc or "",
 | |
| 			Rotation = v.Rotation or 0.0,
 | |
| 			Size = {Sprite = DefaultButton},
 | |
| 			Sprite = v.Sprite,
 | |
| 			Text = v.Name,
 | |
| 			x = Ptx, y = Pty,
 | |
| 			Rotation = 0.0
 | |
| 		}
 | |
| 	end
 | |
| 	if Config.ExtrasEnabled then -- The extra buttons arent tied to the wheel, and can be moved with simple offsets.
 | |
| 		for k,v in pairs(Config.ExtraCommands) do
 | |
| 			local Enabled = v.Enabled if Enabled == nil then Enabled = true end
 | |
| 			ExtraButtons[k] = {
 | |
| 				Command = k,
 | |
| 				Desc = v.Desc or "",
 | |
| 				OffsetX = v.OffsetX, OffsetY = v.OffsetY,
 | |
| 				Size = { Circle = {x = DefaultCircle.x, y = DefaultCircle.y}, Sprite = {x = DefaultButton.x/1.35, y = DefaultButton.y/1.35}},
 | |
| 				Sprite = v.Sprite,
 | |
| 				SpriteFunc = v.SpriteFunc,
 | |
| 				Text = v.Name,
 | |
| 				Enabled = Enabled,
 | |
| 				Rotate = v.Rotate,
 | |
| 				Rotation = 0.0
 | |
| 			}
 | |
| 		end
 | |
| 	end
 | |
| end
 | |
| 
 | |
| local function PushedButton(button, extra, rotate, info) -- https://www.youtube.com/watch?v=v57i1Ze0jB8
 | |
| 	Citizen.CreateThread(function()	
 | |
| 		SoundPlay("Select")
 | |
| 		local Button = nil
 | |
| 		if extra then Button = ExtraButtons[button] elseif info then Button = InfoButton else Button = Buttons[button] end
 | |
| 		if rotate then
 | |
| 			for i = 1, 18 do
 | |
| 				if not info then Button.Rotation = -i*20+0.0 Wait(1) else InfoButtonRot = -i*20+0.0 Wait(1) end
 | |
| 			end return
 | |
| 		end
 | |
| 		if not extra then
 | |
| 			Button.Size = {Sprite = {x = DefaultButton.x/1.1, y = DefaultButton.y/1.1}}
 | |
| 			Wait(100)
 | |
| 			Button.Size = {Sprite = {x = DefaultButton.x, y = DefaultButton.y}}
 | |
| 		else
 | |
| 			Button.Size = { Circle = {x = DefaultCircle.x, y = DefaultCircle.y}, Sprite = {x = DefaultButton.x/1.3/1.1, y = DefaultButton.y/1.3/1.1}}
 | |
| 			Wait(100)
 | |
| 			Button.Size = { Circle = {x = DefaultCircle.x, y = DefaultCircle.y}, Sprite = {x = DefaultButton.x/1.35, y = DefaultButton.y/1.35}}
 | |
| 		end
 | |
| 	end)
 | |
| end
 | |
| 
 | |
| local function HoveredButton()
 | |
| 	local x,y = GetCursor()
 | |
| 	for k,v in pairs(Buttons) do
 | |
| 		local Distance = Distance(v.x+0.005, v.y+0.025, x, y)
 | |
| 		if Distance < 0.025 then
 | |
| 			Text(Config.GUI.Position.x, Config.GUI.Position.y-0.10, 0.3, v.Text, false, false, true)
 | |
| 			Text(Config.GUI.Position.x, Config.GUI.Position.y-0.08, 0.22, v.Desc, {210,210,210}, false, true, {x = 0.1, y = 0.2})
 | |
| 		end
 | |
| 	end
 | |
| 	for k,v in pairs(ExtraButtons) do
 | |
| 		if v.Enabled then
 | |
| 			local Distance = Distance(Config.GUI.Position.x+v.OffsetX+0.005, Config.GUI.Position.y+v.OffsetY+0.025, x, y)
 | |
| 			local ShouldDisplay = true
 | |
| 			if v.SpriteFunc then
 | |
| 				local SpriteVar = v.SpriteFunc()
 | |
| 				if SpriteVar then
 | |
| 					ShouldDisplay = true
 | |
| 				else
 | |
| 					ShouldDisplay = false
 | |
| 				end
 | |
| 			end
 | |
| 			if ShouldDisplay then
 | |
| 				if Distance < 0.025 then
 | |
| 					Text(Config.GUI.Position.x, Config.GUI.Position.y-0.10, 0.3, v.Text, false, false, true)
 | |
| 					Text(Config.GUI.Position.x, Config.GUI.Position.y-0.08, 0.22, v.Desc, {210,210,210}, false, true, {x = 0.1, y = 0.2})
 | |
| 				end
 | |
| 			end
 | |
| 		end
 | |
| 	end
 | |
| 	local Distance = Distance(Config.GUI.Position.x+0.005, Config.GUI.Position.y+0.025, x, y)
 | |
| 	if Distance < 0.015 then
 | |
| 		Text(Config.GUI.Position.x, Config.GUI.Position.y-0.09, 0.3, Lang("Info"), false, false, true)
 | |
| 	end
 | |
| end
 | |
| 
 | |
| --[[
 | |
| 		This is the function that draws the GUI, im using native DrawSprites and Texts.
 | |
| 		Its not the most efficient thing ms wise, but it does the job pretty well, and i dont have to bother with NUI HTML stuff.
 | |
| 		If you have any performance tips, let me know.
 | |
| ]]--
 | |
| 
 | |
| local function DrawGUI()
 | |
| 	DisableControl() -- Disable control while GUI is active.
 | |
| 	HoveredButton()	 -- This checks if you are hovering a button, and if you are it displays name and description.
 | |
| 	local x, y, rx, ry = Config.GUI.Position.x, Config.GUI.Position.y, 0.1, 0.175
 | |
| 	for k,v in pairs(Buttons) do
 | |
| 		local Colour local Alpha
 | |
| 		if LastEquipped[FirstUpper(v.Sprite)] then
 | |
| 			Alpha = 180 Colour = {r=0,g=100,b=210,a=220}
 | |
| 		else 
 | |
| 			Alpha = 255 Colour = {r=0,g=0,b=0,a=255}
 | |
| 		end
 | |
| 		DrawSprite("dp_wheel", k.."", x, y, 0.4285, 0.7714, 0.0, Colour.r, Colour.g, Colour.b, Colour.a)
 | |
| 		local Button = DrawButton({	-- Lets draw the buttons!
 | |
| 			Alpha = Alpha,
 | |
| 			Colour = Colour,
 | |
| 			Rotation = v.Rotation,
 | |
| 			Size = v.Size,
 | |
| 			Sprite = v.Sprite,
 | |
| 			Text = v.Text,
 | |
| 			x = v.x, y = v.y,
 | |
| 			Rotation = v.Rotation,
 | |
| 		})
 | |
| 		if Button and not Cooldown then	-- If the button is clicked we execute the command, just like if the player typed it in chat.
 | |
| 			if v.Sprite == "gloves" then
 | |
| 				if not LastEquipped["Shirt"] then
 | |
| 					PushedButton(k)  ExecuteCommand(v.Command)  
 | |
| 				else
 | |
| 					Notify(Lang("NoShirtOn"))
 | |
| 				end
 | |
| 			else
 | |
| 				PushedButton(k)  ExecuteCommand(v.Command)  
 | |
| 			end
 | |
| 			
 | |
| 		end
 | |
| 	end
 | |
| 	for k,v in pairs(ExtraButtons) do
 | |
| 		if v.Enabled then
 | |
| 			local Colour local Alpha
 | |
| 			if LastEquipped[FirstUpper(v.Sprite)] then
 | |
| 				Alpha = 180 Colour = {r=0,g=100,b=210,a=220}
 | |
| 			else 
 | |
| 				Alpha = 255 Colour = {r=0,g=0,b=0,a=255}
 | |
| 			end
 | |
| 			local sprite = v.Sprite
 | |
| 			if v.SpriteFunc then
 | |
| 				local SpriteVar = v.SpriteFunc()
 | |
| 				if SpriteVar then
 | |
| 					sprite = SpriteVar
 | |
| 				else
 | |
| 					sprite = false
 | |
| 				end
 | |
| 			end
 | |
| 			if sprite then
 | |
| 				local Button = DrawButton({
 | |
| 					Alpha = Alpha,
 | |
| 					Colour = Colour,
 | |
| 					Shadow = true,
 | |
| 					Size = v.Size,
 | |
| 					Sprite = sprite,
 | |
| 					Text = v.Text,
 | |
| 					x = x + v.OffsetX,
 | |
| 					y = y + v.OffsetY,
 | |
| 					Rotation = v.Rotation,
 | |
| 				})
 | |
| 				if Button and not Cooldown then
 | |
| 					PushedButton(k, true, v.Rotate) ExecuteCommand(v.Command)  
 | |
| 				end
 | |
| 			end
 | |
| 		end
 | |
| 	end
 | |
| 	if Cooldown then Text(x, y+0.05, 0.28, Lang("PleaseWait"), false, false, true) end 		-- Cooldown indicator, if theres a cooldown we display a little text.
 | |
| 	local InfoButton = DrawButton({
 | |
| 		Alpha = 255,
 | |
| 		Colour = {r=0,g=0,b=0},
 | |
| 		Shadow = true,
 | |
| 		Size = {Circle = {x = 0.0345, y = 0.06}, Sprite = {x = 0.0234, y = 0.0425}},
 | |
| 		Sprite = "info",
 | |
| 		Text = Lang("Info"),
 | |
| 		x = x, y = y,
 | |
| 		Rotation = InfoButtonRot,
 | |
| 	})
 | |
| 	if InfoButton then 			
 | |
| 		PushedButton(k, true, true, true)										
 | |
| 		Notify(Lang("Information"))
 | |
| 		for k,v in pairs(LastEquipped) do log(k.." : "..json.encode(v)) end		-- If the info button is pressed we log all "LastEquipped" items, for debugging purposes.
 | |
| 	end
 | |
| end
 | |
| 
 | |
| local TextureDicts = {"dp_clothing", "dp_wheel"}
 | |
| Citizen.CreateThread(function()
 | |
| 	for k,v in pairs(TextureDicts) do while not HasStreamedTextureDictLoaded(v) do Wait(100) RequestStreamedTextureDict(v, true) end end
 | |
| 	GenerateTheButtons()
 | |
| 	while true do Wait(0)
 | |
| 		if not Config.GUI.Toggle then
 | |
| 			if IsControlPressed(1, Config.GUI.Key) then
 | |
| 				local Ped = PlayerPedId() 
 | |
| 				if Check(Ped) then MenuOpened = true end
 | |
| 			else MenuOpened = false end
 | |
| 			if IsControlJustPressed(1, Config.GUI.Key) then
 | |
| 				local Ped = PlayerPedId() 
 | |
| 				if Check(Ped) then SoundPlay("Open") SetCursorLocation(Config.GUI.Position.x, Config.GUI.Position.y) end
 | |
| 			elseif IsControlJustReleased(1, Config.GUI.Key) then
 | |
| 				if Check(Ped) then MenuOpened = false SoundPlay("Close") end
 | |
| 			end
 | |
| 		else
 | |
| 			if IsControlJustPressed(1, Config.GUI.Key) then
 | |
| 				local Ped = PlayerPedId() 
 | |
| 				if Check(Ped) then SoundPlay("Open") SetCursorLocation(Config.GUI.Position.x, Config.GUI.Position.y) MenuOpened = not MenuOpened end
 | |
| 			end
 | |
| 		end
 | |
| 		if MenuOpened then DrawGUI() end
 | |
| 		if Config.Debug then DrawDev() end
 | |
| 	end
 | |
| end) | 
