FiveM Docs
Seasonal

esx_christmas

esx_christmas is the official ESX Legacy Christmas present hunt with timed spawns, tiered cash and item rewards, claim limits and built-in anti-abuse checks.

esx_christmas is a seasonal ESX Legacy resource that spawns a landmark and a few presents at a configured location on a timer. Players walk up to a present, press E and receive cash and items depending on how early they opened it. It lives in the separate ESX-Legacy-Seasonal repository, not in [esx_addons].

Overview

Resourceesx_christmas (version 1.0.0)
Repositoryesx-framework/ESX-Legacy-Seasonal, folder [esx_seasonal]
SideServer state, client props and prompts
Dependencieses_extended in fxmanifest.lua; the shared scripts also load @ox_lib/init.lua; the prompt needs esx_textui
DatabaseNone; event state lives in memory and resets on restart
Localesen only (locales/en.lua)

The manifest only lists es_extended under dependencies, but it loads @ox_lib/init.lua as a shared script. Start ox_lib before this resource, see ox_lib.

Installation

Copy esx_christmas into your resources folder and start it after its dependencies:

server.cfg
ensure ox_lib
ensure es_extended
ensure esx_textui
ensure esx_christmas

The resource streams its own props (stream/*, with this_is_a_map 'yes' and a .ytyp file), so no extra map resource is needed.

How it works

  1. A server thread calls StartCycle immediately on start and then every Config.EventInterval seconds.
  2. A cycle first clears the previous locations (if DespawnLocationOnCycleEnd is on), then picks Config.MaxLocationsPerCycle entries from Config.Locations, randomly when UseRandomLocation is on, and broadcasts them to all clients.
  3. Each client spawns the landmark, an optional hint prop and one present prop per PresentCoords entry as local, non-networked objects. A present shows the text UI "Press E to open the present" within 2.0 units.
  4. Pressing E sends esx_christmas:server:claim. The server validates the claim, picks the reward tier from the claim order at that location and pays the player.
  5. All clients get the claim notification, the present disappears and, when every present at a location is taken, the whole location is removed.

Configuration

All keys are in config/main.lua.

KeyDefaultDescription
Config.EnabledtrueMaster switch; when false, cycles do nothing
Config.DebugtruePrints [ESX_Christmas] debug lines on server and client
Config.EventInterval600Seconds between cycles; 0 or lower disables the cycle thread
Config.MaxLocationsPerCycle1Locations activated per cycle
Config.UseRandomLocationtruePick locations randomly instead of in list order
Config.GlobalMaxClaims20Claim cap across all locations until counters reset; nil or 0 disables it
Config.PerPlayerMaxClaimsPerCycle3Claim cap per player (by ESX identifier); nil or 0 disables it
Config.UseTierScalingtrueUse Config.Tiers by claim order; when false everyone gets the default tier
Config.DefaultTierName"Common"Tier used when no tier matches the claim order
Config.DespawnPresentOnClaimtrueRemove a present for all players when it is opened
Config.DespawnLocationWhenAllClaimedtrueRemove the location once all its presents are taken
Config.DespawnLocationOnCycleEndtrueClear locations and reset claim counters when a new cycle starts
Config.UseHintstrueSpawn a hint prop next to the landmark
Config.Account"bank"Account for cash rewards; nil pays cash in hand via addMoney
Config.MinClaimInterval2Minimum seconds between claims (and sync requests) per player; 0 disables the check
Config.MaxViolations5Violations before the kick
Config.KickOnMaxViolationstrueDrop the player at MaxViolations
Config.MaxClaimDistance5.0Max distance in units between player and present on the server; 0 disables the check
Config.LocaleGetConvar("esx:locale", "en")Locale for notifications

Locations

config/main.lua
Config.Locations = {
  {
    Name = "Legion Square",
    LandmarkCoords = vec3(203.525284, -941.169250, 29.55),
    LandmarkModel = "sp_medium_christmas_santa",
    PresentCoords = {
      vec3(199.437363, -935.485718, 29.678345),
      vec3(199.318680, -953.432983, 29.088623),
      vec3(175.002197, -950.268127, 29.088623),
    },
    HintModel = "sp_christmas_snowman"
  }
}
FieldTypeDescription
NamestringLabel used in debug output
LandmarkCoordsvector3Where the landmark prop spawns
LandmarkModelstring?Fixed landmark model; when empty a random one from Config.Props.LandmarkModels is used
PresentCoordsvector3[]One present per entry; this count is the number of claims at the location
HintModelstring?Hint prop, spawned 2 units to the side of the landmark when UseHints is on

A hint model only shows its floating text when it has an entry in Config.Hints, which maps the model name to a locale key (xmas_hint_snowman, xmas_hint_deer ship by default).

Props

Config.Props lists the model names the resource may use: LandmarkModels, PresentModels (picked randomly per present), HintModels and ExtraDecorModels. The shipped names (sp_*, prop_xmas_*) come from the files in stream/. In the current code only LandmarkModels (server, random landmark) and PresentModels (client, random present) are read. HintModels and ExtraDecorModels are not used anywhere, so a hint prop comes from HintModel in the location. Custom models you add must be streamed by this or another resource.

Tiers and rewards

config/main.lua
Config.Tiers = {
  {
    Name = "Legendary",
    ClaimOrder = { 1 },
    Rewards = {
      { Type = "cash", Amount = 10000 },
      { Type = "item", Name = "armor",            Amount = 1 },
      { Type = "item", Name = "christmas_ticket", Amount = 1 }
    }
  },
  -- Epic: ClaimOrder = { 2 }, Common: ClaimOrder = { 3 }
}

The first present opened at a location pays the Legendary tier, the second Epic, the third Common. ClaimOrder lists the claim numbers a tier applies to, so { 3, 4, 5 } stretches a tier. Rewards use xPlayer.addAccountMoney(Config.Account, amount) for cash and xPlayer.addInventoryItem(name, amount) for item, see xPlayer.

Events

Client to server (both are validated on the server):

EventArgumentsPurpose
esx_christmas:server:claimlocationId, presentIndexOpen a present
esx_christmas:server:requestSyncnoneAsk for the active locations; sent once after the player loads

Server to client: setLocations, removeLocation, clearLocations, despawnPresent, onClaim, presentAlreadyClaimed, cannotClaim and notify, all prefixed with esx_christmas:client:. They only drive props and notifications.

Common issues

  • Rewards do nothing or throw errors. The default item names are not defined in the official legacy.sql or addons. Add rows to the items table or change Config.Tiers, see Add items.
  • Debug spam in the console. Config.Debug is true by default. Set it to false for production.
  • Claim limits never reset. The global and per-player counters are only reset when a cycle clears the locations. With DespawnLocationOnCycleEnd = false they keep growing until a restart.
  • No "Press E" prompt. The prompt uses ESX.TextUI, which only works while esx_textui is running. Without it the present can still be opened with E, but nothing is shown.
  • Only English text. Only locales/en.lua ships. Add a file in locales/ for other languages.

Frequently asked questions

Independent documentation

esx-fivem.com is a community project and is not affiliated with the ESX Framework team. Facts on this page were checked against the upstream source. Official resources: docs.esx-framework.org and github.com/esx-framework.

Last updated on

On this page