1
0
Fork 0
forked from Simnation/Main

neue sachen

This commit is contained in:
Nordi98 2025-06-09 23:59:42 +02:00
parent e542e77789
commit b992cdcfef
119 changed files with 5522 additions and 0 deletions

Binary file not shown.

View file

@ -0,0 +1,4 @@
-- if you want this script for... lets say like only vip, edit this function.
function YourSpecialPermission()
return true
end

View file

@ -0,0 +1,119 @@
local cameras = {}
function CreateCamera(name, pos, rot, fov)
fov = fov or 50.0
rot = rot or vector3(0, 0, 0)
local cam = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", pos.x, pos.y, pos.z, rot.x, rot.y, rot.z, fov, false, 0)
local try = 0
while not DoesCamExist(cam) do
Wait(33)
end
local self = {}
self.cam = cam
self.attachedEntity = nil
self.position = pos
self.rotation = rot
self.fov = fov
self.name = name
self.lastPointTo = nil
self.changingPos = false
self.SetCoords = function(pos)
self.position = pos
SetCamCoord(self.cam, pos.x, pos.y, pos.z)
end
self.GetCoords = function()
return GetCamCoord(self.cam)
end
self.AttachCameraToEntity = function(entity, offSet)
if not offSet then
offSet = vector3(0, 0, 0)
end
self.attachedEntity = entity
AttachCamToEntity(self.cam, entity, offSet.x, offSet.y, offSet.z, true)
end
self.DeattachCameraFromEntity = function()
AttachCamToEntity(self.cam, 0, 0, 0, 0, true)
end
self.FocusOnCoords = function(pos)
self.lastPointTo = pos
PointCamAtCoord(self.cam, pos.x, pos.y, pos.z)
end
self.FocusOnEntity = function(entity, offSet)
PointCamAtEntity(self.cam, entity, offSet.x, offSet.y, offSet.z, true)
end
self.StopFocus = function()
StopCamPointing(self.cam)
end
self.SetRotation = function(rot)
SetCamRot(self.cam, rot.x, rot.y, rot.z, 2)
end
self.GetRotation = function()
return GetCamRot(self.cam, 2)
end
self.IsRendering = function()
return IsCamRendering(self.cam or -1)
end
self.SetCamFov = function(fov)
SetCamFov(self.cam, fov)
end
self.Render = function()
SetCamActive(self.cam, true)
RenderScriptCams(true, true, 1, true, true)
end
self.ChangeCam = function(newCam, duration)
duration = duration or 3000
SetCamActiveWithInterp(newCam, self.cam, duration, true, true)
end
self.Destroy = function()
SetCamActive(self.cam, false)
DestroyCam(self.cam)
cameras[name] = nil
end
self.GetCam = function()
return self.cam
end
self.IsChangingCamera = function()
return self.changingPos
end
self.ChangePosition = function(newPos, newPoint, newRot, duration)
newRot = newRot or vector3(0, 0, 0)
duration = duration or 4000
self.changingPos = true
local tempCam = CreateCamera(string.format('tempCam-%s', self.name), newPos, newRot, self.fov)
tempCam.Render()
self.ChangeCam(tempCam.cam, duration)
Citizen.Wait(duration)
tempCam.Destroy()
SetCamActiveWithInterp(tempCam.cam, self.cam, 0, true, true)
SetCamCoord(self.cam, newPoint.x, newPoint.y, newPoint.z)
SetCamFov(self.cam, self.fov)
SetCamRot(self.cam, newRot.x, newRot.y, newRot.z, 2)
self.changingPos = false
end
cameras[name] = self
return self
end
function StopRendering()
RenderScriptCams(false, false, 1, false, false)
end

View file

@ -0,0 +1,15 @@
-- adding suggestions messages for commands
CreateThread(function()
TriggerEvent('chat:addSuggestion', "/" .. Config.volumeCommand, _U("volume_info") or 'Will set a new volume for TV', {
{ name = _U("volume_argument") or "volume", help = "0-100" },
})
TriggerEvent('chat:addSuggestion', "/" .. Config.playUrl, _U("playlink_info") or 'Will play a custom URL in the TV.', {
{ name = "URL", help = _U("play_url_info") or "Your URL for website" },
})
end)
-- fetching cache
CreateThread(function()
TriggerServerEvent("rcore_television:fetchCache")
end)

View file

@ -0,0 +1,93 @@
-- will return true / false if player is looking at TV
function IsPlayerLookingAtTV()
return IsLookingAtTV
end
-- will return true / false if player is in TV menu
function IsPlayerInTVMenu()
return ViewingTvMenu
end
-- will return type of redirect from URL
--- @param URL string
function GetRedirectFromURL(URL)
for key, value in pairs(Config.CustomSupport) do
if string.match(URL, key) then
return value
end
end
return RedirectType.OTHER
end
-- will return true/false if hash is in config
--- @param hash int
function IsModelTelevision(hash)
return Config.resolution[hash] ~= nil
end
--- Will display help notification
--- @param msg string
--- @param thisFrame boolean
--- @param beep boolean
--- @param duration int
function ShowHelpNotification(msg, thisFrame, beep, duration)
AddTextEntry('rcore_Tv_help_msg', msg)
if thisFrame then
DisplayHelpTextThisFrame('rcore_Tv_help_msg', false)
else
if beep == nil then
beep = false
end
BeginTextCommandDisplayHelp('rcore_Tv_help_msg')
EndTextCommandDisplayHelp(0, false, beep, duration)
end
end
--- Formated help text to prevent dup code anywhere i need to call it.
--- @param time int
function displayHelp(time)
local text = _U("help")
text = text .. _U("tv_help_line_2")
text = text .. _U("tv_help_line_3")
text = text .. _U("tv_help_line_4")
text = text .. _U("tv_help_line_5")
text = text .. _U("tv_help_line_6")
if not Config.CustomNotification then
ShowHelpNotification(text, false, false, time)
else
if type(Config.CustomNotification) == "function" then
Config.CustomNotification(text)
end
end
end
--- Will register key action
--- @param fc function
--- @param uniqid string
--- @param description string
--- @param key string
--- @param inputDevice string
function RegisterKey(fc, uniqid, description, key, inputDevice)
if inputDevice == nil then
inputDevice = "keyboard"
end
RegisterCommand(uniqid .. key, fc, false)
RegisterKeyMapping(uniqid .. key, description, inputDevice, key)
end
--- Will send a print when debug is enabled
--- @param ... object
function Debug(...)
if Config.Debug then
print(...)
end
end
--- Will send a print when debug is enabled
--- @param ... object
function MegaDebug(...)
if Config.FunctionsDebug then
print("[Mega Debug]", ...)
end
end

View file

