Início › Documentação › Instalação · origen_masterjob

Instalação · origen_masterjob

Recomendamos carregar os ficheiros do script sem usar o FileZilla, porque o processo de envio pode corromper os scripts. Usa o WinSCP ou outros programas fiáveis.


1. Modificações do framework

Tens de modificar o código-fonte do teu framework para que o origen_masterjob consiga intercetar as mudanças de job e a lógica dos salários.

QBCore

qb-core/server/player.lua

Substitui a função self.Functions.SetJob pela seguinte:

lua
function self.Functions.SetJob(job, grade, fromMJ)
    local job = job:lower()
    local grade = tostring(grade) or '0'
 
    if QBCore.Shared.Jobs[job] ~= nil then
        if not fromMJ and GetResourceState('origen_masterjob') == 'started' then
            local BusN = exports["origen_masterjob"]:GetBusiness(self.PlayerData.job.name)
            if BusN then
                BusN.Functions.RemovePlayer(self.PlayerData.citizenid, true)
                TriggerClientEvent("origen_masterjob:client:OnBusinessUpdate", self.PlayerData.source, false)
            end
        end
        self.PlayerData.job.name = job
        self.PlayerData.job.label = QBCore.Shared.Jobs[job].label
        self.PlayerData.job.onduty = QBCore.Shared.Jobs[job].defaultDuty
 
        if QBCore.Shared.Jobs[job].grades[grade] then
            local jobgrade = QBCore.Shared.Jobs[job].grades[grade]
            self.PlayerData.job.grade = {}
            self.PlayerData.job.grade.name = jobgrade.name
            self.PlayerData.job.grade.level = tonumber(grade)
            self.PlayerData.job.payment = jobgrade.payment ~= nil and jobgrade.payment or 30
            self.PlayerData.job.isboss = jobgrade.isboss ~= nil and jobgrade.isboss or false
        else
            return false
        end
 
        self.Functions.UpdatePlayerData()
        TriggerClientEvent("QBCore:Client:OnJobUpdate", self.PlayerData.source, self.PlayerData.job)
        return true
    elseif GetResourceState('origen_masterjob') == 'started' then
        local BusN = exports["origen_masterjob"]:GetBusiness(job)
        if BusN then
            local jobgrade = BusN.Functions.GetGrade(grade)
            if not jobgrade then
                return false
            end
            
            local oldBusN = exports["origen_masterjob"]:GetBusiness(self.PlayerData.job.name)
            if oldBusN then
                BusN.Functions.RemovePlayer(self.PlayerData.citizenid, true)
                TriggerClientEvent("origen_masterjob:client:OnBusinessUpdate", self.PlayerData.source, false)
            end
 
            self.PlayerData.job.name = job
            self.PlayerData.job.label = BusN.Data.label
            self.PlayerData.job.onduty = false
 
            self.PlayerData.job.grade = {}
            self.PlayerData.job.grade.name = jobgrade.label or "Sin grado"
            self.PlayerData.job.grade.level = tonumber(grade)
 
            self.PlayerData.job.payment = jobgrade.pay or 30
            self.PlayerData.job.isboss = jobgrade.boss or false
 
            self.Functions.UpdatePlayerData()
            TriggerClientEvent("QBCore:Client:OnJobUpdate", self.PlayerData.source, self.PlayerData.job)
 
            if not fromMJ then
                BusN.Functions.AddPlayer(self.PlayerData.citizenid, self.PlayerData.charinfo.firstname .. " " .. self.PlayerData.charinfo.lastname, tostring(grade), true)
            end
 
            return true
        end
    end
 
    return false
end

qb-core/shared/jobs.lua

Define ForceJobDefaultDutyAtLogin como false:

lua
QBShared.ForceJobDefaultDutyAtLogin = false

qb-core/server/functions.lua

Adiciona a seguinte verificação dentro da função PaycheckInterval. Envolve a lógica de salários existente com uma guarda que ignore os jobs partilhados que não existem (para que os jobs geridos pelo masterjob não deem erros):

