diff --git a/client/blip.lua b/client/blip.lua new file mode 100644 index 0000000..f88c1df --- /dev/null +++ b/client/blip.lua @@ -0,0 +1,11 @@ +CreateThread(function() + local blip = AddBlipForCoord(Config.blip.coords.x, Config.blip.coords.y, Config.blip.coords.z) + SetBlipSprite(blip, Config.blip.sprite) + SetBlipDisplay(blip, Config.blip.display) + SetBlipScale(blip, Config.blip.scale) + SetBlipColour(blip, Config.blip.color) + SetBlipAsShortRange(blip, true) + BeginTextCommandSetBlipName("STRING") + AddTextComponentString(Config.blip.label) + EndTextCommandSetBlipName(blip) +end) \ No newline at end of file diff --git a/client/main.lua b/client/main.lua new file mode 100644 index 0000000..dcb8df1 --- /dev/null +++ b/client/main.lua @@ -0,0 +1,7 @@ +RegisterNUICallback('exit', function() + SendNUIMessage({ + type = "off", + game = "", + }) + SetNuiFocus(false, false) +end) diff --git a/client/menus.lua b/client/menus.lua new file mode 100644 index 0000000..03012af --- /dev/null +++ b/client/menus.lua @@ -0,0 +1,70 @@ +local function GenerateOptions() + local options = {} + for i = 1, #Config.games, 1 do + options[#options + 1] = { + label = Config.games[i].label, + icon = Config.games[i].icon or 'fa-gamepad', -- WIP: Verplaatsen naar config voor fa-gamepad + } + end + return options +end + +local function GenerateHacks() + local options = {} + for i = 1, #Config.hacks, 1 do + options[#options + 1] = { + label = Config.hacks[i].label, + icon = Config.hacks[i].icon or 'fa-gamepad', -- WIP: Verplaatsen naar config voor fa-gamepad + } + end + return options +end + +CreateThread(function() + lib.registerMenu({ + id = 'arcade_machine', + title = Lang:t('menu.arcade'), + position = 'top-right', + options = GenerateOptions(), + }, function(selected, scrollIndex, args) + SendNUIMessage({ + type = "on", + game = Config.games[selected].args, + gpu = "ETX2080", + cpu = "U9_9900" + }) + SetNuiFocus(true, true) + end) + + lib.registerMenu({ + id = 'arcade_hacking', + title = Lang:t('menu.special'), + position = 'top-right', + options = GenerateHacks(), + }, function(selected, scrollIndex, args) + Config.hacks[selected].action() + end) + + lib.registerContext({ + id = 'arcade_purchase_token', + title = Lang:t('menu.purchase_token'):format(Config.TokenPrice), + options = {{ + title = Lang:t('menu.purchase_token'):format(Config.TokenPrice), + icon = 'fa-shopping-cart', + onSelect = function() + local amount = lib.inputDialog(Lang:t('menu.amount'), { + { + label = Lang:t('menu.amount'), + type = 'number', + min = 1, + required = true, + } + }) + if amount then + TriggerServerEvent('qb-arcade:server:buyToken', amount[1]) + end + end + + }} + }) +end) \ No newline at end of file diff --git a/client/target.lua b/client/target.lua new file mode 100644 index 0000000..b2bf5c9 --- /dev/null +++ b/client/target.lua @@ -0,0 +1,52 @@ +local models = {1876055757, -1501557515, -1502319666, 815879628, -1991361770, 1301167921, -538006270, 2303605526, 4185618299, 3756961026, 2793409781, 398786301, 568464183, 3067040863, 3171514707, 3899793496, 974001996, 4206216415, 1457191833, 3054877820, 4129005630, 3963576280, 3325005861, 543442061, 372224036, -1273554963} -- WIP: Verplaatsen naar config? + + +local function requireToken() + if not lib.callback.await('qb-arcade:server:hasToken') then + + lib.notify({ + title = Lang:t('error.no_token_title'), + description = Lang:t('error.no_token'), + type = 'error', + }) + + return false + end + + return true +end + +CreateThread(function() + + exports['qb-target']:AddTargetModel(models, { + options = { + { + num = 1, + icon = 'fas fa-gamepad', + label = Lang:t('target.arcade'), + action = function() + if not requireToken() then return end + lib.showMenu('arcade_machine') + end + }, + { + num = 2, + icon = 'fas fa-circle-dot', + label = Lang:t('target.special'), + action = function() + if not requireToken() then return end + lib.showMenu('arcade_hacking') + end + }, + }, + }) +end) + +AddEventHandler('onResourceStop', function(resource) + if resource == GetCurrentResourceName() then + for _, v in ipairs(models) do + exports['qb-target']:RemoveTargetModel(v, Lang:t('target.arcade')) + exports['qb-target']:RemoveTargetModel(v, Lang:t('target.special')) + end + end +end) \ No newline at end of file diff --git a/client/tokens.lua b/client/tokens.lua new file mode 100644 index 0000000..81e2328 --- /dev/null +++ b/client/tokens.lua @@ -0,0 +1,28 @@ +local function Nearby() + if IsControlJustPressed(0, 38) then + lib.showContext('arcade_purchase_token') + return + end +end + +CreateThread(function() + for _, v in ipairs(Config.Zones) do + lib.points.new({ + coords = v, + distance = 3, + + onEnter = function() + lib.showTextUI(Lang:t('interactions.enter_token_shop'), { + position = "left-center", + icon = 'e' + }) + end, + + onExit = function() + lib.hideTextUI() + end, + + nearby = Nearby + }) + end +end) \ No newline at end of file diff --git a/config.lua b/config.lua new file mode 100644 index 0000000..39b275b --- /dev/null +++ b/config.lua @@ -0,0 +1,113 @@ +Config = {} +QBCore = exports['qb-core']:GetCoreObject() + +-- Item that players get when they buy tokens and use to pay for a game. +Config.TokenItem = "gametoken" -- WIP (Item name: Game Token) +Config.TokenPrice = "5" +Config.PaymentType = "cash" -- WIP + +Config.Zones = { + vector3(-1654.7384033203, -1063.3900146484, 12.160423278809) +} + +Config.blip = { + coords = vector3(-1655.7844238281, -1066.8046875, 12.160425186157), + label = "Arcade", + sprite = 484, + color = 0, + scale = 0.7, + display = 2, +} + +Config.games = { + { + label = "Pacman", + args = "http://xogos.robinko.eu/PACMAN/", + icon = 'ghost' + }, + { + label = "Tetris", + args = "http://xogos.robinko.eu/TETRIS/", + icon = "cube" + }, + { + label = "Uno", + args = "https://duowfriends.eu/", + icon = "diamond" + }, + { + label = "FlappyParrot", + args = "http://xogos.robinko.eu/FlappyParrot/", + icon = "dove" + }, + { + label = 'slither', + args = 'http://slither.io', + icon = 'staff-snake', + }, + { + label = 'Duke Nukem 3D', + args = string.format("nui://qb-arcade/html/msdos.html?url=%s¶ms=%s", "https://www.retrogames.cz/dos/zip/duke3d.zip", "./DUKE3D.EXE"), + icon = 'gun' + }, + { + label = 'DOOM', + args = string.format("nui://qb-arcade/html/msdos.html?url=%s¶ms=%s", "https://www.retrogames.cz/dos/zip/Doom.zip", "./DOOM.EXE"), + icon = 'gun' + } +} + +Config.hacks = { + { + label = "Rondjes", + icon = 'fa-regular fa-circle', + action = function() + exports['ps-ui']:Circle(function(success) + if success then + QBCore.Functions.Notify("Je hebt de hack voltooid!", "success") + else + QBCore.Functions.Notify("Je hebt de hack gefaald!", "error") + end + end, 2, 20) -- NumberOfCircles, MS + end + }, + { + label = "Speurtocht", + icon = 'search', + action = function() + exports['ps-ui']:Maze(function(success) + if success then + QBCore.Functions.Notify("Je hebt de hack voltooid!", "success") + else + QBCore.Functions.Notify("Je hebt de hack gefaald!", "error") + end + end, 20) + end + }, + { + label = "VR", + icon = 'vr-cardboard', + action = function() + exports['ps-ui']:VarHack(function(success) + if success then + QBCore.Functions.Notify("Je hebt de hack voltooid!", "success") + else + QBCore.Functions.Notify("Je hebt de hack gefaald!", "error") + end + end, math.random(3,5), math.random(6,9)) + end + }, + { + label = "blokjes", + icon = 'fa-chess-board', + action = function() + exports['ps-ui']:Thermite(function(success) + if success then + QBCore.Functions.Notify("Je hebt de hack voltooid!", "success") + else + QBCore.Functions.Notify("Je hebt de hack gefaald!", "error") + end + end, 10, 5, 3) -- Time, Gridsize (5, 6, 7, 8, 9, 10), IncorrectBlocks + end + } +} \ No newline at end of file diff --git a/fxmanifest.lua b/fxmanifest.lua new file mode 100644 index 0000000..b0974a4 --- /dev/null +++ b/fxmanifest.lua @@ -0,0 +1,30 @@ +fx_version 'adamant' +game 'gta5' +lua54 'yes' + +client_scripts { + 'client/*', +} + +server_scripts { + 'server.lua', +} + +shared_scripts { + '@ox_lib/init.lua', + '@qb-core/shared/locale.lua', + 'locales/en.lua', + 'locales/*.lua', + 'config.lua' +} + +files { + "html/css/style.css", + "html/css/reset.css", + "html/css/img/monitor.png", + "html/css/img/table.png", + "html/*.html", + "html/scripts/listener.js", +} + +ui_page "html/index.html" \ No newline at end of file diff --git a/gametoken.png b/gametoken.png new file mode 100644 index 0000000..164fc2c Binary files /dev/null and b/gametoken.png differ diff --git a/html/css/img/monitor.png b/html/css/img/monitor.png new file mode 100644 index 0000000..d686d3c Binary files /dev/null and b/html/css/img/monitor.png differ diff --git a/html/css/reset.css b/html/css/reset.css new file mode 100644 index 0000000..af94440 --- /dev/null +++ b/html/css/reset.css @@ -0,0 +1,48 @@ +/* http://meyerweb.com/eric/tools/css/reset/ + v2.0 | 20110126 + License: none (public domain) +*/ + +html, body, div, span, applet, object, iframe, +h1, h2, h3, h4, h5, h6, p, blockquote, pre, +a, abbr, acronym, address, big, cite, code, +del, dfn, em, img, ins, kbd, q, s, samp, +small, strike, strong, sub, sup, tt, var, +b, u, i, center, +dl, dt, dd, ol, ul, li, +fieldset, form, label, legend, +table, caption, tbody, tfoot, thead, tr, th, td, +article, aside, canvas, details, embed, +figure, figcaption, footer, header, hgroup, +menu, nav, output, ruby, section, summary, +time, mark, audio, video { + margin: 0; + padding: 0; + border: 0; + font-size: 100%; + font: inherit; + vertical-align: baseline; +} +/* HTML5 display-role reset for older browsers */ +article, aside, details, figcaption, figure, +footer, header, hgroup, menu, nav, section { + display: block; +} +body { + line-height: 1; +} +ol, ul { + list-style: none; +} +blockquote, q { + quotes: none; +} +blockquote:before, blockquote:after, +q:before, q:after { + content: ''; + content: none; +} +table { + border-collapse: collapse; + border-spacing: 0; +} \ No newline at end of file diff --git a/html/css/style.css b/html/css/style.css new file mode 100644 index 0000000..0a20972 --- /dev/null +++ b/html/css/style.css @@ -0,0 +1,54 @@ +#loading{ + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + margin: auto; + max-width: 970px; + max-height: 30px; + width: 100%; + height: 100%; + background-color: #eee; + border-radius: 2px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.25) inset; +} + + +#cont{ + max-width: 1192px; + max-height: 602px; + height: 100%; + width: 100%; + background-image: url(./img/monitor.png); + background-size: 100% 100%; + padding: 38px; + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + margin: auto; +} + +#browser{ + height: 97%; + width: 100%; +} + + +a{ + color: #fff; + font-family: 'Montserrat', sans-serif; + background: black; + padding: 11px; + position: relative; + top: 19px; + left: 0px; + border-radius: 13px; +} + +a:hover{ + background: gray; + cursor: pointer; +} \ No newline at end of file diff --git a/html/index.html b/html/index.html new file mode 100644 index 0000000..1d0454d --- /dev/null +++ b/html/index.html @@ -0,0 +1,29 @@ + + + + + + + + + + + +
+ + + Arcade machine uitzetten +
+ + + + + \ No newline at end of file diff --git a/html/msdos.html b/html/msdos.html new file mode 100644 index 0000000..b9726e2 --- /dev/null +++ b/html/msdos.html @@ -0,0 +1,79 @@ + + + + + +js-dos api + + +
+ + + + + + \ No newline at end of file diff --git a/html/scripts/listener.js b/html/scripts/listener.js new file mode 100644 index 0000000..0327de8 --- /dev/null +++ b/html/scripts/listener.js @@ -0,0 +1,106 @@ +var gaming = false; +$(function(){ + function display(bool) { + if (bool) { + $("#body").show(); + } else { + $("#body").hide(); + } + } + display(false); + + window.addEventListener('message', function(event) { + var item = event.data; + if (item.type === "on") + { + $("#loading").show(); + alreadydid = true; + display(true); + gaming = true; + if(item.gpu === "ETX660") + { + $("#cont").css('max-height',300); + $("#cont").css('max-width',500); + } + if(item.gpu === "ETX1050") + { + $("#cont").css('max-height',700); + $("#cont").css('max-width',1100); + } + if(item.gpu === "ETX2080") + { + $("#cont").css('max-height',800); + $("#cont").css('max-width',1600); + } + + if(item.cpu === "U9_9900") { loadGame(3*10); } + if(item.cpu === "U7_8700") { loadGame(10*10); } + if(item.cpu === "U3_6300") { loadGame(15*10); } + if(item.cpu === "BENTIUM") { loadGame(20*10); } + } + if (item.type === "off") { + display(false); + loadIframe(true, ""); + gaming = false; + $("#loading").hide(); + alreadydid = false; + time_seconds = 0; + kokotina = 0; + } + + loadIframe(false, item.game); + }) +}); + +var url_game = ""; +var alreadydid = false; +var time_seconds = 0,kokotina = 0; +function loadGame(seconds) +{ + time_seconds = seconds; + $('#loading').attr('value', 0); + $('#loading').attr('max', seconds / 10); +} + +function progress() +{ + if(time_seconds == 0) + { + if(alreadydid == true){ + loadIframe(true, url_game); + alreadydid = false; + $("#loading").hide(); + } + kokotina = 0; + } + else + { + kokotina += 0.1; + time_seconds --; + $('#loading').attr('value', kokotina); + } + + setTimeout(progress, 100); +} +setTimeout(progress, 100); + +$(document).keyup(function(e) { + if (e.keyCode === 27){ + $.post('https://qb-arcade/exit', JSON.stringify({})); + } +}); + + +$( "#off_pc" ).click(function() { + $.post('https://qb-arcade/exit', JSON.stringify({})); +}); +function loadIframe(give,url) { + url_game = url; + if(give == false) return false; + var $iframe = $('#browser'); + if ( $iframe.length ) { + $iframe.attr('src',url); + return false; + } + return true; +} \ No newline at end of file diff --git a/locales/en.lua b/locales/en.lua new file mode 100644 index 0000000..4f0ed26 --- /dev/null +++ b/locales/en.lua @@ -0,0 +1,31 @@ +local Translations = { + menu = { + arcade = "Arcade cabinet", + special = "Special button!", + + purchase_token = "Purchase token | Price %s", + amount = "Amount", + }, + + target = { + arcade = "Arcade cabinet", + special = "Special button!!", + }, + + interactions = { + enter_token_shop = "Purchase gametoken" + }, + + error = { + no_token_title = "Arcade Cabinet", + no_token = "You need a Game Token to use this.", + + not_enough_money_title = "Gametokens", + not_enough_money = "You don't have enough money to buy this amount of tokens.", + }, +} + +Lang = Lang or Locale:new({ + phrases = Translations, + warnOnMissing = true +}) diff --git a/locales/nl.lua b/locales/nl.lua new file mode 100644 index 0000000..922efc6 --- /dev/null +++ b/locales/nl.lua @@ -0,0 +1,34 @@ +local Translations = { + menu = { + arcade = "Arcade kast", + special = "Speciale knop", + + purchase_token = "Koop token | Prijs: %s", + amount = "Aantal", + }, + + target = { + arcade = "Arcade kast", + special = "Speciale knop kab00m!", + }, + + interactions = { + enter_token_shop = "Gametokens inkopen" + }, + + error = { + no_token_title = "Arcadekast", + no_token = "Je hebt een gametoken nodig om een spelletje te kunnen spelen.", + + not_enough_money_title = "Gametokens", + not_enough_money = "Je hebt niet voldoende geld om een gametoken te kopen.", + } +} + +if GetConvar('qb_locale', 'en') == 'nl' then + Lang = Locale:new({ + phrases = Translations, + warnOnMissing = true, + fallbackLang = Lang, + }) +end diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..d896a8a --- /dev/null +++ b/readme.md @@ -0,0 +1,29 @@ +WIP: +- Locales +- Token Item +- Token Price +- Zones waar je een item kan kopen (OX menu met informatie over de prijs en waar je aantal tokens kan instellen en dan koop knop.) +- Controle of je een token hebt om een spel te spelen. +- In kunnen stellen bij normale spellen hoeveel tokens het kost. +- In kunnen stellen bij hacks hoeveel tokens het kost. +- Wanner iemand niet beschikt over een token bij de game melding in de zin van "Je hebt X token(s) nodig om dit spel te kunnen spelen" (in locales). + + +-- Voor de uit eindelijke Readme. + +['gametoken'] = { + ['name'] = 'gametoken', + ['label'] = 'Game Token', + ['weight'] = 100, + ['type'] = 'item', + ['image'] = 'gametoken.png', + ['unique'] = false, + ['useable'] = false, + ['shouldClose'] = false, + ['combinable'] = nil, + ['description'] = 'Om een spelletje mee te spelen in de Arcade.' +}, + +MLO's +- Gabz Arcade +- https://www.gta5-mods.com/maps/arcade-bar-interior-mlo-fivem-sp \ No newline at end of file diff --git a/server.lua b/server.lua new file mode 100644 index 0000000..dd18e40 --- /dev/null +++ b/server.lua @@ -0,0 +1,29 @@ +lib.callback.register('qb-arcade:server:hasToken', function(source) + local src = source + local player = QBCore.Functions.GetPlayer(src) + local hasToken = player.Functions.GetItemByName(Config.TokenItem) + if hasToken ~= nil then + player.Functions.RemoveItem(Config.TokenItem, 1) + return true + else + return false + end +end) + +RegisterNetEvent('qb-arcade:server:buyToken', function(amount) + local price = Config.TokenPrice * amount + + local player = QBCore.Functions.GetPlayer(source) + + if not player then return end + if not player.Functions.RemoveMoney(Config.PaymentType, price, 'arcade-token-purchase') then + TriggerClientEvent('ox_lib:notify', source, { + title = Lang:t('error.not_enough_money_title'), + description = Lang:t('error.not_enough_money'), + type = 'error', + }) + return + end + + player.Functions.AddItem(Config.TokenItem, amount) +end) \ No newline at end of file