@ -0,0 +1,866 @@
Config = {}
-- 0 standalone
-- 1 ESX
-- 2 QBCore
Config.FrameWork = 0
-- 1 = raycast (whitedot in center of the screen)
-- 2 = E click on keyboard only.
Config.DetectorType = 2
-- Target type
-- 0 = In build target system
-- 1 = Q_Target
-- 2 = BT Target
-- 3 = QB Target
-- 4 = OX Target
Config.TargetZoneType = 0
-- i will leave this function open, just in case you had anticheat.
Config.SetPlayerInvisible = function()
--local ped = PlayerPedId()
--SetEntityLocallyInvisible(ped)
end
Config.QBCoreObject = "QBCore:GetObject"
-- is the script es_extended based?
Config.ESX_Object = "esx:getSharedObject"
-- event for player loaded
Config.EsxPlayerLoaded = "esx:playerLoaded"
-- event for setJob
Config.EsxSetJob = "esx:setJob"
-- event for player loaded
Config.OnPlayerLoaded = "QBCore:Client:OnPlayerLoaded"
-- event for setJob
Config.OnJobUpdate = "QBCore:Client:OnJobUpdate"
-- will enable debug print and stuff
Config.Debug = false
-- will type start and end of events + nui callbacks
Config.FunctionsDebug = false
-- Will print in what type of thing error has happened.. Example CreateThread, RegisterNetEvent, RegisterCommand, etc.
Config.GeneralDebug = false
-- a command to set volume for TV
Config.volumeCommand = "tvvolume"
-- a command to change TV channel
Config.playUrl = "playlink"
-- a key to open television
Config.keyOpenTV = "E"
-- a key to select program in TV menu
Config.keyToSelectProgram = "RETURN" -- is enter
-- a keys to leave TV menu
Config.keyToLeaveMenu = "BACK"
Config.secondKeyToLeaveMenu = "escape"
-- a keys to stop current TV program
Config.keyToStopChannel = "SPACE"
-- Default youtube playing volume
-- Only goes for youtube...
Config.defaultVolume = 40
-- i dont recommend to change this number
-- how far away TV can be visible
Config.visibleDistance = 10
-- if you want have whitelist to prevent troll links keep this on true.
-- i dont recommend turning this option off, people just can use
-- shortcut url and the system wont know that it is on blacklist etc.
Config.useWhitelist = true
-- Message list
-- the command for this is /streamertelevision
Config.Messages = {
["streamer_on"] = "Streamer mode is on. From now you will not hear any music/sound from any TV.",
["streamer_off"] = "Streamer mode is off. From now you will be able to watch any TV.",
}
-- list of scaleform to use to televison
-- the more there is = the more television can be active on single place
-- the hard limit should be 15? i think?
-- keep the value on false.
Config.ScaleFormLists = {
["television_scaleform_1"] = false,
["television_scaleform_2"] = false,
["television_scaleform_3"] = false,
["television_scaleform_4"] = false,
["television_scaleform_5"] = false,
["television_scaleform_6"] = false,
["television_scaleform_7"] = false,
}
-- what website are allowed to put on tv ?
Config.whitelisted = {
"youtube",
"youtu.be",
"twitch",
".mp3",
"wav",
"mp4",
"webm",
"ogg",
"ogv",
"kick",
"douyin",
"bilibili",
}
-- Black list urls
Config.blackListed = {
"pornhub",
"sex-slave",
"cryzysek"
}
function split(text, sep)
local sep, fields = sep or ":", {}
local pattern = string.format("([^%s]+)", sep)
text:gsub(pattern, function(c)
fields[#fields + 1] = c
end)
return fields
end
-- if you need complet redirect for some reason then you can do it here
Config.CompletRedirect = {
-- i have not found other solution how to play twitch from this, so redirect is one option for me now.
["twitch"] = function(url, time, volume)
local newUrl = split(url, "/")
newUrl = "https://player.twitch.tv/?channel=" .. newUrl[#newUrl] .. "&parent=localhost&volume=" .. ((volume or 30) / 100)
return newUrl
end,
["kick"] = function(url, time, volume)
return "https://proxy.rcore.cz/kick.html?url=" .. url .. "&volume=" .. ((volume or 30) / 100)
end,
--["youtube"] = function(url, time, volume)
-- return "https://rco.re/product/television/v2.html?url=" .. url .. "&volume=" .. (volume or 30) .. "&time=" .. (time or 0)
--end,
--["youtu.be"] = function(url, time, volume)
-- return "https://rco.re/product/television/v2.html?url=" .. url .. "&volume=" .. (volume or 30) .. "&time=" .. (time or 0)
--end,
}
-- will get called each second because I have not found better way.
Config.ClickOnScreen = {
["twitch"] = function(duiObj)
-- will accept the "i am over 18 hell yeah"
-- old position for the 18+ (leaving it here just in case it was added back)
--SendDuiMouseMove(duiObj, 870, 605)
--SendDuiMouseDown(duiObj, "left")
--SendDuiMouseUp(duiObj, "left")
-- another old twitch
--SendDuiMouseMove(duiObj, 784, 604)
--SendDuiMouseDown(duiObj, "left")
--SendDuiMouseUp(duiObj, "left")
SendDuiMouseMove(duiObj, 846, 630)
SendDuiMouseDown(duiObj, "left")
SendDuiMouseUp(duiObj, "left")
end,
}
-- if the pasted URL contains one of the words bellow it will redirect it to
-- html/support/DEFINED VALUE/index.html so you can make your own support
-- to another website.
Config.CustomSupport = {
-- youtube
["youtube"] = "youtube",
["youtu.be"] = "youtube",
-- sound
-- i do not recommend using .ogg there atleast small amout of video format that can be played.
-- also who uses ogg for music ? right ?
[".mp3"] = "music",
[".wav"] = "music",
-- videos
[".mp4"] = "video",
[".webm"] = "video",
[".ogg"] = "video",
[".ogv"] = "video",
-- douyin support
["douyin"] = "douyin",
-- bilibili support
["bilibili"] = "bilibili",
}
-- you can blacklist here the SendDUIMessage about player position for example
-- if you're streaming picture so there isnt any reason to send the DUI message about position right?
Config.IgnorePositionUpdateCustomSupport = {
["youtube"] = false,
["menu"] = true,
["other"] = true,
}
-- this will disable forever poping the scaleform at some point fivem update broke this
-- but to make sure I am leaving the option here just in case it wasnt working
-- for now it will ne enabled
-- false value = enabled poping
-- true value = disabled
Config.ScaleformPop = true
-- this will allow networked objects to be streamed on (possible that they can move)
-- this feature is in work-in-progress it can have some unwanted bugs!
Config.AllowNetworkedObjects = false
-- list of default videos for TV.. you have to manualy change it in html/menu.html aswell
Config.listVideos = {
[1] = {
name = "Flute Tune",
icon = "fa-solid fa-newspaper",
url = "https://www.youtube.com/watch?v=X2cl6_DVpFI"
},
[2] = {
name = "Video 2",
icon = "fas fa-cat",
url = ""
},
[3] = {
name = "Video 3",
icon = "fas fa-city",
url = ""
},
[4] = {
name = "Video 4",
icon = "fas fa-hourglass-half",
url = ""
},
[5] = {
name = "Video 5",
icon = "fas fa-grin-beam",
url = ""
},
[6] = {
name = "Video 6",
icon = "fas fa-skull-crossbones",
url = ""
},
}
function PlayWearAnimation()
local ped = PlayerPedId()
local dict, anim = "gestures@m@standing@casual", "gesture_damn"
RequestAnimDict(dict)
while not HasAnimDictLoaded(dict) do
Wait(33)
end
TaskPlayAnim(ped, dict, anim, 8.0, 1.0, -1, 48, 0.0, false, false, false)
end
-- this will create television at defined coords with default URL.
Config.PlayingTelevisionOnLocation = {
--["random_uniqid"] = {
-- ModelHash = GetHashKey("prop_tv_flat_michael"),
-- Position = vector3(0, 0, 0),
-- Heading = 180.0,
--
-- URL = "https://www.youtube.com/watch?v=oqwKTKbsINY", -- will ignore the whitelist / blacklist since only a dev can add this.
--
-- -- There is variable "time" which getting called in NUI / complet redirect, so should it count?
-- -- true = wont
-- -- false = will count
-- DisableCountTime = false,
-- DisableInteraction = true,
--},
["some_tv_uniq_id"] = {
ModelHash = GetHashKey("prop_tv_flat_michael"),
Position = vector3(459.02, -983.5, 31.2),
Heading = 180.0,
-- will add behind the url ?identifier=some_tv_uniq_id
AddIdentifierToURL = true,
URL = "nui://rcore_television/html/custom/menu/index.html", -- will ignore the whitelist / blacklist since only a dev can add this.
Job = {
["police"] = { "*" },
["ambulance"] = { "grade1", "grade2", "grade3" }
},
-- this table will get send to the DUI message, which mean you can build your custom html menu or whatever you would love to.
Items = {
[0] = {
Label = "Wear bulletproof vest",
CallBack = function()
SetPedArmour(PlayerPedId(), 100)
TriggerEvent('skinchanger:getSkin', function(skin)
skin.bproof_1 = 20
TriggerEvent('skinchanger:loadSkin', skin)
end)
PlayWearAnimation()
end,
CloseAfterUse = true,
},
[1] = {
Label = "Take it off",
CallBack = function()
SetPedArmour(PlayerPedId(), 0)
TriggerEvent('skinchanger:getSkin', function(skin)
skin.bproof_1 = -1
TriggerEvent('skinchanger:loadSkin', skin)
end)
PlayWearAnimation()
end,
CloseAfterUse = true,
},
},
-- There is variable "time" which getting called in NUI / complet redirect, so should it count?
-- true = wont
-- false = will count
DisableCountTime = true,
},
}
Config.ReplaceObjects = {
{
pos = vector3(-54.47, -1087.27, 27.27),
radius = 2.0,
originalModelHash = 1036195894,
newModelHash = GetHashKey("prop_tv_flat_01"),
}
}
-- this will create television on coords that can be used by other folks
Config.CreateTelevisionModelOnCoords = {
{
ModelHash = GetHashKey("prop_tv_flat_01"),
Position = vector3(-921.48, -1181.22, -0.38),
Heading = 300.00,
},
}
-- if this is set to true it will preload one scaleform of television if some users experiencing bad loading
Config.UsePreloaded = true
-- Do not switch to true use command /tveditor
Config.Editor = false
-- default open distance from the model
Config.DefaultOpenDistance = 1.5
-- i wouldn't recommend to change anything there unless you know what you're doing
Config.resolution = {
[1036195894] = {
['ScreenSize'] = vec3(0.000000, 0.000000, 0.000000),
['Job'] = nil,
['CameraOffSet'] = {
['y'] = -3.0,
['z'] = 0.35,
['rotationOffset'] = vec3(0.000000, 0.000000, 0.000000),
['x'] = 0.0
},
['distance'] = 10,
['distanceToOpen'] = 1.5,
['ScreenOffSet'] = vec3(-1.045570, -0.069395, 1.058675),
['ItemToOpen'] = nil
},
[1522819744] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(7.036000, 0.572270, 3.442090),
ScreenSize = vector3(0.767885, 0.027010, 0.0),
rotationOffset = vector3(0, 0, 0),
distanceToOpen = 10.0,
distance = 30.0,
CameraOffSet = {
x = 0.0,
y = 12.0,
z = 0.2,
rotationOffset = vector3(0, 0, 180),
},
},
[GetHashKey("ch_prop_ch_tv_rt_01a")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.090645, 1.413200, 0.885070),
ScreenSize = vector3(0.894370, 0.503975, 0.0),
rotationOffset = vector3(0, 0, 90), -- rotation of scaleform
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = -3.0,
y = 0.0,
z = 0.2,
rotationOffset = vector3(0, 0, 90), -- rotation of camera
},
},
[GetHashKey("prop_monitor_w_large")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(0.373000, -0.076500, 0.622000),
ScreenSize = vector3(-0.000685, -0.001575, 0),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.0,
y = -1.0,
z = 0.4,
},
},
[GetHashKey("apa_mp_h_str_avunitl_04")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.291720, -0.407225, 2.083020),
ScreenSize = vector3(0.081970, 0.046270, 0.0),
--ScreenOffSet = vector3(-0.335, -0.409, 2.074),
--ScreenSize = vector3(0.081, 0.047, 0.090),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.6,
y = -2.7,
z = 1.2,
},
},
[GetHashKey("prop_monitor_01b")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.240, -0.084, 0.449),
ScreenSize = vector3(0, 0, 0),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.05,
y = -1.0,
z = 0.1,
rotationOffset = vector3(0, 0, 0),
},
},
[GetHashKey("apa_mp_h_str_avunitl_01_b")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.471, -0.130, 1.941),
ScreenSize = vector3(0.075, 0.042, 0.038),
distanceToOpen = 3.0,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.5,
y = -3.0,
z = 1.20,
},
},
[GetHashKey("ex_prop_ex_tv_flat_01")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-1.049, -0.062, 1.072),
ScreenSize = vector3(-0.0, -0.0, -0.025),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.0,
y = -2.0,
z = 0.40,
},
},
[-1833573429] = {
['CameraOffSet'] = {
['rotationOffset'] = vec3(0.000000, 0.000000, 0.000000),
['x'] = 0.0,
['y'] = -5.0,
['z'] = -1.0
},
['distance'] = 10,
['distanceToOpen'] = 4.0,
['ScreenSize'] = vec3(0.020170, 0.024115, 0.000000),
['ScreenOffSet'] = vec3(-1.994405, -0.056000, 0.000000),
['Job'] = nil,
['ItemToOpen'] = nil
},
[GetHashKey("prop_huge_display_01")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-5.110, -0.105, 3.640),
ScreenSize = vector3(0.04, 0.025, 0.0),
distanceToOpen = 15.0,
distance = 30.0,
CameraOffSet = {
x = -0.6,
y = -15.9,
z = 1.0,
rotation = vector3(0, 0, 0),
},
},
[GetHashKey("prop_cs_tv_stand")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.552, -0.080, 1.553),
ScreenSize = vector3(0.0045, 0.004, 0.001),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.0,
y = -1.0,
z = 1.23,
},
},
[GetHashKey("v_ilev_cin_screen")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-6.967, -0.535, 2.821),
ScreenSize = vector3(-0.009, 0.057, 0),
distanceToOpen = 15.0,
distance = 30.0,
CameraOffSet = {
x = 0.15,
y = -10.7,
z = 0.5,
},
},
[GetHashKey("sm_prop_smug_tv_flat_01")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.682, -0.043, 0.978),
ScreenSize = vector3(-0.0045, -0.0025, -0.006),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.15,
y = -2.7,
z = 0.5,
},
},
[GetHashKey("prop_trev_tv_01")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.26, -0.01, 0.28),
ScreenSize = vector3(0.0035, 0.002, 0.0135),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.0,
y = -1.0,
z = 0.1,
},
},
[GetHashKey("prop_tv_02")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.20, -0.10, 0.19),
ScreenSize = vector3(0.005, 0.0, 0.0135),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.05,
y = -1.0,
z = 0.0,
},
},
[GetHashKey("prop_tv_03")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.35, -0.11, 0.22),
ScreenSize = vector3(0.008, 0.003, 0.0355),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.05,
y = -1.0,
z = 0.0,
},
},
[GetHashKey("prop_tv_03_overlay")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.36, -0.11, 0.21),
ScreenSize = vector3(0.0009, 0.0005, 0.036),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.05,
y = -1.0,
z = 0.0,
},
},
[GetHashKey("prop_tv_04")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(0, 0, 0),
ScreenSize = vector3(0, 0, 0),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.05,
y = -1.0,
z = 0.0,
},
},
[GetHashKey("prop_tv_06")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.34, -0.09, 0.25),
ScreenSize = vector3(0.0055, 0.0025, 0.0385),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.05,
y = -1.0,
z = 0.0,
},
},
[GetHashKey("prop_tv_flat_01_screen")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-1.04, -0.06, 1.06),
ScreenSize = vector3(-0.0055, -0.0035, 0.0735),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.15,
y = -2.7,
z = 0.5,
},
},
[GetHashKey("prop_tv_flat_02")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.55, -0.01, 0.57),
ScreenSize = vector3(0.00049, -0.0005, 0.073),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.05,
y = -1.5,
z = 0.25,
},
},
[GetHashKey("prop_tv_flat_02b")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.55, -0.01, 0.57),
ScreenSize = vector3(0.00049, -0.0005, 0.073),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.05,
y = -1.5,
z = 0.25,
},
},
[GetHashKey("prop_tv_flat_03")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.335, -0.008, 0.412),
ScreenSize = vector3(-0.0005, 0.0, 0.0745),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.05,
y = -1.0,
z = 0.2,
},
},
[GetHashKey("prop_tv_flat_03b")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.335, -0.065, 0.211),
ScreenSize = vector3(0.003, 0.002, 0.002),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.05,
y = -1.0,
z = 0.0,
},
},
[GetHashKey("apa_mp_h_str_avunits_01")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-1.012, -0.302, 2.085),
ScreenSize = vector3(0.023, 0.014, 0.004),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = -0.1,
y = -2.7,
z = 1.2,
},
},
[GetHashKey("hei_heist_str_avunitl_03")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-1.197, -0.372, 2.089),
ScreenSize = vector3(0.071, 0.037, 0.094),
distanceToOpen = Config.DefaultOpenDistance + 1.0,
distance = Config.visibleDistance,
CameraOffSet = {
x = -0.1,
y = -2.7,
z = 1.2,
},
},
[GetHashKey("prop_tv_flat_michael")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-0.711, -0.067, 0.441),
ScreenSize = vector3(0.0056, 0.0036, 0.0),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.15,
y = -2.7,
z = 0.1,
},
},
[GetHashKey("prop_tv_test")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(0, 0, 0),
ScreenSize = vector3(0, 0, 0),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.05,
y = -1.0,
z = 0.1,
},
},
[GetHashKey("xm_prop_x17_tv_flat_02")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-1.049, -0.049, 1.068),
ScreenSize = vector3(0, 0, 0),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.05,
y = -3.0,
z = 0.4,
},
},
-- i dont recommend using this.. i have no idea if this TV is on more location
-- than Michael house.. if there is just one TV then go ahead enable it.
[GetHashKey("des_tvsmash_start")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(0.096, -1.010, 0.940),
ScreenSize = vector3(0.009, 0.004, 0.004),
rotationOffset = vector3(0, 0, -90),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 2.7,
y = 0.1,
z = 0.4,
rotationOffset = vector3(0, 0, -90),
},
},
-- i dont recommend to enable this.. you need to swap model to get this working.
-- if you know what you're doing.. swap this model: v_ilev_mm_scre_off to this one v_ilev_mm_screen2
-- with function "CreateModelSwap"
[GetHashKey("v_ilev_mm_screen2")] = {
--Job = { ["police"] = {"*"}, },
--ItemToOpen = { "remote", "another item" },
ScreenOffSet = vector3(-1.544, 0.006, -0.098),
ScreenSize = vector3(0.040, 0.023, 0.002),
distanceToOpen = Config.DefaultOpenDistance,
distance = Config.visibleDistance,
CameraOffSet = {
x = 0.15,
y = -2.7,
z = -1.0,
},
},
}
-- Because many mappers like to resize television... There is the option for custom size...
Config.CustomScreenSizes = {
[GetHashKey("prop_tv_flat_01")] = {-- {
-- pos = vector3(-54.51, -1087.36, 27.26),
-- ScreenSize = vector3(0.10, 0.0, 0),
-- distanceToOpen = Config.DefaultOpenDistance,
-- },
},
[GetHashKey("prop_huge_display_01")] = {-- {
-- pos = vector3(-54.51, -1087.36, 27.26),
-- ScreenSize = vector3(0.0, 0.0, 0),
-- }
},
}
-- permission map
Config.PermissionGroup = {
ESX = {
-- group system that used to work on numbers only
[1] = {
1, 2, 3, 4, 5
},
-- group system that works on name
[2] = {
"helper", "mod", "admin", "superadmin",
},
},
QBCore = {
-- group system that works on ACE
[1] = {
"god", "admin", "mod",
},
}
}
Config.CommandPermissions = {
["tveditor"] = { 3, 4, 5, "admin", "superadmin", "god" },
}

View file

@ -0,0 +1,15 @@
TargetType = {
NO_TARGET = 0,
Q_TARGET = 1,
BT_TARGET = 2,
QB_TARGET = 3,
OX_TARGET = 4
}
TargetTypeResourceName = {
[TargetType.NO_TARGET] = "none",
[TargetType.Q_TARGET] = "qtarget",
[TargetType.BT_TARGET] = "bt-target",
[TargetType.QB_TARGET] = "qb-target",
[TargetType.OX_TARGET] = "ox_target"
}

View file

@ -0,0 +1,32 @@
RegisterNUICallback("menuloaded", function(data_, cb)
local data = TelevisionCache[data_.identifier]
local items = Config.PlayingTelevisionOnLocation[data_.identifier].Items
local duiObj = data.duiObj
local active = true
for k, v in pairs(items) do
local itemData = Deepcopy(v)
itemData.CallBack = nil
itemData.identifier = k
itemData.active = active
active = false
DuiMessage(duiObj, {
type = "menuItems",
items = itemData,
})
end
if cb then cb('ok') end
end)
RegisterNUICallback("itemSelected", function(data, cb)
local dataItem = Config.PlayingTelevisionOnLocation[data.identifier]
if dataItem then
if dataItem.Items[data.item].CloseAfterUse then
LeaveTelevisionMenu()
end
dataItem.Items[data.item].CallBack()
end
if cb then cb('ok') end
end)

View file

@ -0,0 +1 @@
INSERT INTO `items` (`name`, `label`, `weight`, `rare`, `can_remove`) VALUES ('remote', 'remote', '1', '0', '1')

View file

