29 Commits

Author SHA1 Message Date
Jim Shield
c6ef0897fc Release Notifier Push 2025-09-24 18:18:57 +01:00
Jim Shield
afe79273d5 Update notify-discord.yml 2025-09-04 17:00:39 +01:00
Jim Shield
bc694fa850 Create release.yml
Automate release zips and make them generate the folder name correctly

This helps users download a correctly named script so they dont end up with a script with a version number in the title
2025-09-01 10:23:35 +01:00
Jim Shield
8cf3257da9 Set Usebzzz to false in default config
Left this on when testing, sorry :(
2025-07-28 12:40:53 +01:00
Jim Shield
4e80be9b30 Update notify-discord.yml 2025-07-27 18:48:55 +01:00
Jim Shield
c657beb323 Update README.md 2025-07-24 22:52:34 +01:00
Jim Shield
be43ade5fb Version Bump
`3.0.04` - `3.0.05`
2025-06-10 00:43:45 +01:00
Jim Shield
5a3556ad2c swap phone charging to jim_bridge function 2025-06-08 22:38:07 +01:00
Jim Shield
597e8d9336 Add new feature "lookAtCharge"
New feature added, and set to default

Allows for simply looking at a player to get their server id and start charging them instead of creating a list or asking their user id.
2025-06-08 22:37:46 +01:00
Jim Shield
874eee530c add extra check for if playerdata exists or not 2025-06-03 02:22:25 +01:00
Jim Shield
ee11d79fa6 Version Bump
`3.0.03` - `3.0.04`
2025-06-01 21:48:25 +01:00
Jim Shield
784d13914f Separate and fix ped loading for tickets/banks
I unified the bank locations and ticket cash in locations and forgot that people disable the banking part of the script

Now, if Banks and `CashInAnywhere` is disabled, it creates a separate ped for tickets only (default location is pacific bank)

If Banks are enabled, but `CashInAnywhere` is disabled, it creates the separate ped also

If Banks are enabled AND `CashInAnywhere` is enabled, the separate ped won't be used and the bank peds will share the target options
2025-06-01 21:44:29 +01:00
Jim Shield
10f14f846e Fix typo for Gabz default cash in location 2025-06-01 21:38:56 +01:00
Jim Shield
1ca2e45a37 add workaround for if onlineList is nil 2025-05-26 18:59:10 +01:00
Jim Shield
2e3fef8846 fix job/gang lock of custom cash registers 2025-05-26 18:58:17 +01:00
Jim Shield
1b69b44f5c fix custom cash registers spawn offset location 2025-05-26 18:51:18 +01:00
Jim Shield
d252ce6a02 Version Bump
`3.0.02` - `3.0.03`
2025-05-21 11:00:23 +01:00
Jim Shield
4bc2aaa95f Re-add terminal item and info 2025-05-21 10:59:07 +01:00
Jim Shield
fdf92fde64 fix custom cash register function 2025-05-21 10:49:14 +01:00
Jim Shield
954b208016 add if statement to prop removal, just incase 2025-05-19 15:20:26 +01:00
Jim Shield
51265681c1 Update README.md 2025-05-19 15:16:53 +01:00
Jim Shield
6ab839e2a3 Unify cashregister and terminal commands
This makes `/cashregister` and `/terminal` the same, since they were already.

(I kept both as not to confuse people if one went missing)

`/terminal` originally was added to make use of the `bzzz_terminal` prop and anim, but now it works with both commands if enabled in the config
2025-05-19 15:04:28 +01:00
Jim Shield
9eb2e987d4 Version Bump
`3.0.01` - `3.0.02`
2025-05-14 20:25:05 +01:00
Jim Shield
e73520a10c Tidy up the double check for commPercent
Left in the old code for commission calculation

I don't think it was making a difference but it wasn't needed
2025-05-14 20:24:47 +01:00
Jim Shield
f869c682c1 fix missing variable for polcharge
Fixes missing variable when using /polcharge and the confirmation option
2025-05-14 20:23:41 +01:00
Jim Shield
ca625c50e2 fix duplicate text entry for charging users
Apparently missed this completely, removed the duplicate text entry when not using the list option

this should fix any issues with this
2025-05-14 20:23:03 +01:00
Jim Shield
49f4d404e3 place start functions behind onResourceStart()
ESX helper
2025-05-12 22:49:28 +01:00
Jim Shield
2b92f749b5 Refactor a couple files for readability 2025-05-12 10:49:00 +01:00
Jim Shield
5e80192cef Update fxmanifest.lua to new format
Removes core loading in `fxmanifest.lua` in favour of more "verbose" file loader in jim_bridge v`2.0.08+`
2025-05-10 20:08:03 +01:00
18 changed files with 712 additions and 372 deletions

12
.gitattributes vendored Normal file
View File

@@ -0,0 +1,12 @@
# VCS / CI noise
.gitattributes export-ignore
.gitignore export-ignore
.github/** export-ignore
.gitmodules export-ignore
# Dev tooling/config
.vscode/** export-ignore
*.code-workspace export-ignore
.editorconfig export-ignore
.eslintrc* export-ignore
.prettier* export-ignore

View File

@@ -3,15 +3,16 @@ name: Discord Commit Notifier
on:
push:
branches:
- '*' # triggers on all branches
- '*'
jobs:
notify:
runs-on: ubuntu-latest
steps:
- name: Discord Commits
uses: Sniddl/discord-commits@v1.6
with:
webhook: ${{ secrets.DISCORD_WEBHOOK }}
template: "avatar-with-link"
include-extras: true
- name: Send commit payload to Discord Bot
env:
URL: http://${{ secrets.DISCORDBOT }}:3000/github-commits
run: |
curl -sS -X POST "$URL" \
-H 'Content-Type: application/json' \
--data-binary "@$GITHUB_EVENT_PATH"

71
.github/workflows/notify-release.yml vendored Normal file
View File

@@ -0,0 +1,71 @@
name: Discord Release Notifier
on:
# Manual or UI-published releases
release:
types: [published]
# Releases created by your tag-driven workflow
workflow_run:
workflows: ["Package & Release"] # must match the 'name:' in release.yml
types: [completed]
permissions:
contents: read
jobs:
# 1) Handle manual / UI / non-workflow-created releases
notify-from-release:
if: github.event_name == 'release' && github.event.action == 'published'
runs-on: ubuntu-latest
steps:
- name: Send release payload to Discord Bot
env:
URL: http://${{ secrets.DISCORDBOT }}:3000/github-releases
run: |
curl -sS -X POST "$URL" \
-H 'Content-Type: application/json' \
--data-binary "@$GITHUB_EVENT_PATH"
# 2) Handle releases created by your 'Package & Release' workflow
# (which wont trigger `on: release` when using GITHUB_TOKEN)
notify-from-workflow-run:
if: >
github.event_name == 'workflow_run' &&
github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
steps:
- name: Install jq
run: sudo apt-get update && sudo apt-get install -y jq
- name: Fetch release JSON by tag
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
OWNER="${GITHUB_REPOSITORY%/*}"
REPO="${GITHUB_REPOSITORY#*/}"
TAG="${{ github.event.workflow_run.head_branch }}"
# head_branch is the tag name for a tag push workflow_run
curl -fsSL -H "Authorization: Bearer $GH_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/$OWNER/$REPO/releases/tags/$TAG" \
> release.json
- name: Wrap as 'release' event payload & notify bot
env:
URL: http://${{ secrets.DISCORDBOT }}:3000/github-releases
run: |
set -euo pipefail
jq -n --slurpfile rel release.json \
--arg repo "$GITHUB_REPOSITORY" \
--arg repo_url "https://github.com/$GITHUB_REPOSITORY" \
--arg action "published" '
{ action: $action,
repository: { full_name: $repo, html_url: $repo_url },
release: $rel[0],
sender: { login: "github-actions[bot]" } }' > payload.json
curl -sS -X POST "$URL" \
-H 'Content-Type: application/json' \
--data-binary "@payload.json"

