[WIP] Having 2 jobs

jobs

#1

Hi dear community

I’m working with @Cheleber on a 2 jobs scripts modifictions. It’s a lot of work (and debug for me and my dev skills).
Working

  • :white_check_mark: Selecting job and job2
  • :white_check_mark: Load job and job2
  • :white_check_mark: Load hud job and job2 names
  • :white_check_mark: Load hud job and job2 boss accounts
  • :white_check_mark: Save job and job2
  • :white_check_mark: Paychecks
  • :white_check_mark: Getting access to jobs actions, like markers, vehicle spawners etc… for both jobs (as to be done for each job)
  • :white_check_mark: Getting access to both company accounts when grade is boss
  • :white_check_mark: Getting access to both interactions menus (as to be done for each job),
  • :white_check_mark: Only the interaction menu refered to the first job is available if jobs are not modified
  • :white_check_mark:/setjob and /setjob2 commands
  • :white_check_mark: Getting access to both bossmenuaction

Modifications have to be done for:

  • es_extended
  • essentialmode
  • esx_society
  • esx_phone3 from esx_ALphone
  • DBG_LesterJobs (the second job office) or you can copy the esx_joblisting
  • Each job (I will share the esx_ambulancejob to use as base or example)

What I have done:

  • I’m using the job and job grades tables to pick my 2nd job from this list.
  • The second job will be stored in the users table as job2 and job2_grade. Again these are pointing the jobs/name columns.
  • Duplicate all job and job grade function/variables in es_extended & essentialmode
  • Detect 2 jobs in the paycheck function and getting 2 paychecks (depending of job, job_grage, job2 and job2_grade

db

Update 1
-Not solved the name displayed when loading… (its just a visual text and it makes me crazy xD)
-Done: Show correct names on HUD when /setjob and /setjob2
-Done: Show Company account when setjob.grade=boss and setjob2.grade=boss
-Done: Access to both interactions menu F6 and F7
-Done: Access to markers, spawners, functions that requiere a specific job

Update 2
-Done: solved the name displayed when loading… (@Cheleber the hero )

Update 3

  • Everything works with the modified esx_ambulancejob

Release in few days
We will test it on our server for 1 or 2 days to find major bugs.

Participate
Please feel free to participate to improvments like for example :slight_smile:

  • Getting both interaction menu with pressing F6
  • Check and detect if the player has already the job before recruiting him as his job2…

Thanks in advance


[Request] I need a Faction system or 2 jobs system... [In ESX]
#2

For the Load problem you should not being getting the second job the right way when the player connects, show me this function in es_extended/server.lua:

AddEventHandler('es:playerLoaded', function(source, _player)

#3

Already done :cry: but you may have put your finger on the issue. I may have an issue while calling results with [1] that I dont understand very well

** L1-L14 es_extended/server/main.lua**

AddEventHandler('es:playerLoaded', function(source, _player)

  local _source = source
  local tasks   = {}

  local userData = {
    accounts     = {},
    inventory    = {},
    job          = {},
    job2          = {},
    loadout      = {},
    playerName   = GetPlayerName(_source),
    lastPosition = nil
  }

**L149-243 es_extended/server/main.lua **

    -- Get job and loadout
    table.insert(tasks, function(cb)

      local tasks2 = {}

      -- Get job name, grade and last position
      table.insert(tasks2, function(cb2)

        MySQL.Async.fetchAll(
          'SELECT * FROM `users` WHERE `identifier` = @identifier',
          {
            ['@identifier'] = player.getIdentifier()
          },
          function(result)

            userData.job['name']  = result[1].job
			userData.job2['name']  = result[1].job2
            userData.job['grade'] = result[1].job_grade
			userData.job2['grade'] = result[1].job2_grade

            if result[1].loadout ~= nil then
              userData.loadout = json.decode(result[1].loadout)
            end

            if result[1].position ~= nil then
              userData.lastPosition = json.decode(result[1].position)
            end

            cb2()

          end
        )

      end)

      -- Get job label
      table.insert(tasks2, function(cb2)

        MySQL.Async.fetchAll(
          'SELECT * FROM `jobs` WHERE `name` = @name', 
          {
            ['@name'] = userData.job.name,
			['@name'] = userData.job2.name
          },
          function(result)

            userData.job['label'] = result[1].label
			userData.job2['label'] = result[1].label

            cb2()

          end
        )

      end)

      -- Get job grade data
      table.insert(tasks2, function(cb2)

        MySQL.Async.fetchAll(
          'SELECT * FROM `job_grades` WHERE `job_name` = @job_name AND `grade` = @grade',
          {
            ['@job_name'] = userData.job.name,
			['@job_name'] = userData.job2.name,
            ['@grade']    = userData.job.grade,
			['@grade']    = userData.job2.grade
          },
          function(result)

            userData.job['grade_name']   = result[1].name
            userData.job['grade_label']  = result[1].label
            userData.job['grade_salary'] = result[1].salary
			userData.job2['grade_name']   = result[1].name
            userData.job2['grade_label']  = result[1].label
            userData.job2['grade_salary'] = result[1].salary
            userData.job['skin_male']   = {}
            userData.job['skin_female'] = {}

            if result[1].skin_male ~= nil then
              userData.job['skin_male'] = json.decode(result[1].skin_male)
            end

            if result[1].skin_female ~= nil then
              userData.job['skin_female'] = json.decode(result[1].skin_female)
            end

            cb2()

          end
        )

      end)

      Async.series(tasks2, cb)

    end)

 -- Run Tasks
    Async.parallel(tasks, function(results)

      local xPlayer = CreateExtendedPlayer(player, userData.accounts, userData.inventory, userData.job, userData.job2, userData.loadout, userData.playerName, userData.lastPosition)

      xPlayer.getMissingAccounts(function(missingAccounts)

        if #missingAccounts > 0 then

          for i=1, #missingAccounts, 1 do
            table.insert(xPlayer.accounts, {
              name  = missingAccounts[i],
              money = 0,
              label = Config.AccountLabels[missingAccounts[i]]
            })
          end

          xPlayer.createAccounts(missingAccounts)
        end

        ESX.Players[_source] = xPlayer

        TriggerEvent('esx:playerLoaded', _source)

        TriggerClientEvent('esx:playerLoaded', _source, {
          identifier   = xPlayer.identifier,
          accounts     = xPlayer.getAccounts(),
          inventory    = xPlayer.getInventory(),
          job          = xPlayer.getJob(),
		  job2          = xPlayer.getJob2(),
          loadout      = xPlayer.getLoadout(),
          lastPosition = xPlayer.getLastPosition(),
          money        = xPlayer.get('money')
        })

        xPlayer.player.displayMoney(xPlayer.get('money'))

      end)

    end)

  end)

end)

#4

I think this may solve the problem, test it

-- Get job label
      table.insert(tasks2, function(cb2)

        MySQL.Async.fetchAll(
          'SELECT * FROM `jobs` WHERE `name` = @name',
          {
            ['@name'] = userData.job.name
          },
          function(result)

            userData.job['label'] = result[1].label

            cb2()

          end
        )

      end)
      -- Get job2 label
      table.insert(tasks2, function(cb2)

        MySQL.Async.fetchAll(
          'SELECT * FROM `jobs` WHERE `name` = @name',
          {
            ['@name'] = userData.job2.name
          },
          function(result)

            userData.job2['label'] = result[1].label

            cb2()

          end
        )

      end)

      -- Get job grade data
      table.insert(tasks2, function(cb2)

        MySQL.Async.fetchAll(
          'SELECT * FROM `job_grades` WHERE `job_name` = @job_name AND `grade` = @grade',
          {
            ['@job_name'] = userData.job.name,
            ['@grade']    = userData.job.grade
          },
          function(result)

            userData.job['grade_name']   = result[1].name
            userData.job['grade_label']  = result[1].label
            userData.job['grade_salary'] = result[1].salary

            userData.job['skin_male']   = {}
            userData.job['skin_female'] = {}

            if result[1].skin_male ~= nil then
              userData.job['skin_male'] = json.decode(result[1].skin_male)
            end

            if result[1].skin_female ~= nil then
              userData.job['skin_female'] = json.decode(result[1].skin_female)
            end

            cb2()

          end
        )

      end)
	  
	  table.insert(tasks2, function(cb2)

        MySQL.Async.fetchAll(
          'SELECT * FROM `job_grades` WHERE `job_name` = @job_name AND `grade` = @grade',
          {
            ['@job_name'] = userData.job2.name,
            ['@grade']    = userData.job2.grade
          },
          function(result)

            userData.job2['grade_name']   = result[1].name
            userData.job2['grade_label']  = result[1].label
            userData.job2['grade_salary'] = result[1].salary

            userData.job2['skin_male']   = {}
            userData.job2['skin_female'] = {}

            if result[1].skin_male ~= nil then
              userData.job2['skin_male'] = json.decode(result[1].skin_male)
            end

            if result[1].skin_female ~= nil then
              userData.job2['skin_female'] = json.decode(result[1].skin_female)
            end

            cb2()

          end
        )

      end)

      Async.series(tasks2, cb)

    end)

