15 Commits

Author SHA1 Message Date
Michachatz 67b71a8912 Update README.md 2025-11-02 00:52:23 +01:00
Michachatz 81e777ae9c Update fxmanifest.lua 2025-11-02 00:40:28 +01:00
Michachatz acfc0b6232 Update config.lua 2025-11-02 00:39:49 +01:00
Michachatz d3ed042bdd Update tv.lua 2025-11-02 00:37:42 +01:00
Michachatz 081d452f49 Update main.js 2025-11-02 00:34:19 +01:00
Michachatz 969ce331e6 Update tv.lua 2025-11-02 00:32:54 +01:00
Michachatz 0f082b4114 Update main.lua 2025-11-02 00:32:30 +01:00
Michachatz 95ec3294b8 Update dui.lua 2025-11-02 00:31:41 +01:00
Michachatz 42152a844e Update cursor.lua 2025-11-02 00:31:19 +01:00
Michachatz f67f8496df Update main.lua 2025-11-02 00:26:00 +01:00
Michachatz ee703e04d1 Update README.md 2025-11-02 00:24:32 +01:00
Michachatz 54fae17c32 Update default URL for Dui object 2025-11-02 00:18:01 +01:00
Michachatz fc55ac2d27 Delete .github/FUNDING.yml 2025-11-02 00:11:38 +01:00
Michachatz f4d70a0741 Refactor main.js for improved readability 2025-11-02 00:10:28 +01:00
Michachatz 80b6fcf380 Update renderer link and clean up README content 2025-11-01 23:59:41 +01:00
9 changed files with 197 additions and 193 deletions
-1
View File
@@ -1 +0,0 @@
ko_fi: picklemods
+3 -8
View File
@@ -1,5 +1,4 @@
<div align='center'><img src='https://user-images.githubusercontent.com/111543470/198868741-d78353cf-0576-4f2e-8554-1f7e4ef4c986.png'/></div>
<div align='center'><h3><a href='https://picklemods.com/'>More Information & Scripts can be found here!</a></h3></div>
<div align='center'><img src='https://michatec.github.io/ptelevision_web/ptelevision.png'/></div>
## What is this?
@@ -16,12 +15,8 @@ With this resource, you will be able to do the following:
You will need the following for this script to work.
- [Ox Lib](https://github.com/overextended/ox_lib/releases) (works with any framework)
- [Ox Lib](https://github.com/CommunityOx/ox_lib/releases) (works with any framework)
- [Renderer](https://forum.cfx.re/t/release-generic-dui-2d-3d-renderer/131208) (works with any framework)
- [Renderer](https://github.com/Michatec/ptelevision/releases/tag/renderer_gfx) (works with any framework)
If you want to make a fork, please obtain permission with a valid reason.
## Need Support?
<a href='https://pickle-mods.tebex.io/contact'>Click here!</a>
+3 -3
View File
@@ -1,7 +1,7 @@
local scale = 1.5
local screenWidth = math.floor(1920 / scale)
local screenHeight = math.floor(1080 / scale)
shouldDraw = false
local shouldDraw = false
function SetInteractScreen(bool)
if (not shouldDraw and bool) then
@@ -19,7 +19,7 @@ function SetInteractScreen(bool)
local minY, maxY = ((h - (h / 2)) / 2), (h - (h / 4))
local totalY = minY - maxY
RequestTextureDictionary('fib_pc')
lib.requestStreamedTextureDict('fib_pc')
-- Update controls while active
while shouldDraw do
@@ -27,7 +27,7 @@ function SetInteractScreen(bool)
nY = GetControlNormal(0, 240) * screenHeight
DisableControlAction(0, 1, true) -- Disable looking horizontally
DisableControlAction(0, 2, true) -- Disable looking vertically
DisablePlayerFiring(PlayerPedId(), true) -- Disable weapon firing
DisablePlayerFiring(cache.ped, true) -- Disable weapon firing
DisableControlAction(0, 142, true) -- Disable aiming
DisableControlAction(0, 106, true) -- Disable in-game mouse controls
-- Update mouse position when changed
+5 -22
View File
@@ -12,28 +12,11 @@ function CreateNamedRenderTargetForModel(name, model)
return handle
end
function RequestTextureDictionary(dict)
RequestStreamedTextureDict(dict)
while not HasStreamedTextureDictLoaded(dict) do Wait(0) end
return dict
end
function LoadModel(model)
if not IsModelInCdimage(model) then return end
RequestModel(model)
while not HasModelLoaded(model) do Wait(0) end
return model
end
function RenderScaleformTV(renderTarget, scaleform, entity)
SetTextRenderId(renderTarget) -- set render target
Set_2dLayer(4)
SetScriptGfxDrawBehindPausemenu(1)
--DrawRect(0.5, 0.5, 1.0, 0.5, 255, 0, 0, 255); -- WOAH!
local coords = GetEntityCoords(entity)
local rot = GetEntityRotation(entity)
SetTextRenderId(renderTarget)
SetScriptGfxDrawOrder(4)
SetScriptGfxDrawBehindPausemenu(true)
DrawSprite("ptelevision_b_dict", "ptelevision_b_txd", 0.5, 0.5, 1.0, 1.0, 0.0, 255, 255, 255, 255)
SetTextRenderId(GetDefaultScriptRendertargetRenderId()) -- reset
SetScriptGfxDrawBehindPausemenu(0)
SetTextRenderId(GetDefaultScriptRendertargetRenderId())
SetScriptGfxDrawBehindPausemenu(false)
end
+8 -21
View File
@@ -1,4 +1,4 @@
DEFAULT_URL = "https://cfx-nui-ptelevision/html/index.html"
DEFAULT_URL = "https://michatec.github.io/ptelevision_web/index.html"
duiUrl = DEFAULT_URL
duiObj = nil
tvObj = nil
@@ -37,20 +37,9 @@ local height = 720
local sfHandle = nil
local txdHasBeenSet = false
function loadScaleform(scaleform)
local scaleformHandle = RequestScaleformMovie(scaleform)
while not HasScaleformMovieLoaded(scaleformHandle) do
scaleformHandle = RequestScaleformMovie(scaleform)
Citizen.Wait(0)
end
return scaleformHandle
end
function ShowScreen(data)
CURRENT_SCREEN = data
sfHandle = loadScaleform(sfName)
sfHandle = lib.requestScaleformMovie(sfName)
runtimeTxd = 'ptelevision_b_dict'
local txd = CreateRuntimeTxd('ptelevision_b_dict')
@@ -105,7 +94,7 @@ function ShowScreen(data)
SetVolume(coords, modelData.DefaultVolume)
end
while duiObj do
local pcoords = GetEntityCoords(PlayerPedId())
local pcoords = GetEntityCoords(cache.ped)
local dist = #(coords - pcoords)
SendDuiMessage(duiObj, json.encode({
setVolume = true,
@@ -129,7 +118,7 @@ end
function GetClosestScreen()
local objPool = GetGamePool('CObject')
local closest = {dist = -1}
local pcoords = GetEntityCoords(PlayerPedId())
local pcoords = GetEntityCoords(cache.ped)
for i=1, #objPool do
local entity = objPool[i]
local model = GetEntityModel(entity)
@@ -165,9 +154,9 @@ Citizen.CreateThread(function()
local wait = 2500
for i=1, #Locations do
local data = Locations[i]
local dist = #(GetEntityCoords(PlayerPedId()) - v3(data.Position))
local dist = #(GetEntityCoords(cache.ped) - v3(data.Position))
if not Locations[i].obj and dist < 20.0 then
LoadModel(data.Model)
lib.requestModel(data.Model)
Locations[i].obj = CreateObject(data.Model, data.Position.x, data.Position.y, data.Position.z)
SetEntityHeading(Locations[i].obj, data.Position.w)
FreezeEntityPosition(Locations[i].obj, true)
@@ -207,11 +196,9 @@ RegisterNetEvent("ptelevision:requestSync", function(coords, data)
end
end)
RegisterNUICallback("pageLoaded", function(cb)
RegisterNUICallback("pageLoaded", function(data, cb)
waitForLoad = false
if cb then cb() end
cb(1)
end)
AddEventHandler('onResourceStop', function(name)
+16 -13
View File
@@ -1,4 +1,4 @@
TelevisionsLocal = {}
local TelevisionsLocal = {}
function SetChannel(index)
TriggerServerEvent("ptelevision:event", CURRENT_SCREEN, "ptv_status", {
@@ -20,8 +20,8 @@ function GetChannelList()
channel = status.channel
end
for index,value in pairs(Channels) do
table.insert(channel_list, {index = index, url = value.url})
table.insert(menu_list, "Channel #" .. index .. " (".. value.name ..")")
channel_list[#channel_list+1] = {index = index, url = value.url}
menu_list[#menu_list+1] = "Channel #" .. index .. " (".. value.name ..")"
if channel ~= nil and channel == index then
current = #channel_list
end
@@ -59,11 +59,17 @@ end
function VideoMenu()
lib.hideMenu()
local input = lib.inputDialog('Video Player', {'URL:'})
local input = lib.inputDialog('Video Player', {
{ type = 'input', label = 'Video URL' },
{ type = 'checkbox', label = 'Loop Video' },
{ type = 'checkbox', label = 'Show Video Controls' }
})
if input then
TriggerServerEvent("ptelevision:event", CURRENT_SCREEN, "ptv_status", {
type = "play",
url = input[1]
url = input[1],
loop = input[2],
showControls = input[3]
})
end
Citizen.Wait(300)
@@ -95,10 +101,6 @@ function OpenTVMenu()
SetChannel(ChannelList.list[scrollIndex].index)
end
end,
onSelected = function(selected, scrollIndex, args)
end,
onClose = function(keyPressed)
end,
options = {
{label = 'Videos', description = 'Play a video or stream on the screen.'},
{label = 'Web Browser', description = 'Access the web via your TV.'},
@@ -185,7 +187,7 @@ RegisterNetEvent("ptelevision:event", function(data, index, key, value)
if (index) then
local event = value
if (event.type == "play") then
local data = { url = event.url }
local data = { url = event.url, loop = event.loop, showControls = event.showControls }
if (event.channel) then
data = Channels[event.channel]
data.channel = event.channel
@@ -219,8 +221,9 @@ end)
RegisterCommand('tv', function()
OpenTVMenu()
end)
end, false)
RegisterCommand("broadcast", function(source, args, raw)
RegisterCommand('broadcast', function()
BroadcastMenu()
end)
end, false)
+15
View File
@@ -120,6 +120,20 @@ Config.Models = { -- Any TV Models used on the map or in locations must be defin
Scale = 0.085,
Offset = vector3(-1.02, -0.055, 1.04)
},
[-240931727] = { --Casino Penthouse Theater Room
DefaultVolume = 0.5,
Range = 20.0,
Target = "tvscreen", -- Only use if prop has render-target name.
Scale = 0.085,
Offset = vector3(-1.02, -0.055, 1.04)
},
[`v_ilev_cin_screen`] = { --Cinema/Theater Screen
DefaultVolume = 0.5,
Range = 60.0,
Target = "cinscreen", -- Only use if prop has render-target name.
Scale = 0.085,
Offset = vector3(-1.02, -0.055, 1.04)
},
}
Config.Locations = { -- REMOVE ALL IF NOT USING ONESYNC, OR IT SHALL BREAK.
@@ -152,3 +166,4 @@ Config.Events = { -- Events for approving broadcasts / interactions (due to popu
cb()
end,
}
+3 -2
View File
@@ -1,7 +1,7 @@
fx_version "cerulean"
game "gta5"
author "Pickle Mods#0001"
version "v1.2.5"
author "Pickle Mods & Michatec"
version "v1.2.6"
ui_page "html/blank.html"
files {
@@ -30,3 +30,4 @@ server_scripts {
}
lua54 'yes'
+85 -64
View File
@@ -1,110 +1,127 @@
var player;
var playerData;
$(document).ready(function() {
$.post("https://ptelevision/pageLoaded", JSON.stringify({}))
})
function GetURLID(link) {
if (link == null) return;
let url = link.toString();
var regExp = /^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
var regExp =
/^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
var match = url.match(regExp);
if (match && match[2].length == 11) {
return { type: "youtube", id: match[2] };
}
else if (url.split("twitch.tv/").length > 1) {
} else if (url.split("twitch.tv/").length > 1) {
return { type: "twitch", id: url.split("twitch.tv/")[1] };
}
}
function ChannelDisplay(channel, channelFound) {
if (channel) {
var temp = 'CH<span style="font-size: 18pt !important;"> </span>'
var temp = 'CH<span style="font-size: 18pt !important;"> </span>';
if (channel > 9) {
temp += channel
temp += channel;
} else {
temp += "0" + channel;
}
else {
temp += ("0" + channel)
}
$("#overlay span").show()
$("#overlay span").html(temp)
}
else {
$("#overlay span").show()
$("#overlay span").html("")
$("#overlay span").show();
$("#overlay span").html(temp);
} else {
$("#overlay span").show();
$("#overlay span").html("");
}
if (channelFound) {
$("#tv-container").hide()
}
else {
$("#tv-container").show()
$("#tv-container").hide();
} else {
$("#tv-container").show();
}
}
function SetVideo(video_data) {
var url = video_data.url;
var channel = video_data.channel;
var data = GetURLID(url)
var loop = video_data.loop;
var showControls = Number(video_data.showControls);
var data = GetURLID(url);
playerData = data
playerData = data;
if (player) {
player.destroy()
player.destroy();
player = null;
}
if (data) {
if (data.type == "youtube") {
player = new YT.Player('twitch-embed', {
height: '100%',
width: '100%',
if (loop == true) {
player = new YT.Player("twitch-embed", {
height: "100%",
width: "100%",
videoId: data.id,
playerVars: {
'playsinline': 1,
playsinline: 1,
loop: 1,
playlist: data.id,
controls: showControls,
},
events: {
'onReady': function(event) {
onReady: function (event) {
event.target.playVideo();
event.target.seekTo(video_data.time)
event.target.seekTo(video_data.time);
},
'onStateChange': function(event) {
onStateChange: function (event) {
if (event.data == YT.PlayerState.PLAYING) {
event.target.unMute();
} else if (event.data == YT.PlayerState.PAUSED) {
}
else if (event.data == YT.PlayerState.PAUSED) {
}
}
},
},
});
} else {
player = new YT.Player("twitch-embed", {
height: "100%",
width: "100%",
videoId: data.id,
playerVars: {
playsinline: 1,
controls: showControls,
},
events: {
onReady: function (event) {
event.target.playVideo();
event.target.seekTo(video_data.time);
},
onStateChange: function (event) {
if (event.data == YT.PlayerState.PLAYING) {
event.target.unMute();
} else if (event.data == YT.PlayerState.PAUSED) {
}
},
},
});
}
else if (data.type == "twitch") {
} else if (data.type == "twitch") {
player = new Twitch.Player("twitch-embed", {
width: "100%",
height: "100%",
channel: data.id,
volume: 1.0
volume: 1.0,
});
player.addEventListener(Twitch.Embed.VIDEO_READY, function () {
player.setMuted(false);
});
}
$("#overlay span").hide()
$("#tv-container").hide()
$("#overlay span").hide();
$("#tv-container").hide();
}
if (channel) {
ChannelDisplay(channel, url)
ChannelDisplay(channel, url);
}
}
function SetVolume(volume) {
if (player && playerData && player.setVolume) {
if (playerData.type == "twitch") {
player.setMuted(false);
player.setVolume(volume / 100.0);
}
else if (playerData.type == "youtube") {
} else if (playerData.type == "youtube") {
player.unMute();
player.setVolume(volume);
}
@@ -112,33 +129,37 @@ function SetVolume(volume) {
}
function ShowNotification(channel, data) {
$("#tv-container").addClass("notify")
$("#tv-container div").addClass("notify")
var display = $('#tv-container').is(':visible')
$('#tv-container').show()
$("#tv-container div").html("Channel #" + channel + (data ? (" ("+data.name+")") : "") + " is now " + (data ? "live!" : "offline."))
$("#tv-container").addClass("notify");
$("#tv-container div").addClass("notify");
var display = $("#tv-container").is(":visible");
$("#tv-container").show();
$("#tv-container div").html(
"Channel #" +
channel +
(data ? " (" + data.name + ")" : "") +
" is now " +
(data ? "live!" : "offline.")
);
setTimeout(function () {
$("#tv-container").removeClass("notify")
$("#tv-container div").removeClass("notify")
$("#tv-container div").html("NO SIGNAL")
$("#tv-container").removeClass("notify");
$("#tv-container div").removeClass("notify");
$("#tv-container div").html("NO SIGNAL");
if (!display) {
$('#tv-container').hide()
$("#tv-container").hide();
}
}, 3500)
}, 3500);
}
window.addEventListener("message", function (ev) {
if (ev.data.setVideo) {
SetVideo(ev.data.data)
SetVideo(ev.data.data);
} else if (ev.data.setVolume) {
SetVolume(ev.data.data);
} else if (ev.data.showNotification) {
ShowNotification(ev.data.channel, ev.data.data);
}
else if (ev.data.setVolume) {
SetVolume(ev.data.data)
}
else if (ev.data.showNotification) {
ShowNotification(ev.data.channel, ev.data.data)
}
})
});
$(document).ready(function () {
ChannelDisplay()
})
ChannelDisplay();
});