@ -0,0 +1,97 @@
fx_version 'cerulean'
games { 'gta5' }
version "2.1.4"
client_scripts {
"config.lua",
"const.lua",
"utils/shared.lua",
"Debug.lua",
"locales/*.lua",
"utils/client.lua",
"client/permission.lua",
"client/VIP.lua",
"client/init.lua",
"client/utils.lua",
"client/client_editable.lua",
"client/utils_editable.lua",
"client/create_television.lua",
"client/editor.lua",
"client/television_utils/volume.lua",
"client/render_scaleform.lua",
"client/link.lua",
"client/television_utils/menu.lua",
"client/camera.lua",
"client/television_utils/program.lua",
"client/events.lua",
"client/cache_event.lua",
"client/dui_events.lua",
"custom/client/*.lua"
}
server_scripts {
"config.lua",
"const.lua",
"utils/shared.lua",
"Debug.lua",
"locales/*.lua",
"utils/server.lua",
"server/*.lua",
}
ui_page "html/off.html"
files {
"html/*.mp4",
"html/*.html",
"html/*.js",
"html/support/**/*.*",
"html/js/*.js",
"html/css/*.css",
"html/css/img/*.png",
"html/css/img/*.jpg",
"html/menu/*.html",
"html/menu/*.js",
"html/menu/css/*.css",
"html/menu/css/img/*.jpg",
"html/menu/css/img/*.png",
"html/custom/**/*.*",
"html/custom/**/css/*.*",
"html/custom/**/js/*.*",
}
dependencies {
"tv_scaleform",
'/server:4752',
}
lua54 'yes'
escrow_ignore {
"config.lua",
"locales/*.lua",
"utils/*.lua",
"const.lua",
"custom/client/*.lua",
"custom/server/*.lua",
"server/server.lua",
"client/camera.lua",
"client/VIP.lua",
"client/client_editable.lua",
"client/utils_editable.lua",
}
dependency '/assetpacks'

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

View file

@ -0,0 +1,106 @@
#blackscreen{
background: black;
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
z-index: 999999;
}
.bounce-enter-active {
animation: bounce-in 0.5s;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.10);
}
100% {
transform: scale(1);
}
}
#offButton{
font-size: 32px;
position: absolute;
top: 6px;
right: 52px;
}
#off{
background: aliceblue;
position: absolute;
height: 50px;
width: 70px;
position: absolute;
top: 0;
right: 0;
z-index: 100;
}
#circle{
height: 75px;
width: 75px;
background-color: aliceblue;
border-radius: 50%;
display: inline-block;
position: absolute;
top: -25px;
right: 32px;
}
body {
background-image: url(./img/bg.jpg);
background-size: cover;
overflow: hidden;
}
#icon-size{
font-size: 47px;
padding: unset;
padding-bottom: 40px;
padding-top: 22px;
}
#menu{
margin: auto;
width: 89%;
}
#container{
height: 649px;
width: 871px;
margin: auto;
position: fixed;
top: 29%;
left: 27%;
}
.text{
font-family: Montserrat, sans-serif;
text-overflow: ellipsis;
font-size: 39px;
width: 100%;
position: relative;
bottom: 17px;
}
.box{
transition-duration: 500ms;
background: aliceblue;
float: left;
margin: 8px;
text-align: center;
height: 96px;
width: 100%;
}
.box.active {
z-index: 999 !important;
border-radius: 6px;
background: #b8dbfb;
}

View file

@ -0,0 +1,23 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="./css/tv-menu.css">
<link href="https://fonts.googleapis.com/css?family=Montserrat:600" rel="stylesheet">
<script src="./js/vue.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<div id = "blackscreen"> </div>
<div id = "container">
<div id = "menu">
<div class = "box" v-for="item, key in menuItems" v-bind:class="{ active: item.active }">
<p class = 'text'>{{item.Label}}</p>
</div>
</div>
</div>
</body>
</html>
<script src="./js/script.js" type="text/javascript"></script>

View file

@ -0,0 +1,71 @@
$("#blackscreen").fadeOut(1500);
var VueJS = new Vue({
el: '#container',
data:
{
menuItems: [],
},
})
function getQueryParams() {
var qs = window.location.search;
qs = qs.split('+').join(' ');
var params = {},
tokens,
re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
}
return params;
}
var activeIndex = 0;
function ChangeNumber(result){
if(result){
if(activeIndex + 1 == VueJS.menuItems.length) {
activeIndex = -1;
}
activeIndex ++;
}else{
if(activeIndex == 0){
activeIndex = VueJS.menuItems.length;
}
activeIndex --;
}
}
$(document).ready(function(){
var params = getQueryParams();
$.post('http://rcore_television/menuloaded', JSON.stringify({
identifier: params.identifier,
}));
window.addEventListener('message', function(event) {
var data = event.data;
if(data.type === "menuItems"){
VueJS.menuItems.push(data.items)
}
if(data.type === "enter"){
$.post('http://rcore_television/itemSelected', JSON.stringify({
identifier: params.identifier,
item: activeIndex,
}));
}
if(data.type === "direction_bottom"){
ChangeNumber(true)
for(var i = 0; i < VueJS.menuItems.length; i ++) VueJS.menuItems[i].active = false
VueJS.menuItems[activeIndex].active = true
}
if(data.type === "direction_top"){
ChangeNumber(false)
for(var i = 0; i < VueJS.menuItems.length; i ++) VueJS.menuItems[i].active = false
VueJS.menuItems[activeIndex].active = true
}
});
});

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,105 @@
function getQueryParams() {
var qs = window.location.search;
qs = qs.split('+').join(' ');
var params = {},
tokens,
re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
}
return params;
}
function updateFrame(){
var result = getQueryParams();
$("#black").css(
{
"max-width": "1920px",
"max-height": "1080px",
"top": "0",
"bottom": "0",
"left": "0",
"right": "0",
});
}
function editString(string){
var str = string.toLowerCase();
var res = str.split("/");
var final = res[res.length - 1];
final = final.replace(".mp3", " ");
final = final.replace(".wav", " ");
final = final.replace(".wma", " ");
final = final.replace(".wmv", " ");
final = final.replace(".aac", " ");
final = final.replace(".ac3", " ");
final = final.replace(".aif", " ");
final = final.replace(".ogg", " ");
final = final.replace("%20", " ");
final = final.replace("-", " ");
return final;
}
var MaxDistance = 10;
var max_volume = 0.5;
var TelevisionPos = [0,0,0];
var PlayerPos = [0,0,0];
$(document).ready(function(){
var result = getQueryParams();
$.post('http://rcore_television/loaded', JSON.stringify({
isMenu: false,
identifier: result.identifier,
}));
window.addEventListener('message', function(event) {
var data = event.data;
if(data.type === "rcore_tv_update_pos"){
PlayerPos = [data.x,data.y,data.z];
}
if(data.type === "rcore_tv_update_tv_pos"){
TelevisionPos = [data.x,data.y,data.z];
MaxDistance = data.MaxDistance;
max_volume = data.max_volume / 100;
}
if(data.type === "rcore_tv_update_tv_volume"){
max_volume = data.max_volume / 100;
}
});
});
//taken from xsound
//https://github.com/Xogy/xsound
function GetNewVolume()
{
var d_max = MaxDistance;
var d_now = BetweenCoords();
var vol = 0;
var distance = (d_now / d_max);
if (distance < 1)
{
distance = distance * 100;
var far_away = 100 - distance;
vol = (max_volume / 100) * far_away;
}
return vol;
}
function BetweenCoords()
{
var deltaX = PlayerPos[0] - TelevisionPos[0];
var deltaY = PlayerPos[1] - TelevisionPos[1];
var deltaZ = PlayerPos[2] - TelevisionPos[2];
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ);
return distance;
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,167 @@
var w = c.width = window.innerWidth,
h = c.height = window.innerHeight,
ctx = c.getContext( '2d' ),
minDist = 10,
maxDist = 30,
initialWidth = 10,
maxLines = 100,
initialLines = 4,
speed = 5,
lines = [],
frame = 0,
timeSinceLast = 0,
dirs = [
// straight x, y velocity
[ 0, 1 ],
[ 1, 0 ],
[ 0, -1 ],
[ -1, 0 ],
// diagonals, 0.7 = sin(PI/4) = cos(PI/4)
[ .7, .7 ],
[ .7, -.7 ],
[ -.7, .7 ],
[ -.7, -.7]
],
starter = { // starting parent line, just a pseudo line
x: w / 2,
y: h / 2,
vx: 0,
vy: 0,
width: initialWidth
};
function init() {
lines.length = 0;
for( var i = 0; i < initialLines; ++i )
lines.push( new Line( starter ) );
ctx.fillStyle = '#222';
ctx.fillRect( 0, 0, w, h );
// if you want a cookie ;)
// ctx.lineCap = 'round';
}
function getColor( x ) {
return 'hsl( hue, 80%, 50% )'.replace(
'hue', x / w * 360 + frame
);
}
function anim() {
window.requestAnimationFrame( anim );
++frame;
ctx.shadowBlur = 0;
ctx.fillStyle = 'rgba(0,0,0,.02)';
ctx.fillRect( 0, 0, w, h );
ctx.shadowBlur = .5;
for( var i = 0; i < lines.length; ++i )
if( lines[ i ].step() ) { // if true it's dead
lines.splice( i, 1 );
--i;
}
// spawn new
++timeSinceLast
if( lines.length < maxLines && timeSinceLast > 10 && Math.random() < .5 ) {
timeSinceLast = 0;
lines.push( new Line( starter ) );
// cover the middle;
ctx.fillStyle = ctx.shadowColor = getColor( starter.x );
ctx.beginPath();
ctx.arc( starter.x, starter.y, initialWidth, 0, Math.PI * 2 );
ctx.fill();
}
}
function Line( parent ) {
this.x = parent.x | 0;
this.y = parent.y | 0;
this.width = parent.width / 1.25;
do {
var dir = dirs[ ( Math.random() * dirs.length ) |0 ];
this.vx = dir[ 0 ];
this.vy = dir[ 1 ];
} while (
( this.vx === -parent.vx && this.vy === -parent.vy ) || ( this.vx === parent.vx && this.vy === parent.vy) );
this.vx *= speed;
this.vy *= speed;
this.dist = ( Math.random() * ( maxDist - minDist ) + minDist );
}
Line.prototype.step = function() {
var dead = false;
var prevX = this.x,
prevY = this.y;
this.x += this.vx;
this.y += this.vy;
--this.dist;
// kill if out of screen
if( this.x < 0 || this.x > w || this.y < 0 || this.y > h )
dead = true;
// make children :D
if( this.dist <= 0 && this.width > 1 ) {
// keep yo self, sometimes
this.dist = Math.random() * ( maxDist - minDist ) + minDist;
// add 2 children
if( lines.length < maxLines ) lines.push( new Line( this ) );
if( lines.length < maxLines && Math.random() < .5 ) lines.push( new Line( this ) );
// kill the poor thing
if( Math.random() < .2 ) dead = true;
}
ctx.strokeStyle = ctx.shadowColor = getColor( this.x );
ctx.beginPath();
ctx.lineWidth = this.width;
ctx.moveTo( this.x, this.y );
ctx.lineTo( prevX, prevY );
ctx.stroke();
if( dead ) return true
}
init();
anim();
window.addEventListener( 'resize', function() {
w = c.width = window.innerWidth;
h = c.height = window.innerHeight;
starter.x = w / 2;
starter.y = h / 2;
init();
} )

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<script src='./js/jquery.min.js'></script>
<script src="./js/functions.js"></script>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
</body>
<script>
var result = getQueryParams();
$.post('http://rcore_television/duiHasLoaded', JSON.stringify({
identifier: result.identifier,
url: window.location.search.split('&link=')[1],
}));
</script>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 632 KiB

View file

@ -0,0 +1,161 @@
#blackscreen{
background: black;
position: absolute;
height: 100%;
width: 100%;
top: 0;
left: 0;
z-index: 999999;
}
.bounce-enter-active {
animation: bounce-in 0.5s;
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.10);
}
100% {
transform: scale(1);
}
}
#offButton{
font-size: 32px;
position: absolute;
top: 6px;
right: 52px;
}
#off{
background: aliceblue;
position: absolute;
height: 50px;
width: 70px;
position: absolute;
top: 0;
right: 0;
z-index: 100;
}
#circle{
height: 75px;
width: 75px;
background-color: aliceblue;
border-radius: 50%;
display: inline-block;
position: absolute;
top: -25px;
right: 32px;
}
body {
background-image: url(./img/bg.jpg);
background-size: cover;
overflow: hidden;
}
#icon-size{
font-size: 47px;
padding: unset;
padding-bottom: 40px;
padding-top: 22px;
}
@media screen and (max-width: 768px) {
#menu {
max-height: 43vw;
max-width: 60vw;
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
margin: auto;
height: 100%;
width: 100%;
}
}
@media screen and (min-width: 768px) {
#menu{
max-height: 43vw;
max-width: 76vw;
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
margin: auto;
height: 100%;
width: 100%;
}
}
@media screen and (max-width: 768px) {
.text {
font-family: Montserrat, sans-serif;
text-overflow: ellipsis;
position: relative;
justify-content: center;
align-items: center;
font-size: 25px;
}
}
@media screen and (min-width: 768px) {
.text{
font-family: Montserrat, sans-serif;
height: 95px;
text-overflow: ellipsis;
font-size: 39px;
position: relative;
bottom: 83px;
width: 419px;
left: 26px;
display: flex;
justify-content: center;
align-items: center;
}
}
.box.active {
z-index: 999 !important;
border-radius: 17px;
background: #e0eefb;
transform: scale(1.25);
box-shadow: 1px 7px 63px 0px #000000;
}
@media screen and (min-width: 768px) {
.box{
transition-duration: 500ms;
background: aliceblue;
max-height: 160px;
max-width: 467px;
float: left;
margin: 8px;
text-align: center;
height: 100%;
width: 100%;
z-index: 9 !imporant;
}
}
@media screen and (max-width: 768px) {
.box {
transition-duration: 500ms;
background: aliceblue;
float: left;
margin: 8px;
text-align: center;
width: 100%;
z-index: 9 !imporant;
}
#icon-size{
display: none;
}
}

View file

@ -0,0 +1,30 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link rel="stylesheet" href="./css/tv-menu.css">
<link href="https://fonts.googleapis.com/css?family=Montserrat:800" rel="stylesheet">
<script src="../js/vue.min.js"></script>
<link rel="stylesheet" href="https://rco.re/fa/css/all.css">
<script src="https://rco.re/fa/js/all.js" crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
<body>
<div id = "blackscreen"> </div>
<div id = "off"><i id ="offButton" class="fas fa-power-off"></i></div>
<div id = "circle"></div>
<div id = "menu">
<div v-for="item, index in menuItems" class = 'box bounce-enter-active' v-bind:class="{ active: item.active }">
<i id = 'icon-size' v-bind:class='item.icon'></i>
<p class = 'text'>{{item.title}}</p>
</div>
</div>
</body>
</html>
<script src="./script.js" type="text/javascript"></script>

View file

