> For the complete documentation index, see [llms.txt](https://savana.gitbook.io/savanascripts/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://savana.gitbook.io/savanascripts/scripts/farming-job/editable-files.md).

# Editable Files

{% hint style="info" %} <mark style="color:$info;">The core logic files are encrypted via Cfx.re Escrow, but all configuration and language files remain fully accessible and editable. You retain full control over the script’s behavior, visual settings, and translations without any restrictions.</mark>

<mark style="color:blue;">(Source package users are not affected by this)</mark>
{% endhint %}

{% tabs %}
{% tab title="core/core.lua" %}

```lua
-- do not edit this page

core = {}

core.framework = { -- do not edit here [Auto Detect]
    name = nil,
    export = nil
}


-- @param framework notify [Auto detect QB/QBX/ESX]
-- @param script notify | Use script notify with coming farming UI
core.notify = 'framework' -- script or framework
core.webhook = '' -- ensure your discord webhook url for logs

CreateThread(function()
    if GetResourceState('qb-core') == 'started' or GetResourceState('qbx_core') == 'started' then
        core.framework.name = 'qb'
        core.framework.export = exports['qb-core']:GetCoreObject()
    elseif GetResourceState('es_extended') == 'started' then
        core.framework.name = 'esx'
        core.framework.export = exports["es_extended"]:getSharedObject()
    end
    fw = core.framework.export
end)






```

{% endtab %}

{% tab title="core/locale.lua" %}

```lua
-- do not edit this page


Locales = Locales or {}

local function lookup(lang, section, key)
    local store = Locales[lang]
    if not store then return nil end
    local sec = store[section]
    if not sec then return nil end
    return sec[key]
end

function T(path, ...)
    if type(path) ~= 'string' then return tostring(path) end

    local section, key = path:match('^(.-)%.(.+)$')
    if not section or not key then return path end

    local lang = (cfg and cfg.language) or 'en'
    local val = lookup(lang, section, key)

    if val == nil and lang ~= 'en' then
        val = lookup('en', section, key)
    end

    if val == nil then return path end

    if select('#', ...) > 0 then
        local ok, res = pcall(string.format, val, ...)
        if ok then return res end
    end
    return val
end

function GetLocale()
    local lang = (cfg and cfg.language) or 'en'
    return Locales[lang] or Locales['en'] or {}
end

function GetLocaleLang()
    return (cfg and cfg.language) or 'en'
end

```

{% endtab %}

{% tab title="core/target.lua" %}

```lua
-- Editing is not recommended.

target = {}

local function isOx() return GetResourceState('ox_target') == 'started' end
local function isQb() return GetResourceState('qb-target') == 'started' end
local function useShowText() return (cfg and cfg.interaction == 'showText') end

local function getShowTextKey()      return (cfg.showText and cfg.showText.key)      or 38 end
local function getShowTextKeyLabel() return (cfg.showText and cfg.showText.keyLabel) or 'E' end
local function getShowTextPosition() return (cfg.showText and cfg.showText.position) or 'right-center' end

local activePoints = {}
local activeEntityPoints = {}
local currentShownLabel = nil
local activePoint = nil

local function toQbOptions(options)
    local result = {}
    for i = 1, #options do
        local o = options[i]
        local select = o.onSelect or o.action
        result[#result + 1] = {
            type = "client",
            action = select and function(entity) select(entity) end,
            icon = o.icon,
            label = o.label,
            num = o.num,
            distance = o.distance or 2.0,
        }
    end
    return result
end

local function toOxOptions(options)
    local result = {}
    for i = 1, #options do
        local o = options[i]
        local fn = o.onSelect or o.action
        result[#result + 1] = {
            name = o.name,
            label = o.label,
            icon = o.icon,
            onSelect = fn,
            distance = o.distance or 2.0,
            num = o.num,
        }
    end
    return result
end

local function buildShowTextLabel(options)
    local keyLabel = getShowTextKeyLabel()
    for i = 1, #options do
        local o = options[i]
        if o.label then
            return string.format('[%s] %s', keyLabel, o.label)
        end
    end
    return string.format('[%s]', keyLabel)
end

local function fireFirstAction(options, entity)
    for i = 1, #options do
        local o = options[i]
        local fn = o.onSelect or o.action
        if fn then
            fn(entity)
            return
        end
    end
end

local function showLabel(label)
    currentShownLabel = label
    lib.showTextUI(label, { position = getShowTextPosition() })
end

local function hideLabel(label)
    if currentShownLabel == label then
        currentShownLabel = nil
        lib.hideTextUI()
    end
end

local function distToPoint(p)
    if not p or not p.coords then return math.huge end
    local pc = GetEntityCoords(PlayerPedId())
    return #(pc - p.coords)
end

local function makePoint(coords, distance, options, entity)
    local label = buildShowTextLabel(options)
    local point = lib.points.new({
        coords = coords,
        distance = distance,
    })
    point.label = label
    point.options = options
    point.entity = entity
    point.nearby = function(self)
        if animPlaying then
            if activePoint == self then
                hideLabel(self.label)
                activePoint = nil
            end
            return
        end

        local selfDist = distToPoint(self)
        local activeDist = activePoint and distToPoint(activePoint) or math.huge

        if not activePoint or activePoint == self or selfDist < activeDist then
            if activePoint ~= self then
                if activePoint then hideLabel(activePoint.label) end
                activePoint = self
                showLabel(self.label)
            end
        end
    end
    point.onExit = function(self)
        if activePoint == self then
            hideLabel(self.label)
            activePoint = nil
        end
    end
    return point
end

CreateThread(function()
    while true do
        local wait = 500
        if activePoint and not animPlaying then
            wait = 0
            if IsControlJustReleased(0, getShowTextKey()) then
                local p = activePoint
                fireFirstAction(p.options, p.entity)
            end
        end
        Wait(wait)
    end
end)

local function clearActiveIfPoint(p)
    if p and activePoint == p then
        hideLabel(p.label)
        activePoint = nil
    end
end

function target.addLocalEntity(entity, options)
    if not entity or not options or #options == 0 then return end
    local distance = options[1].distance or 2.0
    if useShowText() then
        local coords = GetEntityCoords(entity)
        activeEntityPoints[entity] = makePoint(coords, distance, options, entity)
        return
    end
    if isOx() then
        exports.ox_target:addLocalEntity(entity, toOxOptions(options))
    elseif isQb() then
        exports['qb-target']:AddTargetEntity(entity, {
            options = toQbOptions(options),
            distance = distance
        })
    end
end

function target.removeLocalEntity(entity, optionNames)
    if not entity then return end
    if useShowText() then
        local p = activeEntityPoints[entity]
        if p then
            clearActiveIfPoint(p)
            hideLabel(p.label)
            p:remove()
            activeEntityPoints[entity] = nil
        end
        return
    end
    if isOx() then
        exports.ox_target:removeLocalEntity(entity, optionNames)
    elseif isQb() then
        exports['qb-target']:RemoveTargetEntity(entity, optionNames)
    end
end

function target.addSphereZone(data)
    if not data or not data.name or not data.coords or not data.options then return end
    local radius = data.radius or 1.5
    local distance = (data.options[1] and data.options[1].distance) or 2.0
    if useShowText() then
        activePoints[data.name] = makePoint(data.coords, math.max(radius, distance), data.options)
        return
    end
    if isOx() then
        exports.ox_target:addSphereZone({
            name = data.name,
            coords = data.coords,
            radius = radius,
            debug = data.debug or false,
            options = toOxOptions(data.options)
        })
    elseif isQb() then
        exports['qb-target']:AddBoxZone(data.name, data.coords, radius, radius, {
            name = data.name,
            heading = 0,
            debugPoly = data.debug or false,
            minZ = data.coords.z - radius,
            maxZ = data.coords.z + radius,
        }, {
            options = toQbOptions(data.options),
            distance = distance
        })
    end
end

function target.addBoxZone(data)
    if not data or not data.name or not data.coords or not data.options then return end
    local distance = (data.options[1] and data.options[1].distance) or 2.0
    local size = data.size or vec3(1.0, 1.0, 1.0)
    local heading = data.rotation or data.heading or 0
    if useShowText() then
        local reach = math.max(size.x, size.y, size.z, distance)
        activePoints[data.name] = makePoint(data.coords, reach, data.options)
        return
    end
    if isOx() then
        exports.ox_target:addBoxZone({
            name = data.name,
            coords = data.coords,
            size = size,
            rotation = heading,
            debug = data.debug or false,
            options = toOxOptions(data.options)
        })
    elseif isQb() then
        exports['qb-target']:AddBoxZone(data.name, data.coords, size.x, size.y, {
            name = data.name,
            heading = heading,
            debugPoly = data.debug or false,
            minZ = data.coords.z - (size.z / 2),
            maxZ = data.coords.z + (size.z / 2),
        }, {
            options = toQbOptions(data.options),
            distance = distance
        })
    end
end

function target.removeZone(name)
    if not name then return end
    if useShowText() then
        local p = activePoints[name]
        if p then
            clearActiveIfPoint(p)
            hideLabel(p.label)
            p:remove()
            activePoints[name] = nil
        end
        return
    end
    if isOx() then
        exports.ox_target:removeZone(name)
    elseif isQb() then
        exports['qb-target']:RemoveZone(name)
    end
end

```

{% endtab %}

{% tab title="core/nui.lua" %}

```lua
-- do not edit this page


function nui(action, data)
    SendNUIMessage({
        action = action,
        data = data
    })
end

function sendLocaleToNUI()
    if not GetLocale then return end
    SendNUIMessage({
        action = 'setLocale',
        data = {
            lang = GetLocaleLang(),
            strings = GetLocale()
        }
    })
end

RegisterNUICallback('requestLocale', function(_, cb)
    sendLocaleToNUI()
    cb('ok')
end)

CreateThread(function()
    while not Locales or not GetLocale or not next(GetLocale() or {}) do
        Wait(50)
    end
    sendLocaleToNUI()
end)

AddEventHandler('onClientResourceStart', function(resource)
    if resource ~= GetCurrentResourceName() then return end
    sendLocaleToNUI()
end)
```

{% endtab %}

{% tab title="core/main/client.lua" %}

```lua
local MugshotsCache = {}
fw = nil -- Don’t change this.

function getPlayerName()  -- Retrieves the player's name from the client.
    local name = "Name Undefined"
    if core.framework.name == 'qb' then
        local PlayerData = fw.Functions.GetPlayerData()
        if PlayerData and PlayerData.charinfo then
            name = PlayerData.charinfo.firstname .. ' ' .. PlayerData.charinfo.lastname
        end
    elseif core.framework.name == 'esx' then
        local PlayerData = fw.GetPlayerData()
        
        if PlayerData.firstName and PlayerData.lastName then
            name = PlayerData.firstName .. ' ' .. PlayerData.lastName
        else
            name = GetPlayerName(PlayerId())
        end
    end
    return name
end

function getPlayerMoney() -- Retrieves the player's money from the client.
    local money = 0

    if core.framework.name == 'qb' then
        local PlayerData = fw.Functions.GetPlayerData()
        if PlayerData and PlayerData.money then
            local cash = PlayerData.money['cash']
            local bank = PlayerData.money['bank']
            money = tonumber(bank) + tonumber(cash)
        end

    elseif core.framework.name == 'esx' then
        local PlayerData = fw.GetPlayerData()
        if PlayerData and PlayerData.accounts then
            local cash, bank = 0, 0
            for _, account in pairs(PlayerData.accounts) do
                if account.name == 'money' then
                    cash = account.money or 0
                elseif account.name == 'bank' then
                    bank = account.money or 0
                end
            end
            money = cash + bank
        end
    end

    return money
end


function getPlayerCid() -- Retrieves the player's citizenid from the client.
    if core.framework.name == 'qb' then
        return fw.Functions.GetPlayerData().citizenid
    else
        return fw.GetPlayerData().identifier
    end
end

function getPlayerImage() -- for mugshot
  local Ped = PlayerPedId()
  local Handle = RegisterPedheadshot(Ped)

  local timer = 2000
  while ((not Handle or not IsPedheadshotReady(Handle) or not IsPedheadshotValid(Handle)) and timer > 0) do
    Citizen.Wait(10)
    timer = timer - 10
  end

  local MugShotTxd = 'none'
  if (IsPedheadshotReady(Handle) and IsPedheadshotValid(Handle)) then
    MugShotTxd = GetPedheadshotTxdString(Handle)
  end

  table.insert(MugshotsCache, Handle)

  return "https://nui-img/"..MugShotTxd.."/"..MugShotTxd
end


function notify(message, types)
    if core.notify == 'script' then
        SendNUIMessage({ -- It may be added in the next update.
            action = 'notify',
            msg = message,
            type = types
        })
    elseif core.notify == 'framework' then
        if core.framework.name == 'qb' then
            fw.Functions.Notify(message, types)
        elseif core.framework.name == 'esx' then
            fw.ShowNotification(message, types)
        end
    end
end

function DrawFarmArea(points) 
    if #points < 3 then return end
    
    local z = {}
    for i = 1, #points do
        local _, groundZ = GetGroundZFor_3dCoord(points[i].x, points[i].y, 800.0, false)
        z[i] = (groundZ or points[i].z) + 0.1
    end

    local p1, p2, p3 = points[1], points[2], points[3]
    DrawPoly(p1.x, p1.y, z[1] + 3, p2.x, p2.y, z[2] + 3, p3.x, p3.y, z[3] + 3, 137, 255, 0, 80)
    
    if #points >= 4 then
        local p4 = points[4]
        DrawPoly(p1.x, p1.y, z[1] + 3, p3.x, p3.y, z[3] + 3, p4.x, p4.y, z[4] + 3, 137, 255, 0, 80)
    end
end

function DrawFarmBoundaries(points)
    for i = 1, #points do
        local p1 = points[i]
        local p2 = points[i % #points + 1]

        local _, z1 = GetGroundZFor_3dCoord(p1.x, p1.y, 800.0, false)
        local _, z2 = GetGroundZFor_3dCoord(p2.x, p2.y, 800.0, false)
        
        z1 = (z1 or p1.z) + 0.1
        z2 = (z2 or p2.z) + 0.1

        DrawLine(p1.x, p1.y, z1, p2.x, p2.y, z2, 0, 255, 255, 200)
    end
end

function clearMugshot()
  for ped, handle in pairs(MugshotsCache) do
    UnregisterPedheadshot(handle)
  end
  MugshotsCache = {}
end

function getItemCount(item)
    if GetResourceState('ox_inventory') == 'started' then
        return exports.ox_inventory:Search('count', item) or 0
    end

    if GetResourceState('one_inventory') == 'started' then
        return exports.one_inventory:SearchInventory('count', item, nil) or 0
    end

    if core.framework.name == 'qb' and fw and fw.Functions and fw.Functions.GetPlayerData then
        local PlayerData = fw.Functions.GetPlayerData()
        if PlayerData and PlayerData.items then
            for _, slotData in pairs(PlayerData.items) do
                if slotData.name == item then
                    return slotData.amount or slotData.count or 0
                end
            end
        end
    elseif core.framework.name == 'esx' and fw and fw.GetPlayerData then
        local PlayerData = fw.GetPlayerData()
        if PlayerData and PlayerData.inventory then
            for _, slotData in pairs(PlayerData.inventory) do
                if slotData.name == item then
                    return slotData.count or 0
                end
            end
        end
    end

    return 0
end


scriptPeds = scriptPeds or {}
scriptBlips = scriptBlips or {}

CreateThread(function()
    local pedModel = GetHashKey(cfg.farmingCenter.ped)
    RequestModel(pedModel)

    while not HasModelLoaded(pedModel) do
        Wait(1)
    end

    local farmingPed = CreatePed(4, pedModel, cfg.farmingCenter.coord.x, cfg.farmingCenter.coord.y, cfg.farmingCenter.coord.z, cfg.farmingCenter.coord.w, false, true)
    table.insert(scriptPeds, farmingPed)

    SetEntityHeading(farmingPed, cfg.farmingCenter.coord.w)
    FreezeEntityPosition(farmingPed, true)
    SetEntityInvincible(farmingPed, true)
    SetBlockingOfNonTemporaryEvents(farmingPed, true)

    local blip = AddBlipForCoord(cfg.farmingCenter.coord.x, cfg.farmingCenter.coord.y, cfg.farmingCenter.coord.z)
    table.insert(scriptBlips, blip)

    SetBlipSprite(blip, 304)
    SetBlipDisplay(blip, 4)
    SetBlipScale(blip, 0.5)
    SetBlipColour(blip, 2)
    SetBlipAsShortRange(blip, true)

    BeginTextCommandSetBlipName("STRING")
    AddTextComponentString(T('blip.farmingCenter'))
    EndTextCommandSetBlipName(blip)

    target.addLocalEntity(farmingPed, {
        {
            name = 'farming_center_menu',
            icon = 'fa-solid fa-seedling',
            label = T('target.farmingCenter'),
            onSelect = function()
                openBuyFarmMenu()
            end,
            action = function()
                openBuyFarmMenu()
            end,
            distance = 2.0
        }
    })
end)

CreateThread(function()
    for k,v in pairs(market.locations) do
        local pedModel = GetHashKey(v.ped)
        RequestModel(pedModel)

        while not HasModelLoaded(pedModel) do
            Wait(1)
        end

        local farmingPed = CreatePed(4, pedModel, v.coord.x, v.coord.y, v.coord.z, v.coord.w, false, true)
        table.insert(scriptPeds, farmingPed)

        SetEntityHeading(farmingPed, v.coord.w)
        FreezeEntityPosition(farmingPed, true)
        SetEntityInvincible(farmingPed, true)
        SetBlockingOfNonTemporaryEvents(farmingPed, true)

        local blip = AddBlipForCoord(v.coord.x, v.coord.y, v.coord.z)
        table.insert(scriptBlips, blip)

        SetBlipSprite(blip, 59)
        SetBlipDisplay(blip, 4)
        SetBlipScale(blip, 0.5)
        SetBlipColour(blip, 2)
        SetBlipAsShortRange(blip, true)

        BeginTextCommandSetBlipName("STRING")
        AddTextComponentString(T('blip.farmingMarket'))
        EndTextCommandSetBlipName(blip)

        target.addLocalEntity(farmingPed, {
            {
                name = 'farming_market_menu',
                icon = 'fa-solid fa-seedling',
                label = T('target.farmingMarket'),
                distance = 2.0,
                onSelect = function()
                    openMarket()
                end,
                action = function()
                    openMarket()
                end
            }
        })
    end
end)

AddEventHandler('onResourceStop', function(resourceName)
    if GetCurrentResourceName() ~= resourceName then return end
    clearMugshot()

    if scriptPeds then
        for _, ped in pairs(scriptPeds) do
            if DoesEntityExist(ped) then
                DeletePed(ped)
            end
        end
        scriptPeds = {}
    end

    if scriptBlips then
        for _, blip in pairs(scriptBlips) do
            if DoesBlipExist(blip) then
                RemoveBlip(blip)
            end
        end
        scriptBlips = {}
    end
end)
```

{% endtab %}

{% tab title="core/main/server.lua" %}

```lua
function getPlayer(id)
    if core.framework.name == 'qb' then
        return fw.Functions.GetPlayer(tonumber(id)) 
    else
        return fw.GetPlayerFromId(tonumber(id))
    end
end

function getPlayerByCid(cid)
    if not cid then return nil end

    if core.framework.name == 'qb' then
        local p = fw.Functions.GetPlayerByCitizenId(cid)
        if p and p.PlayerData then
            return p.PlayerData.source
        end
        return nil
    else
        local p = fw.GetPlayerFromIdentifier(cid)
        if p then
            return p.source
        end
        return nil
    end
end

function getPlayerName(id)
    if not id then 
        id = source
    end
    
    if core.framework.name == 'qb' then
        local player = fw.Functions.GetPlayer(id)
        if player then
            return player.PlayerData.charinfo.firstname .. " " .. player.PlayerData.charinfo.lastname
        end
    else
        local player = fw.GetPlayerFromId(id)
        if player then
            return player.getName()
        end
    end
    return GetPlayerName(id) or "Bilinmiyor"
end

function getPlayerCid(id)
    local player = getPlayer(tonumber(id))
    
    if not player then 
        return nil 
    end


    if core.framework.name == 'qb' then
        if player.PlayerData then
            return player.PlayerData.citizenid
        end
    else
        return player.identifier
    end
end

function getItemCounts(player, item)
    if not player then return 0 end

    if GetResourceState('ox_inventory') == 'started' then
        local src = (player.PlayerData and player.PlayerData.source) or player.source
        if src then
            return exports.ox_inventory:GetItemCount(src, item) or 0
        end
    end

    if GetResourceState('one_inventory') == 'started' then
        local src = (player.PlayerData and player.PlayerData.source) or player.source
        if src then
            return exports.one_inventory:GetItemCount(src, item, nil) or 0
        end
    end

    if core.framework.name == 'qb' then
        local inventory = player.PlayerData.items or player.PlayerData.inventory
        if inventory then
            for _, v in pairs(inventory) do
                if v and v.name == item then
                    return v.amount or v.count or 0
                end
            end
        end
    else
        if player.getInventoryItem then
            local inventoryItem = player.getInventoryItem(item)
            if inventoryItem and inventoryItem.count then
                return inventoryItem.count
            end
        end
    end

    return 0
end

function addItem(src, item, count)
    if GetResourceState('ox_inventory') == 'started' then
        return exports.ox_inventory:AddItem(src, item, count)
    end

    if GetResourceState('one_inventory') == 'started' then
        return exports.one_inventory:AddItem(src, item, count)
    end

    local player = getPlayer(src)
    if not player then return false end

    if core.framework.name == 'qb' then
        return player.Functions.AddItem(item, count)
    else
        return player.addInventoryItem(item, count)
    end
end



function removeItem(src, item, count)
    if GetResourceState('ox_inventory') == 'started' then
        return exports.ox_inventory:RemoveItem(src, item, count)
    end

    if GetResourceState('one_inventory') == 'started' then
        return exports.one_inventory:RemoveItem(src, item, count)
    end

    local player = getPlayer(src)
    if not player then return false end

    if core.framework.name == 'qb' then
        if player.Functions.RemoveItem(item, count) then
            return true
        end
        return false
    else
        if player.removeInventoryItem(item, count) then
            return true
        end
        return false
    end
end

function getMoney(src, account)
    account = account or 'cash'
    local player = getPlayer(src)
    if not player then return 0 end

    if core.framework.name == 'qb' then
        return player.Functions.GetMoney(account) or 0
    else
        if account == 'bank' then
            local acc = player.getAccount and player.getAccount('bank')
            return (acc and acc.money) or 0
        else
            return player.getMoney() or 0
        end
    end
end

function addMoney(src, account, amount, reason)
    account = account or 'cash'
    local player = getPlayer(src)
    if not player then return false end

    if core.framework.name == 'qb' then
        player.Functions.AddMoney(account, amount, reason or 'savana-farming')
        return true
    else
        if account == 'bank' then
            player.addAccountMoney('bank', amount)
        else
            player.addMoney(amount)
        end
        return true
    end
end

function removeMoney(src, account, amount, reason)
    account = account or 'cash'
    local player = getPlayer(src)
    if not player then return false end

    if core.framework.name == 'qb' then
        if player.Functions.RemoveMoney(account, amount, reason or 'savana-farming') then
            return true
        end
        return false
    else
        if account == 'bank' then
            local acc = player.getAccount and player.getAccount('bank')
            if acc and acc.money >= amount then
                player.removeAccountMoney('bank', amount)
                return true
            end
            return false
        else
            if player.getMoney() >= amount then
                player.removeMoney(amount)
                return true
            end
            return false
        end
    end
end

function createUsableItem(itemName, cb)
    if core.framework.name == 'qb' then
        if GetResourceState('qbx_core') == 'started' then
            exports.qbx_core:CreateUseableItem(itemName, cb)
        end
        if fw and fw.Functions and fw.Functions.CreateUseableItem then
            fw.Functions.CreateUseableItem(itemName, cb)
        end
    else
        if fw and fw.RegisterUsableItem then
            fw.RegisterUsableItem(itemName, cb)
        end
    end
end

function getItemData(itemName)
    if GetResourceState('ox_inventory') == 'started' then
        local items = exports.ox_inventory:Items()
        if items and items[itemName] then return items[itemName] end
    end

    if core.framework.name == 'qb' and fw and fw.Shared and fw.Shared.Items then
        return fw.Shared.Items[itemName]
    end

    if core.framework.name == 'esx' and fw and fw.Items then
        return fw.Items[itemName]
    end

    return nil
end

function notifyClient(src, message, ntype)
    TriggerClientEvent('savana-farming:notify', src, message, ntype)
end


```

{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://savana.gitbook.io/savanascripts/scripts/farming-job/editable-files.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
