533 lines
17 KiB
TypeScript
533 lines
17 KiB
TypeScript
import { CollectionConfig } from "payload";
|
|
import { isDeveloper } from "@/utils/access-control/isRole";
|
|
|
|
export const Assets: CollectionConfig = {
|
|
slug: "assets",
|
|
admin: {
|
|
group: "Logistics",
|
|
useAsTitle: "name",
|
|
},
|
|
fields: [
|
|
{
|
|
name: "name",
|
|
type: "text",
|
|
required: true,
|
|
},
|
|
{
|
|
name: "approvalStatus",
|
|
type: "select",
|
|
label: "Approval Status",
|
|
options: [
|
|
{ label: "In Progress", value: "in_progress" },
|
|
{ label: "Ready for Review", value: "ready_for_review" },
|
|
{ label: "Approved", value: "approved" },
|
|
{ label: "Rejected", value: "rejected" },
|
|
{ label: "Revision Requested", value: "revision_requested" },
|
|
],
|
|
defaultValue: "in_progress",
|
|
filterOptions: ({ options, data, req }) => {
|
|
return !isDeveloper({ req })
|
|
? options.filter((option) =>
|
|
typeof option === "string"
|
|
? options
|
|
: ["in_progress", "ready_for_review"].includes(option.value),
|
|
)
|
|
: options;
|
|
},
|
|
required: true,
|
|
admin: {
|
|
description:
|
|
"Mark whether this asset is ready for developer approval and implementation into the live environment.",
|
|
},
|
|
},
|
|
{
|
|
type: "tabs",
|
|
tabs: [
|
|
{
|
|
label: "Real Data",
|
|
description:
|
|
"In-game technical data for this asset, like its config class name, the mod it belongs to, a preview thumbnail image, etc.",
|
|
fields: [
|
|
{
|
|
name: "className",
|
|
type: "text",
|
|
required: true,
|
|
defaultValue: "",
|
|
},
|
|
{
|
|
name: "assetType",
|
|
type: "select",
|
|
required: true,
|
|
options: [
|
|
{
|
|
label: "Weapon",
|
|
value: "weapon",
|
|
},
|
|
{
|
|
label: "Magazine",
|
|
value: "magazine",
|
|
},
|
|
{
|
|
label: "Optic",
|
|
value: "optic",
|
|
},
|
|
{
|
|
label: "Muzzle",
|
|
value: "muzzle",
|
|
},
|
|
{
|
|
label: "Bipod",
|
|
value: "bipod",
|
|
},
|
|
{
|
|
label: "Uniform",
|
|
value: "uniform",
|
|
},
|
|
{
|
|
label: "Vest",
|
|
value: "vest",
|
|
},
|
|
{
|
|
label: "Backpack",
|
|
value: "backpack",
|
|
},
|
|
{
|
|
label: "Helmet",
|
|
value: "helmet",
|
|
},
|
|
{
|
|
label: "Facewear",
|
|
value: "facewear",
|
|
},
|
|
{
|
|
label: "NVG",
|
|
value: "nvg",
|
|
},
|
|
{
|
|
label: "Radio",
|
|
value: "radio",
|
|
},
|
|
{
|
|
label: "Medical",
|
|
value: "medical",
|
|
},
|
|
{
|
|
label: "Tool",
|
|
value: "tool",
|
|
},
|
|
{
|
|
label: "Explosive",
|
|
value: "explosive",
|
|
},
|
|
{
|
|
label: "Miscellaneous",
|
|
value: "miscellaneous",
|
|
},
|
|
],
|
|
defaultValue: "weapon",
|
|
},
|
|
{
|
|
name: "Weapon Configuration",
|
|
type: "group",
|
|
admin: {
|
|
condition: (data, siblingData) => siblingData.assetType === "weapon",
|
|
},
|
|
fields: [
|
|
{
|
|
name: "slotType",
|
|
type: "select",
|
|
options: [
|
|
{
|
|
label: "Primary",
|
|
value: "primary",
|
|
},
|
|
{
|
|
label: "Secondary",
|
|
value: "secondary",
|
|
},
|
|
{
|
|
label: "Launcher",
|
|
value: "launcher",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "compatibleMagazines",
|
|
type: "relationship",
|
|
relationTo: "assets",
|
|
hasMany: true,
|
|
filterOptions: {
|
|
assetType: {
|
|
equals: "magazine",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "compatibleAttachments",
|
|
type: "relationship",
|
|
relationTo: "assets",
|
|
hasMany: true,
|
|
filterOptions: {
|
|
assetType: {
|
|
in: "optic,muzzle,bipod",
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "Nightvision Configuration",
|
|
type: "group",
|
|
admin: {
|
|
condition: (data, siblingData) => siblingData.assetType === "nvg",
|
|
},
|
|
fields: [
|
|
{
|
|
name: "nvgGeneration",
|
|
type: "select",
|
|
label: "NVG Generation",
|
|
options: [
|
|
{
|
|
label: "Gen 1",
|
|
value: "gen1",
|
|
},
|
|
{
|
|
label: "Gen 2",
|
|
value: "gen2",
|
|
},
|
|
{
|
|
label: "Gen 3",
|
|
value: "gen3",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "nvgHasThermals",
|
|
type: "checkbox",
|
|
label: "NVG Thermal Capability",
|
|
admin: {
|
|
description:
|
|
"Whether or not these night-vision goggles possess a thermal vision mode.",
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "Container Configuration",
|
|
type: "group",
|
|
admin: {
|
|
condition: (data, siblingData) =>
|
|
["uniform", "vest", "backpack"].includes(siblingData.assetType),
|
|
},
|
|
fields: [
|
|
{
|
|
name: "capacityKg",
|
|
type: "number",
|
|
label: "Storage Capacity (kg.)",
|
|
},
|
|
{
|
|
name: "weightKg",
|
|
type: "number",
|
|
label: "Weight (kg.)",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "Magazine Configuration",
|
|
type: "group",
|
|
admin: {
|
|
condition: (data, siblingData) => siblingData.assetType === "magazine",
|
|
},
|
|
fields: [
|
|
{
|
|
name: "roundCapacity",
|
|
type: "number",
|
|
},
|
|
{
|
|
name: "ammoType",
|
|
type: "text",
|
|
},
|
|
{
|
|
name: "greenmagCompatible",
|
|
type: "checkbox",
|
|
admin: {
|
|
description:
|
|
"Whether or not this magazine is compatible with the GreenMag mod.",
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "Asset Metadata",
|
|
type: "group",
|
|
fields: [
|
|
{
|
|
name: "mod",
|
|
type: "text",
|
|
},
|
|
{
|
|
name: "thumbnail",
|
|
type: "upload",
|
|
relationTo: "media",
|
|
},
|
|
{
|
|
name: "gameDescription",
|
|
type: "textarea",
|
|
label: "In-Game Description",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
label: "Virtual Data",
|
|
description:
|
|
"Virtual data for this asset, like the factions that use it, its rarity and perceived value, trading and market flags, resources for crafting, etc.",
|
|
fields: [
|
|
{
|
|
name: "tradeable",
|
|
type: "checkbox",
|
|
admin: {
|
|
description:
|
|
"Whether or not this asset can be traded on the market. If unchecked, the asset can never be bought or sold, only crafted or collected.",
|
|
},
|
|
},
|
|
{
|
|
name: "marketTrading",
|
|
type: "group",
|
|
label: "Market & Trading",
|
|
admin: {
|
|
condition: (data, siblingData) => siblingData.tradeable,
|
|
},
|
|
fields: [
|
|
{
|
|
name: "Rarity",
|
|
type: "select",
|
|
admin: {
|
|
description:
|
|
"The rarity of this item in the world of the active campaign. Rarity will be accounted for in market valuation and trading calculations.",
|
|
},
|
|
options: [
|
|
{
|
|
label: "Basic",
|
|
value: "basic",
|
|
},
|
|
{
|
|
label: "Common",
|
|
value: "common",
|
|
},
|
|
{
|
|
label: "Uncommon",
|
|
value: "uncommon",
|
|
},
|
|
{
|
|
label: "Rare",
|
|
value: "rare",
|
|
},
|
|
{
|
|
label: "Very Rare",
|
|
value: "veryRare",
|
|
},
|
|
{
|
|
label: "Epic",
|
|
value: "epic",
|
|
},
|
|
{
|
|
label: "Legendary",
|
|
value: "legendary",
|
|
},
|
|
{
|
|
label: "Unique",
|
|
value: "unique",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "perceivedValue",
|
|
type: "group",
|
|
admin: {
|
|
description:
|
|
'The asset\'s "perceived value" when considered in market and trading calculations. Note that the "base" values are the "resting" valuations. Later calculations will increase and decrease the valuation based on this resting valuation, ultimately tending to remain within some percentage margin of this base price. Always and only considers the primary campaign currency in regard to price.',
|
|
},
|
|
fields: [
|
|
{
|
|
type: "row",
|
|
fields: [
|
|
{
|
|
name: "baseBuyPrice",
|
|
type: "number",
|
|
},
|
|
{
|
|
name: "baseSellPrice",
|
|
type: "number",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "crafting",
|
|
type: "group",
|
|
fields: [
|
|
{
|
|
name: "craftable",
|
|
type: "checkbox",
|
|
},
|
|
{
|
|
name: "blueprintRequired",
|
|
type: "checkbox",
|
|
admin: {
|
|
description:
|
|
"This asset requires a blueprint to be crafted, otherwise it can only be obtained from scavenging and/or trading.",
|
|
},
|
|
},
|
|
{
|
|
name: "technologyRequired",
|
|
type: "relationship",
|
|
relationTo: "technologies",
|
|
hasMany: true,
|
|
admin: {
|
|
description:
|
|
"One or more technologies required before this weapon can be crafted.",
|
|
},
|
|
},
|
|
{
|
|
name: "technologyRequiredToUse",
|
|
type: "checkbox",
|
|
admin: {
|
|
description:
|
|
"If checked, this asset requires the above technologies or else cannot be used at all.",
|
|
},
|
|
},
|
|
{
|
|
name: "craftingData",
|
|
type: "group",
|
|
fields: [
|
|
{
|
|
name: "inputs",
|
|
type: "array",
|
|
fields: [
|
|
{
|
|
name: "resource",
|
|
type: "relationship",
|
|
relationTo: "resources",
|
|
hasMany: true,
|
|
required: true,
|
|
},
|
|
{
|
|
name: "quantity",
|
|
type: "number",
|
|
},
|
|
{
|
|
name: "lended",
|
|
type: "checkbox",
|
|
admin: {
|
|
description:
|
|
'If checked, this resource is "lended" to the crafting of this asset. Upon the crafting\'s completion, this resource is refunded to the unit.',
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "requiresStructure",
|
|
type: "relationship",
|
|
relationTo: "structures",
|
|
hasMany: true,
|
|
},
|
|
{
|
|
name: "craftingTimePerUnit",
|
|
type: "number",
|
|
label: "Crafting Time per Unit",
|
|
defaultValue: 1,
|
|
min: 1,
|
|
required: true,
|
|
admin: {
|
|
components: {
|
|
Description: {
|
|
path: "@/components/static/TickDurationDescription",
|
|
clientProps: {
|
|
task: "complete production of one unit of this asset",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
name: "byproducts",
|
|
type: "array",
|
|
admin: {
|
|
description:
|
|
"Byproducts of the crafting process. For each unit crafted of this Asset, these byproducts are also created and added to the unit's resources.",
|
|
},
|
|
fields: [
|
|
{
|
|
name: "resource",
|
|
type: "relationship",
|
|
relationTo: "resources",
|
|
hasMany: true,
|
|
required: true,
|
|
},
|
|
{
|
|
name: "quantity",
|
|
type: "number",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "batchSize",
|
|
type: "number",
|
|
admin: {
|
|
description:
|
|
"An optional batch size. If provided, this number of this asset will be created upon crafting completion.",
|
|
},
|
|
required: true,
|
|
defaultValue: 1,
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: "relatedAssets",
|
|
type: "relationship",
|
|
relationTo: "assets",
|
|
hasMany: true,
|
|
admin: {
|
|
description:
|
|
"Suggested complements to this asset (for example, if the asset was a Bandage, some related assets could include an IV, blood bag, epinephrine, etc.)",
|
|
},
|
|
},
|
|
],
|
|
},
|
|
{
|
|
label: "Auditing",
|
|
description: "Auditing and moderation for this Asset.",
|
|
admin: {
|
|
condition: ({ user }) => isDeveloper({ req: { user: user } } as never),
|
|
},
|
|
access: {
|
|
read: isDeveloper,
|
|
create: isDeveloper,
|
|
update: isDeveloper,
|
|
},
|
|
fields: [
|
|
{
|
|
name: "isLive",
|
|
type: "checkbox",
|
|
admin: {
|
|
description:
|
|
'If checked, this item is approved and considered "live" (i.e. it will be considered in calculations and made available in-game.)',
|
|
},
|
|
},
|
|
{
|
|
name: "notes",
|
|
type: "richText",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
],
|
|
};
|