@ -0,0 +1,51 @@
$("#blackscreen").fadeOut(1500);
var VueJS = new Vue({
el: '#menu',
data:
{
menuItems: [],
},
})
$(document).ready(function(){
$.post('http://rcore_television/loaded', JSON.stringify({
isMenu: true,
}));
window.addEventListener('message', function(event) {
var data = event.data;
if(data.type === "reset"){
VueJS.menuItems = [];
}
if(data.type === "rcore_tv_change"){
for(var i = 0; i < VueJS.menuItems.length; i ++) VueJS.menuItems[i].active = false;
for(var i = 0; i < VueJS.menuItems.length; i ++){
var menuData = VueJS.menuItems[i]
if(menuData.index == data.selected){
VueJS.menuItems[i].active = true;
break;
}
}
}
if(data.type === "rcore_tv_add_tv"){
VueJS.menuItems.push({
active: false,
icon: data.icon,
title: data.title,
index: data.index,
});
}
if(data.type === "active_first"){
for(var i = 0; i < VueJS.menuItems.length; i ++){
var menuData = VueJS.menuItems[i]
if(menuData.index == 1){
VueJS.menuItems[i].active = true;
break;
}
}
}
});
});

View file

@ -0,0 +1,75 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<script src="./js/jquery.min.js"></script>
<link rel="stylesheet" href="./css/bootstrap.min.css">
<script src="./bootstrap.min.js" ></script>
<title>Welcome traveler, hope you like this file. :) Here, have a cookie to your journey!</title>
<style>
.dot{
position: absolute;
top: 50%;
left: 50%;
width: 0.25vw;
height: 0.25vw;
background: white;
border-radius: 100%;
border-color: black;
border-style: solid;
box-sizing: unset !important;
}
</style>
</head>
<body style="background: transparent !important;">
<div class = "dot" style = "display:none;"></div>
<div class="modal fade" id="textboard" tabindex="-1" role="dialog" aria-hidden="true" data-keyboard="false"
data-backdrop="static">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="textboard_header">Result</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" onclick="Close()">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<form onkeydown="return event.key != 'Enter';">
<div class="form-group">
<textarea class="textarea" style="min-height: 28vw;min-width: 100%;"></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal" onclick="Close()">Close</button>
</div>
</div>
</div>
</div>
</body>
<script>
function Close(){
$("#textboard").modal("hide");
$.post('https://rcore_television/declined', JSON.stringify({}));
}
$(function(){
window.addEventListener('message', function(event) {
var item = event.data;
if(item.type === "showdot"){
$(".dot").show("slow");
}
if(item.type === "hidedot"){
$(".dot").hide("slow");
}
if(item.type === "display_for_copy"){
$('#textboard').modal("show");
$(".textarea").val(item.text);
}
})
});
</script>
</html>

View file

@ -0,0 +1,82 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<script src="/html/js/jquery.min.js"></script>
<link rel="stylesheet" href="./css.css">
<script src="/html/js/functions.js"></script>
<style>
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
background: black;
}
iframe {
position: absolute;
top: 0;
left: 1.5%;
width: 96.79%;
height: 100%;
border: none;
}
</style>
<head>
<meta charset="utf-8">
<title>rcore_television douyin support</title>
</head>
<body>
<iframe id ="frame" frameborder="0" referrerpolicy="unsafe-url" allowfullscreen></iframe>
</body>
</html>
<script>
function getQueryParams() {
var qs = window.location.search;
qs = qs.split('+').join(' ');
var params = {},
tokens,
re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
}
return params;
}
function extractVideoID(url) {
const regex = /\/(BV\w+)/;
const match = url.match(regex);
return match ? match[1] : null;
}
var result = getQueryParams();
var vol = Number(result.volume);
var time = Number(result.time);
$("#frame").attr("src", "https://player.bilibili.com/player.html?bvid=" + extractVideoID(result.url) + "&autoplay=1&high_quality=1&danmaku=0");
$('#frame').on("load", function() {
const iframe = document.getElementById("frame");
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
const interval = setInterval(() => {
const video = iframeDocument.querySelector("video");
if (video !== null) {
clearInterval(interval);
setInterval(() => {
video.volume = GetNewVolume();
}, 100);
video.addEventListener("loadedmetadata", () => {
video.play();
video.currentTime = time;
$.post('http://rcore_television/updatePos', JSON.stringify({
identifier: result.identifier,
}));
});
}
}, 50);
});
</script>

View file

@ -0,0 +1,77 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<script src="/html/js/jquery.min.js"></script>
<link rel="stylesheet" href="./css.css">
<script src="/html/js/functions.js"></script>
<style>
body, html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
overflow: hidden;
background: black;
}
iframe {
position: absolute;
top: 0;
left: 1.5%;
width: 96.79%;
height: 100%;
border: none;
}
</style>
<head>
<meta charset="utf-8">
<title>rcore_television douyin support</title>
</head>
<body>
<iframe id ="frame" frameborder="0" referrerpolicy="unsafe-url" allowfullscreen></iframe>
</body>
</html>
<script>
function getQueryParams() {
var qs = window.location.search;
qs = qs.split('+').join(' ');
var params = {},
tokens,
re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])] = decodeURIComponent(tokens[2]);
}
return params;
}
var result = getQueryParams();
var vol = Number(result.volume);
var time = Number(result.time);
$("#frame").attr("src", "https://open.douyin.com/player/video?vid="+ result.url.split("/").pop() +"&autoplay=1")
$('#frame').on("load", function() {
const iframe = document.getElementById("frame");
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
const interval = setInterval(() => {
const video = iframeDocument.querySelector("video");
if (video !== null) {
clearInterval(interval);
setInterval(() => {
video.volume = GetNewVolume();
}, 100);
video.addEventListener("loadedmetadata", () => {
video.play();
video.currentTime = time;
$.post('http://rcore_television/updatePos', JSON.stringify({
identifier: result.identifier,
}));
});
}
}, 50);
});
</script>

View file

@ -0,0 +1,26 @@
.centered {
position: absolute;
top:275px;
bottom: 0;
left: 68px;
right: 0;
margin: auto;
width: 100%;
height: 100%;
max-width: 950px;
max-height: 370px;
}
#black iframe{
width: 100%;
height: 100%;
}
canvas {
position: absolute;
top: 0;
left: 0;
background-color: black;
}

View file

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<script src='/html/js/jquery.min.js'></script>
<script src="/html/js/howler.min.js" type="text/javascript"></script>
<script src="/html/js/prefixfree.min.js"></script>
<script src="/html/js/functions.js"></script>
<link rel="stylesheet" href="./css.css">
<head>
<meta charset="utf-8">
<title>rcore_television audio support</title>
</head>
<body style="background-color: black;">
<div id = "black" class = "centered">
<canvas id="c"></canvas>
</div>
</body>
</html>
<script src="/html/js/visualizer.js"></script>
<script>
var result = getQueryParams();
var howl = null;
updateFrame();
$( document ).ready(function() {
howl = new Howl({
src: [result.url],
loop: false,
format: ['mp3'],
volume: 0,
autoplay: true,
onplay: function() {
$.post('http://rcore_television/updatePos', JSON.stringify({
identifier: result.identifier,
}));
this.seek(result.time);
setTimeout(UpdatVolume, 70);
},
});
});
function UpdatVolume(){
if(howl){
howl.volume(GetNewVolume());
}
setTimeout(UpdatVolume, 70);
}
</script>

View file

@ -0,0 +1,22 @@
body {
background: black;
}
.centered {
position: absolute;
top:275px;
bottom: 0;
left: 68px;
right: 0;
margin: auto;
width: 100%;
height: 100%;
max-width: 950px;
max-height: 370px;
}
#black iframe{
width: 100%;
height: 100%;
}

View file

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<script src="/html/js/jquery.min.js"></script>
<script src="/html/js/functions.js"></script>
<link rel="stylesheet" href="./css.css">
<head>
<meta charset="utf-8">
<title>rcore_television other support</title>
</head>
<body>
<div id = "black" class = "centered">
</div>
</body>
</html>
<script>
var result = getQueryParams();
updateFrame();
$("#black").append("<iframe src='"+ result.url +"'></iframe>");
</script>

View file

@ -0,0 +1,23 @@
### Function list
------------
- getQueryParams() will return array list
```
url
volume
time
```
- Usage:
```javascript
var result = getQueryParams();
alert(result.url);
```
<br>
- updateFrame() <br> Will update the container to the resolution of TV from config<br>
it is important to always call it or the TV might be too big to fit the screen.
------------

View file

@ -0,0 +1,27 @@
body{
background-color: black;
}
video{
height: 100%;
width: 100%;
}
.centered {
position: absolute;
top:275px;
bottom: 0;
left: 68px;
right: 0;
margin: auto;
width: 100%;
height: 100%;
max-width: 950px;
max-height: 370px;
}
#black iframe{
width: 100%;
height: 100%;
}

View file

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<script src="/html/js/jquery.min.js"></script>
<script src="https://embed.twitch.tv/embed/v1.js"></script>
<script src="/html/js/functions.js"></script>
<link rel="stylesheet" href="./css.css">
<head>
<meta charset="utf-8">
<title>rcore_television twitch support</title>
</head>
<body >
<div id = "black" class = "centered">
</div>
</body>
</html>
<script>
var result = getQueryParams();
updateFrame();
var player = new Twitch.Embed("black", {
width: '100%',
height: '100%',
channel: result.url.replace("https://www.twitch.tv/", ""),
parent: ["localhost:13172"]
});
player.setVolume(result.volume);
</script>

View file

@ -0,0 +1,59 @@
body{
background-color: black;
}
#main-video {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 100;
}
#blurred-video {
left: 50%;
position: absolute;
top: 50%;
transform: translate(-50%, -50%);
filter: blur(15px);
width: 100%;
}
.centered {
position: absolute;
top:275px;
bottom: 0;
left: 68px;
right: 0;
margin: auto;
width: 100%;
height: 100%;
max-width: 950px;
max-height: 370px;
}
#black iframe{
width: 100%;
height: 100%;
}
::-webkit-scrollbar {
display: none;
}
video::-webkit-media-controls {
display: none;
}
/* Could Use thise as well for Individual Controls */
video::-webkit-media-controls-play-button {}
video::-webkit-media-controls-volume-slider {}
video::-webkit-media-controls-mute-button {}
video::-webkit-media-controls-timeline {}
video::-webkit-media-controls-current-time-display {}

View file

@ -0,0 +1,65 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<script src='/html/js/jquery.min.js'></script>
<script src="/html/js/functions.js"></script>
<link rel="stylesheet" href="./css.css">
<head>
<meta charset="utf-8">
<title>rcore_television video support</title>
</head>
<body>
<div>
<video id = "main-video" preload="none" onplay="updateTime(1)" controls autoplay>
<source id = "main-video-source">
</video>
<video id = "blurred-video" preload="none" onplay="updateTime(2)" onloadstart="this.volume=0.0" controls autoplay>
<source id = "blurred-video-source">
</video>
</div>
</body>
</html>
<script>
var result = getQueryParams();
var vol = result.volume;
var time = result.time;
updateFrame();
$( document ).ready(function() {
$("#main-video-source").attr("src", result.url);
$("#main-video")[0].load();
$('#main-video').trigger('play');
$("#blurred-video-source").attr("src", result.url);
$("#blurred-video")[0].load();
$('#blurred-video').trigger('play');
});
function updateTime(video){
if(video == 1){
var player = $("#main-video").get(0);
player.currentTime = time;
player.volume = 0;
setTimeout(UpdatVolume, 100);
}
if(video == 2){
var blurredVideo = $("#blurred-video").get(0);
blurredVideo.currentTime = time;
blurredVideo.volume = 0;
}
$.post('http://rcore_television/updatePos', JSON.stringify({
identifier: result.identifier,
}));
}
function UpdatVolume(){
var player = $("#main-video").get(0);
player.volume = GetNewVolume();
setTimeout(UpdatVolume, 100);
}
</script>

View file

@ -0,0 +1,19 @@
body{
background-color: black;
}
.centered {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
width: -webkit-fill-available;
height: -webkit-fill-available;
overflow: hidden;
}
#black iframe{
width: 100%;
height: 100%;
}

View file

@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en" dir="ltr">
<script src="/html/js/jquery.min.js"></script>
<script src="https://s.ytimg.com/yts/jsbin/www-widgetapi-vflJJaNgk/www-widgetapi.js"></script>
<script src="https://www.youtube.com/iframe_api"></script>
<script src="/html/js/functions.js"></script>
<script src="./yt-player.js"></script>
<link rel="stylesheet" href="./css.css">
<head>
<meta charset="utf-8">
<title>rcore_television youtube support</title>
</head>
<body>
<iframe id="frame" class="centered" frameborder="0"></iframe>
</body>
</html>
<script>
var result = getQueryParams();
var vol = Number(result.volume);
var time = Number(result.time);
$("#frame").attr("src", "https://proxy.rcore.cz/v2.html?url=" + result.url + "&volume=0.0");
$('#frame').on("load", function() {
const iframe = document.getElementById("frame");
const iframeDocument = iframe.contentDocument || iframe.contentWindow.document;
if (iframeDocument) {
const interval = setInterval(() => {
const blackIframe = iframeDocument.getElementById("black");
if (blackIframe) {
const blackIframeDocument = blackIframe.contentDocument || blackIframe.contentWindow.document;
const video = blackIframeDocument.querySelector("video");
if (video !== null) {
$.post('http://rcore_television/updatePos', JSON.stringify({
identifier: result.identifier,
}));
clearInterval(interval);
setInterval(() => {
video.volume = GetNewVolume();
}, 100);
video.addEventListener("loadedmetadata", () => {
video.currentTime = time;
});
}
}
}, 50);
}
});
</script>

View file

@ -0,0 +1,31 @@
var yPlayer = null;
function callMe(vol, time){
yPlayer.setVolume(vol);
yPlayer.playVideo();
yPlayer.seekTo(time);
setTimeout(UpdatVolume, 100);
yPlayer.setVolume(0);
}
function getYoutubeUrlId(url)
{
var videoId = "";
if( url.indexOf("youtube") !== -1 ){
var urlParts = url.split("?v=");
videoId = urlParts[1].substring(0,11);
}
if( url.indexOf("youtu.be") !== -1 ){
var urlParts = url.replace("//", "").split("/");
videoId = urlParts[1].substring(0,11);
}
return videoId;
}
function UpdatVolume(){
if(yPlayer){
yPlayer.setVolume(GetNewVolume() * 100);
}
setTimeout(UpdatVolume, 100);
}

View file

