[{"data":1,"prerenderedAt":822},["ShallowReactive",2],{"/docs/base/jobs-base/events":3,"/docs/base/jobs-base/events-surround":808,"/docs/base/jobs-base/events-implemented-suggestions":821},{"id":4,"title":5,"body":6,"description":797,"extension":798,"head":799,"implementedSuggestions":799,"meta":800,"navigation":801,"path":803,"schemaOrg":799,"seo":804,"sitemap":805,"stem":806,"__hash__":807},"docs/1.docs/base/2.jobs-base/5.events.md","Events",{"type":7,"value":8,"toc":788},"minimark",[9,13,25,30,48,53,149,229,236,240,401,470,477,481,543,559,563,634,657,661,667,742,745,781,784],[10,11,12],"p",{},"Use events when your script needs to react to a change. Use an export when your script needs to read something or perform an action.",[10,14,15,16,20,21,24],{},"The names on this page are case-sensitive. The ",[17,18,19],"code",{},"sky_jobs:"," prefix on job/duty events is intentional. It is different from the ",[17,22,23],{},"sky_jobs_base:"," prefix used by the other events.",[26,27,29],"h2",{"id":28},"server-events","Server events",[10,31,32,33,37,38,41,42,47],{},"Listen in ",[34,35,36],"strong",{},"server.lua"," using ",[17,39,40],{},"AddEventHandler",". These are notifications emitted by Jobs Base. Do not trigger them to change a player's job, duty or money; call the corresponding ",[43,44,46],"a",{"href":45},"/docs/base/jobs-base/server-exports","server export",".",[49,50,52],"h3",{"id":51},"job-changed","Job changed",[54,55,60],"pre",{"className":56,"code":57,"filename":36,"language":58,"meta":59,"style":59},"language-lua shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","AddEventHandler(\"sky_jobs:jobChanged\", function(playerId, newJob, oldJob, entry)\n    print((\"Player %d changed job from %s to %s\"):format(playerId, oldJob, newJob))\nend)\n","lua","",[17,61,62,116,141],{"__ignoreMap":59},[63,64,67,70,74,78,82,84,87,91,93,97,100,103,105,108,110,113],"span",{"class":65,"line":66},"line",1,[63,68,40],{"class":69},"s2Zo4",[63,71,73],{"class":72},"sTEyZ","(",[63,75,77],{"class":76},"sMK4o","\"",[63,79,81],{"class":80},"sfazB","sky_jobs:jobChanged",[63,83,77],{"class":76},[63,85,86],{"class":72},", ",[63,88,90],{"class":89},"s7zQu","function",[63,92,73],{"class":76},[63,94,96],{"class":95},"sHdIc","playerId",[63,98,99],{"class":76},",",[63,101,102],{"class":95}," newJob",[63,104,99],{"class":76},[63,106,107],{"class":95}," oldJob",[63,109,99],{"class":76},[63,111,112],{"class":95}," entry",[63,114,115],{"class":76},")\n",[63,117,119,122,125,127,130,132,135,138],{"class":65,"line":118},2,[63,120,121],{"class":69},"    print",[63,123,124],{"class":72},"((",[63,126,77],{"class":76},[63,128,129],{"class":80},"Player %d changed job from %s to %s",[63,131,77],{"class":76},[63,133,134],{"class":72},"):",[63,136,137],{"class":69},"format",[63,139,140],{"class":72},"(playerId, oldJob, newJob))\n",[63,142,144,147],{"class":65,"line":143},3,[63,145,146],{"class":89},"end",[63,148,115],{"class":72},[150,151,152,168],"table",{},[153,154,155],"thead",{},[156,157,158,162,165],"tr",{},[159,160,161],"th",{},"Argument",[159,163,164],{},"Type",[159,166,167],{},"Meaning",[169,170,171,186,201,215],"tbody",{},[156,172,173,178,183],{},[174,175,176],"td",{},[17,177,96],{},[174,179,180],{},[17,181,182],{},"number",[174,184,185],{},"Online player's server ID",[156,187,188,193,198],{},[174,189,190],{},[17,191,192],{},"newJob",[174,194,195],{},[17,196,197],{},"string",[174,199,200],{},"New technical job name",[156,202,203,208,212],{},[174,204,205],{},[17,206,207],{},"oldJob",[174,209,210],{},[17,211,197],{},[174,213,214],{},"Previous technical job name",[156,216,217,222,226],{},[174,218,219],{},[17,220,221],{},"entry",[174,223,224],{},[17,225,150],{},[174,227,228],{},"Current PlayerCache entry; treat it as read-only",[10,230,231,232,235],{},"Emitted when an existing cached job name changes. A grade-only update or a player's first load is not a job-name change. Read current grade and duty with ",[17,233,234],{},"getPlayerJobInfo(playerId)"," when needed.",[49,237,239],{"id":238},"duty-changed","Duty changed",[54,241,243],{"className":56,"code":242,"filename":36,"language":58,"meta":59,"style":59},"AddEventHandler(\"sky_jobs:dutyChanged\", function(playerId, onDuty, entry, previousJob)\n    local info = exports[\"sky_jobs_base\"]:getPlayerJobInfo(playerId)\n    if info and info.job == \"sunrise_cafe\" then\n        print((\"Cafe employee %d is %s\"):format(playerId, onDuty and \"on duty\" or \"off duty\"))\n    end\nend)\n",[17,244,245,282,312,344,388,394],{"__ignoreMap":59},[63,246,247,249,251,253,256,258,260,262,264,266,268,271,273,275,277,280],{"class":65,"line":66},[63,248,40],{"class":69},[63,250,73],{"class":72},[63,252,77],{"class":76},[63,254,255],{"class":80},"sky_jobs:dutyChanged",[63,257,77],{"class":76},[63,259,86],{"class":72},[63,261,90],{"class":89},[63,263,73],{"class":76},[63,265,96],{"class":95},[63,267,99],{"class":76},[63,269,270],{"class":95}," onDuty",[63,272,99],{"class":76},[63,274,112],{"class":95},[63,276,99],{"class":76},[63,278,279],{"class":95}," previousJob",[63,281,115],{"class":76},[63,283,284,287,290,293,296,298,301,303,306,309],{"class":65,"line":118},[63,285,286],{"class":76},"    local",[63,288,289],{"class":72}," info ",[63,291,292],{"class":76},"=",[63,294,295],{"class":72}," exports[",[63,297,77],{"class":76},[63,299,300],{"class":80},"sky_jobs_base",[63,302,77],{"class":76},[63,304,305],{"class":72},"]:",[63,307,308],{"class":69},"getPlayerJobInfo",[63,310,311],{"class":72},"(playerId)\n",[63,313,314,317,319,322,325,329,332,335,338,341],{"class":65,"line":143},[63,315,316],{"class":89},"    if",[63,318,289],{"class":72},[63,320,321],{"class":76},"and",[63,323,324],{"class":72}," info.",[63,326,328],{"class":327},"sBMFI","job",[63,330,331],{"class":76}," ==",[63,333,334],{"class":76}," \"",[63,336,337],{"class":80},"sunrise_cafe",[63,339,340],{"class":76},"\" ",[63,342,343],{"class":89},"then\n",[63,345,347,350,352,354,357,359,361,363,366,368,370,373,375,378,380,383,385],{"class":65,"line":346},4,[63,348,349],{"class":69},"        print",[63,351,124],{"class":72},[63,353,77],{"class":76},[63,355,356],{"class":80},"Cafe employee %d is %s",[63,358,77],{"class":76},[63,360,134],{"class":72},[63,362,137],{"class":69},[63,364,365],{"class":72},"(playerId, onDuty ",[63,367,321],{"class":76},[63,369,334],{"class":76},[63,371,372],{"class":80},"on duty",[63,374,340],{"class":76},[63,376,377],{"class":76},"or",[63,379,334],{"class":76},[63,381,382],{"class":80},"off duty",[63,384,77],{"class":76},[63,386,387],{"class":72},"))\n",[63,389,391],{"class":65,"line":390},5,[63,392,393],{"class":89},"    end\n",[63,395,397,399],{"class":65,"line":396},6,[63,398,146],{"class":89},[63,400,115],{"class":72},[150,402,403,413],{},[153,404,405],{},[156,406,407,409,411],{},[159,408,161],{},[159,410,164],{},[159,412,167],{},[169,414,415,427,442,455],{},[156,416,417,421,425],{},[174,418,419],{},[17,420,96],{},[174,422,423],{},[17,424,182],{},[174,426,185],{},[156,428,429,434,439],{},[174,430,431],{},[17,432,433],{},"onDuty",[174,435,436],{},[17,437,438],{},"boolean",[174,440,441],{},"New duty state",[156,443,444,448,452],{},[174,445,446],{},[17,447,221],{},[174,449,450],{},[17,451,150],{},[174,453,454],{},"Current read-only PlayerCache entry",[156,456,457,462,467],{},[174,458,459],{},[17,460,461],{},"previousJob",[174,463,464],{},[17,465,466],{},"string?",[174,468,469],{},"Previous job name when supplied by the transition",[10,471,472,473,476],{},"The event also occurs during initialisation of an on-duty player, so it is not a once-only reward or payment hook. It describes the current active job. Use ",[17,474,475],{},"setPlayerDuty"," to change duty.",[49,478,480],{"id":479},"employees","Employees",[150,482,483,496],{},[153,484,485],{},[156,486,487,490,493],{},[159,488,489],{},"Event",[159,491,492],{},"Arguments",[159,494,495],{},"When it is emitted",[169,497,498,513,528],{},[156,499,500,505,510],{},[174,501,502],{},[17,503,504],{},"sky_jobs_base:management:memberAdded",[174,506,507],{},[17,508,509],{},"playerId, identifier, jobName",[174,511,512],{},"The online hiring/enrolment path adds a job member.",[156,514,515,520,525],{},[174,516,517],{},[17,518,519],{},"sky_jobs_base:management:memberRemoved",[174,521,522],{},[17,523,524],{},"identifier, jobName",[174,526,527],{},"A job employee is removed through management.",[156,529,530,535,540],{},[174,531,532],{},[17,533,534],{},"sky_jobs_base:multijob:memberRemoved",[174,536,537],{},[17,538,539],{},"jobName, identifier, playerId?",[174,541,542],{},"A saved membership is removed; the player can be offline.",[10,544,545,546,549,550,554,555,558],{},"These events describe the indicated workflow; ",[17,547,548],{},"memberAdded"," is not a universal promotion or offline-membership event. Use ",[43,551,553],{"href":552},"/docs/base/jobs-base/server-exports/players-members","getJobMembers"," when you need the current complete roster. ",[17,556,557],{},"identifier"," is a persistent character ID; keep it in server-side integrations.",[49,560,562],{"id":561},"invoice-changed","Invoice changed",[54,564,566],{"className":56,"code":565,"filename":36,"language":58,"meta":59,"style":59},"AddEventHandler(\"sky_jobs_base:billing:changed\", function(invoice)\n    if invoice.status == \"paid\" then\n        -- Refresh your invoice display or reconcile your saved payment record.\n        -- Use invoice.id as the key; a notification is not a second payment.\n    end\nend)\n",[17,567,568,592,613,619,624,628],{"__ignoreMap":59},[63,569,570,572,574,576,579,581,583,585,587,590],{"class":65,"line":66},[63,571,40],{"class":69},[63,573,73],{"class":72},[63,575,77],{"class":76},[63,577,578],{"class":80},"sky_jobs_base:billing:changed",[63,580,77],{"class":76},[63,582,86],{"class":72},[63,584,90],{"class":89},[63,586,73],{"class":76},[63,588,589],{"class":95},"invoice",[63,591,115],{"class":76},[63,593,594,596,599,602,604,606,609,611],{"class":65,"line":118},[63,595,316],{"class":89},[63,597,598],{"class":72}," invoice.",[63,600,601],{"class":327},"status",[63,603,331],{"class":76},[63,605,334],{"class":76},[63,607,608],{"class":80},"paid",[63,610,340],{"class":76},[63,612,343],{"class":89},[63,614,615],{"class":65,"line":143},[63,616,618],{"class":617},"sHwdD","        -- Refresh your invoice display or reconcile your saved payment record.\n",[63,620,621],{"class":65,"line":346},[63,622,623],{"class":617},"        -- Use invoice.id as the key; a notification is not a second payment.\n",[63,625,626],{"class":65,"line":390},[63,627,393],{"class":89},[63,629,630,632],{"class":65,"line":396},[63,631,146],{"class":89},[63,633,115],{"class":72},[10,635,636,637,86,640,86,642,86,645,648,649,652,653,47],{},"The argument is the invoice's public data, including ",[17,638,639],{},"id",[17,641,601],{},[17,643,644],{},"amount",[17,646,647],{},"amountPaid"," and ",[17,650,651],{},"balanceDue",". Creation, partial payment, payment, cancellation and other updates can all notify listeners. This is not an instruction to pay the invoice again. See ",[43,654,656],{"href":655},"/docs/base/jobs-base/server-exports/billing","Billing",[26,658,660],{"id":659},"client-events","Client events",[10,662,32,663,666],{},[34,664,665],{},"client.lua",". These events update the current player's display; make money and permission decisions on the server.",[150,668,669,680],{},[153,670,671],{},[156,672,673,675,677],{},[159,674,489],{},[159,676,492],{},[159,678,679],{},"Use",[169,681,682,703,715,727],{},[156,683,684,689,694],{},[174,685,686],{},[17,687,688],{},"sky_jobs_base:gradeChanged",[174,690,691],{},[17,692,693],{},"oldGrade, newGrade",[174,695,696,697,648,700,47],{},"Management changed the online player's grade; each argument contains ",[17,698,699],{},"level",[17,701,702],{},"label",[156,704,705,709,712],{},[174,706,707],{},[17,708,578],{},[174,710,711],{},"None",[174,713,714],{},"Relevant invoices changed; refresh your authorised billing view. The server event with the same name has an invoice argument.",[156,716,717,722,724],{},[174,718,719],{},[17,720,721],{},"sky_jobs_base:business:stateChanged",[174,723,711],{},[174,725,726],{},"The synchronised Business state was applied; refresh your display.",[156,728,729,734,739],{},[174,730,731],{},[17,732,733],{},"sky_jobs_base:business:historyChanged",[174,735,736],{},[17,737,738],{},"jobName",[174,740,741],{},"That job's announcement history changed.",[10,743,744],{},"For example, receive billing refreshes on the client:",[54,746,748],{"className":56,"code":747,"filename":665,"language":58,"meta":59,"style":59},"RegisterNetEvent(\"sky_jobs_base:billing:changed\", function()\n    -- Refresh your existing billing view through its authorised server request.\nend)\n",[17,749,750,770,775],{"__ignoreMap":59},[63,751,752,755,757,759,761,763,765,767],{"class":65,"line":66},[63,753,754],{"class":69},"RegisterNetEvent",[63,756,73],{"class":72},[63,758,77],{"class":76},[63,760,578],{"class":80},[63,762,77],{"class":76},[63,764,86],{"class":72},[63,766,90],{"class":89},[63,768,769],{"class":76},"()\n",[63,771,772],{"class":65,"line":118},[63,773,774],{"class":617},"    -- Refresh your existing billing view through its authorised server request.\n",[63,776,777,779],{"class":65,"line":143},[63,778,146],{"class":89},[63,780,115],{"class":72},[10,782,783],{},"Business state notifications can also occur when the initial snapshot arrives. Refreshes may repeat. Register listeners when your resource starts and load the current data separately: events do not replay changes that happened before your listener existed.",[785,786,787],"style",{},"html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .s7zQu, html code.shiki .s7zQu{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic}html pre.shiki code .sHdIc, html code.shiki .sHdIc{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}",{"title":59,"searchDepth":66,"depth":118,"links":789},[790,796],{"id":28,"depth":118,"text":29,"children":791},[792,793,794,795],{"id":51,"depth":143,"text":52},{"id":238,"depth":143,"text":239},{"id":479,"depth":143,"text":480},{"id":561,"depth":143,"text":562},{"id":659,"depth":118,"text":660},"React to job, duty, employee, billing and Business changes from your own scripts.","md",null,{},{"icon":802},"i-lucide-radio-tower","/docs/base/jobs-base/events",{"title":5,"description":797},{"loc":803},"1.docs/base/2.jobs-base/5.events","t8ZXETLmo0TtptAAh70poH-OK4RwGBzLYV5OoT6Kfu8",[809,815],{"title":810,"path":811,"stem":812,"description":813,"icon":814,"children":-1},"Training","/docs/base/jobs-base/client-events/training","1.docs/base/2.jobs-base/5.client-events/2.training","Read-only Training App lifecycle and notification events emitted to clients.","i-lucide-graduation-cap",{"title":816,"path":817,"stem":818,"description":819,"icon":820,"children":-1},"Media Providers","/docs/base/jobs-base/media-providers","1.docs/base/2.jobs-base/6.media-providers","Configure FiveManage, Qbox CDN, or register a custom media provider for tablet, gallery, camera, CCTV, speedcam, and bodycam uploads.","i-lucide-cloud-upload",[],1792862174051]