NPC Pro – talking, remembering street NPCs with trust, gossip and errands NPC PRO - talk to ANY ped. They remember, they gossip, they snitch. €29.99 See NPC PRO

Overview

About Touch Grass

A player stays on your server for an hour and a small sunset banner comes up with their gift, $250 and a water by default. The gift is paid on the spot, so there is nothing to claim. Every eight hours they go up a level, and a bigger synthwave banner plays across the top of the screen with the new rank.

Time is read on the server, from its own online timer. Each check only adds the new time, so a resource restart doesn't count anything twice. The client checks movement, camera and voice chat, and after 10 idle minutes by default (Config.afk.minutes) a player stops earning time until they move again. Playtime is saved per license by default, so all characters on one account share a level.

Levels and gifts

The default ladder goes up to level 8 at 64 hours. You can change the hours or add rows. Rank names like Newcomer, Regular and Icon are in the language files.

Milestone hours pay more, for example $5,000 in the bank at hour 8. One gift can mix money, items, a server event and a console command, so you can hand out a vehicle or VIP from another script. If the inventory is full, the gift waits and is tried again, even after a restart. The default items are water, burger, phone and lockpick, so rename them to items your inventory has.

Level gates

Your other resources can ask with one line if a player has the level for something, like level 3 for buying a weapon. The gates are only names and levels, so each resource decides for itself what to do with the answer.

Panel and admin

Players see their level, a live countdown, the next gift and the gates in a panel on /levels or PAGE UP. Admins use /levelsadmin, and its info, add, sethours, setlevel and reset also work on offline players. Level-ups, gifts and admin changes can be logged to a webhook.

Requirements

  • oxmysql
  • An FXServer build with the GetPlayerTimeOnline server native. Without it tracking does not start, and the console says why.
  • ESX, QBCore or QBox if you use one. Without a framework it runs standalone, and money gifts then need ncore_inventory.
  • An inventory for item gifts. ncore_inventory, ox_inventory and qb-inventory are detected, otherwise the framework's own item functions are used.

English and Hungarian are included.

Editions

Escrow and Full source have the same features. In Escrow the Lua code is protected by Cfx.re escrow, and the config files, the language files and server/bridge.lua (the framework and inventory calls) stay open to edit. In Full source every file is readable.

New versions are announced on intelnpc.com. When you update, your config and language files stay as they are.

The full feature list is in README.md, also on intelnpc.com.

Support is on intelnpc.com and I reply within 72 hours. Refunds are handled by Tebex under their terms.

Not approved, sponsored or endorsed by Rockstar Games.

What you get

Config open, core escrowed

  • Open for you to edit: config, locales and the framework bridge - tune it to your server.
  • No key from us, nothing calls home to us. The core is Cfx-escrowed and Cfx checks your server key when it starts.
  • Bought outright it is yours for good - the Cfx grant is permanent unless the payment is refunded or charged back.
  • Lifetime updates. Buy it once and every later version is yours.

Docs

Read it before you buy

The same docs that ship with the script, updated with every release.

Playtime levels, hourly gifts and level gates for FiveM, with a sunset-themed panel and webhook logs.

nCore Development · intelnpc.com · Resource: ncore_touchgrass · Version: see fxmanifest.lua

What it is#

Touch Grass rewards the players who stay. It counts how long each player has really been on the server, using the server's own online timer, and stops counting while they're AFK. Played hours become levels with named ranks, every hour pays out a gift, and other resources can lock things behind a level.

It runs on ESX, QBCore, QBox or standalone. It needs oxmysql and a server artifact with the GetPlayerTimeOnline native. Everything else is optional.

Features#