@ -0,0 +1,38 @@
Locales = {
["help"] = "Television help\n",
["tv_help_line_2"] = "Use keys ~INPUT_CELLPHONE_UP~ ~INPUT_CELLPHONE_DOWN~ to switch default TV program\n",
["tv_help_line_3"] = "To start selected program press ~INPUT_CELLPHONE_SELECT~\n",
["tv_help_line_4"] = "To end current program press ~INPUT_DIVE~\n\n",
["tv_help_line_5"] = "To play custom video use command ~g~/playlink~w~\n\n",
["tv_help_line_6"] = "To change TV volume use command ~g~/tvvolume~w~\n",
["volume_changed"] = "You updated prefer TV volume to: %s",
["tvstation_changed"] = "You changed TV station to: %s",
["volume_invalid"] = "The volume has to be between 0-100",
["argument_has_to_be_number"] = "The volume has to be a number!",
["volume_info"] = "Will set a new volume for TV",
["volume_argument"] = "volume",
["playlink_info"] = "Will play a custom URL in the TV.",
["play_url_info"] = "Your URL for website",
["switch_to_menu"] = "Push ~INPUT_COVER~ button to open television menu",
["doesnt_have_remote"] = "You will need this/these item %s to open the TV!",
["cant_play_video"] = "You need to be in a TV menu to play video!",
["link_isnt_whitelisted"] = "You cant use this link ! It is not whitelisted!",
["blacklisted_link"] = "This link is blacklisted! Use other one please.",
["stopped_program"] = "You stopped the current TV program",
["not_vip"] = "You're not VIP to use a television!",
["target_label"] = "Open the TV",
["target_icon"] = "fas fa-gamepad",
["target_targeticon"] = "fas fa-gamepad",
}

View file

@ -0,0 +1,279 @@
ESX = nil
QBCore = nil
if Config.FrameWork == 1 then
ESX = GetEsxObject()
end
if Config.FrameWork == 2 then
QBCore = Config.GetQBCoreObject()
end
--- Will send a print when debug is enabled
--- @param ... object
function Debug(...)
if Config.Debug then
print(...)
end
end
TelevisionCache = {}
PlayerBucketCache = {}
RegisterNetEvent("rcore_television:stopTelevisionAtCoords", function(coords)
if not source then
print("Event: \"rcore_television:stopTelevisionAtCoords\" has to be called from client side only!")
end
local playerBucket = GetPlayerRoutingBucket(source)
if not TelevisionCache[playerBucket] then
TelevisionCache[playerBucket] = {}
end
for k, v in pairs(TelevisionCache[playerBucket]) do
if #(v.tvPos - coords) < 1.5 then
table.remove(TelevisionCache[playerBucket], k)
TriggerClientEvent("rcore_television:stopTelevisionAtCoords", -1, coords)
break
end
end
end)
RegisterNetEvent("rcore_television:fetchCache", function()
local playerBucket = GetPlayerRoutingBucket(source)
if not TelevisionCache[playerBucket] then
TelevisionCache[playerBucket] = {}
end
TriggerClientEvent("rcore_television:fetchCache", source, TelevisionCache[playerBucket])
end)
-- adding time thread
CreateThread(function()
while true do
Wait(1000)
for _, val in pairs(TelevisionCache) do
for _, v in pairs(val) do
if v.time then
v.time = v.time + 1
end
end
end
end
end)
-- updating bucket thread
CreateThread(function()
while true do
Wait(500)
for k, v in pairs(GetPlayers()) do
Wait(2)
local bucketID = GetPlayerRoutingBucket(k)
if PlayerBucketCache[k] ~= bucketID then
PlayerBucketCache[k] = bucketID
TriggerClientEvent(TriggerName("UpdatePlayerBucketID"), k, bucketID)
Debug("Updating player bucket ID cache", bucketID, "player ID", k)
end
end
end
end)
RegisterNetEvent("rcore_television:AddTelevisionToCache", function(data)
if not source then
print("Event: \"rcore_television:AddTelevisionToCache\" has to be called from client side only!")
end
local found = false
local key
local playerBucket = GetPlayerRoutingBucket(source)
if not TelevisionCache[playerBucket] then
TelevisionCache[playerBucket] = {}
end
for k, v in pairs(TelevisionCache[playerBucket]) do
if data.NetID then
if v.NetID == data.NetID then
found = true
key = k
break
end
end
if #(v.tvPos - data.tvPos) < 1.5 then
found = true
key = k
break
end
end
if not found then
table.insert(TelevisionCache[playerBucket], data)
TriggerClientEvent("rcore_television:AddTelevisionToCache", -1, data)
else
TelevisionCache[playerBucket][key].URL = data.URL
TelevisionCache[playerBucket][key].time = 0
TriggerClientEvent("rcore_television:UpdateTelevisionCache", -1, key, TelevisionCache[playerBucket][key])
end
end)
registerCallback(TriggerName("DoesPlayerHaveCertain"), function(source, cb, items)
if Config.FrameWork == 1 then
local xPlayer = ESX.GetPlayerFromId(source)
for k, v in pairs(items) do
local item = xPlayer.getInventoryItem(v)
if item then
if item.count ~= 0 then
cb(true)
return
end
end
end
cb(false)
end
if Config.FrameWork == 2 then
local qbPlayer = QBCore.Functions.GetPlayer(source)
for k, v in pairs(items) do
if qbPlayer.Functions.GetItemByName(v) then
cb(true)
return
end
end
cb(false)
end
end)
local SharedGroups = {}
if Config.Framework ~= 2 then
SharedGroups = {
"user", "mod", "moderator", "help", "helper", "admin", "superadmin", "god",
}
else
SharedGroups = QBCore.Config.Server.Permissions
end
for k, v in pairs(SharedGroups) do
ExecuteCommand(("add_ace qbcore.%s rcore_perm.%s allow"):format(v, v))
ExecuteCommand(("add_ace group.%s rcore_perm.%s allow"):format(v, v))
end
local grantedPermission = {}
function IsPlayerInGroup(source, groups, acePermission)
if grantedPermission[source] then
return true
end
if acePermission then
if IsPlayerAceAllowed(source, acePermission) then
return true
end
end
if Config.FrameWork == 2 then
for k, v in pairs(groups) do
if IsPlayerAceAllowed(source, "rcore_perm." .. v) then
return true
end
end
end
if Config.FrameWork == 1 then
local xPlayer = ESX.GetPlayerFromId(source)
if xPlayer then
for k, v in pairs(groups) do
if xPlayer.getPermissions then
if Config.PermissionGroup.ESX[1][xPlayer.getPermissions()] then
return true
end
end
if xPlayer.getGroup then
if Config.PermissionGroup.ESX[2][xPlayer.getGroup()] then
return true
end
end
end
end
end
return false
end
registerCallback(TriggerName("hasPermission"), function(source, cb, groups, acePermission)
cb(IsPlayerInGroup(source, groups, acePermission))
end)
CreateThread(function()
local deepCopy = function(object)
local lookup_table = {}
local function _copy(object)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local new_table = {}
lookup_table[object] = new_table
for index, value in pairs(object) do
new_table[_copy(index)] = _copy(value)
end
return setmetatable(new_table, getmetatable(object))
end
return _copy(object)
end
local permissionGroup = deepCopy(Config.PermissionGroup)
for framework, v in pairs(permissionGroup) do
for index, _v in pairs(v) do
for key, permissions in pairs(_v) do
Config.PermissionGroup[framework][index][key] = nil
Config.PermissionGroup[framework][index][permissions] = true
end
end
end
end)
RegisterCommand('tvgrantpermission', function(source, args, user)
if source ~= 0 then
TriggerClientEvent('chat:addMessage', source, { args = { "This command can be used ONLY in console! The 'Live Console' in txadmin panel." } })
return
end
if args[1] == nil then
print("Please use command: /tvgrantpermission [player ID] | Example: /tvgrantpermission 7")
return
end
local sourceNumber = tonumber(args[1])
if not sourceNumber then
print("The player ID has to be number!")
return
end
if grantedPermission[sourceNumber] ~= nil then
print("This player has already temporary permission!")
return
end
grantedPermission[sourceNumber] = true
print("You granted temporary permission to the user with server ID: ", sourceNumber, "The permission last 30 minutes")
Wait(1000 * 60 * 30)
grantedPermission[sourceNumber] = nil
end)
RegisterCommand("televisionversion", function(source, args, rawCommand)
local frameworks = { [0] = "standlone", [1] = "esx", [2] = "qb-core" }
local detection = { [1] = "Raycast", [2] = "GetClosestObject" }
print("^3")
print("rcore_television")
print(string.format("^7framework: ^3%s", frameworks[Config.FrameWork]))
print(string.format("^7detection type: ^3%s", detection[Config.DetectorType]))
print(string.format("^7version: ^3%s", GetResourceMetadata(GetCurrentResourceName(), "version")))
print("https://documentation.rcore.cz/paid-resources/rcore_television")
print("^7")
end, false)

View file

@ -0,0 +1,150 @@
------------------------------------------------------------------
-- Need to be changed to your framework, for now default is ESX --
------------------------------------------------------------------
if Config.FrameWork == 1 then
local PlayerData = {}
ESX = GetEsxObject()
CreateThread(function()
if ESX then
if ESX.IsPlayerLoaded() then
PlayerData = ESX.GetPlayerData()
end
end
end)
RegisterNetEvent(Config.EsxPlayerLoaded or 'esx:playerLoaded', function(xPlayer)
PlayerData = xPlayer
end)
RegisterNetEvent(Config.EsxSetJob or 'esx:setJob', function(job)
PlayerData.job = job
end)
function IsAtJob(name, grade)
if not PlayerData or not PlayerData.job then
print("ERROR", "the job for ESX is nil value please check if your events are correct.")
return true
end
if grade and grade == "*" and PlayerData.job.name == name then
return true
end
if grade then
return PlayerData.job.name == name and PlayerData.job.grade_name == grade
end
return PlayerData.job.name == name
end
end
if Config.FrameWork == 2 then
local PlayerData = {}
local QBCore
function UpdatePlayerDataForQBCore()
local pData = QBCore.Functions.GetPlayerData()
local jobName = "none"
local gradeName = "none"
if pData.job then
jobName = pData.job.name or "none"
if pData.job.grade then
gradeName = pData.job.grade.name
end
end
PlayerData = {
job = {
name = jobName,
grade_name = gradeName,
}
}
end
CreateThread(function()
QBCore = Config.GetQBCoreObject()
if QBCore and QBCore.Functions.GetPlayerData() then
UpdatePlayerDataForQBCore()
end
end)
-- Will load player job + update markers
RegisterNetEvent(Config.OnPlayerLoaded, function()
UpdatePlayerDataForQBCore()
end)
-- Will load player job + update markers
RegisterNetEvent(Config.OnJobUpdate, function()
UpdatePlayerDataForQBCore()
end)
function IsAtJob(name, grade)
if not PlayerData or not PlayerData.job then
print("ERROR", "the job for QBcore is nil value please check if your events are correct.")
return true
end
if grade and grade == "*" and PlayerData.job.name == name then
return true
end
if grade then
return PlayerData.job.name == name and PlayerData.job.grade_name == grade
end
return PlayerData.job.name == name
end
end
if Config.FrameWork == 0 then
function IsAtJob(name, grade)
return true
end
end
------------------------
-- Optional to change --
------------------------
-- This will allow to open any TV if true, other players wont be able to interact but will albe to see
-- what is playing on TVscreen
function CustomPermission()
return true
end
function showNotification(text)
SetNotificationTextEntry('STRING')
AddTextComponentString(text)
DrawNotification(0, 1)
end
RegisterNetEvent('rcore_tv:notification')
AddEventHandler('rcore_tv:notification', showNotification)
--- call callback
---TAKEN FROM rcore framework
---https://githu.com/Isigar/relisoft_core
---https://docs.rcore.cz
local clientCallbacks = {}
local currentRequest = 0
function callCallback(name, cb, ...)
clientCallbacks[currentRequest] = cb
TriggerServerEvent(TriggerName('callCallback'), name, currentRequest, ...)
if currentRequest < 65535 then
currentRequest = currentRequest + 1
else
currentRequest = 0
end
end
exports('callCallback', callCallback)
RegisterNetEvent(TriggerName('callback'))
AddEventHandler(TriggerName('callback'), function(requestId, ...)
if clientCallbacks[requestId] == nil then
return
end
clientCallbacks[requestId](...)
end)

View file

@ -0,0 +1,65 @@
------------------------------------------------------------------
-- Need to be changed to your framework, for now default is ESX --
------------------------------------------------------------------
ESX = nil
QBCore = nil
if Config.FrameWork == 1 then
ESX = GetEsxObject()
end
if Config.FrameWork == 2 then
QBCore = Config.GetQBCoreObject()
end
function HavePlayerControler(source, itemName)
if Config.FrameWork == 1 then
local sourceItem = ESX.GetPlayerFromId(source).getInventoryItem(itemName)
return (sourceItem ~= nil and sourceItem.count ~= 0)
end
if Config.FrameWork == 2 then
local qbPlayer = QBCore.Functions.GetPlayer(source)
local item = qbPlayer.Functions.GetItemByName(itemName) or {}
local ItemInfo = {
name = itemName,
count = item.amount or 0,
label = item.label or "none",
weight = item.weight or 0,
usable = item.useable or false,
rare = false,
canRemove = false,
}
return ItemInfo.count ~= 0
end
return true
end
--- call callback
---TAKEN FROM rcore framework
---https://githu.com/Isigar/relisoft_core
---https://docs.rcore.cz
local serverCallbacks = {}
local callbacksRequestsHistory = {}
function registerCallback(cbName, callback)
serverCallbacks[cbName] = callback
end
RegisterNetEvent(TriggerName('callCallback'))
AddEventHandler(TriggerName('callCallback'), function(name, requestId, ...)
local source = source
if serverCallbacks[name] == nil then
return
end
callbacksRequestsHistory[requestId] = {
name = name,
source = source,
}
local call = serverCallbacks[name]
call(source, function(...)
TriggerClientEvent(TriggerName('callback'), source, requestId, ...)
end, ...)
end)

View file

