Configuration

6 min readUpdated Today

Overview

Configuration is split across multiple files:

  • shared/config.lua: General settings, growth mechanics, rendering, ground materials
  • shared/zones.lua: Growth zones with multipliers and blips
  • server/config_server.lua: Discord webhooks

Plant types, categories, and items are managed through the admin panel and stored in the database.

General

shared/config.lua
1Config.Language = 'en'
2Config.Debug = false
3Config.Theme = 'default'
4Config.MinimizeKey = 'F9'
5Config.GlobalGrowTime = 30
6Config.SeedDefaultPlants = true
7Config.PlayerPlantLimit = 10
8Config.PlantDistance = 1.5
9Config.DefaultSharedInteraction = true
  • GlobalGrowTime: Base growth time in minutes
  • PlayerPlantLimit: Max plants a single player can have active
  • PlantDistance: Minimum distance between plants
  • DefaultSharedInteraction: When a plant type or category does not set its own rule: true lets any nearby player water and harvest, false limits it to the owner and admins.
  • SeedDefaultPlants: On the very first start, fills the panel with two ready-made plant types so it is not empty. Once any plant type exists they are never re-created; false starts empty
  • MinimizeKey: Key that minimises and restores the admin panel

Per-Plant Limits

Override the global limit for specific plant types:

shared/config.lua
1Config.PlantLimitOverrides = {
2    ['weed_seed'] = 4,
3    ['coca_seed'] = 10,
4}

Growth Mechanics

shared/config.lua
1Config.HealthBaseDecay = { 7, 10 }
2Config.WaterDecay = 1.0
3Config.FertilizerDecay = 0.7
4Config.WaterThreshold = 10
5Config.FireTime = 5000
6Config.DeadPlantTimeout = 10
  • HealthBaseDecay: Health lost per minute while water sits at or below WaterThreshold (random between the two values)
  • WaterDecay: Water lost per minute. Real elapsed time is used, so plants keep drying while the server is down
  • FertilizerDecay: Fertilizer lost per minute. Only the part above 50 speeds growth up
  • WaterThreshold: Water level at or below which the plant starts losing health. At 0 the damage doubles and growth stops
  • FireTime: Duration of fire effect when a plant is destroyed by burning
  • DeadPlantTimeout: Minutes before dead plants auto-destroy (0 = instant)

Ground Restrictions

Control which ground surfaces plants can be placed on.

shared/config.lua
1Config.OnlyAllowedGrounds = false
2Config.AllowedGrounds = {
3    1333033863,   -- Grass
4    -1885547121,  -- Dirt Track
5    -700658213,   -- Soil
6    -- default list covers grass, sand, dirt, gravel, mud, clay, leaves, marsh
7}
  • OnlyAllowedGrounds = false: Plants can go anywhere
  • OnlyAllowedGrounds = true: Only surfaces listed in AllowedGrounds are valid

Available ground materials are documented in Config.GroundMaterials.

Plant types can also carry their own allowed-surface list (set per type or per category in the admin panel), which overrides the global setting.

Rendering

Plants use a chunk-based rendering system for performance.

shared/config.lua
1Config.ChunkSize = 100.0
2Config.StreamRadius = 150.0
3Config.StreamOutRadius = 200.0
4Config.MaxPropsPerFrame = 3
5Config.PlantInteractionRadius = 1.0
6Config.RayCastDistance = 7.0
  • ChunkSize: Size of each spatial chunk for prop loading
  • StreamRadius: Distance within which plants are loaded around each player
  • StreamOutRadius: Distance beyond which loaded props are despawned (kept larger than StreamRadius so plants do not repeatedly load and unload at the edge)
  • MaxPropsPerFrame: Max plant props spawned per frame while streaming in
  • PlantInteractionRadius: Sphere zone radius around each plant for interaction
  • RayCastDistance: How far ahead of the camera the placement ray looks for a spot to plant on

Growth Zones

Define areas where plants grow faster and yield more. Seed zones in shared/zones.lua or draw them in-game from the admin panel. Zones from shared/zones.lua are synced into the database on every start and overwrite entries with the same id; zones created from the panel are preserved.