88
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,88 @@
name: Package & Release
on:
push:
tags:
- "v*"
- "*.*.*"
permissions:
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout (full history)
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Derive vars
id: vars
shell: bash
run: |
echo "name=${GITHUB_REPOSITORY##*/}" >> $GITHUB_OUTPUT # e.g. jim_bridge
echo "version=${GITHUB_REF_NAME#v}" >> $GITHUB_OUTPUT # strip leading v
- name: Build zip with folder prefix
shell: bash
run: |
NAME='${{ steps.vars.outputs.name }}'
VER='${{ steps.vars.outputs.version }}'
git archive --format=zip --prefix="${NAME}/" -o "${NAME}-${VER}.zip" "$GITHUB_REF_NAME"
ls -lh "${NAME}-${VER}.zip"
# --- Patch notes generation (commit titles + links) -------------------
- name: Find previous tag (SemVer aware)
id: prev
shell: bash
run: |
CUR="${GITHUB_REF_NAME}"
# Sort tags by version desc, drop the current, take the next newest
PREV=$(git tag --sort=-v:refname | grep -v -x "$CUR" | head -n 1 || true)
echo "prev=$PREV" >> $GITHUB_OUTPUT
echo "Previous tag: ${PREV:-<none>}"
- name: Generate RELEASE_NOTES.md from commits
shell: bash
run: |
REPO="${{ github.repository }}"
CUR="${GITHUB_REF_NAME}"
PREV='${{ steps.prev.outputs.prev }}'
if [ -n "$PREV" ]; then
RANGE="$PREV..$CUR"
HEADER="## Changes in $CUR"
else
# First release: include all commits
ROOT=$(git rev-list --max-parents=0 HEAD | tail -n 1)
RANGE="$ROOT..$CUR"
HEADER="## Changes"
fi
{
echo "$HEADER"
echo
# Oldest → newest, subject only, skip merge commits
# Escape '[' and ']' so markdown doesn't break on rare titles
git log --reverse --no-merges --pretty=format:'- ['%h'] - %s' "$RANGE" \
| perl -pe 's/([\[\]])/\\$1/g'
} > RELEASE_NOTES.md
echo "--- RELEASE_NOTES.md ---"
cat RELEASE_NOTES.md
echo "------------------------"
- name: Create / Update GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ github.ref_name }}
name: ${{ github.ref_name }}
files: |
*.zip
body_path: RELEASE_NOTES.md # attach our generated notes
# If you wanted GitHub's auto notes instead, set:
# generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

228
README.md
View File