@ -0,0 +1,241 @@
function GetEsxObject()
local promise_ = promise:new()
local obj
xpcall(function()
obj = exports['es_extended']['getSharedObject']()
promise_:resolve(obj)
end, function(error)
TriggerEvent(Config.ESX_Object or "esx:getSharedObject", function(module)
obj = module
promise_:resolve(obj)
end)
end)
Citizen.Await(obj)
return obj
end
Config.GetQBCoreObject = function()
local promise_ = promise:new()
local obj
xpcall(function()
obj = exports['qb-core']['GetCoreObject']()
promise_:resolve(obj)
end, function(error)
xpcall(function()
obj = exports['qb-core']['GetSharedObject']()
promise_:resolve(obj)
end, function(error)
local QBCore = nil
local tries = 10
LoadQBCore = function()
if tries == 0 then
print("The QBCORE couldnt load any object! You need to correct the event / resource name for export!")
return
end
tries = tries - 1
if QBCore == nil then
SetTimeout(100, LoadQBCore)
end
TriggerEvent(Config.QBCoreObject or "QBCore:GetObject", function(module)
QBCore = module
obj = QBCore
promise_:resolve(QBCore)
end)
end
LoadQBCore()
end)
end)
Citizen.Await(obj)
return obj
end
function DrawUIText(text, x, y)
SetTextFont(0)
SetTextScale(0.5, 0.5)
SetTextColour(255, 255, 255, 255)
SetTextOutline()
SetTextCentre(true)
BeginTextCommandDisplayText("STRING")
AddTextComponentSubstringPlayerName(text)
EndTextCommandDisplayText(x, y)
end
--- this is for translation
--- @param str string
--- @param ... parameters
function _U(str, ...)
if type(Locales) ~= "table" then
return string.format("Locales table doesnt exists! There is probably syntax error in the translation or the file is missing completely!\n", GetCurrentResourceName())
end
if not Locales[str] then
return string.format("[%s] There isnt such [%s] translation", GetCurrentResourceName(), str)
end
return string.format(Locales[str], ...)
end
--- Will return true/false
--- @param url string
function isWhitelisted(url)
url = string.lower(url)
for k, v in pairs(Config.whitelisted) do
if string.match(url, v) ~= nil then
return true
end
end
return false
end
--- Will return true/false
--- @param url string
function isBlackListed(url)
url = string.lower(url or "")
for k, v in pairs(Config.blackListed) do
if string.match(url, v) ~= nil then
return true
end
end
return false
end
--- Will return timestamp from youtube URL
--- @param url string
function GetTimeFromUrl(url)
local pattern = "t=([^#&\n\r]+)"
local _time = string.match(url, pattern)
if _time then
_time = _time.gsub(_time, "%D+", "")
_time = tonumber(_time)
else
_time = 0
end
return _time
end
--- trigger name
--- @param name string
function TriggerName(name)
return string.format('%s:%s', GetCurrentResourceName(), name)
end
-- Will deep copy table
--- @param orig table
function Deepcopy(orig)
local orig_type = type(orig)
local copy
if orig_type == 'table' then
copy = {}
for orig_key, orig_value in next, orig, nil do
copy[Deepcopy(orig_key)] = Deepcopy(orig_value)
end
setmetatable(copy, Deepcopy(getmetatable(orig)))
else
-- number, string, boolean, etc
copy = orig
end
return copy
end
-- will dump table
--- @param node table
--- @param printing boolean
function Dump(node, printing)
local cache, stack, output = {}, {}, {}
local depth = 1
local output_str = "{\n"
while true do
local size = 0
for k, v in pairs(node) do
size = size + 1
end
local cur_index = 1
for k, v in pairs(node) do
if (cache[node] == nil) or (cur_index >= cache[node]) then
if (string.find(output_str, "}", output_str:len())) then
output_str = output_str .. ",\n"
elseif not (string.find(output_str, "\n", output_str:len())) then
output_str = output_str .. "\n"
end
-- This is necessary for working with HUGE tables otherwise we run out of memory using concat on huge strings
table.insert(output, output_str)
output_str = ""
local key
if (type(k) == "number" or type(k) == "boolean") then
key = "[" .. tostring(k) .. "]"
else
key = "['" .. tostring(k) .. "']"
end
local isWhitelisted = false
if type(v) == "string" then
isWhitelisted = string.match(string.lower(v), "nil")
end
if (type(v) == "number" or type(v) == "boolean" or type(v) == "vector3" or isWhitelisted) then
output_str = output_str .. string.rep('\t', depth) .. key .. " = " .. tostring(v)
elseif (type(v) == "table") then
output_str = output_str .. string.rep('\t', depth) .. key .. " = {\n"
table.insert(stack, node)
table.insert(stack, v)
cache[node] = cur_index + 1
break
else
output_str = output_str .. string.rep('\t', depth) .. key .. " = '" .. tostring(v) .. "'"
end
if (cur_index == size) then
output_str = output_str .. "\n" .. string.rep('\t', depth - 1) .. "}"
else
output_str = output_str .. ","
end
else
-- close the table
if (cur_index == size) then
output_str = output_str .. "\n" .. string.rep('\t', depth - 1) .. "}"
end
end
cur_index = cur_index + 1
end
if (size == 0) then
output_str = output_str .. "\n" .. string.rep('\t', depth - 1) .. "}"
end
if (#stack > 0) then
node = stack[#stack]
stack[#stack] = nil
depth = cache[node] == nil and depth + 1 or depth - 1
else
break
end
end
-- This is necessary for working with HUGE tables otherwise we run out of memory using concat on huge strings
table.insert(output, output_str)
output_str = table.concat(output)
if not printing then
print(output_str)
end
return output_str
end

View file

@ -0,0 +1,17 @@
# rcore_television
if you see error: Bad binary format or syntax error near </1>
Read this guide:
https://documentation.rcore.cz/cfx-auth-system/error-syntax-error-near-less-than-1-greater-than
i see "you lack the entitelment to run this resource"
Follow thid guide: https://documentation.rcore.cz/cfx-auth-system/you-lack-the-entitlement
### editor
Use: /tveditor
Permission needed: add_ace group.admin command.tveditor allow
if you're not sure how to grant someone else principal just please use command: tvgrantpermission

Binary file not shown.

View file

@ -0,0 +1,9 @@
fx_version "cerulean"
games { "gta5" }
lua54 "yes"
escrow_ignore {
"stream/*.*",
}
dependency '/assetpacks'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

View file

@ -0,0 +1,157 @@
if Config.Framework ~= 'esx' then
return
end
ESX = exports['es_extended']:getSharedObject()
PlayerJob = false
CreateThread(function()
while not GetPlayerData() or not GetPlayerData().job do
Wait(100)
end
PlayerJob = GetPlayerData().job.name
end)
RegisterNetEvent('esx:setJob')
AddEventHandler('esx:setJob', function(job)
PlayerJob = job.name
end)
function TriggerServerCallback(name, cb, ...)
ESX.TriggerServerCallback(name, cb, ...)
end
function GetPlayerData()
return ESX.GetPlayerData()
end
function GetJobName()
return GetPlayerData()?.job?.name
end
local texts = {}
if GetResourceState('qs-textui') == 'started' then
function DrawText3D(x, y, z, text, id, key)
local _id = id
if not texts[_id] then
CreateThread(function()
texts[_id] = 5
while texts[_id] > 0 do
texts[_id] = texts[_id] - 1
Wait(0)
end
texts[_id] = nil
exports['qs-textui']:DeleteDrawText3D(id)
Debug('Deleted text', id)
end)
TriggerEvent('textui:DrawText3D', x, y, z, text, id, key)
end
texts[_id] = 5
end
else
function DrawText3D(x, y, z, text)
SetTextScale(0.35, 0.35)
SetTextFont(4)
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextEntry('STRING')
SetTextCentre(true)
AddTextComponentString(text)
SetDrawOrigin(x, y, z, 0)
DrawText(0.0, 0.0)
local factor = text:len() / 370
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
ClearDrawOrigin()
end
end
function DrawText3Ds(x, y, z, text)
SetTextScale(0.35, 0.35)
SetTextFont(4)
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextEntry('STRING')
SetTextCentre(true)
AddTextComponentString(text)
SetDrawOrigin(x, y, z, 0)
DrawText(0.0, 0.0)
local factor = (string.len(text)) / 370
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
ClearDrawOrigin()
end
function ProgressBar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
if GetResourceState('qs-interface') == 'started' then
local success = exports['qs-interface']:ProgressBar({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flags
},
prop = prop
})
if success then
onFinish()
else
onCancel()
end
return
end
if lib.progressCircle({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flags
},
prop = prop
}) then
onFinish()
else
onCancel()
end
end
function SendTextMessage(msg, type)
if GetResourceState('qs-interface') == 'started' then
if type == 'inform' then
exports['qs-interface']:AddNotify(msg, 'Inform', 2500, 'fas fa-file')
elseif type == 'error' then
exports['qs-interface']:AddNotify(msg, 'Error', 2500, 'fas fa-bug')
elseif type == 'success' then
exports['qs-interface']:AddNotify(msg, 'Success', 2500, 'fas fa-thumbs-up')
end
return
end
if type == 'inform' then
lib.notify({
title = 'Weed',
description = msg,
type = 'inform'
})
elseif type == 'error' then
lib.notify({
title = 'Weed',
description = msg,
type = 'error'
})
elseif type == 'success' then
lib.notify({
title = 'Weed',
description = msg,
type = 'success'
})
end
end

View file

@ -0,0 +1,157 @@
if Config.Framework ~= 'qb' then
return
end
QBCore = exports['qb-core']:GetCoreObject()
PlayerJob = false
CreateThread(function()
while not GetPlayerData() or not GetPlayerData().job do
Wait(100)
end
PlayerJob = GetPlayerData().job.name
end)
RegisterNetEvent('QBCore:Client:OnJobUpdate')
AddEventHandler('QBCore:Client:OnJobUpdate', function(job)
PlayerJob = job.name
end)
function TriggerServerCallback(name, cb, ...)
QBCore.Functions.TriggerCallback(name, cb, ...)
end
function GetPlayerData()
return QBCore.Functions.GetPlayerData()
end
function GetJobName()
return GetPlayerData()?.job?.name
end
local texts = {}
if GetResourceState('qs-textui') == 'started' then
function DrawText3D(x, y, z, text, id, key)
local _id = id
if not texts[_id] then
CreateThread(function()
texts[_id] = 5
while texts[_id] > 0 do
texts[_id] = texts[_id] - 1
Wait(0)
end
texts[_id] = nil
exports['qs-textui']:DeleteDrawText3D(id)
Debug('Deleted text', id)
end)
TriggerEvent('textui:DrawText3D', x, y, z, text, id, key)
end
texts[_id] = 5
end
else
function DrawText3D(x, y, z, text)
SetTextScale(0.35, 0.35)
SetTextFont(4)
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextEntry('STRING')
SetTextCentre(true)
AddTextComponentString(text)
SetDrawOrigin(x, y, z, 0)
DrawText(0.0, 0.0)
local factor = text:len() / 370
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
ClearDrawOrigin()
end
end
function DrawText3Ds(x, y, z, text)
SetTextScale(0.35, 0.35)
SetTextFont(4)
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextEntry('STRING')
SetTextCentre(true)
AddTextComponentString(text)
SetDrawOrigin(x, y, z, 0)
DrawText(0.0, 0.0)
local factor = (string.len(text)) / 370
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
ClearDrawOrigin()
end
function ProgressBar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
if GetResourceState('qs-interface') == 'started' then
local success = exports['qs-interface']:ProgressBar({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flags
},
prop = prop
})
if success then
onFinish()
else
onCancel()
end
return
end
if lib.progressCircle({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flags
},
prop = prop
}) then
onFinish()
else
onCancel()
end
end
function SendTextMessage(msg, type)
if GetResourceState('qs-interface') == 'started' then
if type == 'inform' then
exports['qs-interface']:AddNotify(msg, 'Inform', 2500, 'fas fa-file')
elseif type == 'error' then
exports['qs-interface']:AddNotify(msg, 'Error', 2500, 'fas fa-bug')
elseif type == 'success' then
exports['qs-interface']:AddNotify(msg, 'Success', 2500, 'fas fa-thumbs-up')
end
return
end
if type == 'inform' then
lib.notify({
title = 'Weed',
description = msg,
type = 'inform'
})
elseif type == 'error' then
lib.notify({
title = 'Weed',
description = msg,
type = 'error'
})
elseif type == 'success' then
lib.notify({
title = 'Weed',
description = msg,
type = 'success'
})
end
end

View file

@ -0,0 +1,157 @@
if Config.Framework ~= 'qbx' then
return
end
QBCore = exports['qb-core']:GetCoreObject()
PlayerJob = false
CreateThread(function()
while not GetPlayerData() or not GetPlayerData().job do
Wait(100)
end
PlayerJob = GetPlayerData().job.name
end)
RegisterNetEvent('QBCore:Client:OnJobUpdate')
AddEventHandler('QBCore:Client:OnJobUpdate', function(job)
PlayerJob = job.name
end)
function TriggerServerCallback(name, cb, ...)
QBCore.Functions.TriggerCallback(name, cb, ...)
end
function GetPlayerData()
return exports.qbx_core:GetPlayerData()
end
function GetJobName()
return GetPlayerData()?.job?.name
end
local texts = {}
if GetResourceState('qs-textui') == 'started' then
function DrawText3D(x, y, z, text, id, key)
local _id = id
if not texts[_id] then
CreateThread(function()
texts[_id] = 5
while texts[_id] > 0 do
texts[_id] = texts[_id] - 1
Wait(0)
end
texts[_id] = nil
exports['qs-textui']:DeleteDrawText3D(id)
Debug('Deleted text', id)
end)
TriggerEvent('textui:DrawText3D', x, y, z, text, id, key)
end
texts[_id] = 5
end
else
function DrawText3D(x, y, z, text)
SetTextScale(0.35, 0.35)
SetTextFont(4)
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextEntry('STRING')
SetTextCentre(true)
AddTextComponentString(text)
SetDrawOrigin(x, y, z, 0)
DrawText(0.0, 0.0)
local factor = text:len() / 370
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
ClearDrawOrigin()
end
end
function DrawText3Ds(x, y, z, text)
SetTextScale(0.35, 0.35)
SetTextFont(4)
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextEntry('STRING')
SetTextCentre(true)
AddTextComponentString(text)
SetDrawOrigin(x, y, z, 0)
DrawText(0.0, 0.0)
local factor = (string.len(text)) / 370
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
ClearDrawOrigin()
end
function ProgressBar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
if GetResourceState('qs-interface') == 'started' then
local success = exports['qs-interface']:ProgressBar({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flags
},
prop = prop
})
if success then
onFinish()
else
onCancel()
end
return
end
if lib.progressCircle({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flags
},
prop = prop
}) then
onFinish()
else
onCancel()
end
end
function SendTextMessage(msg, type)
if GetResourceState('qs-interface') == 'started' then
if type == 'inform' then
exports['qs-interface']:AddNotify(msg, 'Inform', 2500, 'fas fa-file')
elseif type == 'error' then
exports['qs-interface']:AddNotify(msg, 'Error', 2500, 'fas fa-bug')
elseif type == 'success' then
exports['qs-interface']:AddNotify(msg, 'Success', 2500, 'fas fa-thumbs-up')
end
return
end
if type == 'inform' then
lib.notify({
title = 'Weed',
description = msg,
type = 'inform'
})
elseif type == 'error' then
lib.notify({
title = 'Weed',
description = msg,
type = 'error'
})
elseif type == 'success' then
lib.notify({
title = 'Weed',
description = msg,
type = 'success'
})
end
end

View file

