Skip to content

Commit

Permalink
feat: report system and bug fixes
Browse files Browse the repository at this point in the history
* Implement #24

Implement #24

* Resolve issues with weapons not adding

* Remove due to ugly overflow

* Fix kill and revive player

* Fix view inventory

* Remove old customs option

* Give keys on plate change

* Fix issue where it wouldn't give money
  • Loading branch information
Scullyy authored Apr 19, 2024
1 parent c2000bf commit d5bd874
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 36 deletions.
5 changes: 4 additions & 1 deletion client/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ lib.registerMenu({
{label = locale('main_options.label2'), description = locale('main_options.desc2'), icon = 'fas fa-user', args = {'qbx_adminmenu_players_menu'}},
{label = locale('main_options.label3'), description = locale('main_options.desc3'), icon = 'fas fa-server', args = {'qbx_adminmenu_server_menu'}},
{label = locale('main_options.label4'), description = locale('main_options.desc4'), icon = 'fas fa-car', args = {'qbx_adminmenu_vehicles_menu'}},
{label = locale('main_options.label5'), description = locale('main_options.desc5'), icon = 'fas fa-toolbox', args = {'qbx_adminmenu_dev_menu'}}
{label = locale('main_options.label5'), description = locale('main_options.desc5'), icon = 'fas fa-toolbox', args = {'qbx_adminmenu_dev_menu'}},
{label = locale('main_options.label6'), description = locale('main_options.desc6'), icon = 'fas fa-list', args = {'qbx_adminmenu_reports_menu'}}
}
}, function(_, _, args)
if args[1] == 'qbx_adminmenu_players_menu' then
GeneratePlayersMenu()
elseif args[1] == 'qbx_adminmenu_reports_menu' then
GenerateReportMenu()
else
lib.showMenu(args[1], MenuIndexes[args[1]])
end
Expand Down
8 changes: 6 additions & 2 deletions client/player.lua
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ function GeneratePlayersMenu()
end
local optionsList = {}
for i = 1, #players do
optionsList[#optionsList + 1] = {label = string.format('ID: %s | Name: %s', players[i].id, players[i].name), description = string.format('CID: %s | %s', players[i].cid, players[i].license), args = {players[i]}}
optionsList[#optionsList + 1] = {label = string.format('ID: %s | Name: %s', players[i].id, players[i].name), description = string.format('CID: %s', players[i].cid), args = {players[i]}}
end
lib.registerMenu({
id = 'qbx_adminmenu_players_menu',
Expand Down Expand Up @@ -283,7 +283,7 @@ lib.registerMenu({
}
}, function(selected)
if selected == 1 then
ExecuteCommand(('viewinv %s'):format(selectedPlayer.id))
exports.ox_inventory:openInventory('player', selectedPlayer.id)
elseif selected == 2 then
local succeeded = lib.callback.await('qbx_admin:server:clothingMenu', false, selectedPlayer.id)
if succeeded then return end
Expand All @@ -302,3 +302,7 @@ lib.registerMenu({
exports['pma-voice']:toggleMutePlayer(selectedPlayer.id)
end
end)

RegisterNetEvent('qbx_admin:client:killPlayer', function()
SetEntityHealth(cache.ped, 0)
end)
98 changes: 98 additions & 0 deletions client/reports.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
local reportOptions = {
function(report)
lib.alertDialog({
header = string.format('Report ID: %s | Sender: %s', report.id, report.senderName),
content = report.message,
centered = true,
cancel = false,
size = 'lg',
labels = {
confirm = 'Close'
}
})

lib.showMenu(('qbx_adminmenu_reports_menu_%s'):format(report.id), MenuIndexes[('qbx_adminmenu_reports_menu_%s'):format(report.id)])
end,
function(report)
local input = lib.inputDialog(string.format('Report ID: %s | Sender: %s', report.id, report.senderName), {
{type = 'input', label = 'Reply'}
})

if not input then
exports.qbx_core:Notify(locale('error.no_report_reply'), 'error')
else
TriggerServerEvent('qbx_admin:server:sendReply', report, input[1])
end

lib.showMenu(('qbx_adminmenu_reports_menu_%s'):format(report.id), MenuIndexes[('qbx_adminmenu_reports_menu_%s'):format(report.id)])
end,
function(report)
TriggerServerEvent('qbx_admin:server:deleteReport', report)

GenerateReportMenu()
end
}

function GenerateReportMenu()
local reports = lib.callback.await('qbx_admin:server:getReports', false)

if not reports or #reports < 1 then
lib.showMenu('qbx_adminmenu_main_menu', MenuIndexes.qbx_adminmenu_main_menu)
return
end

local optionsList = {}

for i = 1, #reports do
optionsList[#optionsList + 1] = {label = string.format('Report ID: %s | Sender: %s', reports[i].id, reports[i].senderName), description = locale('report_options.desc1'), args = {reports[i]}}
end

lib.registerMenu({
id = 'qbx_adminmenu_reports_menu',
title = locale('title.reports_menu'),
position = 'top-right',
onClose = function(keyPressed)
CloseMenu(false, keyPressed, 'qbx_adminmenu_main_menu')
end,
onSelected = function(selected)
MenuIndexes.qbx_adminmenu_reports_menu = selected
end,
options = optionsList
}, function(_, _, args)
local report = args[1]

lib.registerMenu({
id = ('qbx_adminmenu_reports_menu_%s'):format(report.id),
title = string.format('Report ID: %s | Sender: %s', report.id, report.senderName),
position = 'top-right',
onClose = function(keyPressed)
CloseMenu(false, keyPressed, 'qbx_adminmenu_reports_menu')
end,
onSelected = function(selected)
MenuIndexes[('qbx_adminmenu_reports_menu_%s'):format(report.id)] = selected
end,
options = {
{label = 'View Message', icon = 'fas fa-message'},
{label = 'Send Message', icon = 'fas fa-reply'},
{label = 'Close Report', icon = 'fas fa-trash'},
{label = string.format('Claimed By: %s', report.claimed)},
{label = string.format('Report ID: %s', report.id)},
{label = string.format('Sender ID: %s', report.senderId)},
{label = string.format('Sender Name: %s', report.senderName)}
}
}, function(selected)
local reportOption = reportOptions[selected]

if not reportOption then
lib.showMenu(('qbx_adminmenu_reports_menu_%s'):format(report.id), MenuIndexes[('qbx_adminmenu_reports_menu_%s'):format(report.id)])
return
end

reportOption(report)
end)

lib.showMenu(('qbx_adminmenu_reports_menu_%s'):format(report.id), MenuIndexes[('qbx_adminmenu_reports_menu_%s'):format(report.id)])
end)

lib.showMenu('qbx_adminmenu_reports_menu', MenuIndexes.qbx_adminmenu_reports_menu)
end
26 changes: 5 additions & 21 deletions client/vehicle.lua
Original file line number Diff line number Diff line change
Expand Up @@ -114,33 +114,16 @@ lib.registerMenu({
lib.showMenu('qbx_adminmenu_vehicles_menu', MenuIndexes.qbx_adminmenu_vehicles_menu)
return
end
local override = {
coords = GetEntityCoords(cache.ped),
heading = GetEntityHeading(cache.ped),
categories = {
mods = true,
repair = true,
armor = true,
respray = true,
liveries = true,
wheels = true,
tint = true,
plate = true,
extras = true,
neons = true,
xenons = true,
horn = true,
turbo = true,
cosmetics = true,
},
}
TriggerEvent('qb-customs:client:EnterCustoms', override)

-- New customs needs a way to open it from other resources
exports.qbx_core:Notify('Currently no support for new customs', 'error')
elseif selected == 6 then
if not cache.vehicle then
exports.qbx_core:Notify('You have to be in a vehicle, to use this', 'error')
lib.showMenu('qbx_adminmenu_vehicles_menu', MenuIndexes.qbx_adminmenu_vehicles_menu)
return
end

local dialog = lib.inputDialog('Custom License Plate (Max. 8 characters)', {'License Plate'})

if not dialog or not dialog[1] or dialog[1] == '' then
Expand All @@ -157,6 +140,7 @@ lib.registerMenu({
end

SetVehicleNumberPlateText(cache.vehicle, dialog[1])
TriggerEvent('qb-vehiclekeys:client:AddKeys', dialog[1])
end
end)

Expand Down
1 change: 1 addition & 0 deletions config/server.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
return {
commandPerms = {
useMenu = 'mod',
reportReply = 'mod',
noclip = 'mod',
names = 'mod',
blips = 'mod',
Expand Down
18 changes: 14 additions & 4 deletions locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"dev_menu": "Developer Options",
"main_menu": "Admin Menu",
"players_menu": "Online Players",
"server_menu": "Manage Server"
"server_menu": "Manage Server",
"reports_menu": "Reports"
},
"main_options": {
"label1": "Admin Options",
Expand All @@ -16,7 +17,9 @@
"label4": "Vehicles",
"desc4": "All about vehicles here",
"label5": "Developer Options",
"desc5": "Options that are handy for a developer"
"desc5": "Options that are handy for a developer",
"label6": "Pending Reports",
"desc6": "Someone needs to do it :("
},
"admin_options": {
"label1": "Noclip",
Expand Down Expand Up @@ -141,15 +144,22 @@

}
},
"report_options": {
"desc1": "Click to view report options"
},
"success": {
"blips_activated": "Blips activated",
"names_activated": "Names activated",
"coords_copied": "Coordinates copied to clipboard",
"heading_copied": "Heading copied to clipboard"
"heading_copied": "Heading copied to clipboard",
"report_sent": "Report has been sent",
"new_report": "A new report has been received",
"sent_report_reply": "Your reply has been sent"
},
"error": {
"no_perms": "You don't have permission to do this",
"blips_deactivated": "Blips deactivated",
"names_deactivated": "Names deactivated"
"names_deactivated": "Names deactivated",
"no_report_reply": "Reply failed to send due to no message"
}
}
11 changes: 10 additions & 1 deletion server/commands.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
local config = require 'config.server'.commandPerms

lib.addCommand('report', {
help = 'Send Report',
params = {
{name = 'report', help = 'Your report message', type = 'string'}
}
}, function(source, args, raw)
SendReport(source, string.sub(raw, 8))
end)

lib.addCommand('admin', {
help = 'Opens Adminmenu',
help = 'Opens Admin Menu',
restricted = config.useMenu,
}, function(source)
TriggerClientEvent('qbx_admin:client:openMenu', source)
Expand Down
79 changes: 72 additions & 7 deletions server/main.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,42 @@
local config = require 'config.server'
local isFrozen = {}

REPORTS = {}

--- Trigger something on players who have the passed permission
--- @param permission string - The required permission
--- @param cb function - The function, will return player object as parameter
function OnAdmin(permission, cb)
for k, v in pairs(exports.qbx_core:GetQBPlayers()) do
if IsPlayerAceAllowed(k, permission) then
cb(v)
end
end
end

--- Sends a report to online staff members
--- @param source string - The player's ID
--- @param message string - Message for the report
function SendReport(source, message)
local reportId = #REPORTS + 1

REPORTS[reportId] = {
id = reportId,
senderId = source,
senderName = GetPlayerName(source),
message = message,
claimed = 'Nobody'
}

table.sort(REPORTS, function(a, b) return a.id < b.id end)

exports.qbx_core:Notify(source, locale('success.report_sent'), 'success')

OnAdmin(config.commandPerms.reportReply, function(target)
exports.qbx_core:Notify(target.PlayerData.source, locale('success.new_report'), 'success')
end)
end

--- Checks if the source is inside of the target's routingbucket
--- if not set the source's routingbucket to the target's
--- @param source string - The player's ID
Expand All @@ -11,9 +47,35 @@ function CheckRoutingbucket(source, target)
if sourceBucket ~= targetBucket then SetPlayerRoutingBucket(source, targetBucket) end
end

RegisterNetEvent('qbx_admin:server:sendReply', function(report, message)
if not IsPlayerAceAllowed(source, config.commandPerms.reportReply) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end

if REPORTS[report.id] then
local name = GetPlayerName(source)

TriggerClientEvent('chatMessage', report.senderId, "", {255, 0, 0}, string.format('[REPORT #%s] [%s] ^7%s', report.id, name, message))

exports.qbx_core:Notify(source, locale('success.sent_report_reply'), 'success')

if REPORTS[report.id].claimed == 'Nobody' then
REPORTS[report.id].claimed = name

OnAdmin(config.commandPerms.reportReply, function(target)
exports.qbx_core:Notify(target.PlayerData.source, string.format('Report #%s was claimed by %s', report.id, name), 'success')
end)
end
end
end)

RegisterNetEvent('qbx_admin:server:deleteReport', function(report)
if not IsPlayerAceAllowed(source, config.commandPerms.reportReply) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end

REPORTS[report.id] = nil
end)

local generalOptions = {
function(selectedPlayer) TriggerClientEvent('hospital:client:KillPlayer', selectedPlayer.id) end,
function(selectedPlayer) TriggerClientEvent('hospital:client:Revive', selectedPlayer.id) end,
function(selectedPlayer) TriggerClientEvent('qbx_admin:client:killPlayer', selectedPlayer.id) end,
function(selectedPlayer) TriggerClientEvent('qbx_medical:client:playerRevived', selectedPlayer.id) end,
function(selectedPlayer)
if isFrozen[selectedPlayer.id] then
FreezeEntityPosition(GetPlayerPed(selectedPlayer.id), false)
Expand Down Expand Up @@ -92,12 +154,10 @@ local playerDataOptions = {
crafting = function(target, input) target.Functions.SetMetaData('craftingrep', input[1]) end,
dealer = function(target, input) target.Functions.SetMetaData('dealerrep', input[1]) end,
cash = function(target, input)
target.PlayerData.moneycash = input[1]
target.Functions.SetPlayerData('money', target.PlayerData.money)
target.Functions.SetMoney('cash', input[1], 'qbx_adminmenu')
end,
bank = function(target, input)
target.PlayerData.moneybank = input[1]
target.Functions.SetPlayerData('money', target.PlayerData.money)
target.Functions.SetMoney('bank', input[1], 'qbx_adminmenu')
end,
job = function(target, input)
target.Functions.SetJob(input[1], input[2])
Expand Down Expand Up @@ -125,7 +185,6 @@ RegisterNetEvent('qbx_admin:server:giveAllWeapons', function(weaponType, playerI
if not IsPlayerAceAllowed(source, config.eventPerms.giveAllWeapons) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end

for i = 1, #config.weaponList[weaponType], 1 do
if not exports.ox_inventory:Items()[config.weaponList[weaponType][i]] then return end
target.Functions.AddItem(config.weaponList[weaponType][i], 1)
end
end)
Expand Down Expand Up @@ -234,3 +293,9 @@ lib.callback.register('qbx_admin:server:spawnVehicle', function(source, model)
exports.qbx_vehiclekeys:GiveKeys(source, plate)
return netId
end)

lib.callback.register('qbx_admin:server:getReports', function(source)
if not IsPlayerAceAllowed(source, config.commandPerms.reportReply) then exports.qbx_core:Notify(source, locale('error.no_perms'), 'error') return end

return REPORTS
end)

0 comments on commit d5bd874

Please sign in to comment.