#5

Man I even don’t have words to say thank you … The minimum I can do is to credit you for the release !

Thank you @Cheleber


#6

No problem mate, you were getting the job1 for the two jobs! Awesome release by the way!


#7

Let me until tomorrow to prepare a correct post with all the modifications to be done.
-I will include modifications for 1 complete job usable as job2 (as an exemple that others could use for others scripts and jobs)
-I have to finish the boss management when getting the job2.grade=boss

Its should not be hard, just including most of function in a bigger loop like

for j=1,2,1 do
local job=job[j]

functions...

end

#8

Nice!

For the second thing i dont know if i get you, but how about this idea:

Create a function equal to “OpenBossMenu” .

function OpenBossMenu2(society, close, options)

AddEventHandler('esx_society:openBossMenu2', function(society, close, options)
  OpenBossMenu2(society, close, options)
end)

EDIT: Other functions that maybe need to be replicate:

function OpenManageGradesMenu(society)
function OpenPromoteMenu(society, employee)
function OpenRecruitMenu(society)
function OpenEmployeeList(society)
function OpenManageEmployeesMenu(society)

#9

How you do to get in job2 in the database?


#10

He created a job2 and jo2_grade column in the table users


#11

It’s a good idea. Its there a way to not getting limitations when checking the job2 for players getting the same job but as job1