@@ -1,208 +1,28 @@
# jim-payments
- QBCore based payment system
- Enchanced QB-Input payment system from my other scripts now free on its own
## FiveM MuliFramework based payment system
- Highly customisable via config.lua
- Locations are easily changeable/removable
- Features:
- Payment Tickets for successful payments over a specific amount player can cash in for extra bonus
- ATM's become usable, with options to show them on your map when nearby
- Adds Ped bank targets where players can manage their bank account balances
- Supports police charges
- Supports
- QB-Core
- ESX
- QBOX
- OX_Core
---
# Installation and Usage:
## [JixelPatterns GitBook Documentation](https://jixelpatterns.gitbook.io/docs)
### If you need support I have a discord server available, it helps me keep track of issues and give better support.
## https://discord.gg/xKgQZ6wZvS
## [JixelPatterns Discord](https://discord.gg/9pCDHmjYwd)
### We also have Documentation over on Gitbook, feel free to check it out
## https://jixelpatterns.gitbook.io/jixelpatterns-script-guide/overview/who-we-are
### If you think I did a good job here, consider donating as it keeps by lights on and my cat fat/floofy:
## https://ko-fi.com/jixelpatterns
---
- If you use a different phone/invoice system let me know and I will add support for it as best I can!
- Currently supported are:
- qb-phone
- gks-phone
- qs-smartphone - Leave the setting as "qb"
---
# Installation
---
- I always recommend starting my scripts AFTER `[qb]` not inside it as it can mess with any dependancies on server load
- I have a separate folder called `[jim]` (that is also in the resources folder) that starts WAY after everything else.
- This ensure's it has everything it requires before trying to load
- Example of my load order:
```CSS
# QBCore & Extra stuff
ensure qb-core
ensure [qb]
ensure [standalone]
ensure [voice]
ensure [defaultmaps]
ensure [vehicles]
#Extra Jim Stuff
ensure [jim]
```
---
## BZZ Terminal Instructions
Free Package https://bzzz.tebex.io/package/5551076
Stream the prop and add the emote that is provided to rpemotes or dpemotes
```lua
['terminal'] = {['name'] = 'terminal', ['label'] = 'Wireless Terminal', ['weight'] = 5000, ["type"] = "item", ["image"] = 'terminal.png', ['unique'] = true, ['useable'] = true, ["shouldClose"] = true, ["combinable"] = nil, ['description'] = ''},
```
---
## Item installation
- To make use of the ticket reward system for workers you need to add the ticket item to your shared items lua
- Naviage to `[qb] > qb-core / shared / items.lua` and add this line
```lua
payticket = { name = "payticket", label = "Receipt", weight = 10, type = "item", image = "ticket.png", unique = false, useable = false, shouldClose = false, description = "Cash these in at the bank!" },
```
- Add the ticket image to your inventory script:
- Naviage to `[qb] > qb-inventory > html > images` and add this line
![](https://github.com/jimathy/jim-payments/blob/main/images/ticket.png?raw=true)
---
## Phone Setup
- There are two modes in the script, one that uses the phone for invoices/bank charges
- The script supports many features like pay tickets, commission payments etc.
- If you want to use phone systems for these then you need to add the event for when a payment is accepted:
- REMINDER: IF using phone invoices, the money being added to the society accounts is handled `BY THE PHONE`, not by my script. If money isn't going to the account its the phone system or bossmenu script.
#### QB-Phone:
- Go to `[qb] > qb-phone > client > main.lua`
- Search for the event `RegisterNUICallback('PayInvoice', function(data, cb)` and look for the line:
```lua
TriggerServerEvent('qb-phone:server:BillingEmail', data, true)
```
- Directly *above* this line add:
```lua
TriggerServerEvent('jim-payments:Tickets:Give', data)
```
- The phone should now be integrated with jim-payments
#### GKS-Phone:
- Go to `gks-phone > server > serverapi.lua`
- Search for the event: `gksphone:faturapayBill` and search for this line:
```lua
Ply.Functions.RemoveMoney('bank', data[1].amount, "paid-invoice")
```
- Directly under this line add this event:
```lua
TriggerEvent('jim-payments:Tickets:Give', { sender = Ply.PlayerData.charinfo.firstname, senderCitizenId = data[1].sendercitizenid, society = data[1].society, amount = data[1].amount })
```
- The phone should now be integrated with jim-payments
#### Renewed QB-Phone:
- Go to `qb-phone > server > invoices.lua`
- Search for the event: `qb-phone:server:PayMyInvoice` and search for this line:
```lua
TriggerEvent("qb-phone:server:InvoiceHandler", true, amount, src, resource)
```
- Directly under this line add this event:
```lua
TriggerEvent('jim-payments:Tickets:Give', { amount = amount, senderCitizenId = sendercitizenid, sender = SenderPly.PlayerData.charinfo.firstname, society = society }, SenderPly)
```
- When invoices are paid, they should now be integrated with jim-payments
# Setup/Config
## Custom Locations
- You can make of this payment system for a job script that wasn't created by me
- All you need to do is add the job, grab a `vector4` (vector3 + heading) and set if you need a to spawn prop or not
- For example:
```lua
CustomCashRegisters = { -- Located in the config.lua
["burgershot"] = { -- Player job role restriction
{ coords = vector4(-1185.5, -878.54, 13.91, 305.53), prop = true, }, -- vector4 to place the till and the way it faces
{ coords = vector4(-1184.34, -880.51, 13.93, 302.04), prop = true, }, -- "prop = true" spawns a prop at the coords
},
},
```
### This does not need to be done for MY job scripts, they already have built in support
---
## PayTickets
![](https://i.imgur.com/ICbQyeQ.jpeg)
- This script has a built in ticket reward system
- On successful sale, the employees will be handed a ticket if they are clocked in
- This can then be handed in to the bank to receive payment
- Works as a reward and incentive for turning up to do work
- The values are set per job in `Config.Jobs`
- `TicketSystem` Enable this if you want to use the ticket system false
- `TicketSystemAll` Enable this to give tickets to all workers clocked in
---
## Commission System
- Support for commission to be paid as a reward for each successful payment
- Very customisable with the config.lua
- `Commission` Choose wether people get commission from every sale
- `CommissionAll` Choose if **EVERY** worker gets Commission that is on duty
- `CommissionDouble` Choose if Commission is limited by `MinAmountForTicket`
- `CommissionLimit` Choose if the worker charging the customer gets double commission
---
## Multiple Job and Gang Role support
- The script supports adding job roles to the config so they can get rewards for successful payments
- This includes Gang roles for stores/bars owned by a gang allowing them to get ticket rewards and commission
- Examples of adding jobs / gangs to config.lua:
```lua
Jobs = {
['mechanic'] = { MinAmountforTicket = 1000, PayPerTicket = 500, Commission = 0.10, },
['lostmc'] = { MinAmountforTicket = 50, PayPerTicket = 50, Commission = 0.10, gang = true, },
},
```
- `MinAmountforTicket` is the amount required in a charge before they can get a ticket
- `PayPerTicket` is the amount paid per ticket at the bank for the job role
- I personally recommend this being lower than `MinAmountforTicket`, being too high makes it exploitable
- `Commission` is the amount of commission given to players on successful payments (0.10 = 10%)
- `gang = true` add this if the added role is a gang role
---
## /cashgive
![](https://i.imgur.com/AIdXzxX.jpeg)
- Alternative to /givecash
- A simple command built in to send cash to a `nearby player`
- Shows a list of names and id's of people nearby to select from rather
- Better experience than trying to figure out their ID and entering it manually
---
## /cashregister
![](https://i.imgur.com/37d2mE3.jpeg)
- This command is mean't as a portable cash register alternative
- For example:
- When a person is devliering food they can do `/cashregister` and the payment will still be sent to the society account
- Doesn't utilize the ticket reward system unfortunately
---
## /polcharge
- This script supports a customisable "police billing"
- This is the ability for selected jobroles to charge a nearby player
- Depending on how you've set it up, this can take money directly from the players bank to the job's society account
- This is by default enabled for `police` and `ambulance`
- This also supports giving the player a cut of the payment as `commission`
- Default Config:
```lua
FineJobs = {
['police'] = { Commission = 0.25, },
['ambulance'] = { Commission = 0.25, },
},
FineJobConfirmation = false, -- "true" makes it so fines need confirmation, "false" skips this ands just removes the money
FineJobList = true, -- "true" to use nearby player list feature in the cash registers, "false" for manual id entry
```
---
## Banking
![](https://i.imgur.com/RYADcI2.jpeg)
- This script has simple banking systems built in
- Works as a basic replacement for qb-banking and qb-atms
- Adjust the options in config.lua:
- `useATM` Choose wether to make atm's usable
- `useBanks` Choose wether to make bank desks/teller's usable
- `BankBlips` Enable this if you disabled qb-banking and need bank locations
- `ATMBlips` Enable this if you are a pyscho and need every ATM to be on the map too
- `Gabz` Enable to change to Gabz Bank locations, this corrects the ATM/Bank Cashier + Ticket Cash in
---
### Renewed's qb-phone
- Simply leave the Config.PhoneType as `"qb"`
### AP-Goverment
- Support for AP-Goverment Tax on payments
- Toggle `ApGov` in the config.lua to enable this
### If you think I did a good job here, consider donating as it keeps by lights on and my cat round:
## [JixelPatterns Kofi](https://ko-fi.com/jixelpatterns)

View File

@@ -24,22 +24,29 @@ if Config.Banks.enable then
jobroles[k] = 0
end
end
createCircleTarget(
{ name, vec3(v[i].x, v[i].y, v[i].z+0.2), 2.0, { name = name, debugPoly = debugMode, useZ = true, }, }, {
{ action = function()
local options = {
{ action = function()
if Config.General.Peds and isStarted("jim-talktonpc") then
exports["jim-talktonpc"]:createCam(Peds[name], true, "generic", true)
end
TriggerEvent(getScript()..":Client:Bank", { ped = Config.General.Peds and Peds[name] })
end,
icon = "fas fa-piggy-bank", label = locale("target", "bank") },
icon = "fas fa-piggy-bank", label = locale("target", "bank")
},
}
if Config.Receipts.CashInAnywhere then
options[#options+1] =
{ action = function() TriggerEvent(getScript()..":Tickets:Menu", { gang = false }) end,
icon = "fas fa-receipt", label = locale("target", "cashin_boss"), job = jobroles,
},
}
options[#options+1] =
{ action = function() TriggerEvent(getScript()..":Tickets:Menu", { gang = true }) end,
icon = "fas fa-receipt", label = locale("target", "cashin_gang"), gang = gangroles,
},
}, 2.5)
}
end
createCircleTarget(
{ name, vec3(v[i].x, v[i].y, v[i].z+0.2), 2.0, { name = name, debugPoly = debugMode, useZ = true, }, }, options, 2.5)
if Config.Banks.showBlips then
makeBlip({coords = v[i], sprite = 814, col = 2, scale = 0.7, disp = 6, name = locale("blip", "blip_bank") })
end

View File

@@ -7,17 +7,25 @@ function spawnCustomRegisters()
for i = 1, #v do
local job, gang = v[i].gang and nil or k, v[i].gang and k or nil
createBoxTarget({"CustomRegister: "..k..i, v[i].coords.xyz, 0.47, 0.34, { name="CustomRegister: "..k..i, heading = v[i].coords[4], debugPoly=debugMode, minZ=v[i].coords.z-0.1, maxZ=v[i].coords.z+0.4}}, {
{ onSelect = function() TriggerEvent(getScript()..":client:Charge", { job = job, gang = gang, img = ""}) end, icon = "fas fa-credit-card", label = locale("target", "charge"), }
{
action = function()
TriggerEvent(getScript()..":client:Charge", { job = job, gang = gang, img = ""})
end,
icon = "fas fa-credit-card",
label = locale("target", "charge"),
job = job,
gang = gang
}
}, 2.0)
if v[i].prop then makeProp({prop = "prop_till_03", coords = v[i].coords}, 1, false) end
if v[i].prop then makeProp({prop = "prop_till_03", coords = v[i].coords + vec4(0,0,1.0, 0.0)}, 1, false) end
end
end
end
onPlayerLoaded(function() spawnCustomRegisters() end, true)
local billPrev = "cash"
RegisterNetEvent(getScript()..":client:Charge", function(data, outside)
local billPrev = "cash"
--if not outside and not onDuty and data.gang == nil then triggerNotify(nil, locale("error", "not_onduty") return end
local newinputs = {} -- Begin qb-input creation here.
local nearbyList = {}
@@ -25,8 +33,13 @@ RegisterNetEvent(getScript()..":client:Charge", function(data, outside)
--Retrieve a list of nearby players from server
local onlineList = triggerCallback(getScript()..":MakePlayerList")
--Convert list of players nearby into one qb-input understands + add distance info
local playerCoords = GetEntityCoords(PlayerPedId())
if onlineList == nil or #onlineList == 0 then
goto failed
end
for _, v in ipairs(GetPlayersFromCoords(playerCoords, Config.General.PaymentRadius)) do
local ped = GetPlayerPed(v)
local dist = #(GetEntityCoords(ped) - playerCoords)
@@ -42,22 +55,165 @@ RegisterNetEvent(getScript()..":client:Charge", function(data, outside)
end
end
end
::failed::
--If list is empty(no one nearby) show error and stop
if not nearbyList[1] then triggerNotify(nil, locale("error" ,"no_one"), "error") return end
if not nearbyList[1] then
triggerNotify(nil, locale("error" ,"no_one"), "error")
return
end
newinputs[#newinputs+1] = {
type = "select",
text = locale("menu", "cus_id"),
name = "citizen",
label = locale("menu", "cus_id"),
default = 1,
options = nearbyList
}
elseif Config.General.lookAtCharge then
local selectedPed = nil
local highlightedPed = nil
local running = true
CreateThread(function()
while running do
Wait(0)
-- Raycast to get entity being looked at
local camCoord = GetGameplayCamCoord()
local direction = RotationToDirection(GetGameplayCamRot(2))
local targetCoord = camCoord + direction * 6.0
local hit, _ , hitCoords, _, entityHit = PerformRaycast(camCoord, targetCoord, PlayerPedId(), 4)
if hit then
DrawSphere(hitCoords.x, hitCoords.y, hitCoords.z, 0.05, 255, 255, 255, 0.5)
end
if entityHit and IsEntityAPed(entityHit) and entityHit ~= PlayerPedId() then
if highlightedPed ~= entityHit then
if highlightedPed and DoesEntityExist(highlightedPed) then
SetEntityAlpha(highlightedPed, 255, false)
ResetEntityAlpha(highlightedPed)
end
highlightedPed = entityHit
SetEntityAlpha(highlightedPed, 200, false)
end
elseif highlightedPed then
SetEntityAlpha(highlightedPed, 255, false)
ResetEntityAlpha(highlightedPed)
highlightedPed = nil
end
local loc = vec2(0.89+0.037, 0.9)
DrawSprite("timerbars", "all_black_bg", loc.x, loc.y, 0.12, 0.05, 0.0, 255, 255, 255, 255)
SetTextScale(0.80, 0.80)
SetTextWrap(0.75, 0.985)
SetTextJustification(2)
SetTextFont(4)
SetTextColour(255, 255, 255, 255)
BeginTextCommandDisplayText("STRING")
AddTextComponentSubstringKeyboardDisplay(highlightedPed and "~s~Selected ID: ~g~"..GetPlayerServerId(NetworkGetPlayerIndexFromPed(highlightedPed)) or "~s~No Selection")
EndTextCommandDisplayText(loc.x+0.06, loc.y - 0.026)
-- Show instructional UI
local buttons = {
{ keys = { 194 }, text = "Cancel" }
}
if highlightedPed then
table.insert(buttons, { keys = { 86, 191 }, text = "Confirm" })
end
makeInstructionalButtons(buttons)
-- Handle controls
if IsControlJustPressed(0, 194) then -- Backspace
if highlightedPed then
SetEntityAlpha(highlightedPed, 255, false)
ResetEntityAlpha(highlightedPed)
end
running = false
return
end
if highlightedPed and (IsControlJustPressed(0, 191) or IsControlJustPressed(0, 86)) then
local serverId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(highlightedPed))
if serverId then
running = false
SetEntityAlpha(highlightedPed, 255, false)
ResetEntityAlpha(highlightedPed)
--Grab Player Job name or Gang Name if needed
local getInfo = getPlayer()
--Check if image was given when opening the regsiter
local img = data.img ~= nil and (Config.System.Menu == "qb" and "<center><img src="..(data.img).." width=200px></center>") or Jobs[getInfo.job].label
local newinputs = {
{
type = 'select',
name = 'billtype',
text = locale("menu", "type"),
default = billPrev,
options = {
{ value = "cash", text = locale("menu", "cash"), label = locale("menu", "cash") },
{ value = "bank", text = locale("menu", "card"), label = locale("menu", "card") }
}
},
{
type = 'number',
isRequired = true,
name = 'price',
text = locale("menu", "amount_charge")
}
}
local dialog = createInput(img, newinputs)
if dialog then
-- If ox_menu style input, fix indexes
if dialog[1] then
dialog.billtype = dialog[1]
dialog.price = dialog[2]
end
billPrev = dialog.billtype
TriggerServerEvent(getScript()..":server:Charge", serverId, dialog.price, dialog.billtype, data.img, outside, gang)
if Config.General.Usebzzz then
destroyProp(prop)
stopAnim('cellphone@', 'cellphone_text_read_base')
end
end
end
end
end
end)
return -- Skip continuing function until selection is made
else -- If Config.List is false, create input text box for ID's
newinputs[#newinputs+1] = { type = 'text', isRequired = true, required = true, name = 'citizen', label = locale("menu" ,"person_id"), text = locale("menu" ,"person_id") }
newinputs[#newinputs+1] = {
type = 'text',
isRequired = true,
required = true,
name = 'citizen',
label = locale("menu", "cus_id"),
text = locale("menu", "cus_id")
}
end
local prop = nil
if Config.General.Usebzzz then
local Ped = PlayerPedId()
prop = makeProp({ prop = 'bzzz_prop_payment_terminal', coords = vec4(0,0,0,0)}, false, true)
AttachEntityToEntity(prop, Ped, GetPedBoneIndex(Ped, 57005), 0.17, 0.04, 0.01, 340.0, 200.0, 50.0, true, true, false, false, 1, true)
playAnim('cellphone@', 'cellphone_text_read_base', -1, 49)
end
--Grab Player Job name or Gang Name if needed
local getInfo = getPlayer()
--Check if image was given when opening the regsiter
local img = data.img ~= nil and (Config.System.Menu == "qb" and "<center><img src="..(data.img).." width=200px></center>") or Jobs[getInfo.job].label
if Config.General.List then
newinputs[#newinputs+1] = { type = "select", text = locale("menu" ,"cus_id"), name = "citizen", label = locale("menu" ,"cus_id"), default = 1, options = nearbyList }
else
newinputs[#newinputs+1] = { type = 'text', isRequired = true, name = 'citizen', text = locale("menu" ,"cus_id") }
end
newinputs[#newinputs+1] = {
type = 'select',
name = 'billtype',
@@ -73,7 +229,11 @@ RegisterNetEvent(getScript()..":client:Charge", function(data, outside)
local dialog = createInput(img, newinputs)
if dialog then
if dialog[1] then
if dialog[1] then -- if ox menu, auto adjust values
if dialog[1] == "" then
TriggerEvent(getScript()..":client:Charge", data, outside)
return
end
dialog.citizen = dialog[1]
dialog.billtype = dialog[2]
dialog.price = dialog[3]
@@ -81,11 +241,15 @@ RegisterNetEvent(getScript()..":client:Charge", function(data, outside)
billPrev = dialog.billtype
TriggerServerEvent(getScript()..":server:Charge", dialog.citizen, dialog.price, dialog.billtype, data.img, outside, gang)
end
if Config.General.Usebzzz then
destroyProp(prop)
stopAnim('cellphone@', 'cellphone_text_read_base')
end
end)
RegisterNetEvent(getScript()..":client:PayPopup", function(amount, biller, billtype, img, billerjob, gang, outside)
local setimage = ""
print(billerjob)
if not img then
setimage = billerjob
else
@@ -134,7 +298,7 @@ RegisterNetEvent(getScript()..":client:PayPopup", function(amount, biller, billt
})
end,
}
debugPrint(setimage)
openMenu(Menu, {
header = setimage,
onExit = function()

View File

@@ -2,38 +2,179 @@ RegisterNetEvent(getScript()..":client:PolCharge", function()
local Playerinfo = getPlayer()
--Check if player is allowed to use /cashregister command
local allowed = false
for k in pairs(Config.PolCharge.FineJobs) do if k == Playerinfo.job then allowed = true end end
if not allowed then triggerNotify(nil, locale("error", "no_job"), "error") return end
for k in pairs(Config.PolCharge.FineJobs) do
if k == Playerinfo.job then
allowed = true
break
end
end
if not allowed then
triggerNotify(nil, locale("error", "no_job"), "error")
return
end
local newinputs = {} -- Begin qb-input creation here.
local nearbyList = {}
if Config.PolCharge.FineJobList then -- If nearby player list is wanted:
--Retrieve a list of nearby players from server
-- Retrieve a list of nearby players from server
local onlineList = triggerCallback(getScript()..":MakePlayerList")
--Convert list of players nearby into one qb-input understands + add distance info
-- Convert list of players nearby into one an input script understands + add distance info
for _, v in pairs(Core.Functions.GetPlayersFromCoords(GetEntityCoords(PlayerPedId()), Config.General.PaymentRadius)) do
local dist = #(GetEntityCoords(GetPlayerPed(v)) - GetEntityCoords(PlayerPedId()))
for i = 1, #onlineList do
if onlineList[i].value == GetPlayerServerId(v) then
if v ~= PlayerId() or debugMode then
nearbyList[#nearbyList+1] = { value = onlineList[i].value, label = onlineList[i].text..' ('..math.floor(dist+0.05)..'m)', text = onlineList[i].text..' ('..math.floor(dist+0.05)..'m)' }
nearbyList[#nearbyList+1] = {
value = onlineList[i].value,
label = onlineList[i].text..' ('..math.floor(dist+0.05)..'m)',
text = onlineList[i].text..' ('..math.floor(dist+0.05)..'m)'
}
end
end
end
end
--If list is empty(no one nearby) show error and stop
if not nearbyList[1] then triggerNotify(nil, locale("error" ,"no_one"), "error") return end
end
if not nearbyList[1] then
triggerNotify(nil, locale("error" ,"no_one"), "error")
return
end
newinputs[#newinputs+1] = {
type = "select",
text = locale("menu" ,"cus_id"),
name = "citizen",
label = locale("menu" ,"cus_id"),
default = 1,
options = nearbyList
}
elseif Config.General.lookAtCharge then
local selectedPed = nil
local highlightedPed = nil
local running = true
CreateThread(function()
while running do
Wait(0)
-- Raycast to get entity being looked at
local camCoord = GetGameplayCamCoord()
local direction = RotationToDirection(GetGameplayCamRot(2))
local targetCoord = camCoord + direction * 6.0
local hit, _ , hitCoords, _, entityHit = PerformRaycast(camCoord, targetCoord, PlayerPedId(), 4)
if hit then
DrawSphere(hitCoords.x, hitCoords.y, hitCoords.z, 0.05, 0, 0, 255, 0.5)
end
if entityHit and IsEntityAPed(entityHit) and entityHit ~= PlayerPedId() then
if highlightedPed ~= entityHit then
if highlightedPed and DoesEntityExist(highlightedPed) then
SetEntityAlpha(highlightedPed, 255, false)
ResetEntityAlpha(highlightedPed)
end
highlightedPed = entityHit
SetEntityAlpha(highlightedPed, 200, false)
end
elseif highlightedPed then
SetEntityAlpha(highlightedPed, 255, false)
ResetEntityAlpha(highlightedPed)
highlightedPed = nil
end
local loc = vec2(0.89+0.037, 0.9)
DrawSprite("timerbars", "all_black_bg", loc.x, loc.y, 0.12, 0.05, 0.0, 255, 255, 255, 255)
SetTextScale(0.80, 0.80)
SetTextWrap(0.75, 0.985)
SetTextJustification(2)
SetTextFont(4)
SetTextColour(255, 255, 255, 255)
BeginTextCommandDisplayText("STRING")
AddTextComponentSubstringKeyboardDisplay(highlightedPed and "~s~Selected ID: ~b~"..GetPlayerServerId(NetworkGetPlayerIndexFromPed(highlightedPed)) or "~s~No Selection")
EndTextCommandDisplayText(loc.x+0.06, loc.y - 0.026)
-- Show instructional UI
local buttons = {
{ keys = { 194 }, text = "Cancel" }
}
if highlightedPed then
table.insert(buttons, { keys = { 86, 191 }, text = "Confirm" })
end
makeInstructionalButtons(buttons)
-- Handle controls
if IsControlJustPressed(0, 194) then -- Backspace
if highlightedPed then
SetEntityAlpha(highlightedPed, 255, false)
ResetEntityAlpha(highlightedPed)
end
running = false
return
end
if highlightedPed and (IsControlJustPressed(0, 191) or IsControlJustPressed(0, 86)) then
local serverId = GetPlayerServerId(NetworkGetPlayerIndexFromPed(highlightedPed))
if serverId then
running = false
SetEntityAlpha(highlightedPed, 255, false)
ResetEntityAlpha(highlightedPed)
local newinputs = {
{
type = 'select',
name = 'billtype',
text = locale("menu", "type"),
default = billPrev,
options = {
{ value = "cash", text = locale("menu", "cash"), label = locale("menu", "cash") },
{ value = "bank", text = locale("menu", "card"), label = locale("menu", "card") }
}
},
{
type = 'number',
isRequired = true,
name = 'price',
text = locale("menu", "amount_charge")
}
}
local dialog = createInput(Jobs[getPlayer().job].label, newinputs)
if dialog then
-- If ox_menu style input, fix indexes
if dialog[1] then
dialog.billtype = dialog[1]
dialog.price = dialog[2]
end
billPrev = dialog.billtype
TriggerServerEvent(getScript()..":server:PolCharge", serverId, dialog.price)
end
end
end
end
end)
return -- Skip continuing function until selection is made
if Config.PolCharge.FineJobList then
newinputs[#newinputs+1] = { type = "select", text = locale("menu" ,"cus_id"), name = "citizen", label = locale("menu" ,"cus_id"), default = 1, options = nearbyList }
else
newinputs[#newinputs+1] = { type = 'text', isRequired = true, name = 'citizen', text = locale("menu" ,"cus_id") }
newinputs[#newinputs+1] = {
type = 'text',
isRequired = true,
name = 'citizen',
text = locale("menu" ,"cus_id")
}
end
newinputs[#newinputs+1] = { type = 'number', isRequired = true, name = 'price', text = locale("menu" ,"amount_charge") }
newinputs[#newinputs+1] = {
type = 'number',
isRequired = true,
name = 'price',
text = locale("menu" ,"amount_charge")
}
local dialog = createInput(Jobs[Playerinfo.job].label, newinputs)
if dialog then
jsonPrint(dialog)
if dialog[1] then
dialog.citizen = dialog[1]
dialog.price = dialog[2]
@@ -42,9 +183,13 @@ RegisterNetEvent(getScript()..":client:PolCharge", function()
end
end)
RegisterNetEvent(getScript()..":client:PolPopup", function(amount, biller, billerjob)
RegisterNetEvent(getScript()..":client:PolPopup", function(amount, biller, billerjob, commPercent)
local Menu = {}
Menu[#Menu+1] = { isMenuHeader = true, header = "", txt = locale("menu" ,"bank_charge")..amount }
Menu[#Menu+1] = {
isMenuHeader = true,
header = "",
txt = locale("menu" ,"bank_charge")..amount
}
Menu[#Menu+1] = {
icon = "fas fa-circle-check",
header = locale("menu" ,"yes"),
@@ -54,6 +199,7 @@ RegisterNetEvent(getScript()..":client:PolPopup", function(amount, biller, bille
accept = true,
amount = amount,
biller = biller,
commPercent = commPercent,
})
end,
}

View File

@@ -1,3 +1,46 @@
if not Config.Banks.enable or not Config.Receipts.CashInAnywhere then
onPlayerLoaded(function()
local locations = BankLocations
if not Config.Receipts.CashInAnywhere then
locations = {
["receipts"] = Config.Receipts.CashInLocations
}
end
for k, v in pairs(locations) do
for i = 1, #v do
local name = getScript()..":BankLocation:"..k..i
if Config.General.Peds then
if not Config.Gabz then CreateModelHide(v[i].xyz, 1.0, `v_corp_bk_chair3`, true) end
if not Peds[name] then
Peds[name] = makePed(Config.General.PedPool[math.random(1, #Config.General.PedPool)], v[i], false, false)
if isStarted("jim-talktonpc") then
exports["jim-talktonpc"]:createDistanceMessage("hi", Peds[name], 3.0, false)
end
end
end
local jobroles = {}
local gangroles = {}
for k, v in pairs(Config.Receipts.Jobs) do
if v.gang then
gangroles[k] = 0
else
jobroles[k] = 0
end
end
createCircleTarget(
{ name, vec3(v[i].x, v[i].y, v[i].z+0.2), 2.0, { name = name, debugPoly = debugMode, useZ = true, }, }, {
{ action = function() TriggerEvent(getScript()..":Tickets:Menu", { gang = false }) end,
icon = "fas fa-receipt", label = locale("target", "cashin_boss"), job = jobroles,
},
{ action = function() TriggerEvent(getScript()..":Tickets:Menu", { gang = true }) end,
icon = "fas fa-receipt", label = locale("target", "cashin_gang"), gang = gangroles,
},
}, 2.5)
end
end
end, true)
end
RegisterNetEvent(getScript()..":Tickets:Menu", function(data)
local PlayerInfo = getPlayer()
local hasItem, hasTable = hasItem("payticket", 1)

View File

@@ -1,6 +1,6 @@
-- If you need support I now have a discord available, it helps me keep track of issues and give better support.
-- https://discord.gg/xKgQZ6wZvS
-- https://discord.gg/9pCDHmjYwd
Config = {
Lan = "en",
@@ -25,7 +25,9 @@ Config = {
General = {
ApGov = false, -- Toggle support for AP-Goverment Tax
lookAtCharge = false, -- "true" to use the "look at charge" feature
List = true, -- "true" to use nearby player list feature in the cash registers, "false" for manual id entry
PaymentRadius = 15, -- This is how far the playerlist will check for nearby players (based on the person charging)
Usebzzz = false, -- enable if you're using the prop from bzzz
@@ -149,7 +151,8 @@ Config = {
['ambulance'] = { Commission = 0.25, },
},
FineJobConfirmation = false, --"true" makes it so fines need confirmation, "false" skips this ands just removes the money
FineJobList = true, -- "true" to use nearby player list feature in the cash registers, "false" for manual id entry
FineJobList = false, -- "true" to use nearby player list feature in the cash registers, "false" for manual id entry
lookAtCharge = true, -- "true" to use the "look at charge" feature
},
}

View File

@@ -1,7 +1,7 @@
name "Jim-Payments"
author "Jimathy"
version "3.0.01"
description "Payment Script By Jimathy"
version "3.0.05"
description "Payment Script"
fx_version "cerulean"
game "gta5"
lua54 'yes'
@@ -12,25 +12,12 @@ shared_scripts {
'locales/*.lua',
'config.lua',
-- Required core scripts
'@ox_lib/init.lua',
'@ox_core/lib/init.lua',
'@es_extended/imports.lua',
'@qbx_core/modules/playerdata.lua',
--Jim Bridge
--Jim Bridge - https://github.com/jimathy/jim_bridge
'@jim_bridge/starter.lua',
'shared/*.lua',
}
client_scripts {
'@PolyZone/client.lua',
'@PolyZone/BoxZone.lua',
'@PolyZone/EntityZone.lua',
'@PolyZone/CircleZone.lua',
'@PolyZone/ComboZone.lua',
'client/*.lua',
}

BIN
images/terminal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -1,10 +1,49 @@
registerCommand("cashgive", {
locale("command" , "pay_user"), {}, false,
function(source)
TriggerClientEvent(getScript()..":client:ATM:give", source)
end
})
onResourceStart(function()
registerCommand("cashgive", {
locale("command" , "pay_user"), {}, false,
function(source)
TriggerClientEvent(getScript()..":client:ATM:give", source)
end
})
createCallback(getScript()..":GetInfo", function(source)
local Player = getPlayer(source)
local society, gsociety = 0, 0
society = getSocietyAccount(Player.job)
if Player.gang ~= "none" then
gsociety = getSocietyAccount(Player.gang)
end
-- Savings account is only QBCore for now
if isStarted(QBExport) and not isStarted(QBXExport) then
-- Grab Savings account info
local result = MySQL.Sync.fetchAll('SELECT * FROM bank_accounts WHERE citizenid = ? AND account_name = ?', { Player.citizenId, 'Savings_'..Player.citizenId, })
if result[1] then
accountID = result[1].citizenid
savingBalance = result[1].account_balance
else
MySQL.Async.insert('INSERT INTO bank_accounts (citizenid, account_name, account_balance) VALUES (?, ?, ?)', { Player.citizenId, 'Savings_'..Player.citizenId, 0}, function() completed = true end) repeat Wait(0) until completed == true
local result = MySQL.Sync.fetchAll('SELECT * FROM bank_accounts WHERE citizenid = ? AND account_name = ?', { Player.citizenId, 'Savings_'..Player.citizenId, })
accountID = result[1].citizenid
savingBalance = result[1].account_balance
end
end
local retTable = {
name = Player.firstname..' '..Player.lastname,
cash = Player.cash,
bank = Player.bank,
account = Player.account,
cid = Player.citizenId.." ["..source.."]",
savbal = savingBalance,
aid = accountID,
society = society,
gsociety = gsociety
}
return retTable
end)
end, true)
RegisterServerEvent(getScript()..":server:ATM:use", function(amount, billtype, baccount, account, society, gsociety)
local src = source
@@ -207,44 +246,6 @@ RegisterServerEvent(getScript()..":server:ATM:use", function(amount, billtype, b
end
end)
createCallback(getScript()..":GetInfo", function(source)
local Player = getPlayer(source)
local society, gsociety = 0, 0
society = getSocietyAccount(Player.job)
if Player.gang ~= "none" then
gsociety = getSocietyAccount(Player.gang)
end
-- Savings account is only QBCore for now
if isStarted(QBExport) and not isStarted(QBXExport) then
-- Grab Savings account info
local result = MySQL.Sync.fetchAll('SELECT * FROM bank_accounts WHERE citizenid = ? AND account_name = ?', { Player.citizenId, 'Savings_'..Player.citizenId, })
if result[1] then
accountID = result[1].citizenid
savingBalance = result[1].account_balance
else
MySQL.Async.insert('INSERT INTO bank_accounts (citizenid, account_name, account_balance) VALUES (?, ?, ?)', { Player.citizenId, 'Savings_'..Player.citizenId, 0}, function() completed = true end) repeat Wait(0) until completed == true
local result = MySQL.Sync.fetchAll('SELECT * FROM bank_accounts WHERE citizenid = ? AND account_name = ?', { Player.citizenId, 'Savings_'..Player.citizenId, })
accountID = result[1].citizenid
savingBalance = result[1].account_balance
end
end
local retTable = {
name = Player.firstname..' '..Player.lastname,
cash = Player.cash,
bank = Player.bank,
account = Player.account,
cid = Player.citizenId.." ["..source.."]",
savbal = savingBalance,
aid = accountID,
society = society,
gsociety = gsociety
}
return retTable
end)
RegisterServerEvent(getScript()..":server:ATM:give", function(citizen, price)
local Player = getPlayer(source)
local Reciever = getPlayer(tonumber(citizen))

View File

@@ -9,26 +9,37 @@ onResourceStart(function()
if Items and not Items["payticket"] then
debugPrint("^1Error^7: ^2Unable to find ^7'^3payticket^7' ^2item it in the Shared^7")
end
end, true)
registerCommand("cashregister", {
locale("command", "cash_reg"), {}, false,
function(source)
TriggerClientEvent(getScript()..":client:Charge", source, {}, true)
for _, v in pairs({"cashregister", "terminal"}) do
registerCommand(v, {
locale("command", "cash_reg"), {}, false,
function(source)
TriggerClientEvent(getScript()..":client:Charge", source, {}, true)
end
})
end
})
createCallback(getScript()..":MakePlayerList", function(source)
local onlineList = {}
for _, v in pairs(GetPlayers()) do
if v ~= nil or type(v) ~= "number" then
local Player = getPlayer(v)
onlineList[#onlineList+1] = { value = tonumber(v), text = "["..v.."] - "..Player.name }
Wait(10)
if Items["terminal"] then
createUseableItem("terminal", function(source, item)
TriggerClientEvent(getScript()..":client:Charge", source, {}, true)
end)
end
createCallback(getScript()..":MakePlayerList", function(source)
local onlineList = {}
for _, v in pairs(GetPlayers()) do
if v ~= nil or type(v) ~= "number" then
local Player = getPlayer(v)
if Player.name then
onlineList[#onlineList+1] = { value = tonumber(v), text = "["..v.."] - "..Player.name }
end
Wait(10)
end
end
end
return onlineList
end)
return onlineList
end)
end, true)
RegisterServerEvent(getScript()..":server:Charge", function(citizen, price, billtype, img, outside, gang)
local src = source
@@ -46,29 +57,21 @@ RegisterServerEvent(getScript()..":server:Charge", function(citizen, price, bill
if Config.General.PhoneBank == false or gang == true or billtype == "cash" then
TriggerClientEvent(getScript()..":client:PayPopup", billed.source, amount, src, billtype, img, label, gang, outside)
else
if Config.General.PhoneType == "qb" then
MySQL.Async.insert(
'INSERT INTO phone_invoices (citizenid, amount, society, sender, sendercitizenid) VALUES (?, ?, ?, ?, ?)',
{billed.citizenid, amount, biller.job, biller.firstname, biller.citizenid}, function(id)
if id then
TriggerClientEvent('qb-phone:client:AcceptorDenyInvoice', billed.source, id, biller.firstname, biller.job, biller.citizenid, amount, GetInvokingResource())
end
end)
TriggerClientEvent('qb-phone:RefreshPhone', billed.source)
elseif Config.General.PhoneType == "gks" then
MySQL.Async.execute('INSERT INTO gksphone_invoices (citizenid, amount, society, sender, sendercitizenid, label) VALUES (@citizenid, @amount, @society, @sender, @sendercitizenid, @label)', {
['@citizenid'] = billed.citizenid,
['@amount'] = amount,
['@society'] = biller.job,
['@sender'] = biller.firstname,
['@sendercitizenid'] = biller.citizenid,
['@label'] = label,
})
TriggerClientEvent('gksphone:notifi', src, {title = 'Billing', message = locale("success", "inv_succ"), img= '/html/static/img/icons/logo.png' })
TriggerClientEvent('gksphone:notifi', billed.source, {title = 'Billing', message = locale("success", "inv_recieved"), img= '/html/static/img/icons/logo.png' })
if sendPhoneInvoice({
src = billed.source,
amount = amount,
billedCitizenid = billed.citizenId,
job = biller.job,
name = biller.firstname,
billerCitizenid = biller.citizenId,
label = label,
}) then
triggerNotify(nil, locale("success", "inv_succ"), 'success', src)
triggerNotify(nil, locale("success", "inv_recieved"), nil, billed.source)
else
end
triggerNotify(nil, locale("success", "inv_succ"), 'success', src)
triggerNotify(nil, locale("success", "inv_recieved"), nil, billed.source)
end
else triggerNotify(nil, locale("error", "charge_zero"), 'error', source) return end
end)
@@ -93,12 +96,4 @@ RegisterServerEvent(getScript()..":server:PayPopup", function(data)
triggerNotify(nil, locale("success", "declined"), "error", src)
triggerNotify(nil, billed.firstname..locale("error", "decline_pay")..data.amount..locale("success", "payment"), "error", data.biller)
end
end)
CreateThread(function()
if Config.General.Usebzzz then
createUseableItem('terminal', function(source, item)
TriggerClientEvent(getScript()..":client:Charge", source, {}, true)
end)
end
end)

View File

@@ -1,9 +1,11 @@
registerCommand("polcharge", {
locale("command", "charge"), {}, false,
function(source)
TriggerClientEvent(getScript()..":client:PolCharge", source)
end
})
onResourceStart(function()
registerCommand("polcharge", {
locale("command", "charge"), {}, false,
function(source)
TriggerClientEvent(getScript()..":client:PolCharge", source)
end
})
end, true)
RegisterServerEvent(getScript()..":server:PolCharge", function(citizen, price)
local src = source
@@ -12,12 +14,7 @@ RegisterServerEvent(getScript()..":server:PolCharge", function(citizen, price)
local price = math.floor(tonumber(price))
local commPercent = Config.PolCharge.FineJobs[biller.job] and Config.PolCharge.FineJobs[biller.job].Commission or 0.25
if Config.PolCharge.FineJobs[biller.job] then
commPercent = Config.PolCharge.FineJobs[biller.job].Commission
else
commPercent = 0.25
print("Can't find job in 'FineJobs', defaulting to 0.25 (25% commission)")
end
local commission = math.floor(price * commPercent)
if price > 0 then

View File

@@ -3,11 +3,9 @@ RegisterServerEvent(getScript()..":Tickets:Give", function(data, biller, gang)
local activePlayers = GetPlayers()
local commPercent = 0
jsonPrint(data)
if Config.Receipts.Jobs[data.society] then
commPercent = Config.Receipts.Jobs[data.society].Commission
else commPercent = 0.25
print("^1Error^7: ^2Can't find job in ^7'^3Config^7.^3Receipts^7.^3Jobs^7', ^2defaulting to 0.25 (25% commission)^7")
end
local commPercent = Config.PolCharge.FineJobs[data.society] and Config.PolCharge.FineJobs[data.society].Commission or 0.25
local takecomm = math.floor(data.amount * commPercent)
if biller ~= nil then -- If this is found, it ISN'T a phone payment, so add money to society here

View File

@@ -27,7 +27,9 @@ BankLocations = {
}
if Config.General.Gabz then
Config.Receipts.CashInLocation = vec4(269.28, 217.24, 106.28, 69.0)
Config.Receipts.CashInLocations = {
vec4(269.28, 217.24, 106.28, 69.0)
}
BankLocations = {
["legion"] = {
vec4(149.5, -1042.08, 29.37, 342.74), -- Legion Fleeca

View File

@@ -1 +1,6 @@
3.0.01
3.0.05
- Add extra check for if playerData exists when getting player list
- Add new lookAtCharge option to allow players to target who to charge
https://github.com/jimathy/jim-payments