@ -0,0 +1,183 @@
if Config.Framework ~= 'standalone' then return end
PlayerJob = 'unemployed'
local RequestId = 0
local serverRequests = {}
local clientCallbacks = {}
---@param eventName string
---@param callback function
---@param ... any
TriggerServerCallback = function(eventName, callback, ...)
serverRequests[RequestId] = callback
TriggerServerEvent('weed:triggerServerCallback', eventName, RequestId, GetInvokingResource() or 'unknown', ...)
RequestId = RequestId + 1
end
exports('TriggerServerCallback', TriggerServerCallback)
RegisterNetEvent('weed:serverCallback', function(requestId, invoker, ...)
if not serverRequests[requestId] then
return print(('[^1ERROR^7] Server Callback with requestId ^5%s^7 Was Called by ^5%s^7 but does not exist.'):format(requestId, invoker))
end
serverRequests[requestId](...)
serverRequests[requestId] = nil
end)
---@param eventName string
---@param callback function
_RegisterClientCallback = function(eventName, callback)
clientCallbacks[eventName] = callback
end
RegisterNetEvent('weed:triggerClientCallback', function(eventName, requestId, invoker, ...)
if not clientCallbacks[eventName] then
return print(('[^1ERROR^7] Client Callback not registered, name: ^5%s^7, invoker resource: ^5%s^7'):format(eventName, invoker))
end
clientCallbacks[eventName](function(...)
TriggerServerEvent('weed:clientCallback', requestId, invoker, ...)
end, ...)
end)
function GetPlayerData()
ImplementError('You need to implement GetPlayerData()')
return {}
end
function GetJobName()
Error('GetJobName is used with standalone')
return Config.PoliceJobs
end
local texts = {}
if GetResourceState('qs-textui') == 'started' then
function DrawText3D(x, y, z, text, id, key)
local _id = id
if not texts[_id] then
CreateThread(function()
texts[_id] = 5
while texts[_id] > 0 do
texts[_id] = texts[_id] - 1
Wait(0)
end
texts[_id] = nil
exports['qs-textui']:DeleteDrawText3D(id)
Debug('Deleted text', id)
end)
TriggerEvent('textui:DrawText3D', x, y, z, text, id, key)
end
texts[_id] = 5
end
else
function DrawText3D(x, y, z, text)
SetTextScale(0.35, 0.35)
SetTextFont(4)
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextEntry('STRING')
SetTextCentre(true)
AddTextComponentString(text)
SetDrawOrigin(x, y, z, 0)
DrawText(0.0, 0.0)
local factor = text:len() / 370
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
ClearDrawOrigin()
end
end
function DrawText3Ds(x, y, z, text)
SetTextScale(0.35, 0.35)
SetTextFont(4)
SetTextProportional(1)
SetTextColour(255, 255, 255, 215)
SetTextEntry('STRING')
SetTextCentre(true)
AddTextComponentString(text)
SetDrawOrigin(x, y, z, 0)
DrawText(0.0, 0.0)
local factor = (string.len(text)) / 370
DrawRect(0.0, 0.0 + 0.0125, 0.017 + factor, 0.03, 0, 0, 0, 75)
ClearDrawOrigin()
end
function ProgressBar(name, label, duration, useWhileDead, canCancel, disableControls, animation, prop, propTwo, onFinish, onCancel)
if GetResourceState('qs-interface') == 'started' then
local success = exports['qs-interface']:ProgressBar({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flags
},
prop = prop
})
if success then
onFinish()
else
onCancel()
end
return
end
if lib.progressCircle({
duration = duration,
label = label,
position = 'bottom',
useWhileDead = useWhileDead,
canCancel = canCancel,
disable = disableControls,
anim = {
dict = animation.animDict,
clip = animation.anim,
flag = animation?.flags
},
prop = prop
}) then
onFinish()
else
onCancel()
end
end
function SendTextMessage(msg, type)
if GetResourceState('qs-interface') == 'started' then
if type == 'inform' then
exports['qs-interface']:AddNotify(msg, 'Inform', 2500, 'fas fa-file')
elseif type == 'error' then
exports['qs-interface']:AddNotify(msg, 'Error', 2500, 'fas fa-bug')
elseif type == 'success' then
exports['qs-interface']:AddNotify(msg, 'Success', 2500, 'fas fa-thumbs-up')
end
return
end
if type == 'inform' then
lib.notify({
title = 'Weed',
description = msg,
type = 'inform'
})
elseif type == 'error' then
lib.notify({
title = 'Weed',
description = msg,
type = 'error'
})
elseif type == 'success' then
lib.notify({
title = 'Weed',
description = msg,
type = 'success'
})
end
end

Binary file not shown.

View file

@ -0,0 +1,34 @@
fx_version 'cerulean'
games { 'gta5' }
lua54 'yes'
shared_script {
'@ox_lib/init.lua',
'shared/*.lua',
'locales/*.lua'
}
client_scripts {
'client/**/**/**.lua'
}
server_scripts {
'@mysql-async/lib/MySQL.lua',
'server/**/**/**.lua'
}
dependencies {
'ox_lib'
}
escrow_ignore {
'shared/config.lua',
'locales/*.lua',
'client/custom/**/**.lua',
'server/custom/**/**.lua',
'server/custom/missions'
}
dependency '/assetpacks'

View file

@ -0,0 +1,26 @@
Locales["ar"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[ه] - حرق النبات',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[ز] - نبات الحمل',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[هـ] - إزالة النبات الميت',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[هـ] حصاد النبات',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'يكتب:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'تَغذِيَة:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'صحة:',
["WEED_PROGRESS_GROWING_PLANT"] = 'نبات ينمو...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'إزالة النبات...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'زرع النبات ...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'مصنع تغذية ...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'لقد غيرت موقف النبات',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'اشتعلت النيران في المصنع بالكامل',
["WEED_NOTIFICATION_NO_PLACE"] = 'لا يوجد مكان لوضع النبات',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'أنت لست في منزلك أو في منطقة آمنة',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'هذا النبات لا يحتاج إلى مزيد من التغذية',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'لم يتم العثور على الكائن أو أنه مكسور',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'لقد حصدت النبات بشكل صحيح',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'المصنع لم يعد موجودا',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'ليس لديك أكياس كافية لحصاد النبات بأكمله',
["WEED_NOTIFICATION_NOT_PLANT"] = 'إنه ليس نباتك ولا يمكنك حصاد نبات لاعب آخر',
["WEED_NOTIFICATION_NO_PLANTS"] = 'لا يمكنك وضع المزيد من النباتات في هذا المنزل',
}

View file

@ -0,0 +1,26 @@
Locales["bg"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - Изгорено растение',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - Носещо растение',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - Премахнете мъртвото растение',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - Жътва',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'Тип:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'Хранене:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'здраве:',
["WEED_PROGRESS_GROWING_PLANT"] = 'Отглеждане на растение...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'Премахване на растението...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'Засаждане на растение...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'Завод за хранене...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'Променихте позицията на растението',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'Заводът се е запалил напълно',
["WEED_NOTIFICATION_NO_PLACE"] = 'Няма къде да поставите растението',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'Не сте вкъщи или в безопасна зона',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'Това растение не се нуждае от повече хранене',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'Предметът не е намерен или е счупен',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'Вие сте събрали растението правилно',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'Заводът вече не съществува',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'Нямате достатъчно торби, за да приберете цялото растение',
["WEED_NOTIFICATION_NOT_PLANT"] = 'Това не е вашето растение, нито можете да берете растението на друг играч',
["WEED_NOTIFICATION_NO_PLANTS"] = 'Не можете да поставите повече растения в този дом',
}

View file

@ -0,0 +1,26 @@
Locales["ca"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - Cremar planta',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - Portar planta',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - Eliminar la planta morta',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - Planta de verema',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'Tipus:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'Nutrició:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'Salut:',
["WEED_PROGRESS_GROWING_PLANT"] = 'Planta en creixement...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'Eliminant planta...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'Plantar planta...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'Planta d\'alimentació...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'Has canviat la posició de la planta',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'La planta es va incendiar completament',
["WEED_NOTIFICATION_NO_PLACE"] = 'No hi ha lloc per posar la planta',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'No estàs a casa teva ni en una zona segura',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'Aquesta planta no necessita més nutrició',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'L\'objecte no s\'ha trobat o està trencat',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'Has collit correctament la planta',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'La planta ja no existeix',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'No teniu prou bosses per collir tota la planta',
["WEED_NOTIFICATION_NOT_PLANT"] = 'No és la teva planta ni pots collir la planta d\'un altre jugador',
["WEED_NOTIFICATION_NO_PLANTS"] = 'No podeu posar més plantes en aquesta casa',
}

View file

@ -0,0 +1,26 @@
Locales["cs"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - Spálit rostlinu',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - Přenášecí rostlina',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - Odstraňte odumřelou rostlinu',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - Sklizeň rostlin',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'Typ:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'Výživa:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'Zdraví:',
["WEED_PROGRESS_GROWING_PLANT"] = 'Rostoucí rostlina...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'Odstraňování rostlin...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'Výsadba rostlin...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'Krmná rostlina...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'Změnil jsi polohu rostliny',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'Závod úplně vzplál',
["WEED_NOTIFICATION_NO_PLACE"] = 'Rostlinu není kam umístit',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'Nejste doma nebo v bezpečné zóně',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'Tato rostlina nepotřebuje více výživy',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'Předmět nebyl nalezen nebo je rozbitý',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'Rostlinu jste sklidili správně',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'Rostlina již neexistuje',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'Nemáte dostatek pytlů na sklizeň celé rostliny',
["WEED_NOTIFICATION_NOT_PLANT"] = 'Není to vaše rostlina ani nemůžete sklízet rostlinu jiného hráče',
["WEED_NOTIFICATION_NO_PLANTS"] = 'Do tohoto domu nemůžete umístit více rostlin',
}

View file

@ -0,0 +1,26 @@
Locales["da"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - Brænd plante',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - Bær plante',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - Fjern døde plante',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - Høstplante',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'Type:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'Ernæring:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'Sundhed:',
["WEED_PROGRESS_GROWING_PLANT"] = 'Plante i vækst...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'Fjerner plante...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'Planter plante...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'Foderplante...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'Du ændrede anlæggets position',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'Anlægget brød fuldstændig i brand',
["WEED_NOTIFICATION_NO_PLACE"] = 'Der er ikke noget sted at sætte planten',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'Du er ikke i dit hjem eller i en sikker zone',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'Denne plante har ikke brug for mere næring',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'Genstanden blev ikke fundet eller er ødelagt',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'Du har høstet planten korrekt',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'Planten eksisterer ikke længere',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'Du har ikke nok poser til at høste hele planten',
["WEED_NOTIFICATION_NOT_PLANT"] = 'Det er ikke din plante, og du kan heller ikke høste en anden spillers plante',
["WEED_NOTIFICATION_NO_PLANTS"] = 'Du kan ikke sætte flere planter i dette hjem',
}

View file

@ -0,0 +1,26 @@
Locales["de"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] Pflanze verbrennen',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] Pflanze tragen',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] Abgestorbene Pflanzen entfernen',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] Pflanze ernten',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'Typ:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'Ernährung:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'Gesundheit:',
["WEED_PROGRESS_GROWING_PLANT"] = 'Wachsende Pflanze...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'Pflanze entfernen...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'Pflanze pflanzen...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'Futterpflanze...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'Sie haben die Anlagenposition geändert',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'Die Anlage geriet vollständig in Brand',
["WEED_NOTIFICATION_NO_PLACE"] = 'Es gibt keinen Platz für die Pflanze',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'Sie befinden sich nicht zu Hause oder in einer sicheren Zone',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'Diese Pflanze benötigt keine weitere Nahrung',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'Das Objekt wurde nicht gefunden oder ist kaputt',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'Sie haben die Pflanze richtig geerntet',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'Die Pflanze existiert nicht mehr',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'Sie haben nicht genügend Beutel, um die gesamte Pflanze zu ernten',
["WEED_NOTIFICATION_NOT_PLANT"] = 'Es ist weder Ihre Pflanze, noch können Sie die Pflanze eines anderen Spielers ernten',
["WEED_NOTIFICATION_NO_PLANTS"] = 'Sie können in diesem Haus nicht mehr Pflanzen pflanzen',
}

View file

@ -0,0 +1,26 @@
Locales["el"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - Φυτό καύσης',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - Φυτό μεταφοράς',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - Αφαιρέστε το νεκρό φυτό',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - Φυτό συγκομιδής',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'Τύπος:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'Θρέψη:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'Υγεία:',
["WEED_PROGRESS_GROWING_PLANT"] = 'Καλλιέργεια φυτών...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'Αφαίρεση φυτού...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'Φύτευση φυτού...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'Φυτό τροφοδοσίας...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'Αλλάξατε τη θέση του φυτού',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'Το εργοστάσιο πήρε φωτιά εντελώς',
["WEED_NOTIFICATION_NO_PLACE"] = 'Δεν υπάρχει μέρος για να βάλετε το φυτό',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'Δεν βρίσκεστε στο σπίτι σας ή σε ασφαλή ζώνη',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'Αυτό το φυτό δεν χρειάζεται περισσότερη διατροφή',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'Το αντικείμενο δεν βρέθηκε ή είναι σπασμένο',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'Έχετε μαζέψει σωστά το φυτό',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'Το φυτό δεν υπάρχει πλέον',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'Δεν έχετε αρκετές σακούλες για να μαζέψετε ολόκληρο το φυτό',
["WEED_NOTIFICATION_NOT_PLANT"] = 'Δεν είναι το φυτό σας ούτε μπορείτε να μαζέψετε φυτό άλλου παίκτη',
["WEED_NOTIFICATION_NO_PLANTS"] = 'Δεν μπορείτε να βάλετε περισσότερα φυτά σε αυτό το σπίτι',
}

View file

@ -0,0 +1,26 @@
Locales["en"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - Burn plant',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - Carry plant',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - Remove dead plant',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - Harvest plant',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'Type:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'Nutrition:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'Health:',
["WEED_PROGRESS_GROWING_PLANT"] = 'Growing plant...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'Removing plant...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'Planting plant...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'Feeding plant...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'You changed the plant position',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'The plant caught fire completely',
["WEED_NOTIFICATION_NO_PLACE"] = 'There is no place to put the plant',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'You are not at your home or in a safe zone',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'This plant does not need more nutrition',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'The object was not found or is broken',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'You have harvested the plant correctly',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'The plant no longer exists',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'You do not have enough bags to harvest the entire plant',
["WEED_NOTIFICATION_NOT_PLANT"] = 'It is not your plant nor can you harvest another player\\\'s plant',
["WEED_NOTIFICATION_NO_PLANTS"] = 'You cannot put more plants in this home',
}

View file

