GKSPHONE V2
Job Center
Define solo and group jobs for the Job Center app, and drive them from your own scripts.
The Job Center lists jobs players can pick up, alone or as a group, and tracks a task list while they work. Two ship as working examples — sanitation and carthief.
| What | Where |
|---|---|
| Job list | gksphone/config/jobs/sh_jobs.lua |
| Task lists | gksphone/config/jobs/sh_tasks.lua |
| Example scripts | gksphone/server/jobs/, gksphone/client/apps/jobs/ |
Define a job
Add an entry to GKSJobs.Jobs, keyed by the job code:
["carthief"] = {
["Name"] = "carthief",
["Label"] = "Car Thief",
["Description"] = "We need someone with magic hands. Is that you?",
["Icon"] = "directions_car",
["IconColor"] = "red",
["Rating"] = 4,
["Money"] = math.random(100, 1000),
["MimWorkers"] = 1,
["MaxWorkers"] = 1,
["Location"] = false,
["RequiredItem"] = true,
["ItemRequired"] = "lockpick",
["IsActive"] = true
},| Field | |
|---|---|
Name | Job code. Match the table key |
Label | Name shown in the app |
Description | Blurb on the job card |
Icon | A Google Material Symbols name |
IconColor | Icon colour |
Rating | Difficulty stars shown on the card |
Money | Payout. Your job script reads this — wrap it in math.random for a range |
MimWorkers / MaxWorkers | Group size limits |
Location | vector3 or vector4 start point, or false for none |
RequiredItem | true if an item is needed to see the job |
ItemRequired | The item's name. Only read when RequiredItem is true |
IsActive | Whether the job is listed at all |
RequiredItem and ItemRequired are two different fields. RequiredItem is the on/off switch, ItemRequired holds the item name — putting the name in RequiredItem does not work.
Define its tasks
Keyed by the same job code, in order:
['sanitation'] = {
{ ["TaskId"] = 1, ["TaskText"] = "Get in the garbage truck", ["Finished"] = false },
{ ["TaskId"] = 2, ["TaskText"] = "Go to mission area", ["Finished"] = false },
{
["TaskId"] = 3,
["TaskText"] = "Collect trash %s",
["Finished"] = false,
["ExtraDone"] = 0,
["ExtraNeed"] = 10
},
}| Field | |
|---|---|
TaskId | Starts at 1, increments by one |
TaskText | Shown to the player. %s is replaced with progress |
Finished | Always false here — the phone flips it |
ExtraDone / ExtraNeed | For counted tasks: starting count and target |
Events
-- Fires for every group member when the job starts
RegisterNetEvent("gksphone:client:JobStartTask", function(jobInfoName, Tasks) end)
-- Fires for the group leader only
RegisterNetEvent("gksphone:client:jobStartLeader", function(jobInfoName) end)
-- Fires for every member when the task advances
RegisterNetEvent("gksphone:client:JobNextTask", function(NewTaskID) end)There is no finish event. Your script decides when the job is done, and must delete the group itself with DeleteJobGroup.
Exports
Server
-- Group of the player who leads it
local group = exports["gksphone"]:GetJobGroupByLeader(identifier)
-- Group a player belongs to
local group = exports["gksphone"]:GetGroupByMember(identifier)
-- End the job
exports["gksphone"]:DeleteJobGroup("carthief", groupID)Client
exports["gksphone"]:IsGroupLeader() -- boolean
exports["gksphone"]:IsTaskStatus(taskId) -- boolean, is that task finished
exports["gksphone"]:TaskList() -- the current task list
-- Mark a task done, or advance a counted one
exports["gksphone"]:TaskUpdate(taskId, true, extraDone)
-- Rewrite the whole list, e.g. to change task text mid-job
exports["gksphone"]:TaskListUpdate(taskList)TaskUpdate's third argument is the new ExtraDone count for counted tasks — pass 0 for a plain one.