shared/zones.lua
1Config.Zones = {
2    ['weed_zone_one'] = {
3        points = {
4            vec3(2031.0, 4853.0, 43.0),
5            vec3(2007.0, 4877.0, 43.0),
6            -- ...
7        },
8        thickness = 4.0,
9        growMultiplier = 2.0,
10        yieldMultiplier = 1.0,
11        allowlist = {},
12        blocklist = {},
13        plantLimitOverride = nil,
14        blip = {
15            display = true,
16            sprite = 469,
17            color = 2,
18            text = 'Cannabis Zone',
19        },
20    },
21}
  • growMultiplier: Multiplies the growth speed inside this zone (2.0 = twice as fast)
  • yieldMultiplier: Multiplies harvested item counts for plants inside the zone
  • allowlist / blocklist - Restrict which seeds may be planted in the zone
  • plantLimitOverride: Max total plants allowed inside the zone
  • blip: Optional map blip. Set display = false to hide it.

Skill Progression

Skill requirements and XP rewards are optional and read from ml_skills. The config holds the global switches; every plant type then sets its own.

shared/config.lua
1Config.ExternalSkills = {
2    Enabled = true,
3    Resource = 'ml_skills',
4    XpMultiplier = 1.0,
5    MaxXpPerHarvest = 500,
6}
  • Enabled: false ignores every requirement and grants no XP, whatever the plant types define
  • Resource: Name of the progression resource that provides the skill trees
  • XpMultiplier: Global multiplier applied to every XP award
  • MaxXpPerHarvest: Ceiling applied after the multipliers. 0 removes the ceiling

Requirements and rewards live in the plant editor, under Skill Integration. Four actions are configured independently, each on its own tab:

  • Plant: Checked when the seed item is used, before placement mode opens
  • Water: Checked before the watering animation starts
  • Fertilize: Checked before the fertilizing animation starts
  • Harvest: Checked before the harvest animation starts

Each tab holds the same two groups:

  • Requirement: A skill the player must have unlocked, and a minimum level in that skill's category. Leave both empty to require nothing
  • XP Reward: The skill that receives the XP (its category is bound automatically) or a plain category, plus the amount. Leave the amount at 0 to grant nothing

Harvest XP scales with the plant health and the zone yield multiplier. The other three actions grant their flat amount.

Progression is optional

With the progression resource stopped, or Enabled = false, every requirement passes and no XP is granted. Plants never become unplantable because progression is down.

Set it once per category

Categories carry the same Skill Integration block. A plant type inherits its category unless the OVERRIDE toggle on that section is on.

Admin Panel

shared/config.lua
1Config.AdminCommand = 'plantadmin'

The admin panel allows creating and editing plant types, categories, seed items, and growth configurations - all stored in the database.

Access requires admin permission from your framework, resolved through ml_bridge (the admin/god group on QBCore, Qbox and ESX, or ACE admin on standalone).

Logging

Every webhook event can be toggled individually:

shared/config.lua
1Config.Log = {
2    Plant        = true,  -- Player planted a seed
3    Water        = true,  -- Player watered a plant
4    Fertilize    = true,  -- Player fertilized a plant
5    Harvest      = true,  -- Player harvested a plant (logs full reward list)
6    Destroy      = true,  -- Player destroyed their own plant
7    AdminDestroy = true,  -- Admin destroyed another player's plant
8    Death        = true,  -- Plant died from decay (water=0 / health=0)
9    AdminPanel   = true,  -- Admin opened the panel
10    AdminConfig  = true,  -- Admin saved/deleted a plant type, category or zone
11}

Discord Webhooks

server/config_server.lua
1ServerConfig.DiscordWebhook = {
2    Default      = '',
3    Plant        = '',
4    Water        = '',
5    Fertilize    = '',
6    Harvest      = '',
7    Destroy      = '',
8    Death        = '',
9    AdminDestroy = '',
10    AdminPanel   = '',
11    AdminConfig  = '',
12    AntiExploit  = '',
13}
  • Each key is one action, matching the toggles in Config.Log. That action is logged to its own channel.
  • Default is the fallback channel: any action whose own webhook is empty is sent there instead.
  • Leave an action and Default both empty to skip that log.