lua
function PaycheckInterval()
    if next(QBCore.Players) then
        for _, Player in pairs(QBCore.Players) do
            if Player then
                if QBShared.Jobs[Player.PlayerData.job.name] then -- Add this check
                    local payment = QBShared.Jobs[Player.PlayerData.job.name]['grades'][tostring(Player.PlayerData.job.grade.level)].payment
                    if not payment then payment = Player.PlayerData.job.payment end
                    if Player.PlayerData.job and payment > 0 and (QBShared.Jobs[Player.PlayerData.job.name].offDutyPay or Player.PlayerData.job.onduty) then
                        if QBCore.Config.Money.PayCheckSociety then
                            local account = exports['qb-management']:GetAccount(Player.PlayerData.job.name)
                            if account ~= 0 then
                                if account < payment then
                                    TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('error.company_too_poor'), 'error')
                                else
                                    Player.Functions.AddMoney('bank', payment, 'paycheck')
                                    exports['qb-management']:RemoveMoney(Player.PlayerData.job.name, payment)
                                    TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', {value = payment}))
                                end
                            else
                                Player.Functions.AddMoney('bank', payment, 'paycheck')
                                TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', {value = payment}))
                            end
                        else
                            Player.Functions.AddMoney('bank', payment, 'paycheck')
                            TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', {value = payment}))
                        end
                    end
                end -- Add this check
            end
        end
    end
    SetTimeout(QBCore.Config.Money.PayCheckTimeOut * (60 * 1000), PaycheckInterval)
end

qb-core/shared/items.lua

Adiciona o item tablet do negócio:

lua
['business_cad']    = {["name"] = "business_cad",   ["label"] = "Business tablet",  ["weight"] = 0,      ["type"] = "item",     ["image"] = "tablet.png",  ["unique"] = true,    ["useable"] = true,  ["shouldClose"] = false,   ["combinable"] = nil,   ["description"] = "Your personal tablet with all the information of the San Andreas business"},

ESX

es_extended/server/classes/player.lua

Substitui a função self.setJob pela seguinte:

lua
function self.setJob(newJob, grade)
    grade = tostring(grade)
    local lastJob = json.decode(json.encode(self.job))
 
    if ESX.DoesJobExist(newJob, grade) then
        if not fromMJ and  GetResourceState('origen_masterjob'):find('start') then
            local BusN = exports["origen_masterjob"]:GetBusiness(self.job.name)
            if BusN then
                BusN.Functions.RemovePlayer(self.identifier, true)
                TriggerClientEvent("origen_masterjob:client:OnBusinessUpdate", self.source, false)
            end
        end
 
        local jobObject, gradeObject = ESX.Jobs[newJob], ESX.Jobs[newJob].grades[grade]
 
        self.job.id                  = jobObject.id
        self.job.name                = jobObject.name
        self.job.label               = jobObject.label
 
        self.job.grade               = tonumber(grade)
        self.job.grade_name          = gradeObject.name
        self.job.grade_label         = gradeObject.label
        self.job.grade_salary        = gradeObject.salary
 
        if gradeObject.skin_male then
            self.job.skin_male = json.decode(gradeObject.skin_male)
        else
            self.job.skin_male = {}
        end
 
        if gradeObject.skin_female then
            self.job.skin_female = json.decode(gradeObject.skin_female)
        else
            self.job.skin_female = {}
        end
 
        TriggerEvent('esx:setJob', self.source, self.job, lastJob)
        self.triggerEvent('esx:setJob', self.job, lastJob)
        Player(self.source).state:set("job", self.job, true)
    elseif GetResourceState('origen_masterjob'):find('start') then
        local BusN = exports["origen_masterjob"]:GetBusiness(newJob)
        if BusN then
            local jobgrade = BusN.Functions.GetGrade(grade)
 
            if not jobgrade then
                print(('[es_extended] [^3WARNING^7] Ignoring invalid ^5.setJob()^7 usage for ID: ^5%s^7, Job: ^5%s^7'):format(self.source, newJob))
            end
 
            local oldBusN = exports["origen_masterjob"]:GetBusiness(self.job.name)
 
            if oldBusN then
                oldBusN.Functions.RemovePlayer(self.identifier, true)
                TriggerClientEvent("origen_masterjob:client:OnBusinessUpdate", self.source, false)
            end
 
            self.job.name                = newJob
            self.job.label               = BusN.Data.label
 
            self.job.grade               = tonumber(grade)
            self.job.grade_name          = jobgrade.boss and "boss" or jobgrade.label:lower():gsub(" ", "_")
            self.job.grade_label         = jobgrade.label or "Sin grado"
            self.job.grade_salary        = jobgrade.pay or 30
            self.job.isBusiness          = true
            self.job.skin_male = {}
            self.job.skin_female = {}
 
            TriggerEvent('esx:setJob', self.source, self.job, lastJob)
            self.triggerEvent('esx:setJob', self.job, lastJob)
            Player(self.source).state:set("job", self.job, true)
 
            if not fromMJ then
                BusN.Functions.AddPlayer(self.identifier, self.get("firstName") .. " " .. self.get("lastName"), tostring(grade), true)
            end
        else
            print(('[es_extended] [^3WARNING^7] Ignoring invalid ^5.setJob()^7 usage for ID: ^5%s^7, Job: ^5%s^7'):format(self.source, newJob))
        end
    else
        print(('[es_extended] [^3WARNING^7] Ignoring invalid ^5.setJob()^7 usage for ID: ^5%s^7, Job: ^5%s^7'):format(self.source, newJob))
    end
