Fix as per CSV sheet tracking + creature explanation
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
export { default as MGNECharacter } from "./character.mjs"
|
||||
export { default as MGNECreature } from "./creature.mjs"
|
||||
export { default as MGNECompanion } from "./companion.mjs"
|
||||
export { default as MGNEParty } from "./party.mjs"
|
||||
export { default as MGNEWeapon } from "./weapon.mjs"
|
||||
export { default as MGNEArmor } from "./armor.mjs"
|
||||
export { default as MGNEShield } from "./shield.mjs"
|
||||
@@ -8,3 +9,4 @@ 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"
|
||||
export { default as MGNECreatureTrait } from "./creature-trait.mjs"
|
||||
|
||||
@@ -12,8 +12,16 @@ export default class MGNEArmor extends foundry.abstract.TypeDataModel {
|
||||
choices: SYSTEM.armorDieChoices,
|
||||
}),
|
||||
penalty: numberField(0, 0, 6),
|
||||
weight: new foundry.data.fields.StringField({
|
||||
required: true, nullable: false, initial: "heavy",
|
||||
choices: SYSTEM.weightCategories,
|
||||
}),
|
||||
equipped: booleanField(false),
|
||||
broken: booleanField(false),
|
||||
durabilityDie: new foundry.data.fields.StringField({
|
||||
required: true, nullable: false, initial: "d6",
|
||||
choices: SYSTEM.usageDieChoices,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,12 +5,6 @@ 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({
|
||||
@@ -20,6 +14,14 @@ export default class MGNEArtifact extends foundry.abstract.TypeDataModel {
|
||||
choices: SYSTEM.usageDieChoices,
|
||||
}),
|
||||
broken: booleanField(false),
|
||||
durabilityDie: new foundry.data.fields.StringField({
|
||||
required: true, nullable: false, initial: "d6",
|
||||
choices: SYSTEM.usageDieChoices,
|
||||
}),
|
||||
weight: new foundry.data.fields.StringField({
|
||||
required: true, nullable: false, initial: "normal",
|
||||
choices: SYSTEM.weightCategories,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,6 +45,34 @@ export default class MGNECharacter extends foundry.abstract.TypeDataModel {
|
||||
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"
|
||||
|
||||
// Compute current load per RAW:
|
||||
// trivial = 0, light = 10 per slot, normal = 1, heavy = fills remaining capacity (max 1)
|
||||
let normalLoad = 0
|
||||
let lightCount = 0
|
||||
let heavyCount = 0
|
||||
for (const item of (this.parent?.items ?? [])) {
|
||||
if (item.system?.carried === false) continue // not being carried
|
||||
const w = item.system?.weight ?? "normal"
|
||||
if (w === "trivial") continue
|
||||
else if (w === "light") lightCount++
|
||||
else if (w === "normal") normalLoad++
|
||||
else if (w === "heavy") heavyCount++
|
||||
}
|
||||
normalLoad += Math.floor(lightCount / 10)
|
||||
this.lightItemCount = lightCount
|
||||
this.heavyItemCount = heavyCount
|
||||
|
||||
if (heavyCount >= 2) {
|
||||
// Can't carry two heavy items — automatically overloaded
|
||||
this.currentLoad = this.carryCapacity + (heavyCount - 1)
|
||||
} else if (heavyCount === 1) {
|
||||
// Heavy fills remaining capacity; other items fit alongside it
|
||||
this.currentLoad = Math.max(normalLoad, this.carryCapacity)
|
||||
} else {
|
||||
this.currentLoad = normalLoad
|
||||
}
|
||||
this.overloaded = this.currentLoad > this.carryCapacity
|
||||
}
|
||||
|
||||
/** @override */
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
import { abilitySchema, htmlField, numberField, stringField, trackSchema } from "./shared.mjs"
|
||||
import { 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({
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import { htmlField, stringField } from "./shared.mjs"
|
||||
|
||||
export default class MGNECreatureTrait extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
return {
|
||||
description: htmlField(""),
|
||||
trigger: stringField(""),
|
||||
}
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static LOCALIZATION_PREFIXES = ["MGNE.CreatureTrait"]
|
||||
}
|
||||
@@ -1,27 +1,39 @@
|
||||
import { SYSTEM } from "../config/system.mjs"
|
||||
import { abilitySchema, htmlField, numberField, stringField, trackSchema } from "./shared.mjs"
|
||||
import { htmlField, numberField, stringField, trackSchema } from "./shared.mjs"
|
||||
|
||||
const CREATURE_TYPES = ["human", "construct", "animal"]
|
||||
|
||||
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"),
|
||||
}),
|
||||
creatureType: new fields.SetField(
|
||||
new fields.StringField({ required: true, choices: CREATURE_TYPES }),
|
||||
{ required: true, nullable: false, initial: [] }
|
||||
),
|
||||
number: stringField("1"),
|
||||
actionTableUuid: stringField(""),
|
||||
description: htmlField(""),
|
||||
special: htmlField(""),
|
||||
notes: htmlField(""),
|
||||
}
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static LOCALIZATION_PREFIXES = ["MGNE.Creature"]
|
||||
|
||||
/** @override */
|
||||
static migrateData(source) {
|
||||
// Remove old attack field if present (no longer part of the schema)
|
||||
if ("attack" in source) delete source.attack
|
||||
// Form submissions send null for unchecked checkboxes in array fields — filter them out
|
||||
if (Array.isArray(source.creatureType)) {
|
||||
source.creatureType = source.creatureType.filter(v => v != null && v !== "")
|
||||
}
|
||||
return super.migrateData(source)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,15 @@ export default class MGNEEquipment extends foundry.abstract.TypeDataModel {
|
||||
choices: SYSTEM.usageDieChoices,
|
||||
}),
|
||||
consumable: booleanField(false),
|
||||
broken: booleanField(false),
|
||||
durabilityDie: new foundry.data.fields.StringField({
|
||||
required: true, nullable: false, initial: "d6",
|
||||
choices: SYSTEM.usageDieChoices,
|
||||
}),
|
||||
weight: new foundry.data.fields.StringField({
|
||||
required: true, nullable: false, initial: "normal",
|
||||
choices: SYSTEM.weightCategories,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import { htmlField } from "./shared.mjs"
|
||||
|
||||
export default class MGNEParty extends foundry.abstract.TypeDataModel {
|
||||
static defineSchema() {
|
||||
const fields = foundry.data.fields
|
||||
|
||||
return {
|
||||
memberRefs: new fields.ArrayField(
|
||||
new fields.SchemaField({
|
||||
id: new fields.StringField({ required: true, nullable: false, blank: false }),
|
||||
})
|
||||
),
|
||||
credits: new fields.NumberField({ required: true, nullable: false, integer: true, initial: 0, min: 0 }),
|
||||
notes: htmlField(""),
|
||||
}
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static LOCALIZATION_PREFIXES = ["MGNE.Party"]
|
||||
}
|
||||
@@ -18,6 +18,15 @@ export default class MGNEResonanceCore extends foundry.abstract.TypeDataModel {
|
||||
choices: SYSTEM.usageDieChoices,
|
||||
}),
|
||||
burnedOut: booleanField(false),
|
||||
broken: booleanField(false),
|
||||
durabilityDie: new foundry.data.fields.StringField({
|
||||
required: true, nullable: false, initial: "d6",
|
||||
choices: SYSTEM.usageDieChoices,
|
||||
}),
|
||||
weight: new foundry.data.fields.StringField({
|
||||
required: true, nullable: false, initial: "trivial",
|
||||
choices: SYSTEM.weightCategories,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,8 +12,16 @@ export default class MGNEShield extends foundry.abstract.TypeDataModel {
|
||||
choices: SYSTEM.armorDieChoices,
|
||||
}),
|
||||
penalty: numberField(0, 0, 4),
|
||||
weight: new foundry.data.fields.StringField({
|
||||
required: true, nullable: false, initial: "normal",
|
||||
choices: SYSTEM.weightCategories,
|
||||
}),
|
||||
equipped: booleanField(false),
|
||||
broken: booleanField(false),
|
||||
durabilityDie: new foundry.data.fields.StringField({
|
||||
required: true, nullable: false, initial: "d6",
|
||||
choices: SYSTEM.usageDieChoices,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,14 @@ export default class MGNEWeapon extends foundry.abstract.TypeDataModel {
|
||||
}),
|
||||
damage: stringField("1d4"),
|
||||
range: stringField("Touch"),
|
||||
properties: stringField(""),
|
||||
properties: new foundry.data.fields.SetField(
|
||||
new foundry.data.fields.StringField({ required: true, nullable: false, blank: false }),
|
||||
{ required: true, nullable: false, initial: [] }
|
||||
),
|
||||
weight: new foundry.data.fields.StringField({
|
||||
required: true, nullable: false, initial: "normal",
|
||||
choices: SYSTEM.weightCategories,
|
||||
}),
|
||||
usageDie: new foundry.data.fields.StringField({
|
||||
required: true,
|
||||
nullable: false,
|
||||
@@ -23,9 +30,29 @@ export default class MGNEWeapon extends foundry.abstract.TypeDataModel {
|
||||
quantity: numberField(1, 0),
|
||||
equipped: booleanField(false),
|
||||
broken: booleanField(false),
|
||||
durabilityDie: new foundry.data.fields.StringField({
|
||||
required: true, nullable: false, initial: "d6",
|
||||
choices: SYSTEM.usageDieChoices,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/** @override */
|
||||
static LOCALIZATION_PREFIXES = ["MGNE.Weapon"]
|
||||
|
||||
/**
|
||||
* Migrate old string-based properties field to the new SetField format.
|
||||
* @override
|
||||
*/
|
||||
static migrateData(source) {
|
||||
// Old data stored properties as a plain string; convert to empty array
|
||||
if (typeof source.properties === "string") {
|
||||
source.properties = []
|
||||
}
|
||||
// Remove any null/undefined/blank entries that may have crept in
|
||||
if (Array.isArray(source.properties)) {
|
||||
source.properties = source.properties.filter(p => p != null && p !== "")
|
||||
}
|
||||
return super.migrateData(source)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user