🗒️TMC 2.1

The release of TMC 2.1 on the 20th June 2025. Includes major overhauls of internal features to improve performance, usability and add some key features that have been missing.

Base

PlayerData Replication

  • Reworked how PlayerData is saved to player state bags.

    • Reduced state bag sync frequency to avoid potential issues with high player counts.

    • Only essential or infrequently updated values are now replicated.

    • Configurable via:

      core/config.server.lua > Config.Server.PlayerDataToSaveToStateBags
    • No changes are required for our internal scripts. However, if your external scripts rely on remote state bag access, you may need to adjust accordingly or enable replication for those values manually.

    • All original PlayerData remains accessible on the local client side.


💵 Cash Denominations System

See thread - https://discord.com/channels/1072182006584184843/1346952944251174962 Enabled via: (this is the new default behaviour for using cash as items)

TMCConfig.Money.UseCashAsItem = true

Configuration

  • Moved config:

    core/config.gta5.lua > Config.Money.UseCashAsItem
    now in
    core/config.lua > TMCConfig.Money.UseCashAsItem
  • Toggle debugging:

    /toggledenomdebugging [playerId] [0|1]
    • Enables server-side denomination logic debugging.

    • Must be run from the server console.

  • Denomination value setup:

    core/config.lua > TMCConfig.Money.CashDenominations
    • Default: US coin denominations.

    • UK denominations included as commented examples.

    • You can expand this to include bills/notes.

    • cash always equals the base unit (e.g. $1, £1).

  • Item configuration:

    core/shared.gta5.lua > denomConfig
    • Matches the items to the defined denominations.

    • UK denominations included as commented examples.

  • Banking has been updated to accept fraction values in input dialogs. Enabled by default

    • Can be toggled in Config.AllowFractions


Coin Exchange System

  • Added coin exchange and purchase prompt at all bank location

  • Players can now:

    • Pay a fee (Config.CoinExchangeFee) to convert all cash on hand into the largest denomination combination possible.

    • Pay a separate fee (Config.ChangePurchaseFee) to purchase coin denominations (change).

  • This feature is enabled by default but can be toggled via:

  Config.CoinExchangeEnabled

Wallet System

  • New item: wallet

    • Only accepts denomination items as defined in the config.

    • Incoming cash goes into the wallet if the item exists.

    • If no wallet is present, cash is received in the standard inventory.


🧾 Command Updates

  • /cash

    • Displays total cash with decimal precision.

  • /cashb new

    • Shows breakdown of denominations across inventory and wallet.

  • /givecash

    • Requires exact denomination match to complete transaction.

    • Example:

Player A has $1.23 (1x $1, 1x $0.20, 3x $0.01) Player A cannot give $1.13 unless they have the exact change.


⚙️ Inventory & Item Performance Optimizations

We're making an effort to improve on stability of processing large number of items, especially with stackable items.

  • Player weight calculation reworked for improved performance during player objection transactions.

  • Shop purchase/sell logic optimized for handling stackable item transactions.

  • Improved AddItem logic for inbound stackable items.

  • Inventory syncs to the client are now throttled and batched. This reduces network load, especially during high volumes of add/remove item transactions.


Dead Player Tracking

  • Added:

    TMC.Player.GetDeadCharacters
    • Returns a table of dead characters currently online:

      {
        [1] = "ABCDE123", -- serverId = CSN
        [5] = "FGHIJ123",
      }
  • You can reference it with:

    if TMC.Player.DeadCharacters[source] then
      -- do something
    end
  • No longer necessary to manually loop through TMC.Players and check metadata.


Garages - Misc

Added stored procedure check in order to display warning when an invalid SQL setup is detected.


Item Display

  • Added a new client event for showing bulk item boxes.

    • Example usage:

    local itemArray = {
        { name = "apple", amount = 2, info = { _label = "Some New Label" } },
        { name = "water_bottle", amount = 3 }
    }

    TriggerClientEvent("inventory:client:itemBoxBulk", source, itemArray, "add" or "remove")

Bundled Items

  • Added support for the bundled_item item type.

    • When used, it gives the player multiple items specified in its metadata.

    • Example usage:

    local player = TMC.Functions.GetPlayer(source)
    player.Functions.AddItem("bundled_item", 1, nil, {
        _label = "Packed Lunch",
        items = {
            { name = "apple", amount = 2 },
            { name = "water_bottle", amount = 1 }
        }
    })
  • Can also be sold in shops using standard buy config with metadata for included items.


Shop System Enhancements

  • Added new fields for 'sell' shop configuration:

    • requireMetadata

    • requireRep

    • sellAmount

    • Example:

    {
        name = 'log',
        price = 1,
        sellAmount = 5,
        info = { _label = "5x Douglas Log" },
        requireMetadata = { species = "p_tree_douglasfir_snow_05" },
        requireRep = { name = "lumberjack", amount = 10 }
    }
  • These options allow conditional sales based on metadata, reputation, and required quantity.


Shop Access Conditions

  • Added support for condition functions to restrict shop access globally or per location.

    • Example configuration:

['pawnshop'] = {
    label = 'Pawn Shop',
    blipInfo = {
        type = 272,
        color = 4
    },
    type = 'sell',
    condition = function()
        if TMC.Functions.HasJob("pawnshop") then
            return true
        end
        return false
    end,
    locations = {
        { -- Southside
            center = vector3(182.6522, -1319.378, 29.323),
            length = 2.0,
            width = 1.6,
            options = {
                heading = 333,
                minZ = 28.0,
                maxZ = 31.0
            },
            condition = function()
                if TMC.Functions.HasItem("pawn_shop_key_southside") then
                    return true
                end
                return false
            end
        },
    }
}
  • These conditions are optional but allow greater control over who can access shops.


Item Tagging

  • Introduced logic for item_tag items.

    • Used to apply _label metadata to items.

    • Displays in inventory as a uniquely named item.

    • Not applicable to weapons or currency items.

    • Usage is logged under the itemtag category.


Carriable Item Metadata Requirements

  • Config.CarriableConfig now supports MetadataRequired.

    • Example:

    ['sand_sack'] = {
        ObjectModel = `p_sandbags03x`,
        MetadataRequired = { full = true }
    }

Item Exchanges

  • Added Config.ItemExchanges for trade-based interactions.

    • Example: 20x water bottles for 2x apples.

    • Supports reputation requirements and per-character limits.

    • Character limits reset on script/server restart.


Internal Events

  • Added internal server-side events:

  AddEventHandler("inventory:server:itemAdded", function(stashId, itemName, slot, itemInfo, amount, originSource) end)
  AddEventHandler("inventory:server:itemRemoved", function(stashId, itemName, slot, slotIndex, amount, originSource) end)

Stash Restrictions

  • New system to apply whitelist/blacklist restrictions on stashes.

  • Also allows setting a maximum item amount per slot.

  • Example usage:

  exports.inventory:SetStashItemRestriction("food_stash", "whitelist", { "bread", "water" }, 10)
  exports.inventory:SetStashItemRestriction("safe_stash", "blacklist", { "gun", "ammo" })
  • New exports:

    • GetStashItemRestriction(stashId)

    • ClearStashItemRestriction(stashId)

    • Example:

    local restriction = GetStashItemRestriction("food_stash")
    if restriction then
        print("Type:", restriction.type)
        print("Items:", table.concat(restriction.items, ", "))
        if restriction.maxAmount then
            print("Max:", restriction.maxAmount)
        end
    end

    ClearStashItemRestriction("food_stash")

Player Shops & Market Stalls

  • Updated player shops to support multiple stackable items per stock slot.

  • Menus now support decimal value prices for items.

  • Added feedback when updating market stalls to improve user clarity.

  • Additional general improvements made to stock management logic


Misc

  • Added TMC.Functions.StopNotify for server-side use.

    • Works similarly to SimpleNotify.

    • Usage:

      TMC.Functions.StopNotify(source, "perist_notify_id")
  • Improved the logic within the core playerDropped function.

  • TMC.Common.FormatCashString new

    • Formats a number to a readable string with 2 decimal places.

  • TMC.Common.RoundToPennynew

    • Rounds a number to 2 decimal places.


Gangs

Gang Member Management

  • Added two new exports for better gang management:

    • GetOnlineGangMembers

    • IsPlayerInGang

  • Refer to the README.md for usage examples and documentation.

  • Removed unused debug print statements.


Territories

Actioned Influence Enhancements

  • Added radius-based influence gain for actioned influence.

    • Example provided in:

      serverConfig.lua > ActionedInfluenceConfig > example_radius_action
    • Influence gain is scaled down the further it gets from the center hexagon. The scaling is configurable

  • Each action in ActionedInfluenceConfig now supports an enabled toggle.

    • Ensure you update your config:

      serverConfig.lua > ActionedInfluenceConfig

Influence System Improvements

  • Added influence gain through player presence in zones.

    • Configurable via:

      serverConfig.lua > ActionedInfluenceConfig > player_in_zone
    • Note: For balance reasons, players will only gain influence through presence in zones that already exist

      • To create a new zone, one of the other influence actions must be performed first

      • Once a zone is created, players can then begin earning influence in it simply by being at that location

  • Refactored passive influence loss to streamline performance.

  • Improved ModifyZoneInfluence to prevent repeated save/sync calls on failed attempts.

  • Added logs for zone contest and claim timeouts.


General Updates

  • Improved debug output for overdue upkeep and zone discovery.

  • Updated permission sync for staff view access to reduce network load.

  • Removed unnecessary debug prints.


Changed Files

Base

banking/
|-  client.lua
|-  config.lua
|-  server.lua
|-  html/
|-  |-  REPLACE EVERYTHING
core/
|-  config.gta5.lua
|-  config.lua
|-  config.server.lua
|-  shared.gta5.lua
|-  client/
|-  |-  events.lua
|-  common/
|-  |-  functions.lua
|-  server/
|-  |-  events.lua
|-  |-  functions.lua
|-  |-  main.lua
|-  |-  player.lua
core_game/
|-  server/
|-  |-  server.lua
inventory/
|-  client.lua
|-  config.lua
|-  inventories.lua
|-  server.lua
garages/
|-  proc.sql
|-  server/
|-  |-  main.lua
tmc_queue/
|-  server.js

Addon

gangs/
|- server.lua
|- README.md
playershops/
|-  client.lua
|-  server.lua
|-  marketstalls/
|-  |-  server.lua
territories/
|- serverConfig.lua
|- server.lua
|- utils.lua

Last updated