end

es_extended/server/main.lua

Comenta ou remove as seguintes linhas:

lua
if not ESX.DoesJobExist(job, grade) then
    print(("[^3WARNING^7] Ignoring invalid job for ^5%s^7 [job: ^5%s^7, grade: ^5%s^7]"):format(identifier, job, grade))
    job, grade = "unemployed", "0"
end
 
local jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade]

Substitui-as pelas seguintes:

lua
if ESX.DoesJobExist(job, grade) then
    jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade]
elseif  GetResourceState('origen_masterjob'):find('start') then
    local BusN = exports["origen_masterjob"]:GetBusiness(job)
    if BusN then
        local jobgrade = BusN.Functions.GetGrade(grade)
 
        if jobgrade then
            jobObject = {
                id = BusN.Data.id,
                name = job,
                label = BusN.Data.label,
            }
            gradeObject = {
                name = jobgrade.boss and "boss" or jobgrade.label:lower():gsub(" ", "_"),
                label = jobgrade.label or "Sin grado",
                salary = jobgrade.pay or 30
            }
        else
            print(('[^3WARNING^7] Ignoring invalid job for ^5%s^7 [job: ^5%s^7, grade: ^5%s^7]'):format(identifier, job, grade))
        end
    else
        print(('[^3WARNING^7] Ignoring invalid job for ^5%s^7 [job: ^5%s^7, grade: ^5%s^7]'):format(identifier, job, grade))
    end
else
    print(('[^3WARNING^7] Ignoring invalid job for ^5%s^7 [job: ^5%s^7, grade: ^5%s^7]'):format(identifier, job, grade))
    job, grade = 'unemployed', '0'
    jobObject, gradeObject = ESX.Jobs[job], ESX.Jobs[job].grades[grade]
end

es_extended/server/paycheck.lua

Adiciona a seguinte verificação antes da lógica de pagamento do salário para ignorar os salários dos negócios geridos pelo masterjob:

lua
if xPlayer.job.isBusiness then
    salary = 0
end

pma-voice

Adiciona os seguintes exports no fim de pma-voice/client/init/main.lua:

lua
exports("toggleVoice", toggleVoice)
exports("playerTargets", playerTargets)

2. Base de dados

Executa as seguintes instruções SQL para criar as tabelas necessárias.

