Events
Hook into these from other resources with AddEventHandler. They're server-local unless marked otherwise, and they fire only after np_phone has validated the action.
Core
| Event | Side | Arguments | When |
|---|---|---|---|
np_phone:playerReady | server | src, player | Phone profile loaded or created. player = { source, identifier, number, name, job } |
np_phone:playerUnloaded | server | src, identifier, number | Logout, character switch or drop |
np_phone:opened | client | Phone opened | |
np_phone:closed | client | Phone closed |
Wallet & jobs
| Event | Arguments | When |
|---|---|---|
np_phone:invoicePaid | invoice | A business invoice was paid. invoice = { id, identifier, sender, senderJob, senderIdentifier, amount, reason, payerSource }. Credit the society account here (or use Config.City.invoicePayout) |
np_phone:jobs:setDuty | src, onDuty | Duty toggled in the Jobs app. Always fires, even on frameworks without duty support |
np_phone:jobs:applied | src, jobId | "Apply" in the job center |
Garage
The fee is already charged when these fire.
| Event | Arguments | When |
|---|---|---|
np_phone:garage:valet | src, plate, vehicle | Valet requested (with valetSpawn = true: after a successful spawn) |
np_phone:garage:impoundRelease | src, plate, vehicle | Impound release paid |
np_phone:garage:shareKeys | src, targetSrc, plate | Keys shared |
np_phone:garage:revokeKeys | src, targetIdentifier, plate | Keys revoked |
Groups
| Event | Arguments | When |
|---|---|---|
np_phone:groups:signIn | groupId, jobId, leaderSrc | The leader signed in to a group job. Your job script drives it from here with groupStartJob / groupSetStage / … |
np_phone:groups:created | groupId, leaderSrc | Group created |
np_phone:groups:disbanded | groupId | Group disbanded |
np_phone:groups:memberJoined | groupId, src | |
np_phone:groups:memberLeft | groupId, src |
Files
| Event | Arguments | When |
|---|---|---|
np_phone:files:contractSigned | contractId, c | Party B signed. c = { id, title, partyA, partyB, sourceA, sourceB, meta, signedAt } |
np_phone:files:contractDeclined | contractId, { id, partyA, partyB } | Party B declined |
Mail actions
Mail action buttons of type = 'event' trigger your own event:
lua
-- server (default)
TriggerEvent(event, src, args, mailId)
-- client, with data.client = true
TriggerClientEvent(event, src, args, mailId)See City → Mail.
Example: group job
lua
AddEventHandler('np_phone:groups:signIn', function(groupId, jobId, leaderSrc)
if jobId ~= 'sanitation' then return end
exports.np_phone:groupStartJob(groupId, {
id = 'sanitation', label = 'Sanitation', icon = 'fa-solid fa-trash-can',
stages = { { label = 'Pick up truck at depot' }, { label = 'Collect bags', total = 8 }, { label = 'Return truck' } },
payout = '$1.4k', next = 'Depot · Alta St',
})
end)
-- later, from your job logic
exports.np_phone:groupSetStage(groupId, 2, { next = 'Vinewood Blvd' })
exports.np_phone:groupSetProgress(groupId, 5, 8)
exports.np_phone:groupFinishJob(groupId, { payoutEach = 350 })Internal net events
np_phone:rpc, np_phone:rpc:reply, np_phone:push, np_phone:notify, np_phone:init, np_phone:requestInit, np_phone:forceClose, np_phone:calls:* and np_phone:messages:live* are np_phone's own transport. Don't trigger them or listen to them from other resources. Use the exports instead.