System development, WIP

This commit is contained in:
2026-05-05 13:55:42 +02:00
commit c0223977d2
250 changed files with 10362 additions and 0 deletions
+10
View File
@@ -0,0 +1,10 @@
export { default as MGNECharacter } from "./character.mjs"
export { default as MGNECreature } from "./creature.mjs"
export { default as MGNECompanion } from "./companion.mjs"
export { default as MGNEWeapon } from "./weapon.mjs"
export { default as MGNEArmor } from "./armor.mjs"
export { default as MGNEShield } from "./shield.mjs"
export { default as MGNEEquipment } from "./equipment.mjs"
export { default as MGNEResonanceCore } from "./resonance-core.mjs"
export { default as MGNEArtifact } from "./artifact.mjs"
export { default as MGNEFeature } from "./feature.mjs"
+22
View File
@@ -0,0 +1,22 @@
import { SYSTEM } from "../config/system.mjs"
import { booleanField, htmlField, numberField } from "./shared.mjs"
export default class MGNEArmor extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
description: htmlField(""),
armorDie: new foundry.data.fields.StringField({
required: true,
nullable: false,
initial: "d4",
choices: SYSTEM.armorDieChoices,
}),
penalty: numberField(0, 0, 6),
equipped: booleanField(false),
broken: booleanField(false),
}
}
/** @override */
static LOCALIZATION_PREFIXES = ["MGNE.Armor"]
}
+28
View File
@@ -0,0 +1,28 @@
import { SYSTEM } from "../config/system.mjs"
import { booleanField, htmlField, stringField } from "./shared.mjs"
export default class MGNEArtifact extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
description: htmlField(""),
artifactId: new foundry.data.fields.StringField({
required: true,
nullable: false,
initial: "shiver-lens",
choices: SYSTEM.artifactChoices,
}),
synchronized: booleanField(false),
synchronizedTo: stringField(""),
usageDie: new foundry.data.fields.StringField({
required: true,
nullable: false,
initial: "d6",
choices: SYSTEM.usageDieChoices,
}),
broken: booleanField(false),
}
}
/** @override */
static LOCALIZATION_PREFIXES = ["MGNE.Artifact"]
}
+52
View File
@@ -0,0 +1,52 @@
import { SYSTEM } from "../config/system.mjs"
import { abilitySchema, booleanField, conditionSchema, htmlField, numberField, stringField, trackSchema } from "./shared.mjs"
export default class MGNECharacter extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
return {
abilities: abilitySchema(),
hp: trackSchema(1, 1),
omens: new fields.SchemaField({
current: numberField(0, 0),
die: new fields.StringField({ required: true, nullable: false, initial: "d2", choices: SYSTEM.omenDieChoices }),
}),
resonance: new fields.SchemaField({
max: numberField(1, 0),
used: numberField(0, 0),
blocked: booleanField(false),
}),
artifactSync: new fields.SchemaField({
used: numberField(0, 0),
}),
survival: new fields.SchemaField({
salvationUsed: booleanField(false),
}),
conditions: conditionSchema(),
carryCapacity: numberField(8, 0),
rations: numberField(0, 0),
kiffol: numberField(0, 0),
background: stringField(""),
origin: stringField(""),
scars: stringField(""),
motivation: stringField(""),
vice: stringField(""),
description: htmlField(""),
notes: htmlField(""),
}
}
prepareDerivedData() {
super.prepareDerivedData()
this.carryCapacity = (this.abilities.strength?.value ?? 0) + 8
this.resonance.remaining = Math.max(0, (this.resonance.max ?? 0) - (this.resonance.used ?? 0))
this.syncLimit = Math.max(0, this.abilities.toughness?.value ?? 0)
this.syncRemaining = Math.max(0, this.syncLimit - (this.artifactSync.used ?? 0))
this.armorFormula = this.parent?.getArmorRollFormula?.() ?? "0"
}
/** @override */
static LOCALIZATION_PREFIXES = ["MGNE.Character"]
}
+32
View File
@@ -0,0 +1,32 @@
import { SYSTEM } from "../config/system.mjs"
import { abilitySchema, htmlField, numberField, stringField, trackSchema } from "./shared.mjs"
export default class MGNECompanion extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
return {
abilities: abilitySchema(),
hp: trackSchema(1, 1),
morale: numberField(7, 2, 12),
armor: new fields.SchemaField({
die: new fields.StringField({ required: true, nullable: false, initial: "0", choices: SYSTEM.armorDieChoices }),
}),
attack: new fields.SchemaField({
label: stringField("Attack"),
damage: stringField("1d4"),
}),
valueText: stringField(""),
traitText: stringField(""),
specialtyText: stringField(""),
adventuringBehavior: htmlField(""),
combatBehavior: htmlField(""),
upkeep: stringField("3d10c per full rest"),
description: htmlField(""),
notes: htmlField(""),
}
}
/** @override */
static LOCALIZATION_PREFIXES = ["MGNE.Companion"]
}
+27
View File
@@ -0,0 +1,27 @@
import { SYSTEM } from "../config/system.mjs"
import { abilitySchema, htmlField, numberField, stringField, trackSchema } from "./shared.mjs"
export default class MGNECreature extends foundry.abstract.TypeDataModel {
static defineSchema() {
const fields = foundry.data.fields
return {
abilities: abilitySchema(),
hp: trackSchema(1, 1),
morale: numberField(7, 2, 12),
armor: new fields.SchemaField({
die: new fields.StringField({ required: true, nullable: false, initial: "0", choices: SYSTEM.armorDieChoices }),
}),
attack: new fields.SchemaField({
label: stringField("Attack"),
damage: stringField("1d4"),
}),
description: htmlField(""),
special: htmlField(""),
notes: htmlField(""),
}
}
/** @override */
static LOCALIZATION_PREFIXES = ["MGNE.Creature"]
}
+29
View File
@@ -0,0 +1,29 @@
import { SYSTEM } from "../config/system.mjs"
import { booleanField, htmlField, numberField } from "./shared.mjs"
export default class MGNEEquipment extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
description: htmlField(""),
subtype: new foundry.data.fields.StringField({
required: true,
nullable: false,
initial: "gear",
choices: SYSTEM.equipmentSubtypes,
}),
quantity: numberField(1, 0),
carried: booleanField(true),
equipped: booleanField(false),
usageDie: new foundry.data.fields.StringField({
required: true,
nullable: false,
initial: "d6",
choices: SYSTEM.usageDieChoices,
}),
consumable: booleanField(false),
}
}
/** @override */
static LOCALIZATION_PREFIXES = ["MGNE.Equipment"]
}
+19
View File
@@ -0,0 +1,19 @@
import { SYSTEM } from "../config/system.mjs"
import { htmlField } from "./shared.mjs"
export default class MGNEFeature extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
featureId: new foundry.data.fields.StringField({
required: true,
nullable: false,
initial: "akimbo-hit-priest",
choices: SYSTEM.featureChoices,
}),
description: htmlField(""),
}
}
/** @override */
static LOCALIZATION_PREFIXES = ["MGNE.Feature"]
}
+26
View File
@@ -0,0 +1,26 @@
import { SYSTEM } from "../config/system.mjs"
import { booleanField, htmlField, stringField } from "./shared.mjs"
export default class MGNEResonanceCore extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
description: htmlField(""),
resonationId: new foundry.data.fields.StringField({
required: true,
nullable: false,
initial: "accelerate",
choices: SYSTEM.resonanceList,
}),
usageDie: new foundry.data.fields.StringField({
required: true,
nullable: false,
initial: "d6",
choices: SYSTEM.usageDieChoices,
}),
burnedOut: booleanField(false),
}
}
/** @override */
static LOCALIZATION_PREFIXES = ["MGNE.ResonanceCore"]
}
+67
View File
@@ -0,0 +1,67 @@
import { SYSTEM } from "../config/system.mjs"
export function htmlField(initial = "", options = {}) {
return new foundry.data.fields.HTMLField({ required: true, initial, textSearch: true, ...options })
}
export function stringField(initial = "", options = {}) {
return new foundry.data.fields.StringField({ required: true, nullable: false, initial, ...options })
}
export function numberField(initial = 0, min = 0, max = null, options = {}) {
return new foundry.data.fields.NumberField({
required: true,
nullable: false,
integer: true,
initial,
min,
...(max === null ? {} : { max }),
...options,
})
}
export function booleanField(initial = false, options = {}) {
return new foundry.data.fields.BooleanField({ required: true, initial, ...options })
}
export function abilitySchema() {
const fields = foundry.data.fields
const schema = {}
for (const abilityId of SYSTEM.abilityOrder) {
const ability = SYSTEM.abilities[abilityId]
schema[abilityId] = new fields.SchemaField(
{
label: stringField(ability.label, { label: "MGNE.Common.Label" }),
value: numberField(0, -3, 6, { label: "MGNE.Common.Value" }),
},
{ label: ability.label }
)
}
return new fields.SchemaField(schema)
}
export function conditionSchema() {
const fields = foundry.data.fields
const schema = {}
for (const condition of Object.values(SYSTEM.conditions)) {
if (condition.hasValue) {
schema[condition.id] = new fields.SchemaField(
{ value: numberField(0, 0, 12, { label: "MGNE.Common.Value" }) },
{ label: condition.label }
)
} else {
schema[condition.id] = new fields.SchemaField(
{ active: booleanField(false, { label: condition.label }) },
{ label: condition.label }
)
}
}
return new fields.SchemaField(schema)
}
export function trackSchema(initialValue = 0, initialMax = 0) {
return new foundry.data.fields.SchemaField({
value: numberField(initialValue, -99),
max: numberField(initialMax, 0),
})
}
+22
View File
@@ -0,0 +1,22 @@
import { SYSTEM } from "../config/system.mjs"
import { booleanField, htmlField, numberField } from "./shared.mjs"
export default class MGNEShield extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
description: htmlField(""),
armorDie: new foundry.data.fields.StringField({
required: true,
nullable: false,
initial: "d4",
choices: SYSTEM.armorDieChoices,
}),
penalty: numberField(0, 0, 4),
equipped: booleanField(false),
broken: booleanField(false),
}
}
/** @override */
static LOCALIZATION_PREFIXES = ["MGNE.Shield"]
}
+31
View File
@@ -0,0 +1,31 @@
import { SYSTEM } from "../config/system.mjs"
import { booleanField, htmlField, numberField, stringField } from "./shared.mjs"
export default class MGNEWeapon extends foundry.abstract.TypeDataModel {
static defineSchema() {
return {
description: htmlField(""),
category: new foundry.data.fields.StringField({
required: true,
nullable: false,
initial: "melee",
choices: SYSTEM.weaponCategories,
}),
damage: stringField("1d4"),
range: stringField("Touch"),
properties: stringField(""),
usageDie: new foundry.data.fields.StringField({
required: true,
nullable: false,
initial: "d6",
choices: SYSTEM.usageDieChoices,
}),
quantity: numberField(1, 0),
equipped: booleanField(false),
broken: booleanField(false),
}
}
/** @override */
static LOCALIZATION_PREFIXES = ["MGNE.Weapon"]
}