import { GlobalConfig } from "payload"; import { requirePermission } from "@/utils/access-control/hasPermission"; export const GameRules: GlobalConfig = { slug: "game-rules", access: { read: requirePermission("game-rules:read"), update: requirePermission("game-rules:update"), }, fields: [ { name: "mainCurrency", type: "relationship", relationTo: "resources", required: true, admin: { description: 'The base currency ("gold standard") used by all factions to pay for goods and services.', }, }, { label: "Universal Currency", type: "collapsible", admin: { initCollapsed: true, description: "Display names used throughout the app. These do not change the accounting resource selected above.", }, fields: [ { name: "currencyName", type: "text", admin: { description: 'General display name for the currency, e.g. "credit". Used when singular or plural names are not set.', }, }, { name: "currencySymbol", type: "text", admin: { description: 'Optional symbol prefixed to amounts, e.g. "¢" or "$".', }, }, { name: "currencySingular", type: "text", admin: { description: 'Singular amount label, e.g. "credit".', }, }, { name: "currencyPlural", type: "text", admin: { description: 'Plural amount label, e.g. "credits".', }, }, { name: "currencyDenomination", type: "text", admin: { description: 'Optional subunit name for future fractional displays, e.g. "cent". This does not affect stored values.', }, }, ], }, { name: "commandAssignments", type: "relationship", relationTo: "assignments", hasMany: true, admin: { description: "Assignment(s) considered unit command. Members and leaders of these assignments get elevated access to draft missions and other restricted content.", }, }, { name: "intelAssignments", type: "relationship", relationTo: "assignments", hasMany: true, admin: { description: "Assignment(s) considered the intelligence division. Members and leaders of these assignments get elevated access to draft missions and intelligence content.", }, }, { name: "proximityThreshold", type: "number", defaultValue: 1000, admin: { description: "Distance threshold in real meters for instant transfers. Structures within this distance can transfer resources instantly. Beyond this, shipments are required.", }, }, { name: "gameTickIntervalMinutes", type: "number", defaultValue: 10, admin: { description: "How often the game tick runs, in minutes. This processes shipment movement, fuel consumption, and arrivals.", }, }, { name: "lockerGridWidth", type: "number", defaultValue: 10, min: 4, admin: { description: "Width of each member's personal locker grid, in cells. Applies to newly provisioned lockers.", }, }, { name: "lockerGridHeight", type: "number", defaultValue: 6, min: 4, admin: { description: "Height of each member's personal locker grid, in cells. Applies to newly provisioned lockers.", }, }, { name: "staffHiringEnabled", type: "checkbox", defaultValue: false, admin: { description: "When off, logistics officers cannot hire staff anywhere (both labor crews and named NPC staff).", }, }, { name: "staffHiringDisabledMessage", type: "text", admin: { description: "Message shown to logistics officers when hiring is disabled, e.g. explaining the in-universe reason.", }, }, { name: "economy", type: "group", label: "Market Economy", admin: { description: "Global knobs for the supply-and-demand market simulation run by the economy tick (docs/economy/supply-demand-design.md).", }, fields: [ { name: "enabled", type: "checkbox", defaultValue: false, admin: { description: "Master gate for the market economy simulation. When off, the economy tick leaves all prices at their resting values.", }, }, { name: "defaultPriceBand", type: "number", min: 0, max: 1, defaultValue: 0.5, admin: { description: "Default price band as a fraction of base price (e.g. 0.5 = price can move ±50%). Used when an item does not set its own band.", }, }, { name: "realDemandWindowTicks", type: "number", min: 1, defaultValue: 24, admin: { description: "How many economy ticks of completed-purchase history feed the real-demand signal.", }, }, { name: "realDemandDecay", type: "number", min: 0, max: 1, defaultValue: 0.5, admin: { description: "Fraction of accumulated real demand that survives each tick (0.5 halves it every tick).", }, }, { name: "artificialDemandDrift", type: "number", min: 0, max: 1, defaultValue: 0.05, admin: { description: "How far the NPC (artificial) demand random walk may move per tick, as a fraction of the GM baseline.", }, }, { name: "coldStartObservations", type: "number", min: 0, defaultValue: 5, admin: { description: "Completed purchases needed before an item's price starts moving. Until then items stay at their resting price (modifier 1).", }, }, { name: "tickIntervalHintMinutes", type: "number", min: 1, defaultValue: 60, admin: { description: "Suggested economy tick cadence in minutes, for cron documentation only. The tick itself is triggered externally.", }, }, ], }, ], };