@ -0,0 +1,26 @@
Locales["es"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - Quemar planta',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - Planta de transporte',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - Quitar la planta muerta',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - Planta de cosecha',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'Tipo:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'Nutrición:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'Salud:',
["WEED_PROGRESS_GROWING_PLANT"] = 'Planta en crecimiento...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'Quitando planta...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'Plantación de planta...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'Planta de alimentación...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'Cambiaste la posición de la planta.',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'La planta se incendió por completo.',
["WEED_NOTIFICATION_NO_PLACE"] = 'No hay lugar para poner la planta.',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'No estás en tu casa ni en una zona segura',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'Esta planta no necesita más nutrición.',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'El objeto no fue encontrado o está roto.',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'Has cosechado la planta correctamente.',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'La planta ya no existe.',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'No tienes suficientes bolsas para cosechar toda la planta.',
["WEED_NOTIFICATION_NOT_PLANT"] = 'No es tu planta ni puedes cosechar la planta de otro jugador.',
["WEED_NOTIFICATION_NO_PLANTS"] = 'No se pueden poner más plantas en esta casa.',
}

View file

@ -0,0 +1,26 @@
Locales["fa"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[اِ] - گیاه را بسوزانید',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - گیاه را حمل کنید',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - گیاه مرده را بردارید',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - گیاه درو',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'نوع:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'تغذیه:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'سلامت:',
["WEED_PROGRESS_GROWING_PLANT"] = 'در حال رشد گیاه ...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'حذف گیاه ...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'کاشت گیاه ...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'گیاه تغذیه ...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'شما موقعیت گیاه را تغییر دادید',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'این گیاه کاملاً آتش گرفت',
["WEED_NOTIFICATION_NO_PLACE"] = 'جایی برای قرار دادن گیاه وجود ندارد',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'شما در خانه یا در یک منطقه امن نیستید',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'این گیاه به تغذیه بیشتری نیاز ندارد',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'شی پیدا نشد یا شکسته است',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'شما گیاه را به درستی برداشت کرده اید',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'این گیاه دیگر وجود ندارد',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'کیسه های کافی برای برداشت کل گیاه ندارید',
["WEED_NOTIFICATION_NOT_PLANT"] = 'این گیاه شما نیست و نمی توانید گیاه بازیکن دیگری را برداشت کنید',
["WEED_NOTIFICATION_NO_PLANTS"] = 'شما نمی توانید گیاهان بیشتری را در این خانه قرار دهید',
}

View file

@ -0,0 +1,26 @@
Locales["fr"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - Brûler plante',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - Plante de transport',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - Supprimer la plante morte',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - Plante de récolte',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'Taper:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'Nutrition:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'Santé:',
["WEED_PROGRESS_GROWING_PLANT"] = 'Plante en croissance...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'Suppression d\'une plante...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'Plante à planter...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'Plante nourricière...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'Vous avez changé la position de la plante',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'L\'usine a complètement pris feu',
["WEED_NOTIFICATION_NO_PLACE"] = 'Il n\'y a pas de place pour mettre la plante',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'Vous n\'êtes pas chez vous ou dans une zone sûre',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'Cette plante n\'a pas besoin de plus de nutrition',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'L\'objet n\'a pas été trouvé ou est cassé',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'Vous avez récolté la plante correctement',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'La plante n\'existe plus',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'Vous n\'avez pas assez de sacs pour récolter la plante entière',
["WEED_NOTIFICATION_NOT_PLANT"] = 'Ce n\'est pas votre plante et vous ne pouvez pas non plus récolter la plante d\'un autre joueur',
["WEED_NOTIFICATION_NO_PLANTS"] = 'Vous ne pouvez pas mettre plus de plantes dans cette maison',
}

View file

@ -0,0 +1,26 @@
Locales["he"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - Burn plant',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - Carry plant',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - Remove dead plant',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - Harvest plant',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'Type:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'Nutrition:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'Health:',
["WEED_PROGRESS_GROWING_PLANT"] = 'Growing plant...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'Removing plant...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'Planting plant...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'Feeding plant...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'You changed the plant position',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'The plant caught fire completely',
["WEED_NOTIFICATION_NO_PLACE"] = 'There is no place to put the plant',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'You are not at your home or in a safe zone',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'This plant does not need more nutrition',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'The object was not found or is broken',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'You have harvested the plant correctly',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'The plant no longer exists',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'You do not have enough bags to harvest the entire plant',
["WEED_NOTIFICATION_NOT_PLANT"] = 'It is not your plant nor can you harvest another player\'s plant',
["WEED_NOTIFICATION_NO_PLANTS"] = 'You cannot put more plants in this home',
}

View file

@ -0,0 +1,26 @@
Locales["hi"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[ई] - जला हुआ पौधा',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[जी] - कैरी प्लांट',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[ई] - मृत पौधे को हटा दें',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[ई] - फसल का पौधा',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'प्रकार:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'पोषण:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'स्वास्थ्य:',
["WEED_PROGRESS_GROWING_PLANT"] = 'बढ़ता हुआ पौधा...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'पौधा हटाया जा रहा है...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'पौधारोपण...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'भोजन देने वाला पौधा...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'आपने पौधे की स्थिति बदल दी',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'प्लांट पूरी तरह से जलकर खाक हो गया',
["WEED_NOTIFICATION_NO_PLACE"] = 'पौधा लगाने की जगह नहीं है',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'आप अपने घर पर या सुरक्षित क्षेत्र में नहीं हैं',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'इस पौधे को अधिक पोषण की आवश्यकता नहीं होती',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'वस्तु नहीं मिली या टूट गयी है',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'आपने पौधे की सही कटाई की है',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'संयंत्र अब अस्तित्व में नहीं है',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'आपके पास पूरे पौधे की कटाई के लिए पर्याप्त बैग नहीं हैं',
["WEED_NOTIFICATION_NOT_PLANT"] = 'यह आपका पौधा नहीं है और न ही आप किसी अन्य खिलाड़ी का पौधा काट सकते हैं',
["WEED_NOTIFICATION_NO_PLANTS"] = 'आप इस घर में अधिक पौधे नहीं लगा सकते',
}

View file

@ -0,0 +1,26 @@
Locales["hu"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - Égess el egy növényt',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - Növényhordozó',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - Távolítsa el az elhalt növényt',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - Betakarítás növény',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'Típus:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'Táplálás:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'Egészség:',
["WEED_PROGRESS_GROWING_PLANT"] = 'Növekvő növény...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'Növény eltávolítása...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'Növény ültetése...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'Etető üzem...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'Megváltoztatta az üzem pozícióját',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'Az üzem teljesen kigyulladt',
["WEED_NOTIFICATION_NO_PLACE"] = 'Nincs hová tenni a növényt',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'Nem tartózkodik otthonában vagy biztonságos zónában',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'Ennek a növénynek nincs szüksége több táplálékra',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'A tárgy nem található, vagy elromlott',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'Helyesen betakarította a növényt',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'Az üzem már nem létezik',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'Nincs elég zacskója az egész növény betakarításához',
["WEED_NOTIFICATION_NOT_PLANT"] = 'Ez nem a te növényed, és nem is betakaríthatod egy másik játékos növényét',
["WEED_NOTIFICATION_NO_PLANTS"] = 'Nem tehet több növényt ebbe az otthonba',
}

View file

@ -0,0 +1,26 @@
Locales["it"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - Brucia la pianta',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - Trasportare la pianta',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - Rimuovere la pianta morta',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - Pianta da raccogliere',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'Tipo:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'Nutrizione:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'Salute:',
["WEED_PROGRESS_GROWING_PLANT"] = 'Pianta in crescita...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'Rimozione pianta...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'Piantare una pianta...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'Pianta da nutrire...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'Hai cambiato la posizione della pianta',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'L\'impianto ha preso fuoco completamente',
["WEED_NOTIFICATION_NO_PLACE"] = 'Non c\'è posto dove mettere la pianta',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'Non sei a casa tua o in una zona sicura',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'Questa pianta non ha bisogno di più nutrimento',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'L\'oggetto non è stato trovato o è rotto',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'Hai raccolto la pianta correttamente',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'L\'impianto non esiste più',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'Non hai abbastanza sacchi per raccogliere l\'intera pianta',
["WEED_NOTIFICATION_NOT_PLANT"] = 'Non è la tua pianta né puoi raccogliere la pianta di un altro giocatore',
["WEED_NOTIFICATION_NO_PLANTS"] = 'Non puoi mettere più piante in questa casa',
}

View file

@ -0,0 +1,26 @@
Locales["ja"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - 植物を燃やす',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - キャリープラント',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - 枯れた植物を取り除く',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - 収穫植物',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'タイプ:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = '栄養:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = '健康:',
["WEED_PROGRESS_GROWING_PLANT"] = '成長中の植物...',
["WEED_PROGRESS_REMOVE_PLANT"] = '植物を除去しています...',
["WEED_PROGRESS_PLANTING_PLANT"] = '植物を植える...',
["WEED_PROGRESS_NUTRITION_PLANT"] = '給餌植物...',
["WEED_NOTIFICATION_PUT_OBJECT"] = '工場の位置を変更しました',
["WEED_NOTIFICATION_FIRE_PLANT"] = '工場は完全に火災になった',
["WEED_NOTIFICATION_NO_PLACE"] = '植物を置く場所がない',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'あなたは自宅または安全地帯にいません',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'この植物にはそれ以上の栄養は必要ありません',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'オブジェクトが見つからないか壊れています',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = '植物を正しく収穫しました',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'その工場はもう存在しません',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = '植物全体を収穫するのに十分な袋がありません',
["WEED_NOTIFICATION_NOT_PLANT"] = 'それはあなたの植物ではなく、他のプレイヤーの植物を収穫することもできません',
["WEED_NOTIFICATION_NO_PLANTS"] = 'この家にはこれ以上植物を置くことはできません',
}

View file

@ -0,0 +1,26 @@
Locales["ko"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - 식물 태우기',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - 식물 운반',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - 죽은 식물 제거',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - 수확 식물',
["WEED_DRAWTEXT_TYPE_STATUS"] = '유형:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = '영양물 섭취:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = '건강:',
["WEED_PROGRESS_GROWING_PLANT"] = '식물을 키우는 중...',
["WEED_PROGRESS_REMOVE_PLANT"] = '식물 제거 중...',
["WEED_PROGRESS_PLANTING_PLANT"] = '식물을 심는 중...',
["WEED_PROGRESS_NUTRITION_PLANT"] = '먹이를 주는 식물...',
["WEED_NOTIFICATION_PUT_OBJECT"] = '공장 위치를 ​​바꾸셨네요',
["WEED_NOTIFICATION_FIRE_PLANT"] = '식물에 완전히 불이 붙었습니다',
["WEED_NOTIFICATION_NO_PLACE"] = '식물을 심을 곳이 없어요',
["WEED_NOTIFICATION_SAFE_ZONE"] = '당신은 집에 없거나 안전지대에 있지 않습니다.',
["WEED_NOTIFICATION_NO_NUTRITION"] = '이 식물에는 더 많은 영양이 필요하지 않습니다.',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = '개체를 찾을 수 없거나 손상되었습니다.',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = '식물을 올바르게 수확했습니다',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = '그 식물은 더 이상 존재하지 않습니다.',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = '전체 식물을 수확할 만큼 충분한 봉지가 없습니다.',
["WEED_NOTIFICATION_NOT_PLANT"] = '그것은 당신의 식물이 아니며 다른 플레이어의 식물을 수확할 수도 없습니다.',
["WEED_NOTIFICATION_NO_PLANTS"] = '이 집에는 더 이상 식물을 심을 수 없습니다',
}

View file

@ -0,0 +1,26 @@
Locales["nl"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - Installatie verbranden',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - Draag plant',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - Verwijder dode plant',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - Oogstplant',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'Type:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'Voeding:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'Gezondheid:',
["WEED_PROGRESS_GROWING_PLANT"] = 'Groeiende plant...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'Plant verwijderen...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'Plantje planten...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'Voedingsplant...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'Je hebt de plantpositie gewijzigd',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'De fabriek vloog volledig in brand',
["WEED_NOTIFICATION_NO_PLACE"] = 'Er is geen plek om de plant neer te zetten',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'U bent niet thuis of in een veilige zone',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'Meer voeding heeft deze plant niet nodig',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'Het object is niet gevonden of is kapot',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'Je hebt de plant correct geoogst',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'De fabriek bestaat niet meer',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'Je hebt niet genoeg zakken om de hele plant te oogsten',
["WEED_NOTIFICATION_NOT_PLANT"] = 'Het is niet jouw plant en je kunt ook niet de plant van een andere speler oogsten',
["WEED_NOTIFICATION_NO_PLANTS"] = 'Je kunt niet meer planten in dit huis zetten',
}

View file

@ -0,0 +1,26 @@
Locales["no"] = {
["WEED_DRAWTEXT_FIRE_PLANT"] = '[E] - Brenn plante',
["WEED_DRAWTEXT_CARRY_PLANT"] = '[G] - Bær plante',
["WEED_DRAWTEXT_DEAD_PLANT"] = '[E] - Fjern døde plante',
["WEED_DRAWTEXT_HARVEST_PLANT"] = '[E] - Høsteplante',
["WEED_DRAWTEXT_TYPE_STATUS"] = 'Type:',
["WEED_DRAWTEXT_NUTRITION_STATUS"] = 'Ernæring:',
["WEED_DRAWTEXT_HEALTH_STATUS"] = 'Helse:',
["WEED_PROGRESS_GROWING_PLANT"] = 'Voksende plante...',
["WEED_PROGRESS_REMOVE_PLANT"] = 'Fjerner planten...',
["WEED_PROGRESS_PLANTING_PLANT"] = 'Plante plante...',
["WEED_PROGRESS_NUTRITION_PLANT"] = 'Matplante...',
["WEED_NOTIFICATION_PUT_OBJECT"] = 'Du endret anleggsposisjonen',
["WEED_NOTIFICATION_FIRE_PLANT"] = 'Anlegget tok fullstendig fyr',
["WEED_NOTIFICATION_NO_PLACE"] = 'Det er ikke noe sted å sette planten',
["WEED_NOTIFICATION_SAFE_ZONE"] = 'Du er ikke hjemme eller i en trygg sone',
["WEED_NOTIFICATION_NO_NUTRITION"] = 'Denne planten trenger ikke mer næring',
["WEED_NOTIFICATION_BROKEN_OBJECT"] = 'Gjenstanden ble ikke funnet eller er ødelagt',
["WEED_NOTIFICATION_HARVESTED_PLANT"] = 'Du har høstet planten riktig',
["WEED_NOTIFICATION_PLANT_NOT_EXIST"] = 'Planten eksisterer ikke lenger',
["WEED_NOTIFICATION_PLANT_NO_BAGS"] = 'Du har ikke nok poser til å høste hele planten',
["WEED_NOTIFICATION_NOT_PLANT"] = 'Det er ikke din plante, og du kan heller ikke høste en annen spillers plante',
["WEED_NOTIFICATION_NO_PLANTS"] = 'Du kan ikke sette flere planter i dette hjemmet',
}

Some files were not shown because too many files have changed in this diff Show more