1
0
Fork 0
polaris-task-force/src/collections/game/GameRules.ts
Z8MB1E 5f06039697 feat(world): game map collections with basemaps, map permissions, and meter proximity
Add maps basemap config (world size, image/tiles mode, zoom defaults, isActive), map-roads, map-zones, and resource-nodes collections with maps:* permissions. Track game-structures map placement, meter coordinates, and label visibility/priority. Bump proximityThreshold to meters and adapt side-op map creation plus test fixtures to the new required fields.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-09-16 23:13:57 -04:00

228 lines
6.5 KiB
TypeScript

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.",
},
},
],
},
],
};