feat(minigames): add custom minefield and radio test collections with permissions, events, and migration
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
parent
0143c235bc
commit
1f99e34c0d
13 changed files with 25060 additions and 1 deletions
|
|
@ -36,6 +36,10 @@ const TARGET_COLLECTIONS = [
|
|||
{ label: "Voice Submissions", value: "voice-submissions" },
|
||||
{ label: "Story Beats", value: "story-beats" },
|
||||
{ label: "Story Beat States", value: "story-beat-states" },
|
||||
{ label: "Custom Minefields", value: "custom-minefields" },
|
||||
{ label: "Custom Minefield Scores", value: "custom-minefield-scores" },
|
||||
{ label: "Custom Radio Tests", value: "custom-radio-tests" },
|
||||
{ label: "Custom Radio Test Scores", value: "custom-radio-test-scores" },
|
||||
] as const;
|
||||
|
||||
export const GameEventLogs: CollectionConfig = {
|
||||
|
|
|
|||
48
src/collections/minigames/CustomMinefieldScores.ts
Normal file
48
src/collections/minigames/CustomMinefieldScores.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import { CollectionConfig } from "payload";
|
||||
import { requirePermission } from "@/utils/access-control/hasPermission";
|
||||
|
||||
export const CustomMinefieldScores: CollectionConfig = {
|
||||
slug: "custom-minefield-scores",
|
||||
admin: {
|
||||
group: "Minigames",
|
||||
defaultColumns: ["minefield", "user", "seconds", "won", "createdAt"],
|
||||
},
|
||||
access: {
|
||||
read: ({ req }) => !!req.user,
|
||||
create: ({ req }) => !!req.user,
|
||||
update: () => false,
|
||||
delete: requirePermission("custom-minefield-scores:delete"),
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: "minefield",
|
||||
type: "relationship",
|
||||
relationTo: "custom-minefields",
|
||||
required: true,
|
||||
index: true,
|
||||
},
|
||||
{
|
||||
name: "user",
|
||||
type: "relationship",
|
||||
relationTo: "users",
|
||||
required: true,
|
||||
index: true,
|
||||
},
|
||||
{
|
||||
name: "seconds",
|
||||
type: "number",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "flags",
|
||||
type: "number",
|
||||
defaultValue: 0,
|
||||
},
|
||||
{
|
||||
name: "won",
|
||||
type: "checkbox",
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
82
src/collections/minigames/CustomMinefields.ts
Normal file
82
src/collections/minigames/CustomMinefields.ts
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import { CollectionConfig } from "payload";
|
||||
import { requirePermission, hasPermission } from "@/utils/access-control/hasPermission";
|
||||
|
||||
export const CustomMinefields: CollectionConfig = {
|
||||
slug: "custom-minefields",
|
||||
admin: {
|
||||
group: "Minigames",
|
||||
useAsTitle: "name",
|
||||
defaultColumns: ["name", "author", "rows", "cols", "mineCount", "published", "playCount"],
|
||||
listSearchableFields: ["name"],
|
||||
},
|
||||
access: {
|
||||
read: ({ req }) => !!req.user,
|
||||
create: ({ req }) => !!req.user,
|
||||
update: async ({ req }) => {
|
||||
if (!req.user) return false;
|
||||
if (await hasPermission(req.payload, req.user, "custom-minefields:update")) return true;
|
||||
return { author: { equals: req.user.id } };
|
||||
},
|
||||
delete: requirePermission("custom-minefields:delete"),
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: "name",
|
||||
type: "text",
|
||||
required: true,
|
||||
maxLength: 100,
|
||||
},
|
||||
{
|
||||
name: "author",
|
||||
type: "relationship",
|
||||
relationTo: "users",
|
||||
required: true,
|
||||
admin: {
|
||||
description: "Player who authored this minefield.",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "rows",
|
||||
type: "number",
|
||||
required: true,
|
||||
min: 9,
|
||||
max: 500,
|
||||
},
|
||||
{
|
||||
name: "cols",
|
||||
type: "number",
|
||||
required: true,
|
||||
min: 9,
|
||||
max: 500,
|
||||
},
|
||||
{
|
||||
name: "mines",
|
||||
type: "json",
|
||||
required: true,
|
||||
admin: {
|
||||
description: "Array of { row, col } mine positions.",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "mineCount",
|
||||
type: "number",
|
||||
required: true,
|
||||
min: 1,
|
||||
max: 10000,
|
||||
},
|
||||
{
|
||||
name: "published",
|
||||
type: "checkbox",
|
||||
defaultValue: true,
|
||||
},
|
||||
{
|
||||
name: "playCount",
|
||||
type: "number",
|
||||
defaultValue: 0,
|
||||
admin: {
|
||||
readOnly: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
69
src/collections/minigames/CustomRadioTestScores.ts
Normal file
69
src/collections/minigames/CustomRadioTestScores.ts
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
import { CollectionConfig } from "payload";
|
||||
import { requirePermission } from "@/utils/access-control/hasPermission";
|
||||
|
||||
export const CustomRadioTestScores: CollectionConfig = {
|
||||
slug: "custom-radio-test-scores",
|
||||
admin: {
|
||||
group: "Minigames",
|
||||
defaultColumns: ["test", "user", "score", "accuracy", "mode", "createdAt"],
|
||||
},
|
||||
access: {
|
||||
read: ({ req }) => !!req.user,
|
||||
create: ({ req }) => !!req.user,
|
||||
update: () => false,
|
||||
delete: requirePermission("custom-radio-test-scores:delete"),
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: "test",
|
||||
type: "relationship",
|
||||
relationTo: "custom-radio-tests",
|
||||
required: true,
|
||||
index: true,
|
||||
},
|
||||
{
|
||||
name: "user",
|
||||
type: "relationship",
|
||||
relationTo: "users",
|
||||
required: true,
|
||||
index: true,
|
||||
},
|
||||
{
|
||||
name: "score",
|
||||
type: "number",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "accuracy",
|
||||
type: "number",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "correctMessages",
|
||||
type: "number",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "incorrectMessages",
|
||||
type: "number",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: "mode",
|
||||
type: "select",
|
||||
required: true,
|
||||
options: [
|
||||
{ label: "Sprint", value: "sprint" },
|
||||
{ label: "Watch", value: "watch" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "timeMs",
|
||||
type: "number",
|
||||
admin: {
|
||||
description: "Sprint mode only: elapsed time in milliseconds.",
|
||||
},
|
||||
},
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
77
src/collections/minigames/CustomRadioTests.ts
Normal file
77
src/collections/minigames/CustomRadioTests.ts
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
import { CollectionConfig } from "payload";
|
||||
import { requirePermission, hasPermission } from "@/utils/access-control/hasPermission";
|
||||
|
||||
export const CustomRadioTests: CollectionConfig = {
|
||||
slug: "custom-radio-tests",
|
||||
admin: {
|
||||
group: "Minigames",
|
||||
useAsTitle: "name",
|
||||
defaultColumns: ["name", "author", "messageCount", "order", "published", "playCount"],
|
||||
listSearchableFields: ["name"],
|
||||
},
|
||||
access: {
|
||||
read: ({ req }) => !!req.user,
|
||||
create: ({ req }) => !!req.user,
|
||||
update: async ({ req }) => {
|
||||
if (!req.user) return false;
|
||||
if (await hasPermission(req.payload, req.user, "custom-radio-tests:update")) return true;
|
||||
return { author: { equals: req.user.id } };
|
||||
},
|
||||
delete: requirePermission("custom-radio-tests:delete"),
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: "name",
|
||||
type: "text",
|
||||
required: true,
|
||||
maxLength: 100,
|
||||
},
|
||||
{
|
||||
name: "author",
|
||||
type: "relationship",
|
||||
relationTo: "users",
|
||||
required: true,
|
||||
admin: {
|
||||
description: "Player who authored this radio test.",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "messages",
|
||||
type: "json",
|
||||
required: true,
|
||||
admin: {
|
||||
description: "Array of message strings used as the typing pool.",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "messageCount",
|
||||
type: "number",
|
||||
required: true,
|
||||
min: 1,
|
||||
max: 100,
|
||||
},
|
||||
{
|
||||
name: "order",
|
||||
type: "select",
|
||||
defaultValue: "fixed",
|
||||
options: [
|
||||
{ label: "Fixed Order", value: "fixed" },
|
||||
{ label: "Shuffled", value: "shuffled" },
|
||||
],
|
||||
},
|
||||
{
|
||||
name: "published",
|
||||
type: "checkbox",
|
||||
defaultValue: true,
|
||||
},
|
||||
{
|
||||
name: "playCount",
|
||||
type: "number",
|
||||
defaultValue: 0,
|
||||
admin: {
|
||||
readOnly: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
timestamps: true,
|
||||
};
|
||||
24406
src/migrations/20260908_172241_add_custom_minigame_collections.json
Normal file
24406
src/migrations/20260908_172241_add_custom_minigame_collections.json
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
|
@ -45,6 +45,7 @@ import * as migration_20260907_090245_add_mission_ready_reminder_fields from './
|
|||
import * as migration_20260907_120754_add_story_beats from './20260907_120754_add_story_beats';
|
||||
import * as migration_20260907_124024_convert_story_beats_body_to_lexical from './20260907_124024_convert_story_beats_body_to_lexical';
|
||||
import * as migration_20260908_152021_add_opord_recall_minigame_stats from './20260908_152021_add_opord_recall_minigame_stats';
|
||||
import * as migration_20260908_172241_add_custom_minigame_collections from './20260908_172241_add_custom_minigame_collections';
|
||||
|
||||
export const migrations = [
|
||||
{
|
||||
|
|
@ -282,4 +283,9 @@ export const migrations = [
|
|||
down: migration_20260908_152021_add_opord_recall_minigame_stats.down,
|
||||
name: '20260908_152021_add_opord_recall_minigame_stats'
|
||||
},
|
||||
{
|
||||
up: migration_20260908_172241_add_custom_minigame_collections.up,
|
||||
down: migration_20260908_172241_add_custom_minigame_collections.down,
|
||||
name: '20260908_172241_add_custom_minigame_collections'
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -125,6 +125,10 @@ export interface Config {
|
|||
'game-servers': GameServer;
|
||||
'arma-sync-events': ArmaSyncEvent;
|
||||
'arma-commands': ArmaCommand;
|
||||
'custom-minefields': CustomMinefield;
|
||||
'custom-minefield-scores': CustomMinefieldScore;
|
||||
'custom-radio-tests': CustomRadioTest;
|
||||
'custom-radio-test-scores': CustomRadioTestScore;
|
||||
'plugin-ai-instructions': PluginAiInstruction;
|
||||
'payload-mcp-api-keys': PayloadMcpApiKey;
|
||||
'payload-kv': PayloadKv;
|
||||
|
|
@ -198,6 +202,10 @@ export interface Config {
|
|||
'game-servers': GameServersSelect<false> | GameServersSelect<true>;
|
||||
'arma-sync-events': ArmaSyncEventsSelect<false> | ArmaSyncEventsSelect<true>;
|
||||
'arma-commands': ArmaCommandsSelect<false> | ArmaCommandsSelect<true>;
|
||||
'custom-minefields': CustomMinefieldsSelect<false> | CustomMinefieldsSelect<true>;
|
||||
'custom-minefield-scores': CustomMinefieldScoresSelect<false> | CustomMinefieldScoresSelect<true>;
|
||||
'custom-radio-tests': CustomRadioTestsSelect<false> | CustomRadioTestsSelect<true>;
|
||||
'custom-radio-test-scores': CustomRadioTestScoresSelect<false> | CustomRadioTestScoresSelect<true>;
|
||||
'plugin-ai-instructions': PluginAiInstructionsSelect<false> | PluginAiInstructionsSelect<true>;
|
||||
'payload-mcp-api-keys': PayloadMcpApiKeysSelect<false> | PayloadMcpApiKeysSelect<true>;
|
||||
'payload-kv': PayloadKvSelect<false> | PayloadKvSelect<true>;
|
||||
|
|
@ -1686,6 +1694,12 @@ export interface Role {
|
|||
| 'tickets:staff'
|
||||
| 'discord:staff'
|
||||
| 'discord:announce'
|
||||
| 'custom-minefields:update'
|
||||
| 'custom-minefields:delete'
|
||||
| 'custom-minefield-scores:delete'
|
||||
| 'custom-radio-tests:update'
|
||||
| 'custom-radio-tests:delete'
|
||||
| 'custom-radio-test-scores:delete'
|
||||
)[]
|
||||
| null;
|
||||
/**
|
||||
|
|
@ -1888,6 +1902,10 @@ export interface GameEventLog {
|
|||
| 'voice-submissions'
|
||||
| 'story-beats'
|
||||
| 'story-beat-states'
|
||||
| 'custom-minefields'
|
||||
| 'custom-minefield-scores'
|
||||
| 'custom-radio-tests'
|
||||
| 'custom-radio-test-scores'
|
||||
)
|
||||
| null;
|
||||
targetId?: number | null;
|
||||
|
|
@ -3692,6 +3710,101 @@ export interface ArmaCommand {
|
|||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "custom-minefields".
|
||||
*/
|
||||
export interface CustomMinefield {
|
||||
id: number;
|
||||
name: string;
|
||||
/**
|
||||
* Player who authored this minefield.
|
||||
*/
|
||||
author: number | User;
|
||||
rows: number;
|
||||
cols: number;
|
||||
/**
|
||||
* Array of { row, col } mine positions.
|
||||
*/
|
||||
mines:
|
||||
| {
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| unknown[]
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null;
|
||||
mineCount: number;
|
||||
published?: boolean | null;
|
||||
playCount?: number | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "custom-minefield-scores".
|
||||
*/
|
||||
export interface CustomMinefieldScore {
|
||||
id: number;
|
||||
minefield: number | CustomMinefield;
|
||||
user: number | User;
|
||||
seconds: number;
|
||||
flags?: number | null;
|
||||
won: boolean;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "custom-radio-tests".
|
||||
*/
|
||||
export interface CustomRadioTest {
|
||||
id: number;
|
||||
name: string;
|
||||
/**
|
||||
* Player who authored this radio test.
|
||||
*/
|
||||
author: number | User;
|
||||
/**
|
||||
* Array of message strings used as the typing pool.
|
||||
*/
|
||||
messages:
|
||||
| {
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| unknown[]
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null;
|
||||
messageCount: number;
|
||||
order?: ('fixed' | 'shuffled') | null;
|
||||
published?: boolean | null;
|
||||
playCount?: number | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "custom-radio-test-scores".
|
||||
*/
|
||||
export interface CustomRadioTestScore {
|
||||
id: number;
|
||||
test: number | CustomRadioTest;
|
||||
user: number | User;
|
||||
score: number;
|
||||
accuracy: number;
|
||||
correctMessages: number;
|
||||
incorrectMessages: number;
|
||||
mode: 'sprint' | 'watch';
|
||||
/**
|
||||
* Sprint mode only: elapsed time in milliseconds.
|
||||
*/
|
||||
timeMs?: number | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "plugin-ai-instructions".
|
||||
|
|
@ -4012,6 +4125,22 @@ export interface PayloadLockedDocument {
|
|||
relationTo: 'arma-commands';
|
||||
value: number | ArmaCommand;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'custom-minefields';
|
||||
value: number | CustomMinefield;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'custom-minefield-scores';
|
||||
value: number | CustomMinefieldScore;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'custom-radio-tests';
|
||||
value: number | CustomRadioTest;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'custom-radio-test-scores';
|
||||
value: number | CustomRadioTestScore;
|
||||
} | null)
|
||||
| ({
|
||||
relationTo: 'plugin-ai-instructions';
|
||||
value: number | PluginAiInstruction;
|
||||
|
|
@ -5651,6 +5780,66 @@ export interface ArmaCommandsSelect<T extends boolean = true> {
|
|||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "custom-minefields_select".
|
||||
*/
|
||||
export interface CustomMinefieldsSelect<T extends boolean = true> {
|
||||
name?: T;
|
||||
author?: T;
|
||||
rows?: T;
|
||||
cols?: T;
|
||||
mines?: T;
|
||||
mineCount?: T;
|
||||
published?: T;
|
||||
playCount?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "custom-minefield-scores_select".
|
||||
*/
|
||||
export interface CustomMinefieldScoresSelect<T extends boolean = true> {
|
||||
minefield?: T;
|
||||
user?: T;
|
||||
seconds?: T;
|
||||
flags?: T;
|
||||
won?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "custom-radio-tests_select".
|
||||
*/
|
||||
export interface CustomRadioTestsSelect<T extends boolean = true> {
|
||||
name?: T;
|
||||
author?: T;
|
||||
messages?: T;
|
||||
messageCount?: T;
|
||||
order?: T;
|
||||
published?: T;
|
||||
playCount?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "custom-radio-test-scores_select".
|
||||
*/
|
||||
export interface CustomRadioTestScoresSelect<T extends boolean = true> {
|
||||
test?: T;
|
||||
user?: T;
|
||||
score?: T;
|
||||
accuracy?: T;
|
||||
correctMessages?: T;
|
||||
incorrectMessages?: T;
|
||||
mode?: T;
|
||||
timeMs?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "plugin-ai-instructions_select".
|
||||
|
|
|
|||
|
|
@ -68,6 +68,10 @@ import { migrations } from "./migrations";
|
|||
import { nodemailerAdapter } from "@payloadcms/email-nodemailer";
|
||||
import nodemailer from "nodemailer";
|
||||
import { Shims } from "@/collections/Shims";
|
||||
import { CustomMinefields } from "@/collections/minigames/CustomMinefields";
|
||||
import { CustomMinefieldScores } from "@/collections/minigames/CustomMinefieldScores";
|
||||
import { CustomRadioTests } from "@/collections/minigames/CustomRadioTests";
|
||||
import { CustomRadioTestScores } from "@/collections/minigames/CustomRadioTestScores";
|
||||
import { requireAdminPageAccess } from "@/utils/access-control/hasPermission";
|
||||
import { payloadAiPlugin, PayloadAiPluginLexicalEditorFeature } from "@ai-stack/payloadcms";
|
||||
import { mcpPlugin } from "@payloadcms/plugin-mcp";
|
||||
|
|
@ -236,6 +240,12 @@ const collections = [
|
|||
GameServers,
|
||||
ArmaSyncEvents,
|
||||
ArmaCommands,
|
||||
|
||||
// Minigames
|
||||
CustomMinefields,
|
||||
CustomMinefieldScores,
|
||||
CustomRadioTests,
|
||||
CustomRadioTestScores,
|
||||
];
|
||||
|
||||
// Scoped admin pages: a user needs BOTH `<slug>:read` AND `admin:<slug>:manage`
|
||||
|
|
|
|||
|
|
@ -589,6 +589,17 @@ export const PERMISSION_GROUPS: PermissionGroup[] = [
|
|||
{ value: "discord:announce", label: "Post Announcements (/announce)" },
|
||||
],
|
||||
},
|
||||
{
|
||||
group: "Minigames",
|
||||
permissions: [
|
||||
{ value: "custom-minefields:update", label: "Edit Any Custom Minefield" },
|
||||
{ value: "custom-minefields:delete", label: "Delete Custom Minefields" },
|
||||
{ value: "custom-minefield-scores:delete", label: "Delete Custom Minefield Scores" },
|
||||
{ value: "custom-radio-tests:update", label: "Edit Any Custom Radio Test" },
|
||||
{ value: "custom-radio-tests:delete", label: "Delete Custom Radio Tests" },
|
||||
{ value: "custom-radio-test-scores:delete", label: "Delete Custom Radio Test Scores" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
|
@ -855,6 +866,12 @@ export const ALL_PERMISSION_VALUES = PERMISSION_GROUPS.flatMap((g) =>
|
|||
"tickets:staff",
|
||||
"discord:staff",
|
||||
"discord:announce",
|
||||
"custom-minefields:update",
|
||||
"custom-minefields:delete",
|
||||
"custom-minefield-scores:delete",
|
||||
"custom-radio-tests:update",
|
||||
"custom-radio-tests:delete",
|
||||
"custom-radio-test-scores:delete",
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -40,7 +40,11 @@ interface GameEventInput {
|
|||
| "voice-scripts"
|
||||
| "voice-submissions"
|
||||
| "story-beats"
|
||||
| "story-beat-states";
|
||||
| "story-beat-states"
|
||||
| "custom-minefields"
|
||||
| "custom-minefield-scores"
|
||||
| "custom-radio-tests"
|
||||
| "custom-radio-test-scores";
|
||||
targetId?: number;
|
||||
data?: Record<string, unknown>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,14 @@ export const EventTypes = {
|
|||
MinigameRadioTraffic: "minigame:radio-traffic",
|
||||
MinigameAimTrainer: "minigame:aim-trainer",
|
||||
MinigameOpordRecall: "minigame:opord-recall",
|
||||
MinigameCustomEodCreate: "minigame:custom-eod-create",
|
||||
MinigameCustomEodEdit: "minigame:custom-eod-edit",
|
||||
MinigameCustomEodDelete: "minigame:custom-eod-delete",
|
||||
MinigameCustomEodPlay: "minigame:custom-eod-play",
|
||||
MinigameCustomRadioCreate: "minigame:custom-radio-create",
|
||||
MinigameCustomRadioEdit: "minigame:custom-radio-edit",
|
||||
MinigameCustomRadioDelete: "minigame:custom-radio-delete",
|
||||
MinigameCustomRadioPlay: "minigame:custom-radio-play",
|
||||
|
||||
// Voiceover
|
||||
VoiceoverSubmit: "voiceover:submit",
|
||||
|
|
|
|||
Loading…
Reference in a new issue