Playtime#

  • Time comes from the server's own online timer. The client only reports whether the player is AFK.
  • Each check only adds the new time, so a resource restart never counts time twice.
  • The last minutes are saved when a player leaves and when the resource stops. Players are also saved on a timer (ServerConfig.save_seconds, 300 by default).
  • Playtime is stored per license by default (ServerConfig.identifier), with other identifiers as backups. It belongs to the account, so on a multi-character server all characters share one level, and gifts go to the character that is loaded when the hour is reached.
  • A player with no usable identifier is not tracked, and the console warns.
  • If the server build has no online timer, tracking does not start and the console explains why.

AFK detection#

  • The client checks movement, turning, camera and voice chat every 5 seconds.
  • After the set idle time (Config.afk.minutes, 10 by default) the player stops earning time and gets a message. Time resumes as soon as they're active again.
  • Time earned before AFK was detected still counts.
  • The movement limits are in Config.afk.

Levels and ranks#

  • Default ladder: level 1 at 8 hours, then one level every 8 hours, up to level 8 at 64 hours.
  • Add or remove rows and change the hours in Config.levels. The max level follows the number of rows.
  • A row that doesn't need more hours than the one before it is refused in the console, and the ladder stops there.
  • Stored levels are corrected when a player joins.
  • Nine rank names ship in the locale files: Newcomer, Visitor, Local, Regular, Known Face, Resident, Veteran, Legend and Icon. Rename them in locales/*.lua. A level without a name shows as "Level N".

Gifts#

  • A gift after every played hour, plus bigger gifts on milestone hours. It is paid the moment the hour is reached, there is nothing to claim.
  • Defaults: $250 cash and a water every hour. Milestones at hour 1 (2 water, 2 burgers), hour 8 ($5,000 bank and a phone), hour 24 ($15,000 bank and 3 lockpicks), hour 40 ($25,000 bank) and hour 64 ($50,000 bank). Rename the items to match your server.
  • With ServerConfig.gifts.stack on, a milestone hour pays both gifts. With it off, the milestone gift replaces the hourly one.
  • ServerConfig.gifts.enabled = false turns all gifts off.
  • A gift entry takes money = { account = 'cash', amount = 250 } (cash or bank, plus black_money on ESX and crypto on QBCore and QBox), items = { { name = 'water', count = 1 } } with optional metadata, event = 'name' and command = '...'.
  • One gift can combine money, items, a server event and a console command. The event is triggered on the server with the player id, the hour and the identifier. The command gets {id}, {hour} and {identifier}, never the player name, so nobody can inject commands through their name. Use events and commands to give vehicles, VIP or XP from any other script.
  • Item names are checked first, so a typo gives a clear console error instead of endless retries.
  • A gift that can't be given yet, for example because the inventory is full or the character isn't loaded, is saved as waiting and tried again. This survives a reconnect and a server restart. The player is told it's waiting and told again when it arrives.
  • Gifts that can never work, like a misspelled item, are dropped, and the console names the problem.
  • When a player jumps many hours at once, only the last few hourly gifts are paid (24 by default, ServerConfig.gifts.max_catch_up), and the console says so. Only those hours fire the hour event.
  • Setting hours or level never pays the skipped hours, and removing time never takes gifts back.
  • Gift text is built from the locale files. Add gift_label_every or gift_label_<hour> to write your own text for an hour.

Level gates#

  • Three gates ship in Config.gates: buy_vehicle at level 1, buy_weapon at level 3 and own_business at level 5. Rename them or add your own.
  • The gates are names and levels. Your other resources ask with one line, on the server or on the client, and decide what to do with the answer. Nothing is enforced by this resource itself.
  • On the server you can ask silently (CanDo) or let the script tell the player why they were refused (RequireAction, RequireLevel). The client check is silent.
  • Gates show in the player's panel with lock and check icons.
  • An action without a gate is always allowed.
  • Other resources can add, replace or remove gates while the server runs, with a label in one or more languages. Gates added this way live in memory and are gone when ncore_touchgrass restarts.
  • Refusal messages name the level, for example "You need level 3 (Regular) for this."

Screens#

  • The level-up banner is a full-width synthwave sunset banner across the top, with palms, twinkling stars and GTA's rank-up sound. It shows the new level, the rank and the total time played, with a countdown bar. Banners queue so they never overlap, and only level-ups are announced. Config.ui.banner_seconds sets how long it stays.
  • The gift banner is a smaller banner with a sound when a gift arrives, next to the normal message. Config.ui.gift_banner = false keeps only the message.
  • The levels panel opens with /levels or PAGE UP. It shows the current level and rank, time played, a progress bar with a live Next level in countdown, the next hourly gift and the next milestone gift, the level ladder and the gates. It closes with ESC, the X or the Close button, and fits small screens. Opened while the player is AFK, it shows an AFK badge and the countdown stands still.
  • The panel doesn't open over the pause menu or another nCore panel. Opened from chat, it waits a moment for chat to close first.
  • The level-up and gift sounds can be any GTA menu sound. If a sound doesn't work, the console warns once and the banner plays silently.
  • Fonts ship inside the resource, so nothing loads from the internet.
  • Panel data requests are limited to one per second per player.

Admin commands#

  • /levelsadmin covers info, add, sethours, setlevel, reset, gift, levelup, event, gate and discord. The table below has the details.
  • info, add, sethours, setlevel and reset also work on offline players by identifier.
  • Access is the ACE ncore_touchgrass.admin. The server console can always use it. A player without access is told the exact line to add.
  • Replies go to chat with your own prefix and color (ServerConfig.admin_chat).
  • Preview tools: show the level-up banner, fire the level and hour events in preview mode, check a gate for a player, post a sample message to the webhook. Previews change nothing.

Webhook logging#

  • Level-ups, gifts (what arrived and what failed) and every admin change are posted as embeds. Admin changes name the staff member or the console.
  • Entries about a player show their name, server id and identifier. ServerConfig.discord.mention (on by default) also mentions the player's account when the server has that identifier for them.
  • Each log type can be turned on or off. The webhook name, avatar and colors are yours to set.
  • Keep the webhook out of the config with the ncore_touchgrass:webhook convar in server.cfg.
  • Messages are queued about one per second and retried up to 3 times when the webhook is rate limited. The webhook must be https.
  • Other resources can post their own embed through the same queue with SendDiscord.

Frameworks, inventories and other resources#

  • ESX, QBCore and QBox are detected automatically. Without one, it runs standalone. Detection runs again when a framework or inventory starts or stops.
  • Standalone: levels, gates, the panel and the banners work. Money gifts need ncore_inventory, and item gifts need an inventory resource.
  • ncore_inventory is preferred and also works on standalone servers. ox_inventory and qb-inventory are detected too, and without any of them items go through the framework's own item functions.
  • Messages go through ncore_hud when it runs, otherwise through your framework, ox_lib or the standard GTA feed.
  • Other resources can grant bonus minutes that count toward levels and gifts, remove minutes, or set playtime directly. ncore_npc_pro uses this to reward quests.
  • Other resources can show the sunset banner with their own text, full or compact and with or without sound.
  • Each player's level and AFK state, and the list of gates, are shared as state bags, so any script can read them without an export.
  • Keep the folder name ncore_touchgrass, because other nCore resources look it up by name.

Data#

  • The database table is created on start. sql/install.sql is optional.
  • On first start, if the new table is empty, it can import names and minutes once from another playtime table. Levels are recalculated and no past gifts are paid. The source table needs the columns identifier_kind, account_id, display_name, total_minutes, first_seen and last_seen. Set ServerConfig.migrate_from to false to skip it.
  • Gifts and the webhook live in config_server.lua, which only the server loads. Players never download it.

Languages and console#

  • English and Hungarian. All texts are in the locale files. Missing texts fall back to English, and a new language is one copied file.
  • Config.locale = 'auto' reads your server's locale setting (the convars lr:locale, locale, ox:locale, esx:locale and txAdmin-locale, in that order), and English when none of them has a language that ships.
  • The console prints a colored startup summary with the detected framework and inventory, every level change, and clear errors. Config.debug adds detail.
  • tools/fetch_refs.sh downloads GTA's sound name list so you can find valid sounds. The resource doesn't load it.

Commands and keys#

Command or key Who What it does
/levels Everyone Opens the playtime panel (name set by Config.ui.command)
PAGE UP Everyone Opens the panel (rebindable in the game's key settings, Config.ui.key, '' for no key)
ESC Everyone Closes the panel
/levelsadmin Admin / console Lists the subcommands
/levelsadmin info <id\|identifier> Admin / console Level, played time, online status, gift hour and waiting gifts
/levelsadmin add <id\|identifier> <minutes> [reason] Admin / console Adds minutes, negative removes. Logged to the webhook
/levelsadmin sethours <id\|identifier> <hours> Admin / console Sets played hours. Skipped hours pay no gifts. Logged to the webhook
/levelsadmin setlevel <id\|identifier> <0-max> Admin / console Jumps to the start of a level. Skipped hours pay no gifts. Logged to the webhook
/levelsadmin reset <id\|identifier> Admin / console Clears time, bonus, gift hour and waiting gifts. Logged to the webhook
/levelsadmin gift <id> <hour> Admin / console Gives that hour's gift now, for real (online only). Logged to the webhook
/levelsadmin levelup <id> [level] Admin / console Previews the level-up banner. Nothing changes
/levelsadmin event <id> levelup [level] Admin / console Fires the level event in preview mode and shows the banner
/levelsadmin event <id> hour [hour] Admin / console Fires the hour event in preview mode
/levelsadmin gate <id> <action> Admin / console Checks whether the player passes a gate. An unknown action lists the known gates
/levelsadmin discord Admin / console Posts a sample message to the webhook

For developers#

Server exports: GetLevel, GetPlaytime, GetPlayedHours, GetProgress, GetMaxLevel, GetLevelTitle, HasLevel, RequireLevel, CanDo, RequireAction, RegisterGate, RemoveGate, GetGates, GrantBonusMinutes, RemoveMinutes, SetPlaytime, ShowBanner, SendDiscord, IsAfk.

Client exports: GetLevel, HasLevel, CanDo, GetGates, IsAfk, OpenPanel, ClosePanel.

A few calls as examples:

Lua
-- server
local allowed, needed = exports.ncore_touchgrass:CanDo(source, 'buy_weapon')         -- silent
if not exports.ncore_touchgrass:RequireAction(source, 'buy_weapon') then return end  -- tells the player
exports.ncore_touchgrass:RegisterGate('rent_hangar', 4, { en = 'Rent a hangar' })
exports.ncore_touchgrass:GrantBonusMinutes(source, 30, 'quest')
exports.ncore_touchgrass:ShowBanner(source, { kicker = 'Race', title = 'First place', subtitle = 'Sandy Shores', variant = 'gift' })
exports.ncore_touchgrass:SendDiscord({ title = 'Race', description = 'Finished first', player = source })

-- client
local allowed, needed = exports.ncore_touchgrass:CanDo('buy_weapon')

CanDo returns true and nil for an action without a gate. ShowBanner with variant = 'gift' shows the smaller banner, and sound = false plays it silent. SetPlaytime(src, seconds, give_gifts) pays the skipped hours only when give_gifts is true.

Event Side When
ncore_touchgrass:levelChanged(src, new, old, preview) Server and client A level goes up or down
ncore_touchgrass:hourReached(src, hour, preview) Server and client A played hour is reached
ncore_touchgrass:giftDelivered(src, hour, delivered, failed, preview) Server A gift was handled

preview is true only when fired by the admin preview or gift commands. Clients can't fire the server events. State bags: Player(src).state.lrLevel, Player(src).state.lrAfk, GlobalState.lrLevelGates.

Configuration#

  • config.lua: language, debug, level ladder, level gates, AFK rules, panel command and key, banner time, gift banner and sounds.
  • config_server.lua: framework, identifier, tick and save timing, import table, gifts, admin command and chat style, webhook and logs.
  • locales/en.lua, locales/hu.lua: all texts, including rank names, gate names, gift text, messages, admin replies and log text.

Settings you'll change first:

  • Config.levels for the hours each level needs.
  • Config.gates for which action needs which level.
  • ServerConfig.gifts.every_hour and ServerConfig.gifts.hours for the gifts.
  • ServerConfig.gifts.stack to pay milestone and hourly gifts together or not.
  • Config.afk.minutes for the idle time before AFK.
  • ServerConfig.discord.webhook, or the ncore_touchgrass:webhook convar.
  • ServerConfig.admin_ace for the admin permission.

Other settings:

  • Config.afk.enabled = false turns AFK detection off, so all online time counts.
  • ServerConfig.framework is 'auto'. Set 'esx', 'qb' or 'qbox' to pick one when more than one is running.
  • ServerConfig.tick_seconds (30, at least 10) is how often time is added and waiting gifts are tried again.
  • ServerConfig.identifier is the identifier kind playtime is saved under. If a player has none of that kind, license, license2, fivem, discord and steam are tried in that order.
  • ServerConfig.admin_command and Config.ui.command rename /levelsadmin and /levels.

Troubleshooting#

What you see What to do
The console says there is no GetPlayerTimeOnline native Update your FXServer artifact. Nothing is tracked until it has the native.
Admin commands reply "not ready" The console names the cause, usually the missing native above or a database error while the table was prepared.
A gift item never arrives The console names the item. An item your inventory doesn't know is dropped, so rename the default items (water, burger, phone, lockpick) in config_server.lua.
Money gifts fail on a standalone server Without a framework only cash can be given, and only through ncore_inventory. Use an event or command gift for anything else.
"You are missing the ace" Add add_ace group.admin ncore_touchgrass.admin allow to server.cfg. The reply prints the same line.
Nothing reaches the webhook Run /levelsadmin discord and watch the console. The URL must start with https://, and the console prints the HTTP answer when a post fails.
The panel doesn't open It stays closed over the pause menu and while another nCore panel has focus. From chat it waits up to 1.5 seconds for chat to close.
A crash lost some minutes The timed save runs every ServerConfig.save_seconds (300 by default), so a crash can lose the time since the last one. A normal resource stop saves everything.

Requirements#

  • oxmysql.
  • An FXServer build that has the GetPlayerTimeOnline server native.

Optional, detected automatically:

  • ESX, QBCore or QBox. Without one it runs standalone.
  • ncore_inventory, ox_inventory or qb-inventory. Without one, items go through the framework's own item functions.
  • ncore_hud for messages, with ox_lib as a fallback.
  • ncore_npc_pro for quest bonus time.
  • Any chat resource that uses the standard chat events, such as ncore_chat.
  • A webhook URL for logging.

Setup steps are in INSTALLATION.md.

Support#

Support is on intelnpc.com and I reply within 72 hours. It covers installing, configuring and bugs in the script as shipped. Payments and refunds are handled by Tebex under their terms.

The escrow edition is protected with Cfx.re Asset Escrow. config.lua, config_server.lua, server/bridge.lua (the framework and inventory calls) and the locale files stay editable. The full source edition has every file open.


nCore Touch Grass is made by nCore Development. It is not approved, sponsored or endorsed by Rockstar Games.

€9.99

Ready when you are

Instant delivery, checkout right here on the site, and a Discord full of people who will answer before you pay.

Ask on Discord first

Touch Grass

€9.99

Latest script updates

Every new version on the day it ships. Updates are free for owners.

Full changelog →