sql
CREATE TABLE IF NOT EXISTS `origen_masterjob` (
  `id`            varchar(50)  NOT NULL DEFAULT 'ERROR',
  `label`         varchar(255) NOT NULL DEFAULT 'ERROR',
  `type`          varchar(50)  NOT NULL DEFAULT 'shop',
  `level`         int(11)      NOT NULL DEFAULT 0,
  `experience`    int(11)      NOT NULL DEFAULT 0,
  `money`         int(11)      NOT NULL DEFAULT 0,
  `open`          int(1)       NOT NULL DEFAULT 0,
  `skills`        longtext     NOT NULL DEFAULT '{}',
  `grades`        longtext     NOT NULL DEFAULT '[]',
  `players`       longtext     NOT NULL DEFAULT '[]',
  `npcs`          longtext     NOT NULL DEFAULT '[]',
  `markers`       longtext     NOT NULL DEFAULT '[]',
  `items`         longtext     NOT NULL DEFAULT '[]',
  `missions`      longtext     NOT NULL DEFAULT '[]',
  `vehicles`      longtext     NOT NULL DEFAULT '[]',
  `metadata`      longtext     NOT NULL DEFAULT '[]',
  `stats`         longtext     NOT NULL DEFAULT '[]',
  `allowed_items` longtext     NOT NULL DEFAULT '[]',
  PRIMARY KEY (`id`)
);
 
CREATE TABLE IF NOT EXISTS `origen_masterjob_bills` (
  `id`        int(11)      NOT NULL AUTO_INCREMENT,
  `citizenid` varchar(50)  NOT NULL,
  `title`     varchar(255) DEFAULT '',
  `concepts`  text         DEFAULT '[]',
  `price`     int(11)      DEFAULT 0,
  `job`       varchar(50)  DEFAULT '',
  `author`    varchar(255) DEFAULT '',
  `payed`     int(1)       DEFAULT 0,
  `date`      timestamp    DEFAULT current_timestamp(),
  `months`    int(11)      DEFAULT 0,
  `reportid`  int(11)      DEFAULT 0,
  PRIMARY KEY (`id`)
);
 
CREATE TABLE IF NOT EXISTS `origen_masterjob_documents` (
  `id`         int(11)      NOT NULL AUTO_INCREMENT,
  `businessid` varchar(255) NOT NULL DEFAULT '',
  `title`      varchar(255) DEFAULT '',
  `description` text        DEFAULT '',
  `author`     varchar(255) NOT NULL DEFAULT '',
  `date`       timestamp    DEFAULT current_timestamp(),
  `images`     text         DEFAULT '[]',
  PRIMARY KEY (`id`)
);
 
CREATE TABLE IF NOT EXISTS `origen_masterjob_garage` (
  `id`        varchar(50) NOT NULL DEFAULT 'ERROR',
  `garage`    varchar(50) DEFAULT NULL,
  `plate`     varchar(50) NOT NULL DEFAULT 'ERROR',
  `mods`      longtext    DEFAULT NULL,
  `state`     int(1)      DEFAULT 0,
  `citizenid` varchar(50) DEFAULT NULL,
  `model`     varchar(50) DEFAULT NULL,
  PRIMARY KEY (`plate`)
);
 
CREATE TABLE IF NOT EXISTS `origen_masterjob_notes` (
  `id`          int(11)      NOT NULL AUTO_INCREMENT,
  `documentid`  varchar(50)  NOT NULL,
  `title`       varchar(255) DEFAULT '',
  `description` text         DEFAULT '',
  `author`      varchar(255) DEFAULT '',
  `date`        timestamp    DEFAULT current_timestamp(),
  `fixed`       int(1)       DEFAULT 0,
  PRIMARY KEY (`id`)
);

origen_masterjob_garage só é usada quando a funcionalidade de garagem do negócio está ativada na configuração.

origen_metadata (opcional)

Só é obrigatória quando Config.fixQS está a true em ambientes ESX. Esta tabela guarda os metadados de cada jogador quando não se usa o sistema de metadados nativo do ESX.

sql
CREATE TABLE IF NOT EXISTS `origen_metadata` (
  `id`   varchar(55) NOT NULL,
  `data` longtext    DEFAULT '',
  PRIMARY KEY (`id`)
);

3. server.cfg

text
ensure origen_masterjob

Garante que o origen_masterjob arranca DEPOIS do teu framework (qb-core ou es_extended) e DEPOIS do oxmysql.