function OpenBossMenu(society, close, options)

AddEventHandler('esx_society:openBossMenu', function(society, close, options)
  OpenBossMenu(society, close, options)
end)

function OpenManageGradesMenu(society)
function OpenPromoteMenu(society, employee)
function OpenRecruitMenu(society)
function OpenEmployeeList(society)
function OpenManageEmployeesMenu(society)

Correct, for this reason OpenBossMenu Should check players’s jobs 1 and 2.
To be able to Promote/Recruit/get list/and manage all players getting the job as job1 or job2

Or do you think that it would be better to split it as 2 different functions openbossmenu and openbossmenu ?


#12

job2.sql

ALTER TABLE users ADD job2 varchar(255) NULL DEFAULT 'unemployed2' AFTER job_grade;
ALTER TABLE users ADD job2_grade INT NULL DEFAULT 0 AFTER job2;

Unemployed 2 was added to the jobs and job_grades tables

table jobs:
55 unemployed2 unemploi 0 1

table job_grades:
247 unemployed2 0 rsa Citoyen 0 {} {}


#13

For now i cant answer your question, what is better or not, I just took a look and I did not see anything very premonized!
Here it’s late and I’m tired, I’ll take a closer look tomorrow if you have not already done this of course!

EDITED:
And i have take another look now, and yes you probably dont need to replicate the OpenBossMenu function, but you need to send the information if it is a job1 or a job2! And then just replicate the promote/recruit/get list/manage functions!

Like this

function OpenBossMenu(society, close, options, jobnumber)

AddEventHandler('esx_society:openBossMenu', function(society, close, options, jobnumber)
  OpenBossMenu(society, close, options, jobnumber)
end)

#14

Update 3

Its working with the modified job esx_ambulancejob !


#15

is this something you want to share?


#16

Where is the release. i so need this.